Add collapsible Team Help chat widget on all public pages

Self-contained assistant (no external services) with a knowledge base
covering the strategy, levels, costs, wallet setup, funding, joining,
training videos, and live current-sponsor/queue data; falls back to
the configured Telegram group link when it can't answer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-08-12 08:35:28 -05:00
parent 023f8a3464
commit 708068a9a7
5 changed files with 116 additions and 3 deletions
+89
View File
@@ -0,0 +1,89 @@
(function(){
let config=null,sponsorInfo=null;
async function loadData(){
try{const r=await fetch('/api/public/config');if(r.ok)config=await r.json()}catch(e){}
try{const r=await fetch('/api/public/current-sponsor');if(r.ok)sponsorInfo=await r.json()}catch(e){}
}
function esc(s){return String(s??'').replace(/[&<>'"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[c]))}
function tg(){return (config&&config.telegramUrl)||'https://t.me/cryptoteambuild'}
function pol(){return (config&&config.premiumEntryPol)||362}
function tgLink(label){return `<a href="${esc(tg())}" target="_blank" rel="noopener noreferrer">${esc(label||'Open the Telegram group ↗')}</a>`}
const KB=[
{k:['what is','rm circle','about','this site','this project','crypto team build','who are you','network'],
a:()=>`The RM Circle is a team build project of the <strong>Crypto Team Build Network</strong>. We enter the RM Circle dApp at the Premium tier (${pol()} POL on Polygon) and build as one team: each member gets exactly 2 directs, then helps those 2 get their 2 — building depth instead of width. Start with the <a href="/training">training videos</a>.`},
{k:['how does it work','strategy','how it works','plan','roadmap','system','duplicate','duplication'],
a:()=>`The core strategy: <strong>get your 2, retire your link, help your 2 get their 2, upgrade with profits, repeat.</strong> Once a position has 2 directs it's qualified — we stop using its link and move the team's effort down to the next positions. The full picture is in <a href="/training">Video 1 of the training</a>, and the roadmap poster is on the <a href="/">home page</a>.`},
{k:['cost','price','entry','how much','362','fee','pol needed','expensive'],
a:()=>`Premium entry is <strong>${pol()} POL</strong> on Polygon Mainnet, plus a small extra POL balance for network gas. POL's dollar value changes with the market. Only ever use funds you can afford to lose.`},
{k:['pol','polygon','network','chain','gas','matic','mainnet'],
a:()=>`The build runs on <strong>Polygon Mainnet</strong> (chain ID 137). POL is the network's native token — it pays for your Premium entry and for transaction gas. In MetaMask, make sure Polygon is the selected network before doing anything.`},
{k:['metamask','wallet','create wallet','install','set up wallet','setup wallet'],
a:()=>`Install MetaMask only from the <a href="https://metamask.io/" target="_blank" rel="noopener noreferrer">official site</a> or your device's official app store, then create your wallet. <a href="/training">Video 2 in the training</a> walks through it step by step. Never share your Secret Recovery Phrase with anyone — not the team, not this site, not a "support agent".`},
{k:['fund','funding','buy pol','get pol','deposit','exchange','transfer','send pol'],
a:()=>`You'll need about ${pol()} POL plus a little extra for gas, on Polygon Mainnet. <a href="/training">Video 3 in the training</a> shows how to fund your wallet. Double-check you're sending POL on the Polygon network — not another chain.`},
{k:['join','buy','purchase','premium position','enter','sign up','signup','register','get started','start'],
a:()=>`Ready to join? Go to the <a href="/start">Getting Started page</a> — it always shows the current team sponsor to use. <a href="/training">Video 4 in the training</a> walks through the purchase in the dApp. Always confirm the sponsor ID in the dApp matches the one on the start page before signing.`},
{k:['sponsor','current sponsor','who do i join under','placement','whose link','referral'],
a:()=>{const s=sponsorInfo&&sponsorInfo.sponsor;return s?`The current team sponsor is <strong>ID ${esc(s.id)}${s.name?' ('+esc(s.name)+')':''}</strong> — always verify on the <a href="/start">Getting Started page</a> right before you join, because placements rotate as positions qualify. Don't use an old screenshot or saved link.`:`The current sponsor is always shown live on the <a href="/start">Getting Started page</a> — check there right before joining, because placements rotate as positions qualify.`}},
{k:['qualified','qualification','2 directs','two directs','directs','retire'],
a:()=>`A position is <strong>qualified</strong> once it has exactly 2 directs. At that point we retire its referral link — no more directs on it — and shift the team's recruiting to its two positions below. That's what keeps the build growing in depth.`},
{k:['level','levels','upgrade','scintilla','ascensus','fabrica','culmen','apex','fastigium','vertex','corona','8 levels'],
a:()=>`There are 8 Premium levels: <strong>Scintilla, Ascensus, Fabrica, Culmen, Apex, Fastigium, Vertex, Corona</strong>. Everyone starts at Scintilla. Upgrade as quickly as practical — ideally using earned POL — because the first two payments at each level are designed to help fund your next upgrade. Stay aware of your active downline's levels so you don't fall behind.`},
{k:['30 positions','goal','milestone','matrix','how many people','team size'],
a:()=>`The first major team goal is <strong>30 properly placed positions</strong>: 2 → 4 → 8 → 16 across the first four generations. Then we keep going — 32, 64, 128 and beyond.`},
{k:['moving link','why not my link','own link','my referral','use my link','extra legs'],
a:()=>`We use a <strong>moving-link strategy</strong>: one link at a time until that position qualifies with 2 directs, then the link retires and effort moves down. That's why you should always use the sponsor shown on the <a href="/start">Getting Started page</a> — not a personal or saved link. Extra directs on a qualified link create shallow legs instead of depth.`},
{k:['risk','safe','scam','lose money','guarantee','guaranteed','income','earnings','legit'],
a:()=>`Straight answer: participation involves cryptocurrency and smart-contract risk, and <strong>no income is guaranteed</strong>. Results depend on team effort, duplication, upgrades, smart-contract rules, and POL's market value. Only use funds you can afford to lose.`},
{k:['video','videos','training','watch','tutorial','learn','how to'],
a:()=>`All four training videos are on the <a href="/training">Training page</a>: (1) How the team build works, (2) Create your MetaMask wallet, (3) Funding your wallet, (4) Buying the Premium position. Watch them in order.`},
{k:['seed phrase','secret recovery','recovery phrase','private key','12 words','passphrase'],
a:()=>`<strong>Never share your Secret Recovery Phrase or private keys with anyone</strong> — not this site, not a sponsor, not "support". Anyone asking for it is trying to steal your funds. MetaMask will never ask for it either, except when you restore a wallet yourself.`},
{k:['telegram','group','chat','human','support','contact','talk','someone','admin','help me'],
a:()=>`For live help from the team, join the Telegram group: ${tgLink()}. Tell them where you're stuck and someone will walk you through it.`},
{k:['after join','next','what happens','confirmed','joined','i bought','i am in'],
a:()=>`Once your position is confirmed: tell the team your new RM Circle ID and your sponsor ID (in the Telegram group: ${tgLink('here')}) so your placement gets mapped. Then your job is simple — get your 2 directs, and when you're qualified, help your 2 get their 2.`},
{k:['waiting','queue','line','how long','when my turn'],
a:()=>{const w=sponsorInfo&&typeof sponsorInfo.waitingCount==='number'?sponsorInfo.waitingCount:null;return `${w!==null?`Right now there ${w===1?'is':'are'} <strong>${w}</strong> team placement${w===1?'':'s'} waiting behind the current sponsor. `:''}The queue moves every time a position qualifies with its 2 directs — the more the team helps each other, the faster it rotates.`}},
];
function answer(q){
const t=q.toLowerCase().replace(/[^a-z0-9 ]/g,' ');
let best=null,bestScore=0;
for(const e of KB){
let score=0;
for(const k of e.k){if(t.includes(k))score+=k.includes(' ')?2:1}
if(score>bestScore){bestScore=score;best=e}
}
if(best&&bestScore>0)return best.a();
return `I don't have a good answer for that one. The team can help you directly — ${tgLink('join our Telegram group ↗')} and ask there. You can also check the <a href="/training">training videos</a> or the <a href="/">strategy overview</a>.`;
}
const CHIPS=['How does it work?','What does it cost?','Who is the current sponsor?','How do I set up a wallet?','Is there risk?'];
const fab=document.createElement('button');
fab.className='chat-fab';fab.setAttribute('aria-label','Open team help chat');fab.innerHTML='💬';
const panel=document.createElement('div');
panel.className='chat-panel chat-hidden';
panel.innerHTML=`<div class="chat-head"><div><strong>Team Help</strong><div class="chat-sub">Ask about the RM Circle team build</div></div><button class="chat-close" aria-label="Close chat">×</button></div><div class="chat-msgs"></div><div class="chat-chips"></div><form class="chat-input"><input type="text" placeholder="Type a question…" aria-label="Your question" maxlength="300"><button type="submit" class="btn btn-primary btn-sm">Send</button></form><div class="chat-foot">Can't find it? ${tgLink('Get live help on Telegram ↗')}</div>`;
document.body.appendChild(fab);document.body.appendChild(panel);
const msgs=panel.querySelector('.chat-msgs'),chipsEl=panel.querySelector('.chat-chips'),form=panel.querySelector('.chat-input'),input=form.querySelector('input');
function addMsg(html,who){const d=document.createElement('div');d.className=`chat-msg ${who}`;if(who==='user'){d.textContent=html}else{d.innerHTML=html}msgs.appendChild(d);msgs.scrollTop=msgs.scrollHeight}
function ask(q){addMsg(q,'user');setTimeout(()=>{addMsg(answer(q),'bot');},250)}
let started=false;
function open(){
panel.classList.remove('chat-hidden');fab.classList.add('chat-hidden');input.focus();
if(!started){started=true;loadData().then(()=>{
panel.querySelector('.chat-foot').innerHTML=`Can't find it? ${tgLink('Get live help on Telegram ↗')}`;
addMsg(`Hi! I can answer questions about the RM Circle team build — the strategy, wallet setup, funding, joining, levels, and more. What do you want to know?`,'bot');
for(const c of CHIPS){const b=document.createElement('button');b.type='button';b.className='chat-chip';b.textContent=c;b.addEventListener('click',()=>{chipsEl.classList.add('chat-hidden');ask(c)});chipsEl.appendChild(b)}
})}
}
function close(){panel.classList.add('chat-hidden');fab.classList.remove('chat-hidden')}
fab.addEventListener('click',open);
panel.querySelector('.chat-close').addEventListener('click',close);
form.addEventListener('submit',e=>{e.preventDefault();const q=input.value.trim();if(!q)return;input.value='';chipsEl.classList.add('chat-hidden');ask(q)});
})();
+1 -1
View File
@@ -13,4 +13,4 @@
<section class="section"><div class="wrap"><div class="section-head"><div class="eyebrow">Depth over width</div><h2>2 → 4 → 8 → 16 → 32</h2><p>The first major team milestone is 30 correctly placed positions across the first four generations: 2 + 4 + 8 + 16.</p></div><div class="matrix" aria-label="Matrix growth illustration"><div class="matrix-group"><div class="people"><span class="person"></span><span class="person"></span></div><b>2</b></div><div class="matrix-group"><div class="people"><span class="person"></span><span class="person"></span><span class="person"></span><span class="person"></span></div><b>4</b></div><div class="matrix-group"><div class="people" id="p8"></div><b>8</b></div><div class="matrix-group"><div class="people" id="p16"></div><b>16</b></div></div><div class="notice"><strong>Team principle:</strong> once your two are in place, do not keep adding more directs to the same qualified link. Help the next positions become qualified so the matrix develops depth instead of extra shallow legs.</div></div></section> <section class="section"><div class="wrap"><div class="section-head"><div class="eyebrow">Depth over width</div><h2>2 → 4 → 8 → 16 → 32</h2><p>The first major team milestone is 30 correctly placed positions across the first four generations: 2 + 4 + 8 + 16.</p></div><div class="matrix" aria-label="Matrix growth illustration"><div class="matrix-group"><div class="people"><span class="person"></span><span class="person"></span></div><b>2</b></div><div class="matrix-group"><div class="people"><span class="person"></span><span class="person"></span><span class="person"></span><span class="person"></span></div><b>4</b></div><div class="matrix-group"><div class="people" id="p8"></div><b>8</b></div><div class="matrix-group"><div class="people" id="p16"></div><b>16</b></div></div><div class="notice"><strong>Team principle:</strong> once your two are in place, do not keep adding more directs to the same qualified link. Help the next positions become qualified so the matrix develops depth instead of extra shallow legs.</div></div></section>
<section class="section"><div class="wrap"><div class="card" style="text-align:center;padding:34px"><div class="eyebrow">Ready to start?</div><h2 style="font-size:38px;margin:10px 0">See the current team placement.</h2><p style="max-width:680px;margin:0 auto 20px;color:var(--muted)">The onboarding page automatically shows the sponsor position the team is currently helping. Always use the sponsor shown there instead of an old screenshot or saved link.</p><a class="btn btn-primary" href="/start">Open Getting Started Instructions →</a></div></div></section> <section class="section"><div class="wrap"><div class="card" style="text-align:center;padding:34px"><div class="eyebrow">Ready to start?</div><h2 style="font-size:38px;margin:10px 0">See the current team placement.</h2><p style="max-width:680px;margin:0 auto 20px;color:var(--muted)">The onboarding page automatically shows the sponsor position the team is currently helping. Always use the sponsor shown there instead of an old screenshot or saved link.</p><a class="btn btn-primary" href="/start">Open Getting Started Instructions →</a></div></div></section>
</main><footer class="wrap disclaimer">This independent team page is educational and is not an earnings guarantee or investment advice. Cryptocurrency and smart-contract participation involve risk, including possible loss of funds. Never use funds you cannot afford to lose. Results depend on actual participation, qualification, upgrades, smart-contract behavior, and the market value of POL.<div class="footer-links"><a href="/training">Training</a><a href="/start">Getting Started</a><a href="/admin">Team Admin</a></div></footer> </main><footer class="wrap disclaimer">This independent team page is educational and is not an earnings guarantee or investment advice. Cryptocurrency and smart-contract participation involve risk, including possible loss of funds. Never use funds you cannot afford to lose. Results depend on actual participation, qualification, upgrades, smart-contract behavior, and the market value of POL.<div class="footer-links"><a href="/training">Training</a><a href="/start">Getting Started</a><a href="/admin">Team Admin</a></div></footer>
<script src="/track.js"></script><script src="/bridge.js"></script></body></html> <script src="/track.js"></script><script src="/bridge.js"></script><script src="/chat.js" defer></script></body></html>
+1 -1
View File
@@ -16,4 +16,4 @@
<div class="callout warning" style="margin-top:12px"><strong>Risk reminder:</strong> participation involves cryptocurrency and smart-contract risk. No income is guaranteed. Use only funds you can afford to lose.</div><div id="supportBox" class="notice" style="margin-top:12px"></div><div id="supportLinkWrap" class="hidden" style="margin-top:10px"><a id="supportLink" class="btn btn-secondary" target="_blank" rel="noopener noreferrer">Open Team Support ↗</a></div></section></div> <div class="callout warning" style="margin-top:12px"><strong>Risk reminder:</strong> participation involves cryptocurrency and smart-contract risk. No income is guaranteed. Use only funds you can afford to lose.</div><div id="supportBox" class="notice" style="margin-top:12px"></div><div id="supportLinkWrap" class="hidden" style="margin-top:10px"><a id="supportLink" class="btn btn-secondary" target="_blank" rel="noopener noreferrer">Open Team Support ↗</a></div></section></div>
<figure class="roadmap-figure"><a href="/roadmap.webp" target="_blank" rel="noopener"><img src="/roadmap.webp" alt="RM Circle Premium Team Build Roadmap — core strategy, step-by-step guide, premium levels, and duplication formula" width="1149" height="1369" loading="lazy"></a><figcaption>The RM Circle is a team build project of the <strong>Crypto Team Build Network</strong>. This roadmap is the plan every member follows — tap to view full size.</figcaption></figure></div></main> <figure class="roadmap-figure"><a href="/roadmap.webp" target="_blank" rel="noopener"><img src="/roadmap.webp" alt="RM Circle Premium Team Build Roadmap — core strategy, step-by-step guide, premium levels, and duplication formula" width="1149" height="1369" loading="lazy"></a><figcaption>The RM Circle is a team build project of the <strong>Crypto Team Build Network</strong>. This roadmap is the plan every member follows — tap to view full size.</figcaption></figure></div></main>
<footer class="wrap disclaimer">This is an independent Crypto Team Build onboarding resource, not an owner/principal page. Always confirm transaction details in your wallet before signing. Never disclose your Secret Recovery Phrase.</footer> <footer class="wrap disclaimer">This is an independent Crypto Team Build onboarding resource, not an owner/principal page. Always confirm transaction details in your wallet before signing. Never disclose your Secret Recovery Phrase.</footer>
<script src="/track.js"></script><script src="/start.js"></script></body></html> <script src="/track.js"></script><script src="/start.js"></script><script src="/chat.js" defer></script></body></html>
+24
View File
@@ -20,3 +20,27 @@ a{color:inherit}.wrap{width:min(1160px,calc(100% - 32px));margin:auto}.nav{heigh
.video-card{max-width:880px;margin:0 auto;padding:10px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)} .video-card{max-width:880px;margin:0 auto;padding:10px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.video-frame{display:block;width:100%;height:auto;aspect-ratio:16/9;border:0;border-radius:12px} .video-frame{display:block;width:100%;height:auto;aspect-ratio:16/9;border:0;border-radius:12px}
.chat-fab{position:fixed;right:18px;bottom:18px;width:58px;height:58px;border-radius:50%;background:var(--gold);color:#071421;border:0;box-shadow:var(--shadow);cursor:pointer;z-index:998;font-size:26px;line-height:1;display:flex;align-items:center;justify-content:center;transition:transform .15s}
.chat-fab:hover{transform:scale(1.07)}
.chat-panel{position:fixed;right:18px;bottom:18px;width:min(372px,calc(100vw - 24px));height:min(560px,calc(100vh - 90px));display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow);z-index:999;overflow:hidden}
.chat-head{display:flex;justify-content:space-between;align-items:center;padding:14px 16px;border-bottom:1px solid var(--line);background:rgba(243,190,67,.06)}
.chat-head strong{font-size:15px}
.chat-sub{color:var(--muted);font-size:12px;margin-top:2px}
.chat-close{background:none;border:0;color:var(--muted);font-size:22px;cursor:pointer;padding:0 4px;line-height:1}
.chat-close:hover{color:var(--text)}
.chat-msgs{flex:1;overflow-y:auto;padding:14px;display:flex;flex-direction:column;gap:10px}
.chat-msg{max-width:88%;padding:10px 13px;border-radius:12px;font-size:13.5px;line-height:1.5;overflow-wrap:break-word}
.chat-msg.bot{background:rgba(78,214,203,.08);border:1px solid rgba(78,214,203,.18);color:var(--text);align-self:flex-start;border-bottom-left-radius:4px}
.chat-msg.user{background:var(--gold);color:#071421;align-self:flex-end;border-bottom-right-radius:4px}
.chat-msg a{color:var(--teal)}
.chat-msg.user a{color:#071421}
.chat-chips{display:flex;flex-wrap:wrap;gap:6px;padding:0 14px 8px}
.chat-chip{font-size:12px;padding:6px 11px;border-radius:999px;background:transparent;border:1px solid var(--line);color:var(--muted);cursor:pointer}
.chat-chip:hover{color:var(--text);border-color:var(--teal)}
.chat-input{display:flex;gap:8px;padding:12px;border-top:1px solid var(--line)}
.chat-input input{flex:1;min-width:0;background:var(--bg);border:1px solid var(--line);border-radius:10px;color:var(--text);padding:9px 12px;font-size:14px}
.chat-input input:focus{outline:none;border-color:var(--teal)}
.chat-foot{padding:8px 14px 12px;font-size:12px;color:var(--muted);text-align:center}
.chat-foot a{color:var(--teal)}
.chat-hidden{display:none}
+1 -1
View File
@@ -21,4 +21,4 @@
</div></section> </div></section>
</main> </main>
<footer class="wrap disclaimer">This is an independent Crypto Team Build training resource. Always confirm transaction details in your wallet before signing. Never disclose your Secret Recovery Phrase.<div class="footer-links"><a href="/">Strategy</a><a href="/start">Getting Started</a><a href="/admin">Team Admin</a></div></footer> <footer class="wrap disclaimer">This is an independent Crypto Team Build training resource. Always confirm transaction details in your wallet before signing. Never disclose your Secret Recovery Phrase.<div class="footer-links"><a href="/">Strategy</a><a href="/start">Getting Started</a><a href="/admin">Team Admin</a></div></footer>
<script src="/track.js"></script><script src="/training.js"></script></body></html> <script src="/track.js"></script><script src="/training.js"></script><script src="/chat.js" defer></script></body></html>