CyberMax-tools commited on
Commit
bdc2129
·
verified ·
1 Parent(s): 332029c

Apps pro.js: offline Pro keys (Ed25519) + direct checkout map (Workers cap fix, 17 Oct 2026)

Browse files
billsprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -154,7 +177,7 @@
154
 
155
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
156
 
157
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
158
  function start() {
159
  if (m && SID.test(decodeURIComponent(m[1]))) {
160
  var code = decodeURIComponent(m[1]);
@@ -164,3 +187,23 @@
164
  }
165
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
166
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
177
 
178
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
179
 
180
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
181
  function start() {
182
  if (m && SID.test(decodeURIComponent(m[1]))) {
183
  var code = decodeURIComponent(m[1]);
 
187
  }
188
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
189
  })();
190
+
191
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
192
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
193
+ by a background beacon. Without the map the link works as before. */
194
+ (function () {
195
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
196
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
197
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
198
+ document.addEventListener("click", function (e) {
199
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
200
+ if (!a || !MAP || !MAP.offers) return;
201
+ try {
202
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
203
+ if (!t) return;
204
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
205
+ a.href = t.split(MAP.ph).join(s);
206
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
207
+ } catch (x) { /* keep the counted link */ }
208
+ }, true);
209
+ })();
fitcheck/pro.js CHANGED
@@ -11,7 +11,7 @@
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
- var SID = /^(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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
@@ -19,7 +19,30 @@
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  function check(code) {
 
 
 
 
 
 
 
 
 
 
23
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
24
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
25
  }
@@ -99,10 +122,30 @@
99
 
100
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
101
 
102
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
103
  if (m && SID.test(decodeURIComponent(m[1]))) {
104
  var code = decodeURIComponent(m[1]);
105
  history.replaceState(null, "", location.pathname + location.search);
106
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
107
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
108
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
 
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
22
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
23
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
24
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
25
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
26
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
27
+ function cmxVerify(k) {
28
+ var parts = k.split("."), p = null;
29
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
30
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
31
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
32
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
33
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
34
+ }
35
  function check(code) {
36
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
37
+ return cmxVerify(code).then(function (r) {
38
+ var p = r.p;
39
+ if (!p || p.a !== C.id) return false;
40
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
41
+ return p.c ? checkOnline(p.c) : false;
42
+ });
43
+ }
44
+
45
+ function checkOnline(code) {
46
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
47
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
48
  }
 
122
 
123
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
124
 
125
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
126
  if (m && SID.test(decodeURIComponent(m[1]))) {
127
  var code = decodeURIComponent(m[1]);
128
  history.replaceState(null, "", location.pathname + location.search);
129
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
130
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
131
  })();
132
+
133
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
134
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
135
+ by a background beacon. Without the map the link works as before. */
136
+ (function () {
137
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
138
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
139
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
140
+ document.addEventListener("click", function (e) {
141
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
142
+ if (!a || !MAP || !MAP.offers) return;
143
+ try {
144
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
145
+ if (!t) return;
146
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
147
+ a.href = t.split(MAP.ph).join(s);
148
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
149
+ } catch (x) { /* keep the counted link */ }
150
+ }, true);
151
+ })();
hazelsprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
honeyfold/pro.js CHANGED
@@ -11,7 +11,7 @@
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
- var SID = /^(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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
@@ -19,7 +19,30 @@
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  function check(code) {
 
 
 
 
 
 
 
 
 
 
23
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
24
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
25
  }
@@ -99,10 +122,30 @@
99
 
100
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
101
 
102
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
103
  if (m && SID.test(decodeURIComponent(m[1]))) {
104
  var code = decodeURIComponent(m[1]);
105
  history.replaceState(null, "", location.pathname + location.search);
106
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
107
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
108
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
 
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
22
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
23
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
24
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
25
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
26
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
27
+ function cmxVerify(k) {
28
+ var parts = k.split("."), p = null;
29
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
30
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
31
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
32
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
33
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
34
+ }
35
  function check(code) {
36
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
37
+ return cmxVerify(code).then(function (r) {
38
+ var p = r.p;
39
+ if (!p || p.a !== C.id) return false;
40
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
41
+ return p.c ? checkOnline(p.c) : false;
42
+ });
43
+ }
44
+
45
+ function checkOnline(code) {
46
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
47
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
48
  }
 
122
 
123
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
124
 
125
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
126
  if (m && SID.test(decodeURIComponent(m[1]))) {
127
  var code = decodeURIComponent(m[1]);
128
  history.replaceState(null, "", location.pathname + location.search);
129
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
130
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
131
  })();
132
+
133
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
134
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
135
+ by a background beacon. Without the map the link works as before. */
136
+ (function () {
137
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
138
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
139
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
140
+ document.addEventListener("click", function (e) {
141
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
142
+ if (!a || !MAP || !MAP.offers) return;
143
+ try {
144
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
145
+ if (!t) return;
146
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
147
+ a.href = t.split(MAP.ph).join(s);
148
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
149
+ } catch (x) { /* keep the counted link */ }
150
+ }, true);
151
+ })();
hoursprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -154,7 +177,7 @@
154
 
155
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
156
 
157
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
158
  function start() {
159
  if (m && SID.test(decodeURIComponent(m[1]))) {
160
  var code = decodeURIComponent(m[1]);
@@ -164,3 +187,23 @@
164
  }
165
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
166
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
177
 
178
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
179
 
180
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
181
  function start() {
182
  if (m && SID.test(decodeURIComponent(m[1]))) {
183
  var code = decodeURIComponent(m[1]);
 
187
  }
188
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
189
  })();
190
+
191
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
192
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
193
+ by a background beacon. Without the map the link works as before. */
194
+ (function () {
195
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
196
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
197
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
198
+ document.addEventListener("click", function (e) {
199
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
200
+ if (!a || !MAP || !MAP.offers) return;
201
+ try {
202
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
203
+ if (!t) return;
204
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
205
+ a.href = t.split(MAP.ph).join(s);
206
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
207
+ } catch (x) { /* keep the counted link */ }
208
+ }, true);
209
+ })();
menumoor/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -154,7 +177,7 @@
154
 
155
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
156
 
157
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
158
  function start() {
159
  if (m && SID.test(decodeURIComponent(m[1]))) {
160
  var code = decodeURIComponent(m[1]);
@@ -164,3 +187,23 @@
164
  }
165
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
166
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
177
 
178
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
179
 
180
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
181
  function start() {
182
  if (m && SID.test(decodeURIComponent(m[1]))) {
183
  var code = decodeURIComponent(m[1]);
 
187
  }
188
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
189
  })();
190
+
191
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
192
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
193
+ by a background beacon. Without the map the link works as before. */
194
+ (function () {
195
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
196
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
197
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
198
+ document.addEventListener("click", function (e) {
199
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
200
+ if (!a || !MAP || !MAP.offers) return;
201
+ try {
202
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
203
+ if (!t) return;
204
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
205
+ a.href = t.split(MAP.ph).join(s);
206
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
207
+ } catch (x) { /* keep the counted link */ }
208
+ }, true);
209
+ })();
pactsprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
pitchsprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
platesprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
profit-margin-calculator/pro.js CHANGED
@@ -11,7 +11,7 @@
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
- var SID = /^(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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
@@ -19,7 +19,30 @@
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  function check(code) {
 
 
 
 
 
 
 
 
 
 
23
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
24
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
25
  }
@@ -99,10 +122,30 @@
99
 
100
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
101
 
102
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
103
  if (m && SID.test(decodeURIComponent(m[1]))) {
104
  var code = decodeURIComponent(m[1]);
105
  history.replaceState(null, "", location.pathname + location.search);
106
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
107
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
108
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
 
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
22
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
23
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
24
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
25
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
26
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
27
+ function cmxVerify(k) {
28
+ var parts = k.split("."), p = null;
29
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
30
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
31
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
32
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
33
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
34
+ }
35
  function check(code) {
36
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
37
+ return cmxVerify(code).then(function (r) {
38
+ var p = r.p;
39
+ if (!p || p.a !== C.id) return false;
40
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
41
+ return p.c ? checkOnline(p.c) : false;
42
+ });
43
+ }
44
+
45
+ function checkOnline(code) {
46
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
47
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
48
  }
 
122
 
123
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
124
 
125
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
126
  if (m && SID.test(decodeURIComponent(m[1]))) {
127
  var code = decodeURIComponent(m[1]);
128
  history.replaceState(null, "", location.pathname + location.search);
129
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
130
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
131
  })();
132
+
133
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
134
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
135
+ by a background beacon. Without the map the link works as before. */
136
+ (function () {
137
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
138
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
139
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
140
+ document.addEventListener("click", function (e) {
141
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
142
+ if (!a || !MAP || !MAP.offers) return;
143
+ try {
144
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
145
+ if (!t) return;
146
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
147
+ a.href = t.split(MAP.ph).join(s);
148
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
149
+ } catch (x) { /* keep the counted link */ }
150
+ }, true);
151
+ })();
quotesprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
rentsprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
rotasprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -154,7 +177,7 @@
154
 
155
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
156
 
157
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
158
  function start() {
159
  if (m && SID.test(decodeURIComponent(m[1]))) {
160
  var code = decodeURIComponent(m[1]);
@@ -164,3 +187,23 @@
164
  }
165
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
166
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
177
 
178
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
179
 
180
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
181
  function start() {
182
  if (m && SID.test(decodeURIComponent(m[1]))) {
183
  var code = decodeURIComponent(m[1]);
 
187
  }
188
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
189
  })();
190
+
191
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
192
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
193
+ by a background beacon. Without the map the link works as before. */
194
+ (function () {
195
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
196
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
197
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
198
+ document.addEventListener("click", function (e) {
199
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
200
+ if (!a || !MAP || !MAP.offers) return;
201
+ try {
202
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
203
+ if (!t) return;
204
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
205
+ a.href = t.split(MAP.ph).join(s);
206
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
207
+ } catch (x) { /* keep the counted link */ }
208
+ }, true);
209
+ })();
salary-to-hourly-calculator/pro.js CHANGED
@@ -11,7 +11,7 @@
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
- var SID = /^(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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
@@ -19,7 +19,30 @@
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  function check(code) {
 
 
 
 
 
 
 
 
 
 
23
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
24
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
25
  }
@@ -99,10 +122,30 @@
99
 
100
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
101
 
102
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
103
  if (m && SID.test(decodeURIComponent(m[1]))) {
104
  var code = decodeURIComponent(m[1]);
105
  history.replaceState(null, "", location.pathname + location.search);
106
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
107
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
108
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
 
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
22
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
23
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
24
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
25
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
26
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
27
+ function cmxVerify(k) {
28
+ var parts = k.split("."), p = null;
29
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
30
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
31
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
32
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
33
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
34
+ }
35
  function check(code) {
36
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
37
+ return cmxVerify(code).then(function (r) {
38
+ var p = r.p;
39
+ if (!p || p.a !== C.id) return false;
40
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
41
+ return p.c ? checkOnline(p.c) : false;
42
+ });
43
+ }
44
+
45
+ function checkOnline(code) {
46
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
47
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
48
  }
 
122
 
123
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
124
 
125
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
126
  if (m && SID.test(decodeURIComponent(m[1]))) {
127
  var code = decodeURIComponent(m[1]);
128
  history.replaceState(null, "", location.pathname + location.search);
129
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
130
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
131
  })();
132
+
133
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
134
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
135
+ by a background beacon. Without the map the link works as before. */
136
+ (function () {
137
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
138
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
139
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
140
+ document.addEventListener("click", function (e) {
141
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
142
+ if (!a || !MAP || !MAP.offers) return;
143
+ try {
144
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
145
+ if (!t) return;
146
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
147
+ a.href = t.split(MAP.ph).join(s);
148
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
149
+ } catch (x) { /* keep the counted link */ }
150
+ }, true);
151
+ })();
sigsprig/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
stampsprig/pro.js CHANGED
@@ -2,8 +2,8 @@
2
  * self-contained). Extends pro.js with several plans (monthly, yearly, one-time) and a re-check for subscriptions.
3
  * Config before this script:
4
  * window.CMX_PRO = { id, name, perks: [..], plans: [{ offer, label, price, per, note, best }], free: "one line" }
5
- * Buy: counted link https://data.cybermax-tools.workers.dev/buy/<offer>?s=app-<id> -> Stripe Payment Link.
6
- * After checkout Stripe sends the buyer to data.cybermax-tools.workers.dev/unlock/<id>?session_id=..., which checks the
7
  * Checkout Session (and, for a subscription, that it is still active) and returns here with #cmx-pro=<session id>.
8
  * The app checks that code once (/unlock/<id>?json=1&session_id=..) and remembers Pro in this browser; it re-checks every
9
  * 3 days, so a cancelled subscription turns off by itself (one tiny request per buyer every 3 days, none for free users).
@@ -13,9 +13,9 @@
13
  "use strict";
14
  var C = window.CMX_PRO || {};
15
  if (!C.id) return;
16
- var DATA = "https://data.cybermax-tools.workers.dev";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^cs_(live|test)_[A-Za-z0-9]{10,200}$/;
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -58,6 +81,18 @@
58
  function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }[c]; }); }
59
  function buyUrl(offer, from) { return DATA + "/buy/" + offer + "?s=app-" + C.id + (from ? "-" + from : ""); }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  function box() {
62
  var el = document.getElementById("cmx-pro");
63
  if (!el) {
@@ -86,10 +121,16 @@
86
  }).join("");
87
  el.innerHTML = '<h2>' + esc(C.name) + ' Pro</h2>' + (C.free ? '<p class="cmx-pro-small">Free: ' + esc(C.free) + "</p>" : "") +
88
  "<ul>" + C.perks.map(function (p) { return "<li>" + esc(p) + "</li>"; }).join("") + '</ul><div class="cmx-plans">' + plans +
89
- '</div><p class="cmx-pro-small">Secure Stripe checkout. Pro turns on the moment you pay; no account needed.' + (subs ? " Subscriptions cancel any time." : " One payment, no subscription.") + '</p>' +
90
- '<details><summary>Already bought Pro?</summary><form id="cmx-pro-form"><label>Unlock code <input id="cmx-pro-code" autocomplete="off" placeholder="cs_live_…"></label> <button class="btn ghost" type="submit">Unlock</button></form></details><p id="cmx-pro-msg" class="cmx-pro-small" aria-live="polite"></p>';
 
 
 
 
 
 
91
  var f = document.getElementById("cmx-pro-form");
92
- if (f) f.onsubmit = function (e) { e.preventDefault(); var c = (document.getElementById("cmx-pro-code").value || "").trim(); if (SID.test(c)) unlock(c); else toast("Paste the code from your receipt page (it starts with cs_live_)."); };
93
  }
94
 
95
  function apply() {
@@ -103,6 +144,12 @@
103
  var el = box();
104
  if (from) Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.href = buyUrl(a.getAttribute("data-offer"), from); });
105
  if (reason) toast(reason);
 
 
 
 
 
 
106
  el.scrollIntoView({ behavior: "smooth", block: "start" });
107
  el.classList.add("cmx-pro-flash"); setTimeout(function () { el.classList.remove("cmx-pro-flash"); }, 1600);
108
  }
@@ -128,7 +175,7 @@
128
 
129
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
130
 
131
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
132
  function start() {
133
  if (m && SID.test(decodeURIComponent(m[1]))) {
134
  var code = decodeURIComponent(m[1]);
@@ -138,3 +185,23 @@
138
  }
139
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
140
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  * self-contained). Extends pro.js with several plans (monthly, yearly, one-time) and a re-check for subscriptions.
3
  * Config before this script:
4
  * window.CMX_PRO = { id, name, perks: [..], plans: [{ offer, label, price, per, note, best }], free: "one line" }
5
+ * Buy: counted link https://data.cybermaxtools.com/buy/<offer>?s=app-<id> -> Stripe Payment Link.
6
+ * After checkout Stripe sends the buyer to data.cybermaxtools.com/unlock/<id>?session_id=..., which checks the
7
  * Checkout Session (and, for a subscription, that it is still active) and returns here with #cmx-pro=<session id>.
8
  * The app checks that code once (/unlock/<id>?json=1&session_id=..) and remembers Pro in this browser; it re-checks every
9
  * 3 days, so a cancelled subscription turns off by itself (one tiny request per buyer every 3 days, none for free users).
 
13
  "use strict";
14
  var C = window.CMX_PRO || {};
15
  if (!C.id) return;
16
+ var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
81
  function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }[c]; }); }
82
  function buyUrl(offer, from) { return DATA + "/buy/" + offer + "?s=app-" + C.id + (from ? "-" + from : ""); }
83
 
84
+ // Convert kit (funnel beacons, real proof, email capture, phone buy bar), loaded from the CyberMax Store; optional:
85
+ // if it can't load (offline), the app and the Pro box work exactly the same.
86
+ var KIT = "https://cybermaxtools.com/store/convert.js", kitQ = [];
87
+ function conv(fn) {
88
+ if (window.CMXConvert) return fn(window.CMXConvert);
89
+ kitQ.push(fn);
90
+ if (kitQ.length > 1 || !navigator.onLine) return;
91
+ var sc = document.createElement("script"); sc.src = KIT; sc.async = true;
92
+ sc.onload = function () { var q = kitQ.splice(0); q.forEach(function (f) { try { f(window.CMXConvert); } catch (e) { /* */ } }); };
93
+ document.head.appendChild(sc);
94
+ }
95
+
96
  function box() {
97
  var el = document.getElementById("cmx-pro");
98
  if (!el) {
 
121
  }).join("");
122
  el.innerHTML = '<h2>' + esc(C.name) + ' Pro</h2>' + (C.free ? '<p class="cmx-pro-small">Free: ' + esc(C.free) + "</p>" : "") +
123
  "<ul>" + C.perks.map(function (p) { return "<li>" + esc(p) + "</li>"; }).join("") + '</ul><div class="cmx-plans">' + plans +
124
+ '</div><p class="cmx-pro-small">Secure Stripe checkout. Pro turns on the moment you pay; no account needed.' + (subs ? " Subscriptions cancel any time from your receipt email." : " One payment, no subscription.") +
125
+ ' 14-day promise: if it doesn\'t work as described, we fix it or refund you in full (<a href="https://cybermaxtools.com/terms#payments" target="_blank" rel="noopener">terms</a>). Questions: <a href="mailto:cybermax.tools@gmail.com">cybermax.tools@gmail.com</a></p><div class="cmx-pro-proof"></div><div class="cmx-pro-cap"></div>' +
126
+ '<details><summary>Already bought Pro?</summary><form id="cmx-pro-form"><label>Unlock code <input id="cmx-pro-code" autocomplete="off" placeholder="cs_live_… or Gumroad licence key"></label> <button class="btn ghost" type="submit">Unlock</button></form></details><p id="cmx-pro-msg" class="cmx-pro-small" aria-live="polite"></p>';
127
+ Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.addEventListener("click", function () { conv(function (K) { K.event("upgrade-click", C.id); }); }); });
128
+ conv(function (K) {
129
+ K.proof(el.querySelector(".cmx-pro-proof"), C.id);
130
+ K.capture(el.querySelector(".cmx-pro-cap"), { list: "weekly-" + C.id, src: "app-" + C.id, label: "Not ready for Pro? Email me " + C.name + " tips and new features (about once a week)" });
131
+ });
132
  var f = document.getElementById("cmx-pro-form");
133
+ if (f) f.onsubmit = function (e) { e.preventDefault(); var c = (document.getElementById("cmx-pro-code").value || "").trim(); if (SID.test(c)) unlock(c); else toast("Paste the code from your receipt page (it starts with cs_live_) or your Gumroad licence key."); };
134
  }
135
 
136
  function apply() {
 
144
  var el = box();
145
  if (from) Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.href = buyUrl(a.getAttribute("data-offer"), from); });
146
  if (reason) toast(reason);
147
+ // A real limit: count it, and on phones keep one buy button in reach (no timer; closes with one tap).
148
+ conv(function (K) {
149
+ K.event("limit", C.id); K.event("upgrade-view", C.id);
150
+ var best = (C.plans || []).filter(function (p) { return p.best; })[0] || (C.plans || [])[0];
151
+ if (best && !isPro()) K.sticky({ text: C.name + " Pro: " + best.price + (best.per || ""), cta: "Go Pro", href: buyUrl(best.offer, (from || "limit") + "-bar"), product: C.id });
152
+ });
153
  el.scrollIntoView({ behavior: "smooth", block: "start" });
154
  el.classList.add("cmx-pro-flash"); setTimeout(function () { el.classList.remove("cmx-pro-flash"); }, 1600);
155
  }
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
tagwren/pro.js CHANGED
@@ -15,7 +15,7 @@
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
- var SID = /^(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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
@@ -24,7 +24,30 @@
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  function check(code) {
 
 
 
 
 
 
 
 
 
 
28
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
29
  .then(function (r) { return r.json(); })
30
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
@@ -152,7 +175,7 @@
152
 
153
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
154
 
155
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
156
  function start() {
157
  if (m && SID.test(decodeURIComponent(m[1]))) {
158
  var code = decodeURIComponent(m[1]);
@@ -162,3 +185,23 @@
162
  }
163
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
164
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!C.id) return;
16
  var DATA = "https://data.cybermaxtools.com";
17
  var KEY = "cmx-pro:" + C.id;
18
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
19
  var RECHECK = 3 * 864e5;
20
  var listeners = [];
21
 
 
24
  var mem = get();
25
  function isPro() { return !!(mem && mem.code); }
26
 
27
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
28
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
29
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
30
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
31
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
32
+ function cmxVerify(k) {
33
+ var parts = k.split("."), p = null;
34
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
35
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
36
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
37
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
38
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
39
+ }
40
  function check(code) {
41
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
42
+ return cmxVerify(code).then(function (r) {
43
+ var p = r.p;
44
+ if (!p || p.a !== C.id) return false;
45
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
46
+ return p.c ? checkOnline(p.c) : false;
47
+ });
48
+ }
49
+
50
+ function checkOnline(code) {
51
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
52
  .then(function (r) { return r.json(); })
53
  .then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
 
175
 
176
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
177
 
178
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
179
  function start() {
180
  if (m && SID.test(decodeURIComponent(m[1]))) {
181
  var code = decodeURIComponent(m[1]);
 
185
  }
186
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
187
  })();
188
+
189
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
190
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
191
+ by a background beacon. Without the map the link works as before. */
192
+ (function () {
193
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
194
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
195
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
196
+ document.addEventListener("click", function (e) {
197
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
198
+ if (!a || !MAP || !MAP.offers) return;
199
+ try {
200
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
201
+ if (!t) return;
202
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
203
+ a.href = t.split(MAP.ph).join(s);
204
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
205
+ } catch (x) { /* keep the counted link */ }
206
+ }, true);
207
+ })();
utm-builder/pro.js CHANGED
@@ -11,7 +11,7 @@
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
- var SID = /^(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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
@@ -19,7 +19,30 @@
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  function check(code) {
 
 
 
 
 
 
 
 
 
 
23
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
24
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
25
  }
@@ -99,10 +122,30 @@
99
 
100
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
101
 
102
- var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
103
  if (m && SID.test(decodeURIComponent(m[1]))) {
104
  var code = decodeURIComponent(m[1]);
105
  history.replaceState(null, "", location.pathname + location.search);
106
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
107
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
108
  })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if (!C.id) return;
12
  var DATA = "https://data.cybermaxtools.com";
13
  var KEY = "cmx-pro:" + C.id;
14
+ var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|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; // Stripe order code or Gumroad licence key
15
  var listeners = [];
16
 
17
  function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
 
19
  var mem = get();
20
  function isPro() { return !!(mem && mem.code); }
21
 
22
+ // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
23
+ // here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
24
+ // (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
25
+ var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
26
+ function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
27
+ function cmxVerify(k) {
28
+ var parts = k.split("."), p = null;
29
+ try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
30
+ if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
31
+ return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
32
+ .then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
33
+ .then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
34
+ }
35
  function check(code) {
36
+ if (!/^cmxk1\./.test(code)) return checkOnline(code);
37
+ return cmxVerify(code).then(function (r) {
38
+ var p = r.p;
39
+ if (!p || p.a !== C.id) return false;
40
+ if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
41
+ return p.c ? checkOnline(p.c) : false;
42
+ });
43
+ }
44
+
45
+ function checkOnline(code) {
46
  return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
47
  .then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
48
  }
 
122
 
123
  window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
124
 
125
+ var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
126
  if (m && SID.test(decodeURIComponent(m[1]))) {
127
  var code = decodeURIComponent(m[1]);
128
  history.replaceState(null, "", location.pathname + location.search);
129
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
130
  } else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
131
  })();
132
+
133
+ /* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
134
+ the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
135
+ by a background beacon. Without the map the link works as before. */
136
+ (function () {
137
+ var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
138
+ try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
139
+ if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
140
+ document.addEventListener("click", function (e) {
141
+ var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
142
+ if (!a || !MAP || !MAP.offers) return;
143
+ try {
144
+ var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
145
+ if (!t) return;
146
+ var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
147
+ a.href = t.split(MAP.ph).join(s);
148
+ if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
149
+ } catch (x) { /* keep the counted link */ }
150
+ }, true);
151
+ })();