diff --git a/public/assets/my.js b/public/assets/my.js index 89c94b6..6c187df 100644 --- a/public/assets/my.js +++ b/public/assets/my.js @@ -42,10 +42,10 @@ // achievement badges: the milestone ladder as unlockable medals + share-to-image const BADGES = [ - { key: 'payouts', label: 'Payouts On', sub: 'wallet linked', emblem: '⚡', icon: '' }, - { key: 'firstBuyer', label: 'First Buyer', sub: 'first qualified referral', emblem: '🎯', icon: '' }, - { key: 'level2', label: 'Level 2', sub: '2 qualifying buyers', emblem: '⭐', icon: '' }, - { key: 'level3', label: 'Level 3', sub: 'fully qualified', emblem: '🏆', icon: '' } + { key: 'payouts', label: 'Spark', sub: 'payouts on', img: '/badges/badge-spark.jpg' }, + { key: 'firstBuyer', label: 'Surge', sub: 'first qualifying buyer', img: '/badges/badge-surge.jpg' }, + { key: 'level2', label: 'Circuit', sub: '2 qualifying buyers', img: '/badges/badge-circuit.jpg' }, + { key: 'level3', label: 'Nexus', sub: 'fully qualified', img: '/badges/badge-nexus.jpg' } ]; let lastMilestones = []; function renderBadges(d) { @@ -57,9 +57,9 @@ strip.innerHTML = BADGES.map(b => { const got = reached.includes(b.key); return '
' - + '
' + b.icon + '
' + + '' + b.label + ' badge' + '
' + b.label + '
' + b.sub + '
' - + (got ? '' : '') + '
'; + + (got ? '' : '
🔒 locked
') + ''; }).join(''); strip.querySelectorAll('[data-badge]').forEach(btn => btn.addEventListener('click', () => shareBadge(btn.dataset.badge, d))); @@ -71,40 +71,35 @@ } } // compose a shareable badge image on a canvas (zero-dep) and download it + // composite the ornate badge template with the member's @username on the ribbon function shareBadge(key, d) { const b = BADGES.find(x => x.key === key); if (!b) return; - const c = document.createElement('canvas'); c.width = 1200; c.height = 630; - const x = c.getContext('2d'); - const g = x.createLinearGradient(0, 0, 1200, 630); - g.addColorStop(0, '#041109'); g.addColorStop(1, '#0b2018'); - x.fillStyle = g; x.fillRect(0, 0, 1200, 630); - x.strokeStyle = 'rgba(67,232,195,.5)'; x.lineWidth = 6; x.strokeRect(24, 24, 1152, 582); - x.fillStyle = '#43e8c3'; x.font = 'bold 34px Sora, sans-serif'; x.fillText('InstantAdPay', 70, 100); - x.fillStyle = '#8ba69c'; x.font = '22px Sora, sans-serif'; x.fillText('ACHIEVEMENT UNLOCKED', 70, 150); - // medal with the milestone emblem - x.beginPath(); x.arc(600, 300, 112, 0, Math.PI * 2); - const mg = x.createRadialGradient(600, 270, 20, 600, 300, 112); - mg.addColorStop(0, 'rgba(67,232,195,.5)'); mg.addColorStop(1, 'rgba(9,26,19,.92)'); - x.fillStyle = mg; x.fill(); x.strokeStyle = '#43e8c3'; x.lineWidth = 6; x.stroke(); - x.save(); x.shadowColor = 'rgba(67,232,195,.6)'; x.shadowBlur = 24; - x.font = '90px "Segoe UI Emoji","Noto Color Emoji",sans-serif'; x.textAlign = 'center'; x.textBaseline = 'middle'; - x.fillText(b.emblem || '', 600, 300); x.restore(); x.textBaseline = 'alphabetic'; - x.fillStyle = '#eef7f3'; x.textAlign = 'center'; - x.font = 'bold 60px Sora, sans-serif'; x.fillText(b.label, 600, 485); - x.font = '25px Sora, sans-serif'; x.fillStyle = '#8ba69c'; x.fillText(b.sub, 600, 527); const who = d.username ? '@' + d.username : d.memberId ? 'member #' + d.memberId : ''; - if (who) { x.fillStyle = '#43e8c3'; x.font = 'bold 30px Sora, sans-serif'; x.fillText(who, 600, 575); } - x.textAlign = 'left'; - try { - c.toBlob(bl => { - const a = document.createElement('a'); - a.href = URL.createObjectURL(bl); - a.download = 'instantadpay-' + key + '-badge.png'; - a.click(); - setTimeout(() => URL.revokeObjectURL(a.href), 5000); - IAP.status('Badge image saved — share it anywhere.', 'ok'); - }, 'image/png'); - } catch (e) { IAP.status('Could not generate the image.', 'bad'); } + const img = new Image(); + img.onload = () => { + const c = document.createElement('canvas'); c.width = img.width; c.height = img.height; + const x = c.getContext('2d'); + x.drawImage(img, 0, 0); + if (who) { // the blank ribbon sits at ~76% down; name it in dark ink on the mint banner + x.textAlign = 'center'; + x.fillStyle = '#04231b'; + x.font = 'bold ' + Math.round(c.width * 0.052) + 'px Sora, "Segoe UI", sans-serif'; + x.fillText(who, c.width / 2, c.height * 0.78); + x.textAlign = 'left'; + } + try { + c.toBlob(bl => { + const a = document.createElement('a'); + a.href = URL.createObjectURL(bl); + a.download = 'instantadpay-' + b.label.toLowerCase() + '-badge.jpg'; + a.click(); + setTimeout(() => URL.revokeObjectURL(a.href), 5000); + IAP.status('Your ' + b.label + ' badge is saved — share it anywhere.', 'ok'); + }, 'image/jpeg', 0.9); + } catch (e) { IAP.status('Could not generate the image.', 'bad'); } + }; + img.onerror = () => IAP.status('Could not load the badge art.', 'bad'); + img.src = b.img; // same-origin, canvas stays untainted } // milestone stepper under "Your next move": lit nodes for what's done, @@ -115,10 +110,10 @@ const b = d.buyerCount || 0; const steps = [ { label: 'Joined', sub: 'free account', hit: true }, - { label: 'Payouts on', sub: 'wallet linked', hit: !!d.memberId }, - { label: 'First buyer', sub: '50% of every pack', hit: b >= 1 }, - { label: 'Level 2', sub: '2 buyers · +20%', hit: b >= 2 }, - { label: 'Level 3', sub: '5 buyers · +10%', hit: b >= 5 } + { label: 'Spark', sub: 'payouts on', hit: !!d.memberId }, + { label: 'Surge', sub: 'first buyer · 50%', hit: b >= 1 }, + { label: 'Circuit', sub: '2 buyers · +20%', hit: b >= 2 }, + { label: 'Nexus', sub: '5 buyers · +10%', hit: b >= 5 } ]; const cur = steps.findIndex(s => !s.hit); el.innerHTML = steps.map((s, i) => diff --git a/public/assets/site.css b/public/assets/site.css index 3cc55b6..299ead6 100644 --- a/public/assets/site.css +++ b/public/assets/site.css @@ -280,8 +280,10 @@ textarea{resize:vertical;font:inherit} .feat-strip a:hover{border-color:var(--mint)} .feat-strip .by{font-size:12px;color:var(--muted);font-weight:500;white-space:nowrap} /* ── achievement badges ── */ -.badges{display:flex;gap:16px;flex-wrap:wrap;margin-top:12px} -.badge-a{display:flex;flex-direction:column;align-items:center;gap:8px;width:120px;text-align:center} +.badges{display:flex;gap:18px;flex-wrap:wrap;margin-top:12px} +.badge-a{display:flex;flex-direction:column;align-items:center;gap:6px;width:150px;text-align:center} +.badge-a .badge-img{width:150px;height:150px;border-radius:14px;object-fit:cover;border:1px solid var(--line-strong)} +.badge-a.locked .badge-img{filter:grayscale(.85) brightness(.5);opacity:.7} .badge-a .medal{width:76px;height:76px;border-radius:50%;display:grid;place-items:center;position:relative; background:radial-gradient(circle at 50% 35%,rgba(67,232,195,.28),rgba(9,26,19,.9)); border:2px solid var(--mint);box-shadow:0 0 18px rgba(67,232,195,.3)} diff --git a/public/badges/badge-circuit.jpg b/public/badges/badge-circuit.jpg new file mode 100644 index 0000000..b75d43d Binary files /dev/null and b/public/badges/badge-circuit.jpg differ diff --git a/public/badges/badge-nexus.jpg b/public/badges/badge-nexus.jpg new file mode 100644 index 0000000..31ce810 Binary files /dev/null and b/public/badges/badge-nexus.jpg differ diff --git a/public/badges/badge-spark.jpg b/public/badges/badge-spark.jpg new file mode 100644 index 0000000..fe3b15c Binary files /dev/null and b/public/badges/badge-spark.jpg differ diff --git a/public/badges/badge-surge.jpg b/public/badges/badge-surge.jpg new file mode 100644 index 0000000..13da958 Binary files /dev/null and b/public/badges/badge-surge.jpg differ diff --git a/public/contract.html b/public/contract.html index af86125..0bf7e6d 100644 --- a/public/contract.html +++ b/public/contract.html @@ -16,7 +16,7 @@ - +
@@ -140,8 +140,8 @@
Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible. Never spend what you cannot afford.
- - - + + + diff --git a/public/index.html b/public/index.html index 03b226c..a434e3f 100644 --- a/public/index.html +++ b/public/index.html @@ -19,7 +19,7 @@ - + @@ -437,9 +437,9 @@ - - - - + + + + diff --git a/public/ledger.html b/public/ledger.html index 5b501bd..53385f9 100644 --- a/public/ledger.html +++ b/public/ledger.html @@ -16,7 +16,7 @@ - +
@@ -36,8 +36,8 @@
- - - + + + diff --git a/public/my.html b/public/my.html index f35f97a..8325a82 100644 --- a/public/my.html +++ b/public/my.html @@ -4,7 +4,7 @@ Member area | InstantAdPay - + @@ -595,9 +595,9 @@ - - - - + + + + diff --git a/public/shorts.html b/public/shorts.html index a5d274c..97b731c 100644 --- a/public/shorts.html +++ b/public/shorts.html @@ -4,7 +4,7 @@ Shorts | InstantAdPay - +