// CyberMax game Skin Pack: a one-time cosmetic unlock for ONE game (separate from the Fun Pass, which covers every // game's archive + themes). Buy: counted redirect data.cybermaxtools.com/buy/st--skins-pack?s=game- // -> Stripe Payment Link; or the Gumroad listing (licence key). After checkout data.cybermaxtools.com/unlock/-skins // checks the order (or the Gumroad licence key) and returns to the game with ?unlock=skins#cmx-pro=. // capture() must run BEFORE funpass.init() so the Fun Pass never mistakes a skin-pack code for a pass code. // Cosmetic only: skins never change the game, scores or the daily course. (c) 2026 CyberMax. import { count, store, toast } from './cmx.js'; const DATA = 'https://data.cybermaxtools.com'; const CODE = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; let cfg = { game: '', name: '', price: '$1.99', gumroad: '', skins: 0 }; let state = null; const subs = []; const key = () => `cmx-skins:${cfg.game}`; export const owned = () => !!(state && state.code); export function onChange(fn) { subs.push(fn); } const emit = () => subs.forEach((f) => { try { f(owned()); } catch { /* game hook */ } }); async function check(code) { try { const r = await fetch(`${DATA}/unlock/${cfg.game}-skins?json=1&session_id=${encodeURIComponent(code)}`); const j = await r.json(); return j && typeof j.pro === 'boolean' ? j.pro : null; } catch { return null; } } export async function unlock(code) { const ok = await check(code); if (ok) { state = store(key(), { code, at: new Date().toISOString() }); count(cfg.game, 'pro', 'skins-unlocked'); toast(`${cfg.name} Skin Pack is on. Enjoy the new looks!`, 3500); emit(); render(); } else if (ok === false) toast('That code is not a Skin Pack order for this game.', 3500); else toast('Could not reach the unlock check. Try again in a minute.', 3500); return ok; } /** Call first: game id, display name, skin count, Gumroad URL. Reads ?unlock=skins#cmx-pro= after checkout. */ export function capture(options) { cfg = { ...cfg, ...options }; state = store(key()); const q = new URLSearchParams(location.search); const m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || ''); if (q.get('unlock') === 'skins' && m) { const code = decodeURIComponent(m[1]); q.delete('unlock'); history.replaceState(null, '', location.pathname + (q.toString() ? `?${q}` : '')); if (CODE.test(code)) unlock(code); } } const buyUrl = (from) => `${DATA}/buy/st-${cfg.game}-skins-pack?s=game-${cfg.game}${from ? `-${from}` : ''}`; function dialog() { let d = document.getElementById('skinpack'); if (!d) { d = document.createElement('dialog'); d.id = 'skinpack'; d.className = 'funpass'; document.body.appendChild(d); d.addEventListener('click', (e) => { if (e.target === d || e.target.closest('[data-close]')) d.close(); }); } return d; } function render() { const d = dialog(); const prev = (cfg.preview || []).map((s) => ``).join(''); if (owned()) { d.innerHTML = `

${cfg.name} Skin Pack

All ${cfg.skins} skins are yours. Thank you!

Pick one from the colour dots under the game.

Your code (paste it on another device):

${state.code}
`; return; } d.innerHTML = `

${cfg.name} Skin Pack

${cfg.skins} extra looks, ${cfg.price} once

${prev}

    ${(cfg.perks || []).map((p) => `
  • ${p}
  • `).join('')}
  • Cosmetic only: same course, same scores for everyone
  • Pay once, keep forever, on any device with your code

Get the Skin Pack: ${cfg.price}${cfg.gumroad ? ` or on Gumroad` : ''}

Secure Stripe checkout · the skins turn on as soon as you pay · 14-day promise: if it doesn't work as described, we fix it or refund you (terms). The Fun Pass is a separate pass for every game's archive and themes.

Already bought it?
`; d.querySelector('.fp-form').addEventListener('submit', (e) => { e.preventDefault(); const c = e.target.querySelector('input').value.trim(); if (CODE.test(c)) unlock(c); else toast('Paste the code from your receipt page (cs_live_…) or your Gumroad licence key.', 3500); }); d.querySelector('[data-buy]').addEventListener('click', () => count(cfg.game, 'cta', 'skins-buy')); d.querySelector('[data-gum]')?.addEventListener('click', () => count(cfg.game, 'cta', 'skins-gumroad')); } export function open(from = 'button') { render(); const d = dialog(); if (d.showModal) d.showModal(); else d.setAttribute('open', ''); count(cfg.game, 'cta', `skins-open-${from}`); }