{"id":29770,"date":"2026-09-07T12:45:08","date_gmt":"2026-09-07T16:45:08","guid":{"rendered":"https:\/\/thegiveawayguy.biz\/?page_id=29770"},"modified":"2026-09-08T05:31:07","modified_gmt":"2026-09-08T09:31:07","slug":"webinar-calculator","status":"publish","type":"page","link":"https:\/\/thegiveawayguy.biz\/webinar-calculator\/","title":{"rendered":"Webinar Calculator"},"content":{"rendered":"<p style=\"text-align: center;\"><strong><span data-contrast=\"none\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 1\" style=\"\"><span data-contrast=\"none\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 2\" style=\"\"><span data-contrast=\"none\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 3\" style=\"\"><strong><span data-ccp-parastyle=\"heading 1\" style=\"\"><span data-contrast=\"none\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 2\" style=\"\"><span data-contrast=\"none\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 2\" style=\"\"><span data-contrast=\"auto\" lang=\"EN-US\" style=\"\"><span data-contrast=\"none\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 2\" style=\"\"><span data-ccp-parastyle=\"heading 1\" style=\"\"><span data-ccp-parastyle=\"heading 1\"><span data-ccp-parastyle=\"heading 1\"><span data-ccp-parastyle=\"heading 1\">Private Partnership Offer<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/strong><\/span><\/span><\/span><\/span><\/span><\/span><\/strong><\/p>\n<p style=\"text-align: center;\"><span data-contrast=\"auto\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 3\" style=\"\"><span data-contrast=\"auto\" lang=\"EN-US\" style=\"\"><span data-ccp-parastyle=\"heading 2\" style=\"\"><span data-ccp-parastyle=\"heading 3\" style=\"\"><span data-ccp-parastyle=\"heading 2\" style=\"\"><span data-contrast=\"auto\" lang=\"EN-US\" style=\"\"><span data-contrast=\"auto\" lang=\"EN-US\"><span data-contrast=\"auto\" lang=\"EN-US\"><span data-contrast=\"auto\" lang=\"EN-US\">ADD ANY EXTRA BENEFITS OR DESCRIPTION HERE<\/span><\/span><\/span><br \/><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p><span><img decoding=\"async\" alt=\"\" width=\"477\" data-init-width=\"2560\" height=\"266\" data-init-height=\"1429\" loading=\"lazy\" src=\"https:\/\/thegiveawayguy.biz\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_is0wkqis0wkqis0w-scaled.jpg\" data-width=\"477\" data-height=\"266\" style=\"aspect-ratio: auto 2560 \/ 1429;\" data-id=\"30011\" title=\"Gemini_Generated_Image_is0wkqis0wkqis0w\"><\/span><span><img decoding=\"async\" alt=\"\" width=\"477\" data-init-width=\"2560\" height=\"266\" data-init-height=\"1429\" loading=\"lazy\" src=\"https:\/\/thegiveawayguy.biz\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_o8iymdo8iymdo8iy-scaled.jpg\" data-width=\"477\" data-height=\"266\" style=\"aspect-ratio: auto 2560 \/ 1429;\" data-id=\"30012\" title=\"Gemini_Generated_Image_o8iymdo8iymdo8iy\"><\/span><span><img decoding=\"async\" alt=\"\" width=\"477\" data-init-width=\"2560\" height=\"260\" data-init-height=\"1397\" loading=\"lazy\" src=\"https:\/\/thegiveawayguy.biz\/wp-content\/uploads\/2026\/09\/2-scaled.jpg\" data-width=\"477\" data-height=\"260\" style=\"aspect-ratio: auto 2560 \/ 1397;\" data-id=\"30018\" title=\"2\"><\/span><span><img decoding=\"async\" alt=\"\" width=\"477\" data-init-width=\"2560\" height=\"260\" data-init-height=\"1396\" loading=\"lazy\" src=\"https:\/\/thegiveawayguy.biz\/wp-content\/uploads\/2026\/09\/Gemini_Generated_Image_qwbqtuqwbqtuqwbq-scaled.jpg\" data-width=\"477\" data-height=\"260\" style=\"aspect-ratio: auto 2560 \/ 1396;\" data-id=\"30013\" title=\"Gemini_Generated_Image_qwbqtuqwbqtuqwbq\"><\/span><!--  =================================================================  LIFETIME REFERRAL CALCULATOR - popup embed for Thrive Architect  =================================================================  HOW TO USE  1. In Thrive Architect, drag a \"Custom HTML\" element where you     want the button to appear.  2. Paste this ENTIRE file into it and save.  3. Check it on the live page \/ preview link. Thrive's editor     canvas does not run custom scripts, so the popup only opens     on the front end.  NOTES  - Use this snippet ONCE per page (element IDs must stay unique).  - Button text: edit the line marked \"EDIT BUTTON TEXT\".  - The popup fills 95% of the screen on every side and can ONLY    be closed with the X button (clicking outside \/ pressing    Escape does nothing, on purpose).  - \"Saved Scenarios\" are SHARED: every visitor, every browser sees    the same list. This needs the companion WordPress plugin    \"ULC Shared Scenarios\" installed and active on this site (it    stores the list and serves it at \/wp-json\/ulc\/v1\/scenarios).    Without the plugin the widget quietly falls back to per-browser    saving and says so in the status line. Anyone can save AND    delete; to limit deleting to admins, add to wp-config.php:    define('ULC_SCEN_PUBLIC_DELETE', false);  - Everything is namespaced \"ulc-\" and the popup is moved to     at runtime, so it will not restyle other sections and    the theme will not restyle the calculator.  - Optional dark look: add the class \"ulc-dark\" to the    #ulc-overlay div below (default is always-light so it matches    a light sales page for every visitor).--><!-- ======== TRIGGER BUTTON (this is what shows in the section) ======== -->  <!-- vvv EDIT BUTTON TEXT vvv -->  Access Calculator Here  <!-- ^^^ EDIT BUTTON TEXT ^^^ --><!-- ======== POPUP (hidden until the button is clicked) ======== -->            <span>Lifetime Referral Calculator<\/span>      \u2715                      <\/p>\n<p>Referral Compensation Modeling<\/p>\n<h1>Lifetime Referral Calculator<\/h1>\n<p>Plug in numbers for a five-level referral plan and see what it pays out \u2014 level by level, and month by month as the network grows. Prefilled with a starter example: heavy pay on the bottom levels, nothing on the top two. Change anything and the numbers update live.<\/p>\n<p>                  <span><span>\u2713<\/span> $0 to join<\/span>          <span><span>\u2713<\/span> No purchase minimums or quotas<\/span>          <span><span>\u2713<\/span> Paid on real purchases only \u2014 never on recruiting<\/span>                                  <span>Saved scenarios<\/span>                                                                              <\/p>\n<h2>Plan Inputs<\/h2>\n<h3>Commission<\/h3>\n<p>                      Commission mode                          % of volume              % of commission                        <\/p>\n<p id=\"ulc-cascadeHint\" hidden=\"\">Level 1 earns a % of the sale, same as &#8220;% of volume&#8221; mode. Every level below that earns a % of the commission the level directly above it just earned \u2014 not a % of the sale, and not tied to that level&#8217;s own headcount or volume.<\/p>\n<h3>Growth &amp; Retention<\/h3>\n<p>                      Level 1 direct referrals                                            Level 2 direct referrals                                            Avg monthly purchase \/ member ($)                                                          Monthly drop-off (%)                                                    Months to fill out the network                                                          Set yearly income goal                                            <\/p>\n<h3>Saved Scenarios<\/h3>\n<p style=\"margin:0 0 10px;\">Save the current settings under a name \u2014 saved scenarios are shared, so everyone who opens this calculator sees them in the bar under the summary tiles. Click one there anytime to load it.<\/p>\n<p>                                        Save Scenario                        <span id=\"ulc-saveStatus\" aria-live=\"polite\"><\/span>            <\/p>\n<p id=\"ulc-savedEmpty\">No saved scenarios yet.<\/p>\n<h2>Tier Detail<\/h2>\n<p>A tier is only part of the payout when its rate is above 0 \u2014 set it to 0 and that tier drops out of every total below, though its referral ratio still feeds the tier beneath it.<\/p>\n<h2>Month by Month, as the Network Fills In<\/h2>\n<p>This isn&#8217;t the &#8220;full network&#8221; total from the boxes above \u2014 it&#8217;s how the payout builds up over time as people actually join, using the &#8220;months to fill out the network&#8221; number on the left.<\/p>\n<h2>Payout by Tier, at Full Network<\/h2>\n<p id=\"ulc-chartEmptyMsg\" hidden=\"\">No active tiers yet \u2014 set a rate above 0 on at least one tier to see it here.<\/p>\n<p id=\"ulc-chartInactiveNote\">\n<h2>Get Your Feedback Back To Me<\/h2>\n<p>Tune the numbers above until this plan looks right to you, then capture your exact settings below and paste them into an email to me.<\/p>\n<p>                  Your name \/ handle                                    What would get you in?                                    Copy My Scenario          <span id=\"ulc-fbStatus\"><\/span>                                    <\/p>\n<p>Figures are monthly unless noted. Each tier&#8217;s commission applies only to that tier&#8217;s own network volume \u2014 paid for as long as a referred member keeps purchasing, never a one-time recruiting bonus.<\/p>\n<p>This is a modeling tool for exploring &#8220;what-if&#8221; scenarios based on assumptions you control. Projections are hypothetical, not a promise or guarantee of income \u2014 actual results depend on real referral and purchase activity, and individual results vary. Commission is paid solely on completed member purchases, never on recruiting activity, sign-up fees, or membership dues.<\/p>\n<p>          <!-- \/.ulc-page -->  <!-- \/.ulc-modal --><!-- \/#ulc-overlay -->[tcb-script](function(){  &#8216;use strict&#8217;;  function ready(fn){    if(document.readyState === &#8216;loading&#8217;){ document.addEventListener(&#8216;DOMContentLoaded&#8217;, fn); }    else{ fn(); }  }  ready(function(){    var overlay = document.getElementById(&#8216;ulc-overlay&#8217;);    var openBtn = document.getElementById(&#8216;ulc-open-btn&#8217;);    var closeBtn = document.getElementById(&#8216;ulc-close-btn&#8217;);    if(!overlay || !openBtn || !closeBtn){ return; }    \/\/ Move the popup to &lt;body&gt; so position:fixed can&#8217;t get trapped inside    \/\/ transformed\/animated Thrive sections, and so Thrive&#8217;s #tve_editor    \/\/ typography rules can&#8217;t reach into the calculator.    if(overlay.parentNode !== document.body){ document.body.appendChild(overlay); }    var byId = function(id){ return document.getElementById(&#8216;ulc-&#8216; + id); };    var booted = false;    var lastFocus = null;    var prevBodyOverflow = &#8221;;    var prevHtmlOverflow = &#8221;;    function openModal(){      if(!booted){        booted = true;        try{ initCalculator(); }catch(err){ if(window.console &amp;&amp; console.error){ console.error(&#8216;ULC init failed:&#8217;, err); } }      }      lastFocus = document.activeElement;      prevBodyOverflow = document.body.style.overflow;      prevHtmlOverflow = document.documentElement.style.overflow;      document.body.style.overflow = &#8216;hidden&#8217;;      document.documentElement.style.overflow = &#8216;hidden&#8217;;      overlay.classList.add(&#8216;ulc-open&#8217;);      var scroller = overlay.querySelector(&#8216;.ulc-page&#8217;);      if(scroller){ scroller.scrollTop = 0; }      if(overlay.__ulcRefresh){ overlay.__ulcRefresh(); }      closeBtn.focus();    }    function closeModal(){      overlay.classList.remove(&#8216;ulc-open&#8217;);      document.body.style.overflow = prevBodyOverflow;      document.documentElement.style.overflow = prevHtmlOverflow;      if(lastFocus &amp;&amp; typeof lastFocus.focus === &#8216;function&#8217;){ lastFocus.focus(); }    }    openBtn.addEventListener(&#8216;click&#8217;, openModal);    closeBtn.addEventListener(&#8216;click&#8217;, closeModal);    \/\/ Close ONLY via the X button: no backdrop-click close, no Escape close.    document.addEventListener(&#8216;keydown&#8217;, function(e){      if(!overlay.classList.contains(&#8216;ulc-open&#8217;)){ return; }      if(e.key === &#8216;Tab&#8217;){        var focusables = overlay.querySelectorAll(&#8216;button, input, textarea, select, [href], [tabindex]:not([tabindex=&#8221;-1&#8243;])&#8217;);        if(!focusables.length){ return; }        var first = focusables[0];        var last = focusables[focusables.length &#8211; 1];        if(e.shiftKey &amp;&amp; document.activeElement === first){ e.preventDefault(); last.focus(); }        else if(!e.shiftKey &amp;&amp; document.activeElement === last){ e.preventDefault(); first.focus(); }      }    });    \/\/ ================= Calculator (built on first open) =================    function initCalculator(){      const LEVELS = 5;      const compDefaults = { percent: [0, 0, 8, 12, 15], cascade: [10, 50, 50, 50, 50] };      const state = {        mode: &#8216;percent&#8217;,        level1: 50,        level2: 200,        purchase: 120,        churn: 5,        ramp: 12,        baseline: 60000,        comp: compDefaults.percent.slice()      };      const lvlColor = n =&gt; `var(&#8211;ulc-lvl-${n})`;      const fmtMoney = (v, opts) =&gt; {        const o = Object.assign({ maximumFractionDigits: 0 }, opts || {});        return &#8216;$&#8217; + Number(v).toLocaleString(undefined, o);      };      const fmtMoneyShort = v =&gt; {        if (v &gt;= 1000) return &#8216;$&#8217; + (v \/ 1000).toFixed(v &gt;= 10000 ? 0 : 1) + &#8216;k&#8217;;        return &#8216;$&#8217; + Math.round(v);      };      const fmtInt = v =&gt; Math.round(v).toLocaleString();      function compute(){        \/\/ Level 1 and Level 2 are both manual, direct counts. Level 3 is fixed        \/\/ at double Level 2, Level 4 double Level 3, Level 5 double Level 4.        const heads = [state.level1, state.level2];        for(let i=2;i&lt;LEVELS;i++){          heads.push(Math.round(heads[i-1] * 2));        }        const vols = heads.map(h =&gt; h * state.purchase);        const pays = [];        for(let i=0;i&lt;LEVELS;i++){          const rate = state.comp[i] || 0;          if(state.mode === &#8216;percent&#8217;){            pays.push((rate\/100) * vols[i]);          } else { \/\/ cascade: Level 1 = % of its own volume; every level below            \/\/ = % of the DOLLAR commission the level directly above it earned.            const base = i === 0 ? vols[i] : pays[i-1];            pays.push((rate\/100) * base);          }        }        return { heads, vols, pays };      }      function computeTimelineSeries(){        const { heads } = compute();        const activeIdx = state.comp.map(c =&gt; c &gt; 0);        const ramp = Math.max(0.001, state.ramp);        const segment = ramp \/ LEVELS;        const maxMonth = Math.min(60, Math.max(1, Math.round(ramp) + 12));        const series = [];        for(let m=0; m&lt;=maxMonth; m++){          let total = 0;          let prevPay = 0;          for(let i=0;i&lt;LEVELS;i++){            const startM = i * segment;            const finishM = (i+1) * segment;            let head;            if(m &lt;= startM) head = 0;            else if(m &gt;= finishM) head = heads[i];            else head = heads[i] * (m &#8211; startM) \/ (finishM &#8211; startM);            const vol = head * state.purchase;            const rate = state.comp[i] || 0;            let pay = 0;            if(activeIdx[i]){              if(state.mode === &#8216;percent&#8217;) pay = (rate\/100) * vol;              else pay = (rate\/100) * (i === 0 ? vol : prevPay);            }            total += pay;            prevPay = state.mode === &#8216;cascade&#8217; ? pay : prevPay;          }          series.push({ month: m, total });        }        return series;      }      \/\/ &#8212;- DOM is built ONCE per structural change (mode switch) and only      \/\/ &#8212;- text\/values are patched on every keystroke, so inputs never lose focus.      function buildLevelTree(){        const tree = byId(&#8216;levelTree&#8217;);        const rateStep = &#8216;0.1&#8217;;        function rateLabelFor(n){          if(state.mode === &#8216;cascade&#8217;) return n === 1 ? &#8216;Commission rate on sale (%)&#8217; : `% of Level ${n-1}&#8217;s commission`;          return &#8216;Commission rate (%)&#8217;;        }        tree.innerHTML = [1,2,3,4,5].map((n,i)=&gt;`            &lt;div id=&#8221;ulc-row-${n}&#8221;&gt;              &lt;span style=&#8221;background:${lvlColor(n)}&#8221;&gt;&lt;\/span&gt;              &lt;div id=&#8221;ulc-card-${n}&#8221;&gt;                &lt;div&gt;                  &lt;span&gt;Level ${n}&lt;\/span&gt;                  &lt;span id=&#8221;ulc-hc-${n}&#8221;&gt;&lt;\/span&gt;                &lt;\/div&gt;                ${i&gt;=2 ? `&lt;p style=&#8221;margin:-6px 0 10px;&#8221;&gt;Fixed assumption: Level ${n} = double Level ${n-1}.&lt;\/p&gt;` : &#8221;}                &lt;div&gt;                  &lt;div&gt;                    &lt;label for=&#8221;ulc-comp-${n}&#8221; id=&#8221;ulc-complabel-${n}&#8221;&gt;${rateLabelFor(n)}&lt;\/label&gt;                    &lt;input type=&#8221;number&#8221; id=&#8221;ulc-comp-${n}&#8221; data-idx=&#8221;${i}&#8221; min=&#8221;0&#8243; step=&#8221;${rateStep}&#8221; value=&#8221;${state.comp[i]}&#8221;&gt;                  &lt;\/div&gt;                  &lt;div id=&#8221;ulc-volwrap-${n}&#8221;&gt;                    &lt;span&gt;Monthly volume&lt;\/span&gt;                    &lt;span id=&#8221;ulc-vol-${n}&#8221;&gt;&lt;\/span&gt;                  &lt;\/div&gt;                  &lt;div id=&#8221;ulc-paywrap-${n}&#8221;&gt;                    &lt;span&gt;Monthly payout&lt;\/span&gt;                    &lt;span id=&#8221;ulc-pay-${n}&#8221;&gt;&lt;\/span&gt;                  &lt;\/div&gt;                &lt;\/div&gt;                &lt;p id=&#8221;ulc-note-${n}&#8221; hidden&gt;&lt;\/p&gt;              &lt;\/div&gt;            &lt;\/div&gt;          `).join(&#8221;);        tree.querySelectorAll(&#8216;.ulc-comp-input&#8217;).forEach(inp=&gt;{          inp.addEventListener(&#8216;input&#8217;, e=&gt;{            const idx = +e.target.dataset.idx;            state.comp[idx] = Math.max(0, parseFloat(e.target.value) || 0);            updateAll();          });        });      }      function buildChart(){        const chart = byId(&#8216;chart&#8217;);        chart.innerHTML = [1,2,3,4,5].map(n=&gt;`            &lt;div id=&#8221;ulc-crow-${n}&#8221;&gt;              &lt;span&gt;Level ${n}&lt;\/span&gt;              &lt;div id=&#8221;ulc-track-${n}&#8221;&gt;                &lt;div id=&#8221;ulc-fill-${n}&#8221; style=&#8221;background:${lvlColor(n)}&#8221;&gt;&lt;\/div&gt;              &lt;\/div&gt;              &lt;span id=&#8221;ulc-cval-${n}&#8221;&gt;&lt;\/span&gt;              &lt;span id=&#8221;ulc-cformula-${n}&#8221;&gt;&lt;\/span&gt;            &lt;\/div&gt;          `).join(&#8221;);      }      function renderTimeline(){        const wrap = byId(&#8216;timelineChart&#8217;);        const series = computeTimelineSeries();        const baselineMonthly = state.baseline \/ 12;        const maxMonth = series[series.length &#8211; 1].month;        const maxVal = Math.max(baselineMonthly, &#8230;series.map(p =&gt; p.total)) * 1.15 || 1;        const W = 720, H = 260, padL = 60, padR = 16, padT = 16, padB = 30;        const plotW = W &#8211; padL &#8211; padR, plotH = H &#8211; padT &#8211; padB;        const xAt = m =&gt; padL + (maxMonth ? (m \/ maxMonth) : 0) * plotW;        const yAt = v =&gt; padT + plotH &#8211; (maxVal ? (v \/ maxVal) : 0) * plotH;        const linePts = series.map(p =&gt; `${xAt(p.month).toFixed(1)},${yAt(p.total).toFixed(1)}`).join(&#8216; &#8216;);        const areaPts = `${padL.toFixed(1)},${(padT+plotH).toFixed(1)} ${linePts} ${xAt(maxMonth).toFixed(1)},${(padT+plotH).toFixed(1)}`;        const tickEvery = maxMonth &lt;= 12 ? 2 : maxMonth &lt;= 24 ? 4 : 6;        let xTicks = &#8221;;        for(let m=0; m&lt;=maxMonth; m+=tickEvery){          xTicks += `&lt;text x=&#8221;${xAt(m).toFixed(1)}&#8221; y=&#8221;${H-10}&#8221; text-anchor=&#8221;middle&#8221;&gt;${m}&lt;\/text&gt;`;        }        const yVals = [0, maxVal\/2, maxVal];        let yTicks = &#8221;;        yVals.forEach(v=&gt;{          const y = yAt(v);          yTicks += `&lt;line x1=&#8221;${padL}&#8221; y1=&#8221;${y.toFixed(1)}&#8221; x2=&#8221;${W-padR}&#8221; y2=&#8221;${y.toFixed(1)}&#8221;\/&gt;`;          yTicks += `&lt;text x=&#8221;${padL-8}&#8221; y=&#8221;${(y+4).toFixed(1)}&#8221; text-anchor=&#8221;end&#8221;&gt;${fmtMoneyShort(v)}&lt;\/text&gt;`;        });        const baselineY = yAt(baselineMonthly);        const cross = series.find(p =&gt; p.total &gt;= baselineMonthly);        let crossHtml = &#8221;;        if(cross){          const cx = xAt(cross.month), cy = yAt(cross.total);          const anchor = cx &gt; W &#8211; 110 ? &#8216;end&#8217; : &#8216;middle&#8217;;          crossHtml = `            &lt;line x1=&#8221;${cx.toFixed(1)}&#8221; y1=&#8221;${cy.toFixed(1)}&#8221; x2=&#8221;${cx.toFixed(1)}&#8221; y2=&#8221;${(padT+plotH).toFixed(1)}&#8221;\/&gt;            &lt;circle cx=&#8221;${cx.toFixed(1)}&#8221; cy=&#8221;${cy.toFixed(1)}&#8221; r=&#8221;4.5&#8243;\/&gt;            &lt;text x=&#8221;${cx.toFixed(1)}&#8221; y=&#8221;${(cy-10).toFixed(1)}&#8221; text-anchor=&#8221;${anchor}&#8221;&gt;Month ${cross.month}&lt;\/text&gt;          `;        }        wrap.innerHTML = `          &lt;div&gt;            &lt;svg viewBox=&#8221;0 0 ${W} ${H}&#8221; id=&#8221;ulc-tlSvg&#8221; preserveAspectRatio=&#8221;none&#8221;&gt;              ${yTicks}              &lt;line x1=&#8221;${padL}&#8221; y1=&#8221;${baselineY.toFixed(1)}&#8221; x2=&#8221;${W-padR}&#8221; y2=&#8221;${baselineY.toFixed(1)}&#8221;\/&gt;              &lt;text x=&#8221;${W-padR}&#8221; y=&#8221;${(baselineY-6).toFixed(1)}&#8221; text-anchor=&#8221;end&#8221;&gt;${fmtMoney(baselineMonthly)}\/mo baseline&lt;\/text&gt;              &lt;polygon points=&#8221;${areaPts}&#8221;&gt;&lt;\/polygon&gt;              &lt;polyline points=&#8221;${linePts}&#8221;&gt;&lt;\/polyline&gt;              ${crossHtml}              ${xTicks}              &lt;line x1=&#8221;${padL}&#8221; y1=&#8221;${(padT+plotH).toFixed(1)}&#8221; x2=&#8221;${W-padR}&#8221; y2=&#8221;${(padT+plotH).toFixed(1)}&#8221;\/&gt;              &lt;g id=&#8221;ulc-tlCrosshair&#8221; style=&#8221;display:none;&#8221;&gt;                &lt;line x1=&#8221;0&#8243; y1=&#8221;${padT}&#8221; x2=&#8221;0&#8243; y2=&#8221;${padT+plotH}&#8221;&gt;&lt;\/line&gt;                &lt;circle r=&#8221;4&#8243;&gt;&lt;\/circle&gt;              &lt;\/g&gt;              &lt;rect x=&#8221;${padL}&#8221; y=&#8221;${padT}&#8221; width=&#8221;${plotW}&#8221; height=&#8221;${plotH}&#8221; id=&#8221;ulc-tlHit&#8221;&gt;&lt;\/rect&gt;            &lt;\/svg&gt;            &lt;div id=&#8221;ulc-tlTooltip&#8221; hidden&gt;&lt;\/div&gt;          &lt;\/div&gt;          &lt;p&gt;${cross            ? `Around &lt;strong&gt;month ${cross.month}&lt;\/strong&gt;, this plan starts paying more per month than ${fmtMoney(baselineMonthly)} &amp;mdash; which is what $${Math.round(state.baseline\/1000)}k\/yr works out to per month.`            : `At this pace, it doesn&#8217;t get above ${fmtMoney(baselineMonthly)}\/mo within ${maxMonth} months &amp;mdash; try a shorter &#8220;months to fill out the network,&#8221; higher referral numbers, or richer bottom-tier rates.`}&lt;\/p&gt;        `;        const svg = byId(&#8216;tlSvg&#8217;);        const hit = byId(&#8216;tlHit&#8217;);        const crosshair = byId(&#8216;tlCrosshair&#8217;);        const tooltip = byId(&#8216;tlTooltip&#8217;);        const crosshairLine = crosshair.querySelector(&#8216;.ulc-crosshair-line&#8217;);        const crosshairDot = crosshair.querySelector(&#8216;.ulc-crosshair-dot&#8217;);        function onMove(evt){          const rect = svg.getBoundingClientRect();          const clientX = evt.touches ? evt.touches[0].clientX : evt.clientX;          const relX = (clientX &#8211; rect.left) \/ rect.width * W;          let m = Math.round(((relX &#8211; padL) \/ plotW) * maxMonth);          m = Math.max(0, Math.min(maxMonth, m));          const pt = series[m];          const x = xAt(pt.month), y = yAt(pt.total);          crosshair.style.display = &#8216;block&#8217;;          crosshairLine.setAttribute(&#8216;x1&#8217;, x); crosshairLine.setAttribute(&#8216;x2&#8217;, x);          crosshairDot.setAttribute(&#8216;cx&#8217;, x); crosshairDot.setAttribute(&#8216;cy&#8217;, y);          tooltip.hidden = false;          tooltip.textContent = `Month ${pt.month} u00b7 ${fmtMoney(pt.total)}\/mo`;          tooltip.style.left = (x \/ W * 100) + &#8216;%&#8217;;          tooltip.style.top = (y \/ H * 100) + &#8216;%&#8217;;        }        function onLeave(){          crosshair.style.display = &#8216;none&#8217;;          tooltip.hidden = true;        }        hit.addEventListener(&#8216;mousemove&#8217;, onMove);        hit.addEventListener(&#8216;mouseleave&#8217;, onLeave);        hit.addEventListener(&#8216;touchmove&#8217;, onMove, { passive: true });        hit.addEventListener(&#8216;touchend&#8217;, onLeave);        return { cross, maxMonth };      }      function updateAll(){        const { heads, vols, pays } = compute();        const activeIdx = state.comp.map(c =&gt; c &gt; 0);        const totalPayout = pays.reduce((s,p,i)=&gt; s + (activeIdx[i] ? p : 0), 0);        const totalDownline = heads.reduce((s,h,i)=&gt; s + (activeIdx[i] ? h : 0), 0);        const totalVolume = vols.reduce((s,v,i)=&gt; s + (activeIdx[i] ? v : 0), 0);        let totalRate, rateSub;        if(state.mode === &#8216;cascade&#8217;){          \/\/ The level rates aren&#8217;t additive here (each is a cut of a different,          \/\/ shrinking base) &#8211; the honest total is what actually got paid out,          \/\/ expressed as a % of Level 1&#8217;s volume (the original sale amount).          totalRate = vols[0] ? (totalPayout \/ vols[0] * 100) : 0;          rateSub = &#8220;total paid out, as a % of Level 1&#8217;s volume u2014 not a sum of the rates, since each level cuts into the level above&#8221;;        } else {          totalRate = state.comp.reduce((s,c)=&gt;s+c,0);          rateSub = &#8216;sum of all 5 level rates&#8217;;        }        const monthlyReplacement = totalDownline * (state.churn\/100);        const { cross, maxMonth } = renderTimeline();        const crossVal = cross ? `Month ${cross.month}` : `not within ${maxMonth} mo`;        const crossSub = cross ? `that&#8217;s when this plan starts paying more per month than $${Math.round(state.baseline\/1000)}k\/yr works out to` : `at this pace it doesn&#8217;t catch up within ${maxMonth} months u2014 try more months to build, or richer bottom-tier rates`;        byId(&#8216;summary&#8217;).innerHTML = `          &lt;div&gt;            &lt;span&gt;Total Monthly Payout&lt;\/span&gt;            &lt;span&gt;${fmtMoney(totalPayout)}&lt;\/span&gt;            &lt;span&gt;${fmtMoney(totalPayout*12)} \/ yr at full network&lt;\/span&gt;          &lt;\/div&gt;          &lt;div&gt;            &lt;span&gt;Month They Beat Their $${Math.round(state.baseline\/1000)}k&lt;\/span&gt;            &lt;span&gt;${crossVal}&lt;\/span&gt;            &lt;span&gt;${crossSub}&lt;\/span&gt;          &lt;\/div&gt;          &lt;div&gt;            &lt;span&gt;Total Commission Allowed&lt;\/span&gt;            &lt;span&gt;${(Math.round(totalRate*10)\/10) + &#8216;%&#8217;}&lt;\/span&gt;            &lt;span&gt;${rateSub}&lt;\/span&gt;          &lt;\/div&gt;          &lt;div&gt;            &lt;span&gt;New People Needed Monthly&lt;\/span&gt;            &lt;span&gt;${fmtInt(monthlyReplacement)}&lt;\/span&gt;            &lt;span&gt;just to replace the ${state.churn}% who stop buying each month&lt;\/span&gt;          &lt;\/div&gt;          &lt;div&gt;            &lt;span&gt;Total Network (Active Tiers)&lt;\/span&gt;            &lt;span&gt;${fmtInt(totalDownline)}&lt;\/span&gt;            &lt;span&gt;people, at full network&lt;\/span&gt;          &lt;\/div&gt;          &lt;div&gt;            &lt;span&gt;Total Monthly Volume&lt;\/span&gt;            &lt;span&gt;${fmtMoney(totalVolume)}&lt;\/span&gt;            &lt;span&gt;active tiers, at full network&lt;\/span&gt;          &lt;\/div&gt;        `;        const maxPay = Math.max(1, &#8230;pays.filter((p,i)=&gt;activeIdx[i]));        const inactiveLabels = [];        heads.forEach((h,i)=&gt;{          const n = i+1;          const active = activeIdx[i];          if(!active) inactiveLabels.push(n);          byId(&#8216;row-&#8216;+n).classList.toggle(&#8216;ulc-inactive&#8217;, !active);          byId(&#8216;card-&#8216;+n).classList.toggle(&#8216;ulc-inactive&#8217;, !active);          const hcEl = byId(&#8216;hc-&#8216;+n);          hcEl.hidden = !active;          hcEl.textContent = active ? fmtInt(h) + &#8216; people&#8217; : &#8221;;          byId(&#8216;volwrap-&#8216;+n).hidden = !active;          byId(&#8216;vol-&#8216;+n).textContent = active ? fmtMoney(vols[i]) : &#8221;;          byId(&#8216;paywrap-&#8216;+n).hidden = !active;          byId(&#8216;pay-&#8216;+n).textContent = active ? fmtMoney(pays[i]) : &#8221;;          const noteEl = byId(&#8216;note-&#8216;+n);          noteEl.hidden = active;          if(!active){            noteEl.textContent = `No commission on Level ${n} u2014 set a rate above 0 to include it in payout totals.`              + (n &lt; 5 ? ` Level ${n}&#8217;s headcount still feeds into Level ${n+1}&#8217;s network size.` : &#8221;);          }          const crow = byId(&#8216;crow-&#8216;+n);          if(!active){            crow.style.display = &#8216;none&#8217;;            return;          }          crow.style.display = &#8216;grid&#8217;;          let formula;          if(state.mode === &#8216;percent&#8217;){            formula = `${state.comp[i]}% u00d7 ${fmtMoney(vols[i])} volume`;          } else if(i === 0){            formula = `${state.comp[i]}% u00d7 ${fmtMoney(vols[i])} volume`;          } else {            formula = `${state.comp[i]}% u00d7 ${fmtMoney(pays[i-1])} (Level ${n-1}&#8217;s commission)`;          }          const widthPct = Math.max(3, (pays[i]\/maxPay)*100);          const fillEl = byId(&#8216;fill-&#8216;+n);          fillEl.style.width = widthPct + &#8216;%&#8217;;          byId(&#8216;cval-&#8216;+n).textContent = fmtMoney(pays[i]);          byId(&#8216;cformula-&#8216;+n).textContent = formula;        });        byId(&#8216;chartEmptyMsg&#8217;).hidden = activeIdx.some(Boolean);        const noteEl2 = byId(&#8216;chartInactiveNote&#8217;);        noteEl2.textContent = (activeIdx.some(Boolean) &amp;&amp; inactiveLabels.length)          ? `Level${inactiveLabels.length &gt; 1 ? &#8216;s&#8217; : &#8221;} ${inactiveLabels.join(&#8216;, &#8216;)} ${inactiveLabels.length &gt; 1 ? &#8216;are&#8217; : &#8216;is&#8217;} not part of the payout u2014 give ${inactiveLabels.length &gt; 1 ? &#8216;them&#8217; : &#8216;it&#8217;} a rate above 0 to include ${inactiveLabels.length &gt; 1 ? &#8216;them&#8217; : &#8216;it&#8217;} here.`          : &#8221;;        return { totalPayout, totalDownline, totalVolume, totalRate, monthlyReplacement, crossVal };      }      \/\/ Mode toggle rebuilds structure (labels\/units change) &#8211; fine since it&#8217;s      \/\/ a discrete click, not mid-keystroke typing.      const segBtns = overlay.querySelectorAll(&#8216;.ulc-seg-btn&#8217;);      segBtns.forEach(btn=&gt;{        btn.addEventListener(&#8216;click&#8217;, ()=&gt;{          segBtns.forEach(b=&gt;b.classList.remove(&#8216;ulc-active&#8217;));          btn.classList.add(&#8216;ulc-active&#8217;);          state.mode = btn.dataset.mode;          state.comp = compDefaults[state.mode].slice();          byId(&#8216;cascadeHint&#8217;).hidden = state.mode !== &#8216;cascade&#8217;;          buildLevelTree();          updateAll();        });      });      function bindGlobal(id, apply){        byId(id).addEventListener(&#8216;input&#8217;, e=&gt;{          apply(parseFloat(e.target.value));          updateAll();        });      }      bindGlobal(&#8216;level1Count&#8217;, v =&gt; state.level1 = Math.max(0, v || 0));      bindGlobal(&#8216;level2Count&#8217;, v =&gt; state.level2 = Math.max(0, v || 0));      bindGlobal(&#8216;avgPurchase&#8217;, v =&gt; state.purchase = Math.max(0, v || 0));      bindGlobal(&#8216;churnRate&#8217;, v =&gt; state.churn = Math.max(0, v || 0));      bindGlobal(&#8216;rampMonths&#8217;, v =&gt; state.ramp = Math.max(1, v || 1));      bindGlobal(&#8216;baselineIncome&#8217;, v =&gt; state.baseline = Math.max(0, v || 0));      \/\/ &#8212;- Feedback capture: no server-side storage (this page can be opened      \/\/ by people outside your organization, which rules out shared-database      \/\/ storage) &#8211; instead it builds a text summary the affiliate copies      \/\/ and pastes into an email to you.      function buildScenarioText(){        const name = byId(&#8216;fbName&#8217;).value.trim() || &#8216;Anonymous&#8217;;        const comment = byId(&#8216;fbComment&#8217;).value.trim() || &#8216;(no comment)&#8217;;        const { heads, vols, pays } = compute();        const result = updateAll();        const rateUnit = &#8216;%&#8217;;        const modeLabel = state.mode === &#8216;percent&#8217; ? &#8216;% of volume&#8217;          : &#8216;% of commission (cascading)&#8217;;        const rateLine = state.comp.map((c,i)=&gt; `L${i+1} ${c}${rateUnit}`).join(&#8216;, &#8216;);        const totalLabel = state.mode === &#8216;cascade&#8217;          ? `${Math.round(result.totalRate*10)\/10}% of Level 1&#8217;s volume (cascading, not a sum)`          : `${Math.round(result.totalRate*10)\/10}${rateUnit === &#8216;%&#8217; ? &#8216;%&#8217; : &#8221;}`;        return [          `Referral plan scenario u2014 ${name}`,          `Mode: ${modeLabel}`,          `Level 1 direct referrals: ${fmtInt(state.level1)}`,          `Level 2 direct referrals: ${fmtInt(state.level2)}`,          `Levels 3-5: fixed at double the level above (L3=2u00d7L2, L4=2u00d7L3, L5=2u00d7L4)`,          `Avg monthly purchase \/ member: ${fmtMoney(state.purchase)}`,          `% of members who stop buying each month: ${state.churn}%`,          `Months to fill out the whole network: ${state.ramp}`,          `Current income to beat: ${fmtMoney(state.baseline)}\/yr`,          &#8220;,          `Level rates: ${rateLine}`,          `Total commission (all levels added up): ${totalLabel}`,          &#8220;,          `Results once the network is fully built:`,          `  Total monthly payout: ${fmtMoney(result.totalPayout)} (${fmtMoney(result.totalPayout*12)}\/yr)`,          `  Total people in the paid levels: ${fmtInt(result.totalDownline)}`,          `  Month this plan&#8217;s payout passes their current income: ${result.crossVal}`,          `  New people needed monthly just to replace who stops buying: ${fmtInt(result.monthlyReplacement)}`,          &#8220;,          `Comment: ${comment}`        ].join(&#8216;n&#8217;);      }      byId(&#8216;fbCopyBtn&#8217;).addEventListener(&#8216;click&#8217;, async ()=&gt;{        const text = buildScenarioText();        const status = byId(&#8216;fbStatus&#8217;);        const out = byId(&#8216;fbOut&#8217;);        let copied = false;        try{          if(navigator.clipboard &amp;&amp; navigator.clipboard.writeText){            await navigator.clipboard.writeText(text);            copied = true;          }        }catch(e){ copied = false; }        out.value = text;        out.hidden = false;        if(copied){          status.textContent = &#8216;Copied u2014 paste it into an email to me.&#8217;;        } else {          status.textContent = &#8216;Copy didnu2019t run automatically u2014 select the text below and copy it manually.&#8217;;          out.focus();          out.select();        }      });      \/\/ &#8212;- Saved scenarios: SHARED across all visitors and browsers.      \/\/ The list lives on the site itself (WordPress plugin &#8220;ULC Shared      \/\/ Scenarios&#8221;, REST endpoint \/ulc\/v1\/scenarios). If that endpoint      \/\/ isn&#8217;t reachable &#8211; plugin not installed, or offline &#8211; the widget      \/\/ falls back to this browser&#8217;s localStorage so saving still works,      \/\/ and says so in the status line.      const SAVE_KEY = &#8216;ulc-scenarios-v1&#8217;;      const MAX_SAVED = 20;              \/\/ local-fallback cap (server keeps 50)      const API_PATH = &#8216;\/ulc\/v1\/scenarios&#8217;;      let memoryStore = [];      let storageOk = true;      let remote = null;                 \/\/ null = probing, true = shared, false = local-only      let apiBase = null;                \/\/ &#8216;\/wp-json&#8217; or &#8216;\/?rest_route=&#8217;      let canDelete = true;      let cache = [];                    \/\/ last list received from the server      function loadSaved(){        if(!storageOk){ return memoryStore; }        try{          const raw = window.localStorage.getItem(SAVE_KEY);          const arr = raw ? JSON.parse(raw) : [];          return Array.isArray(arr) ? arr : [];        }catch(e){ storageOk = false; return memoryStore; }      }      function persistSaved(list){        if(storageOk){          try{ window.localStorage.setItem(SAVE_KEY, JSON.stringify(list)); return true; }          catch(e){ storageOk = false; }        }        memoryStore = list;        return false;      }      function getList(){ return remote === true ? cache : loadSaved(); }      function acceptServer(data){        if(data &amp;&amp; Array.isArray(data.items)){ cache = data.items; }        if(data){ canDelete = data.can_delete !== false; }      }      \/\/ Probe the REST API once: pretty-permalink URL first, then the      \/\/ ?rest_route= form for sites without pretty permalinks.      const remoteReady = (function(){        if(typeof window.fetch !== &#8216;function&#8217;){ remote = false; return Promise.resolve(false); }        return (async function(){          const bases = [&#8216;\/wp-json&#8217;, &#8216;\/?rest_route=&#8217;];          for(let i = 0; i &lt; bases.length; i++){            try{              const r = await window.fetch(bases[i] + API_PATH, { headers: { &#8216;Accept&#8217;: &#8216;application\/json&#8217; } });              if(r.ok){                acceptServer(await r.json());                apiBase = bases[i];                remote = true;                return true;              }            }catch(e){ \/* try the next base *\/ }          }          remote = false;          return false;        })();      })();      remoteReady.then(function(){ renderSavedList(); });      \/\/ Re-pull the shared list every time the popup opens, so scenarios      \/\/ saved by other visitors show up without a page reload.      function refreshScenarios(){        if(remote !== true){ return; }        window.fetch(apiBase + API_PATH, { headers: { &#8216;Accept&#8217;: &#8216;application\/json&#8217; } })          .then(function(r){ return r.ok ? r.json() : null; })          .then(function(data){ if(data){ acceptServer(data); renderSavedList(); } })          .catch(function(){});      }      overlay.__ulcRefresh = refreshScenarios;      function snapshotState(){        return {          mode: state.mode,          level1: state.level1,          level2: state.level2,          purchase: state.purchase,          churn: state.churn,          ramp: state.ramp,          baseline: state.baseline,          comp: state.comp.slice()        };      }      function applyScenario(s){        \/\/ Mode first (it decides labels\/steps in the level tree), set via        \/\/ state directly &#8211; clicking the seg button would reset rates to defaults.        state.mode = s.mode === &#8216;cascade&#8217; ? &#8216;cascade&#8217; : &#8216;percent&#8217;;        segBtns.forEach(b =&gt; b.classList.toggle(&#8216;ulc-active&#8217;, b.dataset.mode === state.mode));        byId(&#8216;cascadeHint&#8217;).hidden = state.mode !== &#8216;cascade&#8217;;        state.level1 = Math.max(0, +s.level1 || 0);        state.level2 = Math.max(0, +s.level2 || 0);        state.purchase = Math.max(0, +s.purchase || 0);        state.churn = Math.max(0, +s.churn || 0);        state.ramp = Math.max(1, +s.ramp || 1);        state.baseline = Math.max(0, +s.baseline || 0);        const comp = Array.isArray(s.comp) ? s.comp : [];        state.comp = [];        for(let i = 0; i &lt; LEVELS; i++){ state.comp.push(Math.max(0, +comp[i] || 0)); }        byId(&#8216;level1Count&#8217;).value = state.level1;        byId(&#8216;level2Count&#8217;).value = state.level2;        byId(&#8216;avgPurchase&#8217;).value = state.purchase;        byId(&#8216;churnRate&#8217;).value = state.churn;        byId(&#8216;rampMonths&#8217;).value = state.ramp;        byId(&#8216;baselineIncome&#8217;).value = state.baseline;        buildLevelTree(); \/\/ writes state.comp into the rate inputs        updateAll();        \/\/ Jump back to the top so the reloaded numbers are visible.        const scroller = overlay.querySelector(&#8216;.ulc-page&#8217;);        if(scroller){          try{ scroller.scrollTo({ top: 0, behavior: &#8216;smooth&#8217; }); }          catch(e){ scroller.scrollTop = 0; }        }      }      function fmtSavedDate(ts){        try{ return new Date(ts).toLocaleDateString(undefined, { month:&#8217;short&#8217;, day:&#8217;numeric&#8217; }); }        catch(e){ return &#8221;; }      }      function renderSavedList(){        const list = getList();        const set = byId(&#8216;scenSet&#8217;);        byId(&#8216;savedEmpty&#8217;).hidden = list.length &gt; 0;        byId(&#8216;scenTicker&#8217;).hidden = list.length === 0;        const delBtn = canDelete          ? &#8216;&lt;button type=&#8221;button&#8221; aria-label=&#8221;Delete this saved scenario&#8221; title=&#8221;Delete&#8221;&gt;&amp;#10005;&lt;\/button&gt;&#8217;          : &#8221;;        set.innerHTML = list.map(item =&gt; `          &lt;div data-id=&#8221;${String(item.id).replace(\/[^a-z0-9]\/gi,&#8221;)}&#8221;&gt;            &lt;button type=&#8221;button&#8221; title=&#8221;Load this scenario&#8221;&gt;              &lt;span&gt;&lt;\/span&gt;              &lt;span&gt;&lt;\/span&gt;            &lt;\/button&gt;            ${delBtn}          &lt;\/div&gt;`).join(&#8221;);        \/\/ Names are user-typed: inject via textContent, never innerHTML.        Array.prototype.forEach.call(set.children, function(row, i){          const item = list[i];          row.querySelector(&#8216;.ulc-saved-name&#8217;).textContent = item.name;          row.querySelector(&#8216;.ulc-saved-meta&#8217;).textContent = (item.payout ? item.payout + &#8216; u00b7 &#8216; : &#8221;) + fmtSavedDate(item.ts);        });        updateTickerMode();      }      \/\/ Ticker behavior: chips sit in a static row while they fit; once they      \/\/ overflow the strip, the row is duplicated and scrolled continuously      \/\/ (paused on hover\/focus so chips stay clickable).      function updateTickerMode(){        const ticker = byId(&#8216;scenTicker&#8217;);        const viewport = byId(&#8216;scenViewport&#8217;);        const track = byId(&#8216;savedList&#8217;);        const set = byId(&#8216;scenSet&#8217;);        if(!ticker || !viewport || !track || !set){ return; }        const clones = track.querySelectorAll(&#8216;.ulc-scen-clone&#8217;);        Array.prototype.forEach.call(clones, function(c){ c.parentNode.removeChild(c); });        track.classList.remove(&#8216;ulc-scen-marquee&#8217;);        track.style.removeProperty(&#8216;&#8211;ulc-scen-duration&#8217;);        if(ticker.hidden){ return; }        const setW = set.scrollWidth;        const vpW = viewport.clientWidth;        if(vpW &gt; 0 &amp;&amp; setW &gt; vpW){          const clone = set.cloneNode(true);          clone.removeAttribute(&#8216;id&#8217;);          clone.classList.add(&#8216;ulc-scen-clone&#8217;);          clone.setAttribute(&#8216;aria-hidden&#8217;, &#8216;true&#8217;);          track.appendChild(clone);          const dur = Math.max(12, Math.round(setW \/ 40)); \/\/ ~40px per second          track.style.setProperty(&#8216;&#8211;ulc-scen-duration&#8217;, dur + &#8216;s&#8217;);          track.classList.add(&#8216;ulc-scen-marquee&#8217;);        }      }      window.addEventListener(&#8216;resize&#8217;, updateTickerMode);      byId(&#8216;saveBtn&#8217;).addEventListener(&#8216;click&#8217;, async function(){        const result = updateAll();        const nameInput = byId(&#8216;saveName&#8217;);        const status = byId(&#8216;saveStatus&#8217;);        status.textContent = &#8216;Savingu2026&#8217;;        const shared = (await remoteReady) &amp;&amp; remote === true;        let name = nameInput.value.trim();        if(!name){ name = &#8216;Scenario &#8216; + (getList().length + 1); }        const payload = {          name: name.slice(0, 60),          payout: fmtMoney(result.totalPayout) + &#8216;\/mo&#8217;,          state: snapshotState()        };        if(shared){          try{            const r = await window.fetch(apiBase + API_PATH, {              method: &#8216;POST&#8217;,              headers: { &#8216;Content-Type&#8217;: &#8216;application\/json&#8217;, &#8216;Accept&#8217;: &#8216;application\/json&#8217; },              body: JSON.stringify(payload)            });            if(!r.ok){ throw new Error(&#8216;HTTP &#8216; + r.status); }            acceptServer(await r.json());            renderSavedList();            nameInput.value = &#8221;;            status.textContent = &#8216;Saved u2014 everyone who opens this calculator will see it.&#8217;;            return;          }catch(e){            status.textContent = &#8216;Couldnu2019t reach the shared list u2014 saved in this browser instead.&#8217;;          }        }        const list = loadSaved();        list.unshift({          id: Date.now().toString(36) + Math.random().toString(36).slice(2, 7),          ts: Date.now(),          name: payload.name,          payout: payload.payout,          state: payload.state        });        if(list.length &gt; MAX_SAVED){ list.length = MAX_SAVED; }        const persisted = persistSaved(list);        renderSavedList();        nameInput.value = &#8221;;        if(shared){ return; } \/\/ keep the &#8220;couldn&#8217;t reach&#8221; message set above        status.textContent = persisted          ? &#8216;Saved in this browser only u2014 shared saving isnu2019t set up on this site yet.&#8217;          : &#8216;Saved for this visit only (this browser is blocking storage, e.g. private mode).&#8217;;      });      byId(&#8216;savedList&#8217;).addEventListener(&#8216;click&#8217;, async function(e){        const row = e.target.closest(&#8216;.ulc-saved-item&#8217;);        if(!row){ return; }        const id = row.getAttribute(&#8216;data-id&#8217;);        const list = getList();        let idx = -1;        for(let i = 0; i &lt; list.length; i++){ if(String(list[i].id) === id){ idx = i; break; } }        if(idx &lt; 0){ return; }        const status = byId(&#8216;saveStatus&#8217;);        if(e.target.closest(&#8216;.ulc-saved-del&#8217;)){          const removed = list[idx];          if(remote === true){            try{              const r = await window.fetch(apiBase + API_PATH + &#8216;\/&#8217; + encodeURIComponent(id), {                method: &#8216;DELETE&#8217;,                headers: { &#8216;Accept&#8217;: &#8216;application\/json&#8217; }              });              if(!r.ok){ throw new Error(&#8216;HTTP &#8216; + r.status); }              acceptServer(await r.json());              renderSavedList();              status.textContent = &#8216;Deleted u201c&#8217; + removed.name + &#8216;u201d for everyone.&#8217;;            }catch(err){              status.textContent = &#8216;Couldnu2019t delete from the shared list u2014 try again in a moment.&#8217;;            }            return;          }          const local = loadSaved();          for(let i = 0; i &lt; local.length; i++){            if(String(local[i].id) === id){ local.splice(i, 1); break; }          }          persistSaved(local);          renderSavedList();          status.textContent = &#8216;Deleted u201c&#8217; + removed.name + &#8216;u201d.&#8217;;          return;        }        if(e.target.closest(&#8216;.ulc-saved-load&#8217;)){          applyScenario(list[idx].state || {});          status.textContent = &#8216;Loaded u201c&#8217; + list[idx].name + &#8216;u201d u2014 the numbers above now show that scenario.&#8217;;        }      });      buildLevelTree();      buildChart();      updateAll();      renderSavedList();    }  });})();[\/tcb-script]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Private Partnership Offer ADD ANY EXTRA BENEFITS OR DESCRIPTION HERE Access Calculator Here Lifetime Referral Calculator \u2715 Referral Compensation Modeling Lifetime Referral Calculator Plug in numbers for a five-level referral plan and see what it pays out \u2014 level by level, and month by month as the network grows. Prefilled with a starter example: heavy [&hellip;]<\/p>\n","protected":false},"author":42,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":"","tve_updated_post":"","tve_custom_css":"","tve_user_custom_css":"","tve_globals":{},"tcb2_ready":1,"tcb_editor_enabled":1,"tve_landing_page":"bd86f3fc67210fed5b2794ad4a56d3a9","_tve_header":"0","_tve_footer":"0"},"folder":[],"class_list":["post-29770","page","type-page","status-publish","hentry","post-wrapper","thrv_wrapper"],"acf":[],"_links":{"self":[{"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/pages\/29770","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/comments?post=29770"}],"version-history":[{"count":32,"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/pages\/29770\/revisions"}],"predecessor-version":[{"id":30024,"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/pages\/29770\/revisions\/30024"}],"wp:attachment":[{"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/media?parent=29770"}],"wp:term":[{"taxonomy":"folder","embeddable":true,"href":"https:\/\/thegiveawayguy.biz\/v\/wp\/v2\/folder?post=29770"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}