PageSourceSearch

https://greenspacehealth.com/en-us/wp-content/themes/greenspace/js/custom-script.js?ver=2031810131

js greenspacehealth.com collected 2026-09-26 00:50:19 UTC 45,644 bytes, 1,370 lines download raw bytes

1jQuery(function () {
2  jQuery(".member-image img").on("click", function () {
3    jQuery(this).siblings(".member-overlay").removeClass("hide_active");
4  });
5  jQuery(".member-close-btn").on("click", function (event) {
6    event.preventDefault();
7    jQuery(".member-overlay").removeClass("hide_active");
8    jQuery(this).parent(".member-overlay").addClass("hide_active");
9  });
10  jQuery('#field_241vs2').on('change', function () {
11    if (this.value == 'Person Seeking Care') {
12      jQuery("#frm_field_117_container").show();
13    }
14    else {
15      jQuery("#frm_field_117_container").hide();
16    }
17  });
18});
19
20
21let isMixpanelEnabled = false;
22document.addEventListener('onMixpanelReady', () => {
23  isMixpanelEnabled = true;
24  trackEvent('mixpanel_register');
25  trackEvent('mixpanel_page_load');
26});
27
28const isFacebookEnabled = typeof fbq !== 'undefined';
29const isGtagEnabled = typeof gtag !== 'undefined';
30
31const DATACENTER_COUNTRY = "us";
32
33const EVENTS = {
34  'gtag_open_demo_form': 'open_demo_form',
35  'gtag_submit_demo_request': 'submit_demo_request',
36  'gtag_adwords': 'config',
37  'fbq_lead': 'Lead',
38  'fbq_view_content': 'ViewContent',
39  'lintrk': '4752924',
40  'mixpanel_demo': 'Request Demo',
41  'mixpanel_page_load': 'Page Load',
42  'mixpanel_register': 'Register'
43}
44// Register
45var mixpanelSuperProps = {
46  'datacenter_country': DATACENTER_COUNTRY,
47  'site_slug': 'default'
48};
49
50// Track
51var safeUrl = window.location.pathname;
52var urlName = window.urlName || "null";
53var mixpanelEventProps = {
54  'url': safeUrl,
55  'url_name': urlName,
56  'language': 'en-ca',
57}
58
59// {/* <!-- Google Adwords --> */}
60const adwordsId = 'AW-873369729';
61
62// <!-- Linkeding Tracking - Insight Tag  -->
63const _linkedin_partner_id = "3225844";
64window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
65window._linkedin_data_partner_ids.push(_linkedin_partner_id);
66
67(function (l) {
68  if (!l) {
69    window.lintrk = function (a, b) { window.lintrk.q.push([a, b]) };
70    window.lintrk.q = []
71  }
72  var s = document.getElementsByTagName("script")[0];
73  var b = document.createElement("script");
74  b.type = "text/javascript"; b.async = true;
75  b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
76  s.parentNode.insertBefore(b, s);
77})(window.lintrk);
78
79
80function trackEvent(eventName) {
81  const event = EVENTS[eventName];
82  //Facebook Trackers
83  if (isFacebookEnabled && (eventName === 'fbq_lead' || eventName === 'fbq_view_content')) {
84    fbq('track', event);
85  }
86  // Google Trackers
87  if (isGtagEnabled && eventName === 'gtag_adwords') {
88    gtag('config', adwordsId);
89  }
90  if (isGtagEnabled && (eventName === 'gtag_submit_demo_request' || eventName === 'gtag_open_demo_form')) {
91    gtag('event', event, {
92      'event_category': 'engagement'
93    });
94  }
95  // Mixpanel Trackers
96  if (isMixpanelEnabled && eventName === 'mixpanel_register') {
97    mixpanel.register(mixpanelSuperProps);
98  }
99  if (isMixpanelEnabled && eventName === 'mixpanel_page_load') {
100    mixpanel.track(event, mixpanelEventProps);
101  }
102  if (isMixpanelEnabled && eventName === 'mixpanel_demo') {
103    mixpanel.track(event, { 'source': window.requestSource || window.urlName });
104  }
105  // Lintrk
106  if (eventName === 'lintrk') {
107    window.lintrk('track', { conversion_id: event });
108  }
109}
110
111function trackOnDemoRequestSubmission() {
112  // alert('trackOnDemoRequestSubmission');
113  trackEvent('gtag_submit_demo_request');
114  trackEvent('mixpanel_demo');
115  trackEvent('fbq_lead');
116  trackEvent('lintrk');
117}
118
119// onPageLoad
120trackEvent('gtag_adwords');
121
122
123
124// // {/* // Track Request Demo event */}
125// jQuery('#book-a-demo form').on('submit', function () {
126//   trackOnDemoRequestSubmission();
127// });
128
129// // {/* // Track Contact Us form submission event */}
130// jQuery('#form_contact-form').on('submit', function() {
131//   trackOnDemoRequestSubmission();
132// });
133
134// Track open demo request Modal
135jQuery("a:contains('Request a Demo'), a:contains('Book a Demo')").on('click', function () {
136  trackEvent('gtab_open_demo_form');
137});
138
139// {/* <!-- Request Demo Modal --> */}
140jQuery('#book-a-demo .frm_button_submit').on('click', function () {
141  trackEvent('fbq_view_content');
142  trackEvent('lintrk');
143});
144
145/*jQuery(document).ready(function(){
146  jQuery(window).on("load", function(){
147    var urlHash = window.location.href.split("#")[1];
148    //var height = jQuery("#header").outerHeight(true);
149    jQuery('html,body').animate({
150      scrollTop: jQuery('.' + urlHash).offset().top - 240
151    }, 1000);
152  });
153});*/
154
155window.addEventListener('DOMContentLoaded', (event) => {
156  let notification_time = (Number(notification.start_time) + Number(notification.close_time)) * 1000
157  setTimeout(function () {
158    if (notification.notification_id) {
159      jQuery.cookie(notification.notification_id, 'yes', { expires: 730, path: '/' });
160    }
161    else {
162      jQuery.cookie("greenspace_footer_bar5", 'yes', { expires: 730, path: '/' });
163    }
164
165    jQuery('#notification').hide();
166    jQuery("#notification").css("display", "none");
167  }, notification_time);
168});
169jQuery(document).ready(function () {
170  jQuery(document).on("click", ".share-video", function () {
171    let parent = jQuery(this).parent(".social-share");
172    parent.toggleClass("show");
173  })
174  jQuery(document).on("focusout", ".social-share", function () {
175
176    setTimeout(() => {
177      jQuery(this).removeClass("show");
178    }, 1500);
179  })
180  jQuery(document).on("click", ".social-share ul li:first-child a", function (e) {
181    e.preventDefault();
182    navigator.clipboard.writeText(jQuery(this).attr("href"));
183    let text = jQuery(this).find(".text").html();
184    jQuery(this).find(".text").html("Copied");
185    jQuery(this).addClass("copied");
186    setTimeout(() => {
187      jQuery(this).find(".text").html(text);
188      jQuery(this).removeClass("copied");
189      jQuery("body .social-share").removeClass("show");
190    }, 2000);
191  })
192  jQuery(".y-video-popup .close").on("click", function () {
193    jQuery(".y-video-popup").removeClass("show");
194
195  })
196
197
198  const btn = document.querySelector('.share-video');
199
200  jQuery(document).on("click", ".share-video", async (e) => {
201    let title = e.currentTarget.getAttribute("data-title");
202    let url = e.currentTarget.getAttribute("data-url");
203
204    const shareData = {
205      title: "",
206      text: "",
207      url: url
208    }
209    if (navigator.userAgent.match(/Android/i)
210      || navigator.userAgent.match(/webOS/i)
211      || navigator.userAgent.match(/iPhone/i)
212      || navigator.userAgent.match(/iPad/i)
213      || navigator.userAgent.match(/iPod/i)
214      || navigator.userAgent.match(/BlackBerry/i)
215      || navigator.userAgent.match(/Windows Phone/i)) {
216      try {
217        await navigator.share(shareData);
218      } catch (err) {
219        console.log(`Error: ${err}`);
220      }
221    }
222  });
223
224})
225
226jQuery(".popup-youtube-xx").on("click", function () {
227  let parentModal = jQuery(this).attr("href");
228  let ysrc = jQuery(this).attr("data-src");
229  jQuery(parentModal).find("iframe").attr("src",ysrc)
230})
231
232jQuery(".last-updated a").on("mousemove", function (event)
233{
234    var cursorX, cursorY;
235    if (event.type === 'mousemove') {
236        cursorX = event.clientX; 
237        cursorY = event.clientY; 
238      }
239    if (jQuery(window).width() >= 767)
240    {
241        jQuery(".tooltp").css("left", cursorX - jQuery(".tooltp").width() / 2 + "px")
242        jQuery(".tooltp").css("top",cursorY-jQuery(".tooltp").height()-40+"px")
243    }
244  
245  
246})
247jQuery(".last-updated a").on("mouseenter", function (e)
248{
249  jQuery(".tooltp").addClass("show")
250})
251jQuery(".last-updated a").on("mouseleave", function (e)
252{
253  jQuery(".tooltp").removeClass("show")
254})
255jQuery(".last-updated a").on("click", function (e) {
256    e.preventDefault();
257})
258jQuery(window).on("scroll", function () {
259    jQuery(".tooltp").removeClass("show")
260})
261jQuery(".last-updated a").on("click", function (event)
262{
263    jQuery(".tooltp").addClass("show")
264})
265jQuery(".tooltp .close").on("click", function (event)
266{
267    jQuery(".tooltp").removeClass("show")
268})
269
270function initializeRecaptcha() {
271  var recaptchaElements = document.querySelectorAll('.g-recaptcha-x');
272  let i = 0;
273  recaptchaElements.forEach(element => {
274      grecaptcha.ready(function () {
275          i++;
276          grecaptcha.execute(jQuery(element).attr('data-sitekey'), { action: 'submit' + i }).then(function(token) {
277              document.getElementById('g-recaptcha-response' + i).value = token;
278          });
279      });
280      
281  });
282
283}
284
285jQuery(document).ready(function ($) {
286  
287  // $('.frm_pro_form').submit(function (e) {
288  //     var form = $(this);
289  //     e.preventDefault();
290  //     var recaptchaResponse = document.querySelector("#"+form.attr("id")+" .g-recaptcha-response").value;
291  //     if (recaptchaResponse.length === 0) {
292  //         form.find(".frm_captcha_error").html('Please complete the reCAPTCHA.');
293  //         return false;
294  //     }
295  //     else {
296  //         $(".frm_captcha_error").html('');
297  //     }
298
299  //     var formData = $(this).serialize();
300
301  //     $.ajax({
302  //         type: 'POST',
303  //         url: frm_js.ajax_url, 
304  //         data: {
305  //             action:'reCaptcha_verifiction', //this value is first parameter of add_action
306  //             formData: formData
307  //         },
308  //         success: function (response) {
309  //             console.log("response",response,"response")
310  //             if (response == true)
311  //             {
312  //                 console.log(response)
313  //                 // form.submit();    
314  //             }
315  //             else {
316  //                 form.find(".frm_captcha_error").html('reCAPTCHA verification failed.');
317  //                 return false;
318  //             }
319  //         }
320  //     });
321  // });
322});
323// jQuery(window).load(function() {
324//   setTimeout(() => {
325//       renderRecaptcha();
326//   }, 2000);
327// });
328// jQuery(document).ready(function () {
329//   jQuery("form").on("click",function(){
330//     renderRecaptcha();
331// })
332// })
333if (document.querySelector(".proven-practice-btn") != null) {
334  document.querySelector(".proven-practice-btn").addEventListener("click", function () {
335    let src = document.querySelector(".proven-practice-video-container iframe").getAttribute("data-src");
336    document.querySelector(".proven-practice-video-container iframe").setAttribute("src", src)
337  })
338}
339jQuery(document).ready(function(){
340   document.querySelectorAll('.new-testimonial .swiper').forEach(swiperEl => {
341    const slides = swiperEl.querySelectorAll('.swiper-slide');
342    const slideCount = slides.length;
343  
344    const centered = slideCount === 1 || slideCount > 3;
345  
346    new Swiper(swiperEl, {
347      slidesPerView: 1.455,
348      spaceBetween: 42,
349      centeredSlides: centered,
350      loop: true,
351      pagination: {
352        el: swiperEl.querySelector('.swiper-pagination'),
353        clickable: true,
354        renderBullet: (index, className) => '<span class="' + className + '"></span>'
355      },
356      navigation: {
357        nextEl: swiperEl.querySelector('.swiper-button-next'),
358        prevEl: swiperEl.querySelector('.swiper-button-prev')
359      },
360      breakpoints: {
361        320: { slidesPerView: 1, spaceBetween: 20 },
362        480: { slidesPerView: 1, spaceBetween: 30 },
363        640: { slidesPerView: 1, spaceBetween: 40 },
364        1280: { slidesPerView: 1.455, spaceBetween: 42 }
365      }
366    });
367  });
368
369  const swiper = new Swiper('.testimonial-slider-video .swiper', {
370    slidesPerView: 1,
371    spaceBetween: 42,
372    loop: true,
373    centeredSlides: true,
374    pagination: {
375      el: '.swiper-pagination',
376      clickable: true,
377    },
378    navigation: {
379      nextEl: '.swiper-button-next',
380      prevEl: '.swiper-button-prev',
381    },
382    breakpoints: {
383      768: {
384        slidesPerView: 2,
385      },
386      1024: {
387        slidesPerView: 2.9,
388      }
389    },
390    on: {
391      slideChangeTransitionEnd: function () {
392        autoplayActiveSlideVideo(this);
393      },
394    }
395  });
396
397  document.querySelectorAll('.testimonial-slider-video video').forEach(video => {
398    video.muted = true; // Mute video by default
399
400    const videoCard = video.closest('.video-card');
401    if (videoCard) {
402      const muteBtnImg = videoCard.querySelector('.mute-button img');
403      if (muteBtnImg) {
404        muteBtnImg.src = 'https://staging.grnspace.com/en-us/wp-content/uploads/sites/2/2025/05/Volume.svg'; // muted icon URL
405        muteBtnImg.alt = 'Muted';
406      }
407    }
408  });
409  // Observe when the testimonial section is in view
410  const videoSection = document.querySelector('.testimonial-slider-video');
411  let wasVisible = false; // track previous visibility
412  
413  if (videoSection) {
414    const observer = new IntersectionObserver((entries) => {
415      entries.forEach(entry => {
416        const isVisibleEnough = entry.intersectionRatio >= 0.6;
417  
418        if (isVisibleEnough && !wasVisible) {
419          wasVisible = true;
420          autoplayActiveSlideVideo(swiper);
421        }
422        //  else if (!isVisibleEnough && wasVisible) {
423        //   wasVisible = false;
424  
425        //   // Pause all videos & reset buttons
426        //   jQuery('.testimonial-slider-video .video-card').each(function () {
427        //     const video = this.querySelector('video');
428        //     const playButton = this.querySelector('.play-button');
429  
430        //     if (video) video.pause();
431  
432        //     if (playButton) {
433        //       playButton.innerHTML = `
434        //         <svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
435        //           <path d="M16.5172 10.0157C16.5178 10.2705 16.4525 10.5211 16.3276 10.7432C16.2027 10.9652 16.0224 11.1512 15.8043 11.283L2.28927 19.5507C2.06141 19.6902 1.80043 19.7664 1.5333 19.7713C1.26616 19.7763 1.00254 19.7098 0.769671 19.5788C0.53902 19.4499 0.346881 19.2618 0.213014 19.034C0.0791461 18.8061 0.008381 18.5467 0.00799561 18.2825V1.74888C0.008381 1.48462 0.0791461 1.22524 0.213014 0.9974C0.346881 0.769561 0.53902 0.581491 0.769671 0.452529C1.00254 0.321532 1.26616 0.255076 1.5333 0.260023C1.80043 0.26497 2.06141 0.341141 2.28927 0.48067L15.8043 8.74841C16.0224 8.88018 16.2027 9.06614 16.3276 9.28821C16.4525 9.51027 16.5178 9.76089 16.5172 10.0157Z" fill="#147945"/>
436        //         </svg>
437        //       `;
438        //     }
439        //   });
440        // }
441      });
442    }, { threshold: [0, 0.6, 1] });
443  
444    observer.observe(videoSection);
445  }
446  
447
448})
449// new code
450
451let isVideoMuted = true; // Default mute state
452
453
454function autoplayActiveSlideVideo(swiperInstance) {
455  document.querySelectorAll('.testimonial-slider-video .video-card').forEach(card => {
456    const video = card.querySelector('video');
457    const playButton = card.querySelector('.play-button');
458    const muteBtnImg = card.querySelector('.mute-button img');
459
460    if (video) {
461      video.pause();
462      video.currentTime = 0;
463
464      if (playButton) {
465        playButton.innerHTML = `
466          <svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
467            <path d="M16.5172 10.0157C16.5178 10.2705 16.4525 10.5211 16.3276 10.7432C16.2027 10.9652 16.0224 11.1512 15.8043 11.283L2.28927 19.5507C2.06141 19.6902 1.80043 19.7664 1.5333 19.7713C1.26616 19.7763 1.00254 19.7098 0.769671 19.5788C0.53902 19.4499 0.346881 19.2618 0.213014 19.034C0.0791461 18.8061 0.008381 18.5467 0.00799561 18.2825V1.74888C0.008381 1.48462 0.0791461 1.22524 0.213014 0.9974C0.346881 0.769561 0.53902 0.581491 0.769671 0.452529C1.00254 0.321532 1.26616 0.255076 1.5333 0.260023C1.80043 0.26497 2.06141 0.341141 2.28927 0.48067L15.8043 8.74841C16.0224 8.88018 16.2027 9.06614 16.3276 9.28821C16.4525 9.51027 16.5178 9.76089 16.5172 10.0157Z" fill="#147945"/>
468          </svg>
469        `;
470      }
471
472     
473video.muted = isVideoMuted;
474if (muteBtnImg) {
475  if (isVideoMuted) {
476    muteBtnImg.src = 'https://staging.grnspace.com/en-us/wp-content/uploads/sites/2/2025/05/Volume.svg';
477    muteBtnImg.alt = 'Muted';
478  } else {
479    muteBtnImg.src = 'https://staging.grnspace.com/wp-content/uploads/2025/05/volume-button-video.svg';
480    muteBtnImg.alt = 'Unmuted';
481  }
482}
483
484    }
485  });
486
487  // Play video in active slide (but keep muted)
488  const activeSlide = swiperInstance.slides[swiperInstance.activeIndex];
489  if (!activeSlide) return;
490
491  const video = activeSlide.querySelector('video');
492  const videoCard = video?.closest('.video-card');
493
494  if (video && videoCard) {
495    video.play().then(() => {
496      const playButton = videoCard.querySelector('.play-button');
497      const thumbnail = videoCard.querySelector('.video-thumbnail');
498
499      if (thumbnail) {
500        thumbnail.style.display = 'none';
501      }
502
503      // Update to pause icon
504      if (playButton) {
505        playButton.innerHTML = `
506          <svg width="224" height="352" viewBox="0 0 224 352" fill="none" xmlns="http://www.w3.org/2000/svg">
507            <path d="M64 352H16C11.7565 352 7.68688 350.314 4.68629 347.314C1.68571 344.313 0 340.243 0 336V16C0 11.7565 1.68571 7.68688 4.68629 4.68629C7.68688 1.68571 11.7565 0 16 0H64C68.2435 0 72.3131 1.68571 75.3137 4.68629C78.3143 7.68688 80 11.7565 80 16V336C80 340.243 78.3143 344.313 75.3137 347.314C72.3131 350.314 68.2435 352 64 352ZM208 352H160C155.757 352 151.687 350.314 148.686 347.314C145.686 344.313 144 340.243 144 336V16C144 11.7565 145.686 7.68688 148.686 4.68629C151.687 1.68571 155.757 0 160 0H208C212.243 0 216.313 1.68571 219.314 4.68629C222.314 7.68688 224 11.7565 224 16V336C224 340.243 222.314 344.313 219.314 347.314C216.313 350.314 212.243 352 208 352Z" fill="#147945"/>
508          </svg>
509        `;
510      }
511
512      video.addEventListener('ended', () => {
513        if (thumbnail) thumbnail.style.display = 'block';
514
515        if (playButton) {
516          playButton.innerHTML = `
517            <svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
518              <path d="M16.5172 10.0157C16.5178 10.2705 16.4525 10.5211 16.3276 10.7432C16.2027 10.9652 16.0224 11.1512 15.8043 11.283L2.28927 19.5507C2.06141 19.6902 1.80043 19.7664 1.5333 19.7713C1.26616 19.7763 1.00254 19.7098 0.769671 19.5788C0.53902 19.4499 0.346881 19.2618 0.213014 19.034C0.0791461 18.8061 0.008381 18.5467 0.00799561 18.2825V1.74888C0.008381 1.48462 0.0791461 1.22524 0.213014 0.9974C0.346881 0.769561 0.53902 0.581491 0.769671 0.452529C1.00254 0.321532 1.26616 0.255076 1.5333 0.260023C1.80043 0.26497 2.06141 0.341141 2.28927 0.48067L15.8043 8.74841C16.0224 8.88018 16.2027 9.06614 16.3276 9.28821C16.4525 9.51027 16.5178 9.76089 16.5172 10.0157Z" fill="#147945"/>
519            </svg>
520          `;
521        }
522      });
523
524    }).catch(err => console.warn('Autoplay blocked:', err));
525  }
526}
527
528
529
530
531
532// testimonial video section code
533
534
535
536document.querySelectorAll('.play-button').forEach(button => {
537  button.addEventListener('click', () => {
538    const clickedVideoCard = button.closest('.video-card');
539    const clickedVideo = clickedVideoCard.querySelector('video');
540
541    document.querySelectorAll('.testimonial-slider-video .video-card').forEach(card => {
542      const video = card.querySelector('video');
543      const playBtn = card.querySelector('.play-button');
544      const muteBtnImg = card.querySelector('.mute-button img');
545
546      if (video !== clickedVideo) {
547        video.pause();
548        video.currentTime = 0;
549
550        if (playBtn) {
551          playBtn.innerHTML = `
552            <svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
553              <path d="M16.5172 10.0157C16.5178 10.2705 16.4525 10.5211 16.3276 10.7432C16.2027 10.9652 16.0224 11.1512 15.8043 11.283L2.28927 19.5507C2.06141 19.6902 1.80043 19.7664 1.5333 19.7713C1.26616 19.7763 1.00254 19.7098 0.769671 19.5788C0.53902 19.4499 0.346881 19.2618 0.213014 19.034C0.0791461 18.8061 0.008381 18.5467 0.00799561 18.2825V1.74888C0.008381 1.48462 0.0791461 1.22524 0.213014 0.9974C0.346881 0.769561 0.53902 0.581491 0.769671 0.452529C1.00254 0.321532 1.26616 0.255076 1.5333 0.260023C1.80043 0.26497 2.06141 0.341141 2.28927 0.48067L15.8043 8.74841C16.0224 8.88018 16.2027 9.06614 16.3276 9.28821C16.4525 9.51027 16.5178 9.76089 16.5172 10.0157Z" fill="#147945"/>
554            </svg>
555          `;
556        }
557
558        if (video && muteBtnImg) {
559          video.muted = false;
560          muteBtnImg.src = 'https://staging.grnspace.com/wp-content/uploads/2025/05/volume-button-video.svg'; // unmuted icon
561          muteBtnImg.alt = 'Unmuted';
562        }
563      }
564    });
565
566    const iconPlay = `
567       <svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
568         <path d="M16.5172 10.0157C16.5178 10.2705 16.4525 10.5211 16.3276 10.7432C16.2027 10.9652 16.0224 11.1512 15.8043 11.283L2.28927 19.5507C2.06141 19.6902 1.80043 19.7664 1.5333 19.7713C1.26616 19.7763 1.00254 19.7098 0.769671 19.5788C0.53902 19.4499 0.346881 19.2618 0.213014 19.034C0.0791461 18.8061 0.008381 18.5467 0.00799561 18.2825V1.74888C0.008381 1.48462 0.0791461 1.22524 0.213014 0.9974C0.346881 0.769561 0.53902 0.581491 0.769671 0.452529C1.00254 0.321532 1.26616 0.255076 1.5333 0.260023C1.80043 0.26497 2.06141 0.341141 2.28927 0.48067L15.8043 8.74841C16.0224 8.88018 16.2027 9.06614 16.3276 9.28821C16.4525 9.51027 16.5178 9.76089 16.5172 10.0157Z" fill="#147945"/>
569       </svg>
570    `;
571    const iconPause = `
572       <svg width="224" height="352" viewBox="0 0 224 352" fill="none" xmlns="http://www.w3.org/2000/svg">
573         <path d="M64 352H16C11.7565 352 7.68688 350.314 4.68629 347.314C1.68571 344.313 0 340.243 0 336V16C0 11.7565 1.68571 7.68688 4.68629 4.68629C7.68688 1.68571 11.7565 0 16 0H64C68.2435 0 72.3131 1.68571 75.3137 4.68629C78.3143 7.68688 80 11.7565 80 16V336C80 340.243 78.3143 344.313 75.3137 347.314C72.3131 350.314 68.2435 352 64 352ZM208 352H160C155.757 352 151.687 350.314 148.686 347.314C145.686 344.313 144 340.243 144 336V16C144 11.7565 145.686 7.68688 148.686 4.68629C151.687 1.68571 155.757 0 160 0H208C212.243 0 216.313 1.68571 219.314 4.68629C222.314 7.68688 224 11.7565 224 16V336C224 340.243 222.314 344.313 219.314 347.314C216.313 350.314 212.243 352 208 352Z" fill="#147945"/>
574       </svg>
575    `;
576
577    if (clickedVideo.paused) {
578      clickedVideo.play();
579      button.innerHTML = iconPause;
580    } else {
581      clickedVideo.pause();
582      button.innerHTML = iconPlay;
583    }
584  });
585});
586
587// let sharedMuteState = true; // true = muted, false = unmuted
588
589let sharedMuteState = true;
590
591function applyMuteState(videoCard) {
592  const video = videoCard.querySelector('video');
593  const muteImg = videoCard.querySelector('.mute-button img');
594  if (!video || !muteImg) return;
595
596  video.muted = sharedMuteState;
597  updateMuteIcon(video, muteImg);
598}
599
600function updateMuteIcon(video, muteImg) {
601  if (video.muted) {
602    muteImg.src = 'https://staging.grnspace.com/en-us/wp-content/uploads/sites/2/2025/05/Volume.svg';
603    muteImg.alt = 'Muted';
604  } else {
605    muteImg.src = 'https://staging.grnspace.com/wp-content/uploads/2025/05/volume-button-video.svg';
606    muteImg.alt = 'Unmuted';
607  }
608}
609
610function syncAllVideosMuteState() {
611  document.querySelectorAll('.video-card').forEach(applyMuteState);
612}
613
614// Initial setup for mute button + click
615document.querySelectorAll('.video-card').forEach(videoCard => {
616  const video = videoCard.querySelector('video');
617  const muteButton = videoCard.querySelector('.mute-button');
618  const muteImg = muteButton?.querySelector('img');
619  const videoArea = videoCard.querySelector('.card-media');
620
621  if (!video || !muteButton || !muteImg || !videoArea) return;
622
623  // Set initial state
624  applyMuteState(videoCard);
625
626  muteButton.addEventListener('click', (e) => {
627    e.stopPropagation();
628    sharedMuteState = !sharedMuteState;
629    syncAllVideosMuteState();
630  });
631
632  videoArea.addEventListener('click', () => {
633    sharedMuteState = !sharedMuteState;
634    syncAllVideosMuteState();
635  });
636
637  // When video starts playing (e.g. after slide change), re-apply mute state
638  video.addEventListener('play', () => {
639    applyMuteState(videoCard);
640  });
641});
642
643function updateMuteIcon(video, muteImg) {
644  if (video.muted) {
645    muteImg.src = 'https://staging.grnspace.com/en-us/wp-content/uploads/sites/2/2025/05/Volume.svg';
646    muteImg.alt = 'Muted';
647  } else {
648    muteImg.src = 'https://staging.grnspace.com/wp-content/uploads/2025/05/volume-button-video.svg';
649    muteImg.alt = 'Unmuted';
650  }
651}
652
653function syncMuteStateAcrossVideos(isMuted) {
654  document.querySelectorAll('.video-card').forEach(card => {
655    const video = card.querySelector('video');
656    const muteImg = card.querySelector('.mute-button img');
657    if (video && muteImg) {
658      video.muted = isMuted;
659      updateMuteIcon(video, muteImg);
660    }
661  });
662}
663
664
665document.querySelectorAll('.play-button').forEach(btn => {
666  btn.addEventListener('click', (e) => {
667    e.stopPropagation(); 
668  });
669});
670
671// Prevent mute button from triggering mute toggle if still visible
672document.querySelectorAll('.mute-button').forEach(btn => {
673  btn.addEventListener('click', (e) => {
674    e.stopPropagation(); 
675  });
676});
677
678
679
680document.addEventListener("DOMContentLoaded", () => {
681  const videoCards = document.querySelectorAll('.video-card');
682
683  videoCards.forEach((card) => {
684    const video = card.querySelector('video');
685    const thumbnail = card.querySelector('.video-thumbnail');
686    const progressBar = card.querySelector('.video-slide .video-progress-bar');
687    const progressContainer = card.querySelector('.video-progress-container');
688
689    // Hide thumbnail on play
690    video?.addEventListener('play', () => {
691      if (thumbnail) thumbnail.style.display = 'none';
692    });
693
694    // Optional: Show thumbnail again if paused at start
695    video?.addEventListener('pause', () => {
696      if (thumbnail && video.currentTime === 0) {
697        thumbnail.style.display = 'block';
698      }
699    });
700
701    // Update progress bar as video plays
702    video?.addEventListener('timeupdate', () => {
703      const progress = (video.currentTime / video.duration) * 100;
704      if (progressBar) {
705        progressBar.style.width = progress + '%';
706      }
707    });
708
709    // Allow progress bar seeking
710    if (progressContainer && video) {
711      progressContainer.addEventListener('click', (e) => {
712        e.stopPropagation(); // 
713        const rect = progressContainer.getBoundingClientRect();
714        const clickX = e.clientX - rect.left;
715        const width = rect.width;
716        const percent = clickX / width;
717        video.currentTime = percent * video.duration;
718      });
719    
720      // Drag behavior
721      let isDragging = false;
722    
723      progressContainer.addEventListener('mousedown', (e) => {
724        e.stopPropagation(); // 
725        isDragging = true;
726      });
727    
728      document.addEventListener('mouseup', (e) => {
729        isDragging = false;
730      });
731    
732      document.addEventListener('mousemove', (e) => {
733        if (isDragging && video && progressContainer) {
734          const rect = progressContainer.getBoundingClientRect();
735          const moveX = e.clientX - rect.left;
736          const width = rect.width;
737          const percent = Math.min(Math.max(moveX / width, 0), 1);
738          video.currentTime = percent * video.duration;
739        }
740      });
741    }
742    
743  });
744});
745
746document.addEventListener("DOMContentLoaded", () => {
747  const cards = document.querySelectorAll(".stacking-card");
748  const tabs = document.querySelectorAll(".stacking-tab");
749  const container = document.querySelector(".container");
750
751  if (!cards.length || !tabs.length || !container) return;
752  const total = cards.length;
753  let lastClickedIndex = 0;
754  const originalPositions = [];
755  let activeTabIndex = 0;
756  let bulletWrapper;
757
758  // Initialize cards
759  cards.forEach((card, i) => {
760    card.style.transition = "transform 0.8s ease";
761    let shift;
762    if (i === 0) {
763      shift = `calc(2vw)`; // first card
764      card.style.transform = `translateX(${shift})`;
765    } else {
766      shift = `calc(${97 - (total - i - 1) * 3}vw)`; // stacked position
767      card.style.transform = `translateX(${shift})`;
768    }
769    originalPositions[i] = shift;
770    card.dataset.clicked = "false";
771    card.style.zIndex = i + 1;
772
773    card.addEventListener("click", () => {
774      revealCard(i);
775      setActiveTab(i);
776      updateBullets(i);
777      syncVideos(i);
778    });
779  });
780
781  // Reveal card logic
782  function revealCard(clickedIndex) {
783    if (!cards[clickedIndex]) return;
784    const forward = clickedIndex > lastClickedIndex;
785    const delayStep = 50;
786
787    if (forward) {
788      for (let j = 1; j < clickedIndex; j++) {
789        setTimeout(() => {
790          if (!cards[j]) return;
791          cards[j].style.transform = `translateX(calc(2vw + ${j * 3}vw))`;
792          cards[j].dataset.clicked = "true";
793        }, (j - 1) * delayStep);
794      }
795    } else {
796      for (let j = total - 1; j > clickedIndex; j--) {
797        setTimeout(() => {
798          if (!cards[j]) return;
799          cards[j].style.transform = `translateX(${originalPositions[j]})`;
800          cards[j].dataset.clicked = "false";
801        }, (total - 1 - j) * delayStep);
802      }
803    }
804
805    setTimeout(() => {
806      const clickedTranslateX =
807        clickedIndex === 0
808          ? `translateX(calc(2vw))`
809          : `translateX(calc(2vw + ${clickedIndex * 3}vw))`;
810
811      cards[clickedIndex].style.transform = clickedTranslateX;
812      cards[clickedIndex].dataset.clicked = "true";
813
814      if (clickedIndex !== 0) {
815        cards[0].style.transform = `translateX(calc(2vw))`;
816        cards[0].dataset.clicked = "false";
817      }
818    }, delayStep * (forward ? (clickedIndex > 1 ? clickedIndex - 1 : 0) : (total - 1 - clickedIndex)));
819
820    lastClickedIndex = clickedIndex;
821  }
822  function syncVideos(activeIndex) {
823  cards.forEach((card, i) => {
824    const video = card.querySelector('.stacking-video');
825    if (!video) return;
826    if (i === activeIndex) {
827      video.play();
828    } else {
829      video.pause();
830      video.currentTime = 0;
831    }
832  });
833}
834
835  // Tabs control
836  function setActiveTab(i) {
837    tabs.forEach(t => t.classList.remove("active-tab"));
838    if (tabs[i]) tabs[i].classList.add("active-tab");
839  }
840
841  tabs.forEach((tab, i) => {
842    tab.addEventListener("click", () => {
843      revealCard(i);
844      setActiveTab(i);
845      updateBullets(i);
846      syncVideos(i);
847    });
848  });
849
850  // === BULLET PAGINATION (mobile only) ===
851  function createBullets() {
852    // Remove if already exists
853    const existing = document.querySelector(".stacking-bullets");
854    if (existing) existing.remove();
855
856    bulletWrapper = document.createElement("div");
857    bulletWrapper.className = "stacking-bullets";
858
859    for (let i = 0; i < total; i++) {
860      const bullet = document.createElement("span");
861      bullet.className = "stacking-bullet";
862      if (i === activeTabIndex) bullet.classList.add("active-bullet");
863      bullet.addEventListener("click", () => {
864        goToSlide(i);
865      });
866      bulletWrapper.appendChild(bullet);
867    }
868
869    // ✅ Append below .stacking-cards
870    const stackingContainer = document.querySelector(".stacking-container");
871    const stackingCards = stackingContainer?.querySelector(".stacking-cards");
872
873    if (stackingContainer && stackingCards) {
874      stackingCards.insertAdjacentElement("afterend", bulletWrapper);
875    }
876  }
877
878
879  function updateBullets(index) {
880    const bullets = document.querySelectorAll(".stacking-bullet");
881    bullets.forEach((b, i) => {
882      b.classList.toggle("active-bullet", i === index);
883    });
884  }
885
886  function goToSlide(index) {
887    // ignore noop
888    if (index === activeTabIndex) return;
889
890    activeTabIndex = index;
891    updateBullets(index);
892    setActiveTab(index);
893
894    // show/hide cards for mobile
895    showOnlyActiveCard();
896    syncVideos(index);
897
898    // ensure swipe handler sees the updated activeTabIndex
899    enableSwipe();
900  }
901
902
903  // Handle mobile/desktop view
904  function showOnlyActiveCard() {
905    cards.forEach((card, index) => {
906      card.style.display = index === activeTabIndex ? "block" : "none";
907    });
908  }
909
910  let swipeAttached = false;
911
912
913function enableSwipe() {
914  const stackingCards = document.querySelector(".stacking-cards") || document.querySelector(".container");
915  if (!stackingCards) return;
916
917  // Only attach once per page load
918  if (swipeAttached) return;
919  swipeAttached = true;
920
921  let startX = 0;
922  const threshold = 50; // Minimum swipe distance
923  let isThrottled = false; // Prevent multiple triggers too fast
924
925  stackingCards.addEventListener("touchstart", (e) => {
926    if (!e.touches || !e.touches[0]) return;
927    startX = e.touches[0].clientX;
928  }, { passive: true });
929
930  stackingCards.addEventListener("touchend", (e) => {
931    if (isThrottled) return;
932    const endX = e.changedTouches?.[0]?.clientX || 0;
933    const diff = startX - endX;
934
935    if (Math.abs(diff) < threshold) return; // Ignore small drags
936
937    isThrottled = true;
938    setTimeout(() => (isThrottled = false), 250); // Cooldown
939
940    if (diff > 0 && activeTabIndex < total - 1) {
941      // Swipe left → next
942      goToSlide(activeTabIndex + 1);
943    } else if (diff < 0 && activeTabIndex > 0) {
944      // Swipe right → previous
945      goToSlide(activeTabIndex - 1);
946    }
947  }, { passive: true });
948}
949
950
951
952
953  function handleMobileView() {
954    if (window.innerWidth < 991) {
955      showOnlyActiveCard();
956      createBullets();
957      updateBullets(activeTabIndex);
958      enableSwipe();
959    } else {
960      // Desktop: show all cards & remove bullets
961      cards.forEach(card => (card.style.display = "block"));
962      const existing = document.querySelector(".stacking-bullets");
963      if (existing) existing.remove();
964    }
965  }
966
967  // Attach tab click events for mobile
968  tabs.forEach((tab, i) => {
969    tab.addEventListener("click", () => {
970      activeTabIndex = i;
971      if (window.innerWidth < 991) {
972        showOnlyActiveCard();
973        updateBullets(i);
974      }
975    });
976  });
977
978  // Initialize
979  handleMobileView();
980  setActiveTab(0);
981  revealCard(0);
982  syncVideos(0);
983
984  // Recalculate on resize
985  window.addEventListener("resize", handleMobileView);
986});
987
988
989document.querySelectorAll('.new-testimonial .blockquote-text').forEach(el => {
990  const wordCount = el.textContent.trim().split(/\s+/).length; // count words
991  if(wordCount > 26){
992    el.style.fontSize = '16px'; 
993  }
994});
995
996document.addEventListener("click", function (e) {
997  const btn = e.target.closest("[data-book-demo]");
998  if (!btn) return;
999
1000 const demoBtn = document.querySelector('.module-cta a[href="#book-a-demo"]');
1001
1002  if (demoBtn) {
1003    demoBtn.dispatchEvent(new MouseEvent("click", {
1004      bubbles: true,
1005      cancelable: true,
1006      view: window
1007    }));
1008  }
1009});
1010// form submission
1011
1012document.addEventListener("DOMContentLoaded", function () {
1013
1014    const forms = document.querySelectorAll("form");
1015
1016    forms.forEach(function(form) {
1017
1018        const demoField = form.querySelector('input[name="item_meta[418]"]');
1019
1020        if (demoField) {
1021            demoField.value = Date.now();
1022            return; // skip auto field creation
1023        }
1024
1025        if (form.querySelector('.auto-time-check')) return;
1026
1027        let input = document.createElement("input");
1028        input.type = "hidden";
1029        input.name = "form_start_time";
1030        input.className = "auto-time-check";
1031        input.value = Date.now();
1032
1033        form.appendChild(input);
1034    });
1035
1036});
1037
1038//form loading
1039document.addEventListener('DOMContentLoaded', function () {
1040
1041  document.querySelectorAll('.frm-show-form').forEach(form => {
1042    const submitBtn = form.querySelector('.frm_button_submit');
1043
1044    if (!submitBtn) return;
1045
1046    const span = document.createElement('span');
1047    span.className = 'submitting-text';
1048    span.hidden = true;
1049    span.textContent = 'Submitting';
1050
1051    submitBtn.appendChild(span);
1052  });
1053
1054});
1055
1056
1057document.addEventListener("DOMContentLoaded", function () {
1058  const section = document.querySelector('.new-testimonial');
1059
1060  if (!section) return;
1061
1062  section.querySelectorAll('p').forEach(textElement => {
1063    if (textElement.innerHTML.includes('Best MBC Software')) {
1064      textElement.innerHTML = textElement.innerHTML.replace(
1065        'Best MBC Software',
1066        '<a href="https://learn.g2.com/mental-health-software" target="_blank" rel="noopener noreferrer">Best MBC Software</a>'
1067      );
1068    }
1069  });
1070});
1071document.addEventListener("DOMContentLoaded", function () {
1072  const section = document.querySelector('.testimonial-slider-video');
1073
1074  if (!section) return;
1075
1076  section.querySelectorAll('p').forEach(textElement => {
1077    if (textElement.innerHTML.includes('Best MBC Software')) {
1078      textElement.innerHTML = textElement.innerHTML.replace(
1079        'Best MBC Software',
1080        '<a href="https://learn.g2.com/mental-health-software" target="_blank" rel="noopener noreferrer">Best MBC Software</a>'
1081      );
1082    }
1083  });
1084});
1085
1086
1087document.addEventListener('DOMContentLoaded', function () {
1088    fetch('https://api.ipify.org?format=json')
1089        .then(function (response) { return response.json(); })
1090        .then(function (data) {
1091            var ipField = document.getElementById('tfa_57');
1092            if (ipField) {
1093                ipField.value = data.ip;
1094            }
1095        })
1096        .catch(function (error) {
1097            console.error('IP fetch failed:', error);
1098        });
1099});
1100
1101
1102
1103// ROI
1104
1105(function(){
1106  if (document.querySelector('.clac-flex #slider')){
1107
1108  var slider = document.getElementById('slider');
1109  var PER = 6793.75, NOSHOW = 4420, ADMIN = 3093.75;
1110  var fmt = function(n){ return '$' + Math.round(n).toLocaleString('en-US'); };
1111
1112  function render(){
1113    var p = +slider.value;
1114    document.getElementById('prov').textContent = p;
1115    document.getElementById('roi').textContent = fmt(p * PER);
1116    document.getElementById('noshow').textContent = fmt(p * NOSHOW);
1117    document.getElementById('admin').textContent = fmt(p * ADMIN);
1118  }
1119
1120  slider.addEventListener('input', render);
1121  render();
1122}
1123})();
1124
1125
1126document.addEventListener("DOMContentLoaded", function () {
1127document.addEventListener('click', function (e) {
1128    const button = e.target.closest('.demo-button');
1129
1130    if (!button) return;
1131
1132    window.dataLayer = window.dataLayer || [];
1133
1134    window.dataLayer.push({
1135        event: 'open_demo_request',
1136        click_id: button.id
1137    });
1138});
1139});
1140
1141(function () {
1142  if (window.ambassadorCaptchaFixLoaded) return;
1143  window.ambassadorCaptchaFixLoaded = true;
1144
1145  function start() {
1146    let attempts = 0;
1147
1148    const timer = setInterval(function () {
1149      attempts++;
1150
1151      const form = document.querySelector(
1152        '#ambassador-form form[id="16"]'
1153      );
1154
1155      const api = window.grecaptcha?.enterprise;
1156
1157      // Wait until FormAssembly finishes rendering the first CAPTCHA.
1158      if (
1159        !form ||
1160        typeof api?.render !== 'function' ||
1161        !window.hasCaptchaRendered
1162      ) {
1163        if (attempts >= 120) {
1164          clearInterval(timer);
1165          console.error(
1166            'Ambassador CAPTCHA: form or FormAssembly initialization unavailable.'
1167          );
1168        }
1169        return;
1170      }
1171
1172      clearInterval(timer);
1173
1174      const container = form.querySelector('[id="google-captcha"]');
1175      const button = form.querySelector('input[type="submit"]');
1176      const widget = container?.querySelector('.g-recaptcha');
1177      const explanation = container?.querySelector(
1178        '[id="disabled-explanation"]'
1179      );
1180      const error = container?.querySelector('.g-captcha-error');
1181
1182      if (!container || !button || !widget) {
1183        console.error('Ambassador CAPTCHA: required elements missing.');
1184        return;
1185      }
1186
1187      // Leave an already-rendered CAPTCHA under its existing callbacks.
1188      if (widget.querySelector('iframe')) return;
1189
1190      // Give this widget its own ID; render using the element itself.
1191      widget.id = 'ambassador-recaptcha-16';
1192
1193      let widgetId;
1194      let verified = false;
1195
1196      function lockButton() {
1197        verified = false;
1198        button.disabled = true;
1199
1200        if (explanation) explanation.style.display = 'block';
1201      }
1202
1203      lockButton();
1204      container.style.display = 'block';
1205
1206      // Guard keyboard submission as well as button submission.
1207      form.addEventListener('submit', function (event) {
1208        const response =
1209          widgetId === undefined ? '' : api.getResponse(widgetId);
1210
1211        if (!verified || !response) {
1212          event.preventDefault();
1213          event.stopImmediatePropagation();
1214          lockButton();
1215
1216          if (error) {
1217            error.textContent = 'Please complete the CAPTCHA.';
1218          }
1219        }
1220      }, true);
1221
1222      try {
1223        widgetId = api.render(widget, {
1224          sitekey: '6LfMg_EaAAAAAMhDNLMlgqDChzmtYHlx1yU2y7GI',
1225          theme: 'light',
1226          size: 'normal',
1227
1228          callback: function (response) {
1229            verified = Boolean(response);
1230
1231            if (!verified) {
1232              lockButton();
1233              return;
1234            }
1235
1236            if (error) error.textContent = '';
1237            if (explanation) explanation.style.display = 'none';
1238
1239            // The supplied Form 16 button has no conditional-submit rule.
1240            if (!button.hasAttribute('data-condition')) {
1241              button.disabled = false;
1242            }
1243          },
1244
1245          'expired-callback': function () {
1246            lockButton();
1247          },
1248
1249          'error-callback': function () {
1250            lockButton();
1251
1252            if (error) {
1253              error.textContent =
1254                'CAPTCHA could not load. Please reload the page and try again.';
1255            }
1256          }
1257        });
1258
1259        form.addEventListener('reset', function () {
1260          lockButton();
1261          api.reset(widgetId);
1262        });
1263      } catch (err) {
1264        lockButton();
1265
1266        if (error) {
1267          error.textContent =
1268            'CAPTCHA could not load. Please reload the page and try again.';
1269        }
1270
1271        console.error('Ambassador CAPTCHA initialization failed:', err);
1272      }
1273    }, 250);
1274  }
1275
1276  if (document.readyState === 'loading') {
1277    document.addEventListener('DOMContentLoaded', start, { once: true });
1278  } else {
1279    start();
1280  }
1281})();
1282
1283
1284(function () {
1285  function init() {
1286    const form = document.querySelector('#ambassador-form form[id="16"]');
1287    const input = form?.querySelector('[id="tfa_5"]');
1288    const field = form?.querySelector('[id="tfa_5-D"]');
1289
1290    if (!input || !field || field.dataset.emailErrorAttached) return;
1291    field.dataset.emailErrorAttached = 'true';
1292
1293    const workEmailMessage =
1294      'Please enter a valid work email address. Personal email addresses (Gmail, Yahoo, Outlook, etc.) are not accepted.';
1295
1296    function updateError() {
1297      const invalid = input.getAttribute('aria-invalid') === 'true';
1298      const errors = field.querySelectorAll('[id="tfa_5-E"]');
1299
1300      if (!invalid) {
1301        errors.forEach(error => error.remove());
1302        field.classList.remove('errFld', 'tfa-inline-error-present');
1303        return;
1304      }
1305
1306      let error = errors[0];
1307
1308      // Keep just one error inside this field.
1309      errors.forEach((element, index) => {
1310        if (index > 0) element.remove();
1311      });
1312
1313      if (!error) {
1314        error = document.createElement('div');
1315        error.id = 'tfa_5-E';
1316        error.className = 'errMsg';
1317        error.tabIndex = -1;
1318        error.setAttribute('role', 'alert');
1319        error.innerHTML =
1320          '<i class="fa fa-exclamation-circle" aria-hidden="true"></i> <span></span>';
1321        field.appendChild(error);
1322      }
1323
1324      const message = workEmailMessage;
1325
1326      // Avoid repeatedly modifying the DOM.
1327      const text = error.querySelector('span');
1328      if (text && text.textContent !== message) {
1329        text.textContent = message;
1330      }
1331
1332      field.classList.add('errFld', 'tfa-inline-error-present');
1333    }
1334
1335    // Observe FormAssembly's validation state and error removal.
1336    const observer = new MutationObserver(function () {
1337      observer.disconnect();
1338      updateError();
1339      observe();
1340    });
1341
1342    function observe() {
1343      observer.observe(field, {
1344        subtree: true,
1345        childList: true,
1346        attributes: true,
1347        attributeFilter: ['aria-invalid']
1348      });
1349    }
1350
1351    observe();
1352    updateError();
1353
1354    input.addEventListener('input', updateError);
1355  }
1356
1357  if (document.readyState === 'loading') {
1358    document.addEventListener('DOMContentLoaded', init, { once: true });
1359  } else {
1360    init();
1361  }
1362
1363  // Also handle forms inserted after the page loads.
1364  const discovery = new MutationObserver(init);
1365  discovery.observe(document.documentElement, {
1366    childList: true,
1367    subtree: true
1368  });
1369})();
1370

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.