PageSourceSearch

https://postmodern-jukebox.webflow.io/terms

html postmodern-jukebox.webflow.io collected 2026-10-03 13:36:47 UTC 48,094 bytes, 915 lines download raw bytes

1<!DOCTYPE html><!-- Last Published: Thu Sep 24 2026 18:04:18 GMT+0000 (Coordinated Universal Time) --><html data-wf-domain="postmodern-jukebox.webflow.io" data-wf-page="69c3fc5ac9f60b8eed4e5e64" data-wf-site="69c2b9815263da6a49ccf592" lang="en"><head><meta charset="utf-8"/><link href="https://cdn.prod.website-files.com" rel="preconnect" crossorigin="anonymous"/><title>Terms of Use</title><meta content="Terms of Use" property="og:title"/><meta content="Terms of Use" name="twitter:title"/><meta content="width=device-width, initial-scale=1" name="viewport"/><link href="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/css/postmodern-jukebox.webflow.shared.5669ecd2b.css" rel="stylesheet" type="text/css" integrity="sha384-Vmns0rW0m3JUhKEfg3bD7rsUjxrSgSYEfn42Ps7rweANzNKAHZlOahx0wcMLZtnm" crossorigin="anonymous"/><link href="https://fonts.googleapis.com" rel="preconnect"/><link href="https://fonts.gstatic.com" rel="preconnect" crossorigin="anonymous"/>
1<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js" type="text/javascript"></script>
1<script type="text/javascript">WebFont.load({  google: {    families: ["Inter:300,400,500,600,700"]  }});</script>
1<script src="https://use.typekit.net/guh4etq.js" type="text/javascript"></script>
1<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
1<script type="text/javascript">!function(o,c){var n=c.documentElement,t=" w-mod-";n.className+=t+"js",("ontouchstart"in o||o.DocumentTouch&&c instanceof DocumentTouch)&&(n.className+=t+"touch")}(window,document);</script>
1<link href="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/69cae9a5001740fc8d4dc547_fav_circle_32.png" rel="icon" type="image/png" sizes="32x32" media="(prefers-color-scheme: light)"/><link href="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/69cae9a5001740fc8d4dc547_fav_circle_32.png" rel="icon" type="image/png" sizes="32x32" media="(prefers-color-scheme: dark)"/><link href="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/69cae9b1f0926144d376145c_fav_circle_256.png" rel="apple-touch-icon"/>
1<script>(function(w,i,g){w[g]=w[g]||[];if(typeof w[g].push=='function')w[g].push.apply(w[g],Array.isArray(i)?i:[i]);})(window,['G-8JM48JCNFN'],'google_tags_first_party');</script>
1<script async="" src="/haqt6iy0yx2eNjljMmI5ODE1MjYzZGE2YTQ5Y2NmNTky/swoU_Bl-mHSmbWuqdd1JbfE8ew4"></script>
1<script type="text/javascript">window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('set', 'developer_id.dZGVlNj', true);gtag('set', 'developer_id.dYWYxNW', true);gtag('js', new Date());gtag('config', 'G-8JM48JCNFN');</script>
1<!-- Meta Pixel Code -->
2<script>
vendor: 399 bytes, lines 2-11
2
3!function(f,b,e,v,n,t,s)
4{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
5n.callMethod.apply(n,arguments):n.queue.push(arguments)};
6if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
7n.queue=[];t=b.createElement(e);t.async=!0;
8t.src=v;s=b.getElementsByTagName(e)[0];
9s.parentNode.insertBefore(t,s)}(window, document,'script',
10'https://connect.facebook.net/en_US/fbevents.js');
11fbq('init', '
111008267602569190
vendor: 30 bytes, lines 11-12
11');
12fbq('track', 'PageView');
13</script>
13
14<noscript><img height="1" width="1" style="display:none"
15src="https://www.facebook.com/tr?id=1008267602569190&ev=PageView&noscript=1"
16/></noscript>
17<!-- End Meta Pixel Code -->
18
19<!-- Google Analytics --> <!-- UNUSED IN FAVOR OF Apps & Integrations -->
20<!-- Google Tag Manager --> <!-- Tag manager currently appears to be empty -->
21<!-- 
21<script>
vendor: 328 bytes, lines 21-26
21
22(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
23new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
24j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
25'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
26})(window,document,'script','dataLayer','
26GTM-TLGB2WN
vendor: 4 bytes, line 26
26');
27</script>
27 -->
28<!-- End Google Tag Manager -->
29
30<!-- Enzuzo -->
31<!-- 
31<script src="https://app.enzuzo.com/scripts/cookiebar/6495237a-3374-11f1-b383-0bc89965430d"></script>
31 -->
32
33<!-- Global Styles -->
34<style>
35  input::placeholder {
36    color: inherit !important;
37    opacity: 0.5;
38  }
39
40  .iti {
41    --iti-border-color: var(--pmj-gold);
42    --iti-dropdown-bg: var(--pmj-blue);
43    --iti-icon-color: var(--pmj-gold);
44    --iti-hover-color: var(--pmj-lighter-blue);
45
46    width: 100%;
47    margin-bottom: 10px;
48
49    & input[type="search"] {
50      background-color: var(--pmj-blue);
51    }
52  }
53</style></head><body class="body-standard"><div class="header"><div id="mobile-nav" class="mobile-nav hidden"><div class="mobile-nav-scripts w-embed w-script">
53<script>
54  document.addEventListener('DOMContentLoaded', () => {
55    const hamburger = document.getElementById('hamburger')
56    const mobileNav = document.getElementById('mobile-nav')
57
58    if (!hamburger || !mobileNav) {
59      console.warn('Missing required mobile nav element.')
60      return
61    }
62
63    const mobileNavLinks = mobileNav.querySelectorAll('a')
64
65    mobileNavLinks.forEach((link) => {
66      link.addEventListener('click', () => {
67        hideMobileNav()
68      })
69    })
70
71    function hideMobileNav () {
72      mobileNav.classList.add('hidden')
73      hamburger.classList.remove('close')
74    }
75
76    hamburger.addEventListener('click', () => {
77      if (mobileNav.classList.contains('hidden')) {
78        mobileNav.classList.remove('hidden')
79        hamburger.classList.add('close')
80      } else {
81        hideMobileNav()
82      }
83    })
84  })
85</script>
85</div><div class="mobile-nav-styling w-embed"><style>
86  .mobile-nav .nav-tickets-wrap {
87    display: flex !important;
88    flex-direction: column;
89  }
90  .mobile-nav .nav-list {
91    flex-direction: column;
92    align-items: center;
93  }
94</style></div><div class="nav-tickets-wrap header-nav"><ul role="list" class="nav-list"><li><a href="/">Home</a></li><li><a href="/tour-dates">Tour Dates</a></li><li><a href="/#featured-videos">Videos</a></li><li class="hidden-link"><a href="https://postmodernjukebox.myshopify.com/">Store</a></li><li><a href="/#about">About</a></li><li><a data-open-contact="" href="#">Contact</a></li></ul><a href="/tour-dates" class="tickets-button w-button">Tickets</a></div></div><div class="header-styles w-embed"><style>
95  .header .nav-list a {
96    text-decoration: none;
97  }
98
99  .hamburger.close .bar.t {
100    top: 43%;
101    transform: rotateZ(-45deg);
102  }
103  .hamburger.close .bar.m {
104    opacity: 0;
105  }
106  .hamburger.close .bar.b {
107    bottom: 43%;
108    transform: rotateZ(45deg);
109  }
110</style></div><a href="/" class="link-block w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/69c2dcadf485bf6a30da92cb_pmj_header_logotype.svg" alt="" class="header-logotype"/></a><div class="nav-tickets-wrap header-nav"><ul role="list" class="nav-list"><li><a href="/">Home</a></li><li><a href="/tour-dates">Tour Dates</a></li><li><a href="/#featured-videos">Videos</a></li><li class="hidden-link"><a href="https://postmodernjukebox.myshopify.com/">Store</a></li><li><a href="/#about">About</a></li><li><a data-open-contact="" href="#">Contact</a></li></ul><a href="/tour-dates" class="tickets-button w-button">Tickets</a></div><div id="hamburger" class="hamburger"><div class="bars-wrapper"><div class="bar t"></div><div class="bar m"></div><div class="bar b"></div></div></div></div><div class="text-page-content"><h1 class="page-title">Terms of Service</h1><div class="rich-text w-richtext"><p><strong>Last updated: March 31, 2026</strong></p><p>‍</p><p>Welcome to <strong>Postmodern Jukebox</strong> (“we,” “us,” or “our”). These Terms of Service (“Terms”) govern your use of our website located at <strong>[yourdomain.com]</strong> (the “Site”).</p><p>By accessing or using the Site, you agree to be bound by these Terms.</p><p>‍</p><h2>Use of the Site</h2><p>You agree to use this Site only for lawful purposes and in accordance with these Terms.</p><p>You agree not to:</p><ul role="list"><li>Use the Site in any way that violates applicable laws or regulations</li><li>Attempt to gain unauthorized access to any part of the Site</li><li>Interfere with or disrupt the Site or its servers</li><li>Use the Site to transmit any harmful or malicious code</li></ul><p>‍</p><h2>Intellectual Property</h2><p>All content on this Site, including text, images, graphics, logos, and design, is owned by or licensed to <strong>[Your Company]</strong> and is protected by intellectual property laws.</p><p>You may not reproduce, distribute, modify, or create derivative works without our prior written consent.</p><p>‍</p><h2>User Submissions</h2><p>If you submit any information through the Site (e.g., forms, messages, or uploads), you:</p><ul role="list"><li>Grant us the right to use, reproduce, and process that information as necessary to operate the Site and provide services</li><li>Represent that you have the right to submit such information</li></ul><p>We reserve the right to remove or refuse any submissions at our discretion.</p><p>‍</p><h2>Third-Party Links</h2><p>Our Site may contain links to third-party websites or services. We are not responsible for the content, policies, or practices of those third parties.</p><p>Use of third-party sites is at your own risk.</p><p>‍</p><h2>Disclaimer of Warranties</h2><p>The Site is provided on an “as is” and “as available” basis.</p><p>We make no warranties, express or implied, regarding:</p><ul role="list"><li>The operation or availability of the Site</li><li>The accuracy or completeness of content</li><li>The absence of errors or interruptions</li></ul><p>‍</p><h2>Limitation of Liability</h2><p>To the fullest extent permitted by law, <strong>[Your Company]</strong> shall not be liable for any indirect, incidental, special, or consequential damages arising out of or related to your use of the Site.</p><p>‍</p><h2>Indemnification</h2><p>You agree to indemnify and hold harmless <strong>[Your Company]</strong> from any claims, damages, or expenses arising from:</p><ul role="list"><li>Your use of the Site</li><li>Your violation of these Terms</li></ul><p>‍</p><h2>Termination</h2><p>We reserve the right to suspend or terminate your access to the Site at any time, without notice, for conduct that we believe violates these Terms or is otherwise harmful.</p><p>‍</p><h2>Governing Law</h2><p>These Terms are governed by and construed in accordance with the laws of the State of <strong>[Your State]</strong>, without regard to its conflict of law principles.</p><p>‍</p><h2>Changes to These Terms</h2><p>We may update these Terms from time to time. Updates will be posted on this page with a revised “Last updated” date.</p><p>Your continued use of the Site after changes are posted constitutes your acceptance of the updated Terms.</p><p>‍</p><h2>Contact Information</h2><p>If you have any questions about these Terms, please contact us:</p><p><strong>[Company Name]</strong><br/><strong>[Email Address]</strong><br/><strong>[Mailing Address (optional)]</strong></p><p>‍</p></div></div><div class="footer"><div id="subscribe-modal" class="modal hidden"><div class="modal__hitbox"></div><div class="modal__inner"><div class="modal__close"><p class="close-x">×</p></div><div data-listid="27" class="subscribe-form w-form"><form id="wf-form-Modal-Subscribe-Form" name="wf-form-Modal-Subscribe-Form" data-name="Modal Subscribe Form" method="get" data-wf-page-id="69c3fc5ac9f60b8eed4e5e64" data-wf-element-id="189f57b2-242a-d2db-1253-57904bd611d3" data-turnstile-sitekey="0x4AAAAAAAQTptj2So4dx43e"><div class="form-header"><h2 class="form__title">Stay Updated</h2><h3 class="form__subtitle">Hear the latest on tour dates and new releases.</h3></div><div class="input-wrapper name first"><div class="input-single-wrapper"><label for="first-name" class="standard-label">First Name</label><input class="standard-input w-input" maxlength="256" name="first-name" data-name="first-name" placeholder="" type="text"/></div><div class="input-single-wrapper"><label for="last-name" class="standard-label">Last Name</label><input class="standard-input w-input" maxlength="256" name="last-name" data-name="last-name" placeholder="" type="text" id="last-name"/></div></div><label for="City" class="standard-label">Your City</label><input class="standard-input w-input" maxlength="256" name="City" data-name="City" placeholder="" type="text" id="City" required=""/><label for="Email" class="standard-label">Email Address</label><input class="standard-input w-input" maxlength="256" name="Email" data-name="Email" placeholder="" type="email" id="Email" required=""/><label for="subscribe-phone" class="standard-label">Phone Number (Optional)</label><input class="standard-input intl-phone w-input" maxlength="256" name="field" data-name="Field" placeholder="" type="text" id="subscribe-phone"/>
110<p class="sms-disclaimer">By entering your phone number and pressing &quot;Submit&quot; below you confirm that you are 13 years old or older and meet the minimum age requirements to use this service. You agree to Community&#x27;s Terms of Service and Privacy Policy and consent to receive recurring messages at the number above (which may be marketing and/or automated) from or on behalf of Postmodern Jukebox via Community. Consent is not a condition of purchase. Message &amp; data rates may apply. Message HELP for help, STOP to cancel.</p><input type="submit" data-wait="Please wait..." class="btn w-button" value="Submit"/></form><div class="success-message w-form-done"><div>Thank you! Your submission has been received!</div></div><div class="w-form-fail"><div>Oops! Something went wrong while submitting the form.</div></div></div></div></div><div id="contact-modal" class="modal hidden"><div class="modal__hitbox"></div><div class="modal__inner"><div class="modal__close"><p class="close-x">×</p></div><div data-listid="27" class="contact-form w-form"><form id="email-form" name="email-form" data-name="Email Form" method="get" data-wf-page-id="69c3fc5ac9f60b8eed4e5e64" data-wf-element-id="ee3635b7-d4b4-29e4-68d1-fff7f7e074f4" data-turnstile-sitekey="0x4AAAAAAAQTptj2So4dx43e"><div class="form-header"><h2 class="form__title">Got a question?</h2><h3 class="form__subtitle">Send us a message and we&#x27;ll get back to you as soon as possible.</h3></div><div class="input-wrapper name"><div class="input-single-wrapper"><label for="contact-first-name" class="standard-label">First Name</label><input class="standard-input w-input" maxlength="256" name="first-name" data-name="first-name" placeholder="" type="text" id="contact-first-name"/></div><div class="input-single-wrapper"><label for="contact-last-name" class="standard-label">Last Name</label><input class="standard-input w-input" maxlength="256" name="last-name" data-name="last-name" placeholder="" type="text" id="contact-last-name"/></div></div><label for="email" class="standard-label">Email Address</label><input class="standard-input w-input" maxlength="256" name="email" data-name="Email" placeholder="" type="email" id="email" required=""/><label for="email-reason" class="standard-label">Reason for Contacting</label><select id="email-reason" name="Reason" data-name="Reason" required="" class="standard-input w-select"><option value="">Select one...</option><option value="Europe Tickets / VIP">Europe Tickets / VIP</option><option value="North America Tickets / VIP">North America Tickets / VIP</option><option value="Booking">Booking</option><option value="All other inquiries">All other inquiries</option></select><label for="email-subject" class="standard-label">Subject</label><input class="standard-input w-input" maxlength="256" name="Email-Subject" data-name="Email Subject" placeholder="" type="text" id="email-subject" required=""/><label for="email-message" class="standard-label">Message</label><textarea id="email-message" name="Message" maxlength="5000" data-name="Message" placeholder="" class="standard-input w-input"></textarea><label class="w-checkbox standard-checkbox"><input type="checkbox" id="Subscribe" name="Subscribe" data-name="Subscribe" data-subscribe="" class="w-checkbox-input checkbox"/><span class="standard-label check w-form-label" for="Subscribe">Subscribe to Mailing List?</span></label><label for="contact-phone" class="standard-label">Phone Number (Optional)</label><input class="standard-input intl-phone w-input" maxlength="256" name="field" data-name="Field" placeholder="" type="text" id="contact-phone"/><p class="sms-disclaimer">By entering your phone number and pressing &quot;Submit&quot; below you confirm that you are 13 years old or older and meet the minimum age requirements to use this service. You agree to Community&#x27;s Terms of Service and Privacy Policy and consent to receive recurring messages at the number above (which may be marketing and/or automated) from or on behalf of Postmodern Jukebox via Community. Consent is not a condition of purchase. Message &amp; data rates may apply. Message HELP for help, STOP to cancel.</p><input type="submit" data-wait="Please wait..." class="btn w-button" value="Submit"/></form><div class="success-message w-form-done"><div>Thank you! Your submission has been received!</div></div><div class="form-error w-form-fail"><div>Oops! Something went wrong while submitting the form.</div></div></div></div></div><div class="footer-styles w-embed"><style>
111  .footer .nav-list a {
112    text-decoration: none;
113  }
114</style></div><div class="footer__subscribe"><div class="news-headline-wrapper"><div class="code-embed w-embed"><?xml version="1.0" encoding="UTF-8"?>
115<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 49.26 44.56">
116  <defs>
117    <style>
118      .cls-1 {
119        fill: currentColor;
120      }
121    </style>
122  </defs>
123  <g id="FONTS_AND_LAYOUT" data-name="FONTS AND LAYOUT">
124    <g>
125      <path class="cls-1" d="M28.59,22.39l3.74,2.38-15.52,8.33c-2.8,1.5-5.43,4.51-3.49,8.08.98,1.8,2.57,3.16,4.29,3.37.05,0,.1,0,.16.01.63-1.01,1.37-1.95,2.13-2.88.19-.23.39-.46.58-.69-.58-.43-1.07-.94-1.38-1.67-1.13-2.62,6.14-6.69,8-7.83l8.01-4.95,6.03,3.78,8.13-8.13-8.15-8.14-6.35,3.85-8.24-5.09c-1.82-1.12-9.04-5.2-7.85-7.81.21-.47.5-.85.83-1.18-1.18-1.12-2.2-2.43-3.1-3.82-1.39.46-2.65,1.61-3.46,3.05-2.02,3.6.51,6.62,3.34,8.14l15.65,8.41-3.64,2.26C19.65,20.55,8.65,19.33,0,18.51c0,.93.37,5.73.48,7.19,8.58-.86,19.51-2,28.11-3.32Z"/>
126      <path class="cls-1" d="M9.75,9.76c-.18-.1-.37-.
12618-.56-.26-1.16,1.73-2.43,3.39-3.59,5.13-.26.39-.55.73-.87,1.03,7.94,1.8,15.64,3.63,24.13,4.92-6.13-4.26-12.56-7.33-19.11-10.82Z"/>
127      <path class="cls-1" d="M5.53,28.63c.87.43,1.61,1.09,2.06,1.94.59,1.12,1.17,2.23,1.91,3.26.2.27.35.58.45.9.03-.02.07-.03.1-.04,6.48-3.43,12.86-6.54,19.24-10.86-8.26,1.16-15.93,3.03-23.77,4.8Z"/>
128    </g>
129  </g>
130</svg></div><h1 class="headline">News &amp; Updates Here</h1></div><div class="arrow-wrap"><div class="arrow-line"></div><div class="arrow-head w-embed"><svg width="8" height="10" viewBox="0 0 8 10" fill="none" xmlns="http://www.w3.org/2000/svg">
131  <path d="M1 1L7 5L1 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
132</svg></div></div><div data-listid="27" class="subscribe-form-block w-form"><form id="footer-subscribe" name="wf-form-" data-name="Footer Subscribe" method="get" data-wf-page-id="69c3fc5ac9f60b8eed4e5e64" data-wf-element-id="82ea620f-13a0-06ed-ead9-9bb7519967d7" data-turnstile-sitekey="0x4AAAAAAAQTptj2So4dx43e"><div class="input-wrapper"><input class="subscribe-input w-input" maxlength="256" name="email" data-name="Email" placeholder="Enter your email" type="email" id="footer-subscribe-email" required=""/><input type="submit" data-wait="Please wait..." id="footer-subscribe-submit" class="btn w-button" value="Submit"/></div></form><div class="success-message w-form-done"><div>Thank you! Your submission has been received!</div></div><div class="w-form-fail"><div>Sorry, something went wrong. Please try again later.</div></div></div></div><img loading="lazy" src="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/69c3fae7636e6830966d10e3_footer_logo.svg" alt="" class="footer__logo"/><div class="footer__nav"><div class="footer__nav__socials"><ul role="list" class="nav-list condensed"><li><a href="https://www.facebook.com/postmodernjukebox/" target="_blank"></a></li><li><a href="https://x.com/PMJofficial" target="_blank"></a></li><li><a href="https://www.instagram.com/pmjofficial/" target="_blank"></a></li><li><a href="https://www.youtube.com/channel/UCORIeT1hk6tYBuntEXsguLg" target="_blank"></a></li><li><a href="https://open.spotify.com/artist/5HYNPEO2NNBONQkp3Mvwvc" target="_blank"></a></li></ul></div><div class="nav-tickets-wrap"><ul role="list" class="nav-list footer-nav"><li><a href="/terms" aria-current="page" class="w--current">Terms of Service</a></li><li><a href="/privacy-policy">Privacy Policy</a></li><li><a href="#manage_cookies">Cookies</a></li><li><a data-open-contact="" href="#">Contact</a></li></ul><a href="/tour-dates" class="tickets-button w-button">Tickets</a></div></div></div>
132<script src="https://d3e54v103j8qbb.cloudfront.net/js/jquery-3.5.1.min.dc5e7f18c8.js?site=69c2b9815263da6a49ccf592" type="text/javascript" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
132<script src="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/js/webflow.schunk.1398ace9ffbb200a.js" type="text/javascript" integrity="sha384-EVP6t2U07qoLfhZHt+I2uUY5DBG5cLU1LidMdpFA0l5xbMsorberyNhh8TZYB7b1" crossorigin="anonymous"></script>
132<script src="https://cdn.prod.website-files.com/69c2b9815263da6a49ccf592/js/webflow.a0aa6ca1.2628b82da48d0a28.js" type="text/javascript" integrity="sha384-HdQOnR91f9MludhV34T3CDlKHN4sJtqw3YFQ/owDbEaj0SKsRf7UZHGJ0RF9Sa78" crossorigin="anonymous"></script>
132<!-- International Telephone Input -->
133<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/build/css/intlTelInput.css">
134<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/js/intlTelInput.min.js"></script>
vendor: 1 bytes, line 134
134
135<script>
136  const phoneInputs = document.querySelectorAll(".intl-phone");
137  if (phoneInputs && phoneInputs.length) {
138    console.log('Initializing international phone number inputs...')
139    phoneInputs.forEach((input) => {
140      window.intlTelInput(input, {
141        loadUtils: () => import("https://cdn.jsdelivr.net/npm/[email protected]/build/js/utils.js"),
142        hiddenInput: (telInputName) => ({
143          phone: "phone_full",
144          country: "country_code"
145        }),
146      });
147    })
148  } else {
149    console.warn('No .intl-phone inputs found.')
150  }
151</script>
151
152
153<script>
154  // Modal Scripts
155  const subscribeModal = document.getElementById('subscribe-modal')
156  const subscribeModalOpeners = document.querySelectorAll('[data-open-subscribe]')
157
158  function showModal(modal) {
159    if (modal) modal.classList.remove('hidden')
160  }
161  
162  if (subscribeModal) {
163    subscribeModalOpeners.forEach((opener) => {
164      opener.addEventListener('click', (e) => {
165        e.preventDefault()
166        showModal(subscribeModal)
167      })
168    })
169  }
170  
171  const contactModal = document.getElementById('contact-modal')
172  const contactModalOpeners = document.querySelectorAll('[data-open-contact]')
173  
174  if (contactModal) {
175    contactModalOpeners.forEach((opener) => {
176      opener.addEventListener('click', (e) => {
177        showModal(contactModal)
178      })
179    })
180  }
181
182  const modals = document.querySelectorAll('.modal');
183  console.log('Modals', modals)
184  if (modals && modals.length) {
185    modals.forEach((modal) => {
186      const close = modal.querySelector('.modal__close')
187      const hitbox = modal.querySelector('.modal__hitbox')
188  
189      close.addEventListener('click', () => {
190        modal.classList.add('hidden')
191      })
192      hitbox.addEventListener('click', () => {
193        modal.classList.add('hidden')
194      })
195    })
196  }
197  
198  const params = new URLSearchParams(window.location.search);
199  if (params.has('subscribe')) showModal(subscribeModal);
200  if (params.has('contact')) showModal(contactModal);
201  
202/**
203 * Site-wide: POST /app/api/leads for forms in [data-listid].
204 *
205 * - `[data-listid]` and **no** `[data-subscribe]` (legacy): Community (if phone) → POST `/leads` → .w-form-done / .w-form-fail.
206 * - `[data-listid]` + `[data-subscribe]` **checked**: Community (if phone) → `/leads` → native Webflow submit.
207 * - `[data-listid]` + `[data-subscribe]` **unchecked**: Community (if phone) only — **no** `/leads` (email opt-out) → Webflow submit.
208 * - `data-subscribe` gates **email list** only, not Community SMS.
209 * - No `[data-listid]`: default Webflow only.
210 *
211 * Submit button: while the leads request runs (and before Webflow’s second submit), label comes from
212 * `data-wait` on the button (Webflow default), or “Please wait...”.
213 *
214 * Uses stopPropagation on intercept paths so Webflow doesn’t race the leads call.
215 * Webflow handoff uses `setTimeout(0)` before `requestSubmit()` so it runs outside the capturing submit
216 * stack (fixes first-click no-op on WebKit/Webflow); `checkValidity()` runs first so HTML5 errors surface.
217 *
218 * Mount: one global Code Embed (e.g. site footer or Project-wide custom code before </body>).
219 * API: POST /app/api/leads; optional POST /app/api/community-subscribe when `phone_full` is present
220 * (runs before leads + Webflow). Community Invite/Update Member accepts `given_name`, `surname`,
221 * `city`, and `email` per https://developer.community.com/reference/upsert-member — proxied as-is.
222 * Form fields may still use Webflow names like `firstName` / “First Name”; the embed maps those to `given_name`/`surname` for `/community-subscribe` only (`/leads` keeps `firstName`/`lastName` as today).
223 *
224 * intl-tel-input: Webflow often uses `type="text"` + `.iti__tel-input` (not `type="tel"`). We resolve the
225 * plugin element via `[data-intl-tel-input-id]`, `.iti__tel-input`, or `.iti` + text input, then
226 * `intlTelInput.getInstance(input)` → `await iti.promise` → `isValidNumber()` / `getNumber()` for E.164.
227 * Do not rely on a `phone_full` hidden field being populated before submit.
228 *
229 * **Country code in Webflow / intl-tel-input (site script, not this file):** use plugin options such as
230 * `initialCountry: "us"` (or `"auto"` with `geoIpLookup`), `nationalMode: false` for full international
231 * format, and `strictMode: true` if you want stricter typing. This embed blocks submit when the ITI field
232 * has text but `isValidNumber()` is false (incomplete / wrong country).
233 */
234(function () {
235  var LEADS_URL = "/app/api/leads";
236  var COMMUNITY_URL = "/app/api/community-subscribe";
237  var LOG = "[form-leads]";
238  /** Set on the form while re-dispatching so we don’t intercept the Webflow submit. */
239  var SKIP_FLAG = "__formLeadsSkipIntercept";
240
241  /** Console-safe hint for phone values (last 4 digits only). */
242  function maskPhoneForLog(value) {
243    if (value == null || String(value).trim() === "") return "(empty)";
244    var d = String(value).replace(/\D/g, "");
245    if (d.length <= 4) return "(short)";
246    return "…" + d.slice(-4);
247  }
248  /** Original submit label while showing data-wait / Please wait... */
249  var SUBMIT_LABEL_BACKUP = "__formLeadsSubmitLabelBackup";
250
251  function log() {
252    var a = [LOG];
253    for (var i = 0; i < arguments.length; i++) a.push(arguments[i]);
254    console.log.apply(console, a);
255  }
256
257  function warn() {
258    var a = [LOG];
259    for (var i = 0; i < arguments.length; i++) a.push(arguments[i]);
260    console.warn.apply(console, a);
261  }
262
263  function getListSource(form) {
264    if (!(form instanceof HTMLFormElement)) return null;
265    if (form.hasAttribute("data-listid")) return form;
266    return form.closest("[data-listid]");
267  }
268
269  function getSubscribeCheckbox(form) {
270    if (!(form instanceof HTMLFormElement)) return null;
271    return form.querySelector('input[type="checkbox"][data-subscribe]');
272  }
273
274  function getFormWrapper(form) {
275    return form.closest(".w-form") || form.parentElement;
276  }
277
278  function getMessageElements(form) {
279    var wrap = getFormWrapper(form);
280    if (!wrap) return { success: null, fail: null };
281    return {
282      success: wrap.querySelector(".w-form-done, .wf-form-done"),
283      fail: wrap.querySelector(".w-form-fail, .wf-form-fail"),
284    };
285  }
286
287  function pickField(fd, names) {
288    var i;
289    var k;
290    var v;
291    for (i = 0; i < names.length; i++) {
292      v = fd.get(names[i]);
293      if (v != null && String(v).trim()) return String(v).trim();
294    }
295    for (var pair of fd.entries()) {
296      k = pair[0];
297      v = pair[1];
298      if (
299        v != null &&
300        String(v).trim() &&
301        names.some(function (n) {
302          return n.toLowerCase() === k.toLowerCase();
303        })
304      ) {
305        return String(v).trim();
306      }
307    }
308    return "";
309  }
310
311  /** Webflow inputs often use `data-name="First Name"` while `name` is generic; match label loosely. */
312  function findInputValueByDataName(form, re) {
313    if (!(form instanceof HTMLFormElement)) return "";
314    var els = form.querySelectorAll("[data-name]");
315    var i;
316    var el;
317    var dn;
318    var v;
319    for (i = 0; i < els.length; i++) {
320      el = els[i];
321      dn = el.getAttribute("data-name");
322      if (!dn || !re.test(String(dn).trim())) continue;
323      if ("value" in el && el.value != null) {
324        v = String(el.value).trim();
325        if (v) return v;
326      }
327    }
328    return "";
329  }
330
331  function findEmail(form, fd) {
332    var el = form.querySelector(
333      'input[type="email"], input[name="email"], input[name="Email"]'
334    );
335    if (el && el.value && String(el.value).trim()) return String(el.value).trim();
336    var v = fd.get("email") || fd.get("Email") || fd.get("EMAIL");
337    if (v && String(v).trim()) return String(v).trim();
338    for (var pair of fd.entries()) {
339      if (/email/i.test(pair[0]) && pair[1] && String(pair[1]).trim()) {
340        return String(pair[1]).trim();
341      }
342    }
343    return "";
344  }
345
346  function collectPayload(form, listSource) {
347    var fd = new FormData(form);
348    var raw = listSource.getAttribute("data-listid");
349    var listId;
350    if (raw != null && String(raw).trim() !== "") {
351      var n = parseInt(String(raw).trim(), 10);
352      if (Number.isFinite(n)) listId = n;
353    }
354
355    var firstName =
356      pickField(fd, [
357        "firstName",
358        "first-name",
359        "First-Name",
360        "fname",
361        "FirstName",
362        "given_name",
363        "given-name",
364      ]) ||
365      findInputValueByDataName(form, /^first\s*name$/i) ||
366      findInputValueByDataName(form, /^firstname$/i) ||
367      findInputValueByDataName(form, /^given\s*name$/i);
368    var lastName =
369      pickField(fd, [
370        "lastName",
371        "last-name",
372        "Last-Name",
373        "lname",
374        "LastName",
375        "surname",
376      ]) ||
377      findInputValueByDataName(form, /^last\s*name$/i) ||
378      findInputValueByDataName(form, /^lastname$/i) ||
379      findInputValueByDataName(form, /^surname$/i);
380    var city =
381      pickField(fd, [
382        "city",
383        "City",
384        "town",
385        "Town",
386        "hometown",
387        "HomeTown",
388      ]) ||
389      findInputValueByDataName(form, /^city$/i) ||
390      findInputValueByDataName(form, /^town$/i) ||
391      findInputValueByDataName(form, /^hometown$/i);
392
393    return {
394      email: findEmail(form, fd),
395      firstName: firstName,
396      lastName: lastName,
397      city: city,
398      phone: pickField(fd, ["phone", "Phone", "tel", "telephone"]),
399      phoneFull: pickField(fd, [
400        "phone_full",
401        "phone-full",
402        "Phone_Full",
403        "Phone_full",
404      ]),
405      listId: listId,
406    };
407  }
408
409  /**
410   * The input element intl-tel-input was bound to. Webflow uses `type="text"` + `iti__tel-input`, not
411   * always `type="tel"`.
412   */
413  function findIntlTelInput(form) {
414    if (!(form instanceof HTMLFormElement)) return null;
415    var byPluginAttr = form.querySelector("input[data-intl-tel-input-id]");
416    if (byPluginAttr) return byPluginAttr;
417    var byClass = form.querySelector(
418      "input.iti__tel-input, input.intl-tel-input, input.intl-phone"
419    );
420    if (byClass) return byClass;
421    var wrap = form.querySelector(".iti");
422    if (wrap) {
423      var tel = wrap.querySelector('input[type="tel"]');
424      if (tel) return tel;
425      var itiText = wrap.querySelector(
426        "input.iti__tel-input, input.intl-tel-input, input.intl-phone"
427      );
428      if (itiText) return itiText;
429      var textTel = wrap.querySelector('input[type="text"][inputmode="tel"]');
430      if (textTel) return textTel;
431    }
432    return form.querySelector('input[type="tel"]');
433  }
434
435  function getIntlTelInstance(input) {
436    if (!input || typeof window.intlTelInput === "undefined") return null;
437    var g = window.intlTelInput;
438    if (typeof g.getInstance !== "function") return null;
439    try {
440      return g.getInstance(input);
441    } catch (e) {
442      return null;
443    }
444  }
445
446  /**
447   * Fills `payload.phoneFull` from intl-tel-input when present (requires utils: `iti.promise` first).
448   * If the instance exists but `isValidNumber()` is false, clears `phone_full` for Community.
449   * Sets `payload._intlTelMeta` when ITI is present: `{ hasInstance, isEmpty, isValid }` for submit validation.
450   */
451  async function mergePhoneFullFromIntlTel(form, payload) {
452    log("intl-tel: mergePhoneFullFromIntlTel start");
453    var input = findIntlTelInput(form);
454    if (!input) {
455      log("intl-tel: no intl-tel input found — using FormData phone_full only");
456      return;
457    }
458    if (typeof window.intlTelInput === "undefined") {
459      log("intl-tel: window.intlTelInput missing — skip plugin merge");
460      return;
461    }
462    var iti = getIntlTelInstance(input);
463    if (!iti) {
464      log("intl-tel: getInstance returned null — using FormData phone_full only");
465      return;
466    }
467
468    try {
469      if (iti.promise && typeof iti.promise.then === "function") {
470        log("intl-tel: awaiting iti.promise (utils)");
471        await iti.promise;
472        log("intl-tel: utils ready");
473      }
474    } catch (e) {
475      warn("intl-tel: utils failed to load", e);
476      return;
477    }
478
479    var rawVal = String(input.value || "").trim();
480    var isEmpty = rawVal === "";
481    var countryData =
482      typeof iti.getSelectedCountryData === "function"
483        ? iti.getSelectedCountryData()
484        : null;
485    if (!isEmpty && !countryData) {
486      payload._intlTelMeta = {
487        hasInstance: true,
488        isEmpty: false,
489        isValid: false,
490      };
491      log("intl-tel: digits entered but no country — clear phone_full, will validate");
492      payload.phoneFull = "";
493      return;
494    }
495
496    try {
497      if (typeof iti.isValidNumber !== "function" || typeof iti.getNumber !== "function") {
498        log("intl-tel: isValidNumber/getNumber not available — skip");
499        payload._intlTelMeta = {
500          hasInstance: true,
501          isEmpty: isEmpty,
502          isValid: false,
503        };
504        return;
505      }
506      if (!iti.isValidNumber()) {
507        payload._intlTelMeta = {
508          hasInstance: true,
509          isEmpty: isEmpty,
510          isValid: false,
511        };
512        log("intl-tel: not valid — clear phone_full for Community", {
513          masked: maskPhoneForLog(payload.phoneFull),
514          isEmpty: isEmpty,
515        });
516        payload.phoneFull = "";
517        return;
518      }
519      var num = iti.getNumber();
520      if (num && String(num).trim()) {
521        payload.phoneFull = String(num).trim();
522        log("intl-tel: phone_full set from getNumber", maskPhoneForLog(payload.phoneFull));
523        if (!payload.phone || !String(payload.phone).trim()) {
524          payload.phone = payload.phoneFull;
525        }
526      }
527      payload._intlTelMeta = {
528        hasInstance: true,
529        isEmpty: isEmpty,
530        isValid: true,
531      };
532    } catch (e) {
533      warn("intl-tel: isValidNumber/getNumber failed", e);
534      payload._intlTelMeta = {
535        hasInstance: true,
536        isEmpty: isEmpty,
537        isValid: false,
538      };
539    }
540  }
541
542  /** True when ITI is present, user typed something, and the number is not valid (incomplete / wrong country). */
543  function shouldAbortForInvalidIntlPhone(payload) {
544    var m = payload._intlTelMeta;
545    return !!(m && m.hasInstance && !m.isEmpty && !m.isValid);
546  }
547
548  /** Focus phone, optional country dropdown, and native validation message. */
549  function flagInvalidIntlPhone(form) {
550    var input = findIntlTelInput(form);
551    if (!input) return;
552    input.focus();
553    var iti = getIntlTelInstance(input);
554    if (iti && typeof iti.openDropdown === "function") {
555      try {
556        iti.openDropdown();
557      } catch (e) {
558        /* ignore */
559      }
560    }
561    var msg =
562      "Enter a valid phone number including country code (or clear the field).";
563    if (typeof input.setCustomValidity === "function") {
564      input.setCustomValidity(msg);
565      input.reportValidity();
566      var clear = function () {
567        input.setCustomValidity("");
568        input.removeEventListener("input", clear);
569        input.removeEventListener("change", clear);
570      };
571      input.addEventListener("input", clear);
572      input.addEventListener("change", clear);
573    }
574  }
575
576  function hasCommunityPhone(payload) {
577    return (
578      payload.phoneFull != null &&
579      String(payload.phoneFull).trim() !== ""
580    );
581  }
582
583  /** Best-effort; failures are logged and the rest of the flow continues. */
584  async function postCommunitySubscribe(payload) {
585    log("community: POST start", COMMUNITY_URL, {
586      phone: maskPhoneForLog(payload.phoneFull),
587      hasEmail: !!payload.email,
588      hasGivenName: !!payload.firstName,
589      hasSurname: !!payload.lastName,
590      hasCity: !!payload.city,
591    });
592    try {
593      var body = {
594        phone_full: String(payload.phoneFull).trim(),
595      };
596      var em = payload.email != null && String(payload.email).trim();
597      if (em) body.email = String(em);
598      var gn = payload.firstName != null && String(payload.firstName).trim();
599      if (gn) body.given_name = String(gn);
600      var sn = payload.lastName != null && String(payload.lastName).trim();
601      if (sn) body.surname = String(sn);
602      var ct = payload.city != null && String(payload.city).trim();
603      if (ct) body.city = String(ct);
604
605      var res = await fetch(COMMUNITY_URL, {
606        method: "POST",
607        headers: {
608          "Content-Type": "application/json",
609          Accept: "application/json",
610        },
611        body: JSON.stringify(body),
612      });
613      var ctext = await res.text();
614      log("community: response", res.status, res.statusText, "bodyLen", ctext.length);
615      if (!res.ok) {
616        warn("community: error (continuing flow)", ctext.slice(0, 800));
617      } else if (ctext) {
618        log("community: body preview", ctext.slice(0, 500));
619      } else {
620        log("community: ok, empty body");
621      }
622    } catch (err) {
623      warn("community: fetch failed (continuing flow)", err);
624    }
625  }
626
627  function getWaitText(submitBtn) {
628    if (!submitBtn) return "Please wait...";
629    var w = submitBtn.getAttribute("data-wait");
630    if (w != null && String(w).trim() !== "") return String(w).trim();
631    return "Please wait...";
632  }
633
634  function isInputSubmit(el) {
635    return el.tagName === "INPUT" && el.type === "submit";
636  }
637
638  function getSubmitLabel(submitBtn) {
639    if (isInputSubmit(submitBtn)) return submitBtn.value;
640    return submitBtn.textContent || "";
641  }
642
643  function setSubmitLabel(submitBtn, text) {
644    if (isInputSubmit(submitBtn)) submitBtn.value = text;
645    else submitBtn.textContent = text;
646  }
647
648  /** Webflow-style: show data-wait (or “Please wait...”) and disable while our work runs. */
649  function applySubmitWaitState(submitBtn) {
650    if (!submitBtn) {
651      log("ui: applySubmitWaitState — no submit button");
652      return;
653    }
654    log("ui: submit wait state (data-wait / Please wait…)");
655    submitBtn[SUBMIT_LABEL_BACKUP] = getSubmitLabel(submitBtn);
656    setSubmitLabel(submitBtn, getWaitText(submitBtn));
657    submitBtn.disabled = true;
658  }
659
660  function restoreSubmitButton(submitBtn) {
661    if (!submitBtn) return;
662    log("ui: restore submit button");
663    if (submitBtn[SUBMIT_LABEL_BACKUP] !== undefined) {
664      setSubmitLabel(submitBtn, submitBtn[SUBMIT_LABEL_BACKUP]);
665      delete submitBtn[SUBMIT_LABEL_BACKUP];
666    }
667    submitBtn.disabled = false;
668  }
669
670  /** Restore label + enable, then native submit on the next macrotask (outside submit-handler stack). */
671  function handOffToWebflowSubmit(form, submitBtn) {
672    log("flow: schedule native Webflow submit (next task)");
673    submitBtn =
674      submitBtn ||
675      form.querySelector(
676        'input[type="submit"], button[type="submit"], button:not([type])'
677      );
678    setTimeout(function () {
679      if (submitBtn) {
680        restoreSubmitButton(submitBtn);
681      }
682      if (!form.checkValidity()) {
683        warn(
684          "webflow: handoff aborted — HTML5 validation failed (fix highlighted fields and retry)"
685        );
686        form.reportValidity();
687        return;
688      }
689      submitWebflowNative(form, submitBtn);
690    }, 0);
691  }
692
693  function showFormState(form, state) {
694    var messages = getMessageElements(form);
695    var success = messages.success;
696    var fail = messages.fail;
697
698    log("UI state:", state, {
699      hasSuccessEl: !!success,
700      hasFailEl: !!fail,
701    });
702
703    if (state === "success") {
704      form.style.display = "none";
705    } else {
706      form.style.display = "";
707    }
708
709    if (success) {
710      success.style.display = state === "success" ? "block" : "none";
711      success.hidden = state !== "success";
712    }
713    if (fail) {
714      fail.style.display = state === "error" ? "block" : "none";
715      fail.hidden = state !== "error";
716    }
717  }
718
719  /**
720   * Second-phase submit after handoff. `requestSubmit` throws if HTML5 validation fails — clear SKIP_FLAG
721   * and restore the button so the user is not stuck on “Please wait…”.
722   */
723  function submitWebflowNative(form, submitBtn) {
724    submitBtn =
725      submitBtn ||
726      form.querySelector(
727        'input[type="submit"], button[type="submit"], button:not([type])'
728      );
729    form[SKIP_FLAG] = true;
730    try {
731      if (typeof form.requestSubmit === "function") {
732        log("webflow: requestSubmit()");
733        form.requestSubmit(submitBtn || undefined);
734      } else {
735        log("webflow: form.submit() fallback");
736        form.submit();
737      }
738    } catch (err) {
739      delete form[SKIP_FLAG];
740      warn(
741        "webflow: requestSubmit did not run (validation or browser) — restored submit",
742        err
743      );
744      if (submitBtn) {
745        restoreSubmitButton(submitBtn);
746      }
747    }
748  }
749
750  async function handleSubmit(e) {
751    var form = e.target;
752    if (!(form instanceof HTMLFormElement)) {
753      return;
754    }
755
756    if (form[SKIP_FLAG]) {
757      log("event: skip intercept — second pass after handoff (Webflow native)");
758      delete form[SKIP_FLAG];
759      return;
760    }
761
762    log("event: submit", { formId: form.id || "(no id)" });
763
764    var subscribeCb = getSubscribeCheckbox(form);
765    var hasSubscribeCheckbox = !!subscribeCb;
766    var subscribeChecked = !!(subscribeCb && subscribeCb.checked);
767    /** After our work, use native Webflow submit + Webflow UI (any form with data-subscribe). */
768    var useWebflowHandoff = hasSubscribeCheckbox;
769    /** POST /leads only when there is no email opt-out checkbox, or it is checked. */
770    var shouldPostLeads = !hasSubscribeCheckbox || subscribeChecked;
771
772    var listSource = getListSource(form);
773    if (!listSource) {
774      log("decision: no [data-listid] — pass through to Webflow only");
775      return;
776    }
777
778    e.preventDefault();
779    e.stopPropagation();
780    e.stopImmediatePropagation();
781
782    log("intercept", {
783      mode: useWebflowHandoff ? "Webflow handoff" : "leads + embedded success UI",
784      formAction: form.getAttribute("action"),
785      formId: form.id || "(no id)",
786      dataListid: listSource.getAttribute("data-listid"),
787      hasSubscribeCheckbox: hasSubscribeCheckbox,
788      subscribeChecked: hasSubscribeCheckbox ? subscribeChecked : "(n/a)",
789      shouldPostLeads: shouldPostLeads,
790    });
791
792    var payload = collectPayload(form, listSource);
793    await mergePhoneFullFromIntlTel(form, payload);
794    log("payload after intl merge", {
795      email: payload.email ? "(present)" : "(missing)",
796      listId: payload.listId,
797      phone: maskPhoneForLog(payload.phone),
798      phoneFull: maskPhoneForLog(payload.phoneFull),
799      intlTelMeta: payload._intlTelMeta || "(none)",
800    });
801
802    if (shouldAbortForInvalidIntlPhone(payload)) {
803      warn("validation: phone incomplete or invalid — fix or clear before submit");
804      flagInvalidIntlPhone(form);
805      showFormState(form, "error");
806      return;
807    }
808
809    var submitBtn = form.querySelector(
810      'input[type="submit"], button[type="submit"], button:not([type])'
811    );
812
813    applySubmitWaitState(submitBtn);
814
815    try {
816      if (hasCommunityPhone(payload)) {
817        log("step: Community (phone_full present)");
818        await postCommunitySubscribe(payload);
819      } else {
820        log("step: skip Community — no phone_full");
821      }
822
823      if (!payload.email) {
824        warn("validation: no email");
825        if (useWebflowHandoff) {
826          log("flow: no email — skip leads, Webflow only");
827          handOffToWebflowSubmit(form, submitBtn);
828        } else {
829          log("flow: no email — show error (leads only)");
830          showFormState(form, "error");
831        }
832        return;
833      }
834
835      if (!shouldPostLeads) {
836        log("flow: email list opt-out — skip /leads, Webflow only");
837        handOffToWebflowSubmit(form, submitBtn);
838        return;
839      }
840
841      log("step: ActiveCampaign /leads");
842      var body = { email: payload.email };
843      if (payload.firstName) body.firstName = payload.firstName;
844      if (payload.lastName) body.lastName = payload.lastName;
845      if (payload.phone) body.phone = payload.phone;
846      if (payload.city) body.city = payload.city;
847      if (payload.listId !== undefined) body.listId = payload.listId;
848
849      log("leads: POST", LEADS_URL, {
850        hasListId: body.listId !== undefined,
851        hasPhone: !!body.phone,
852        hasCity: !!body.city,
853      });
854
855      var res = await fetch(LEADS_URL, {
856        method: "POST",
857        headers: {
858          "Content-Type": "application/json",
859          Accept: "application/json",
860        },
861        body: JSON.stringify(body),
862      });
863
864      log("leads: response", res.status, res.statusText, res.url);
865
866      if (useWebflowHandoff) {
867        if (res.ok) {
868          log("leads: ok — then Webflow");
869          try {
870            var okJson = await res.json();
871            if (okJson) log("leads: body", okJson);
872          } catch (ignore) {}
873        } else {
874          var errTextWf = await res.text();
875          warn("leads: error (Webflow will still submit)", errTextWf.slice(0, 800));
876        }
877        handOffToWebflowSubmit(form, submitBtn);
878      } else {
879        if (res.ok) {
880          try {
881            var okJson2 = await res.json();
882            if (okJson2) log("leads: body", okJson2);
883          } catch (ignore) {}
884          log("flow: leads success — showFormState success");
885          showFormState(form, "success");
886        } else {
887          var errText = await res.text();
888          warn("leads: error body", errText.slice(0, 800));
889          log("flow: leads error — showFormState error");
890          showFormState(form, "error");
891        }
892      }
893    } catch (err) {
894      warn("leads: fetch threw", err);
895      if (useWebflowHandoff) {
896        log("flow: after leads throw — hand off to Webflow");
897        handOffToWebflowSubmit(form, submitBtn);
898      } else {
899        log("flow: after leads throw — showFormState error");
900        showFormState(form, "error");
901      }
902    } finally {
903      if (submitBtn && !useWebflowHandoff) {
904        log("finally: restore submit (legacy leads-only path)");
905        restoreSubmitButton(submitBtn);
906      }
907    }
908  }
909
910  log(
911    "initialized — [data-listid]: Community if phone; /leads when email opt-in; data-subscribe = email only"
912  );
913  document.addEventListener("submit", handleSubmit, true);
914})();
915</script>
915</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.