
        <!DOCTYPE html>
        <html lang="en">
          <head>
            <meta charset="utf-8">
            <base href="/">
            <title></title>
            <link rel="icon" href="data:,">
            
            <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="description" content="Drag-and-drop funnel builder with native integrations for Konnektive, Limelight, Checkout Champ, Sticky.io, ResponseCRM, Sublytics, Shopify, WooCommerce, Phoenix Technologies and Admoji. 14-day free trial — launch DTC funnels in minutes."/>
<meta name="keywords" content="funnel builder, drag and drop funnel builder, Konnektive, Limelight, Checkout Champ, Sticky.io, ResponseCRM, Sublytics, FNNLDB, Shopify, WooCommerce, Phoenix Technologies, Admoji, DTC funnel builder, e-commerce funnel builder, subscription funnel, ClickFunnels alternative"/>
<meta name="author" content="SubscribeFunnels"/>
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1"/>
<meta name="theme-color" content="#6D4BEF"/>
<link rel="canonical" href="https://subscribefunnels.com/"/>
<meta property="og:type" content="website"/>
<meta property="og:site_name" content="SubscribeFunnels"/>
<meta property="og:title" content="SubscribeFunnels — Funnel Builder for Konnektive, Limelight, Checkout Champ, Sticky.io & Shopify"/>
<meta property="og:description" content="Drag-and-drop funnel builder with native integrations for Konnektive, Limelight, Checkout Champ, Sticky.io, Shopify, Phoenix Technologies, Admoji and more. 14-day free trial."/>
<meta property="og:url" content="https://subscribefunnels.com/"/>
<meta property="og:image" content="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/og-img.png"/>
<meta property="og:image:width" content="1200"/>
<meta property="og:image:height" content="630"/>
<meta property="og:locale" content="en_US"/>
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:site" content="@subscribefunnels"/>
<meta name="twitter:title" content="SubscribeFunnels — Funnel Builder for Konnektive, Limelight, Checkout Champ, Sticky.io & Shopify"/>
<meta name="twitter:description" content="Drag-and-drop funnel builder with native integrations for the DTC CRMs and platforms you already run — Konnektive, Limelight, Checkout Champ, Sticky.io, Shopify, Phoenix Technologies, Admoji."/>
<meta name="twitter:image" content="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/og-img.png"/>
<link rel="icon" type="image/png" href="https://cdn.subscribefunnels.com/ac328728-1d0e-4ac1-998a-4af798c760c0/subscribefunnels-redesign/assets/img/logo-white.png"/>
<link rel="apple-touch-icon" href="https://cdn.subscribefunnels.com/ac328728-1d0e-4ac1-998a-4af798c760c0/subscribefunnels-redesign/assets/img/logo-white.png"/>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"/>
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet"/>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="https://cdn.subscribefunnels.com/ac328728-1d0e-4ac1-998a-4af798c760c0/subscribefunnels-redesign/assets/css/site.css"/>
            <meta name="description" content=""><meta name="keywords" content="">
            
            
            <style>
                .sf-submit-loader-container {display: none;position: fixed;width: 100vw;height: 100vh;top: 0;left: 0;background: rgba(0, 0, 0, 0.2); z-index: 1000}.sf-submit-loader-content {margin: auto;text-align: center;}.sf-submit-loader-text {font-size: 26px;margin-bottom: 6px;color: rgba(0,0,0,0.52);letter-spacing: 1.2px;}.lds-dual-ring {display: inline-block;width: 64px;height: 64px;}.lds-dual-ring:after {content: " ";display: block;width: 46px;height: 46px;margin: 1px;border-radius: 50%;border: 5px solid #fff;border-color: #fff transparent #fff transparent;animation: lds-dual-ring 1.2s linear infinite;}@keyframes lds-dual-ring {0% {  transform: rotate(0deg);}100% {  transform: rotate(360deg);}}
                .sq-input {height: 40px;box-sizing: border-box;border: 1px solid rgba(0,0,0,0.4);background-color: white;display: inline-block;-webkit-transition: border-color .1s ease-in-out;   -moz-transition: border-color .1s ease-in-out; -ms-transition: border-color .1s ease-in-out; transition: border-color .1s ease-in-out;}.sq-input--focus {border: 1px solid rgb(57, 142, 231);}.sq-input--error {border: 1px solid #E02F2F;}
                
                #ik0lp{background:linear-gradient(145deg, rgb(255, 91, 117) 0%, rgb(109, 75, 239) 51%, rgb(255, 91, 117) 100%) 0% 0% / 200%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;display:inline-block;}#iw9gm{color:#8C95AD;font-size:.95rem;}#im958{color:var(--sf-accent);}#i68ou{color:var(--sf-accent);}#iyihvg{letter-spacing:.16em;font-size:.78rem;color:var(--sf-text-muted);font-weight:600;}#i83cye{font-weight:700;}#iw9efj{font-size:.92rem;max-width:56rem;margin-inline:auto;}#i2tm9r{color:var(--sf-accent);}#ihlh7s{color:var(--sf-accent);}#ic2rty{color:var(--sf-primary);font-weight:600;}.mock-browser__body{padding:0 0 0 0;min-height:315px;background-repeat:repeat;background-position:left top;background-attachment:scroll;background-size:cover;background-image:url(https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/background-mock.png);}.pricing-card.is-featured{background-color:var(--sf-ink) !important;}.mock-cursor{background:#FF5B75;}.bi.bi-check2-circle.me-2{color:var(--sf-accent);}
            </style>
            
              
            
            
            


          </head>
          <body>
            
            
            
            
            <script>
                console.log('Rendering project', {"accountId":"016e2fea-33a6-482a-9c70-a9a529d0e5f5","projectId":"ac328728-1d0e-4ac1-998a-4af798c760c0"});
                
    
    if (!Array.from) {
      Array.from = (function () {
        var toStr = Object.prototype.toString;
        var isCallable = function (fn) {
          return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
        };
        var toInteger = function (value) {
          var number = Number(value);
          if (isNaN(number)) { return 0; }
          if (number === 0 || !isFinite(number)) { return number; }
          return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
        };
        var maxSafeInteger = Math.pow(2, 53) - 1;
        var toLength = function (value) {
          var len = toInteger(value);
          return Math.min(Math.max(len, 0), maxSafeInteger);
        };
    
        return function from(arrayLike/*, mapFn, thisArg */) {
          var C = this;
          var items = Object(arrayLike);
          if (arrayLike == null) {
            throw new TypeError('Array.from requires an array-like object - not null or undefined');
          }
          var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
          var T;
          if (typeof mapFn !== 'undefined') {
            if (!isCallable(mapFn)) {
              throw new TypeError('Array.from: when provided, the second argument must be a function');
            }
    
            if (arguments.length > 2) {
              T = arguments[2];
            }
          }
          var len = toLength(items.length);
          var A = isCallable(C) ? Object(new C(len)) : new Array(len);
          var k = 0;
          var kValue;
          while (k < len) {
            kValue = items[k];
            if (mapFn) {
              A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
            } else {
              A[k] = kValue;
            }
            k += 1;
          }
          A.length = len;
          return A;
        };
      }());
    }

    
    if (window.NodeList && !NodeList.prototype.forEach) {
        NodeList.prototype.forEach = function (callback, thisArg) {
            thisArg = thisArg || window;
            for (var i = 0; i < this.length; i++) {
                callback.call(thisArg, this[i], i, this);
            }
        };
    }

    
    if (!Array.prototype.includes) {
      Object.defineProperty(Array.prototype, "includes", {
        enumerable: false,
        value: function(obj) {
            for (var i = 0; i < this.length; i++) {
                if (this[i] == obj) {
                    return true;
                }
            }
            
            return false;
          }
      });
    }


                
    function resolveGeolocation() {
    sfGeolocation = (function () {
        const callbacks = [];
        let countryData = undefined;
        const ip = resolvedIp;
        countryData = resolvedCountryData;
        (callbacks || []).forEach((c) => c(ip, countryData));
        return {
            on: (callback) => {
                if (ip && countryData) {
                    callback(ip, countryData);
                }
                else {
                    callbacks.push(callback);
                }
            },
        };
    })();
}
    var resolvedIp = '66.102.9.104';
    var resolvedCountryData = { country_name: 'United States', country_code: 'US' };
    var sfGeolocation;
    resolveGeolocation();

            </script>
            <title>SubscribeFunnels — Funnel Builder for Konnektive, Limelight, Checkout Champ, Sticky.io & Shopify</title><!-- Open Graph --><!-- Twitter / X --><!-- Favicon — TODO: REPLACE with a real .ico / .svg favicon --><!-- Bootstrap 5 --><!-- Inter as a sensible placeholder; swap fonts in site.css :root --><!-- Structured data: Organization + SoftwareApplication --><script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@graph": [{
        "@type": "Organization",
        "@id": "https://subscribefunnels.com/#organization",
        "name": "SubscribeFunnels",
        "url": "https://subscribefunnels.com/",
        "logo": "https://subscribefunnels.com/assets/img/logo-white.png",
        "description": "Drag-and-drop funnel builder for DTC e-commerce with native integrations for Konnektive, Limelight, Checkout Champ, Sticky.io, ResponseCRM, Sublytics, FNNLDB, Shopify, WooCommerce, Phoenix Technologies and Admoji.",
        "sameAs": []
      },
      {
        "@type": "WebSite",
        "@id": "https://subscribefunnels.com/#website",
        "url": "https://subscribefunnels.com/",
        "name": "SubscribeFunnels",
        "publisher": {
          "@id": "https://subscribefunnels.com/#organization"
        },
        "inLanguage": "en-US"
      },
      {
        "@type": "SoftwareApplication",
        "name": "SubscribeFunnels",
        "applicationCategory": "BusinessApplication",
        "applicationSubCategory": "Sales Funnel Builder",
        "operatingSystem": "Web",
        "url": "https://subscribefunnels.com/",
        "description": "Build high-converting DTC funnels with drag-and-drop simplicity and native integrations for Konnektive, Limelight, Checkout Champ, Sticky.io, Shopify, Phoenix Technologies and Admoji.",
        "offers": {
          "@type": "AggregateOffer",
          "priceCurrency": "USD",
          "lowPrice": "77",
          "highPrice": "497",
          "offerCount": "3"
        }
      }
    ]
  }
</script><!-- ============================ NAV ============================ --><nav data-scroll-tone="true" aria-label="Primary" class="sf-nav is-dark navbar navbar-expand-lg fixed-top"><div class="container"><a href="index" aria-label="SubscribeFunnels home" class="navbar-brand"><img src="https://cdn.subscribefunnels.com/ac328728-1d0e-4ac1-998a-4af798c760c0/subscribefunnels-redesign/assets/img/logo-white.png" alt="SubscribeFunnels" width="100" height="30" class="brand-logo"/></a><button type="button" data-bs-toggle="offcanvas" data-bs-target="#sfNav" aria-controls="sfNav" aria-label="Open menu" class="navbar-toggler text-white border-0"><i data-gjs-type="icon" class="bi bi-list fs-3"></i></button><div tabindex="-1" id="sfNav" aria-labelledby="sfNavLabel" class="offcanvas offcanvas-end bg-ink text-white"><div class="offcanvas-header"><h5 id="sfNavLabel" class="offcanvas-title">Menu</h5><button type="button" data-bs-dismiss="offcanvas" aria-label="Close" class="btn-close btn-close-white"></button></div><div class="offcanvas-body"><ul class="navbar-nav ms-auto align-items-lg-center gap-lg-3"><li class="nav-item"><a href="features" class="nav-link">Features</a></li><li class="nav-item"><a href="#integrations" class="nav-link">Integrations</a></li><li class="nav-item"><a href="pricing" class="nav-link">Pricing</a></li><li class="nav-item"><a href="about" class="nav-link">About</a></li><li class="nav-item"><a href="https://sites.subscribefunnels.com/login" aria-label="Login" class="nav-link">Login</a></li><li class="nav-item ms-lg-2 mt-3 mt-lg-0"><a href="pricing" role="button" class="btn btn-cta">Start free trial</a></li></ul></div></div></div></nav><!-- ============================ HERO ============================ --><header class="hero"><div class="container"><div class="row align-items-center g-5"><div class="col-lg-6 reveal"><span class="eyebrow"><i draggable="true" data-highlightable="1" id="iqgct" data-gjs-type="icon" class="bi bi-lightning-charge-fill"></i> Built for DTC operators
        </span><h1 class="h-display mt-3">Launch funnels in <span id="ik0lp">10 minutes</span>, not 10 days.</h1><p class="lead mt-3">The drag-and-drop funnel builder that natively integrates with the CRMs and platforms you already run —  Sticky.io, Checkout Champ, Admoji, Sublytics, Shopify, Phoenix Technologies, and more. No developers required.</p><div class="d-flex flex-wrap gap-2 mt-4"><a href="pricing" class="btn btn-cta btn-lg">
            Start 14-day free trial <i data-gjs-type="icon" class="bi bi-arrow-right ms-1"></i></a><a href="#how" class="btn btn-ghost btn-lg text-white"><i data-gjs-type="icon" class="bi bi-play-circle me-1"></i> See it in action
          </a></div><p id="iw9gm" class="mt-3 mb-0"><i id="im958" data-gjs-type="icon" class="bi bi-check2-circle me-1"></i> No credit card required  · 
          <i id="i68ou" data-gjs-type="icon" class="bi bi-check2-circle me-1"></i> First project free, forever
        </p></div><div class="col-lg-6 reveal"><div class="position-relative"><!-- TODO: REPLACE this stylized mockup with a real product screenshot or screencap video --><div class="mock-browser"><div class="mock-browser__bar"><span class="mock-browser__dot is-red"></span><span class="mock-browser__dot is-yellow"></span><span class="mock-browser__dot is-green"></span><span class="mock-browser__url">subscribefunnels.com / builder</span></div><div class="mock-browser__body"><!--
  <div aria-hidden="true" class="mock-browser__rail">
    <span class="is-active"></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
  </div>
  <div aria-hidden="true" class="mock-browser__canvas">
    <div class="mock-block is-hero"></div>
    <div class="mock-block is-row">
      <div class="mock-block is-card"></div>
      <div class="mock-block is-card"></div>
      <div class="mock-block is-card"></div>
    </div>
    <div class="mock-block is-cta"></div>
  </div>
  <div aria-hidden="true" class="mock-browser__panel">
    <span class="is-mid"></span>
    <span class="is-wide"></span>
    <span class="is-short"></span>
    <div>
      <span class="swatch is-1"></span>
      <span class="swatch is-2"></span>
      <span class="swatch is-3"></span>
      <span class="swatch is-4"></span>
    </div>
    <span class="is-wide"></span>
    <span class="is-mid"></span>
  </div>--></div></div><div aria-hidden="true" class="mock-cursor"></div></div></div></div></div></header><!-- ============================ INTEGRATIONS BAR ============================ --><!-- TODO: REPLACE placeholder logos below with real integration logos. --><section id="integrations" class="section-sm bg-paper-soft section-pattern pattern-mesh"><div class="container-fluid px-0"><div class="container text-center mb-4"><p id="iyihvg" class="text-uppercase mb-2">
        Plays nice with the stack you already pay for
      </p><h2 id="i83cye" class="h5 mb-2">Native integrations for every major DTC platform</h2><p id="iw9efj" class="text-muted-2 mb-0">
        Konnektive · Limelight · Checkout Champ · Sticky.io · ResponseCRM · Sublytics · FNNLDB · Shopify · WooCommerce · Phoenix Technologies · Admoji
      </p></div><div aria-label="Integration partners" class="sf-logos reveal"><div class="marquee"><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/vrio.png" alt="Brand 03 placeholder" loading="lazy" id="iv8r7z"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/clickfunnels-logo.png" alt="Brand 04 placeholder" loading="lazy" id="ix700v"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/29next-logo.png" alt="Brand 05 placeholder" loading="lazy" id="i9rb8f"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/clickbank.png" alt="Brand 06 placeholder" loading="lazy" id="i08eod"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/stickyio.png" alt="Brand 07 placeholder" loading="lazy" id="iowssl"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/shopify.png" alt="Brand 08 placeholder" loading="lazy" id="iychy3"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/checkoutchamp.png" alt="Brand 09 placeholder" loading="lazy" id="ipjqua"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/admoji.png" alt="Brand 10 placeholder" loading="lazy" id="ijeqjc"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/vrio.png" alt="Brand 03 placeholder" loading="lazy" id="iv8r7z-2"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/clickfunnels-logo.png" alt="Brand 04 placeholder" loading="lazy" id="ix700v-2"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/29next-logo.png" alt="Brand 05 placeholder" loading="lazy" id="i9rb8f-2"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/clickbank.png" alt="Brand 06 placeholder" loading="lazy" id="i08eod-2"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/stickyio.png" alt="Brand 07 placeholder" loading="lazy" id="iowssl-2"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/shopify.png" alt="Brand 08 placeholder" loading="lazy" id="iychy3-2"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/checkoutchamp.png" alt="Brand 09 placeholder" loading="lazy" id="ipjqua-2"/></div><div class="swiper-slide"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/admoji.png" alt="Brand 10 placeholder" loading="lazy" id="ijeqjc-2"/></div></div></div></div></section><!-- ============================ VALUE PROPS ============================ --><section class="section section-pattern pattern-dots glow-tr"><div class="container"><div class="row text-center mb-5 reveal"><div class="col-lg-8 mx-auto"><span class="eyebrow">Why teams switch</span><h2 class="h-section mt-3">Three reasons SubscribeFunnels wins.</h2><p class="lead mt-3">Most funnel builders treat your CRM as an afterthought. We started there.</p></div></div><div class="row g-4"><div class="col-md-4 reveal"><div class="value-card"><div class="icon-square"><i data-gjs-type="icon" class="bi bi-stopwatch-fill"></i></div><h3 class="h5 mb-2">Ship in minutes</h3><p class="text-muted-2 mb-0">Drag, drop, edit copy, hit publish. A real funnel up and converting between meetings.</p></div></div><div class="col-md-4 reveal"><div class="value-card"><div class="icon-square"><i data-gjs-type="icon" class="bi bi-plug-fill"></i></div><h3 class="h5 mb-2">10+ DTC platforms out of the box</h3><p class="text-muted-2 mb-0">Native integrations for Sticky.io, Checkout Champ, Admoji, Vrio, 29Next, Shopify, Phoenix Technologies and more — no fragile webhooks, no glue code.</p></div></div><div class="col-md-4 reveal"><div class="value-card"><div class="icon-square"><i data-gjs-type="icon" class="bi bi-code-slash"></i></div><h3 class="h5 mb-2">No code — but code if you want</h3><p class="text-muted-2 mb-0">A clean WYSIWYG editor for your marketer. A VS Code clone for your developer. As simple or advanced as you need it to be.</p></div></div></div></div></section><!-- ============================ HOW IT WORKS ============================ --><section id="how" class="section bg-paper-soft section-pattern pattern-grid glow-bl"><div class="container"><div class="row text-center mb-5 reveal"><div class="col-lg-8 mx-auto"><span class="eyebrow">How it works</span><h2 class="h-section mt-3">From template to live funnel in three steps.</h2></div></div><div class="row g-4"><div class="col-md-4 reveal"><div class="step-card"><span class="step-num">1</span><h3 class="h5 mb-2">Pick a template</h3><p class="text-muted-2 mb-0">Choose a battle-tested layout from the library, or import a design file from your designer.</p></div></div><div class="col-md-4 reveal"><div class="step-card"><span class="step-num">2</span><h3 class="h5 mb-2">Drag, drop, edit</h3><p class="text-muted-2 mb-0">Swap copy, images, and offers in the WYSIWYG editor. Pixel-control without touching CSS.</p></div></div><div class="col-md-4 reveal"><div class="step-card"><span class="step-num">3</span><h3 class="h5 mb-2">Connect CRM & ship</h3><p class="text-muted-2 mb-0">Two-click connect to Sticky.io, Admoji, Checkout Champ, and others... Publish and start taking orders.</p></div></div></div></div></section><!-- ============================ FEATURE TABS ============================ --><section class="section section-pattern pattern-mesh glow-br"><div class="container"><div class="row text-center mb-5 reveal"><div class="col-lg-8 mx-auto"><span class="eyebrow">A closer look</span><h2 class="h-section mt-3">Everything your funnel team needs, in one place.</h2></div></div><ul role="tablist" class="nav sf-tabs justify-content-center flex-wrap mb-4 reveal"><li class="nav-item"><button data-bs-toggle="tab" data-bs-target="#tab-editor" type="button" role="tab" class="nav-link active"><i data-gjs-type="icon" class="bi bi-cursor-fill"></i> Editor
        </button></li><li class="nav-item"><button data-bs-toggle="tab" data-bs-target="#tab-templates" type="button" role="tab" class="nav-link"><i data-gjs-type="icon" class="bi bi-layout-text-window"></i> Templates
        </button></li><li class="nav-item"><button data-bs-toggle="tab" data-bs-target="#tab-crm" type="button" role="tab" class="nav-link"><i data-gjs-type="icon" class="bi bi-diagram-3-fill"></i> CRM Sync
        </button></li><li class="nav-item"><button data-bs-toggle="tab" data-bs-target="#tab-plugins" type="button" role="tab" class="nav-link"><i data-gjs-type="icon" class="bi bi-puzzle-fill"></i> Plugins
        </button></li></ul><div class="tab-content reveal"><div id="tab-editor" role="tabpanel" class="tab-pane fade show active"><div class="tab-pane-card"><div class="row g-4 align-items-center"><div id="idmm3t" class="col-md-6"><h3 class="h4">As Simple or Advanced as you want to make it.</h3><p class="text-muted-2">Click anything, edit it. Reorder sections with a drag. Tweak layer styles inline without ever opening dev tools ... OR ... Go all out in the HTML editor changing external files and more.</p><ul class="list-unstyled mt-3"><li class="mb-2"><i id="i2tm9r" data-gjs-type="icon" class="bi bi-check2-circle me-2"></i>Inline rich-text editing
                </li><li class="mb-2"><i id="ihlh7s" data-gjs-type="icon" class="bi bi-check2-circle me-2"></i>Drag-reorder any section
                </li><li class="mb-2"><i draggable="true" data-highlightable="1" id="iwy0nz" data-gjs-type="icon" class="bi bi-check2-circle me-2"></i>Live HTML escape hatch for power users
                </li></ul></div><div id="ioj78j" class="col-md-6"><div class="feature-block"><!--

--><div id="carouselExampleSlidesOnly" data-bs-ride="carousel" class="carousel slide carousel-fade"><div class="carousel-inner rounded-3"><div data-bs-interval="2000" class="carousel-item active"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/sf-canvas.png" alt="First slide" class="d-block w-100"/></div><div data-bs-interval="2000" class="carousel-item"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/sf-code.png" alt="Second slide" class="d-block w-100"/></div></div></div><!--

--></div></div></div></div></div><div id="tab-templates" role="tabpanel" class="tab-pane fade"><div class="tab-pane-card"><div class="row g-4 align-items-center"><div class="col-md-6"><h3 class="h4">Battle-tested templates for every offer type.</h3><p class="text-muted-2">Start from a proven layout — VSL, tripwire, subscription, free-plus-shipping, upsell sequence. Or import your designer's file directly.</p></div><div id="iqxlpj" class="col-md-6"><div class="feature-art"><!--

--><div id="carouselExampleSlidesOnly-2" data-bs-ride="carousel" class="carousel slide carousel-fade"><div class="carousel-inner rounded-3"><div data-bs-interval="2000" class="carousel-item active"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/sf-templates.png" alt="First slide" class="d-block w-100"/></div></div></div><!--

--></div></div></div></div></div><div id="tab-crm" role="tabpanel" class="tab-pane fade"><div class="tab-pane-card"><div class="row g-4 align-items-center"><div class="col-md-6"><h3 class="h4">Native CRM sync — not a fragile webhook.</h3><p class="text-muted-2">Two-click connect to Konnektive, Limelight, Checkout Champ, Sticky.io, ResponseCRM, Sublytics, FNNLDB. Order data flows on day one.</p></div><div class="col-md-6"><div class="feature-art"><div id="carouselExampleSlidesOnly-2-2" data-bs-ride="carousel" class="carousel slide carousel-fade"><div class="carousel-inner rounded-3"><div data-bs-interval="2000" class="carousel-item active"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/sf-crm-circle.png" alt="First slide" class="d-block w-100"/></div></div></div></div></div></div></div></div><div id="tab-plugins" role="tabpanel" class="tab-pane fade"><div class="tab-pane-card"><div class="row g-4 align-items-center"><div class="col-md-6"><h3 class="h4">A growing plugin library — plus an open API.</h3><p class="text-muted-2">New plugins ship weekly. Build your own against our open API when you need something custom — without forking the builder.</p></div><div class="col-md-6"><div class="feature-art"><div id="carouselExampleSlidesOnly-2-3" data-bs-ride="carousel" class="carousel slide carousel-fade"><div class="carousel-inner rounded-3"><div data-bs-interval="2000" class="carousel-item active"><img src="https://s3.amazonaws.com/subscribe-funnels-production/assets/ac328728-1d0e-4ac1-998a-4af798c760c0/sf-plugins.png" alt="First slide" class="d-block w-100"/></div></div></div></div></div></div></div></div></div><div class="text-center mt-4"><a href="features" class="btn btn-ink">Tour every feature <i data-gjs-type="icon" class="bi bi-arrow-right ms-1"></i></a></div></div></section><!-- ============================ TESTIMONIALS ============================ --><section class="section bg-paper-soft section-pattern pattern-dots glow-tl"><div class="container"><div class="row text-center mb-5 reveal"><div class="col-lg-8 mx-auto"><span class="eyebrow">From the desk of</span><h2 class="h-section mt-3">Operators who got their nights back.</h2></div></div><div class="row g-4"><div class="col-md-4 reveal"><div class="quote-card"><div aria-label="5 out of 5 stars" class="stars">★★★★★</div><blockquote>"The template library plus the Konnektive integration cut what used to be a two-week funnel launch down to an afternoon."</blockquote><div class="person"><span class="avatar">KK</span><div><strong>K. Kniery</strong><span>Kniery Marketing</span></div></div></div></div><div class="col-md-4 reveal"><div class="quote-card"><div aria-label="5 out of 5 stars" class="stars">★★★★★</div><blockquote>"I'm not a developer and I built our entire subscription funnel in a weekend. The WYSIWYG editor just gets out of the way."</blockquote><div class="person"><span class="avatar">CT</span><div><strong>C. Thompson</strong><span>Coqulous</span></div></div></div></div><div class="col-md-4 reveal"><div class="quote-card"><div aria-label="5 out of 5 stars" class="stars">★★★★★</div><blockquote>"We tried ClickFunnels and Leadpages. SubscribeFunnels was the only one with deep CRM integrations we didn't have to babysit."</blockquote><div class="person"><span class="avatar">PI</span><div><strong>P. Ingram</strong><span>ISP Consulting</span></div></div></div></div></div></div></section><!-- ============================ PRICING TEASER ============================ --><section id="pricing" class="section section-pattern pattern-spotlight"><div class="container"><div class="row text-center mb-5 reveal"><div class="col-lg-8 mx-auto"><span class="eyebrow">Pricing</span><h2 class="h-section mt-3">Pick a plan. Cancel anytime.</h2><p class="lead mt-3">14-day free trial on every plan. First project free, forever.</p></div></div><div class="row g-4 align-items-stretch"><div class="col-lg-4 reveal"><div class="pricing-card"><div class="plan-name">Basic</div><div class="plan-tag">For solo operators and one-product brands.</div><div class="plan-price">$97<small>/mo</small></div><ul><li>25 projects</li><li>25,000 monthly visitors</li><li>Unlimited plugins</li><li>24-hour support</li></ul><a href="https://sites.subscribefunnels.com/signup?planSelected=basic" class="btn btn-ink w-100 mt-auto">See plan details</a></div></div><div class="col-lg-4 reveal"><div class="pricing-card is-featured"><span class="badge-pop">Most popular</span><div class="plan-name">Premium</div><div class="plan-tag">For growing brands running multiple offers.</div><div class="plan-price">$297<small>/mo</small></div><ul><li>100 projects</li><li>100,000 monthly visitors</li><li>Unlimited plugins</li><li>Priority 24-hour support</li></ul><a href="https://sites.subscribefunnels.com/signup?planSelected=premium" class="btn btn-cta w-100 mt-auto">Start 14-day trial</a></div></div><div class="col-lg-4 reveal"><div class="pricing-card"><div class="plan-name">Business</div><div class="plan-tag">For agencies and high-volume operators.</div><div class="plan-price">$497<small>/mo</small></div><ul><li>Unlimited projects</li><li>Unlimited monthly visitors</li><li>Unlimited plugins</li><li>Dedicated support contact</li></ul><a href="https://sites.subscribefunnels.com/signup?planSelected=business" class="btn btn-ink w-100 mt-auto">See plan details</a></div></div></div><p class="text-center mt-4"><a href="pricing" id="ic2rty" class="text-decoration-none">
        Compare all plans <i data-gjs-type="icon" class="bi bi-arrow-right"></i></a></p></div></section><!-- ============================ CTA BAND ============================ --><section class="section-sm"><div class="container"><div class="cta-band text-center reveal"><span class="eyebrow"><i data-gjs-type="icon" class="bi bi-lightning-charge-fill"></i> Ready when you are
      </span><h2 class="h-section mt-3 mb-2">Your next funnel could be live before lunch.</h2><p class="lead mb-4">Start a 14-day free trial. No credit card. First project free, forever.</p><a href="#pricing" class="btn btn-cta btn-lg">Start free trial <i data-gjs-type="icon" class="bi bi-arrow-right ms-1"></i></a></div></div></section><!-- ============================ FOOTER ============================ --><footer class="site-footer"><div class="container"><div class="row g-4"><div class="col-lg-4"><a href="index" aria-label="SubscribeFunnels home" class="d-inline-block mb-3"><img src="https://cdn.subscribefunnels.com/ac328728-1d0e-4ac1-998a-4af798c760c0/subscribefunnels-redesign/assets/img/logo-white.png" alt="SubscribeFunnels" width="107" height="32" class="brand-logo"/></a><p id="iqlfyi">The drag-and-drop funnel builder for DTC operators on the CRMs you already pay for.</p></div><div class="col-6 col-lg-2"><h6>Product</h6><ul class="list-unstyled"><li class="mb-2"><a href="features" id="in8afa">Features</a></li><li class="mb-2"><a href="pricing" id="i6r7cj">Pricing</a></li><li class="mb-2"><a href="index#integrations" id="ihuev3">Integrations</a></li></ul></div><div class="col-6 col-lg-2"><h6>Integrations</h6><ul class="list-unstyled"><li class="mb-2"><a href="sticky-io-funnel-builder.html">Sticky.io</a></li><li class="mb-2"><a href="admoji-funnel-builder.html">Admoji</a></li><li class="mb-2"><a href="#" id="ipctcd">Konnektive</a></li><li class="mb-2"><a href="#" id="i8smal">Limelight</a></li><li class="mb-2"><a href="checkout-champ-funnel-builder.html" id="icdso5">Checkout Champ</a></li><li class="mb-2"><a href="phoenix-technologies-funnel-builder.html">Phoenix Technologies</a></li></ul></div><div class="col-6 col-lg-2"><h6>Company</h6><ul class="list-unstyled"><li class="mb-2"><a href="about" id="impg1f">About</a></li><li class="mb-2"><a href="about#contact" id="i713gb">Contact</a></li><li class="mb-2"><a href="affiliates.subscribefunnels.com" id="iyrofj">Affiliates</a></li><li class="mb-2"><a href="subscribe.zendesk.com" id="iol45g">Help Center</a></li></ul></div><div class="col-6 col-lg-2"><h6>Legal</h6><ul class="list-unstyled"><li class="mb-2"><a href="#" id="iz8b46">Terms</a></li><li class="mb-2"><a href="#" id="igy77f">Privacy</a></li><li class="mb-2"><a href="#" id="ih149u">Disclaimer</a></li></ul></div></div><div class="brand-row"><span>© <span data-year="">2026</span> SubscribeFunnels. All rights reserved.</span><div aria-label="Social media" class="socials"><a href="#" aria-label="Twitter"><i data-gjs-type="icon" class="bi bi-twitter-x"></i></a><a href="#" aria-label="LinkedIn"><i data-gjs-type="icon" class="bi bi-linkedin"></i></a><a href="#" aria-label="YouTube"><i data-gjs-type="icon" class="bi bi-youtube"></i></a><a href="#" aria-label="Facebook"><i data-gjs-type="icon" class="bi bi-facebook"></i></a></div></div></div></footer><script src="https://code.jquery.com/jquery-3.4.1.min.js"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script><script src="https://cdn.subscribefunnels.com/ac328728-1d0e-4ac1-998a-4af798c760c0/subscribefunnels-redesign/assets/js/site.js"></script>
            
            <div class="sf-submit-loader-container" style="background: rgba(0, 0, 0, .5);">
    <div class="sf-submit-loader-content">
        
        <div class="sf-submit-loader-wrapper"><div class="lds-dual-ring"></div></div>
    </div>
</div>
            <script>
                
    var inProgress = false;
    var PAAY_DATA = {};

    // Payment provider registry - allows async token creation before form submission
    var paymentProviders = [];

    function registerPaymentProvider(provider) {
    paymentProviders.push(provider);
}
    function createHiddenInput(name, value) {
    const input = document.createElement('input');
    input.setAttribute('name', name);
    input.setAttribute('value', value);
    input.setAttribute('type', 'hidden');
    input.setAttribute('data-injected', 'true');
    return input;
}

    // Form persistence configuration
    var SENSITIVE_FIELD_PATTERNS = [
        'card', 'cvv', 'cvc', 'exp', 'pin', 'password',
        'token', 'ssn', 'tax', 'account', 'routing',
        'stripe', 'paypal', 'bank', 'credit'
    ];

    function debounce(func, delay) {
    let timeoutId;
    return function (...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func.apply(this, args), delay);
    };
}
    function shouldPersistField(fieldName) {
    if (!fieldName)
        return false;
    const lowerName = fieldName.toLowerCase();
    // Check against sensitive patterns
    for (const pattern of SENSITIVE_FIELD_PATTERNS) {
        if (lowerName.includes(pattern)) {
            return false;
        }
    }
    // Skip hidden fields and submit buttons
    return true;
}
    function getFormStorageKey(form) {
    const dataset = form.dataset || {};
    const formId = form.id || 'default';
    const campaignId = dataset.gjsSfCampaignId || 'unknown';
    const funnelId = dataset.gjsSfFunnelId || 'unknown';
    return `sf_form_${funnelId}_${campaignId}_${formId}`;
}
    function persistFormData(form) {
    try {
        // Check if localStorage is available via global context
        const storage = (typeof localStorage !== 'undefined') ? localStorage : null;
        if (!storage)
            return;
        const storageKey = getFormStorageKey(form);
        const formData = {};
        // Collect form data
        Array.from(form.elements || []).forEach((element) => {
            if (!element.name || !shouldPersistField(element.name)) {
                return;
            }
            // Skip unchecked radio buttons
            if (element.type === 'radio' && !element.checked) {
                return;
            }
            // Skip hidden fields and submit buttons
            if (element.type === 'hidden' || element.type === 'submit') {
                return;
            }
            // Skip dynamically injected fields
            if (element.hasAttribute('data-injected')) {
                return;
            }
            // Checkboxes with same name: store as array of checked values
            if (element.type === 'checkbox') {
                if (!Array.isArray(formData[element.name])) {
                    formData[element.name] = [];
                }
                if (element.checked) {
                    formData[element.name].push(element.value);
                }
                return;
            }
            formData[element.name] = element.value;
        });
        // Add timestamp for expiration tracking
        formData['_timestamp'] = Date.now();
        storage.setItem(storageKey, JSON.stringify(formData));
    }
    catch (e) {
        // Fail silently - don't break form functionality
        console.warn('Failed to persist form data:', e);
    }
}
    function restoreFormData(form) {
    try {
        // Check if localStorage is available via global context
        const storage = (typeof localStorage !== 'undefined') ? localStorage : null;
        if (!storage)
            return;
        const storageKey = getFormStorageKey(form);
        const storedData = storage.getItem(storageKey);
        if (!storedData)
            return;
        const formData = JSON.parse(storedData);
        const timestamp = formData['_timestamp'];
        if (timestamp && (Date.now() - timestamp) > 60000 * 20) {
            storage.removeItem(storageKey);
            return;
        }
        // Restore form fields
        Array.from(form.elements || []).forEach((element) => {
            if (!element.name || !shouldPersistField(element.name)) {
                return;
            }
            // Don't override pre-filled values
            if (element.value && element.type !== 'checkbox' && element.type !== 'radio') {
                return;
            }
            const savedValue = formData[element.name];
            if (savedValue !== undefined) {
                if (element.type === 'checkbox') {
                    if (Array.isArray(savedValue)) {
                        element.checked = savedValue.includes(element.value);
                    }
                    else {
                        element.checked = element.value === savedValue;
                    }
                }
                else if (element.type === 'radio') {
                    element.checked = element.value === savedValue;
                }
                else {
                    element.value = savedValue;
                }
            }
        });
    }
    catch (e) {
        // Fail silently - don't break form functionality
        console.warn('Failed to restore form data:', e);
    }
}
    function clearFormData(form) {
    try {
        // Check if localStorage is available via global context
        const storage = (typeof localStorage !== 'undefined') ? localStorage : null;
        if (!storage)
            return;
        const storageKey = getFormStorageKey(form);
        storage.removeItem(storageKey);
    }
    catch (e) {
        // Fail silently
        console.warn('Failed to clear form data:', e);
    }
}
    function isValidNumber(num) {
    return typeof num === 'number' && isFinite(num) && !isNaN(num);
}
    function preSubmit(form, forms, event) {
    // Save form data at the beginning of submission attempt
    persistFormData(form);
    const routeOnError = form.attributes.getNamedItem('sf-route-on-error');
    if (routeOnError) {
        const input = document.createElement('input');
        input.setAttribute('name', 'routeOnError');
        input.setAttribute('value', 'true');
        input.setAttribute('type', 'hidden');
        form.appendChild(input);
    }
    const delayedUpsell = form.attributes.getNamedItem('sf-delayed-upsell');
    if (delayedUpsell) {
        const input = document.createElement('input');
        input.setAttribute('name', 'delayedUpsell');
        input.setAttribute('value', 'true');
        input.setAttribute('type', 'hidden');
        form.appendChild(input);
    }
    // Block submission if button is disabled (max attempts reached)
    var submitBtn = form.querySelector('button[type="submit"], input[type="submit"], .sf-submit-button');
    if (submitBtn && submitBtn.disabled) {
        if (event) {
            event.preventDefault();
        }
        return Promise.resolve(false);
    }
    if (inProgress) {
        if (event) {
            event.preventDefault();
        }
        return Promise.resolve(false);
    }
    // Check for registered payment providers in this form
    const formPaymentProviders = paymentProviders.filter(p => form.contains(p.container));
    // Helper function to continue form submission after payment providers
    function continueSubmission() {
        if (!performLuhnCheck(form)) {
            if (event) {
                event.preventDefault();
            }
            return false;
        }
        inProgress = true;
        const others = (forms || []).filter((f) => shouldAttach(f, form));
        others.forEach((other) => {
            addDataToForm(form, getDataFromForm(other));
        });
        translateDataAttributes(form);
        normalizeParameters(form);
        handleEmptyValues(form);
        stripCardNumberSpaces(form);
        handleRoute(form);
        injectDataAttributesAsInputs(form);
        injectFlowOptixProductData(form);
        checkForExtraProductInfo(form);
        if (handleThirdPartyIntegrations(form)) {
            if (event) {
                event.preventDefault();
            }
            return false;
        }
        handleRequestStart();
        // Paay
        if (PAAY_DATA && PAAY_DATA.setup && PAAY_DATA.prevent) {
            if (event) {
                event.preventDefault();
            }
            PAAY_DATA.verify();
            return false;
        }
        // If we had payment providers, we need to manually submit the form
        // since we prevented default earlier
        if (formPaymentProviders.length > 0) {
            form.submit();
            return false; // Prevent further processing
        }
        return true;
    }
    if (formPaymentProviders.length > 0) {
        // Prevent default immediately for async payment processing
        if (event) {
            event.preventDefault();
        }
        // Process payment providers sequentially using Promise chain
        let providerPromise = Promise.resolve();
        formPaymentProviders.forEach(function (provider) {
            providerPromise = providerPromise.then(function () {
                return provider.createToken();
            }).then(function (inputs) {
                if (inputs && inputs.length > 0) {
                    inputs.forEach(function (input) { form.appendChild(input); });
                }
            });
        });
        return providerPromise.then(function () {
            return continueSubmission();
        }).catch(function (error) {
            console.error('Payment provider error:', error);
            inProgress = false;
            return false;
        });
    }
    // No payment providers - continue synchronously
    return Promise.resolve(continueSubmission());
}
    function handleRoute(form) {
    if (form && form.dataset && form.dataset.gjsSfRoute) {
        form.action = form.dataset.gjsSfRoute;
    }
}
    function addDataToForm(form, data) {
    const existingElements = Array.from(form.elements || [])
        .map((element) => element.name)
        .filter((element) => !!element);
    data.forEach((item) => {
        const name = item['key'];
        const value = item['value'];
        if (existingElements.includes(name) && name !== 'product' && name !== 'quantity') {
            return;
        }
        const input = document.createElement('input');
        input.setAttribute('name', name);
        input.setAttribute('value', value);
        input.setAttribute('type', 'hidden');
        form.appendChild(input);
    });
    return form;
}
    function getDataFromForm(form) {
    return Object.keys(form.elements)
        .filter((k) => form.elements[k].name !== 'product' || form.elements[k].checked !== false)
        .filter((k) => form.elements[k].name !== 'submit')
        .map((k) => {
        return { key: form.elements[k].name, value: form.elements[k].value };
    });
}
    function translateDataAttributes(form) {
    const result = Object.keys(form.dataset).map((k) => {
        return { key: k, value: form.dataset[k] };
    });
    result.push({
        key: 'triggerMastercardConsent',
        value: form.attributes['sf-trigger-mastercard-consent'] ? 1 : 0,
    });
    result.push({
        key: 'orderVault',
        value: form.attributes['sf-use-order-vault'] ? 1 : '',
    });
    addDataToForm(form, result);
}
    function normalizeParameters(form) {
    const translationMap = {
        gjsSfPluginName: 'sf-plugin-name',
        gjsSfPluginType: 'pluginAction',
        gjsSfCampaignId: 'campaignId',
        gjsSfProduct: 'product',
        gjsSfVariant: 'variant',
        gjsSfVariantId: 'variantId',
        gjsSfReplaceProduct: 'replaceProductId',
        gjsSfEnableReplaceProduct: 'enableReplaceProduct',
        gjsSfReplaceProductEnabled: 'enableReplaceProduct',
        gjsSfExistingProductId: 'replaceProductId',
        gjsSfNewProductId: 'nextRecurringProductId',
        gjsSfShippingId: 'shippingId',
        gjsSfOfferId: 'offerId',
        gjsSfFunnelId: 'funnelId',
        gjsSfProductProperties: 'productProperties',
        gjsSfStartDelay: 'startDelay',
        gjsSfEndDelay: 'endDelay',
        gjsSfBillOption: 'merchantOption',
        gjsSfBillingModelId: 'billingModelId',
        gjsSfSticktosignupmid: 'StickToSignupMid',
        gjsSfAltMerchId: 'sf-pst-forceMerchantId',
        gjsSfForceGatewayId: 'forceGatewayId',
        gjsSfPreserveForceGateway: 'preserveForceGateway',
        gjsSfAllowedAttempts: 'sf-allowed-attempts',
        gjsSfCurrency: 'currency'
    };
    for (const element of form.elements) {
        element.name = translationMap[element.name] || element.name;
        if (((form.dataset || {}).gjsType === 'Limelight Legacy New Upsale' || (form.dataset || {}).gjsType === 'Limelight Prod New Upsale') &&
            element.name === 'campaignId' &&
            !element.value) {
            element.name = 'campaignIdOverridenEmpty';
        }
    }
}
    function attach() {
    const forms = Array.from(document.getElementsByTagName('form'));
    forms.forEach((form) => {
        // Restore persisted form data on page load
        restoreFormData(form);
        // Add auto-save functionality with debounce
        const debouncedPersist = debounce(() => persistFormData(form), 500);
        // Listen for input changes to persist data
        form.addEventListener('input', (event) => {
            const target = event.target;
            if (target && target.name && shouldPersistField(target.name)) {
                debouncedPersist();
            }
        });
        // Listen for change events (for select, checkbox, radio)
        form.addEventListener('change', (event) => {
            const target = event.target;
            if (target && target.name && shouldPersistField(target.name)) {
                debouncedPersist();
            }
        });
        // Submit handler - preSubmit returns a Promise for async payment providers
        form.addEventListener('submit', function (event) {
            preSubmit(form, forms, event);
        });
    });
}
    function initValidation() {
    document.querySelectorAll('[data-gjs-sf-validation-error-text]').forEach((input) => {
        input.addEventListener('invalid', () => {
            if (!input.validity.valid) {
                input.setCustomValidity(input.dataset.gjsSfValidationErrorText);
            }
        }, false);
        input.addEventListener('input', () => {
            input.setCustomValidity('');
            input.checkValidity();
        });
    });
}
    function handleEmptyValues(form) {
    [].slice.apply(form.elements).forEach((e) => {
        if (e.type === 'checkbox' && e.name === 'billShipSame' && e.value === '') {
            e.value = e.checked ? 'on' : '';
        }
        if (e.type === 'hidden' && e.name === 'StickToSignupMid') {
            e.value = true;
        }
        return e;
    });
}
    function stripCardNumberSpaces(form) {
    const cardField = form.querySelector('#ccnum, [name="cardNumber"], [name="creditCardNumber"]');
    if (!cardField || typeof cardField.value !== 'string' || !cardField.name) {
        return;
    }
    const stripped = cardField.value.replace(/\s+/g, '');
    if (stripped === cardField.value) {
        return;
    }
    const hidden = document.createElement('input');
    hidden.setAttribute('type', 'hidden');
    hidden.setAttribute('name', cardField.name);
    hidden.setAttribute('value', stripped);
    hidden.setAttribute('data-injected', 'true');
    form.appendChild(hidden);
    cardField.removeAttribute('name');
}
    function handleRequestStart() {
    const loaders = document.getElementsByClassName('sf-submit-loader-container');
    if (loaders && loaders.length > 0) {
        loaders[0].style.display = 'flex';
    }
    inProgress = true;
}
    function assureId(element) {
    const id = element.id;
    if (!id) {
        element.id = `${Math.floor(Math.random() * 1000000)}`;
    }
    return element;
}
    function handleThirdPartyIntegrations() {
    return false;
}
    function shouldAttach(otherForm, thisForm) {
    if (otherForm === thisForm) {
        return false;
    }
    const dataset = thisForm.dataset || {};
    if (dataset.gjsType === 'Shopping Cart Add Item Form') {
        return false;
    }
    return true;
}
    function checkForExtraProductInfo(form) {
    const formData = getDataFromForm(form);
    const product = formData.find((item) => item.key === 'product');
    if (product && product.value) {
        const productEls = document.querySelectorAll(`[name="product"][value="${product.value}"]`);
        if (productEls) {
            productEls.forEach((sourceProductEl) => {
                const billingModelId = sourceProductEl.getAttribute('data-gjs-sf-billing-model-id');
                const offerId = sourceProductEl.getAttribute('data-gjs-sf-offer-id');
                if (billingModelId) {
                    addDataToForm(form, [
                        {
                            key: 'billingModelId',
                            value: billingModelId,
                        },
                    ]);
                }
                if (offerId) {
                    addDataToForm(form, [
                        {
                            key: 'offerId',
                            value: offerId,
                        },
                    ]);
                }
            });
        }
    }
}
    function convertDataAttributeName(attrName) {
    return attrName.replace(/^data-/, '').replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
}
    function injectDataAttributesAsInputs(form) {
    const elements = form.elements;
    const injectedFields = new Set();
    const standaloneCustomFields = [];
    let maxCartIndex = -1;
    Array.from(elements).forEach((element) => {
        const match = element.name.match(/^cart\[items\]\[(\d+)\]/);
        if (match) {
            maxCartIndex = Math.max(maxCartIndex, parseInt(match[1]));
        }
    });
    let nextCartIndex = maxCartIndex + 1;
    Array.from(elements).forEach((element) => {
        if (!['INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName)) {
            return;
        }
        if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
            return;
        }
        const dataAttrs = {};
        const customFields = [];
        let hasProductData = false;
        let price = null;
        let quantity = null;
        Array.from(element.attributes).forEach((attr) => {
            if (attr.name.startsWith('data-sf-customfields-')) {
                // Extract token name (keep in kebab-case)
                const token = attr.name.replace(/^data-sf-customfields-/, '');
                customFields.push({
                    token: token,
                    value: attr.value
                });
                hasProductData = true;
            }
            else if (attr.name.startsWith('data-sf-')) {
                const cleanName = attr.name
                    .replace(/^data-sf-/, '')
                    .replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
                dataAttrs[cleanName] = attr.value;
                hasProductData = true;
            }
            else if (attr.name === 'data-price') {
                price = attr.value;
            }
            else if (attr.name === 'data-quantity') {
                quantity = attr.value;
            }
        });
        if (Object.keys(dataAttrs).length === 0 && customFields.length === 0 && price === null && quantity === null) {
            return;
        }
        const isProductArray = element.name === 'product[]' && (hasProductData || price !== null || quantity !== null);
        if (isProductArray) {
            const existingCartInput = form.querySelector(`input[name$="[product]"][value="${element.value}"]`);
            if (existingCartInput) {
                // Already handled by cart.js addShippingProductsToForm - skip to avoid duplicates
                return;
            }
            const cartPrefix = `cart[items][${nextCartIndex}]`;
            const productFieldName = `${cartPrefix}[product]`;
            if (!injectedFields.has(productFieldName)) {
                const input = document.createElement('input');
                input.setAttribute('name', productFieldName);
                input.setAttribute('value', element.value);
                input.setAttribute('type', 'hidden');
                input.setAttribute('data-injected', 'true');
                form.appendChild(input);
                injectedFields.add(productFieldName);
            }
            // Add price if exists
            if (price !== null) {
                const priceFieldName = `${cartPrefix}[price]`;
                if (!injectedFields.has(priceFieldName)) {
                    const input = document.createElement('input');
                    input.setAttribute('name', priceFieldName);
                    input.setAttribute('value', price);
                    input.setAttribute('type', 'hidden');
                    input.setAttribute('data-injected', 'true');
                    form.appendChild(input);
                    injectedFields.add(priceFieldName);
                }
            }
            // Add quantity - use data-quantity or data-sf-quantity or default to 1
            const qty = quantity || dataAttrs['quantity'] || '1';
            const quantityFieldName = `${cartPrefix}[quantity]`;
            if (!injectedFields.has(quantityFieldName)) {
                const input = document.createElement('input');
                input.setAttribute('name', quantityFieldName);
                input.setAttribute('value', qty);
                input.setAttribute('type', 'hidden');
                input.setAttribute('data-injected', 'true');
                form.appendChild(input);
                injectedFields.add(quantityFieldName);
            }
            Object.entries(dataAttrs).forEach(([key, value]) => {
                // Skip quantity if already added
                if (key === 'quantity') {
                    return;
                }
                // Handle trial fields - support both camelCase and lowercase variants
                // data-sf-istrial -> istrial, data-sf-is-trial -> isTrial
                if ((key === 'istrial' || key === 'isTrial') && (value === '1' || value === 'true')) {
                    const trialFieldName = `${cartPrefix}[trial]`;
                    if (!injectedFields.has(trialFieldName)) {
                        const input = document.createElement('input');
                        input.setAttribute('name', trialFieldName);
                        input.setAttribute('value', '1');
                        input.setAttribute('type', 'hidden');
                        input.setAttribute('data-injected', 'true');
                        form.appendChild(input);
                        injectedFields.add(trialFieldName);
                    }
                    return;
                }
                // data-sf-trial-productid -> trialProductid, data-sf-trial-product-id -> trialProductId
                if (key === 'trialProductid' || key === 'trialProductId') {
                    const trialProdFieldName = `${cartPrefix}[trialProductId]`;
                    if (!injectedFields.has(trialProdFieldName)) {
                        const input = document.createElement('input');
                        input.setAttribute('name', trialProdFieldName);
                        input.setAttribute('value', value);
                        input.setAttribute('type', 'hidden');
                        input.setAttribute('data-injected', 'true');
                        form.appendChild(input);
                        injectedFields.add(trialProdFieldName);
                    }
                    return;
                }
                // data-sf-trial-quantity -> trialQuantity
                if (key === 'trialQuantity') {
                    const trialQtyFieldName = `${cartPrefix}[trialQuantity]`;
                    if (!injectedFields.has(trialQtyFieldName)) {
                        const input = document.createElement('input');
                        input.setAttribute('name', trialQtyFieldName);
                        input.setAttribute('value', value);
                        input.setAttribute('type', 'hidden');
                        input.setAttribute('data-injected', 'true');
                        form.appendChild(input);
                        injectedFields.add(trialQtyFieldName);
                    }
                    return;
                }
                const fieldName = `${cartPrefix}[${key}]`;
                if (!injectedFields.has(fieldName)) {
                    const input = document.createElement('input');
                    input.setAttribute('name', fieldName);
                    input.setAttribute('value', value);
                    input.setAttribute('type', 'hidden');
                    input.setAttribute('data-injected', 'true');
                    form.appendChild(input);
                    injectedFields.add(fieldName);
                }
            });
            // Add custom fields array
            customFields.forEach((field, index) => {
                const tokenFieldName = `${cartPrefix}[customFields][${index}][token]`;
                const valueFieldName = `${cartPrefix}[customFields][${index}][value]`;
                if (!injectedFields.has(tokenFieldName)) {
                    const tokenInput = document.createElement('input');
                    tokenInput.setAttribute('name', tokenFieldName);
                    tokenInput.setAttribute('value', field.token);
                    tokenInput.setAttribute('type', 'hidden');
                    tokenInput.setAttribute('data-injected', 'true');
                    form.appendChild(tokenInput);
                    injectedFields.add(tokenFieldName);
                }
                if (!injectedFields.has(valueFieldName)) {
                    const valueInput = document.createElement('input');
                    valueInput.setAttribute('name', valueFieldName);
                    valueInput.setAttribute('value', field.value);
                    valueInput.setAttribute('type', 'hidden');
                    valueInput.setAttribute('data-injected', 'true');
                    form.appendChild(valueInput);
                    injectedFields.add(valueFieldName);
                }
            });
            nextCartIndex++;
            // Remove the original element's name attribute to prevent duplicate submission
            element.removeAttribute('name');
        }
        else if (element.name.endsWith('[]') && !element.name.startsWith('product')) {
            const baseName = element.name.slice(0, -2);
            let maxIndex = -1;
            Array.from(elements).forEach((el) => {
                const match = el.name.match(new RegExp(`^${baseName}\\[(\\d+)\\]`));
                if (match) {
                    maxIndex = Math.max(maxIndex, parseInt(match[1]));
                }
            });
            const currentIndex = maxIndex + 1;
            const indexedName = `${baseName}[${currentIndex}]`;
            if (!injectedFields.has(indexedName)) {
                const input = document.createElement('input');
                input.setAttribute('name', indexedName);
                input.setAttribute('value', element.value);
                input.setAttribute('type', 'hidden');
                input.setAttribute('data-injected', 'true');
                form.appendChild(input);
                injectedFields.add(indexedName);
            }
            Object.entries(dataAttrs).forEach(([key, value]) => {
                const fieldName = `${key}[${currentIndex}]`;
                if (!injectedFields.has(fieldName)) {
                    const input = document.createElement('input');
                    input.setAttribute('name', fieldName);
                    input.setAttribute('value', value);
                    input.setAttribute('type', 'hidden');
                    input.setAttribute('data-injected', 'true');
                    form.appendChild(input);
                    injectedFields.add(fieldName);
                }
            });
        }
        else {
            // Collect standalone custom fields (not associated with products)
            if (customFields.length > 0) {
                customFields.forEach(field => {
                    // Check if this exact custom field hasn't been added yet
                    const isDuplicate = standaloneCustomFields.some(existing => existing.token === field.token && existing.value === field.value);
                    if (!isDuplicate) {
                        standaloneCustomFields.push(field);
                    }
                });
            }
            Object.entries(dataAttrs).forEach(([key, value]) => {
                if (!injectedFields.has(key)) {
                    const input = document.createElement('input');
                    input.setAttribute('name', key);
                    input.setAttribute('value', value);
                    input.setAttribute('type', 'hidden');
                    input.setAttribute('data-injected', 'true');
                    form.appendChild(input);
                    injectedFields.add(key);
                }
            });
        }
    });
    // Process elements with name="data-sf-customfields-*" pattern
    Array.from(elements).forEach((element) => {
        if (!['INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName)) {
            return;
        }
        // Skip checkboxes and radios that aren't checked
        if ((element.type === 'checkbox' || element.type === 'radio') && !element.checked) {
            return;
        }
        const elementName = element.name || '';
        if (elementName.startsWith('data-sf-customfields-')) {
            // Extract token from name
            const token = elementName.replace(/^data-sf-customfields-/, '');
            const value = element.value || '';
            // Check if this exact custom field hasn't been added yet
            const isDuplicate = standaloneCustomFields.some(existing => existing.token === token && existing.value === value);
            if (!isDuplicate && value) {
                standaloneCustomFields.push({
                    token: token,
                    value: value
                });
            }
            // Mark the original field for removal to avoid double submission
            element.setAttribute('data-processed-as-customfield', 'true');
            element.removeAttribute('name');
        }
    });
    // Add standalone custom fields as top-level form fields
    standaloneCustomFields.forEach((field, index) => {
        const tokenFieldName = `customFields[${index}][token]`;
        const valueFieldName = `customFields[${index}][value]`;
        if (!injectedFields.has(tokenFieldName)) {
            const tokenInput = document.createElement('input');
            tokenInput.setAttribute('name', tokenFieldName);
            tokenInput.setAttribute('value', field.token);
            tokenInput.setAttribute('type', 'hidden');
            tokenInput.setAttribute('data-injected', 'true');
            form.appendChild(tokenInput);
            injectedFields.add(tokenFieldName);
        }
        if (!injectedFields.has(valueFieldName)) {
            const valueInput = document.createElement('input');
            valueInput.setAttribute('name', valueFieldName);
            valueInput.setAttribute('value', field.value);
            valueInput.setAttribute('type', 'hidden');
            valueInput.setAttribute('data-injected', 'true');
            form.appendChild(valueInput);
            injectedFields.add(valueFieldName);
        }
    });
}
    function injectFlowOptixProductData(form) {
    const foProductElements = Array.from(form.querySelectorAll('[name="foProduct[]"]'));
    if (foProductElements.length === 0) {
        return; // No Flow Optix products
    }
    let validIndex = 0; // Track only valid foProduct entries
    foProductElements.forEach((element) => {
        const campaignId = element.getAttribute('data-fo-campaign-id');
        const productId = element.getAttribute('data-fo-product-id');
        // Only create inputs if both attributes exist
        if (campaignId && productId) {
            // Create campaignId input
            const campaignInput = document.createElement('input');
            campaignInput.setAttribute('name', `foProduct[${validIndex}][campaignId]`);
            campaignInput.setAttribute('value', campaignId);
            campaignInput.setAttribute('type', 'hidden');
            campaignInput.setAttribute('data-injected', 'true');
            form.appendChild(campaignInput);
            // Create productId input
            const productInput = document.createElement('input');
            productInput.setAttribute('name', `foProduct[${validIndex}][productId]`);
            productInput.setAttribute('value', productId);
            productInput.setAttribute('type', 'hidden');
            productInput.setAttribute('data-injected', 'true');
            form.appendChild(productInput);
            validIndex++; // Increment only for valid entries
        }
        // Remove the original element's name attribute to prevent duplicate submission
        element.removeAttribute('name');
    });
}
    function performLuhnCheck(form) {
    const acceptedCreditCards = {
        visa: /^4[0-9]{12}(?:[0-9]{3})?$/,
        mastercard: /^5[1-5][0-9]{14}$|^2(?:2(?:2[1-9]|[3-9][0-9])|[3-6][0-9][0-9]|7(?:[01][0-9]|20))[0-9]{12}$/,
        amex: /^3[47][0-9]{13}$/,
        discover: /^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$/,
        diners_club: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
        jcb: /^(?:2131|1800|35[0-9]{3})[0-9]{11}$/,
    };
    function checkSupported(value) {
        // remove all non digit characters
        value = value.replace(/\D/g, '');
        let accepted = false;
        // loop through the keys (visa, mastercard, amex, etc.)
        Object.keys(acceptedCreditCards).forEach(function (key) {
            const regex = acceptedCreditCards[key];
            if (regex.test(value)) {
                accepted = true;
            }
        });
        return accepted;
    }
    const ccField = form.querySelector('[name="cardNumber"]') || form.querySelector('[name="creditCardName"]');
    const luhnEnabled = Object.keys(form.dataset).includes('gjsSfLuhnEnabled') && !(form.dataset.gjsSfLuhnEnabled === false);
    return !luhnEnabled || (ccField && ccField.value && luhn(ccField.value) && checkSupported(ccField.value));
}
    function luhn(value) {
    // Accept only digits, dashes or spaces
    if (/[^0-9-\s]+/.test(value))
        return false;
    // The Luhn Algorithm. It's so pretty.
    let nCheck = 0, bEven = false;
    value = value.replace(/\D/g, '');
    for (let n = value.length - 1; n >= 0; n--) {
        const cDigit = value.charAt(n);
        let nDigit = parseInt(cDigit, 10);
        if (bEven && (nDigit *= 2) > 9)
            nDigit -= 9;
        nCheck += nDigit;
        bEven = !bEven;
    }
    return nCheck % 10 == 0;
}

    attach();
    initValidation();

                
    function setText(id, text) {
    const element = document.getElementById(id);
    if (element) {
        element.innerText = text;
    }
};
    function setHtml(id, html) {
    const element = document.getElementById(id);
    if (element) {
        element.innerHTML = html;
    }
};
    function setTextIfValue(element, value, id, text) {
    if (element && element.value == value) {
        setText(id, text);
    }
};
    function setHtmlIfValue(element, value, id, html) {
    if (element && element.value == value) {
        setHtml(id, html);
    }
};
    function setProductId(pid, formId) {
    const form = formId ? document.getElementById(formId) : document.forms[0];
    if (form)
        form.setAttribute('data-gjs-sf-product', pid);
};
    function setVariantId(vid, formId) {
    const form = formId ? document.getElementById(formId) : document.forms[0];
    if (form)
        form.setAttribute('data-gjs-sf-variant', vid);
};
    function setOfferId(oid, formId) {
    const form = formId ? document.getElementById(formId) : document.forms[0];
    if (form)
        form.setAttribute('data-gjs-sf-offer', oid);
};
    function setItemId(iid, formId) {
    const form = formId ? document.getElementById(formId) : document.forms[0];
    if (form)
        form.setAttribute('data-gjs-sf-item', iid);
};

                
    function handlePopup() {
    const popups = Array.from(document.querySelectorAll("[data-gjs-type='Popup Modal']"));
    popups.forEach((popup) => {
        popup.style.display = 'none';
        const dataset = popup.dataset;
        if (dataset.gjsSfCloseClickOutside && dataset.gjsSfCloseClickOutside === 'true') {
            popup.addEventListener('click', (event) => {
                if (event.target.id === popup.id) {
                    popup.style.display = 'none';
                }
            });
        }
        const closeIcon = document.getElementById(popup.id + '-close');
        if (closeIcon) {
            closeIcon.addEventListener('click', () => (popup.style.display = 'none'));
        }
        if (!dataset.gjsSfActivateOn) {
            return;
        }
        switch (dataset.gjsSfActivateOn) {
            case 'exit': {
                document.addEventListener('mouseleave', (e) => {
                    if (e.clientY < 0) {
                        popup.style.display = 'block';
                    }
                });
                return;
            }
            case 'load': {
                popup.style.display = 'block';
                return;
            }
        }
    });
}

    handlePopup();

                function sfSendSurvey(data, id) {
    fetch('index', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: data,
        redirect: 'manual',
    });
    const el = document.getElementById(id).closest("[data-gjs-type='Popup Modal']");
    if (el) {
        el.remove();
    }
}
                
    function handleCartBtns() {
    const addButtons = Array.from(document.querySelectorAll("[data-gjs-type='Shopping Cart Add Item']"));
    const removeButtons = Array.from(document.querySelectorAll("[data-gjs-type='Shopping Cart Remove Item']"));
    addButtons.forEach((button) => {
        button.addEventListener('click', () => {
            const form = document.createElement('form');
            const qty = button.dataset.gjsSfQuantity || 1;
            form.method = 'POST';
            if (button.dataset.gjsSfRoute) {
                form.action = button.dataset.gjsSfRoute;
            }
            const pluginNameInput = document.createElement('input');
            pluginNameInput.setAttribute('name', 'sf-plugin-name');
            pluginNameInput.setAttribute('value', button.dataset.gjsSfPluginName);
            pluginNameInput.setAttribute('type', 'hidden');
            form.appendChild(pluginNameInput);
            const pluginActionInput = document.createElement('input');
            pluginActionInput.setAttribute('name', 'pluginAction');
            pluginActionInput.setAttribute('value', 'add');
            pluginActionInput.setAttribute('type', 'hidden');
            form.appendChild(pluginActionInput);
            const productInput = document.createElement('input');
            productInput.setAttribute('name', 'product');
            productInput.setAttribute('value', button.dataset.gjsSfProduct);
            productInput.setAttribute('type', 'hidden');
            form.appendChild(productInput);
            const dataInput = document.createElement('input');
            dataInput.setAttribute('name', 'productProperties');
            dataInput.setAttribute('value', button.dataset.gjsSfProductProperties || '');
            dataInput.setAttribute('type', 'hidden');
            form.appendChild(dataInput);
            const clearInput = document.createElement('input');
            clearInput.setAttribute('name', 'clearCart');
            clearInput.setAttribute('value', button.attributes['sf-clear-cart'] ? 'clear' : '');
            clearInput.setAttribute('type', 'hidden');
            form.appendChild(clearInput);
            const clearItemInput = document.createElement('input');
            clearItemInput.setAttribute('name', 'clearCartItem');
            clearItemInput.setAttribute('value', button.attributes['sf-clear-cart-item'] ? 'clear' : '');
            clearItemInput.setAttribute('type', 'hidden');
            form.appendChild(clearItemInput);
            const quantityInput = document.createElement('input');
            quantityInput.setAttribute('name', 'quantity');
            quantityInput.setAttribute('value', qty);
            quantityInput.setAttribute('type', 'hidden');
            form.appendChild(quantityInput);
            document.body.appendChild(form);
            form.submit();
        });
    });
    removeButtons.forEach((button) => {
        button.addEventListener('click', () => {
            const form = document.createElement('form');
            form.method = 'POST';
            const pluginNameInput = document.createElement('input');
            pluginNameInput.setAttribute('name', 'sf-plugin-name');
            pluginNameInput.setAttribute('value', button.dataset.gjsSfPluginName);
            pluginNameInput.setAttribute('type', 'hidden');
            form.appendChild(pluginNameInput);
            const pluginActionInput = document.createElement('input');
            pluginActionInput.setAttribute('name', 'pluginAction');
            pluginActionInput.setAttribute('value', 'remove');
            pluginActionInput.setAttribute('type', 'hidden');
            form.appendChild(pluginActionInput);
            const productInput = document.createElement('input');
            productInput.setAttribute('name', 'product');
            productInput.setAttribute('value', button.dataset.gjsSfProduct);
            productInput.setAttribute('type', 'hidden');
            form.appendChild(productInput);
            const clearInput = document.createElement('input');
            clearInput.setAttribute('name', 'clearCart');
            clearInput.setAttribute('value', button.attributes['sf-clear-cart'] ? 'clear' : '');
            clearInput.setAttribute('type', 'hidden');
            form.appendChild(clearInput);
            const clearItemInput = document.createElement('input');
            clearItemInput.setAttribute('name', 'clearCartItem');
            clearItemInput.setAttribute('value', button.attributes['sf-clear-cart-item'] ? 'clear' : '');
            clearItemInput.setAttribute('type', 'hidden');
            form.appendChild(clearItemInput);
            document.body.appendChild(form);
            form.submit();
        });
    });
}

    function handleCartForms() {
    const addForms = Array.from(document.querySelectorAll("[data-gjs-type='Shopping Cart Add Item Form']"));
    addForms.forEach((form) => {
        const btn = form.querySelector('button');
        form.addEventListener('submit', function (e) {
            console.warn(e);
            let qtyInput = form.querySelector('[name=quantity]');
            if (!qtyInput) {
                const qty = form.dataset.gjsSfQuantity || 1;
                qtyInput = document.createElement('input');
                qtyInput.setAttribute('name', 'quantity');
                qtyInput.setAttribute('value', qty);
                qtyInput.setAttribute('type', 'hidden');
                form.appendChild(qtyInput);
            }
            const clearInput = document.createElement('input');
            clearInput.setAttribute('name', 'clearCart');
            clearInput.setAttribute('value', btn.attributes['sf-clear-cart'] ? 'clear' : '');
            clearInput.setAttribute('type', 'hidden');
            form.appendChild(clearInput);
            const clearItemInput = document.createElement('input');
            clearItemInput.setAttribute('name', 'clearCartItem');
            clearItemInput.setAttribute('value', btn.attributes['sf-clear-cart-item'] ? 'clear' : '');
            clearItemInput.setAttribute('type', 'hidden');
            form.appendChild(clearItemInput);
        });
    });
}

    handleCartBtns();
    handleCartForms();

                
            </script>
            
                       
            
            
          <script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a115f3165d6c3483',t:'MTc4MjQxMTI0MQ=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
        </html>
    