Spaces:
Running
Running
Deploy platesprig to the hub
Browse files- platesprig/index.html +2 -2
- platesprig/pro.js +27 -2
platesprig/index.html
CHANGED
|
@@ -34,7 +34,7 @@
|
|
| 34 |
</head>
|
| 35 |
<body>
|
| 36 |
<header class="top"><div class="wrap top-in">
|
| 37 |
-
<a class="brand" href=".
|
| 38 |
<nav class="top-nav">
|
| 39 |
<button class="btn ghost sm" id="btn-install" type="button" hidden>Install app</button>
|
| 40 |
<a href="#cmx-pro" class="top-link">Pricing</a>
|
|
@@ -266,5 +266,5 @@ Brioche buns,12 x 1 each,7.80,</pre></details>
|
|
| 266 |
<script src="pro.js"></script>
|
| 267 |
<script src="lib/cost.js"></script>
|
| 268 |
<script src="app.js"></script>
|
| 269 |
-
<
|
| 270 |
</html>
|
|
|
|
| 34 |
</head>
|
| 35 |
<body>
|
| 36 |
<header class="top"><div class="wrap top-in">
|
| 37 |
+
<a class="brand" href="index.html" aria-label="Platesprig home"><img src="icon.svg" alt="" width="30" height="30"><span><b>Platesprig</b> <small>by CyberMax</small></span></a>
|
| 38 |
<nav class="top-nav">
|
| 39 |
<button class="btn ghost sm" id="btn-install" type="button" hidden>Install app</button>
|
| 40 |
<a href="#cmx-pro" class="top-link">Pricing</a>
|
|
|
|
| 266 |
<script src="pro.js"></script>
|
| 267 |
<script src="lib/cost.js"></script>
|
| 268 |
<script src="app.js"></script>
|
| 269 |
+
</body>
|
| 270 |
</html>
|
platesprig/pro.js
CHANGED
|
@@ -58,6 +58,18 @@
|
|
| 58 |
function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[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) {
|
|
@@ -75,9 +87,10 @@
|
|
| 75 |
if (isPro()) {
|
| 76 |
el.innerHTML = '<h2>' + esc(C.name) + ' Pro <span class="cmx-pro-badge">on</span></h2><p>Thank you! Pro is on in this browser: ' + C.perks.map(esc).join(" · ") +
|
| 77 |
'.</p><p class="cmx-pro-small">Your unlock code (paste it on another device): <code style="user-select:all;word-break:break-all">' + esc(mem.code) +
|
| 78 |
-
'</code></p><p class="cmx-pro-small">Monthly or yearly plan? Cancel any time from the link in your Stripe receipt email.</p>';
|
| 79 |
return;
|
| 80 |
}
|
|
|
|
| 81 |
var plans = (C.plans || []).map(function (p) {
|
| 82 |
return '<a class="cmx-plan' + (p.best ? " best" : "") + '" href="' + buyUrl(p.offer) + '" rel="nofollow" data-offer="' + esc(p.offer) + '">' +
|
| 83 |
(p.best ? "<i>Best value</i>" : "") + "<b>" + esc(p.label) + '</b><span class="cmx-price">' + esc(p.price) + "<small>" + esc(p.per || "") +
|
|
@@ -85,8 +98,14 @@
|
|
| 85 |
}).join("");
|
| 86 |
el.innerHTML = '<h2>' + esc(C.name) + ' Pro</h2>' + (C.free ? '<p class="cmx-pro-small">Free: ' + esc(C.free) + "</p>" : "") +
|
| 87 |
"<ul>" + C.perks.map(function (p) { return "<li>" + esc(p) + "</li>"; }).join("") + '</ul><div class="cmx-plans">' + plans +
|
| 88 |
-
'</div><p class="cmx-pro-small">Secure Stripe checkout. Pro turns on the moment you pay; no account needed. Subscriptions cancel any time.
|
|
|
|
| 89 |
'<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>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
var f = document.getElementById("cmx-pro-form");
|
| 91 |
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_)."); };
|
| 92 |
}
|
|
@@ -102,6 +121,12 @@
|
|
| 102 |
var el = box();
|
| 103 |
if (from) Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.href = buyUrl(a.getAttribute("data-offer"), from); });
|
| 104 |
if (reason) toast(reason);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
| 106 |
el.classList.add("cmx-pro-flash"); setTimeout(function () { el.classList.remove("cmx-pro-flash"); }, 1600);
|
| 107 |
}
|
|
|
|
| 58 |
function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[c]; }); }
|
| 59 |
function buyUrl(offer, from) { return DATA + "/buy/" + offer + "?s=app-" + C.id + (from ? "-" + from : ""); }
|
| 60 |
|
| 61 |
+
// Convert kit (funnel beacons, real proof, email capture, phone buy bar), loaded from the CyberMax Store; optional:
|
| 62 |
+
// if it can't load (offline), the app and the Pro box work exactly the same.
|
| 63 |
+
var KIT = "https://cybermax.cybermax-tools.workers.dev/store/convert.js", kitQ = [];
|
| 64 |
+
function conv(fn) {
|
| 65 |
+
if (window.CMXConvert) return fn(window.CMXConvert);
|
| 66 |
+
kitQ.push(fn);
|
| 67 |
+
if (kitQ.length > 1 || !navigator.onLine) return;
|
| 68 |
+
var sc = document.createElement("script"); sc.src = KIT; sc.async = true;
|
| 69 |
+
sc.onload = function () { var q = kitQ.splice(0); q.forEach(function (f) { try { f(window.CMXConvert); } catch (e) { /* */ } }); };
|
| 70 |
+
document.head.appendChild(sc);
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
function box() {
|
| 74 |
var el = document.getElementById("cmx-pro");
|
| 75 |
if (!el) {
|
|
|
|
| 87 |
if (isPro()) {
|
| 88 |
el.innerHTML = '<h2>' + esc(C.name) + ' Pro <span class="cmx-pro-badge">on</span></h2><p>Thank you! Pro is on in this browser: ' + C.perks.map(esc).join(" · ") +
|
| 89 |
'.</p><p class="cmx-pro-small">Your unlock code (paste it on another device): <code style="user-select:all;word-break:break-all">' + esc(mem.code) +
|
| 90 |
+
'</code></p>' + ((C.plans || []).some(function (p) { return /\//.test(p.per || ""); }) ? '<p class="cmx-pro-small">Monthly or yearly plan? Cancel any time from the link in your Stripe receipt email.</p>' : "");
|
| 91 |
return;
|
| 92 |
}
|
| 93 |
+
var subs = (C.plans || []).some(function (p) { return /\//.test(p.per || ""); });
|
| 94 |
var plans = (C.plans || []).map(function (p) {
|
| 95 |
return '<a class="cmx-plan' + (p.best ? " best" : "") + '" href="' + buyUrl(p.offer) + '" rel="nofollow" data-offer="' + esc(p.offer) + '">' +
|
| 96 |
(p.best ? "<i>Best value</i>" : "") + "<b>" + esc(p.label) + '</b><span class="cmx-price">' + esc(p.price) + "<small>" + esc(p.per || "") +
|
|
|
|
| 98 |
}).join("");
|
| 99 |
el.innerHTML = '<h2>' + esc(C.name) + ' Pro</h2>' + (C.free ? '<p class="cmx-pro-small">Free: ' + esc(C.free) + "</p>" : "") +
|
| 100 |
"<ul>" + C.perks.map(function (p) { return "<li>" + esc(p) + "</li>"; }).join("") + '</ul><div class="cmx-plans">' + plans +
|
| 101 |
+
'</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.") +
|
| 102 |
+
' 14-day promise: if it doesn\'t work as described, we fix it or refund you in full (<a href="https://cybermax.cybermax-tools.workers.dev/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>' +
|
| 103 |
'<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>';
|
| 104 |
+
Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.addEventListener("click", function () { conv(function (K) { K.event("upgrade-click", C.id); }); }); });
|
| 105 |
+
conv(function (K) {
|
| 106 |
+
K.proof(el.querySelector(".cmx-pro-proof"), C.id);
|
| 107 |
+
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)" });
|
| 108 |
+
});
|
| 109 |
var f = document.getElementById("cmx-pro-form");
|
| 110 |
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_)."); };
|
| 111 |
}
|
|
|
|
| 121 |
var el = box();
|
| 122 |
if (from) Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.href = buyUrl(a.getAttribute("data-offer"), from); });
|
| 123 |
if (reason) toast(reason);
|
| 124 |
+
// A real limit: count it, and on phones keep one buy button in reach (no timer; closes with one tap).
|
| 125 |
+
conv(function (K) {
|
| 126 |
+
K.event("limit", C.id); K.event("upgrade-view", C.id);
|
| 127 |
+
var best = (C.plans || []).filter(function (p) { return p.best; })[0] || (C.plans || [])[0];
|
| 128 |
+
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 });
|
| 129 |
+
});
|
| 130 |
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
| 131 |
el.classList.add("cmx-pro-flash"); setTimeout(function () { el.classList.remove("cmx-pro-flash"); }, 1600);
|
| 132 |
}
|