315 lines
26 KiB
Python
315 lines
26 KiB
Python
#!/usr/bin/env python3
|
|
"""Landing Factory — kick-ass interactive landing pages for the homelab fleet.
|
|
Emits self-contained HTML (inline CSS+JS, zero external deps) per site.
|
|
Usage: python3 build.py -> writes ~/landing-factory/out/<site>.html
|
|
"""
|
|
import os
|
|
|
|
OUT = os.path.expanduser("~/landing-factory/out")
|
|
os.makedirs(OUT, exist_ok=True)
|
|
|
|
ENGINE_CSS = """
|
|
<style>
|
|
:root{--accent:AC;--accent2:AC2;--bg:BG;--bg2:BG2;--card:CARD;--text:TXT;--muted:MUT}
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
html{scroll-behavior:smooth}
|
|
body{background:var(--bg);color:var(--text);font-family:'Segoe UI',system-ui,-apple-system,sans-serif;overflow-x:hidden;line-height:1.6}
|
|
::selection{background:var(--accent);color:#000}
|
|
#fx{position:fixed;inset:0;z-index:0;pointer-events:none}
|
|
.wrap{position:relative;z-index:1;max-width:1180px;margin:0 auto;padding:0 24px}
|
|
nav{position:fixed;top:0;left:0;right:0;z-index:50;display:flex;align-items:center;justify-content:space-between;padding:16px 28px;background:rgba(0,0,0,.35);backdrop-filter:blur(14px);border-bottom:1px solid rgba(255,255,255,.06)}
|
|
.brand{display:flex;align-items:center;gap:10px;font-weight:800;font-size:1.15rem;letter-spacing:.5px}
|
|
.brand .dot{width:10px;height:10px;border-radius:50%;background:var(--accent);box-shadow:0 0 14px var(--accent);animation:pulse 2s infinite}
|
|
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
|
|
.navlinks{display:flex;gap:22px;align-items:center}
|
|
.navlinks a{color:var(--muted);text-decoration:none;font-size:.92rem;font-weight:600;transition:.25s}
|
|
.navlinks a:hover{color:var(--text)}
|
|
.btn{display:inline-block;padding:14px 30px;border-radius:14px;font-weight:800;font-size:1rem;letter-spacing:.3px;cursor:pointer;border:none;text-decoration:none;transition:transform .25s,box-shadow .25s;position:relative;overflow:hidden}
|
|
.btn:hover{transform:translateY(-3px)}
|
|
.btn-primary{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#04101f;box-shadow:0 8px 30px COLORGLOW}
|
|
.btn-primary:hover{box-shadow:0 14px 44px COLORGLOW}
|
|
.btn-ghost{background:rgba(255,255,255,.06);color:var(--text);border:1px solid rgba(255,255,255,.16)}
|
|
.btn-ghost:hover{background:rgba(255,255,255,.12)}
|
|
.hero{min-height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:120px 24px 60px;position:relative}
|
|
.badge{display:inline-flex;align-items:center;gap:8px;padding:8px 18px;border-radius:40px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);font-size:.85rem;font-weight:700;color:var(--muted);margin-bottom:22px;letter-spacing:.4px}
|
|
.badge .live{width:8px;height:8px;border-radius:50%;background:#2fe07b;box-shadow:0 0 10px #2fe07b;animation:pulse 1.6s infinite}
|
|
.hero h1{font-size:clamp(2.6rem,7vw,5.6rem);font-weight:900;line-height:1.05;letter-spacing:-1.5px;background:linear-gradient(120deg,#fff 20%,var(--accent) 55%,var(--accent2) 90%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;margin:10px 0 20px;filter:drop-shadow(0 0 34px COLORGLOW)}
|
|
.hero .sub{max-width:640px;color:var(--muted);font-size:1.15rem;margin-bottom:36px}
|
|
.hero .cta{display:flex;gap:16px;flex-wrap:wrap;justify-content:center}
|
|
.typewrap{font-family:'SF Mono',ui-monospace,Menlo,monospace;color:var(--accent);font-size:1.05rem;font-weight:700;margin-bottom:14px;min-height:28px}
|
|
.typewrap .cursor{animation:blink 1s steps(1) infinite}
|
|
@keyframes blink{50%{opacity:0}}
|
|
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:18px;margin:80px auto 0;width:100%;max-width:900px}
|
|
.stat{padding:22px;border-radius:18px;background:linear-gradient(160deg,rgba(255,255,255,.06),rgba(255,255,255,.02));border:1px solid rgba(255,255,255,.08);backdrop-filter:blur(8px)}
|
|
.stat .n{font-size:2.3rem;font-weight:900;background:linear-gradient(135deg,var(--accent),var(--accent2));-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
|
.stat .l{color:var(--muted);font-size:.85rem;font-weight:600;margin-top:4px}
|
|
section{padding:90px 0;position:relative}
|
|
section h2{font-size:clamp(1.9rem,4vw,3rem);font-weight:900;text-align:center;letter-spacing:-.5px;margin-bottom:12px}
|
|
section .lead{text-align:center;color:var(--muted);max-width:620px;margin:0 auto 50px;font-size:1.05rem}
|
|
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:22px}
|
|
.card{background:linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.015));border:1px solid rgba(255,255,255,.09);border-radius:20px;padding:28px;transition:transform .3s,border-color .3s,box-shadow .3s;transform-style:preserve-3d;will-change:transform}
|
|
.card:hover{border-color:ACBORDER;box-shadow:0 20px 60px COLORGLOW_SOFT;transform:translateY(-6px)}
|
|
.card .ico{font-size:2.4rem;margin-bottom:14px;display:inline-block}
|
|
.card h3{font-size:1.25rem;margin-bottom:8px}
|
|
.card p{color:var(--muted);font-size:.95rem}
|
|
.stepnum{font-size:1rem;font-weight:900;color:var(--accent);letter-spacing:1px}
|
|
.marquee{overflow:hidden;border-top:1px solid rgba(255,255,255,.07);border-bottom:1px solid rgba(255,255,255,.07);padding:16px 0;background:rgba(0,0,0,.25);margin:30px 0}
|
|
.marquee .track{display:flex;gap:48px;white-space:nowrap;animation:slide 30s linear infinite;width:max-content;font-weight:800;font-size:1.05rem;color:var(--muted)}
|
|
.marquee .track span i{color:var(--accent);font-style:normal;margin-right:8px}
|
|
@keyframes slide{to{transform:translateX(-50%)}}
|
|
.pricing{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:22px;max-width:900px;margin:0 auto}
|
|
.price-card{border-radius:22px;padding:36px 28px;text-align:center;border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.03);transition:.3s;position:relative}
|
|
.price-card.hot{border-color:var(--accent);box-shadow:0 0 50px COLORGLOW_SOFT;transform:scale(1.03)}
|
|
.price-card .tag{position:absolute;top:-13px;left:50%;transform:translateX(-50%);background:linear-gradient(135deg,var(--accent),var(--accent2));color:#04101f;font-size:.75rem;font-weight:900;padding:4px 16px;border-radius:20px;letter-spacing:1px}
|
|
.price-card .amount{font-size:3rem;font-weight:900;margin:14px 0 4px}
|
|
.price-card .per{color:var(--muted);font-size:.9rem;margin-bottom:20px}
|
|
.price-card ul{list-style:none;text-align:left;margin:0 auto 26px;max-width:260px}
|
|
.price-card li{padding:7px 0;color:var(--muted);font-size:.95rem;border-bottom:1px dashed rgba(255,255,255,.08)}
|
|
.price-card li::before{content:"✓ ";color:var(--accent);font-weight:900}
|
|
.cta-band{text-align:center;padding:80px 24px;border-radius:28px;background:radial-gradient(ellipse at center,COLORGLOW_BAND,transparent 70%),rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.08);margin:0 auto;max-width:1000px}
|
|
.cta-band h2{font-size:clamp(2rem,4.5vw,3.2rem)}
|
|
footer{padding:44px 24px;border-top:1px solid rgba(255,255,255,.07);text-align:center;color:var(--muted);font-size:.9rem;margin-top:60px}
|
|
footer a{color:var(--accent);text-decoration:none;font-weight:700}
|
|
.reveal{opacity:0;transform:translateY(36px);transition:opacity .8s cubic-bezier(.16,1,.3,1),transform .8s cubic-bezier(.16,1,.3,1)}
|
|
.reveal.in{opacity:1;transform:none}
|
|
#stickycta{position:fixed;bottom:20px;left:50%;transform:translate(-50%,120px);z-index:60;transition:transform .4s cubic-bezier(.16,1,.3,1)}
|
|
#stickycta.show{transform:translate(-50%,0)}
|
|
@media (max-width:760px){.navlinks{display:none}.hero{padding-top:90px}.stats{grid-template-columns:repeat(2,1fr)}}
|
|
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
|
</style>
|
|
"""
|
|
|
|
ENGINE_JS = """
|
|
<script>
|
|
(function(){
|
|
var cfg={accent:"AC",accent2:"AC2",bg2:"BG2",glow:"COLORGLOW",wave:WAVE,slots:SLOTS,typephrases:TYPEPHRASES};
|
|
// marquee duplication for seamless loop
|
|
var mt=document.getElementById('mtrack');if(mt){mt.innerHTML+=mt.innerHTML;}
|
|
// particle field
|
|
var c=document.getElementById('fx'),x=c.getContext('2d'),W,H,pts=[],mouse={x:-9e3,y:-9e3};
|
|
function rs(){W=c.width=innerWidth;H=c.height=innerHeight;var n=Math.min(110,Math.floor(W*H/16000));pts=[];for(var i=0;i<n;i++)pts.push({x:Math.random()*W,y:Math.random()*H,vx:(Math.random()-.5)*.5,vy:(Math.random()-.5)*.5,r:Math.random()*1.8+.6});}
|
|
rs();addEventListener('resize',rs);addEventListener('mousemove',function(e){mouse.x=e.clientX;mouse.y=e.clientY});
|
|
function tick(){x.clearRect(0,0,W,H);for(var i=0;i<pts.length;i++){var p=pts[i];p.x+=p.vx;p.y+=p.vy;if(p.x<0||p.x>W)p.vx*=-1;if(p.y<0||p.y>H)p.vy*=-1;
|
|
var dx=p.x-mouse.x,dy=p.y-mouse.y,d2=dx*dx+dy*dy;if(d2<14400){p.x+=dx*.02;p.y+=dy*.02}
|
|
x.beginPath();x.arc(p.x,p.y,p.r,0,6.29);x.fillStyle=cfg.accent;x.globalAlpha=.55;x.fill();
|
|
for(var j=i+1;j<pts.length;j++){var q=pts[j],ddx=p.x-q.x,ddy=p.y-q.y,dd=ddx*ddx+ddy*ddy;if(dd<12000){x.globalAlpha=.16*(1-dd/12000);x.beginPath();x.moveTo(p.x,p.y);x.lineTo(q.x,q.y);x.strokeStyle=cfg.accent;x.lineWidth=.7;x.stroke();}}}
|
|
x.globalAlpha=1;requestAnimationFrame(tick)}tick();
|
|
// typewriter
|
|
var tw=document.getElementById('typewriter'),ph=cfg.typephrases,i=0,ci=0,del=false;
|
|
function type(){var t=ph[i];ci+=del?-1:1;tw.textContent=t.slice(0,ci);var sp=del?28:52;
|
|
if(!del&&ci===t.length){sp=1700;del=true}else if(del&&ci===0){del=false;i=(i+1)%ph.length;sp=300}
|
|
setTimeout(type,sp)}if(tw)type();
|
|
// reveals + countup
|
|
var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');var ns=e.target.querySelectorAll('[data-count]');ns.forEach(function(n){var end=parseFloat(n.getAttribute('data-count')),t0=null;
|
|
function up(ts){if(!t0)t0=ts;var p=Math.min((ts-t0)/1600,1);n.textContent=Math.round(end*(1-Math.pow(1-p,3))).toLocaleString();if(p<1)requestAnimationFrame(up)}requestAnimationFrame(up)});io.unobserve(e.target)}})},{threshold:.15});
|
|
document.querySelectorAll('.reveal').forEach(function(el){io.observe(el)});
|
|
// tilt
|
|
document.querySelectorAll('.tilt').forEach(function(t){t.addEventListener('mousemove',function(e){var r=t.getBoundingClientRect(),px=(e.clientX-r.left)/r.width-.5,py=(e.clientY-r.top)/r.height-.5;t.style.transform='perspective(900px) rotateY('+(px*10)+'deg) rotateX('+(-py*10)+'deg) translateY(-6px)'});t.addEventListener('mouseleave',function(){t.style.transform=''});});
|
|
// sticky cta
|
|
var st=document.getElementById('stickycta');if(st)addEventListener('scroll',function(){st.classList.toggle('show',scrollY>500)});
|
|
// waveform (signal miner)
|
|
var wv=document.getElementById('wave');if(wv){var wx=wv.getContext('2d');var wd=[];for(var k=0;k<180;k++)wd.push(Math.random());
|
|
function wtick(){wx.clearRect(0,0,wv.width,wv.height);wx.beginPath();for(k=0;k<wd.length;k++){var a=(wd[k]*.5+.25)*wv.height;var px=k/wd.length*wv.width;k===0?wx.moveTo(px,a):wx.lineTo(px,a);wd[k]=Math.max(0,Math.min(1,wd[k]+(Math.random()-.5)*.14))}wx.strokeStyle=cfg.accent;wx.lineWidth=2.5;wx.shadowColor=cfg.accent;wx.shadowBlur=14;wx.stroke();requestAnimationFrame(wtick)}wtick();}
|
|
})();
|
|
</script>
|
|
"""
|
|
|
|
PAGES = {
|
|
"satsspin": dict(
|
|
title="SatsSpin — Lightning Casino",
|
|
ac="#ffb300", ac2="#7c3aed", bg="#0a0618", bg2="#150b2e", card="#141026", txt="#f2edff", mut="#9a8fc4",
|
|
glow="rgba(255,179,0,.45)", glowsoft="rgba(255,179,0,.15)", border="rgba(255,179,0,.5)",
|
|
band="rgba(124,58,237,.25)",
|
|
typephrases=['⚡ Instant Lightning payouts', '🎰 6 provably-fair games', '🔓 No KYC. No waiting.', '💜 Built for sats, not suits'],
|
|
slots=True, wave=False,
|
|
nav=[('Games','/play'),('How It Works','#how'),('Lightning','#lightning')],
|
|
navcta=('Play Now','/play'),
|
|
body="""<div class="hero">
|
|
<div class="typewrap"><span id="typewriter"></span><span class="cursor">▌</span></div>
|
|
<div class="badge"><span class="live"></span> LIVE · Lightning Network Casino</div>
|
|
<h1>Spin The Lightning.</h1>
|
|
<p class="sub">SatsSpin is a Bitcoin-native casino running on the Lightning Network. Deposit in seconds, win in sats, withdraw instantly. No accounts with strangers, no KYC, no payout delays — just you and the reels.</p>
|
|
<div class="cta"><a class="btn btn-primary" href="/play">⚡ Play Now</a><a class="btn btn-ghost" href="#how">How It Works</a></div>
|
|
<div class="stats reveal">
|
|
<div class="stat"><div class="n" data-count="6">0</div><div class="l">Casino Games</div></div>
|
|
<div class="stat"><div class="n" data-count="100">0</div><div class="l">% Lightning Payouts</div></div>
|
|
<div class="stat"><div class="n" data-count="0">0</div><div class="l">KYC Requirements</div></div>
|
|
<div class="stat"><div class="n" data-count="24">0</div><div class="l">/ 7 Live</div></div>
|
|
</div>
|
|
<div class="marquee"><div class="track" id="mtrack"><span><i>🎰</i>SLOTS</span><span><i>💣</i>MINES</span><span><i>🎲</i>DICE</span><span><i>📈</i>CRASH</span><span><i>🃏</i>BLACKJACK</span><span><i>🎯</i>PLINKO</span><span><i>⚡</i>LIGHTNING</span></div></div>
|
|
</div>
|
|
<section id="games"><div class="wrap">
|
|
<h2 class="reveal">Pick Your Poison</h2>
|
|
<p class="lead reveal">Six games. One engine. Zero delays. <a href="/play" style="color:var(--accent);font-weight:800">Launch the casino →</a></p>
|
|
<div class="grid">
|
|
<div class="card tilt reveal"><span class="ico">🎰</span><h3>Slots</h3><p>Classic 3-reel action with 777 jackpots and multiplier lines. Pure dopamine, one spin away.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">💣</span><h3>Mines</h3><p>Reveal safe tiles, dodge the bombs, cash out when your nerve breaks. Risk/reward at its finest.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🎲</span><h3>Dice</h3><p>Pick your odds, roll under the number, double or nothing. The simplest game in the house.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">📈</span><h3>Crash</h3><p>The multiplier climbs until it doesn't. Cash out before the crash — greed is a strategy, until it isn't.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🃏</span><h3>Blackjack</h3><p>Beat the dealer to 21. Hit, stand, and count your sats when the house busts.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🎯</span><h3>Plinko</h3><p>Drop the ball, watch it bounce, pray to the peg gods. Big drops mean big multipliers.</p></div>
|
|
</div>
|
|
</div></section>
|
|
<section id="how"><div class="wrap">
|
|
<h2 class="reveal">Three Steps To Winning</h2>
|
|
<p class="lead reveal">Faster than a bank transfer to the moon.</p>
|
|
<div class="grid">
|
|
<div class="card reveal"><div class="stepnum">01</div><h3>Create a House Account</h3><p>No KYC, no email hoops. Your account lives in the casino — anonymous by design.</p></div>
|
|
<div class="card reveal"><div class="stepnum">02</div><h3>⚡ Top Up With Lightning</h3><p>Scan the invoice with any Lightning wallet. Sats land in seconds, not days.</p></div>
|
|
<div class="card reveal"><div class="stepnum">03</div><h3>Play & Withdraw Instantly</h3><p>Bet sats, stack sats, withdraw sats. Payouts hit your wallet the moment you cash out.</p></div>
|
|
</div>
|
|
</div></section>
|
|
<section id="lightning"><div class="wrap">
|
|
<div class="cta-band reveal">
|
|
<h2>⚡ Powered By The Lightning Network</h2>
|
|
<p class="lead" style="margin:14px auto 34px">Real Bitcoin, real fast. Deposits and withdrawals over Lightning — the same network the whole sats economy runs on.</p>
|
|
<a class="btn btn-primary" href="/play">⚡ Enter The Casino</a>
|
|
</div>
|
|
</div></section>
|
|
"""
|
|
),
|
|
"signalminer": dict(
|
|
title="Signal Miner X — Market Intelligence",
|
|
ac="#00e676", ac2="#00e5ff", bg="#03050a", bg2="#071018", card="#0d1420", txt="#e4e8f4", mut="#7a8699",
|
|
glow="rgba(0,230,118,.4)", glowsoft="rgba(0,230,118,.14)", border="rgba(0,230,118,.5)",
|
|
band="rgba(0,229,255,.16)",
|
|
typephrases=['📡 1,085+ Telegram channels monitored', '🎁 Gift cards before your competition', '🔑 Software keys, wholesale prices', '🤖 API access for your bots'],
|
|
slots=False, wave=True,
|
|
nav=[('Features','#features'),('Coverage','#coverage'),('Pricing','#pricing')],
|
|
navcta=('Launch App','/signup'),
|
|
body="""<div class="hero">
|
|
<div class="typewrap"><span id="typewriter"></span><span class="cursor">▌</span></div>
|
|
<div class="badge"><span class="live"></span> LIVE · 1,085+ Telegram Marketplaces</div>
|
|
<h1>Mine The Signal.<br>Trade The Noise.</h1>
|
|
<p class="sub">Signal Miner X watches the Telegram marketplace underground in real time. Deals on gift cards, software keys, streaming accounts and hardware — surfaced, credibility-scored, and searchable before your competition even opens the app.</p>
|
|
<div class="cta"><a class="btn btn-primary" href="/signup">Get Free Searches</a><a class="btn btn-ghost" href="#pricing">$1 = 5 Searches</a></div>
|
|
<canvas id="wave" width="900" height="120" style="width:100%;max-width:900px;margin-top:60px;display:block"></canvas>
|
|
<div class="stats reveal">
|
|
<div class="stat"><div class="n" data-count="1085">0</div><div class="l">Channels Monitored</div></div>
|
|
<div class="stat"><div class="n" data-count="776">0</div><div class="l">Commerce Categories</div></div>
|
|
<div class="stat"><div class="n" data-count="430">0</div><div class="l">Gift Card Listings</div></div>
|
|
<div class="stat"><div class="n" data-count="0">0</div><div class="l">KYC Checks</div></div>
|
|
</div>
|
|
</div>
|
|
<section id="features"><div class="wrap">
|
|
<h2 class="reveal">Built For Deal Hunters</h2>
|
|
<p class="lead reveal">Everything you need to find the signal in the noise.</p>
|
|
<div class="grid">
|
|
<div class="card tilt reveal"><span class="ico">🔍</span><h3>Instant Search</h3><p>Search every monitored channel for the exact deal you want. Results in seconds, not scrobbles.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🎯</span><h3>Credibility Scoring</h3><p>Every seller and channel gets a trust score built from history, behavior and network signals.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🤖</span><h3>API Access</h3><p>Wire Signal Miner into your own bots and alerting. Your API key, your pipeline.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🛒</span><h3>776 Categories</h3><p>Gift cards, software keys, accounts, hardware, services. If it's traded, it's tracked.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">⚡</span><h3>Real-Time Feeds</h3><p>New listings land the moment they're posted. Speed is the entire game.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🔓</span><h3>No KYC, Ever</h3><p>Just an email for your key. Pay in Bitcoin. No forms, no ID, no nonsense.</p></div>
|
|
</div>
|
|
</div></section>
|
|
<section id="coverage"><div class="wrap">
|
|
<h2 class="reveal">The Underground, Mapped</h2>
|
|
<p class="lead reveal">1,085+ channels across 776 commerce categories — and counting.</p>
|
|
<div class="grid">
|
|
<div class="card reveal" style="text-align:center"><span class="ico">🎁</span><div class="n" data-count="430" style="font-size:2.2rem;font-weight:900;color:var(--accent)">0</div><p>Gift Cards</p></div>
|
|
<div class="card reveal" style="text-align:center"><span class="ico">🔑</span><div class="n" data-count="60" style="font-size:2.2rem;font-weight:900;color:var(--accent)">0</div><p>Software Keys</p></div>
|
|
<div class="card reveal" style="text-align:center"><span class="ico">📺</span><div class="n" data-count="86" style="font-size:2.2rem;font-weight:900;color:var(--accent)">0</div><p>Accounts</p></div>
|
|
<div class="card reveal" style="text-align:center"><span class="ico">💻</span><div class="n" data-count="80" style="font-size:2.2rem;font-weight:900;color:var(--accent)">0</div><p>Hardware</p></div>
|
|
<div class="card reveal" style="text-align:center"><span class="ico">🛠️</span><div class="n" data-count="120" style="font-size:2.2rem;font-weight:900;color:var(--accent)">0</div><p>Services & Tools</p></div>
|
|
</div>
|
|
</div></section>
|
|
<section id="pricing"><div class="wrap">
|
|
<h2 class="reveal">Ridiculously Simple Pricing</h2>
|
|
<p class="lead reveal">No subscriptions. Pay with Bitcoin. Get intelligence.</p>
|
|
<div class="pricing">
|
|
<div class="price-card reveal"><h3>🆓 Free Tier</h3><div class="amount">$0</div><div class="per">forever</div>
|
|
<ul><li>Free starter searches</li><li>Full channel access</li><li>Credibility scoring</li><li>No expiration</li></ul>
|
|
<a class="btn btn-ghost" href="/signup">Start Free</a></div>
|
|
<div class="price-card hot reveal"><div class="tag">MOST POPULAR</div><h3>🚀 Researcher Tier</h3><div class="amount">$1</div><div class="per">= 5 searches · Bitcoin ⚡</div>
|
|
<ul><li>5 marketplace searches</li><li>Full access to 1,085+ channels</li><li>Credibility scoring</li><li>API access for bots</li><li>No expiration · No KYC</li></ul>
|
|
<a class="btn btn-primary" href="/signup">Sign Up Free</a></div>
|
|
</div>
|
|
</div></section>
|
|
<section><div class="wrap">
|
|
<div class="cta-band reveal">
|
|
<h2>The Next Deal Is Already Posted.</h2>
|
|
<p class="lead" style="margin:14px auto 34px">Get your free searches and see what the underground is selling today.</p>
|
|
<a class="btn btn-primary" href="/signup">Claim Free Searches</a>
|
|
</div>
|
|
</div></section>
|
|
"""
|
|
),
|
|
"workbrain": dict(
|
|
title="Certus WorkBrain",
|
|
ac="#ffb300", ac2="#ff7043", bg="#0c0f14", bg2="#12161d", card="#161b23", txt="#eef1f5", mut="#8a94a3",
|
|
glow="rgba(255,179,0,.4)", glowsoft="rgba(255,179,0,.13)", border="rgba(255,179,0,.5)",
|
|
band="rgba(255,112,67,.14)",
|
|
typephrases=['🐜 Pest knowledge, indexed', '🧠 AI answers with citations', '📄 Every doc, instantly searchable', '🐛 Bug squashing on standby'],
|
|
slots=False, wave=False,
|
|
nav=[('Features','#features'),('Knowledge','#knowledge')],
|
|
navcta=('Open WorkBrain','/app'),
|
|
body="""<div class="hero">
|
|
<div class="typewrap"><span id="typewriter"></span><span class="cursor">▌</span></div>
|
|
<div class="badge"><span class="live"></span> CERTUS · KNOWLEDGE ENGINE</div>
|
|
<h1>Your Second Brain<br>For Pest Control.</h1>
|
|
<p class="sub">WorkBrain ingests your documents, chunks them into knowledge, and answers questions with citations. Chat, search, and squash bugs — one brain for the whole operation.</p>
|
|
<div class="cta"><a class="btn btn-primary" href="/app">🧠 Open WorkBrain</a><a class="btn btn-ghost" href="#features">What It Does</a></div>
|
|
<div class="stats reveal">
|
|
<div class="stat"><div class="n" data-count="24">0</div><div class="l">/ 7 Availability</div></div>
|
|
<div class="stat"><div class="n" data-count="100">0</div><div class="l">% Cited Answers</div></div>
|
|
<div class="stat"><div class="n" data-count="3">0</div><div class="l">Knowledge Pillars</div></div>
|
|
<div class="stat"><div class="n" data-count="1">0</div><div class="l">Bug Squasher</div></div>
|
|
</div>
|
|
</div>
|
|
<section id="features"><div class="wrap">
|
|
<h2 class="reveal">Everything In One Place</h2>
|
|
<p class="lead reveal">Stop digging through folders. Ask the brain.</p>
|
|
<div class="grid">
|
|
<div class="card tilt reveal"><span class="ico">💬</span><h3>AI Chat</h3><p>Ask anything about your operations. Answers come with citations straight from your documents.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">📄</span><h3>Document Vault</h3><p>Every ingested file, organized and retrievable. Drop it in, never lose it again.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🧩</span><h3>Knowledge Chunks</h3><p>Documents broken into searchable knowledge chunks — the raw material for every answer.</p></div>
|
|
<div class="card tilt reveal"><span class="ico">🐛</span><h3>Bug Squasher</h3><p>Click the bugs before they escape. The only pest-control game built into a knowledge base.</p></div>
|
|
</div>
|
|
</div></section>
|
|
<section id="knowledge"><div class="wrap">
|
|
<div class="cta-band reveal">
|
|
<h2>Stop Searching. Start Knowing.</h2>
|
|
<p class="lead" style="margin:14px auto 34px">Your entire pest-control knowledge base, one click away.</p>
|
|
<a class="btn btn-primary" href="/app">🐜 Enter WorkBrain</a>
|
|
</div>
|
|
</div></section>
|
|
"""
|
|
),
|
|
}
|
|
|
|
def build(name):
|
|
p = PAGES[name]
|
|
css = (ENGINE_CSS
|
|
.replace("AC;--accent2:AC2", f"{p['ac']};--accent2:{p['ac2']}").replace("BG;--bg2:BG2", f"{p['bg']};--bg2:{p['bg2']}")
|
|
.replace("CARD;--text:TXT", f"{p['card']};--text:{p['txt']}").replace("--muted:MUT", f"--muted:{p['mut']}")
|
|
.replace("COLORGLOW_SOFT", p['glowsoft']).replace("COLORGLOW_BAND", p['band'])
|
|
.replace("COLORGLOW", p['glow']).replace("ACBORDER", p['border']))
|
|
js = (ENGINE_JS
|
|
.replace('accent:"AC"', f'accent:"{p["ac"]}"').replace('accent2:"AC2"', f'accent2:"{p["ac2"]}"')
|
|
.replace('bg2:"BG2"', f'bg2:"{p["bg2"]}"').replace('glow:"COLORGLOW"', f'glow:"{p["glow"]}"')
|
|
.replace("wave:WAVE", f"wave:{str(p['wave']).lower()}").replace("slots:SLOTS", f"slots:{str(p['slots']).lower()}")
|
|
.replace("typephrases:TYPEPHRASES", "typephrases:" + repr(p['typephrases'])))
|
|
nav_html = "".join(f'<a href="{u}">{l}</a>' for l, u in p["nav"])
|
|
footer = (f'<footer>© 2026 {p["title"].split("—")[0].strip()} · '
|
|
f'<a href="https://buymeacoffee.com/r26xrthzttg">☕ Buy Me a Coffee</a></footer>')
|
|
html = f"""<!DOCTYPE html>
|
|
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
<title>{p['title']}</title><meta name="description" content="{p['title']}"><link rel="icon" href="data:,">
|
|
{css}</head><body>
|
|
<canvas id="fx"></canvas>
|
|
<nav><div class="brand"><span class="dot"></span>{p['title'].split('—')[0].strip()}</div>
|
|
<div class="navlinks">{nav_html}<a class="btn btn-primary" style="padding:10px 22px;font-size:.9rem" href="{p['navcta'][1]}">{p['navcta'][0]}</a></div></nav>
|
|
{p['body']}
|
|
<div id="stickycta"><a class="btn btn-primary" href="{p['navcta'][1]}">{p['navcta'][0]} →</a></div>
|
|
{footer}
|
|
{js}</body></html>"""
|
|
path = os.path.join(OUT, f"{name}.html")
|
|
with open(path, "w") as f:
|
|
f.write(html)
|
|
print(f"built {path} ({len(html)} bytes)")
|
|
|
|
for name in PAGES:
|
|
build(name)
|
|
print("DONE")
|