1<!DOCTYPE html> 2<html class="no-js" lang=en> 3<head> 4 <meta charset="utf-8"> 5 <meta http-equiv="x-ua-compatible" content="ie=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta name="twitter:card" content="summary_large_image"> 8 <meta property="og:type" content="website"> 9 <title>Contact Us | Marco island Florida Real Estate Agents</title> 10 <meta property="og:title" content="Contact Us | Marco island Florida Real Estate Agents"> 11 <meta name="twitter:title" content="Contact Us | Marco island Florida Real Estate Agents"> 12 <meta name="description" content="Looking for reliable real estate agents in Marco Island, Florida? Contact Us today for expert guidance and personalized services in finding your dream home."> 13 <meta property="og:description" content="Looking for reliable real estate agents in Marco Island, Florida? Contact Us today for expert guidance and personalized services in finding your dream home."> 14 <meta name="twitter:description" content="Looking for reliable real estate agents in Marco Island, Florida? Contact Us today for expert guidance and personalized services in finding your dream home."> 15 <meta property="og:image" content="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1920/https://media-production.lp-cdn.com/media/e0c3d97e-0124-4558-bd78-6c9f5b568846"> 16 <meta name="twitter:image" content="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1920/https://media-production.lp-cdn.com/media/e0c3d97e-0124-4558-bd78-6c9f5b568846"> 17 <meta property="og:url" content="https://marcoislandlife.net/contact-us"> 18 <link rel="canonical" href="https://marcoislandlife.net/contact-us"> 19
19<script>(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);</script>
19 20 <link rel="preconnect" href="https://fonts.googleapis.com"> 21 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 22 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i"><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Quicksand:300,400,500,600,700"> 23 <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> 24 <noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css"></noscript> 25 <link rel="icon" type="image/x-icon" href="/favicon.ico"> 26 <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"> 27 <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> 28 <link rel="icon" type="image/png" sizes="48x48" href="/favicon-48x48.png"> 29 <style id="global-css">:root{--global-primary-font-family:Raleway,sans-serif;--global-primary-font-family-short:Raleway;--global-secondary-font-family:Quicksand,sans-serif;--global-secondary-font-family-short:Quicksand;--global-body-padding:0px;--global-background-color:#fff;--global-body-font-size:16px;--global-h1-font-size:60px;--global-h2-font-size:43px;--global-h3-font-size:30px;--global-h4-font-size:21px;--global-h5-font-size:17px;--global-h6-font-size:16px;--global-section-padding:96px;}@media (max-width: 768px){:root{--global-section-padding:64px;}}body{padding:0px;background-color:#fff;font-family:Quicksand,sans-serif;font-size:16px;}@media (min-width: 768px){body{padding:0px 0px 0px 0px;}}h1,h2,h3,h4,h5,h6,button{font-family:Raleway,sans-serif;}h1{font-size:60px;}h2{font-size:43px;}h3{font-size:30px;}h4{font-size:21px;}h5{font-size:17px;}h6{font-size:16px;}</style> 30 <link rel="stylesheet" type="text/css" href="https://styles.luxurypresence.com/producer/index.css" /> 31 <style id="website-css">:root{--overlay-color:rgba(0, 0, 0, 0);}@import url('https://fonts.googleapis.com/css2?family=Abril+Fatface&display=swap');.J-paginationjs-page a{margin:0 5px;}.hyperlink-style-1,.hyperlink-style-2{font-weight:400!important;}.button-style-1,.button-style-2{font-weight:700!important;}.lp-btn,.redesign .lp-btn{padding:20px 46px;}#modal-global-contact-us .contact-form .section-message form .submitButton{padding:14px 20px;}body>div.mobile-contact-wrapper{z-index:2000!important;}body>div.mobile-contact-wrapper .mobile-contact.with-search div.buttons-holder{bottom:150px;}@media only screen and (max-width: 768px){iframe[name='widgetCta']{bottom:55px!important;right:15px!important;}}iframe[name="widgetCta"]{bottom:70px!important;right:15px!important;}.lp-title-group .lp-h2{margin-top:0;}@media (max-width: 768px){.lp-socials{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}}:root{--primary:#363636;--secondary:#363636;--dark:#363636;--light:#fff;--light-gray:#ccc;--accent:#363636;--trans:transparent;}h1,.lp-h1,h2,.lp-h2,h3,.lp-h3,h4,.lp-h4{text-transform:uppercase!important;}h1,.lp-h1,h2,.lp-h2,h3,.lp-h3,h4,.lp-h4,h5,.lp-h5{font-weight:250!important;letter-spacing:5px!important;}.custom-select-item{background:var(--light)!important;color:var(--dark)!important;}.custom-select-item:hover{background:var(--primary)!important;color:var(--light)!important;}nav#global-navbar .header{margin-top:0;}@media only screen and (max-width:768px){nav#global-navbar .header{margin-top:0;}}@media only screen and (max-width:768px){nav#global-navbar .header .container{padding:0 30px;}}nav#global-navbar .navigation ul li:nth-child(3) .sub-nav .sub-nav__item{min-width:180px;}nav#global-navbar li.navigation__item a.navigation__link{color:var(--light);font-weight:500!important;}nav#global-navbar li.navigation__item a.navigation__link span:after{background-color:var(--light);}nav#global-navbar .header .navigation .sub-nav ul{background-color:transparent;}nav#global-navbar .header .navigation .sub-nav ul li{background-color:var(--dark);opacity:.9;}nav#global-navbar .header .navigation .sub-nav ul li:hover{background-color:var(--light);color:var(--dark);}nav#global-navbar .header .navigation .sub-nav ul a{color:var(--light);}nav#global-navbar .header .navigation .sub-nav ul a:hover{color:var(--dark);}nav#global-navbar .header .navigation .sub-nav ul a span:after{background-color:transparent;}nav#global-navbar.scroll{padding-bottom:0;padding-top:0;background-color:var(--primary)!important;opacity:.95;}@media only screen and (max-width:768px){nav#global-navbar.scroll{padding-bottom:0;padding-top:0;}}nav#global-navbar.scroll li.navigation__item a.navigation__link{color:var(--light);}nav#global-navbar.scroll li.navigation__item a.navigation__link span:after{background-color:var(--light)!important;}nav#global-navbar.scroll li.navigation__item a.navigation__link:hover{color:var(--light);}nav#global-navbar.scroll button.hamburger-component.hamburger{color:var(--light);}nav#global-navbar.scroll .logo img{-webkit-filter:none;filter:none;}nav#global-navbar .header .logo img{max-height:100px;max-width:275px;}@media only screen and (max-width: 768px){nav#global-navbar .header .logo img{max-height:60px;max-width:215px;}}nav#global-navbar.scroll .logo__img.light{display:block;}@media only screen and (min-width:320px) and (max-width:1024px){nav#global-navbar.scroll .logo__img.light{display:block!important;}}nav#global-navbar.scroll .logo__img.dark{display:none;}@media only screen and (min-width:320px) and (max-width:1024px){nav#global-navbar.scroll .logo__img.dark{display:none!important;}}footer#global-footer .footer{padding-top:0;padding-bottom:0;}footer#global-footer .footer.no_newsletter h3{color:var(--dark);}@media only screen and (max-width:768px){footer#global-footer .footer.no_newsletter h3{letter-spacing:0;}}footer#global-footer .container{padding-top:96px;}@media only screen and (max-width:768px){footer#global-footer .container{padding-top:64px;}}footer#global-footer .text_footer .images_box{margin-right:46px;}@media only screen and (max-width: 768px){footer#global-footer .text_footer .images_box{margin-right:auto;margin-left:auto;}}footer#global-footer .first_text_footer .img_size img{min-height:60px;width:80%;height:80%;}@media only screen and (max-width:1240px){footer#global-footer .first_text_footer .img_size img{min-height:60px;}}@media only screen and (max-width:768px){footer#global-footer .first_text_footer .img_size img{min-height:60px;}}footer#global-footer a.hvr_animation,footer#global-footer .lp-link,footer#global-footer .link{font-weight:400;text-transform:uppercase!important;position:relative!important;color:var(--dark)!important;-webkit-transition:0.4s;transition:0.4s;}footer#global-footer a.hvr_animation:hover,footer#global-footer .lp-link:hover,footer#global-footer .link:hover{color:var(--dark)!important;}footer#global-footer a.hvr_animation:before,footer#global-footer .lp-link:before,footer#global-footer .link:before,footer#global-footer a.hvr_animation:after,footer#global-footer .lp-link:after,footer#global-footer .link:after{-webkit-transition:0.4s;transition:0.4s;-webkit-text-decoration:none!important;text-decoration:none!important;line-height:1;content:"";height:1px;position:absolute!important;bottom:0;left:0;}footer#global-footer a.hvr_animation:before,footer#global-footer .lp-link:before,footer#global-footer .link:before{width:100%!important;background-color:var(--light-gray)!important;opacity:0.4;}footer#global-footer a.hvr_animation:after,footer#global-footer .lp-link:after,footer#global-footer .link:after{width:0%!important;background-color:var(--accent)!important;}footer#global-footer a.hvr_animation:hover:after,footer#global-footer .lp-link:hover:after,footer#global-footer .link:hover:after{width:100%!important;}footer#global-footer .no_newsletter .info-wrap-contact_zone:first-of-type{margin-bottom:25px;}footer#global-footer .info-wrap-contact_cell{padding-top:0;}footer#global-footer .info-privacy .socials_zone{-webkit-box-pack:center;-ms-flex-pack:center;
31-webkit-justify-content:center;justify-content:center;}@media only screen and (max-width: 768px){footer#global-footer .info-privacy .socials_zone li{padding:0 12px 10px 12px;}footer#global-footer .footer .info-privacy .copy_zone{border-color:var(--accent);}}footer#global-footer .footer .img-wrap img{-webkit-filter:invert(0);filter:invert(0);}@media only screen and (max-width:820px){footer#global-footer .info-wrap .info-wrap-contact_zone.type_user div:nth-child(3){width:100%;}}@media only screen and (max-width:1024px){footer#global-footer .footer .text_footer{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}footer#global-footer .text_footer .images_box{margin-bottom:40px;}}@media only screen and (max-width:820px){footer#global-footer .footer .text_footer{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}footer#global-footer .text_footer .images_box{margin-bottom:20px;}}footer#global-footer .footer .info-wrap-contact_zone i svg path{fill:var(--accent);}footer#global-footer .footer .info-privacy{border-top:1px solid var(--dark);}@media only screen and (max-width:768px){footer#global-footer .footer .info-privacy{padding-top:30px;}}@media only screen and (max-width:375px){footer#global-footer .footer .info-privacy{padding-top:30px;}}footer#global-footer .info-wrap div:nth-child(2) p:nth-child(4){font-weight:400;}@media only screen and (max-width:768px){footer#global-footer #global-footer div.text_footer.first_text_footer div.luxury-text p:nth-child(1){width:80%;margin:0 auto 0;}footer#global-footer .footer .text_footer p{font-size:12px;}}footer#global-footer div.info-privacy div.form-col.form-col--powered.powered-box div.powered_zone a{font-weight:normal;text-transform:capitalize!important;}footer#global-footer div.info-privacy div.form-col.form-col--copyright a{font-weight:normal;text-transform:capitalize!important;}footer#global-footer div.footer div.first_text_footer div.img_size{height:95px;}@media (max-width: 768px){footer#global-footer div.footer .info-wrap{margin-bottom:0px;}footer#global-footer .footer .text_footer .images_box{max-width:215px;}footer#global-footer .footer .text_footer .images_box{margin:0 auto 0px auto;}footer#global-footer div.footer div.first_text_footer div.img_size{margin-bottom:0;}}div#modal-global-contact-us .contact-form{-webkit-background-position:bottom;background-position:bottom;}div#modal-global-contact-us .contact-form .info-zone .info-zone_contact_cell{margin-bottom:21px;}div#modal-global-contact-us .contact-form .info-zone .type_user:nth-of-type(2){margin-bottom:21px;}@media only screen and (max-width: 768px){div#modal-global-contact-us .contact-form .info-zone .type_user{margin-bottom:25px;}}div#modal-global-contact-us .contact-form .info-zone_contact{margin-bottom:14px;}div#modal-global-contact-us .contact-form .section-message h2{font-size:38px;}@media only screen and (max-width: 768px){div#modal-global-contact-us .contact-form .section-message h2{font-size:28px;}}div#modal-global-contact-us .contact-form h2{font-size:38px;}@media only screen and (max-width: 768px){div#modal-global-contact-us .contact-form h2{font-size:28px;}}div#modal-global-contact-us .contact-form .info-zone_contact_link:hover{color:var(--light)!important;}div#modal-global-contact-us .contact-form .section-message:after{background:var(--light);}div#modal-global-contact-us .contact-form .socials_zone li{padding-right:8px!important;padding-left:8px!important;}@media only screen and (max-width: 768px){div#modal-global-contact-us .contact-form .socials_zone li{padding-right:12px!important;padding-left:12px!important;}}div#modal-global-contact-us .contact-form .section-message label{text-transform:uppercase;}div#modal-global-contact-us .contact-form span.lp-tcr-message{font-weight:400;text-transform:none;}div#modal-global-contact-us .contact-form .section-message form .submitButton{padding:20px 46px;}div#modal-global-contact-us .contact-form .contact-form .section-message label{text-transform:uppercase!important;}@media only screen and (max-width: 768px){div#modal-global-contact-us .close{top:8vh!important;}}div#modal-global-contact-us .contact-form .socials_zone{padding-left:0;}div#modal-global-contact-us .close{margin-top:-35px;}
31div#modal-global-contact-us div.section-details div:nth-child(2) p.info-zone_contact_link.pre-line{font-weight:400;}#modal-global-contact-us .contact-form:after{background-color:rgba(0, 0, 0, 0.7)!important;}#modal-global-contact-us .contact-form .section-message label{color:var(--light)!important;}#modal-global-contact-us .lp-input-group .lp-input{border-color:var(--light)!important;}div#modal-global-contact-us a:not(.lp-socials__link):after{background-color:var(--light)!important;}#modal-global-contact-us div.section-details div:nth-child(3) p.info-zone_contact_link.pre-line{font-weight:400;}div#global-sidemenu.sidemenu a{text-transform:uppercase;}div#global-sidemenu.sidemenu a:hover{color:var(--accent);}div#global-sidemenu.sidemenu .sub-nav.visible+.main-nav{color:var(--dark);}div#global-sidemenu.sidemenu .sidebar__subnav-link{color:var(--dark);}@media only screen and (max-width: 1280px){footer#global-footer .text_footer.first_text_footer div.luxury-text{padding-top:30px;}footer#global-footer .text_footer.first_text_footer .link{color:var(--dark);overflow-wrap:anywhere;-webkit-text-decoration:underline!important;text-decoration:underline!important;white-space:normal!important;}footer#global-footer .text_footer.first_text_footer .link:before{background-color:transparent!important;}footer#global-footer .text_footer.first_text_footer .link:after{background-color:transparent!important;}}body>div.mobile-contact-wrapper .connect-btn{border:2px solid var(--primary)!important;background-color:var(--primary)!important;color:var(--light)!important;}body>div.mobile-contact-wrapper .connect-btn:hover{border-color:var(--primary)!important;background-color:var(--primary)!important;color:var(--light)!important;}body>div.mobile-contact-wrapper .search-btn{border:2px solid var(--primary)!important;background-color:var(--primary)!important;color:var(--light)!important;}body>div.mobile-contact-wrapper .search-btn:hover{border-color:var(--primary)!important;background-color:var(--primary)!important;color:var(--light)!important;}body>div.mobile-contact-wrapper .lp-btn{border:2px solid var(--primary)!important;background-color:var(--trans)!important;color:var(--primary)!important;}body>div.mobile-contact-wrapper .lp-btn:hover{border-color:var(--primary)!important;background-color:var(--primary)!important;color:var(--light)!important;}body>div.mobile-contact-wrapper .contact-form__item .lp-input{color:var(--dark);opacity:1;border-color:var(--dark);text-transform:none;}body>div.mobile-contact-wrapper h3{color:var(--dark);}body>div.mobile-contact-wrapper .lp-tcr-content{color:var(--dark);}body>div.mobile-contact-wrapper .pop-up .close-btn:before{-webkit-filter:invert(0);filter:invert(0);}body>div.mobile-contact-wrapper .pop-up .lp-container{background-color:var(--light)!important;}@media only screen and (max-width:768px){body>div.mobile-contact-wrapper .pop-up .lp-container{padding-top:96px;}}div#global-sidemenu.sidemenu .section-options a:hover{color:#363636;border-bottom:2px solid #363636!important;max-width:700px;}div#global-sidemenu.sidemenu .sub-nav-container a{color:#363636!important;text-transform:uppercase;}div#global-sidemenu.sidemenu .sub-nav-container a:hover{color:#363636!important;border-bottom:2px solid #363636!important;}div#global-sidemenu.sidemenu .sub-nav-container .main-nav:hover{color:#363636!important;border-bottom:2px solid #363636!important;}div#global-sidemenu.sidemenu .sub-nav-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;-webkit-box-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-align-content:space-around;-ms-flex-line-pack:space-around;align-content:space-around;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}div#global-sidemenu.sidemenu .sub-nav-container ul li{list-style:none;}div#global-sidemenu.sidemenu .title{text-transform:uppercase;}@media only screen and (max-width: 768px){div#global-sidemenu.sidemenu .sub-nav.visible{max-height:730px;}div#global-sidemenu.sidemenu .section-options a{font-size:30px;}div#global-sidemenu.sidemenu .sub-nav a{font-size:23px;}}div#global-sidemenu.sidemenu .sub-nav a{font-size:21px;}@media only screen and (max-width:768px){div#global-sidemenu.sidemenu button.toggle{right:25px!important;}}@media (max-width:768px){div#global-sidemenu.sidemenu a{font-size:21px;}}#global-mobile-contact .mobile-contact{z-index:9999!important;}nav .header{height:75px!important;}nav .header .navigation .sub-nav__link{padding:13px 15px!important;}@media only screen and (max-width: 768px){.sidebar__content{margin-top:20px;}h1.title.star-overlay{font-size:28px;}}</style> 32 <style id="wow-hide-elements">.wow{visibility:hidden!important}</style> 33 <style id="page-css"> 34 #section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3{color:rgba(255, 255, 255, 1);--fontColor:rgba(255, 255, 255, 1);--fontColor_H:0;--fontColor_S:0%;--fontColor_L:100%;--fontColor_A:1;--fontColor_darkenDir:-1;--bgColor:#ffffff;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:1;--bgColor_darkenDir:-1;background-color:#ffffff;--gradient-color:var(--overlay-color, rgba(0, 0, 0, 0.3));background-image:linear-gradient(var(--gradient-color), var(--gradient-color)),url('https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/e0c3d97e-0124-4558-bd78-6c9f5b568846');background-repeat:no-repeat;-webkit-background-position:center;background-position:center;-webkit-background-size:cover;background-size:cover;}#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 div.custom-intro{height:600px;}#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 h1{text-shadow:0 2px 6px rgba(0, 0, 0, 0.6);}#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .custom-intro{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;height:600px;-webkit-box-pack:center;-ms-flex-pack:center;
34-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .custom-intro .container{z-index:1;text-align:center;max-width:900px;}#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .custom-intro__title{margin-bottom:0px;font-weight:400;margin-bottom:24px;}@media (max-width: 768px){#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .custom-intro__title{font-size:32px;}}@media (max-width: 360px){#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .custom-intro__title{font-size:22px;}}#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .custom-intro__subtitle{font-weight:400;white-space:pre-line;font-size:21px;line-height:1.57;}@media (max-width: 768px){#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .custom-intro__subtitle{font-size:18px;}}#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3 .description{margin-bottom:15px;}@media (min-width: 960px) and (orientation: landscape){#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3{background-image:linear-gradient(var(--gradient-color), var(--gradient-color)),url('https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/e0c3d97e-0124-4558-bd78-6c9f5b568846');}}@media (min-width: 1280px) and (orientation: landscape){#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3{background-image:linear-gradient(var(--gradient-color), var(--gradient-color)),url('https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1920/https://media-production.lp-cdn.com/media/e0c3d97e-0124-4558-bd78-6c9f5b568846');}}@media (min-width: 1920px) and (orientation: landscape){#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3{background-image:linear-gradient(var(--gradient-color), var(--gradient-color)),url('https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=2560/https://media-production.lp-cdn.com/media/e0c3d97e-0124-4558-bd78-6c9f5b568846');}}@media (min-width: 2560px) and (orientation: landscape){#section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3{background-image:linear-gradient(var(--gradient-color), var(--gradient-color)),url('https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=3456/https://media-production.lp-cdn.com/media/e0c3d97e-0124-4558-bd78-6c9f5b568846');}}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02{color:#000;--fontColor:#000;--fontColor_H:0;--fontColor_S:0%;--fontColor_L:0%;--fontColor_A:1;--fontColor_darkenDir:1;--bgColor:#fff;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:1;--bgColor_darkenDir:-1;background-color:#fff;}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .boxed-text__description{margin-bottom:32px;text-align:center;}@media (max-width: 768px){#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .boxed-text__description{margin-bottom:24px;}}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .contact-cta{text-align:center;}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .lp-title-group .lp-h2{margin-top:0;margin-bottom:14px;}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .contact-phone{display:inline-block;font-size:42px;line-height:1.15;font-weight:500;letter-spacing:1px;-webkit-text-decoration:none;text-decoration:none;color:inherit;margin-bottom:26px;-webkit-transition:opacity 0.25s ease;transition:opacity 0.25s ease;}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .contact-phone:hover{opacity:0.7;}@media (max-width: 768px){#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .contact-phone{font-size:34px;}}@media (max-width: 480px){#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .contact-phone{font-size:28px;}}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .button-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:20px;}@media (max-width: 600px){#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .button-container{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:14px;}}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .button-container .lp-btn{margin:0;min-width:150px;}@media (max-width: 600px){#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .button-container .lp-btn{width:100%;}}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .lp-text--subtitle{margin-left:auto;margin-right:auto;text-transform:none;}#section-aaaa421e-7c8d-4472-bfab-8e962f13cf02 .redesign p{margin-bottom:1.666rem;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72{color:#363636;--fontColor:#363636;--fontColor_H:0;--fontColor_S:0%;--fontColor_L:21%;--fontColor_A:1;--fontColor_darkenDir:1;--bgColor:#ffffff;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:1;--bgColor_darkenDir:-1;--section-padding-top:calc(4 / 4 * var(--global-section-padding));--section-padding-bottom:calc(4 / 4 * var(--global-section-padding));background-color:#ffffff;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .uf-cus-sel-item:hover{background-color:var(--primary);color:var(--light);}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .custom-form__img-block{background:transparent center/cover no-repeat;height:450px;}@media only screen and (max-width:768px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .custom-form__img-block{height:430px;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .customa-form__header{max-width:1250px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form h2{color:var(--dark);}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .custom-form__header{max-width:1200px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-label{text-transform:none;color:var(--dark);}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-input{border-color:var(--dark);}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-disclaimer a{-webkit-text-decoration:none!important;text-decoration:none!important;font-weight:400;position:relative!important;color:var(--dark)!important;-webkit-transition:0.4s;transition:0.4s;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-disclaimer a:hover{color:var(--dark)!important;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-disclaimer a:before,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-disclaimer a:after{-webkit-transition:0.4s;transition:0.4s;-webkit-text-decoration:none!important;text-decoration:none!important;line-height:1;content:"";height:1px;position:absolute!important;bottom:0;left:0;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-disclaimer a:before{width:100%!important;background-color:var(--light-gray)!important;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-disclaimer a:after{width:0%!important;background-color:var(--primary)!important;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__form-col .lp-disclaimer a:hover:after{width:100%!important;}@media only screen and (max-width:1024px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.elem-row{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__img-col{margin:auto;margin-bottom:30px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__footer{-webkit-box-pack:center;-ms-flex-pack:center;
34-webkit-justify-content:center;justify-content:center;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .custom-form__img-block img{object-fit:cover;}}@media only screen and (max-width:820px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.elem-row{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__img-col{margin:auto;margin-bottom:30px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__footer{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .custom-form__img-block img{object-fit:cover;}}@media only screen and (max-width:768px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.elem-row{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__img-col{margin:auto;margin-bottom:30px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form__footer{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .custom-form__img-block img{object-fit:cover;}}@media only screen and (max-width:767px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 div.custom-form .custom-form__img-block img{object-fit:cover;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72.modal.is-background-color-light>button.close{padding:5px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72.modal.is-background-color-light>button.close:before{content:'';width:100%;display:block;padding-bottom:100%;-webkit-clip-path:polygon(8% 0, 50% 42%, 92% 0, 100% 8%, 58% 50%, 100% 92%, 92% 100%, 50% 58%, 8% 100%, 0 92%, 42% 50%, 0 8%);clip-path:polygon(8% 0, 50% 42%, 92% 0, 100% 8%, 58% 50%, 100% 92%, 92% 100%, 50% 58%, 8% 100%, 0 92%, 42% 50%, 0 8%);background-color:#000;-webkit-transition:all .3s ease;transition:all .3s ease;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72.modal.is-background-color-light>button.close:hover:before{-webkit-transform:scale(1.2);-moz-transform:scale(1.2);-ms-transform:scale(1.2);transform:scale(1.2);}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72.modal.is-background-color-light>button.close>img,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72.modal.is-background-color-light>button.close .lp-close-icon{display:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .elem-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-left:-16px;margin-right:-16px;-webkit-box-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;}@media (max-width: 767px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .elem-row{-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .elem-col{min-height:1px;padding-left:16px;padding-right:16px;}@media (max-width: 767px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .elem-col{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;max-width:unset;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .form-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;margin-left:-16px;margin-right:-16px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .form-col{padding-left:16px;padding-right:16px;-webkit-flex:1 1 400px;-ms-flex:1 1 400px;flex:1 1 400px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .form-col:last-child .custom-form__group{margin-bottom:20px;}@media (min-width: 768px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .form-col:last-child .custom-form__group{margin-bottom:30px;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-label{text-transform:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-label.field-required:after{content:' *';}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form{padding-top:80px;padding-bottom:80px;}@media (max-width: 767px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form{padding-top:50px;padding-bottom:50px;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__img-col{margin-bottom:30px;}@media (min-width: 768px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__img-col{margin-bottom:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%;}}@media (min-width: 768px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__form-col{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;}}@media (min-width: 992px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__form-col{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__header{max-width:600px;margin-left:auto;margin-right:auto;margin-bottom:50px;text-align:center;}@media (max-width: 767px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__header{margin-bottom:30px;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__heading{margin-bottom:24px;}@media (max-width: 767px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__heading{margin-bottom:13px;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__description{margin-bottom:0;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__img-block{width:100%;height:430px;background:currentColor center/cover no-repeat;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__img-block img{height:100%;width:100%;object-fit:cover;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__download-form{width:100%;margin-bottom:0;}@media (min-width: 992px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__download-form{height:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:start;-ms-flex-pack:start;
34-webkit-justify-content:flex-start;justify-content:flex-start;}}@media (min-width: 768px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__container{max-width:1160px;margin-left:auto;margin-right:auto;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .form-field-descr{opacity:0.5;margin-top:8px;font-size:82%;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-btn-icons{width:0;-webkit-transition:width .3s ease;transition:width .3s ease;display:inline-block;float:left;line-height:inherit;overflow:visible;position:relative;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-btn-icons:before{content:'';display:inline-block;width:0px;height:1em;vertical-align:middle;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-btn-icons .lp-btn-icon-loading{position:absolute;display:block;width:0;height:17px;opacity:0;top:50%;left:0;-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:width .3s ease,opacity .3s ease;transition:width .3s ease,opacity .3s ease;overflow:hidden;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-btn-icons .lp-btn-icon-loading:before{content:none;display:block;background-color:currentColor;width:17px;height:17px;-webkit-clip-path:path('M8.5 0A 8.5 8.5 0 1 1 1.89 3.15L 4.23 5.04A 5.5 5.5 0 1 0 8.5 3Z');clip-path:path('M8.5 0A 8.5 8.5 0 1 1 1.89 3.15L 4.23 5.04A 5.5 5.5 0 1 0 8.5 3Z');-webkit-animation:i-spin 2s linear infinite;animation:i-spin 2s linear infinite;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-btn-icons .lp-btn-icon-success{position:absolute;display:block;width:0;height:17px;opacity:0;top:50%;left:0;-webkit-transform:translateY(-50%) scale(1.02);-moz-transform:translateY(-50%) scale(1.02);-ms-transform:translateY(-50%) scale(1.02);transform:translateY(-50%) scale(1.02);-webkit-transition:width .3s ease,opacity .3s ease;transition:width .3s ease,opacity .3s ease;background-color:currentColor;-webkit-clip-path:path('M0 8.5 A 8.5 8.5 0 0 1 17 8.5 A 8.5 8.5 0 0 1 0 8.5 H 1.2 A 7.3 7.3 0 1 0 15.8 8.5 A 7.3 7.3 0 1 0 1.2 8.5 H0 m5.201-.344L7.4 10.35l4.436-4.45c.311-.202.58-.191.807.033.227.225.25.488.072.788L7.85 11.59c-.14.141-.291.212-.451.212-.16 0-.31-.061-.45-.183L4.338 8.99c-.192-.311-.172-.58.06-.806.231-.226.5-.235.803-.027');clip-path:path('M0 8.5 A 8.5 8.5 0 0 1 17 8.5 A 8.5 8.5 0 0 1 0 8.5 H 1.2 A 7.3 7.3 0 1 0 15.8 8.5 A 7.3 7.3 0 1 0 1.2 8.5 H0 m5.201-.344L7.4 10.35l4.436-4.45c.311-.202.58-.191.807.033.227.225.25.488.072.788L7.85 11.59c-.14.141-.291.212-.451.212-.16 0-.31-.061-.45-.183L4.338 8.99c-.192-.311-.172-.58.06-.806.231-.226.5-.235.803-.027');}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading input,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .success input,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading select,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .success select,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading button,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .success button{pointer-events:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading .lp-btn-icons,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .success .lp-btn-icons{width:27px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading .lp-btn-icons .lp-btn-icon-loading,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .success .lp-btn-icons .lp-btn-icon-loading{width:17px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading .lp-btn-icons .lp-btn-icon-success,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .success .lp-btn-icons .lp-btn-icon-success{width:17px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading .lp-btn-icons .lp-btn-icon-loading{opacity:1;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .loading .lp-btn-icons .lp-btn-icon-loading:before{content:'';}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .success .lp-btn-icons .lp-btn-icon-success{opacity:1;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .js-backup-email{display:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-h-pot{height:0;overflow:hidden;visibility:hidden;position:absolute;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .visually-hidden{position:absolute;overflow:hidden;clip:rect(0 0 0 0);width:1px;height:1px;margin:-1px;padding:0;border:0;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-content{max-height:210px;overflow-y:auto;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-input-group .uf-cus-sel-toggle{width:100%;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel{position:relative;width:100%;--optionHoverColor:hsl(var(--bgColor_H), calc(var(--bgColor_S) + 6% * var(--bgColor_darkenDir)), calc(var(--bgColor_L) + 14% * var(--bgColor_darkenDir)));}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-toggle{position:relative;display:block;width:100%;font-family:inherit;text-align:left;text-transform:none;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:all .25s;transition:all .25s;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-toggle.is-placeholder{color:#999;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-toggle:after{box-sizing:border-box;content:"";position:absolute;right:20px;top:50%;margin-top:0;height:10px;width:10px;border-top:2px solid currentColor;border-left:2px solid currentColor;-webkit-transform:rotateZ(-135deg) translateY(10px);-moz-transform:rotateZ(-135deg) translateY(10px);-ms-transform:rotateZ(-135deg) translateY(10px);transform:rotateZ(-135deg) translateY(10px);-webkit-transition:all .2s;transition:all .2s;}@media (min-width: 992px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-toggle:after{right:25px;}}.uf-cus-sel.open #section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-toggle:after{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-menu{display:none;position:absolute;width:calc(100% + var(--uf-border-left, 0px) + var(--uf-border-right, 0px));top:100%;left:calc(0px - var(--uf-border-left, 0px));z-index:1;}@media (max-width: 768px){#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-menu{position:relative;top:auto;}}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-content{width:100%;background-color:var(--bgColor, #000);border:1px solid #979797;border-top:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-item{display:block;width:100%;padding:11px 24px;border:solid 1px transparent;background:transparent;border-radius:0;color:inherit;font-family:inherit;font-size:inherit;line-height:24px;text-align:left;text-transform:none;-webkit-transition:all .25s;transition:all .25s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-item:focus,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-item:hover{background-color:var(--optionHoverColor, #262222);}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-item.is-selected{font-weight:700;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-item.is-disabled,#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .uf-cus-sel-item:disabled{display:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-text--subtitle{margin-left:auto;margin-right:auto;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__checkbox-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;gap:8px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__checkbox-container .lp-label{opacity:1;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__checkboxes-label{font-size:14px;line-height:1.43;font-weight:600;margin-bottom:0;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__checkboxes-description{font-size:14px;line-height:1.43;font-weight:400;margin-bottom:0;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__checkbox-item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:10px;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .custom-form__checkbox-label{cursor:pointer;font-size:inherit;line-height:1.4;margin:0;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72>div:last-child{padding-top:calc(4 / 4 * var(--global-section-padding))!important;padding-bottom:calc(4 / 4 * var(--global-section-padding))!important;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-input::-webkit-input-placeholder{text-transform:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-input::-moz-placeholder{text-transform:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-input:-ms-input-placeholder{text-transform:none;}#section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72 .lp-input::placeholder{text-transform:none;}#section-7819d273-7c47-485a-a46c-0941f4a0491f{color:#fff;--fontColor:#fff;--fontColor_H:0;--fontColor_S:0%;--fontColor_L:100%;--fontColor_A:1;--fontColor_darkenDir:-1;--bgColor:#363636;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:21%;--bgColor_A:1;--bgColor_darkenDir:1;background-color:#363636;}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component{padding-top:96px;padding-bottom:46px;}@media (max-width: 768px){#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component{padding-top:64px;padding-bottom:44px;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card__title{text-align:center;margin-top:auto;margin-bottom:0;font-size:32px;text-transform:uppercase;}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col{padding-right:10px;padding-left:10px;}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card{width:100%;padding-right:20px;padding-left:20px;height:300px;}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card:before{background-color:rgba(43, 71, 89, 0);transition-duration:0.5s;}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card:hover:before{background-color:rgba(43, 71, 89, 0);transition-duration:0.5s;}@media only screen and (max-width: 768px){#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;padding-right:5px;padding-left:5px;}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card{height:350px;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col:last-child{margin-left:auto;margin-right:auto;}@media only screen and (max-width:1024px){#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card__title{font-size:25px;}}@media only screen and (max-width:820px){#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card__title{font-size:20px;}}@media only screen and (max-width:768px){#section-7819d273-7c47-485a-a46c-0941f4a0491f div.gallery-component__col .gallery-card__title{font-size:1.5em;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component{padding-top:30px;padding-bottom:10px;}@media (min-width: 769px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component{padding:80px 0 60px;}}
34@media (min-width: 1200px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component{padding:80px 0 30px;}}@media (max-width: 767px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__container{padding-left:20px;padding-right:20px;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__header{margin-bottom:30px;max-width:640px;margin-left:auto;margin-right:auto;text-align:center;}@media (min-width: 768px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__header{margin-bottom:50px;}}@media (min-width: 1200px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__header{margin-bottom:70px;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__header img{max-width:260px;height:auto;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__header img:not(:only-child){margin-bottom:30px;}@media (min-width: 768px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__header img:not(:only-child){margin-bottom:50px;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__heading{margin-bottom:20px;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__lead{margin-bottom:0;font-size:20px;line-height:1.4;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__row{margin-left:-7px;margin-right:-7px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__col{width:100%;margin-bottom:20px;padding:0 7px;}@media (min-width: 768px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__col{max-width:33.333333%;-webkit-flex-basis:33.333333%;-ms-flex-preferred-size:33.333333%;flex-basis:33.333333%;}}@media (min-width: 1200px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__col{max-width:25%;-webkit-flex-basis:25%;-ms-flex-preferred-size:25%;flex-basis:25%;margin-bottom:50px;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__col:first-child{margin-left:auto;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component__col:last-child{margin-right:auto;}@media (min-width: 992px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component .cols-2 .gallery-component__col{max-width:50%;-webkit-flex-basis:50%;-ms-flex-preferred-size:50%;flex-basis:50%;}}@media (min-width: 1200px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component .cols-3 .gallery-component__col{max-width:33.333333%;-webkit-flex-basis:33.333333%;-ms-flex-preferred-size:33.333333%;flex-basis:33.333333%;}}@media (min-width: 992px){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-component .cols-4 .gallery-component__col{max-width:25%;-webkit-flex-basis:25%;-ms-flex-preferred-size:25%;flex-basis:25%;}}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card{position:relative;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-end;-webkit-box-align:flex-end;-ms-flex-align:flex-end;align-items:flex-end;padding:20px 15px;-webkit-text-decoration:none;text-decoration:none;overflow:hidden;cursor:pointer;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card:after{content:"";width:0;padding-top:121.5%;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card:before{content:"";position:absolute;left:0;bottom:0;width:100%;height:100%;background-color:transparent;background-image:linear-gradient(to bottom, rgba(0, 0, 0, 0) 76.6%, #000000);opacity:0.6;-webkit-transform:translate3d(0, 0, 0);-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);-webkit-transition:background-color .3s;transition:background-color .3s;z-index:1;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card:focus{outline:none;}@media (hover: hover) and (pointer: fine){#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card:hover:before{background-color:#000;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card:hover .gallery-card__title{-webkit-transform:translateY(-51px);-moz-transform:translateY(-51px);-ms-transform:translateY(-51px);transform:translateY(-51px);}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card:hover .gallery-card__title:after{opacity:.3;-webkit-transform:translateY(20px);-moz-transform:translateY(20px);-ms-transform:translateY(20px);transform:translateY(20px);}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card:hover .gallery-card__preview img{-webkit-transform:scale(1.05);-moz-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05);}}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card__title{position:relative;width:100%;margin-bottom:0;color:#fff;letter-spacing:0;text-shadow:none;z-index:1;
34-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:all .3s;transition:all .3s;text-transform:none;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card__title:after{content:"";position:absolute;left:0;bottom:0;width:100%;border-bottom:1px solid currentColor;opacity:0;-webkit-transition:all .3s;transition:all .3s;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card__preview{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;}#section-7819d273-7c47-485a-a46c-0941f4a0491f .gallery-card__preview>img{width:100%;height:100%;object-fit:cover;-webkit-transform:translate3d(0, 0, 0);-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);-webkit-transition:-webkit-transform .75s ease-out;transition:transform .75s ease-out;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b{color:#fff;--fontColor:#fff;--fontColor_H:0;--fontColor_S:0%;--fontColor_L:100%;--fontColor_A:1;--fontColor_darkenDir:-1;--bgColor:#363636;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:21%;--bgColor_A:1;--bgColor_darkenDir:1;background-color:#363636;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed{padding:80px 0;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .title{margin:0 20px 0 0;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .instagram-link{display:block;margin:0 20px 0 0;color:var(--global-primary-font-color);}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .instagram-link .instagram-name{display:inline;margin:0;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .title+.instagram-link{margin-top:5px;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-wrapper{margin-bottom:20px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:flex-end;-webkit-box-align:flex-end;-ms-flex-align:flex-end;align-items:flex-end;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-right{margin-left:auto;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:stretch;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .follow-button{margin:20px 0 0 0;display:block;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .nav-button{margin-top:20px;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;width:42px;color:#1a1a1a;border:1px solid currentColor;cursor:pointer;transition-property:color,background-color,border-color;transition-duration:.3s;transition-timing-function:ease;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .nav-button.slick-disabled{opacity:0.6;pointer-events:none;cursor:default;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .nav-button:not(.slick-disabled):hover{background-color:#1a1a1a;border-color:#1a1a1a;color:#fff;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-nav-prev{margin-left:30px;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-nav-next{margin-left:10px;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .hidden-control{display:none;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi{position:relative;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:calc(100% / 3);padding:10px;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single:first-child,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi:first-child{margin-left:auto;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single:last-child,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi:last-child{margin-right:auto;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single.type2,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi.type2{width:calc(100% / 5 * 2);}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single.type3,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi.type3{width:calc(100% / 2);}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single.type4,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi.type4{width:calc(100% / 2);}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single.type5,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi.type5{width:100%;}@media (max-width: 440px){#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-container{padding:0;width:100%;}}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-feed{width:calc(100% + 20px);position:relative;
34left:-10px;overflow:hidden;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-slider{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-item__img{position:absolute;left:-1px;top:-1px;bottom:-1px;right:-1px;background:center/cover no-repeat;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-item__info{position:absolute;top:0;left:0;bottom:0;right:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;padding:10%;overflow:hidden;color:#fff;text-align:center;background-color:rgba(0, 0, 0, 0.8);opacity:0;-webkit-transition:opacity .3s ease;transition:opacity .3s ease;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-item:hover .ig-feed-item__info{opacity:1;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-item__caption{text-overflow:ellipsis;-webkit-line-clamp:4;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .video-icon{position:absolute;width:50px;height:50px;background-color:#fff;left:50%;top:50%;-webkit-transform:translate(-50%, -50%);-moz-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);border-radius:50%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-transition:opacity .2s ease;transition:opacity .2s ease;opacity:1;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .video-icon::before{content:'';display:block;width:0px;height:0px;border-style:solid;position:relative;left:1px;border-width:7.5px 0px 7.5px 11px;border-color:transparent transparent transparent #292826;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-item:hover .video-icon{opacity:0;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single .ig-feed-item__info{padding:15%;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-single .ig-feed-item__caption{-webkit-line-clamp:7;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed-item{background-color:var(--tileColor, #000);display:block;width:100%;padding-bottom:125%;overflow:hidden;position:relative;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi::before{content:'';display:block;width:100%;padding-bottom:125%;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi-content{padding:10px;position:absolute;width:100%;height:100%;left:0;top:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;overflow:hidden;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi-content .ig-feed-item{width:calc(50% - 10px);padding-bottom:calc(62.5% - 12.5px);}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .slide-multi-content .ig-feed-item:nth-child(n + 3){-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .bottom-controls{width:100%;display:none;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .bottom-nav-button{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin:20px 10px 0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;
34-webkit-justify-content:center;justify-content:center;width:48px;height:48px;color:#1a1a1a;border:1px solid currentColor;cursor:pointer;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .bottom-nav-button.slick-disabled{opacity:0.6;pointer-events:none;cursor:default;}@media (max-width: 767px){#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-right,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-left{width:100%;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .title,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .instagram-link{margin-right:0;text-align:center;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-nav-prev,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .top-nav-next{display:none;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .bottom-controls{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .ig-feed{display:none;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b .has-data .ig-feed{display:block;}#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b.has-data .ig-feed,#section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b#section-temp .ig-feed{display:block;}#modal-global-contact-us .close{z-index:11;}#modal-global-contact-us .description{margin-bottom:15px;}#modal-global-contact-us .close:focus{outline:0;}#modal-global-contact-us .contact-form{padding:70px 0;width:100%;min-height:100vh;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;position:relative;color:var(--colorTxt, #ffffff);-webkit-background-size:cover;background-size:cover;}#modal-global-contact-us .contact-form:after{content:'';position:absolute;display:block;background-color:rgba(2, 5, 7, 0.85);height:100%;width:100%;z-index:0;}#modal-global-contact-us .contact-form.loading textarea,#modal-global-contact-us .contact-form.loading input,#modal-global-contact-us .contact-form.loading label,#modal-global-contact-us .contact-form.loading button{pointer-events:none;opacity:.5;}#modal-global-contact-us .contact-form.loading .submit-icon{display:inline-block;}#modal-global-contact-us .contact-form .submit-icon{display:none;}#modal-global-contact-us .contact-form .contact-form-close{width:40px;height:50px;display:block;padding:0;border:none;background-color:transparent;cursor:pointer;position:absolute;right:50px;top:50px;z-index:110;}@media (max-width: 560px){#modal-global-contact-us .contact-form .contact-form-close{right:20px;top:20px;width:30px;height:40px;}}#modal-global-contact-us .contact-form .contact-form-close:before,#modal-global-contact-us .contact-form .contact-form-close:after{content:'';display:block;width:40px;height:1px;background-color:#fff;position:absolute;left:50%;top:50%;}@media (max-width: 560px){#modal-global-contact-us .contact-form .contact-form-close:before,#modal-global-contact-us .contact-form .contact-form-close:after{width:30px;}}#modal-global-contact-us .contact-form .contact-form-close:before{-webkit-transform:translate(-50%, -50%) rotate(45deg);-moz-transform:translate(-50%, -50%) rotate(45deg);-ms-transform:translate(-50%, -50%) rotate(45deg);transform:translate(-50%, -50%) rotate(45deg);}#modal-global-contact-us .contact-form .contact-form-close:after{-webkit-transform:translate(-50%, -50%) rotate(-45deg);-moz-transform:translate(-50%, -50%) rotate(-45deg);-ms-transform:translate(-50%, -50%) rotate(-45deg);transform:translate(-50%, -50%) rotate(-45deg);}#modal-global-contact-us .contact-form .container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:1440px;width:100%;padding:0 160px;margin:0 auto;z-index:10;}@media (max-width: 1320px){#modal-global-contact-us .contact-form .container{padding:0 80px;}}@media (max-width: 1200px){#modal-global-contact-us .contact-form .container{padding:0 30px;}}@media (max-width: 900px){#modal-global-contact-us .contact-form .container{-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}}
34@media (max-width: 560px){#modal-global-contact-us .contact-form .container{padding:0 20px;}}#modal-global-contact-us .contact-form h2{margin:0 0 18px 0;padding:0;}@media (max-width: 560px){#modal-global-contact-us .contact-form h2{margin:0 0 24px 0;}}#modal-global-contact-us .contact-form .section-details{width:50%;}@media (max-width: 1200px){#modal-global-contact-us .contact-form .section-details{padding-right:30px;}}@media (max-width: 900px){#modal-global-contact-us .contact-form .section-details{width:100%;padding-right:0;max-width:700px;margin-bottom:38px;}}#modal-global-contact-us .contact-form .section-message{width:50%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;position:relative;}@media (max-width: 1200px){#modal-global-contact-us .contact-form .section-message{padding-left:30px;}}@media (max-width: 900px){#modal-global-contact-us .contact-form .section-message{width:100%;padding-left:0;-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;}}#modal-global-contact-us .contact-form .section-message:after{content:'';position:absolute;display:block;width:1px;background:#999999;height:calc(100% + 50px);left:0;top:-20px;}@media (max-width: 900px){#modal-global-contact-us .contact-form .section-message:after{display:none;}}#modal-global-contact-us .contact-form .section-message form{max-width:435px;width:100%;}#modal-global-contact-us .contact-form .section-message form .submitButton{width:auto;}@media (max-width: 560px){#modal-global-contact-us .contact-form .section-message form .submitButton{width:100%;}}@media (max-width: 900px){#modal-global-contact-us .contact-form .section-message form{max-width:700px;}}#modal-global-contact-us .contact-form .section-message form.loading textarea,#modal-global-contact-us .contact-form .section-message form.loading input,#modal-global-contact-us .contact-form .section-message form.loading label,#modal-global-contact-us .contact-form .section-message form.loading button{pointer-events:none;opacity:.5;}#modal-global-contact-us .contact-form .section-message form.loading .label-loading{display:inline;}#modal-global-contact-us .contact-form .section-message form.loading .label-success,#modal-global-contact-us .contact-form .section-message form.loading .label-initial{display:none;}#modal-global-contact-us .contact-form .section-message form.loading .submit-icon{display:inline-block;}#modal-global-contact-us .contact-form .section-message form.success .label-loading,#modal-global-contact-us .contact-form .section-message form.success .label-initial{display:none;}#modal-global-contact-us .contact-form .section-message form.success .label-success{display:inline;}#modal-global-contact-us .contact-form .section-message .label-loading,#modal-global-contact-us .contact-form .section-message .label-success{display:none;}#modal-global-contact-us .contact-form .section-message .submit-icon{display:none;}#modal-global-contact-us .contact-form .section-message h2{margin-bottom:28px;}#modal-global-contact-us .contact-form .section-message .form-group_modal{-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:39px;}#modal-global-contact-us .contact-form .section-message .form-group_modal input{border:none;border-bottom:1px solid #c0c0c0;display:block;width:100%;background:transparent;color:#ffffff;height:22px;font-size:16px;}@media (max-width: 560px){#modal-global-contact-us .contact-form .section-message .form-group_modal input{height:25px;}}#modal-global-contact-us .contact-form .section-message .form-group-textarea{margin-bottom:30px;}@media (max-width: 560px){#modal-global-contact-us .contact-form .section-message .form-group-textarea{margin-bottom:23px;}}#modal-global-contact-us .contact-form .section-message label{display:block;width:100%;line-height:1.63;letter-spacing:1px;color:#c0c0c0;font-weight:bold;text-transform:uppercase;}#modal-global-contact-us .contact-form .section-message textarea{resize:none;height:105px;width:100%;background:transparent;border:solid 1px #ffffff;margin:23px 0 0 0;color:#ffffff;padding:10px;font-size:16px;}@media (max-width: 560px){#modal-global-contact-us .contact-form .section-message textarea{margin:10px 0 0 0;height:89px;}}#modal-global-contact-us .contact-form .info-zone h4{margin:0 0 16px 0;}@media (max-width: 560px){#modal-global-contact-us .contact-form .info-zone h4{margin:0 0 13px 0;}}#modal-global-contact-us .contact-form .info-zone .type_user:nth-of-type(2){margin-bottom:30px;}@media (max-width: 560px){#modal-global-contact-us .contact-form .info-zone .type_user{margin-bottom:58px;}}#modal-global-contact-us .contact-form .info-zone_contact{margin-bottom:23px;}#modal-global-contact-us .contact-form .info-zone_contact:nth-last-child(2){margin-bottom:30px;}#modal-global-contact-us .contact-form .info-zone_contact_cell{position:relative;padding-left:45px;margin-bottom:22px;font-weight:bold;font-size:14px;max-width:90%;letter-spacing:1.5px;text-transform:uppercase;}@media (max-width: 560px){#modal-global-contact-us .contact-form .info-zone_contact_cell{padding-left:0;}}#modal-global-contact-us .contact-form .info-zone_contact_cell:last-of-type{margin-bottom:0;}#modal-global-contact-us .contact-form .info-zone_contact_cell i{position:absolute;
34left:0;top:0;display:block;}@media (max-width: 560px){#modal-global-contact-us .contact-form .info-zone_contact_cell i{position:relative;margin-bottom:7px;}}#modal-global-contact-us .contact-form .info-zone_contact_cell i svg path{fill:var(--colorTxt);}#modal-global-contact-us .contact-form .info-zone_contact_cell div{padding:0;}#modal-global-contact-us .contact-form .info-zone_contact_cell .contact_title{line-height:1;margin-bottom:5px;}#modal-global-contact-us .contact-form .info-zone_contact_link{color:var(--colorTxt);}@media (max-width: 560px){#modal-global-contact-us .contact-form .info-zone .type_user:nth-of-type(2){margin-bottom:58px;}}@media (max-width: 560px){#modal-global-contact-us .contact-form .hours_box{margin-bottom:52px;}}#modal-global-contact-us .contact-form .socials_zone{padding-left:45px;}@media (max-width: 560px){#modal-global-contact-us .contact-form .socials_zone{padding-left:0;}}#modal-global-contact-us .contact-form .socials_zone li{margin-bottom:10px;}#modal-global-contact-us .contact-form .socials_zone li:not(:last-child){padding-right:34px;}@media (max-width: 560px){#modal-global-contact-us .contact-form .socials_zone li:not(:last-child){padding-right:12px;}}#modal-global-contact-us .contact-form .success-message.success{margin-top:15px;color:var(--colorTxt);position:absolute;}#modal-global-contact-us .contact-form .success-message.hide{opacity:0;}#modal-global-contact-us .contact-form.one_contact .info-zone .type_user{margin-bottom:73px;}@media (max-width: 768px){#modal-global-contact-us .contact-form.one_contact .info-zone .type_user{margin-bottom:51px;}}@media (max-width: 560px){#modal-global-contact-us .contact-form.one_contact .info-zone .type_user{margin-bottom:40px;}}#modal-global-contact-us .contact-form.one_contact .hours_box{margin-bottom:38px;}#modal-global-contact-us .contact-form.no_icon .info-zone_contact_cell{padding-left:0;}#modal-global-contact-us .contact-form.no_icon .info-zone_contact_cell i{display:none;}#modal-global-contact-us .contact-form.no_icon .socials_zone{padding-left:0;}#modal-global-contact-us .contact-form .pre-line{white-space:pre-line;}#modal-global-contact-us .lp-input-group{margin-bottom:40px;}#modal-global-contact-us .lp-input-group.m16{margin-bottom:16px;}#modal-global-contact-us .lp-disclaimer{margin-top:0;}#modal-global-contact-us .lp-input{border-color:#ffffff;}#modal-global-contact-us .lp-input:focus,#modal-global-contact-us .lp-input:active{border-color:#5e5e5e;}nav{color:#fff;-webkit-transition:0.2s -webkit-transform ease;transition:0.2s transform ease;z-index:102;}nav.scroll .logo .logo__img.light{display:block;}nav.scroll .logo .logo__img.dark{display:none;}nav .header{height:100px;-webkit-transform:translateY(24px);-moz-transform:translateY(24px);-ms-transform:translateY(24px);transform:translateY(24px);}@media (max-width: 768px){nav .header{-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);}}nav .header .container{max-width:1440px;padding:0 15px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;}@media (max-width: 1024px){nav .header .container{padding:0 15px;}}nav .header .navbar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;min-height:70px;padding:8px 0 7px;width:100%;}nav .header .logo{z-index:911;position:relative;margin-right:10px;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}nav .header .logo a{overflow:hidden;display:inline-block;}nav .header .logo img{max-width:100%;max-height:52px;vertical-align:top;object-fit:contain;}@media (max-width: 1024px){nav .header .logo img{max-height:50px;}}nav .header .logo img.dark{display:none;}@media(max-width: 1024px){nav .header .logo img.dark{display:none!important;}}nav .header .logo img.light{display:block;}@media(max-width: 1024px){nav .header .logo img.light{display:inline-block!important;}}
34nav .header .logo__link{-webkit-animation-duration:1s;animation-duration:1s;overflow:hidden;}nav .header .logo__img.light{display:block;}nav .header .logo__img.dark{display:none;}nav .header .navigation{margin-left:auto;color:inherit;}@media (max-width: 1024px){nav .header .navigation{display:none;}}nav .header .navigation ul{position:relative;list-style-type:none;padding-left:0;margin-bottom:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}nav .header .navigation ul li a span,nav .header .navigation ul li button span{position:relative;white-space:nowrap;}nav .header .navigation ul li a span:after,nav .header .navigation ul li button span:after{content:'';position:absolute;display:block;height:1px;background-color:#c6c6c6;width:0;bottom:0;left:0;-webkit-transition:all .2s ease;transition:all .2s ease;}nav .header .navigation ul li a:hover span:after,nav .header .navigation ul li button:hover span:after{width:100%;-webkit-transition:all .2s ease;transition:all .2s ease;}nav .header .navigation__item{padding:0;margin:0;}nav .header .navigation__link{display:block;padding:12px 13px;color:inherit;position:relative;font-size:13px;line-height:1.08;font-weight:700;letter-spacing:1.5px;background-color:transparent;border:none;cursor:pointer;text-align:left;text-transform:uppercase;}@media (max-width: 1280px){nav .header .navigation__link{padding:19px 10px;font-size:11.5px;}}nav .header .navigation__link .sub-nav-container .navigation__link:hover{background:#000000;}nav .header .navigation .sub-nav{position:absolute;bottom:0;padding:0;opacity:0;visibility:hidden;-webkit-transition:all .2s ease;transition:all .2s ease;-webkit-transform:translate(0, calc(100% + -10px));-moz-transform:translate(0, calc(100% + -10px));-ms-transform:translate(0, calc(100% + -10px));transform:translate(0, calc(100% + -10px));}nav .header .navigation .sub-nav ul{margin:0;padding:12px 0;display:block;background-color:rgba(26, 26, 26, .75);max-width:300px;}nav .header .navigation .sub-nav__item{position:relative;display:block;margin:0;text-align:left;}nav .header .navigation .sub-nav__item:last-child{border-bottom-color:transparent;}nav .header .navigation .sub-nav__link{display:block;max-width:300px;color:#ffffff;margin:0;line-height:1;letter-spacing:1.5px;padding:19px 13px;-webkit-transition:all .2s ease;transition:all .2s ease;}nav .header .navigation .sub-nav.visible{opacity:1;visibility:visible;-webkit-transform:translate(0, 100%);-moz-transform:translate(0, 100%);-ms-transform:translate(0, 100%);transform:translate(0, 100%);}nav .header .navigation .sub-nav.visible+.navigation__link{background:#000000;}nav .header .hamburger{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;padding:28px 13px;background-color:transparent;color:inherit;vertical-align:middle;cursor:pointer;outline:none;z-index:915;opacity:1;}nav .header .hamburger__bars{position:relative;display:block;width:26px;height:2px;background-color:currentColor;-webkit-transition:0.2s -webkit-transform ease;transition:0.2s transform ease;}nav .header .hamburger__bars:before,nav .header .hamburger__bars:after{content:'';display:block;width:26px;height:2px;background-color:currentColor;position:absolute;left:0;top:0;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:0.2s -webkit-transform ease;transition:0.2s transform ease;}nav .header .hamburger__bars:before{-webkit-transform:translateY(-9px);-moz-transform:translateY(-9px);-ms-transform:translateY(-9px);transform:translateY(-9px);}nav .header .hamburger__bars:after{-webkit-transform:translateY(9px);-moz-transform:translateY(9px);-ms-transform:translateY(9px);transform:translateY(9px);}nav .header .hamburger:hover{text-shadow:.5px 0 0,-.5px 0 0;}nav .header .hamburger:hover .hamburger__bars:before{-webkit-transform:translateY(-7px);-moz-transform:translateY(-7px);-ms-transform:translateY(-7px);transform:translateY(-7px);}nav .header .hamburger:hover .hamburger__bars:after{-webkit-transform:translateY(7px);-moz-transform:translateY(7px);-ms-transform:translateY(7px);transform:translateY(7px);}nav .header .hamburger.active .hamburger__bars{-webkit-transform:rotate(135deg);-moz-transform:rotate(135deg);-ms-transform:rotate(135deg);transform:rotate(135deg);opacity:0;}nav .header .hamburger.active .hamburger__bars:before{display:none;}nav .header .hamburger.active .hamburger__bars:after{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg);}nav .content-container{-webkit-transition:0.2s all ease;transition:0.2s all ease;}nav.scroll .content-container,nav .scroll .content-container{-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);}nav.scroll .content-container .navigation__link,nav .scroll .content-container .navigation__link{visibility:visible!important;}nav.scroll .content-container .navigation .sub-nav,nav .scroll .content-container .navigation .sub-nav{-webkit-transform:translate(0, calc(100% + -10px));-moz-transform:translate(0, calc(100% + -10px));-ms-transform:translate(0, calc(100% + -10px));transform:translate(0, calc(100% + -10px));}nav.scroll .content-container .navigation .sub-nav ul,nav .scroll .content-container .navigation .sub-nav ul{padding:0;}nav.scroll .content-container .navigation .sub-nav.visible,nav .scroll .content-container .navigation .sub-nav.visible{opacity:1;visibility:visible;-webkit-transform:translate(0, calc(100% + 23px));-moz-transform:translate(0, calc(100% + 23px));-ms-transform:translate(0, calc(100% + 23px));transform:translate(0, calc(100% + 23px));}nav .dark-opening{background-color:rgb(26, 26, 26)!important;}nav nav.dark-opening .header{margin-top:0;}nav #ctaShowButton,nav #ctaMessage{display:none!important;}nav #ctaShowButton{display:none;opacity:0;pointer-events:none;}nav .search{cursor:pointer;}nav .search svg{display:block;}nav .buttons-wrapper{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;
34-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}body>div.sidemenu{background-color:rgba(255, 255, 255, 0.9);color:rgba(54, 54, 54, 1);--fontColor:rgba(54, 54, 54, 1);--fontColor_H:0;--fontColor_S:0%;--fontColor_L:21%;--fontColor_A:1;--fontColor_darkenDir:1;--bgColor:rgba(255, 255, 255, 0.9);--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:0.9;--bgColor_darkenDir:-1;}body>div.sidemenu{width:auto!important;left:auto!important;right:-100%;top:0;background-color:transparent;-webkit-transition:right .3s;transition:right .3s;display:block;}body>div.sidemenu:not(.visible){pointer-events:none;visibility:hidden;}body>div.sidemenu.visible{right:0;}body>div.sidemenu .sidebar{position:relative;width:400px;height:100vh;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-top:40px;padding-bottom:100px;background-color:var(--bgColor, #fff);color:var(--fontColor, #000);font-family:var(--global-primary-font-family);font-size:21px;line-height:1.333333;letter-spacing:.5px;-webkit-transition:all .3s ease-in;transition:all .3s ease-in;}@media (max-width: 767px){body>div.sidemenu .sidebar{width:270px;font-size:18px;}}body>div.sidemenu .sidebar__content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:100%;width:100%;padding-left:40px;padding-right:40px;text-align:center;overflow-y:auto;}@media (max-width: 767px){body>div.sidemenu .sidebar__content{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;padding-left:20px;padding-right:20px;}}body>div.sidemenu .sidebar__close{position:absolute;right:30px;top:30px;display:inline-block;width:38px;height:38px;padding:10px;border:none;border-radius:0;background:transparent;color:inherit;z-index:1;cursor:pointer;}body>div.sidemenu .sidebar__close:before,body>div.sidemenu .sidebar__close:after{content:'';display:block;width:22px;height:2px;background-color:currentColor;position:absolute;left:50%;top:50%;}body>div.sidemenu .sidebar__close:before{-webkit-transform:translate(-50%, -50%) rotate(45deg);-moz-transform:translate(-50%, -50%) rotate(45deg);-ms-transform:translate(-50%, -50%) rotate(45deg);transform:translate(-50%, -50%) rotate(45deg);}body>div.sidemenu .sidebar__close:after{-webkit-transform:translate(-50%, -50%) rotate(-45deg);-moz-transform:translate(-50%, -50%) rotate(-45deg);-ms-transform:translate(-50%, -50%) rotate(-45deg);transform:translate(-50%, -50%) rotate(-45deg);}@media (max-width: 767px){body>div.sidemenu .sidebar__close{right:10px;top:10px;}}body>div.sidemenu .sidebar__close:focus{outline:none;}body>div.sidemenu .sidebar__nav{list-style:none;padding:0;margin:auto 0;}body>div.sidemenu .sidebar__nav-item{margin:0;padding-top:4px;padding-bottom:4px;border-bottom:1px solid hsla( 35 var(--bgColor_H, 0), 36 var(--bgColor_S, 0%), 37 calc(50% + (var(--bgColor_L, 100%) - 50%) * 0.9), 38 var(--bgColor_A, 1) 39 );}body>div.sidemenu .sidebar__nav-link{display:inline-block;padding:10px;border:none;border-radius:0;background:transparent;text-transform:none;-webkit-transition:all .25s;transition:all .25s;cursor:pointer;color:inherit;}body>div.sidemenu .sidebar__nav-link:focus{outline:none;}body>div.sidemenu .sidebar__subnav{list-style:none;padding:4px 0 10px;margin:0;font-size:17px;}@media (max-width: 767px){body>div.sidemenu .sidebar__subnav{font-size:14px;letter-spacing:.3px;}}body>div.sidemenu .sidebar__subnav-item{margin-bottom:10px;}body>div.sidemenu .sidebar__subnav-item:last-child{margin-bottom:0;}body>div.sidemenu .sidebar__subnav-link{display:inline-block;padding:0;border:none;border-radius:0;background:transparent;text-transform:none;opacity:.7;-webkit-transition:all .25s;transition:all .25s;cursor:pointer;color:inherit;}body>div.sidemenu .sidebar__subnav-link:focus{outline:none;}body>div.sidemenu .sub-nav{visibility:hidden;opacity:0;max-height:0;-webkit-transition:all .3s;transition:all .3s;}body>div.sidemenu .sub-nav.visible{display:block;visibility:visible;opacity:1;max-height:100vh;}body>div.sidemenu .sub-nav.visible+.main-nav{color:#7a7a7a;}body>div.sidemenu .sub-nav.visible+.main-nav:after{margin-left:40px;border-bottom:2px solid var(--fontColor, #7a7a7a);border-right:2px solid var(--fontColor, #7a7a7a);}body>div.sidemenu .sub-nav-container{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;}body>div.sidemenu .sub-nav-container:hover .main-nav:after{border-bottom:2px solid var(--fontColor, #7a7a7a);border-right:2px solid var(--fontColor, #7a7a7a);}body>div.sidemenu .sub-nav-container .main-nav{position:relative;display:inline-block;}body>div.sidemenu .sub-nav-container .main-nav:after{content:'';display:inline-block;position:relative;width:8px;height:8px;margin-left:25px;-webkit-transform:rotate(45deg) translateX(-100%);-moz-transform:rotate(45deg) translateX(-100%);-ms-transform:rotate(45deg) translateX(-100%);transform:rotate(45deg) translateX(-100%);border-bottom:2px solid var(--fontColor, #000000);border-right:2px solid var(--fontColor, #000000);top:0;bottom:auto;left:auto;-webkit-transition:0.5s all ease;transition:0.5s all ease;background-color:transparent;}body>div.sidemenu #main-section .sidebar{-webkit-transform:translateX(0);-moz-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0);}footer{background-color:#fff;color:rgba(54, 54, 54, 1);--fontColor:rgba(54, 54, 54, 1);--fontColor_H:0;--fontColor_S:0%;--fontColor_L:21%;--fontColor_A:1;--fontColor_darkenDir:1;--bgColor:#fff;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:1;--bgColor_darkenDir:-1;--greyColor:hsla( 40var(--fontColor_H), 41var(--fontColor_S), 42calc(var(--fontColor_L) + (50% - var(--fontColor_L)) * 0.445), 43var(--fontColor_A));}footer .redesign .inp--dark-bg input{color:var(--fontColor);border-color:hsla( 44 var(--fontColor_H), 45 var(--fontColor_S), 46 calc(var(--fontColor_L) + (50% - var(--fontColor_L)) * 0.445), 47 var(--fontColor_A));}footer .redesign .inp--dark-bg input:hover{border-color:var(--fontColor);}footer .redesign .inp+.inp{margin-top:24px;}footer .redesign .btn--primary-light{border-color:var(--fontColor);color:var(--fontColor);}footer .redesign .btn--primary-light:hover{background-color:var(--fontColor);color:var(--bgColor);}footer.is-background-color-light .redesign .btn--primary-light{border-width:1px;}footer .redesign .socials--grey{-webkit-box-pack:end;-ms-flex-pack:end;
47-webkit-justify-content:flex-end;justify-content:flex-end;}footer .redesign .socials--grey .socials__link{background-color:hsla( 48 var(--bgColor_H), 49 var(--bgColor_S), 50 calc(var(--bgColor_L) + (50% - var(--bgColor_L)) * 0.15), 51 var(--bgColor_A));color:var(--greyColor);}footer .redesign .socials--grey .socials__link svg{fill:var(--greyColor);}footer .redesign .socials--grey .socials__link:hover{background-color:hsla( 52 var(--bgColor_H), 53 var(--bgColor_S), 54 calc(var(--bgColor_L) + (50% - var(--bgColor_L)) * 0.4), 55 var(--bgColor_A));color:var(--fontColor);}footer .redesign .socials--grey .socials__link:hover svg{fill:var(--fontColor);}footer .redesign.footer .grey-text{color:var(--fontColor);}footer .footer{position:relative;padding-top:60px;padding-bottom:30px;}@media (max-width: 560px){footer .footer{padding-top:10px;}}@media (max-width: 500px){footer .footer{padding-bottom:70px;}}footer .footer .text_content_wrap p{margin-bottom:15px;}footer .footer .text_content_wrap p:last-of-type{margin-bottom:0;}footer .footer .container{max-width:1440px;}@media (max-width: 768px){footer .footer .container{padding-left:25px;padding-right:25px;}}@media (max-width: 560px){footer .footer .container{padding-left:20px;padding-right:20px;}}footer .footer h3{margin:0 0 15px 0;}footer .footer h5{text-transform:capitalize;}footer .footer .info-wrap{margin-bottom:40px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}footer .footer .info-wrap .agent_box{width:70%;}@media (max-width: 1280px){footer .footer .info-wrap .agent_box{width:50%;}}@media (max-width: 768px){footer .footer .info-wrap .agent_box{width:100%;}}footer .footer .info-wrap .newsletter_box{width:30%;}@media (max-width: 1280px){footer .footer .info-wrap .newsletter_box{width:50%;}}@media (max-width: 768px){footer .footer .info-wrap .newsletter_box{width:100%;}}footer .footer .info-wrap .newsletter_box--padding{padding-top:44px;}@media (max-width: 768px){footer .footer .info-wrap .newsletter_box--padding{padding-top:0;}}footer .footer .info-wrap .newsletter_box .contact_title{margin-bottom:13px;line-height:1.6;}@media (max-width: 768px){footer .footer .info-wrap .newsletter_box .info-wrap-contact_cell{margin-bottom:0;padding-left:0;}}@media (max-width: 768px){footer .footer .info-wrap .newsletter_box .icon_text{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:22px;position:relative;}footer .footer .info-wrap .newsletter_box .icon_text i{position:relative;width:30px;margin-right:20px;}footer .footer .info-wrap .newsletter_box .icon_text .contact_title{margin-bottom:0;}}@media (max-width: 768px){footer .footer .info-wrap .newsletter_box .info-wrap-contact_zone{margin-bottom:0;}}footer .footer .info-wrap-contact{position:relative;}footer .footer .info-wrap-contact_zone{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;margin-bottom:39px;}@media (max-width: 768px){footer .footer .info-wrap-contact_zone{margin-bottom:21px;}footer .footer .info-wrap-contact_zone:last-child{margin-bottom:51px;}}footer .footer .info-wrap-contact_zone i{position:absolute;left:0;display:block;}footer .footer .info-wrap-contact_zone i svg path{fill:currentColor;}footer .footer .info-wrap-contact_zone h4{margin:0 0 13px 0;width:100%;}footer .footer .info-wrap-contact_cell{position:relative;padding-left:50px;width:400px;font-size:14px;text-transform:uppercase;font-weight:bold;letter-spacing:1.5px;}@media (max-width: 1280px){footer .footer .info-wrap-contact_cell:first-of-type{margin-bottom:21px;}}footer .footer .info-wrap-contact_cell .contact_title{line-height:1;margin-bottom:5px;}footer .footer .info-wrap-contact_link{color:var(--greyColor);position:relative;}@media (max-width: 560px){footer .footer .info-wrap-contact_link{letter-spacing:0;}}footer .footer .hvr_animation{position:relative;-webkit-text-decoration:none!important;text-decoration:none!important;}footer .footer .hvr_animation:after{content:'';position:absolute;
55left:0;bottom:0;width:0%;height:1px;background:var(--greyColor);-webkit-transition:.3s linear;transition:.3s linear;}footer .footer .hvr_animation:hover:after{width:100%;}footer .footer .hvr_animation.underlined:after{width:100%;}footer .footer .hvr_animation.underlined:hover:after{width:0%;}footer .footer .form-content{padding:0!important;}footer .footer .form-content label{color:var(--fontColor);text-transform:none;letter-spacing:1;}footer .footer .form-content input{padding:2px 24px 2px 0;}footer .footer .form-content .subscribe_btn{margin-top:20px;position:relative;}footer .footer .form-content .subscribe_btn i{font-size:18px;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-moz-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);opacity:0;}footer .footer .form-content.success i{opacity:1;}footer .footer .form-content.success .subscribe_btn span{opacity:0;}footer .footer .form-content.success .hide{opacity:0;}footer .footer .form-content.success .hide +span{opacity:1;}footer .footer .text_footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;margin-bottom:39px;}@media (max-width: 1280px){footer .footer .text_footer{-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}}@media (max-width: 560px){footer .footer .text_footer{text-align:center;}}footer .footer .text_footer p{white-space:normal;}footer .footer .text_footer .images_box{max-width:186px;width:100%;margin-right:43px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}@media (max-width: 560px){footer .footer .text_footer .images_box{margin:0 auto 20px auto;}}@media (max-width: 1280px){footer .footer .text_footer .img_size{margin-bottom:20px;}}@media (max-width: 560px){footer .footer .text_footer .img_size{margin-bottom:0;}}footer .footer .text_footer .img_size img{width:100%;height:100%;object-fit:contain;}footer .footer .first_text_footer .img_size{width:100%;height:63px;}footer .footer .first_text_footer .img_size img{width:100%;height:100%;object-fit:contain;}@media (max-width: 768px){footer .footer .first_text_footer{margin-bottom:51px;}}footer .footer .second_text_footer .first_img_size{width:45px;height:45px;margin-right:15px;}footer .footer .second_text_footer .second_img_size{width:100px;height:45px;}@media (max-width: 560px){footer .footer .second_text_footer{margin-bottom:21px;}}footer .footer .info-privacy{padding-top:45px;padding-bottom:30px;border-top:1px solid hsla( 56 var(--bgColor_H), 57 var(--bgColor_S), 58 calc(var(--bgColor_L) + (50% - var(--bgColor_L)) * 0.55), 59 var(--bgColor_A));}@media (max-width: 768px){footer .footer .info-privacy{padding-top:0;border-top:none;}}footer .footer .info-privacy__row{-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}footer .footer .info-privacy .copy_zone{font-size:18px;}@media (min-width: 1350px){footer .footer .info-privacy .copy_zone{text-align:center;}}@media (min-width: 1281px){footer .footer .info-privacy .copy_zone{padding-top:8px;padding-bottom:8px;}}@media (max-width: 768px){footer .footer .info-privacy .copy_zone{text-align:center;margin-bottom:10px;padding-top:45px;border-top:1px solid hsla( 60 var(--bgColor_H), 61 var(--bgColor_S), 62 calc(var(--bgColor_L) + (50% - var(--bgColor_L)) * 0.55), 63 var(--bgColor_A));}}footer .footer .info-privacy .copy_zone a{color:var(--greyColor);}footer .footer .info-privacy .powered_zone{font-size:18px;}@media (min-width: 1281px){footer .footer .info-privacy .powered_zone{padding-top:8px;padding-bottom:8px;}}@media (max-width: 1280px){footer .footer .info-privacy .powered_zone{text-align:center;}}@media (max-width: 768px){footer .footer .info-privacy .powered_zone{text-align:center;margin-bottom:24px;}}footer .footer .info-privacy .powered_zone a{color:var(--greyColor);}@media (min-width: 1281px){footer .footer .info-privacy .socials_zone{-webkit-box-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;}}@media (max-width: 1280px){footer .footer .info-privacy .socials_zone{width:100%;margin-top:20px;-webkit-box-pack:start;-ms-flex-pack:start;
63-webkit-justify-content:flex-start;justify-content:flex-start;}}@media (max-width: 768px){footer .footer .info-privacy .socials_zone{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;margin-top:0;margin-bottom:20px;}footer .footer .info-privacy .socials_zone li{padding:0 7px 10px 7px;}}footer .footer.one_contact .type_user{margin-bottom:73px;}@media (max-width: 768px){footer .footer.one_contact .type_user{margin-bottom:51px;}}footer .footer.no_newsletter h3{margin-bottom:46px;}footer .footer.no_newsletter .newsletter_box{display:none;}footer .footer.no_newsletter .info-wrap-contact{width:calc(70% + 230px);width:100%;padding-left:230px;}@media (max-width: 1200px){footer .footer.no_newsletter .info-wrap-contact{padding-left:0;}}@media (max-width: 768px){footer .footer.no_newsletter .info-wrap-contact{width:100%;}}@media (max-width: 1200px){footer .footer.no_newsletter .info-wrap-contact_cell{width:50%;}}@media (max-width: 768px){footer .footer.no_newsletter .info-wrap-contact_cell{width:100%;}}footer .footer.no_newsletter .info-wrap-contact h4{position:absolute;margin-top:-8px;left:0;max-width:200px;}@media (max-width: 1200px){footer .footer.no_newsletter .info-wrap-contact h4{position:relative;left:auto;max-width:100%;width:100%;margin-bottom:20px;margin-top:0;}}@media (max-width: 768px){footer .footer.no_newsletter .info-wrap-contact h4{position:relative;left:auto;max-width:100%;}}footer .footer.no_newsletter .info-wrap-contact_zone:first-of-type{margin-bottom:71px;}@media (max-width: 1200px){footer .footer.no_newsletter .info-wrap-contact_zone:first-of-type{margin-bottom:39px;}}@media (max-width: 768px){footer .footer.no_newsletter .info-wrap-contact_zone:first-of-type{margin-bottom:51px;}}footer .footer.no_newsletter .info-wrap-contact_zone:last-child{margin-bottom:0;}footer .footer.no_icon .info-wrap-contact_cell{padding-left:0;}footer .footer.no_icon .info-wrap-contact_cell i{display:none;}footer .footer.no-names .info-wrap-contact{padding-left:0;}footer .form-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;margin-left:-15px;margin-right:-15px;}@media (min-width: 1281px){footer .form-row{-webkit-box-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;}}@media (max-width: 900px){footer .form-row{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}footer .form-col{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;padding-left:15px;padding-right:15px;}@media (min-width: 768px){footer .form-col{-webkit-flex:1 1 0;-ms-flex:1 1 0;flex:1 1 0;}}@media (min-width: 768px){footer .form-col--socials{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;}}@media (min-width: 1281px){footer .form-col--socials{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;}}@media (max-width: 768px){footer .form-col--socials{-webkit-order:-1;-ms-flex-order:-1;order:-1;}}@media (min-width: 1281px){footer .form-col--xl-auto{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;}}footer .additional-links-separator{display:block;width:100%;height:0;overflow:hidden;}@media (min-width: 768px){footer .additional-links-separator{display:inline;width:auto;height:auto;}footer .additional-links-separator:before{content:"|";}}footer .h-pot{height:0;width:0;overflow:hidden;visibility:hidden;}footer .img-wrap{max-width:100px;width:100%;display:block;margin-right:20px;}@media (max-width: 900px){footer .img-wrap{margin-right:0;margin-bottom:10px;}}footer .img-wrap img{width:100%;object-fit:cover;}footer .powered-box{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;}@media (max-width: 900px){footer .powered-box{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}footer .form-col--copyright{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;margin:10px 0;}footer .luxury-link{white-space:nowrap;}footer .footer__disclaimers{padding-top:24px;padding-bottom:24px;}@media (max-width: 900px){footer .footer__disclaimers{text-align:center;}}body>div.mobile-contact-wrapper{z-index:200;position:relative;}body>div.mobile-contact-wrapper .lp-ico:before{content:'';width:1em;height:1em;background-color:currentColor;-webkit-background-size:cover;background-size:cover;display:block;-webkit-mask-position:center;-webkit-mask-position:center;mask-position:center;-webkit-mask-size:contain;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-transition:all .3s;transition:all .3s;}body>div.mobile-contact-wrapper .lp-ico-search:before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='25' height='25' viewB
63ox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.6231 21.3002L17.1372 16.8143M19.5606 10.9877C19.5606 15.5441 15.8669 19.2377 11.3106 19.2377C6.75421 19.2377 3.06055 15.5441 3.06055 10.9877C3.06055 6.43135 6.75421 2.73769 11.3106 2.73769C15.8669 2.73769 19.5606 6.43135 19.5606 10.9877Z' stroke='black' stroke-width='1.82813' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.6231 21.3002L17.1372 16.8143M19.5606 10.9877C19.5606 15.5441 15.8669 19.2377 11.3106 19.2377C6.75421 19.2377 3.06055 15.5441 3.06055 10.9877C3.06055 6.43135 6.75421 2.73769 11.3106 2.73769C15.8669 2.73769 19.5606 6.43135 19.5606 10.9877Z' stroke='black' stroke-width='1.82813' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.6231 21.3002L17.1372 16.8143M19.5606 10.9877C19.5606 15.5441 15.8669 19.2377 11.3106 19.2377C6.75421 19.2377 3.06055 15.5441 3.06055 10.9877C3.06055 6.43135 6.75421 2.73769 11.3106 2.73769C15.8669 2.73769 19.5606 6.43135 19.5606 10.9877Z' stroke='black' stroke-width='1.82813' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");}body>div.mobile-contact-wrapper .lp-ico-arrow-top:before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='17' height='16' viewBox='0 0 17 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.8716 9.99976L8.87158 5.99976L4.87158 9.99976' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='17' height='16' viewBox='0 0 17 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.8716 9.99976L8.87158 5.99976L4.87158 9.99976' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='17' height='16' viewBox='0 0 17 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.8716 9.99976L8.87158 5.99976L4.87158 9.99976' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");}body>div.mobile-contact-wrapper .lp-ico-scroll-top:before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 3H3M12 21V7M12 7L5 14M12 7L19 14' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E ");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 3H3M12 21V7M12 7L5 14M12 7L19 14' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E ");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 3H3M12 21V7M12 7L5 14M12 7L19 14' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E ");}body>div.mobile-contact-wrapper .lp-ico-close:before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M17.5986 6.32617L5.59863 18.3262M5.59863 6.32617L17.5986 18.3262' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E ");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M17.5986 6.32617L5.59863 18.3262M5.59863 6.32617L17.5986 18.3262' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E ");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M17.5986 6.32617L5.59863 18.3262M5.59863 6.32617L17.5986 18.3262' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E ");}body>div.mobile-contact-wrapper .lp-ico-phone:before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13.8
63699 6.57142C14.7459 6.74157 15.551 7.16808 16.1821 7.79637C16.8132 8.42465 17.2416 9.22612 17.4126 10.0982M13.8699 3C15.6899 3.20128 17.3871 4.01265 18.6827 5.3009C19.9784 6.58914 20.7955 8.27768 21 10.0893M10.4412 13.592C9.36357 12.5192 8.51264 11.3061 7.88843 10.0118C7.83474 9.90047 7.80789 9.84481 7.78726 9.77437C7.71397 9.52405 7.76662 9.21668 7.91909 9.00469C7.962 8.94504 8.01326 8.894 8.11578 8.79194C8.42933 8.47979 8.58611 8.32372 8.6886 8.16677C9.07515 7.57491 9.07515 6.81189 8.6886 6.22002C8.58611 6.06308 8.42933 5.90701 8.11578 5.59486L7.94101 5.42087C7.46438 4.94637 7.22607 4.70912 6.97012 4.58024C6.4611 4.32392 5.85996 4.32392 5.35093 4.58024C5.09499 4.70912 4.85667 4.94637 4.38004 5.42087L4.23867 5.56161C3.76367 6.03449 3.52617 6.27093 3.34478 6.59239C3.1435 6.94909 2.99878 7.5031 3.00001 7.91222C3.00111 8.28092 3.07295 8.53291 3.21664 9.03688C3.98881 11.7453 5.44574 14.3009 7.58743 16.4331C9.72911 18.5652 12.2963 20.0156 15.0168 20.7843C15.523 20.9274 15.7761 20.9989 16.1465 21C16.5575 21.0012 17.114 20.8571 17.4723 20.6568C17.7952 20.4762 18.0327 20.2397 18.5077 19.7669L18.649 19.6261C19.1257 19.1516 19.364 18.9144 19.4934 18.6596C19.7509 18.1528 19.7509 17.5544 19.4934 17.0476C19.364 16.7928 19.1257 16.5556 18.649 16.0811L18.4743 15.9071C18.1607 15.5949 18.0039 15.4388 17.8463 15.3368C17.2518 14.952 16.4853 14.952 15.8908 15.3368C15.7332 15.4388 15.5764 15.5949 15.2628 15.9071C15.1603 16.0091 15.1091 16.0602 15.0491 16.1029C14.8362 16.2547 14.5274 16.3071 14.276 16.2341C14.2052 16.2136 14.1493 16.1869 14.0375 16.1334C12.7374 15.512 11.5189 14.6648 10.4412 13.592Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13.8699 6.57142C14.7459 6.74157 15.551 7.16808 16.1821 7.79637C16.8132 8.42465 17.2416 9.22612 17.4126 10.0982M13.8699 3C15.6899 3.20128 17.3871 4.01265 18.6827 5.3009C19.9784 6.58914 20.7955 8.27768 21 10.0893M10.4412 13.592C9.36357 12.5192 8.51264 11.3061 7.88843 10.0118C7.83474 9.90047 7.80789 9.84481 7.78726 9.77437C7.71397 9.52405 7.76662 9.21668 7.91909 9.00469C7.962 8.94504 8.01326 8.894 8.11578 8.79194C8.42933 8.47979 8.58611 8.32372 8.6886 8.16677C9.07515 7.57491 9.07515 6.81189 8.6886 6.22002C8.58611 6.06308 8.42933 5.90701 8.11578 5.59486L7.94101 5.42087C7.46438 4.94637 7.22607 4.70912 6.97012 4.58024C6.4611 4.32392 5.85996 4.32392 5.35093 4.58024C5.09499 4.70912 4.85667 4.94637 4.38004 5.42087L4.23867 5.56161C3.76367 6.03449 3.52617 6.27093 3.34478 6.59239C3.1435 6.94909 2.99878 7.5031 3.00001 7.91222C3.00111 8.28092 3.07295 8.53291 3.21664 9.03688C3.98881 11.7453 5.44574 14.3009 7.58743 16.4331C9.72911 18.5652 12.2963 20.0156 15.0168 20.7843C15.523 20.9274 15.7761 20.9989 16.1465 21C16.5575 21.0012 17.114 20.8571 17.4723 20.6568C17.7952 20.4762 18.0327 20.2397 18.5077 19.7669L18.649 19.6261C19.1257 19.1516 19.364 18.9144 19.4934 18.6596C19.7509 18.1528 19.7509 17.5544 19.4934 17.0476C19.364 16.7928 19.1257 16.5556 18.649 16.0811L18.4743 15.9071C18.1607 15.5949 18.0039 15.4388 17.8463 15.3368C17.2518 14.952 16.4853 14.952 15.8908 15.3368C15.7332 15.4388 15.5764 15.5949 15.2628 15.9071C15.1603 16.0091 15.1091 16.0602 15.0491 16.1029C14.8362 16.2547 14.5274 16.3071 14.276 16.2341C14.2052 16.2136 14.1493 16.1869 14.0375 16.1334C12.7374 15.512 11.5189 14.6648 10.4412 13.592Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M13.8699 6.57142C14.7459 6.74157 15.551 7.16808 16.1821 7.79637C16.8132 8.42465 17.2416 9.22612 17.4126 10.0982M13.8699 3C15.6899 3.20128 17.3871 4.01265 18.6827 5.3009C19.9784 6.58914 20.7955 8.27768 21 10.0893M10.4412 13.592C9.36357 12.5192 8.51264 11.3061 7.88843 10.0118C7.83474 9.90047 7.80789 9.84481 7.78726 9.77437C7.71397 9.52405 7.76662 9.21668 7.91909 9.00469C7.962 8.94504 8.01326 8.894 8.11578 8.79194C8.42933 8.47979 8.58611 8.32372 8.6886 8.16677C9.07515 7.57491 9.07515 6.81189 8.6886 6.22002C8.58611 6.06308 8.42933 5.90701 8.11578 5.59486L7.94101 5.42087C7.46438 4.94637 7.22607 4.70912 6.97012 4.58024C6.4611 4.32392 5.85996 4.32392 5.35093 4.58024C5.09499 4.70912 4.85667 4.94637 4.38004 5.42087L4.23867 5.56161C3.76367 6.03449 3.52617 6.27093 3.34478 6.59239C3.1435 6.94909 2.99878 7.5031 3.00001 7.91222C3.00111 8.28092 3.07295 8.53291 3.21664 9.03688C3.98881 11.7453 5.44574 14.3009 7.58743 16.4331C9.72911 18.5652 12.2963 20.0156 15.0168 20.7843C15.523 20.9274 15.7761 20.9989 16.1465 21C16.5575 21.0012 17.114 20.8571 17.4723 20.6568C17.7952 20.4762 18.0327 20.2397 18.5077 19.7669L18.649 19.6261C19.1257 19.1516 19.364 18.9144 19.4934 18.6596C19.7509 18.1528 19.7509 17.5544 19.4934 17.0476C19.364 16.7928 19.1257 16.5556 18.649 16.0811L18.4743 15.9071C18.1607 15.5949 18.0039 15.4388 17.8463 15.3368C17.2518 14.952 16.4853 14.952 15.8908 15.3368C15.7332 15.4388 15.5764 15.5949 15.2628 15.9071C15.1603 16.0091 15.1091 16.0602 15.0491 16.1029C14.8362 16.2547 14.5274 16.3071 14.276 16.2341C14.2052 16.2136 14.1493 16.1869 14.0375 16.1334C12.7374 15.512 11.5189 14.6648 10.4412 13.592Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");}body>div.mobile-contact-wrapper .lp-ico-sms:before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 11.5C21.0034 12.8199 20.6951 14.1219 20.1 15.3C19.3944 16.7117 18.3098 17.8992 16.9674 18.7293C15.6251 19.5594 14.0782 19.9994 12.5 20C11.1801 20.0034 9.87812 19.6951 8.7 19.1L3 21L4.9 15.3C4.30493 14.1219 3.99656 12.8199 4 11.5C4.00061 9.92176 4.44061 8.37485 5.27072 7.03255C6.10083 5.69025 7.28825 4.60557 8.7 3.9C9.87812 3.30493 11.1801 2.99656 12.5 3H13C15.0843 3.11499 17.053 3.99476 18.5291 5.47086C20.0052 6.94695 20.885 8.91565 21 11V11.5Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 11.5C21.0034 12.8199 20.6951 14.1219 20.1 15.3C19.3944 16.7117 18.3098 17.8992 16.9674 18.7293C15.6251 19.5594 14.0782 19.9994 12.5 20C11.1801 20.0034 9.87812 19.6951 8.7 19.1L3 21L4.9 15.3C4.30493 14.1219 3.99656 12.8199 4 11.5C4.00061 9.92176 4.44061 8.37485 5.27072 7.03255C6.10083 5.69025 7.28825 4.60557 8.7 3.9C9.87812 3.30493 11.1801 2.99656 12.5 3H13C15.0843 3.11499 17.053 3.99476 18.5291 5.47086C20.0052 6.94695 20.885 8.91565 21 11V11.5Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21 11.5C21.0034 12.8199 20.6951 14.1219 20.1 15.3C19.3944 16.7117 18.3098 17.8992 16.9674 18.7293C15.6251 19.5594 14.0782 19.9994 12.5 20C11.1801 20.0034 9.87812 19.6951 8.7 19.1L3 21L4.9 15.3C4.30493 14.1219 3.99656 12.8199 4 11.5C4.00061 9.92176 4.44061 8.37485 5.27072 7.03255C6.10083 5.69025 7.28825 4.60557 8.7 3.9C9.87812 3.30493 11.1801 2.99656 12.5 3H13C15.0843 3.11499 17.053 3.99476 18.5291 5.47086C20.0052 6.94695 20.885 8.91565 21 11V11.5Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");}body>div.mobile-contact-wrapper .lp-ico-email:before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.5 18L14.85
6371 12M9.14286 12L2.50003 18M2 7L10.1649 12.7154C10.8261 13.1783 11.1567 13.4097 11.5163 13.4993C11.8339 13.5785 12.1661 13.5785 12.4837 13.4993C12.8433 13.4097 13.1739 13.1783 13.8351 12.7154L22 7M6.8 20H17.2C18.8802 20 19.7202 20 20.362 19.673C20.9265 19.3854 21.3854 18.9265 21.673 18.362C22 17.7202 22 16.8802 22 15.2V8.8C22 7.11984 22 6.27976 21.673 5.63803C21.3854 5.07354 20.9265 4.6146 20.362 4.32698C19.7202 4 18.8802 4 17.2 4H6.8C5.11984 4 4.27976 4 3.63803 4.32698C3.07354 4.6146 2.6146 5.07354 2.32698 5.63803C2 6.27976 2 7.11984 2 8.8V15.2C2 16.8802 2 17.7202 2.32698 18.362C2.6146 18.9265 3.07354 19.3854 3.63803 19.673C4.27976 20 5.11984 20 6.8 20Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.5 18L14.8571 12M9.14286 12L2.50003 18M2 7L10.1649 12.7154C10.8261 13.1783 11.1567 13.4097 11.5163 13.4993C11.8339 13.5785 12.1661 13.5785 12.4837 13.4993C12.8433 13.4097 13.1739 13.1783 13.8351 12.7154L22 7M6.8 20H17.2C18.8802 20 19.7202 20 20.362 19.673C20.9265 19.3854 21.3854 18.9265 21.673 18.362C22 17.7202 22 16.8802 22 15.2V8.8C22 7.11984 22 6.27976 21.673 5.63803C21.3854 5.07354 20.9265 4.6146 20.362 4.32698C19.7202 4 18.8802 4 17.2 4H6.8C5.11984 4 4.27976 4 3.63803 4.32698C3.07354 4.6146 2.6146 5.07354 2.32698 5.63803C2 6.27976 2 7.11984 2 8.8V15.2C2 16.8802 2 17.7202 2.32698 18.362C2.6146 18.9265 3.07354 19.3854 3.63803 19.673C4.27976 20 5.11984 20 6.8 20Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M21.5 18L14.8571 12M9.14286 12L2.50003 18M2 7L10.1649 12.7154C10.8261 13.1783 11.1567 13.4097 11.5163 13.4993C11.8339 13.5785 12.1661 13.5785 12.4837 13.4993C12.8433 13.4097 13.1739 13.1783 13.8351 12.7154L22 7M6.8 20H17.2C18.8802 20 19.7202 20 20.362 19.673C20.9265 19.3854 21.3854 18.9265 21.673 18.362C22 17.7202 22 16.8802 22 15.2V8.8C22 7.11984 22 6.27976 21.673 5.63803C21.3854 5.07354 20.9265 4.6146 20.362 4.32698C19.7202 4 18.8802 4 17.2 4H6.8C5.11984 4 4.27976 4 3.63803 4.32698C3.07354 4.6146 2.6146 5.07354 2.32698 5.63803C2 6.27976 2 7.11984 2 8.8V15.2C2 16.8802 2 17.7202 2.32698 18.362C2.6146 18.9265 3.07354 19.3854 3.63803 19.673C4.27976 20 5.11984 20 6.8 20Z' stroke='white' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");}body>div.mobile-contact-wrapper a{-webkit-text-decoration:none;text-decoration:none;}body>div.mobile-contact-wrapper .btn-holder{bottom:-50px;left:19px;position:fixed;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:13px;opacity:0;-webkit-transition:all .3s;transition:all .3s;}@media (max-width: 1024px){body>div.mobile-contact-wrapper .btn-holder{right:19px;padding:0 48px;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}}body>div.mobile-contact-wrapper .btn-holder.visible{bottom:28px;opacity:1;}body>div.mobile-contact-wrapper .search-btn{width:48px;height:48px;border-radius:999px;font-size:0;line-height:0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-transition:all .3s;transition:all .3s;padding:12px;color:#141414;background:#fff;}@media (max-width: 1024px){body>div.mobile-contact-wrapper .search-btn{position:absolute;left:0;bottom:0;}}body>div.mobile-contact-wrapper .search-btn:before{width:24px;height:24px;}body>div.mobile-contact-wrapper .connect-btn{height:48px;padding:0 24px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:4px;text-transform:uppercase;border-radius:25px;color:var(--pillTextColor);background:var(--pillBackgroundColor);border:1px solid rgba(255, 255, 255, 0.2);cursor:pointer;font-size:10px;font-style:normal;font-weight:500;line-height:16px;letter-spacing:0.4px;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;-webkit-transition:all .4s;transition:all .4s;box-shadow:0 0 0 0 rgba(255, 255, 255, 0.2);-webkit-animation:pulsate 2s ease infinite;animation:pulsate 2s ease infinite;}body>div.mobile-contact-wrapper .connect-btn:before{width:16px;height:16px;}body>div.mobile-contact-wrapper .pop-up{display:none;position:fixed;bottom:0;left:0;width:100%;-webkit-transition:all .3s;transition:all .3s;border-radius:16px 16px 0 0;color:var(--textColor);background:var(--backgroundColor);}@media (max-height: 850px){body>div.mobile-contact-wrapper .pop-up{max-height:85vh;overflow-y:auto;}}@media (min-width: 1025px){body>div.mobile-contact-wrapper .pop-up{max-height:none;overflow-y:initial;max-width:637px;border-radius:16px;bottom:28px;left:19px;}}body>div.mobile-contact-wrapper .pop-up .lp-container{padding-top:24px;padding-bottom:24px;-webkit-box-pack:center;-ms-flex-pack:center;
63-webkit-justify-content:center;justify-content:center;}@media (min-width: 1025px){body>div.mobile-contact-wrapper .pop-up .lp-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-top:40px;padding-bottom:40px;min-height:450px;padding-left:56px;padding-right:56px;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}body>div.mobile-contact-wrapper .pop-up .close-btn{width:44px;height:44px;background-color:transparent;border-color:transparent;display:block;margin:24px auto 0;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:var(--textColor);cursor:pointer;padding:10px;border:0;}body>div.mobile-contact-wrapper .pop-up .close-btn:before{width:24px;height:24px;}@media (min-width: 1025px){body>div.mobile-contact-wrapper .pop-up .close-btn{position:absolute;top:14px;right:12px;margin:0;}}body>div.mobile-contact-wrapper .pop-up .icon-btn{width:44px;height:44px;border-radius:999px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-left:8px;color:var(--textColor);position:relative;}body>div.mobile-contact-wrapper .pop-up .icon-btn:after{position:absolute;bottom:0;width:100%;left:0;border-radius:999px;
63height:100%;content:'';border:solid 1px var(--textColor);opacity:.3;}body>div.mobile-contact-wrapper .pop-up .icon-btn:before{width:24px;height:24px;}body>div.mobile-contact-wrapper .success-block{display:none;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}@media (min-width: 1025px){body>div.mobile-contact-wrapper .success-block{-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}}body>div.mobile-contact-wrapper .success-block .lp-btn{margin-top:24px;}body>div.mobile-contact-wrapper .contact-form{margin:0;}@media (max-width: 1024px){body>div.mobile-contact-wrapper .contact-form__item{width:100%;}}body>div.mobile-contact-wrapper .contact-form__item .lp-input{width:100%;}body>div.mobile-contact-wrapper .contact-form__item .is-placeholder{color:#818181;}body>div.mobile-contact-wrapper .contact-form__item+.contact-form__item{margin-top:16px;}body>div.mobile-contact-wrapper .contact-form.show-success .contact-form__container,body>div.mobile-contact-wrapper .contact-form.success .contact-form__container{display:none;}body>div.mobile-contact-wrapper .contact-form.show-success .success-block,body>div.mobile-contact-wrapper .contact-form.success .success-block{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}body>div.mobile-contact-wrapper .contact-form .lp-disclaimer{margin-top:16px;}body>div.mobile-contact-wrapper .contact-form .lp-h3{margin-bottom:16px;}body>div.mobile-contact-wrapper .success-message{font-size:22px;}@-webkit-keyframes pulsate{0%{box-shadow:0 0 0 0 rgba(255, 255, 255, 0.2);}50%{box-shadow:0 0 4px 6px rgba(255, 255, 255, .5);}100%{box-shadow:0 0 12px 12px rgba(255, 255, 255, 0);}} 64 </style> 65 <style id="custom-style-css">.social_icons-style-1 a{border-color:#363636!important;background-color:rgba(0, 0, 0, 0)!important;color:#363636!important;}.social_icons-style-1 a:hover{border-color:#363636!important;background-color:#363636!important;color:#FFFFFF!important;}.social_icons-style-1 a i{color:inherit!important;}
65.social_icons-style-1 a svg,.social_icons-style-1 a svg path{fill:currentColor!important;}.pagination-style-1 li a{color:#363636!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!important;}.pagination-style-1 li a:hover{color:#FFFFFF!important;background-color:#363636!important;border-color:#363636!important;}.pagination-style-1 li.active a{color:#FFFFFF!important;background-color:#363636!important;border-color:#363636!important;}.hyperlink-style-1{color:#002349!important;}.hyperlink-style-1:hover{color:#363636!important;}.button-style-1{color:#363636!important;background-color:rgba(241, 241, 241, 0)!important;border-color:#363636!important;}.button-style-1:hover{color:#FFFFFF!important;background-color:#363636!important;border-color:#363636!important;}.hyperlink-style-2{color:rgba(255, 255, 255, 1)!important;}.hyperlink-style-2:hover{color:#FFFFFF!important;}.button-style-2{color:#FFFFFF!important;background-color:rgba(241, 241, 241, 0)!important;border-color:#FFFFFF!important;}.button-style-2:hover{color:#363636!important;background-color:#FFFFFF!important;border-color:#FFFFFF!important;}.social_icons-style-2 a{border-color:#FFFFFF!important;background-color:rgba(0, 0, 0, 0)!important;color:#FFFFFF!important;}.social_icons-style-2 a:hover{border-color:#FFFFFF!important;background-color:#FFFFFF!important;color:#363636!important;}.social_icons-style-2 a i{color:inherit!important;}
65.social_icons-style-2 a svg,.social_icons-style-2 a svg path{fill:currentColor!important;}.pagination-style-2 li a{color:rgba(255, 255, 255, 1)!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!important;}.pagination-style-2 li a:hover{color:#363636!important;background-color:#FFFFFF!important;border-color:#FFFFFF!important;}.pagination-style-2 li.active a{color:#363636!important;background-color:#FFFFFF!important;border-color:#FFFFFF!important;}.button-style-3{color:#FFFFFF!important;background-color:#363636!important;border-color:#363636!important;}.button-style-3:hover{color:#363636!important;background-color:rgba(241, 241, 241, 0)!important;border-color:#363636!important;}.button-style-4{color:#363636!important;background-color:#FFFFFF!important;border-color:#FFFFFF!important;}.button-style-4:hover{color:#FFFFFF!important;background-color:rgba(241, 241, 241, 0)!important;border-color:#FFFFFF!important;}.button-style-5{color:#363636!important;background-color:rgba(241, 241, 241, 0)!important;border-color:#363636!important;}.button-style-5:hover{color:#FFFFFF!important;background-color:#363636!important;border-color:#363636!important;}.button-style-6{color:#FFFFFF!important;background-color:rgba(241, 241, 241, 0)!important;border-color:#FFFFFF!important;}.button-style-6:hover{color:#363636!important;background-color:#FFFFFF!important;border-color:#FFFFFF!important;}</style> 66 <!-- LP Consent bootstrap: blocking; resolves consent state, pushes Consent Mode 67 defaults, and dynamically loads the locale + main (and banner if needed). --> 68
68<script src="https://cdn.luxurypresence.com/scripts/lp-consent/latest/lp-consent-boot.js" data-website-id="069c1329-5dd0-46bd-b643-b325e5b978a5"></script>
68 69 70 71
71<script> 72 (function utmParse() { 73 const url = new URL(window.location.href); 74 if (url.search) { 75 const utm = url.search.split(/\?|&/g).reduce((acc, current) => { 76 const matched = current.match(/utm_(content|campaign|medium|source|term|id)|gclid/g); 77 if (matched) { 78 acc[matched[0]] = current.replace(`${matched[0]}=`, ''); 79 } 80 return acc; 81 }, {}); 82 if (Object.keys(utm).length) { 83 window.localStorage.setItem('utm_vars', JSON.stringify(utm)); 84 } else { 85 // Remove old utm vars 86 window.localStorage.removeItem('utm_vars'); 87 } 88 } 89 // Set referrer in local storage 90 // This is meant to be stored once to avoid self-referrals and to have the first referrer only. 91 if (!window.localStorage.getItem('referrer')) { 92 // Capture the Referrer URL 93 const referrer = document.referrer; 94 if (referrer) { 95 // Only store the referrer if it comes from outside the current domain (to avoid self-referrals) 96 const currentDomain = window.location.hostname; 97 const referrerDomain = new URL(referrer).hostname; 98 99 if (referrerDomain !== currentDomain) { 100 // Store it in localStorage 101 localStorage.setItem('referrer', referrer); 102 } 103 } 104 } 105 })(); 106 </script>
106 107
107<script src="//code.tidio.co/udmfentqlcxediyt27fs3yd6toen9ems.js" async></script>
107 108 109<!-- Bing Webmaster Tools Verification -->
110<script> 111if (window.location.pathname === '/' || window.location.pathname === '/index.html') { 112 document.write('<meta name="msvalidate.01" content="18166674FE9A03570D2BCFB935D429DC">'); 113} 114</script>
114 115 116<meta name="google-site-verification" content="zA5fHMesCds2rObD4tBtbv2BxxDPj-NwmXxzuot1Yvc"> 117
118<script type="module" defer id="alttextai-ujs" src="https://ujs.alttext.ai/alttextai-ujs.js?site-key=cc4dd1d2280ba03e"></script>
118 119
120<script type="application/ld+json"> 121{ 122 "@context": "https://schema.org", 123 "@type": "RealEstateAgent", 124 "@id": "https://www.marcoislandlife.net/#realestateagent", 125 "name": "Marco Island Life - Realtor Elizabeth Heuermann - Premier Sotheby's International Realty", 126 "url": "https://www.marcoislandlife.net/", 127 "mainEntityOfPage": { 128 "@type": "WebPage", 129 "@id": "https://www.marcoislandlife.net/" 130 }, 131 "logo": "https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/763a7f13-106a-4eb9-b01c-a141d951d084", 132 "image": "https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/bed47232-727e-4bf3-84ed-71b688dea175", 133 "telephone": "+1-239-777-3905", 134 "address": { 135 "@type": "PostalAddress", 136 "streetAddress": "760 N Collier Blvd #101B", 137 "addressLocality": "Marco Island", 138 "addressRegion": "FL", 139 "postalCode": "34145", 140 "addressCountry": "US" 141 }, 142 "geo": { 143 "@type": "GeoCoordinates", 144 "latitude": 25.9539226, 145 "longitude": -81.7318728 146 }, 147 "hasMap": "https://maps.app.goo.gl/kJR94FoDYGS3aCc78", 148 "description": "Marco Island Life is a team of real estate agents in Marco Island, Florida, helping buyers and sellers with luxury waterfront homes, condos, and new construction properties. Backed by over twenty five years of combined experience and affiliated with Premier Sotheby's International Realty, the team provides personalized guidance and deep local market knowledge. As members of the National Association of REALTORS, they specialize in luxury coastal real estate throughout Marco Island, Naples, Isles of Capri, and Goodland.", 149 "sameAs": [ 150 "https://www.facebook.com/profile.php?id=61572442867930", 151 "https://www.instagram.com/Marco.island.life/", 152 "https://x.com/MarcoIslandLife", 153 "https://www.linkedin.com/in/elizabeth-heuermann-323894378", 154 "https://www.tiktok.com/@marcoislandlife" 155 ], 156 "memberOf": { 157 "@type": "Organization", 158 "name": "National Association of REALTORS" 159 }, 160 "parentOrganization": { 161 "@type": "Organization", 162 "name": "Premier Sotheby's International Realty" 163 }, 164 "aggregateRating": { 165 "@type": "AggregateRating", 166 "ratingValue": 5, 167 "bestRating": 5, 168 "reviewCount": 4 169 }, 170 "review": [ 171 { 172 "@type": "Review", 173 "author": { 174 "@type": "Person", 175 "name": "Karen W." 176 }, 177 "reviewBody": "Elizabeth and Mark are great to work with. They have a wealth of knowledge about Marco Island that they willingly shared. They helped us navigate through all of our options.", 178 "reviewRating": { 179 "@type": "Rating", 180 "ratingValue": 5, 181 "bestRating": 5 182 } 183 }, 184 { 185 "@type": "Review", 186 "author": { 187 "@type": "Person", 188 "name": "Bruce A." 189 }, 190 "reviewBody": "Elizabeth did an excellent job with the sale of our home on Marco Island. She provided great consultation and communication throughout the selling process and ultimately closed the sale at an excellent price for our property. We really appreciate the professional excellence and work ethic of both Elizabeth and Mark and would highly recommend them to anyone selling property in the area.", 191 "reviewRating": { 192 "@type": "Rating", 193 "ratingValue": 5, 194 "bestRating": 5 195 } 196 }, 197 { 198 "@type": "Review", 199 "author": { 200 "@type": "Person", 201 "name": "Al S." 202 }, 203 "reviewBody": "Exceptionally helpful and knowledgeable, Elizabeth kept me informed throughout the entire transaction. Any information or questions that I asked were immediately answered.", 204 "reviewRating": { 205 "@type": "Rating", 206 "ratingValue": 5, 207 "bestRating": 5 208 } 209 }, 210 { 211 "@type": "Review", 212 "author": { 213 "@type": "Person", 214 "name": "Jason and Marnie M." 215 }, 216 "reviewBody": "Elizabeth is an extremely hardworking, personable woman. She is prompt with responses and very knowledgeable as well. My husband and I truly enjoyed our experience working with Elizabeth.", 217 "reviewRating": { 218 "@type": "Rating", 219 "ratingValue": 5, 220 "bestRating": 5 221 } 222 } 223 ], 224 "areaServed": [ 225 { 226 "@type": "City", 227 "name": "Marco Island" 228 }, 229 { 230 "@type": "City", 231 "name": "Naples" 232 }, 233 { 234 "@type": "City", 235 "name": "Isles of Capri" 236 }, 237 { 238 "@type": "City", 239 "name": "Goodland" 240 } 241 ], 242 "knowsAbout": [ 243 "Luxury Waterfront Homes", 244 "New Construction Properties", 245 "Coastal Market Trends", 246 "Marco Island Real Estate" 247 ] 248} 249</script>
249 250 251<!-- Google Tag Manager -->
252<script>
vendor: 381 bytes, lines 252-262
252 253(function(w,d,s,l,i){ 254 w[l]=w[l]||[]; 255 w[l].push({'gtm.start': new Date().getTime(), event:'gtm.js'}); 256 var f=d.getElementsByTagName(s)[0], 257 j=d.createElement(s), 258 dl=l!='dataLayer' ? '&l='+l : ''; 259 j.async=true; 260 j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl; 261 f.parentNode.insertBefore(j,f); 262})(window,document,'script','dataLayer','
262GTM-NQNDW7N8
vendor: 5 bytes, line 262
262');
263</script>
263 264<!-- End Google Tag Manager --> 265 <!-- GOOGLE TRANSLATE STYLES are moved to external CSS --> 266</head> 267<body> 268 <div id="google_translate_element" style="display: none"></div> 269 270 <nav id="global-navbar" data-el-id="43e7a874-fb1e-4cdd-91fe-eb6bf5b9179b"> 271 <div class="redesign"> 272 <div class="content-container header"> 273 <div class="container header__container"> 274 <div class="navbar"> 275 <div class="logo"> 276 <a href="/" class="logo__link"> 277 <img src="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/763a7f13-106a-4eb9-b01c-a141d951d084" srcset="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/763a7f13-106a-4eb9-b01c-a141d951d084 320w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=960/https://media-production.lp-cdn.com/media/763a7f13-106a-4eb9-b01c-a141d951d084 960w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/763a7f13-106a-4eb9-b01c-a141d951d084 1204w" class="logo__img light" alt=""> 278 <img src="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/5bb6e51a-0a21-4b36-8093-de315d6668eb" srcset="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/5bb6e51a-0a21-4b36-8093-de315d6668eb 320w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=960/https://media-production.lp-cdn.com/media/5bb6e51a-0a21-4b36-8093-de315d6668eb 960w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/5bb6e51a-0a21-4b36-8093-de315d6668eb 1204w" class="logo__img dark" alt=""> 279 </a> 280 </div> 281 <div class="navigation"> 282 <ul> 283 <li class="navigation__item"> 284 <a href="/properties#section-07fdb1fd-54c6-4239-b9ed-3d3cfe67f346" class="navigation__link wow fadeInUp" data-wow-delay="2.0"><span>EXCLUSIVE LISTINGS</span></a> 285 </li> 286 <li class="navigation__item sub-nav-container"> 287 <a href="#" class="navigation__link wow fadeInUp">PROPERTY SEARCH</a> 288 <div class="sub-nav"> 289 <ul> 290 <li class="sub-nav__item"><a href="/home-search/listings?listingStatus=%5B"ACTIVE"%2C"COMING_SOON"%5D&center=%7B"lat"%3A25.937363334561955%2C"lng"%3A-81.70762106736352%7D&boundary=%5B%5B%5B25.999558168278156%2C-81.80615469773461%5D%2C%5B25.999558168278156%2C-81.60908743699243%5D%2C%5B25.875135646634796%2C-81.60908743699243%5D%2C%5B25.875135646634796%2C-81.80615469773461%5D%2C%5B25.999558168278156%2C-81.80615469773461%5D%5D%5D" class="nav-link sub-nav__link feature"><span>SEARCH ALL</span></a></li> 291 <li class="sub-nav__item"><a href="/basic-search" class="nav-link sub-nav__link feature"><span>BASIC SEARCH</span></a></li> 292 </ul> 293 </div> 294 </li> 295 <li class="navigation__item"> 296 <a href="/communities" class="navigation__link wow fadeInUp" data-wow-delay="2.2"><span>COMMUNITIES</span></a> 297 </li> 298 <li class="navigation__item"> 299 <a href="/shop" class="navigation__link wow fadeInUp" data-wow-delay="2.3"><span>SHOP</span></a> 300 </li> 301 <li class="navigation__item"> 302 <a data-type="CONTACT_US" class="navigation__link wow fadeInUp"><span>CONTACT</span></a> 303 </li> 304 </ul> 305 </div> 306 <div class="buttons-wrapper"> 307 <button type="button" class="hamburger-component hamburger"> 308 <span class="hamburger__bars"></span> 309 </button> 310 </div> 311 </div> 312 </div> 313 </div> 314</div> 315 316 </nav> 317 <div id="global-sidemenu" class="sidemenu" data-el-id="11fa925d-d2dd-4213-a0fa-d46f769e2c18"> 318 <div class="sidebar"> 319 320 <button class="toggle sidebar__close close"></button> 321 <div class="sidebar__content"> 322 323 <ul class="sidebar__nav"> 324 <li class="sidebar__nav-item"> 325 <a href="/" class="sidebar__nav-link">Home</a> 326 </li> 327 <li class="sidebar__nav-item"> 328 <a href="/about-us" class="sidebar__nav-link">About Us</a> 329 </li> 330 <li class="sidebar__nav-item"> 331 <a href="/testimonials" class="sidebar__nav-link">Testimonials</a> 332 </li> 333 <li class="sidebar__nav-item"> 334 <a href="/properties" class="sidebar__nav-link">Exclusive Listings</a> 335 </li> 336 <li class="sidebar__nav-item sub-nav-container"> 337 <div class="sub-nav"> 338 <ul class="sidebar__subnav"> 339 <li class="sidebar__subnav-item"><a href="/home-search/listings?listingStatus=%5B"ACTIVE"%2C"COMING_SOON"%5D&center=%7B"lat"%3A25.937363334561955%2C"lng"%3A-81.70762106736352%7D&boundary=%5B%5B%5B25.999558168278156%2C-81.80615469773461%5D%2C%5B25.999558168278156%2C-81.60908743699243%5D%2C%5B25.875135646634796%2C-81.60908743699243%5D%2C%5B25.875135646634796%2C-81.80615469773461%5D%2C%5B25.999558168278156%2C-81.80615469773461%5D%5D%5D" class="sidebar__subnav-link">SEARCH ALL</a></li> 340 <li class="sidebar__subnav-item"><a href="/basic-search" class="sidebar__subnav-link">BASIC SEARCH</a></li> 341 </ul> 342 </div> 343 <a href="#" class="sidebar__nav-link link main-nav">Property Search</a> 344 </li> 345 <li class="sidebar__nav-item"> 346 <a href="/home-valuation" class="sidebar__nav-link">Home Valuation</a> 347 </li> 348 <li class="sidebar__nav-item"> 349 <a href="/communities" class="sidebar__nav-link">Communities</a> 350 </li> 351 <li class="sidebar__nav-item"> 352 <a href="https://heyzine.com/flip-book/6a28dfd085.html" class="sidebar__nav-link">Marco Island Life Ebook</a> 353 </li> 354 <li class="sidebar__nav-item"> 355 <a target="_blank" href="http://Marcoislandlife.myshopify.com" class="sidebar__nav-link">Shop</a> 356 </li> 357 <li class="sidebar__nav-item"> 358 <a href="/contact-us" class="sidebar__nav-link">Contact</a> 359 </li> 360 <li class="sidebar__nav-item"> 361 <a href="/home-search/account" class="sidebar__nav-link">My Search Portal</a> 362 </li> 363 </ul> 364 </div> 365</div> 366 </div> 367 <div id="global-mobile-contact" class="mobile-contact-wrapper" data-el-id="befe5af2-a6ca-4119-924a-a85d96d36b51"> 368 <div class="btn-holder" 369style=" 370--backgroundColor: rgba(255, 255, 255, 1); 371--textColor: rgba(54, 54, 54, 1); 372--pillTextColor: rgba(255, 255, 255, 1);
373--pillBackgroundColor: rgba(54, 54, 54, 1);"> 374 375 <a href="/home-search/listings" class="search-btn lp-ico lp-ico-search visible hyperlink-style-1">Search</a> 376 <button type="button" class="connect-btn lp-ico lp-ico-arrow-top visible">Contact Us</button> 377</div> 378 379 380<div class="pop-up" style="--backgroundColor: rgba(255, 255, 255, 1); --textColor: rgba(54, 54, 54, 1);"> 381 <div class="lp-container"> 382 <form data-type="contact-form" class="contact-form"> 383 <div class="contact-form__container"> 384 <h3 class="lp-h3">Leave a Message</h3> 385 386 <div class="contact-form__content"> 387 <div class="contact-form__inputs-container"> 388 <div class="contact-form__item"> 389 <input 390 id="__FullName" 391 type="text" name="name" 392 class="lp-input lp-input--light" 393 required 394 placeholder="Full Name"> 395 </div> 396 <div class="contact-form__item"> 397 <input 398 id="__Email" 399 type="email" name="email" 400 class="lp-input js-email-input lp-input--light" 401 required 402 placeholder="Email"> 403 </div> 404 <div class="contact-form__item"> 405 <input 406 class="lp-input lp-input--light" 407 type="tel" 408 placeholder="Phone" 409 id="__Phone" 410 name="phone" 411 required> 412 </div> 413 414 <div class="contact-form__item input-group-select"> 415 <select name="interest" id="-field-interest" placeholder="Interest" 416 class="lp-input dropdown-select js-select js-form-element lp-input--light" required> 417 <option value="" disabled selected data-label="Interest">Interested in...</option> 418 <option value="Selling & Buying">Selling & Buying</option> 419 <option value="Selling">Selling</option> 420 <option value="Buying">Buying</option> 421 <option value="Renting">Renting</option> 422 <option value="Other">Other</option> 423 </select> 424 <label for="-field-interest" class="lp-label sr-only">Interest</label> 425 </div> 426 427 <div class="contact-form__item"> 428 <textarea 429 name="message" 430 rows="4" 431 id="__Message" 432 class="lp-input lp-input--light" 433 placeholder="Message" 434 required></textarea> 435 </div> 436 <div class="lp-disclaimer"> <label style='display: none;' for='-termsAccepted'>Opt In/Disclaimer Consent:</label> 437 <label class='lp-tcr-content'> 438 <span class='lp-tcr-checkbox'> 439 <input 440 type='checkbox' 441 id='-termsAccepted' 442 name='termsAccepted' 443 oninvalid="this.setCustomValidity('Please accept the terms and conditions')" 444 oninput="this.setCustomValidity('')" 445 required 446 /></span> 447 <span class='lp-tcr-message'> 448 449 I agree to be contacted by 450 Marco island life and Heuermann-Skirkanich Team 451 via call, email, and text for real estate services. To opt out, you can reply 'stop' at any time or reply 'help' for assistance. 452 You can also click the unsubscribe link in the emails. Message and data rates may apply. Message frequency may vary. 453 <a href='/terms-and-conditions' target='_blank'>Privacy Policy</a>. 454 </span> 455 </label> 456 457</div> 458 <button type="submit" class="lp-btn lp-btn--filled lp-btn--dark submit button-style-1 contact-form__item">Submit</button> 459 460 <div class="lp-h-pot"> 461 <input id="__newsSignMiddleName" name="middleName" value="" autocomplete="off" tabindex="-1"> 462 </div> 463 464 <input style="display: none;" type="text" name="source" value="CONTACT_INQUIRY" /> 465 <input type="hidden" name="button_text" value="Contact Us"> 466 </div> 467 </div> 468 </div> 469 470 471 <div class="success-block"> 472 <h3 class="lp-h3 success-message">Thank you for your message. We will be in touch with you shortly.</h3> 473 474 <a 475 href="/properties" 476 477 class="lp-btn lp-btn--filled lp-btn--dark button-style-1" 478 479 480 481 482 483 > 484 Explore Our Properties 485 </a> 486 </div> 487 </form> 488 489 <button type="button" class="close-btn lp-ico lp-ico-close"></button> 490 491 492 </div> 493</div> 494 495 496 </div> 497 <section class="image-section is-font-color-light is-background-color-light" id="section-5006ac4f-d162-45ef-adc7-c4debfbbfdd3" data-el-id="e6c6941b-dd32-4d6b-b4aa-56593f2d58bb"> 498 <div class="redesign custom-intro"> 499 <div class="container"> 500 <h1 class="custom-intro__title">Contact</h1> 501 502 </div> 503</div> 504 505</section> 506<section id="section-aaaa421e-7c8d-4472-bfab-8e962f13cf02" class="solid-section is-font-color-dark is-background-color-light" data-el-id="21c5a117-61cb-4f43-8635-2da86e3ae7dd">
507 <div class="boxed-text contact-cta lp-vertical-paddings redesign"> 508 <div class="lp-container"> 509 510 <div class="lp-title-group"> 511 <h2 class="lp-h2 js-title">Questions? Call or Text Us</h2> 512 513 <a href="tel:2397773905" class="contact-phone"> 514 (239) 777-3905 515 </a> 516 </div> 517 518 <div class="boxed-text__description"> 519 <p> 520 Have a question about buying or selling on Marco Island? Reach out by phone or start a chat with us. 521 </p> 522 </div> 523 524 <div class="button-container"> 525 526 <a 527 href="tel:2397773905" 528 class="lp-btn lp-btn--dark lp-btn--outline" 529 > 530 Call Now 531 </a> 532 533 <a 534 href="#" 535 id="marco-tidio-button" 536 class="lp-btn lp-btn--dark lp-btn--outline" 537 > 538 Text Now 539 </a> 540 541 </div> 542 543 </div> 544</div> 545</section> 546<section id="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72" class="solid-section is-font-color-dark is-background-color-light" data-el-id="ee03b9c1-ce78-4c15-86a1-10124375dc59"> 547 <div class="custom-form redesign" id="js-contact-form"> 548 <div class="lp-container custom-form__container"> 549 550 <div class="custom-form__header"> 551 <h2 class="lp-h2 custom-form__heading">Submit a Message</h2> 552 <div class="custom-form__lead lp-text--subtitle">Fill out the form below to learn more about buying or selling a house in your area.</div> 553 </div> 554 <div class="elem-row custom-form__row"> 555 <div class="elem-col custom-form__img-col"> 556 <div class="custom-form__img-block"> 557 <img src="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/0a07db35-0df1-44d6-ba52-07f002bf2ea2" srcset="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/0a07db35-0df1-44d6-ba52-07f002bf2ea2 320w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=960/https://media-production.lp-cdn.com/media/0a07db35-0df1-44d6-ba52-07f002bf2ea2 960w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/0a07db35-0df1-44d6-ba52-07f002bf2ea2 1280w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1920/https://media-production.lp-cdn.com/media/0a07db35-0df1-44d6-ba52-07f002bf2ea2 1920w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/0a07db35-0df1-44d6-ba52-07f002bf2ea2 2400w" alt="Image Form" sizes="(max-width: 768px) 100vw, 50vw" loading="lazy"> 558 </div> 559 </div> 560 <div class="elem-col custom-form__form-col"> 561 <form class="custom-form__download-form" data-type="contact-form" data-delay="6000"> 562 <div class="form-row custom-form__form-row"> 563 564 <div class="h-pot lp-h-pot"> 565 <label for="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-middleName">Middle Name</label> 566 <input id="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-middleName" name="middleName" value="" autocomplete="off" tabindex="-1"> 567 </div> 568 569 <div class="form-col js-backup-email"> 570 <div class="lp-form-group custom-form__group"> 571 <div class="lp-input-group"> 572 <label for="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-required-email-field" class="lp-label field-required">Email</label> 573 <input type="email" id="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-required-email-field" name="email" class="lp-input lp-input--dark js-form-element js-backup-field" placeholder="Email *" required> 574 </div> 575 </div> 576 </div> 577 578 579 <div class="form-col"> 580 <div class="lp-form-group custom-form__group"> 581 <div class="lp-input-group"> 582 <label for="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-0" class="lp-label field-required">FULL NAME</label> 583 <input type="text" id="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-0" name="name" class="lp-in
583put lp-input--dark js-form-element" placeholder="FULL NAME *" required> 584 </div> 585 </div> 586 </div> 587 <div class="form-col"> 588 <div class="lp-form-group custom-form__group"> 589 <div class="lp-input-group"> 590 <label for="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-1" class="lp-label">PHONE</label> 591 <input type="tel" id="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-1" name="phone" class="lp-input lp-input--dark js-form-element" placeholder="PHONE"> 592 </div> 593 </div> 594 </div> 595 <div class="form-col"> 596 <div class="lp-form-group custom-form__group"> 597 <div class="lp-input-group"> 598 <label for="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-2" class="lp-label field-required">EMAIL</label> 599 <input type="email" id="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-2" name="email" class="lp-input lp-input--dark js-form-element" placeholder="EMAIL *" required> 600 </div> 601 </div> 602 </div> 603 <div class="form-col"> 604 <div class="lp-form-group custom-form__group"> 605 <div class="lp-input-group"> 606 <label for="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-3" class="lp-label field-required">MESSAGE</label> 607 <textarea name="message" rows="4" id="section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-field-3" class="lp-input lp-input--dark js-form-element" placeholder="MESSAGE *" required></textarea> 608 </div> 609 </div> 610 </div> 611 </div> 612 613 <div class="lp-disclaimer"> <label style='display: none;' for='section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-termsAccepted'>Opt In/Disclaimer Consent:</label> 614 <label class='lp-tcr-content'> 615 <span class='lp-tcr-checkbox'> 616 <input 617 type='checkbox' 618 id='section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72-termsAccepted' 619 name='termsAccepted' 620 oninvalid="this.setCustomValidity('Please accept the terms and conditions')" 621 oninput="this.setCustomValidity('')" 622 required 623 /></span> 624 <span class='lp-tcr-message'> 625 626 I agree to be contacted by 627 Marco island life and Heuermann-Skirkanich Team 628 via call, email, and text for real estate services. To opt out, you can reply 'stop' at any time or reply 'help' for assistance. 629 You can also click the unsubscribe link in the emails. Message and data rates may apply. Message frequency may vary. 630 <a href='/terms-and-conditions' target='_blank'>Privacy Policy</a>. 631 </span> 632 </label> 633 634</div> 635 636 <div class="custom-form__footer"> 637 <button type="submit" class="lp-btn lp-btn--dark lp-btn--filled lp-btn--mob-full-width custom-form__submit-btn button-style-1"> 638 <span class="lp-btn-icons"> 639 <span class="lp-btn-icon-loading"></span> 640 <span class="lp-btn-icon-success"></span> 641 </span> 642 Submit 643 </button> 644 </div> 645 </form> 646 </div> 647 </div> 648 </div> 649 <a href="https://marcoislandlife.net/thank-you" class="visually-hidden js-redirect-link">link</a> 650</div> 651 652 653</section> 654<section id="section-7819d273-7c47-485a-a46c-0941f4a0491f" class="solid-section is-font-color-light is-background-color-dark" data-el-id="ee87d271-1520-42d7-88f2-27f85a797fa1"> 655 <div class="gallery-component redesign"> 656 <div class="lp-container gallery-component__container"> 657 <div class="row gallery-component__row cols-3"> 658 659 <div class="gallery-component__col"> 660 <a class="gallery-card" 661 href="/home-search/listings" > 662 <div class="gallery-card__preview"> 663 <img src="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/35f86c33-be5f-4f71-800e-a5040a5b6a04" srcset="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/35f86c33-be5f-4f71-800e-a5040a5b6a04 320w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/35f86c33-be5f-4f71-800e-a5040a5b6a04 960w" class="portrait" alt="" loading="lazy"> 664 </div> 665 <h3 class="lp-h3 gallery-card__title">Home Search</h3> 666 </a> 667 </div> 668 669 670 <div class="gallery-component__col"> 671 <a class="gallery-card" 672 href="/home-valuation" > 673 <div class="gallery-card__preview"> 674 <img src="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/fdc6d0d0-0ebf-4fab-a215-0c59497d6da5" srcset="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/fdc6d0d0-0ebf-4fab-a215-0c59497d6da5 320w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=960/https://media-production.lp-cdn.com/media/fdc6d0d0-0ebf-4fab-a215-0c59497d6da5 960w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/fdc6d0d0-0ebf-4fab-a215-0c59497d6da5 1280w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/fdc6d0d0-0ebf-4fab-a215-0c59497d6da5 1886w" class="portrait" alt="" loading="lazy"> 675 </div> 676 <h3 class="lp-h3 gallery-card__title">Home Valuation</h3> 677 </a> 678 </div> 679 680 681 <div class="gallery-component__col"> 682 <a class="gallery-card" 683 href="/about-us" > 684 <div class="gallery-card__preview"> 685 <img src="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/5faf9e20-12f2-4c57-a7f1-56dbe2771460" srcset="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/5faf9e20-12f2-4c57-a7f1-56dbe2771460 320w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=960/https://media-production.lp-cdn.com/media/5faf9e20-12f2-4c57-a7f1-56dbe2771460 960w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/5faf9e20-12f2-4c57-a7f1-56dbe2771460 1280w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1920/https://media-production.lp-cdn.com/media/5faf9e20-12f2-4c57-a7f1-56dbe2771460 1920w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/5faf9e20-12f2-4c57-a7f1-56dbe2771460 2100w" class="portrait" alt="" loading="lazy"> 686 </div> 687 <h3 class="lp-h3 gallery-card__title">About us</h3> 688 </a> 689 </div> 690 691 </div> 692 </div> 693</div> 694 695 696</section> 697<section id="section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b" class="solid-section is-font-color-light is-background-color-dark" data-el-id="5db65d6a-01e9-4ee3-babf-2748e074a284"> 698
698<script type="text/x-handlebars-template" class="jsIGItem"> 699 <a href="{{permalink}}" target="_blank" class="ig-feed-item insta-type-{{mediaType}}"> 700 <div class="ig-feed-item__img" style="background-image: url('{{#ifEquals mediaType 'VIDEO'}}{{thumbnailUrl}}{{^}}{{mediaUrl}}{{/ifEquals}}');"></div> 701 <div class="ig-feed-item__info"><div class="ig-feed-item__caption">{{caption}}</div></div> 702 {{#ifEquals mediaType 'VIDEO'}}<div class="video-icon"></div>{{/ifEquals}} 703 </a> 704</script>
704 705<div class="ig-feed redesign"> 706 <div class="ig-feed-top lp-container"> 707 <div class="top-wrapper"> 708 <div class="top-left"> 709 <h3 class="lp-h3 title">Follow us on Instagram</h3> 710 <a href="#" target="_blank" class="instagram-link jsIGLink"><h4 class="lp-h4 instagram-name jsIGName"></h4></a> 711 </div> 712 <div class="top-right"> 713 <a href="#" target="_blank" class="lp-btn lp-btn--dark lp-btn--outline lp-btn--mob-full-width follow-button jsIGLink button-style-2">Follow Us</a> 714 <a class="nav-button top-nav-prev hidden-control button-style-2"> 715 <svg width="9" height="15" viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.099 13.25l-5.25-5.775L7.099 1.7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 716 </a> 717 <a class="nav-button top-nav-next hidden-control button-style-2"> 718 <svg width="9" height="15" viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.90137 1.75L7.15137 7.525L1.90137 13.3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 719 </a> 720 </div> 721 </div> 722 </div> 723 <div class="lp-container ig-feed-container "> 724 <div class="ig-feed-feed" data-limit="33"> 725 </div> 726 </div> 727 <div class="bottom-controls"> 728 <a class="bottom-nav-button bottom-nav-prev button-style-2"> 729 <svg width="9" height="15" viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.099 13.25l-5.25-5.775L7.099 1.7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 730 </a> 731 <a class="bottom-nav-button bottom-nav-next button-style-2"> 732 <svg width="9" height="15" viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.90137 1.75L7.15137 7.525L1.90137 13.3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 733 </a> 734 </div> 735</div> 736 737</section> 738 739 <div id="modals" class="modals"></div> 740 <footer id="global-footer" class="is-font-color-dark is-background-color-light" data-el-id="874a9373-949d-4275-b72f-04c2a6ec373b"> 741 <div class="footer redesign no_newsletter "> 742 <div class="container"> 743 <h3>Heuermann-Skirkanich Team</h3> 744 <div class="info-wrap"> 745 <div class="info-wrap-contact agent_box"> 746 <div class="info-wrap-contact_zone type_user"> 747 <h4 class="serif">Contact Us</h4> 748 <div class="info-wrap-contact_cell"> 749 <i> 750 <svg width="30" height="19" viewBox="0 0 30 19" fill="none" xmlns="http://www.w3.org/2000/svg"> 751 <path d="M2 0C0.903517 0 0 0.903517 0 2V16.6667C0 17.7631 0.903517 18.6667 2 18.6667H28C29.0965 18.6667 30 17.7631 30 16.6667V2C30 0.903517 29.0965 0 28 0H2ZM2.4375 1.33333H27.5625L15.6458 11.4896C15.3389 11.7512 14.6612 11.7512 14.3542 11.4896L2.4375 1.33333ZM1.33333 2.13542L10.1979 9.6979L1.33333 16.5729V2.13542ZM28.6667 2.13542V16.5729L19.8021 9.6979L28.6667 2.13542ZM11.2396 10.5833L13.4896 12.5C14.3543 13.2369 15.6457 13.2369 16.5104 12.5L18.7604 10.5833L27.4687 17.3333H2.53125L11.2396 10.5833Z" fill="#1A1A1A" /> 752 </svg> 753 </i> 754 <p class="contact_title">Email</p> 755 <a href="/cdn-cgi/l/email-protection#4c232a2a252f290c212d3e2f23253f202d222820252a2962222938" class="lp-link info-wrap-contact_link grey-text hyperlink-style-1"><span class="__cf_email__" data-cfemail="066960606f6563466b677465696f756a6768626a6f606328686372">[email protected]</span></a> 756 </div> 757 <div class="info-wrap-contact_cell"> 758 <i><svg width="30" height="25" viewBox="0 0 30 25" fill="none" xmlns="http://www.w3.org/2000/svg"> 759 <path fill-rule="evenodd" clip-rule="evenodd" d="M10.7964 8.1207H19.2036V8.7279C19.2036 10.8195 20.9082 12.5259 23.001 12.5259H24.741L25.2852 20.7051C25.3776 22.1235 24.2868 23.2719 22.8822 23.2719H7.0032C5.5944 23.2719 4.5084 22.1085 4.6002 20.7039C4.782 17.9895 4.9152 15.23
75913 5.154 12.5265H6.9996C9.0918 12.5265 10.797 10.8207 10.797 8.7285V8.1207H10.7964ZM11.46 16.5807C11.46 14.6565 13.0188 13.0977 14.943 13.0977C16.8666 13.0977 18.4254 14.6571 18.4254 16.5807C18.4254 18.5055 16.8678 20.0631 14.943 20.0631C13.02 20.0637 11.46 18.5043 11.46 16.5807ZM14.943 12.0381C12.4344 12.0381 10.4004 14.0721 10.4004 16.5807C10.4004 19.0887 12.435 21.1233 14.943 21.1233C17.4486 21.1233 19.485 19.0869 19.485 16.5807C19.485 14.0727 17.451 12.0381 14.943 12.0381ZM9.0846 4.8363C8.22 4.8363 7.512 5.5443 7.512 6.4089V8.7285C7.512 9.0093 7.2804 9.2415 6.999 9.2415H1.5726C1.2906 9.2415 1.0596 9.0111 1.0596 8.7285V6.9285C1.0596 6.4797 1.1628 6.0945 1.3902 5.7069C1.896 4.8465 2.7294 4.1013 3.795 3.4749C9.279 0.2517 20.7192 0.2523 26.2044 3.4749C27.2706 4.1013 28.104 4.8465 28.6098 5.7069C28.8354 6.0921 28.9398 6.4815 28.9398 6.9285V8.7285C28.9398 9.0111 28.71 9.2415 28.4268 9.2415H23.0004C22.719 9.2415 22.4874 9.0093 22.4874 8.7285V6.4089C22.4874 5.5425 21.7806 4.8363 20.9148 4.8363H9.0846ZM8.571 6.4089C8.571 6.1263 8.8026 5.8965 9.0846 5.8965H20.9154C21.1968 5.8965 21.429 6.1275 21.429 6.4089V8.7285C21.429 9.5943 22.1352 10.3017 23.001 10.3017H28.4274C29.292 10.3017 30 9.5931 30 8.7285V6.9285C30 6.2835 29.8464 5.7291 29.5206 5.1729C28.9188 4.1493 27.9564 3.2799 26.7384 2.5641C20.9214 -0.8547 9.0798 -0.8547 3.2622 2.5641C2.0436 3.2799 1.0812 4.1487 0.48 5.1729C0.153 5.7291 0 6.2835 0 6.9279V8.7279C0 9.5925 0.7092 10.3011 1.5726 10.3011H6.999C7.8648 10.3011 8.571 9.5937 8.571 8.7279V6.4089ZM9.7368 7.5915V8.7285C9.7368 10.2387 8.5092 11.4669 6.999 11.4669H4.6686C4.3914 11.4669 4.164 11.6799 4.1412 11.9511C3.8892 14.8347 3.7386 17.7435 3.5448 20.6331C3.4116 22.6425 4.989 24.3315 7.0032 24.3315H22.8822C24.882 24.3315 26.475 22.6575 26.3406 20.6343L25.7622 11.9607C25.7436 11.6811 25.5102 11.4675 25.2342 11.4675L23.001 11.4663C21.4902 11.4663 20.2632 10.2375 20.2632 8.7279V7.5909C20.2632 7.2981 20.0262 7.0611 19.7334 7.0611H10.2666C9.9738 7.0611 9.7368 7.2987 9.7368 7.5915Z" fill="#1A1A1A" /> 760 </svg></i> 761 <p class="contact_title">Phone Number</p> 762 <a href="tel:2397773905" class="lp-link info-wrap-contact_link grey-text hyperlink-style-1">239.777.3905</a> 763 </div> 764 </div> 765 <div class="info-wrap-contact_zone"> 766 <div class="info-wrap-contact_cell"> 767 <i> 768 <svg width="31" height="30" viewBox="0 0 31 30" fill="none" xmlns="http://www.w3.org/2000/svg"> 769 <path d="M29.9821 6.49489C29.7931 6.35756 29.679 6.32046 29.4572 6.39228L20.298 9.41368L16.1952 8.03558L15.8172 9.41525L19.7644 10.7038V28.1462L9.89831 25.7069V22.1034H8.71438V25.7515L1.21616 28.2532V15.3945H0.0322266V29.2729C0.0322266 29.5077 0.130098 29.7279 0.321106 29.8645C0.445418 29.9541 0.585911 29.9999 0.735086 29.9999C0.814804 29.9999 0.890971 29.9868 0.967926 29.96L9.48433 27.029L20.1792 29.7887C20.3224 29.8254 20.4751 29.8171 20.6152 29.7654L29.8104 26.2235C30.0942 26.1177 30.0251 25.8466 30.0251 25.5431V7.08291C30.0251 6.85086 30.17 6.63144 29.9821 6.49489ZM28.8412 25.0388L20.9483 28.0361V10.7065L28.8412 8.08649V25.0388Z" fill="#1A1A1A" /> 770 <path d="M6.57515 19.1142C6.6671 19.422 6.95006 19.6323 7.2713 19.6323C7.59215 19.6323 7.87511 19.422 7.96746 19.1142C8.67742 16.7514 10.0393 15.2447 11.3559 13.788C12.9944 11.9747 14.5422 10.2615 14.5422 7.2717C14.5422 3.39788 11.1451 0 7.2713 0C3.39827 0 0 3.39748 0 7.2717C0 10.2615 1.54819 11.9747 3.18674 13.788C4.50328 15.2447 5.86479 16.7514 6.57515 19.1142ZM7.2713 1.45426C10.316 1.45426 13.0883 4.22663 13.0883 7.2717C13.0883 9.70191 11.7852 11.1435 10.2769 12.8121C9.2461 13.9534 8.10992 15.2096 7.2713 16.9199C6.43229 15.2096 5.29651 13.953 4.2657 12.8121C2.75698 11.1432 1.45426 9.70191 1.45426 7.2717C1.45426 4.22663 4.22663 1.45426 7.2713 1.45426Z" fill="#1A1A1A" /> 771 <path d="M7.26193 10.1616C8.8705 10.1616 10.1795 8.86084 10.1795 7.26175C10.1795 5.66305 8.87089 4.3623 7.26193 4.3623C5.65297 4.3623 4.34473 5.66305 4.34473 7.26175C4.34512 8.86084 5.65336 10.1616 7.26193 10.1616ZM7.26193 5.81657C8.06898 5.81657 8.72527 6.46536 8.72527 7.26175C8.72527 8.05932 8.06898 8.70733 7.26193 8.70733C6.45528 8.70733 5.79899 8.05893 5.79899 7.26175C5.79899 6.46536 6.45528 5.81657 7.26193 5.81657Z" fill="#1A1A1A" /> 772 </svg> 773 </i> 774 <p class="info-wrap-contact_title">Address</p> 775 <p class="info-wrap-contact_link grey-text"><p>760 N Collier Blvd #101B<br>Marco Island, FL 34145</p></p> 776 </div> 777 </div> 778 </div> 779 </div> 780 <div class="text_footer first_text_footer"> 781 <div class="images_box"> 782 <div class="img_size"> 783 <img src="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/0b3cb7de-917c-4091-a11e-189728a1787f" srcset="https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/0b3cb7de-917c-4091-a11e-189728a1787f 320w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/0b3cb7de-917c-4091-a11e-189728a1787f 400w" alt="Footer Image" sizes="200px"> 784 </div> 785 </div> 786 <div class="luxury-text"> 787 <p style="font-size: 12px;">âââââSotheby’s International Realty® and the Sotheby’s International Realty Logo are service marks licensed to Sotheby’s International Realty Affiliates LLC and used with permission. Premier Sotheby’s International Realty fully supports the principles of the Fair Housing Act and the Equal Opportunity Act. Eac
787h office is independently owned and operated. Any services or products provided by independently owned and operated franchisees are not provided by, affiliated with or related to Sotheby’s International Realty Affiliates LLC nor any of its affiliated companies.<br><br></p> 788<p style="opacity: 1;"><img style="width: 100px; height: auto;" src="https://res.cloudinary.com/luxuryp/images/zbxf1j3xdplm6lhfnqo3/realtor-eho-logo-07232021-update-dark"></p> 789<p style="opacity: 1;"> </p> 790<p style="opacity: 1;"><a class="link lp-link" style="text-transform: unset!important;" href="https://d1e1jt2fj4r8r.cloudfront.net/cccfad5c-784f-4d3e-8950-0449a0ebf171/65a2c6d0-f1be-4c45-9eb8-201def5b5c87/Website%20Terms%20and%20Conditions.pdf" target="_blank" rel="noopener">Website Terms and Conditions</a></p> 791 </div> 792 </div> 793 <div class="text_footer second_text_footer"> 794 <div class="text_content_wrap"> 795 <div> 796 Sothebyâs International Realty® is a registered trademark licensed to Sothebyâs International Realty Affiliates LLC. Each Office Is Independently Owned and Operated. 797 </div> 798 <div> 799 <div> </div> 800<style>* { box-sizing: border-box; } body {margin: 0;}ul{list-style:inherit;}</style> 801 </div> 802 </div> 803 </div> 804 <div class="info-privacy"> 805 <div class="form-row info-privacy__row"> 806 807 <div class="form-col form-col--powered powered-box"> 808 <div class="powered_zone"> 809 810 </div> 811 </div> 812 813 <div class="form-col form-col--copyright"> 814 <div class="copy_zone"> 815 <span class="copy_words">Copyright ©</span> <span class="auto-year-update">2026</span> 816 | <a href="/terms-and-conditions" class="lp-link grey-text hyperlink-style-1">Privacy Policy</a> 817 818 </div> 819 </div> 820 821 <div class="form-col form-col--socials"> 822 <ul class="lp-socials social_icons-style-1 socials socials--grey socials_zone"> 823 824 <li> 825 <a 826 href="https://www.facebook.com/profile.php?id=61572442867930" 827 class="lp-socials__link socials__item socials__link wow fadeInUp" 828 data-wow-delay="0s" 829 target="_blank" 830 aria-label="FACEBOOK" 831 > 832 <span class="lp-i lp-i--facebook" aria-hidden="true"></span> 833 </a> 834 </li> 835 <li> 836 <a 837 href="https://www.instagram.com/Marco.island.life/" 838 class="lp-socials__link socials__item socials__link wow fadeInUp" 839 data-wow-delay="0.1s" 840 target="_blank" 841 aria-label="INSTAGRAM" 842 > 843 <span class="lp-i lp-i--instagram" aria-hidden="true"></span> 844 </a> 845 </li> 846 <li> 847 <a 848 href="https://x.com/MarcoIslandLife" 849 class="lp-socials__link socials__item socials__link wow fadeInUp" 850 data-wow-delay="0.2s" 851 target="_blank" 852 aria-label="TWITTER" 853 > 854 <span class="lp-i lp-i--twitter" aria-hidden="true"></span> 855 </a> 856 </li> 857 <li> 858 <a 859 href="https://www.linkedin.com/in/elizabeth-heuermann-323894378" 860 class="lp-socials__link socials__item socials__link wow fadeInUp" 861 data-wow-delay="0.3s" 862 target="_blank" 863 aria-label="LINKEDIN" 864 >
865 <span class="lp-i lp-i--linkedin" aria-hidden="true"></span> 866 </a> 867 </li> 868 <li> 869 <a 870 href="https://www.tiktok.com/@marcoislandlife" 871 class="lp-socials__link socials__item socials__link wow fadeInUp" 872 data-wow-delay="0.4s" 873 target="_blank" 874 aria-label="TIKTOK" 875 > 876 <span class="lp-i lp-i--tiktok" aria-hidden="true"></span> 877 </a> 878 </li> 879 </ul> </div> 880 </div> 881 </div> 882 </div> 883</div> 884 885 </footer> 886 887 <div id="modal-global-contact-us" class="modal " 888 data-el-id="" 889 style="background-color: ;" 890 > 891 <div class="modal-content"> 892 <div class="contact-form redesign " style="background-image: url('https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/76d49133-9bf7-4603-8042-85e76217f9a5')"> 893 <div class="container"> 894 <div class="section-details" style="--colorTxt: #ffffff"> 895 <h2>Contact Details</h2> 896 897 <div class="info-zone"> 898 899 <div class="info-zone_contact type_user"> 900 <h4 class="serif">Heuermann-Skirkanich Team</h4> 901 <div class="info-zone_contact_cell"> 902 <i> 903 <svg width="30" height="25" viewBox="0 0 30 25" fill="none" xmlns="http://www.w3.org/2000/svg"> 904 <path fill-rule="evenodd" clip-rule="evenodd" d="M10.7964 8.1207H19.2036V8.7279C19.2036 10.8195 20.9082 12.5259 23.001 12.5259H24.741L25.2852 20.7051C25.3776 22.1235 24.2868 23.2719 22.8822 23.2719H7.0032C5.5944 23.2719 4.5084 22.1085 4.6002 20.7039C4.782 17.9895 4.9152 15.2313 5.154 12.5265H6.9996C9.0918 12.5265 10.797 10.8207 10.797 8.7285V8.1207H10.7964ZM11.46 16.5807C11.46 14.6565 13.0188 13.0977 14.943 13.0977C16.8666 13.0977 18.4254 14.6571 18.4254 16.5807C18.4254 18.5055 16.8678 20.0631 14.943 20.0631C13.02 20.0637 11.46 18.5043 11.46 16.5807ZM14.943 12.0381C12.4344 12.0381 10.4004 14.0721 10.4004 16.5807C10.4004 19.0887 12.435 21.1233 14.943 21.1233C17.4486 21.1233 19.485 19.0869 19.485 16.5807C19.485 14.0727 17.451 12.0381 14.943 12.0381ZM9.0846 4.8363C8.22 4.8363 7.512 5.5443 7.512 6.4089V8.7285C7.512 9.0093 7.2804 9.2415 6.999 9.2415H1.5726C1.2906 9.2415 1.0596 9.0111 1.0596 8.7285V6.9285C1.0596 6.4797 1.1628 6.0945 1.3902 5.7069C1.896 4.8465 2.7294 4.1013 3.795 3.4749C9.279 0.2517 20.7192 0.2523 26.2044 3.4749C27.2706 4.1013 28.104 4.8465 28.6098 5.7069C28.8354 6.0921 28.9398 6.4815 28.9398 6.9285V8.7285C28.9398 9.0111 28.71 9.2415 28.4268 9.2415H23.0004C22.719 9.2415 22.4874 9.0093 22.4874 8.7285V6.4089C22.4874 5.5425 21.7806 4.8363 20.9148 4.8363H9.0846ZM8.571 6.4089C8.571 6.1263 8.8026 5.8965 9.0846 5.8965H20.9154C21.1968 5.8965 21.429 6.1275 21.429 6.4089V8.7285C21.429 9.5943 22.1352 10.3017 23.001 10.3017H28.4274C29.292 10.3017 30 9.5931 30 8.7285V6.9285C30 6.2835 29.8464 5.7291 29.5206 5.1729C28.9188 4.1493 27.9564 3.2799 26.7384 2.5641C20.9214 -0.8547 9.0798 -0.8547 3.2622 2.5641C2.0436 3.2799 1.0812 4.1487 0.48 5.1729C0.153 5.7291 0 6.2835 0 6.9279V8.7279C0 9.5925 0.7092 10.3011 1.5726 10.3011H6.999C7.8648 10.3011 8.571 9.5937 8.571 8.7279V6.4089ZM9.7368 7.5915V8.7285C9.7368 10.2387 8.5092 11.4669 6.999 11.4669H4.6686C4.3914 11.4669 4.164 11.6799 4.1412 11.9511C3.8892 14.8347 3.7386 17.7435 3.5448 20.6331C3.4116 22.6425 4.989 24.3315 7.0032 24.3315H22.8822C24.882 24.3315 26.475 22.6575 26.3406 20.6343L25.7622 11.9607C25.7436 11.6811 25.5102 11.4675 25.2342 11.4675L23.001 11.4663C21.4902 11.4663 20.2632 10.2375 20.2632 8.7279V7.5909C20.2632 7.2981 20.0262 7.0611 19.7334 7.0611H10.2666C9.9738 7.0611 9.7368 7.2987 9.7368 7.5915Z" fill="#1A1A1A"/> 905 </svg> 906 </i> 907 <p class="contact_title">Phone</p> 908 <a href="tel:239.777.3905" class="lp-link info-zone_contact_link link hyperlink-style-2">239.777.3905</a> 909 </div> 910 <div class="info-zone_contact_cell"> 911 <i> 912 <svg width="30" height="19" viewBox="0 0 30 19" fill="none" xmlns="http://www.w3.org/2000/svg"> 913 <path d="M2 0C0.903517 0 0 0.903517 0 2V16.6667C0 17.7631 0.903517 18.6667 2 18.6667H28C29.0965 18.6667 30 17.7631 30 16.6667V2C30 0.903517 29.0965 0 28 0H2ZM2.4375 1.33333H27.5625L15.6458 11.4896C15.3389 11.7512 14.6612 11.7512 14.3542 11.4896L2.4375 1.33333ZM1.33333 2.13542L10.1979 9.6979L1.33333 16.5729V2.13542ZM28.6667 2.13542V16.5729L19.8021 9.6979L28.6667 2.13542ZM11.2396 10.5833L13.4896 12.5C14.3543 13.2369 15.6457 13.2369 16.5104 12.5L18.7604 10.5833L27.4687 17.3333H2.53125L11.2396 10.5833Z" fill="#1A1A1A"/> 914 </svg> 915 </i> 916 <p class="contact_title">Email</p> 917 <a href="/cdn-cgi/l/email-protection#177871717e7472577a766574787e647b7679737b7e717239797263" class="lp-link info-zone_contact_link link hyperlink-style-2"><span class="__cf_email__" data-cfemail="701f1616191315301d1102131f19031c111e141c1916155e1e1504">[email protected]</span></a> 918 </div> 919 </div> 920 <div class="info-zone_contact"> 921 <div class="info-zone_contact_cell"> 922 <i> 923 <svg width="31" height="30" viewBox="0 0 31 30" fill="none" xmlns="http://www.w3.org/2000/svg"> 924 <path d="M29.9821 6.49489C29.7931 6.35756 29.679 6.32046 29.4572 6.39228L20.298 9.41368L16.1952 8.03558L15.8172 9.41525L19.7644 10.7038V28.1462L9.89831 25.7069V22.1034H8.71438V25.7515L1.21616 28.2532V15.3945H0.0322266V29.2729C0.0322266 29.5077 0.130098 29.7279 0.321106 29.8645C0.445418 29.9541 0.585911 29.9999 0.735086 29.9999C0.814804 29.9999 0.890971 29.9868 0.967926 29.96L9.48433 27.029L20.1792 29.7887C20.3224 29.8254 20.4751 29.8171 20.6152 29.7654L29.8104 26.2235C30.0942 26.1177 3
9240.0251 25.8466 30.0251 25.5431V7.08291C30.0251 6.85086 30.17 6.63144 29.9821 6.49489ZM28.8412 25.0388L20.9483 28.0361V10.7065L28.8412 8.08649V25.0388Z" fill="#1A1A1A"/> 925 <path d="M6.57515 19.1142C6.6671 19.422 6.95006 19.6323 7.2713 19.6323C7.59215 19.6323 7.87511 19.422 7.96746 19.1142C8.67742 16.7514 10.0393 15.2447 11.3559 13.788C12.9944 11.9747 14.5422 10.2615 14.5422 7.2717C14.5422 3.39788 11.1451 0 7.2713 0C3.39827 0 0 3.39748 0 7.2717C0 10.2615 1.54819 11.9747 3.18674 13.788C4.50328 15.2447 5.86479 16.7514 6.57515 19.1142ZM7.2713 1.45426C10.316 1.45426 13.0883 4.22663 13.0883 7.2717C13.0883 9.70191 11.7852 11.1435 10.2769 12.8121C9.2461 13.9534 8.10992 15.2096 7.2713 16.9199C6.43229 15.2096 5.29651 13.953 4.2657 12.8121C2.75698 11.1432 1.45426 9.70191 1.45426 7.2717C1.45426 4.22663 4.22663 1.45426 7.2713 1.45426Z" fill="#1A1A1A"/> 926 <path d="M7.26193 10.1616C8.8705 10.1616 10.1795 8.86084 10.1795 7.26175C10.1795 5.66305 8.87089 4.3623 7.26193 4.3623C5.65297 4.3623 4.34473 5.66305 4.34473 7.26175C4.34512 8.86084 5.65336 10.1616 7.26193 10.1616ZM7.26193 5.81657C8.06898 5.81657 8.72527 6.46536 8.72527 7.26175C8.72527 8.05932 8.06898 8.70733 7.26193 8.70733C6.45528 8.70733 5.79899 8.05893 5.79899 7.26175C5.79899 6.46536 6.45528 5.81657 7.26193 5.81657Z" fill="#1A1A1A"/> 927 </svg> 928 </i> 929 <p class="info-wrap-contact_title">Address</p> 930 <p class="info-zone_contact_link pre-line">760 N Collier Blvd #101B 931 Marco Island, FL 34145</p> 932 </div> 933 </div> 934 <div class="info-zone_contact"> 935 <div class="info-zone_contact_cell"> 936 <p class="pre-line"><div></div><style>* { box-sizing: border-box; } body {margin: 0;}ul{list-style:inherit;}</style></p> 937 </div> 938 </div> 939 <ul class="lp-socials social_icons-style-2 socials socials--grey socials_zone footer__contact-column"> 940 941 <li> 942 <a 943 href="https://www.facebook.com/profile.php?id=61572442867930" 944 class="lp-socials__link socials__item wow fadeInUp socials__link" 945 data-wow-delay="0s" 946 target="_blank" 947 aria-label="FACEBOOK" 948 > 949 <span class="lp-i lp-i--facebook" aria-hidden="true"></span> 950 </a> 951 </li> 952 <li> 953 <a 954 href="https://www.instagram.com/Marco.island.life/" 955 class="lp-socials__link socials__item wow fadeInUp socials__link" 956 data-wow-delay="0.1s" 957 target="_blank" 958 aria-label="INSTAGRAM" 959 > 960 <span class="lp-i lp-i--instagram" aria-hidden="true"></span> 961 </a> 962 </li> 963 <li> 964 <a 965 href="https://x.com/MarcoIslandLife" 966 class="lp-socials__link socials__item wow fadeInUp socials__link" 967 data-wow-delay="0.2s" 968 target="_blank" 969 aria-label="TWITTER" 970 > 971 <span class="lp-i lp-i--twitter" aria-hidden="true"></span> 972 </a> 973 </li> 974 <li> 975 <a 976 href="https://www.linkedin.com/in/elizabeth-heuermann-323894378" 977 class="lp-socials__link socials__item wow fadeInUp socials__link" 978 data-wow-delay="0.3s" 979 target="_blank" 980 aria-label="LINKEDIN" 981 >
982 <span class="lp-i lp-i--linkedin" aria-hidden="true"></span> 983 </a> 984 </li> 985 <li> 986 <a 987 href="https://www.tiktok.com/@marcoislandlife" 988 class="lp-socials__link socials__item wow fadeInUp socials__link" 989 data-wow-delay="0.4s" 990 target="_blank" 991 aria-label="TIKTOK" 992 > 993 <span class="lp-i lp-i--tiktok" aria-hidden="true"></span> 994 </a> 995 </li> 996 </ul> </div> 997 </div> 998 <div class="section-message"> 999 <form data-type="contact-form"> 1000 <h2>Submit a Message</h2> 1001 <div class="h-pot"> 1002 <label for="-middleName">Middle Name</label> 1003 <input id="-middleName" name="middleName" value="" autocomplete="off" tabindex="-1"> 1004 </div> 1005 1006 1007 <div class="lp-input-group"> 1008 <label for="prod-name" class="lp-label">Name</label> 1009 <input id="prod-name" name="name" value="" required="" class="lp-input lp-input--light"> 1010 </div> 1011 <div class="lp-input-group"> 1012 <label for="prod-email" class="lp-label">Email</label> 1013 <input id="prod-email" type="email" name="email" value="" required="" class="lp-input lp-input--light"> 1014 </div> 1015 <div class="lp-input-group"> 1016 <label for="prod-phone" class="lp-label">Phone</label> 1017 <input id="prod-phone" type="tel" name="phoneNumber" value="" required="" class="lp-input lp-input--light"> 1018 </div> 1019 <div class="lp-input-group m16"> 1020 <label for="prod-message" class="lp-label">Message</label> 1021 <textarea id="prod-message" name="message" value="" required="" class="lp-input"></textarea> 1022 </div> 1023 1024 <div class="lp-disclaimer"> <label style='display: none;' for='-termsAccepted'>Opt In/Disclaimer Consent:</label> 1025 <label class='lp-tcr-content'> 1026 <span class='lp-tcr-checkbox'> 1027 <input 1028 type='checkbox' 1029 id='-termsAccepted' 1030 name='termsAccepted' 1031 oninvalid="this.setCustomValidity('Please accept the terms and conditions')" 1032 oninput="this.setCustomValidity('')" 1033 required 1034 /></span> 1035 <span class='lp-tcr-message'> 1036 1037 I agree to be contacted by 1038 Marco island life and Heuermann-Skirkanich Team 1039 via call, email, and text for real estate services. To opt out, you can reply 'stop' at any time or reply 'help' for assistance. 1040 You can also click the unsubscribe link in the emails. Message and data rates may apply. Message frequency may vary. 1041 <a href='/terms-and-conditions' target='_blank'>Privacy Policy</a>. 1042 </span> 1043 </label> 1044 1045 </div> 1046 1047 <input style="display: none;" type="text" name="source" value="CONTACT_INQUIRY" /> 1048 1049 1050 <button type="submit" class="submitButton lp-btn button-style-2"> 1051 <span class="label-initial">Submit</span> 1052 <span class="label-loading">Submitting</span> 1053 <span class="label-success">Submitted</span> 1054 <span class="submit-icon lp-i lp-i--circle-notch lp-i--spin"></span> 1055 </button> 1056 <p class="success-message success hide"> 1057 Message sent successfully! 1058 </p> 1059 </form> 1060 1061 <a href="https://marcoislandlife.net/thank-you" class="h-pot redirect-link" data-redirect=true>link</a> 1062 </div> 1063 </div> 1064 </div> 1065 1066 </div> 1067 <button class="close lp-close" type="button" aria-label="close modal">
1068 <span class="lp-close-icon" aria-hidden="true"></span> 1069 </button> 1070 </div> 1071 <div id="qualifying-questions-modal" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="qualifying-questions-modal-title" aria-hidden="true" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 1050; display: none; align-items: center; justify-content: center;"> 1072 <style> 1073 #qualifying-questions-modal .custom-select-toggle { 1074 border: 1px solid #848484; 1075 border-radius: 8px; 1076 padding: 12px 16px; 1077 } 1078 1079 #qualifying-questions-modal .custom-select-toggle.is-placeholder { 1080 color: #848484; 1081 } 1082 1083 #qualifying-questions-modal #qualifying-questions-modal-phoneNumber::placeholder { 1084 color: #848484; 1085 opacity: 1; 1086 } 1087 1088 #qualifying-questions-modal .disclaimer-more { 1089 display: none; 1090 } 1091 1092 #qualifying-questions-modal #qualifying-questions-modal-disclaimer-text:not(.collapsed) .disclaimer-more { 1093 display: inline; 1094 } 1095 1096 #qualifying-questions-modal #qualifying-questions-modal-disclaimer-text:not(.collapsed) .disclaimer-ellipsis { 1097 display: none; 1098 } 1099 </style>
vendor: 119 bytes, lines 1099-1100
1099 1100 <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
1100<script> 1101 function toggleDisclaimerQualifyingQuestionsModal() { 1102 const disclaimerText = document.getElementById('qualifying-questions-modal-disclaimer-text'); 1103 const toggleButton = document.getElementById('qualifying-questions-modal-toggle-disclaimer'); 1104 1105 if (disclaimerText.classList.contains('collapsed')) { 1106 disclaimerText.classList.remove('collapsed'); 1107 toggleButton.textContent = 'Read less'; 1108 toggleButton.setAttribute('aria-expanded', 'true'); 1109 } else { 1110 disclaimerText.classList.add('collapsed'); 1111 toggleButton.textContent = 'Read more'; 1112 toggleButton.setAttribute('aria-expanded', 'false'); 1113 } 1114 } 1115 </script>
1115 1116 <div style="max-width: 400px; width: 95%; margin: 0 auto;"> 1117 <div style="background: #fff; border: none; border-radius: 16px; color: black; box-shadow: none; position: relative;"> 1118 <button type="button" data-dismiss="modal" aria-label="Close" style="position: absolute; right: 20px; top: 10px; font-size: 28px; font-weight: 300; color: black; opacity: 1; background: none; border: none; padding: 0; width: auto; height: auto; cursor: pointer; z-index: 10;"> 1119 <span aria-hidden="true">×</span> 1120 </button> 1121 <div style="padding: 40px 30px 32px;"> 1122 <div style="text-align: left; margin-bottom: 32px;"> 1123 <h2 id="qualifying-questions-modal-title" style="margin: 0; color: #333; font-size: 18px; line-height: 1.4; text-transform: uppercase; letter-spacing: 0.5px; font-weight: normal;"> 1124 Thanks, please provide more information to help serve you 1125 </h2> 1126 </div> 1127 <form id="qualifying-questions-modal-form" data-type="contact-form"> 1128 <input type="hidden" name="source" value="PROFILE_UPDATE" /> 1129 <input type="hidden" name="email" value="" id="qualifying-questions-modal-email" /> 1130 <input type="hidden" name="triggerSource" id="qualifying-questions-modal-triggerSource" value="" /> 1131 <label for="qualifying-questions-modal-email" style="display:none;"> 1132 Email 1133 </label> 1134 <label for="qualifying-questions-modal-triggerSource" style="display:none;"> 1135 Trigger Source 1136 </label> 1137 1138 <div style="margin-bottom: 20px;"> 1139 <label for="qualifying-questions-modal-phoneNumber" style="display:none;"> 1140 Phone Number 1141 </label> 1142 <input 1143 type="tel" 1144 id="qualifying-questions-modal-phoneNumber" 1145 name="phoneNumber" 1146 style="padding: 12px 16px; font-size: 16px; border: 1px solid #848484; border-radius: 8px; background: transparent; color: black; width: 100%; box-sizing: border-box; outline: none;" 1147 pattern="^\+?1?[-.\s]?\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}$" 1148 required 1149 placeholder="Phone" 1150 aria-label="Phone Number" 1151 inputmode="tel" 1152 autocomplete="tel" 1153 onfocus="this.style.borderColor='black';" 1154 onblur="this.style.borderColor='#848484';" 1155 /> 1156 </div> 1157 1158 <div style="margin-bottom: 20px;"> 1159 <label for="qualifying-questions-modal-interest" style="display:none;"> 1160 Interest 1161 </label> 1162 <select 1163 id="qualifying-questions-modal-interest" 1164 name="interest" 1165 required 1166 data-label="Interest" 1167 aria-label="Interest" 1168 style="padding: 12px 16px; font-size: 16px; border: 1px solid #848484; border-radius: 8px; background: #fff; color: #848484; width: 100%; box-sizing: border-box; outline: none; appearance: none; -webkit-appearance: none; -moz-appearance: none; background-image: url('data:image/svg+xml;charset=utf8,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 16 16%22%3E%3Cpath fill=%22%23666%22 d=%22M4.427 7.427l3.396 3.396a.25.25 0 00.354 0l3.396-3.396A.25.25 0 0011.396 7H4.604a.25.25 0 00-.177.427z%22/%3E%3C/svg%3E'); background-repeat: no-repeat; background-position: right 16px center; background-size: 16px;" 1169 onfocus="this.style.borderColor='black'; this.style.color='black';" 1170 onblur="this.style.borderColor='#848484'; if(this.value === '') this.style.color='#848484'; else this.style.color='black';" 1171 > 1172 <option value="" style="background: #fff; color: #848484;" disabled selected>Interested in...</option> 1173 <option value="Selling & Buying" style="background: #fff; color: black;">Selling & Buying</option> 1174 <option value="Selling" style="background: #fff; color: black;">Selling</option> 1175 <option value="Buying" style="background: #fff; color: black;">Buying</option> 1176 <option value="Renting" style="background: #fff; color: black;">Renting</option> 1177 <option value="Other" style="background: #fff; color: black;">Other</option> 1178 </select> 1179 </div> 1180 1181 <div style="margin-bottom: 32px; font-size: 12px; line-height: 1.2;"> 1182 <label style='display: none;' for='qualifying-questions-modal-qualifying-questions-termsAccepted'>Opt In/Disclaimer Consent:</label> 1183 <label class='lp-tcr-content'>
1184 <span class='lp-tcr-checkbox'> 1185 <input 1186 type='checkbox' 1187 id='qualifying-questions-modal-qualifying-questions-termsAccepted' 1188 name='termsAccepted' 1189 aria-describedby='qualifying-questions-modal-disclaimer-text' 1190 oninvalid="this.setCustomValidity('Please accept the terms and conditions')" 1191 oninput="this.setCustomValidity('')" 1192 required 1193 /></span> 1194 <span class='lp-tcr-message'> 1195 <div id="qualifying-questions-modal-disclaimer-text" class="collapsed" style="color: #848484;"> 1196 1197 I agree to be contacted by 1198 <strong>Marco island life and Heuermann-Skirkanich Team</strong> 1199 via call, email, and text <span class="disclaimer-more">for real estate services. 1200 To opt out, you can reply 'stop' at any time or reply 'help' for assistance. 1201 You can also click the unsubscribe link in the emails. 1202 Message and data rates may apply. Message frequency may vary.</span> 1203 <span class="disclaimer-ellipsis">...</span> 1204 <a href='/terms-and-conditions' target='_blank' rel='noopener noreferrer' style='text-decoration: underline;'>Privacy Policy</a>. 1205 </div> 1206 <button 1207 id="qualifying-questions-modal-toggle-disclaimer" 1208 type="button" 1209 style="background: none; border: none; color: #848484; font-size: inherit; font-weight: bold; padding: 0; margin-top: 4px; cursor: pointer;" 1210 aria-expanded="false" 1211 onclick="toggleDisclaimerQualifyingQuestionsModal()" 1212 > 1213 Read more 1214 </button> 1215 </span> 1216 </label> 1217 </div> 1218 1219 <div> 1220 <button 1221 type="submit" 1222 style="padding: 12px 24px; font-size: 16px; font-weight: normal; border-radius: 8px; border: 1px solid black; background: black; color: white; width: 100%; cursor: pointer; transition: all 0.2s ease; text-transform: uppercase; letter-spacing: 0.5px;" 1223 onmouseover="this.style.background='transparent'; this.style.color='black';" 1224 onmouseout="this.style.background='black'; this.style.color='white';" 1225 > 1226 Submit 1227 </button> 1228 </div> 1229 </form> 1230 </div> 1231 </div> 1232 </div> 1233 </div> 1234 1235
1235<script> 1236 (function() { 1237 var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy")); 1238 1239 if ("IntersectionObserver" in window && lazyVideos.length > 0) { 1240 var lazyVideoObserver = new IntersectionObserver(function(entries, observer) { 1241 entries.forEach(function(video) { 1242 if (video.isIntersecting) { 1243 for (var source in video.target.children) { 1244 var videoSource = video.target.children[source]; 1245 if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") { 1246 videoSource.src = videoSource.dataset.src; 1247 } 1248 } 1249 1250 video.target.load(); 1251 video.target.classList.remove("lazy"); 1252 lazyVideoObserver.unobserve(video.target); 1253 } 1254 }); 1255 }); 1256 1257 lazyVideos.forEach(function(lazyVideo) { 1258 lazyVideoObserver.observe(lazyVideo); 1259 }); 1260 } 1261 })(); 1262 </script>
1262 1263 1264 <!-- Global site tag (gtag.js) - Google Analytics --> 1265
1265<script defer src="https://www.googletagmanager.com/gtag/js"></script>
1265 1266 1267 <!-- Google Tag Manager --> 1268
1268<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 1269 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 1270 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.defer=true;j.async=false;j.src= 1271 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 1272 })(window,document,'script','dataLayer','GTM-NQNDW7N8');</script>
1272 1273 <!-- End Google Tag Manager --> 1274 <!-- Google Tag Manager --> 1275
1275<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 1276 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 1277 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.defer=true;j.async=false;j.src= 1278 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 1279 })(window,document,'script','dataLayer','GTM-T9SFQGHZ');</script>
1279 1280 <!-- End Google Tag Manager --> 1281 1282 1283 <!-- LP Tracker (divolte.js) - LP Divolte --> 1284
1284<script>window.divolteLp=window.divolteLp||function(){(divolteLp.q=divolteLp.q||[]).push(arguments)}</script>
1284 1285 <!-- LP Tracker (eventBus) - LP EventBus --> 1286
1286<script>window.eventBusLp=window.eventBusLp||function(){(eventBusLp.q=eventBusLp.q||[]).push(arguments)}</script>
1286 1287 1288
1288<script> 1289 window.dataLayer = window.dataLayer || []; 1290 document.sendGoogleTagManagerEvent = function() { 1291 /* Honor GPC-enabled browsers and prevent GTM event if GPC is enabled. More details: https://global-privacy-control.glitch.me/ */ 1292 if (window.navigator.globalPrivacyControl) { 1293 return; 1294 } 1295 1296 dataLayer.push(arguments); 1297 } 1298 1299 document.sendGoogleTagManagerEvent('js', new Date()); 1300 document.sendGoogleTagManagerEvent('config', 'G-BQJTBQ6NPN', { page: location.pathname, location: location.href }); 1301 document.sendGoogleAnalyticsEvent = function(googleEvent) { 1302 document.sendGoogleTagManagerEvent('event', googleEvent.eventAction || googleEvent.hitType, { 1303 event_category: googleEvent.eventCategory, 1304 event_label: googleEvent.eventLabel, 1305 value: googleEvent.eventValue, 1306 page: googleEvent.page, 1307 location: googleEvent.location 1308 }) 1309 }; 1310 1311 document.addEventListener("DOMContentLoaded", function() { 1312 (function() { 1313 //If the page has an element with ID of auto-year-update the element will be populated with the current year. 1314 var date = new Date(); 1315 var elements = document.getElementsByClassName('auto-year-update'); 1316 var i; 1317 for (i = 0; i < elements.length; i++) { 1318 elements[i].innerText = date.getFullYear(); 1319 } 1320 })(); 1321 if (window.divolteLp) { 1322 window.divolteLp('sendLpPageView', {}); 1323 } 1324 if (window.eventBusLp) { 1325 window.eventBusLp('sendLpPageView', {}); 1326 } 1327 }); 1328 </script>
1328 1329 1330 1331
1331<script> 1332 // Function to dynamically load a script 1333 function loadScript(url, callback) { 1334 var script = document.createElement('script'); 1335 script.type = 'text/javascript'; 1336 script.src = url; 1337 script.defer = true; 1338 script.async = true; 1339 script.onload = callback; 1340 document.head.appendChild(script); 1341 } 1342 1343 // Function to dynamically load CSS file 1344 function loadCSS(url) { 1345 var link = document.createElement("link"); 1346 link.rel = "stylesheet"; 1347 link.href = url; 1348 document.head.appendChild(link); 1349 } 1350 1351 // Global methods / variables that can be accessed by element js 1352 window.luxuryPresence = { 1353 libs: { 1354 loadJs: loadScript, 1355 loadCss: loadCSS, 1356 jsLibsMap: { 1357 paroller: { 1358 jsSrc: 'https://d1e1jt2fj4r8r.cloudfront.net/javascript/jquery.paroller.min.js', 1359 isLoaded: false, 1360 }, 1361 ionRangeSlider: { 1362 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js', 1363 cssSrc: 'https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css', 1364 isLoaded: false, 1365 requires: ['jquery'], 1366 }, 1367 splide: { 1368 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/splidejs/4.1.4/js/splide.min.js', 1369 cssSrc: 'https://cdnjs.cloudflare.com/ajax/libs/splidejs/4.1.4/css/splide-core.min.css', 1370 isLoaded: false, 1371 }, 1372 wow: { 1373 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js', 1374 isLoaded: false, 1375 }, 1376 jquery: { 1377 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js', 1378 isLoaded: false, 1379 }, 1380 slick: { 1381 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js', 1382 isLoaded: false, 1383 requires: ['jquery'], 1384 }, 1385 libphonenumber: { 1386 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/libphonenumber-js/1.11.8/libphonenumber-js.min.js', 1387 isLoaded: false, 1388 }, 1389 }, 1390 }, 1391 }; 1392 </script>
1392 1393
1393<script defer src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer" onload="window.luxuryPresence.libs.jsLibsMap.jquery.isLoaded = true"></script>
1393 1394
1394<script defer src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js"></script>
1394 1395
1395<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/handlebars-intl.min.js"></script>
1395 1396
1396<script defer src="https://cdnjs.cloudflare.com/ajax/libs/superagent/4.1.0/superagent.min.js"></script>
1396 1397
1397<script defer src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js" onload="window.luxuryPresence.libs.jsLibsMap.slick.isLoaded = true"></script>
1397 1398
1398<script defer src="https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js" onload="window.luxuryPresence.libs.jsLibsMap.wow.isLoaded = true"></script>
1398 1399
1399<script defer src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js" onload="window.luxuryPresence.libs.jsLibsMap.ionRangeSlider.isLoaded = true"></script>
1399 1400 1401 <!-- GOOGLE TRANSLATE SCRIPT --> 1402
1402<script> 1403 function googleTranslateElementInit() { 1404 // list of languages can be overridden by setting window.customLanguages in the head JS. example `window.customLanguages = 'en,de,fr,ro,sk,pl'` 1405 // Language codes can be taken from here https://cloud.google.com/translate/docs/languages 1406 const DEFAULT_LANGUAGES = 'en,es,zh-CN,zh-TW,tl,vi,ar,ko,ru,de,fr,hi,pt'; 1407 document.querySelectorAll('[data-type="TRANSLATE"]').forEach(function(translate){ 1408 translate.innerText = ''; 1409 new google.translate.TranslateElement({ 1410 pageLanguage: 'en', 1411 layout: google.translate.TranslateElement.InlineLayout.SIMPLE, 1412 includedLanguages: window.customLanguages || DEFAULT_LANGUAGES, 1413 }, translate); 1414 }); 1415 } 1416 </script>
1416 1417
1417<script defer src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
1417 1418
1418<script defer src="https://accounts.google.com/gsi/intermediate"></script>
1418 1419 1420 <!-- GOOGLE TRANSLATE SCRIPT END--> 1421
1421<script> 1422 1423 // UI helpers 1424 (function () { 1425 1426 function getSideMenu () { 1427 return document.querySelector('body > div.sidemenu'); 1428 } 1429 1430 function sideMenuHide (instant) { 1431 var sideMenu = getSideMenu(); 1432 if (!sideMenu || !sideMenu.classList.contains('visible')) { 1433 return; 1434 } 1435 sideMenu.classList.remove('visible'); 1436 sideMenu.dispatchEvent(new CustomEvent('lpui-hide', { detail: { instant: !!instant } })); 1437 window.dispatchEvent(new CustomEvent('lpui-sidemenu-hide', { detail: {instant: !!instant} })); 1438 } 1439 1440 function sideMenuShow () { 1441 var sideMenu = getSideMenu(); 1442 if (!sideMenu || sideMenu.classList.contains('visible')) { 1443 return; 1444 } 1445 sideMenu.classList.add('visible'); 1446 sideMenu.dispatchEvent(new Event('lpui-show')); 1447 window.dispatchEvent(new Event('lpui-sidemenu-show')); 1448 } 1449 1450 function sideMenuToggle () { 1451 var sideMenu = getSideMenu(); 1452 if (!sideMenu) { 1453 return; 1454 } 1455 var isSideMenuVisible = sideMenu.classList.contains('visible'); 1456 if (isSideMenuVisible) { 1457 sideMenuHide(); 1458 } else { 1459 sideMenuShow(); 1460 } 1461 } 1462 1463 var scrollLockRequests = {}; 1464 window.__debug_scrollLockRequests = scrollLockRequests; 1465 var hideScrollStyles = ''+ 1466 'body {'+ 1467 'overflow: hidden;' + 1468 '}'; 1469 var hideScrollId = 'hide-body-scroll-style'; 1470 1471 function scrollLock () { 1472 var style = document.createElement('style'); 1473 style.id = hideScrollId; 1474 style.textContent = hideScrollStyles; 1475 document.head.appendChild(style); 1476 window.dispatchEvent(new Event('lpui-scroll-locked')); 1477 } 1478 1479 function scrollUnlock () { 1480 document.getElementById(hideScrollId)?.remove(); 1481 window.dispatchEvent(new Event('lpui-scroll-unlocked')); 1482 } 1483 1484 function requestScrollLock (lockId) { 1485 var wasLocked = Object.keys(scrollLockRequests).length > 0; 1486 scrollLockRequests[lockId || '__anonymous_lock'] = true; 1487 if (!wasLocked) { 1488 scrollLock(); 1489 } 1490 } 1491 1492 function releaseScrollLock (lockId) { 1493 if (lockId) { 1494 delete scrollLockRequests[lockId]; 1495 if (!Object.keys(scrollLockRequests).length) { 1496 scrollUnlock(); 1497 } 1498 } else { 1499 scrollLockRequests = {}; 1500 window.__debug_scrollLockRequests = scrollLockRequests; 1501 scrollUnlock(); 1502 } 1503 } 1504 1505 function showModal (modalId, options) { 1506 var modal = document.getElementById(modalId); 1507 if (!modal) { 1508 return; 1509 } 1510 1511 if (!modal.classList.contains('visible')) { 1512 modal.classList.add('visible'); 1513 if (options && options.scrollLock) { 1514 window.lpUI.requestScrollLock(modalId); 1515 } 1516 modal.dispatchEvent(new Event('lpui-show')); 1517 window.dispatchEvent(new CustomEvent('lpui-modal-show', { detail: { id: modalId } })); 1518 } 1519 1520 const visibleModals = document.querySelectorAll('.modal.visible'); 1521 1522 if (visibleModals.length > 1) { 1523 1524 const maxZIndex = Array.from(visibleModals).reduce((maxZIndex, modal) => { 1525 const zIndex = window.getComputedStyle(modal).zIndex; 1526 const parsedZIndex = zIndex !== 'auto' ? parseInt(zIndex) : 0; 1527 return Math.max(maxZIndex, parsedZIndex); 1528 }, 0); 1529 1530 modal.style.zIndex = maxZIndex + 1; 1531 } 1532 1533 } 1534 1535 function _hideModal (modalEl) { 1536 if (!modalEl) { 1537 return; 1538 } 1539 if (!modalEl.classList.contains('visible')) { 1540 return; 1541 } 1542 modalEl.classList.remove('visible'); 1543 modalEl.style.zIndex = '';
1544 modalEl.dispatchEvent(new Event('lpui-hide')); 1545 var modalId = modalEl.getAttribute('id'); 1546 if (modalId) { 1547 window.lpUI.releaseScrollLock(modalId); 1548 window.dispatchEvent(new CustomEvent('lpui-modal-hide', { detail: { id: modalId } })); 1549 } 1550 } 1551 1552 function hideModal (modalId) { 1553 _hideModal(document.getElementById(modalId)); 1554 } 1555 1556 function hideClosestModal (el) { 1557 const modal = el?.closest('.modal'); 1558 if (!modal) { 1559 return; 1560 } 1561 if (modal.classList) { 1562 _hideModal(modal); 1563 return; 1564 } 1565 if (modal.length && modal[0].classList) { 1566 _hideModal(modal[0]); 1567 } 1568 } 1569 1570 window.lpUI = { 1571 sideMenuHide: sideMenuHide, 1572 sideMenuShow: sideMenuShow, 1573 sideMenuToggle: sideMenuToggle, 1574 requestScrollLock: requestScrollLock, 1575 releaseScrollLock: releaseScrollLock, 1576 showModal: showModal, 1577 hideModal: hideModal, 1578 hideClosestModal: hideClosestModal 1579 } 1580 })(); 1581 1582 var stringifyPrimitive = function(v) { 1583 switch (typeof v) { 1584 case 'string': 1585 return v; 1586 1587 case 'boolean': 1588 return v ? 'true' : 'false'; 1589 1590 case 'number': 1591 return isFinite(v) ? v : ''; 1592 1593 default: 1594 return ''; 1595 } 1596 }; 1597 1598 function objectToQuerystring(obj, sep, eq, name) { 1599 // https://github.com/Gozala/querystring/blob/master/encode.js 1600 sep = sep || '&'; 1601 eq = eq || '='; 1602 if (obj === null) { 1603 obj = undefined; 1604 } 1605 1606 if (typeof obj === 'object') { 1607 return Object.keys(obj).map(function(k) { 1608 var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; 1609 if (Array.isArray(obj[k])) { 1610 return obj[k].map(function(v) { 1611 return ks + encodeURIComponent(stringifyPrimitive(v)); 1612 }).join(sep); 1613 } else { 1614 return ks + encodeURIComponent(stringifyPrimitive(obj[k])); 1615 } 1616 }).filter(Boolean).join(sep); 1617 1618 } 1619 1620 if (!name) return ''; 1621 return encodeURIComponent(stringifyPrimitive(name)) + eq + 1622 encodeURIComponent(stringifyPrimitive(obj)); 1623 } 1624 1625 function getPath(url, options) { 1626 var parser = document.createElement('a'); 1627 parser.href = url || ''; 1628 var path = parser.pathname || ''; 1629 if (path[0] !== '/') { 1630 // IE does not return path starting with a slash 1631 path = '/' + path; 1632 } 1633 1634 if (options && options.queryString) { 1635 path += parser.search; 1636 } 1637 1638 return path; 1639 } 1640 1641 function getMLSAutocomplete(keyword) { 1642 var searchURL = window.location.protocol + '//' + window.location.hostname + '/home-search/auto_complete'; 1643 var query = { 1644 kind: 'listings', 1645 query: keyword 1646 }; 1647 1648 return superagent 1649 .get(searchURL) 1650 .query(query) 1651 .then(function(res) { 1652 var data = res.body || []; 1653 /* 1654 Of the format: 1655 [{ 1656 "_index": "listing_auto_completes_production_20190723232720775", 1657 "_type": "listing_auto_complete", 1658 "_id": "235875624", 1659 "_score": 0, 1660 "status_modified_at": 1553250708, 1661 "city": "Jupiter", 1662 "price": 1335743, 1663 "display_address": "10088 Calabrese Trail Unit: 9 Jupiter FL 33478", 1664 "sold_price": null, 1665 "id": 235875624, 1666 "state": "FL", 1667 "photo_urls": [ 1668 "http://cdn.photos.sparkplatform.com/fl/20190322153144208228000000-o.jpg" 1669 ], 1670 "status": "Pending" 1671 }, ...] 1672 */ 1673 1674 return data; 1675 }); 1676 } 1677 1678 function getMLSAutocompleteWithFilters(keyword, filters = {}) { 1679 var searchURL = window.location.protocol + '//' + window.location.hostname + '/home-search/auto_complete'; 1680 1681 return superagent 1682 .get(searchURL) 1683 .query({ kind: 'listings', query: keyword, ...filters }) 1684 .then(function(res) { 1685 /* 1686 Of the format: 1687 [{ 1688 "_index": "listing_auto_completes_production_20190723232720775", 1689 "_type": "listing_auto_complete", 1690 "_id": "235875624", 1691 "_score": 0, 1692 "status_modified_at": 1553250708, 1693 "city": "Jupiter", 1694 "price": 1335743, 1695 "display_address": "10088 Calabrese Trail Unit: 9 Jupiter FL 33478", 1696 "sold_price": null, 1697 "id": 235875624, 1698 "state": "FL", 1699 "photo_urls": [ 1700 "http://cdn.photos.sparkplatform.com/fl/20190322153144208228000000-o.jpg" 1701 ], 1702 "status": "Pending" 1703 }, ...] 1704 */ 1705 return res.body || []; 1706 }); 1707 } 1708 1709 function makeMlsLink(data) { 1710 // Code Dupe from utils/googlePlace 1711 // mapping of google data type to mls data type 1712 var mapping = { 1713 neighborhood: 'neighborhood', 1714 locality: 'place', 1715 administrative_area_level_2: 'county', 1716 administrative_area_level_1: 'state', 1717 postal_code: 'postalcode', 1718 }; 1719 1720 function _filterTypes(types) { 1721 return types.filter(function(type) { return type !== 'political' }); 1722 } 1723 1724 if (!data || !Object.keys(data).length) { 1725 return '/home-search/listings'; 1726 } 1727 1728 var newData = {};
1729 _filterTypes(data.types).forEach(function(type) { 1730 if (mapping[type]) { 1731 newData.search_type = mapping[type]; 1732 } 1733 }); 1734 newData.omnibox = data.formatted_address; 1735 data.address_components.forEach(function(component) { 1736 _filterTypes(component.types).forEach(function(type) { 1737 if (mapping[type]) { 1738 newData[mapping[type]] = component.long_name; 1739 } 1740 }); 1741 }); 1742 var bounds = data.geometry.bounds; 1743 var convertedData = Object.assign(bounds, newData); 1744 1745 return '/home-search/listings?' + objectToQuerystring(convertedData); 1746 } 1747 1748 function debounce(func, wait) { 1749 let timeout; 1750 return function(...args) { 1751 const context = this; 1752 clearTimeout(timeout); 1753 timeout = setTimeout(() => func.apply(context, args), wait) 1754 } 1755 } 1756 1757 // Global methods / variables that can be accessed by element js 1758 window.luxuryPresence = { 1759 ...window.luxuryPresence, 1760 defaults: { 1761 companyId: 'cccfad5c-784f-4d3e-8950-0449a0ebf171', 1762 apiGatewayUrl: '/api-gw', 1763 routerUrl: '/api-nv', 1764 gql: {"agents":"\n query Agents (\n $agentId: ID\n $agentIds: [ID!]\n $companyId: String\n $network: Boolean\n $networkId: String\n $officeId: [ID!]\n $excludeOfficeId: [ID!]\n $offset: Int\n $limit: Int\n $sort: String\n $sortDir: SortDirectionEnum\n $search: String\n $tags: [String]\n $tagsMode: TagsModeEnum\n $teamId: [ID!]\n $developmentId: [ID!]\n $prioritizeIds: Boolean\n ) {\n agents (\n agentId: $agentId\n agentIds: $agentIds\n companyId: $companyId\n network: $network\n networkId: $networkId\n officeId: $officeId\n excludeOfficeId: $excludeOfficeId\n offset: $offset\n limit: $limit\n sort: $sort\n sortDir: $sortDir\n search: $search\n tags: $tags\n tagsMode: $tagsMode\n teamId: $teamId\n developmentId: $developmentId\n prioritizeIds: $prioritizeIds\n ) {\n id\n firstName\n lastName\n avatar {\n smallUrl\n mediumUrl\n largeUrl\n height\n width\n }\n position\n bioLong\n bioShort\n seoTitle\n seoDescription\n slug\n phoneNumber\n phoneNumber2\n license\n email\n leadAgent\n greaterArea\n tags\n }\n agentsCount(\n agentIds: $agentIds\n companyId: $companyId\n network: $network\n networkId: $networkId\n officeId: $officeId\n excludeOfficeId: $excludeOfficeId\n search: $search\n tags: $tags\n tagsMode: $tagsMode\n teamId: $teamId\n developmentId: $developmentId\n prioritizeIds: $prioritizeIds\n ) {\n count\n }\n }\n","properties":"\n query Properties(\n $agentIds: [ID!]\n $teamIds: [ID!]\n $neighborhoodIds: [ID!]\n $officeIds: [ID!]\n $propertyId: ID\n $companyId: String\n $networkId: String\n $network: Boolean\n $statusId: String\n $propertyIds: [ID!]\n $prioritizeIds: Boolean\n $statusIds: [String!]\n $excludeStatusId: [String!]\n $neighborhoodId: String\n $addressState: [String!]\n $addressCity: [String!]\n $relatedNeighborhoodPropertyId: String\n $developmentId: String\n $featuredListing: Boolean\n $leaseProperty: Boolean\n $search: String\n $searchTermMode: SearchTermModeEnum\n $globalProperty: Boolean\n $archived: Boolean\n $salesPriceGTE: Float\n $salesPriceLTE: Float\n $leasePriceGTE: Float\n $leasePriceLTE: Float\n $livingSpaceSizeGTE: Float\n $livingSpaceSizeLTE: Float\n $bathCountGTE: Float\n $bathCountLTE: Float\n $bedroomCountGTE: Float\n $bedroomCountLTE: Float\n $architectureStyle: String\n $lifestyle: String\n $propertyTypeId: String\n $propertyTypeIds: [String!]\n $spaceTypeIds: [ID!]\n $tag: String\n $backfillMLSResults: Boolean\n $displayMLSListings: String\n $hostname: String\n $websiteId: ID\n $backfillProviders: [String!]\n $backfillMLSListingIds: [String!]\n $backfillMLSAgentIds: [String!]\n $backfillMLSOfficeIds: [String!]\n $backfillBoundary: JSON\n $openHouse: Boolean\n $withGeo: Boolean\n $advancedFilters: JSON\n $seasonalPriceId: ID\n $offset: Int\n $limit: Int\n $sort: String\n $sortDir: SortDirectionEnum\n ) {\n properties(\n \n agentIds: $agentIds\n teamIds: $teamIds\n propertyId: $propertyId\n propertyIds: $propertyIds\n prioritizeIds: $prioritizeIds\n companyId: $companyId\n network: $network\n networkId: $networkId\n statusId: $statusId\n statusIds: $statusIds\n excludeStatusId: $excludeStatusId\n neighborhoodId: $neighborhoodId\n neighborhoodIds: $neighborhoodIds\n officeIds: $officeIds\n addressState: $addressState\n addressCity: $addressCity\n developmentId: $developmentId\n featuredListing: $featuredListing\n leaseProperty: $leaseProperty\n search: $search\n searchTermMode: $searchTermMode\n salesPriceGTE: $salesPriceGTE\n salesPriceLTE: $salesPriceLTE\n leasePriceGTE: $leasePriceGTE\n leasePriceLTE: $leasePriceLTE\n livingSpaceSizeGTE: $livingSpaceSizeGTE\n livingSpaceSizeLTE: $livingSpaceSizeLTE\n bathCountGTE: $bathCountGTE\n bathCountLTE: $bathCountLTE\n bedroomCountGTE: $bedroomCountGTE\n bedroomCountLTE: $bedroomCountLTE\n architectureStyle: $architectureStyle\n lifestyle: $lifestyle\n propertyTypeId: $propertyTypeId\n propertyTypeIds: $propertyTypeIds\n spaceTypeIds: $spaceTypeIds\n tag: $tag\n archived: $archived\n globalProperty: $globalProperty\n withGeo: $withGeo\n openHouse: $openHouse\n displayMLSListings: $displayMLSListings\n advancedFilters: $advancedFilters\n seasonalPriceId: $seasonalPriceId\n\n relatedNeighborhoodPropertyId: $relatedNeighborhoodPropertyId\n backfillMLSResults: $backfillMLSResults\n hostname: $hostname\n websiteId: $websiteId\n backfillProviders: $backfillProviders\n backfillMLSListingIds: $backfillMLSListingIds\n backfillMLSAgentIds: $backfillMLSAgentIds\n backfillMLSOfficeIds: $backfillMLSOfficeIds\n backfillBoundary: $backfillBoundary\n offset: $offset\n limit: $limit\n sort: $sort,\n sortDir: $sortDir\n ){\n id\n name\n status\n originalStatus {\n id\n name\n }\n salesPrice\n reducedPrice\n isPasswordProtected\n bedroomCount\n bathCount\n fullBathCount\n halfBathCount\n threeQuarterBathCount\n fullAddress\n addressLine1\n addressLine2\n addressCity\n addressState\n addressCountry\n postalCode\n description\n syncedAt\n officeName\n attributionContact\n neighborhood {\n id\n }\n media {\n smallUrl\n mediumUrl\n largeUrl\n xLargeUrl\n xxLargeUrl\n height\n width\n }\n seoTitle\n seoDescription\n slug\n fromMLS\n mlsId\n mlsLogo\n mlsAttribution\n openHouse\n openHouseHours\n priceUponRequest\n privateAddress\n leaseProperty\n leasePrice\n currency\n leaseTermFrequencyInterval\n leaseTermFrequencyCount\n leasePeriod\n livingSpaceSize\n livingSpaceUnits\n lotAreaSize\n lotAreaUnits\n tags\n latitude\n longitude\n soldDate\n timeZone\n buyerAgencyCompensation\n buyerAgencyCompensationType\n landIdUrl\
1764n }\n propertiesCount(\n \n agentIds: $agentIds\n teamIds: $teamIds\n propertyId: $propertyId\n propertyIds: $propertyIds\n prioritizeIds: $prioritizeIds\n companyId: $companyId\n network: $network\n networkId: $networkId\n statusId: $statusId\n statusIds: $statusIds\n excludeStatusId: $excludeStatusId\n neighborhoodId: $neighborhoodId\n neighborhoodIds: $neighborhoodIds\n officeIds: $officeIds\n addressState: $addressState\n addressCity: $addressCity\n developmentId: $developmentId\n featuredListing: $featuredListing\n leaseProperty: $leaseProperty\n search: $search\n searchTermMode: $searchTermMode\n salesPriceGTE: $salesPriceGTE\n salesPriceLTE: $salesPriceLTE\n leasePriceGTE: $leasePriceGTE\n leasePriceLTE: $leasePriceLTE\n livingSpaceSizeGTE: $livingSpaceSizeGTE\n livingSpaceSizeLTE: $livingSpaceSizeLTE\n bathCountGTE: $bathCountGTE\n bathCountLTE: $bathCountLTE\n bedroomCountGTE: $bedroomCountGTE\n bedroomCountLTE: $bedroomCountLTE\n architectureStyle: $architectureStyle\n lifestyle: $lifestyle\n propertyTypeId: $propertyTypeId\n propertyTypeIds: $propertyTypeIds\n spaceTypeIds: $spaceTypeIds\n tag: $tag\n archived: $archived\n globalProperty: $globalProperty\n withGeo: $withGeo\n openHouse: $openHouse\n displayMLSListings: $displayMLSListings\n advancedFilters: $advancedFilters\n seasonalPriceId: $seasonalPriceId\n\n ) {\n count\n }\n }\n","pressReleases":"\n query PressReleases (\n $pressReleaseId: ID\n $companyId: String\n $offset: Int\n $limit: Int\n $sort: String\n $sortDir: SortDirectionEnum\n $search: String\n $categories: [String!]\n $propertyId: [String!]\n $developmentId: [String!]\n $agentId: [String!]\n $teamId: [String!]\n $year: [Int!]\n ) {\n pressReleases (\n pressReleaseId: $pressReleaseId\n companyId: $companyId\n offset: $offset\n limit: $limit\n sort: $sort\n sortDir: $sortDir\n search: $search\n categories: $categories\n propertyId: $propertyId\n developmentId: $developmentId\n agentId: $agentId\n teamId: $teamId\n year: $year\n ) {\n id\n title\n description\n author\n externalUrl\n media {\n smallUrl\n mediumUrl\n largeUrl\n xLargeUrl\n xxLargeUrl\n height\n width\n }\n publishedAt\n categories\n }\n pressReleasesCount(\n companyId: $companyId\n search: $search\n categories: $categories\n propertyId: $propertyId\n developmentId: $developmentId\n agentId: $agentId\n teamId: $teamId\n year: $year\n ) {\n count\n }\n }\n","posts":"\n query Posts (\n $postId: ID\n $companyId: String\n $offset: Int\n $limit: Int\n $order: String\n $sortDir: SortDirectionEnum\n $search: String\n $featured: Boolean\n $categoryId: String\n $categoryIds: [String!]\n $neighborhoodId: [String!]\n ) {\n posts (\n postId: $postId\n companyId: $companyId\n offset: $offset\n limit: $limit\n order: $order\n sortDir: $sortDir\n search: $search\n featured: $featured\n postStatusId: \"5f528253-abb7-484e-95c3-330269ac1102\"\n categoryId: $categoryId\n categoryIds: $categoryIds\n neighborhoodId: $neighborhoodId\n ) {\n id\n title\n subtitle\n description\n status\n featured\n slug\n categories {\n id\n name\n }\n createdAt\n publishedAt\n scheduledAt\n createdBy {\n firstName\n lastName\n }\n customAuthor\n media {\n smallUrl\n mediumUrl\n largeUrl\n xLargeUrl\n xxLargeUrl\n height\n width\n }\n seoTitle\n seoDescription\n slug\n }\n postsCount(\n companyId: $companyId\n search: $search\n featured: $featured\n postStatusId: \"5f528253-
1764abb7-484e-95c3-330269ac1102\"\n categoryId: $categoryId\n categoryIds: $categoryIds\n neighborhoodId: $neighborhoodId\n ) {\n count\n }\n }\n","testimonials":"\n query Testimonials(\n $testimonialId: ID\n $agentId: ID\n $teamId: ID\n $companyId: String\n $offset: Int\n $limit: Int\n $sort: String\n $sortDir: SortDirectionEnum\n $search: String\n ) {\n testimonials(\n testimonialId: $testimonialId\n agentId: $agentId\n teamId: $teamId\n companyId: $companyId\n offset: $offset\n limit: $limit\n sort: $sort\n sortDir: $sortDir\n search: $search\n ){\n id\n body\n author\n position\n media {\n smallUrl\n mediumUrl\n largeUrl\n xLargeUrl\n xxLargeUrl\n height\n width\n }\n seoTitle\n seoDescription\n agents {\n slug\n email\n firstName\n lastName\n avatar {\n smallUrl\n height\n width\n }\n }\n }\n testimonialsCount(\n companyId: $companyId\n agentId: $agentId\n teamId: $teamId\n search: $search\n ) {\n count\n }\n }\n","neighborhoods":"\n query Neighborhoods (\n $neighborhoodId: ID\n $companyId: String\n $search: String\n $tag: String\n $offset: Int\n $limit: Int\n $sort: String\n $sortDir: SortDirectionEnum\n ) {\n neighborhoods (\n neighborhoodId: $neighborhoodId\n companyId: $companyId\n search: $search\n tag: $tag\n offset: $offset\n limit: $limit\n sort: $sort\n sortDir: $sortDir\n ) {\n id\n name\n description\n descriptionShort\n slug\n tags\n googlePlaceData\n mlsLink\n createdAt\n media {\n smallUrl\n mediumUrl\n largeUrl\n xLargeUrl\n xxLargeUrl\n height\n width\n }\n seoTitle\n seoDescription\n }\n neighborhoodsCount(\n companyId: $companyId\n search: $search\n tag: $tag\n ) {\n count\n }\n }\n","developments":"\n query Developments (\n $developmentId: ID\n $companyId: String\n $offset: Int\n $limit: Int\n $sort: String\n $sortDir: SortDirectionEnum\n $search: String\n $tag: [String!]\n $agentId: [ID!]\n $neighborhoodId: ID\n $neighborhoodIds: [ID!]\n ) {\n developments (\n developmentId: $developmentId\n companyId: $companyId\n offset: $offset\n limit: $limit\n sort: $sort\n sortDir: $sortDir\n search: $search\n tag: $tag\n agentId: $agentId\n neighborhoodId: $neighborhoodId\n neighborhoodIds: $neighborhoodIds\n ) {\n id\n name\n description\n descriptionShort\n slug\n createdAt\n media {\n smallUrl\n mediumUrl\n largeUrl\n xLargeUrl\n xxLargeUrl\n height\n width\n }\n googlePlaceData\n seoTitle\n seoDescription\n tags\n }\n developmentsCount(\n companyId: $companyId\n search: $search\n tag: $tag\n agentId: $agentId\n neighborhoodId: $neighborhoodId\n neighborhoodIds: $neighborhoodIds\n ) {\n count\n }\n }\n","pois":"\nquery PointsOfInterest(\n $regionId: String!,\n $radius: Int,\n $offset: Int,\n $limit: Int,\n $categories: [PoiCategoryEnum!],\n $sortBy: PoiSortByEnum\n) {\n pois(\n regionId: $regi
1764onId,\n radius: $radius,\n offset: $offset,\n limit: $limit,\n categories: $categories,\n sortBy: $sortBy\n ) {\n name\n imageUrl\n url\n reviewCount\n rating\n price\n displayPhone\n distance\n category\n location {\n address1\n address2\n address3\n city\n zipCode\n country\n state\n }\n }\n }\n","offices":"\n query Offices (\n $officeId: ID\n $officeIds: [ID!]\n $companyId: String\n $slug: String\n $sort: String\n $sortDir: SortDirectionEnum\n $search: String\n $tags: [String]\n $offset: Int\n $limit: Int\n ) {\n offices (\n officeId: $officeId\n officeIds: $officeIds\n companyId: $companyId\n slug: $slug\n sort: $sort\n sortDir: $sortDir\n search: $search\n tags: $tags\n offset: $offset\n limit: $limit\n ) {\n id\n companyId\n name\n slug\n officeMlsId\n shortDescription\n fullDescription\n addressLine1\n addressLine2\n addressCity\n addressState\n addressPostalCode\n addressCountry\n phone\n email\n officeHours\n coordinates\n googlePlaceData \n seoTitle\n seoDescription\n fullAddress\n media {\n id\n originalUrl\n thumbnailUrl\n smallUrl\n mediumUrl\n largeUrl\n xLargeUrl\n xxLargeUrl\n }\n }\n officesCount(\n companyId: $companyId\n officeId: $officeId\n officeIds: $officeIds\n slug: $slug\n search: $search\n tags: $tags\n ) {\n count\n }\n }\n","teams":"query TeamsAndCount(\n $offset: Int\n $limit: Int\n $search: String\n $sort: String\n $sortDir: SortDirectionEnum\n $companyId: ID\n) {\n teams(\n offset: $offset\n limit: $limit\n sort: $sort\n sortDir: $sortDir\n search: $search\n companyId: $companyId\n ) {\n \n id\n companyId\n name\n email\n shortBio\n fullBio\n addressLine1\n addressLine2\n addressCity\n addressState\n addressCountry\n phoneNumber1\n phoneNumber2\n postalCode\n avatar {\n id\n thumbnailUrl\n smallUrl\n mediumUrl\n largeUrl\n }\n urlWebsite\n socialLinks\n socialLinksArray\n tags\n seoTitle\n seoDesc\n slug\n displayOrder\n\n }\n teamsCount(\n search: $search\n companyId: $companyId\n ) {\n count\n }\n}"}, 1765 propertyPlaceholderImage: {"id":"9e4c6a9f-9f5d-4e91-910f-3696e2bba210","alt":null,"bytes":43559,"width":1920,"format":"jpeg","height":1200,"pngUrl":"","shared":true,"curated":false,"duration":null,"largeUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/dbe23f28-e629-47f8-aa2b-1b6161195c37","smallUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=960/https://media-production.lp-cdn.com/media/dbe23f28-e629-47f8-aa2b-1b6161195c37","authorUrl":null,"createdAt":"2025-07-21T02:09:44.562Z","mediumUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=1280/https://media-production.lp-cdn.com/media/dbe23f28-e629-47f8-aa2b-1b6161195c37","sourceUrl":null,"updatedAt":"2025-07-21T02:09:44.562Z","xLargeUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/dbe23f28-e629-47f8-aa2b-1b6161195c37","__typename":"Media","altTagText":null,"authorName":null,"sourceName":"r2","xxLargeUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/dbe23f28-e629-47f8-aa2b-1b6161195c37","description":null,"displayName":"property-placeholder","originalUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/dbe23f28-e629-47f8-aa2b-1b6161195c37","resourceType":"image","thumbnailUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85,fit=scale-down,width=320/https://media-production.lp-cdn.com/media/dbe23f28-e629-47f8-aa2b-1b6161195c37","originalFileName":"Property Placeholder","cloudinaryPublicId":"dbe23f28-e629-47f8-aa2b-1b6161195c37"} 1766 }, 1767 objectToQuerystring: objectToQuerystring, 1768 getPath: getPath, 1769 getMLSAutocomplete: getMLSAutocomplete, 1770 getMLSAutocompleteWithFilters: getMLSAutocompleteWithFilters, 1771 makeMlsLink: makeMlsLink, 1772 debounce: debounce, 1773 }; 1774 1775 var wowOffset = 100; 1776 </script>
1776 1777
1777<script> 1778 (() => { 1779 1780function $parcel$interopDefault(a) { 1781 return a && a.__esModule ? a.default : a; 1782} 1783// Entry point for lp-sdk bundle 1784// This file exists to ensure Parcel v2 outputs the correct filename 1785/* global window */ var $53de3c160faf5a81$exports = {}; 1786/* 1787WARNING!!! This file is used both on the server and in client's web-browser 1788please don't require/import any server-side related config/functions here 1789If we need something, let's pass it as a parameter of the factory 1790*/ var $0ce6edea77f7b81a$exports = {}; 1791$0ce6edea77f7b81a$exports = { 1792 getVideoFirstFrame (videoUrl) { 1793 // The default Cloudinary asset delivery URL has the following structure: https://res.cloudinary.com/<cloud_name>/<asset_type>/<delivery_type>/<transformations>/<version>/<public_id>.<extension> 1794 // https://cloudinary.com/documentation/video_manipulation_and_delivery#transformation_url_structure 1795 // The problem is that <transformations> and <version> are optional, and <transformations> can be chained separated by '/' 1796 // One more issue to be handled https://cloudinary.com/documentation/advanced_url_delivery_options#seo_friendly_media_asset_urls 1797 const CLOUDINARY_URL = 'https://res.cloudinary.com/'; 1798 const invalid = !videoUrl || !videoUrl.startsWith(CLOUDINARY_URL); 1799 if (invalid) return null; 1800 const urlComponents = videoUrl.replace(CLOUDINARY_URL, '').replace('f_auto:video', 'f_auto').split('/'); 1801 // checking if <asset_type> is not video or videos 1802 if (urlComponents[1].toLowerCase().indexOf('video') === -1) return null; 1803 // Filename is last urlComponent <public_id>.<extension> 1804 let filename = urlComponents[urlComponents.length - 1]; 1805 if (filename.lastIndexOf('.') > -1) filename = `${filename.slice(0, filename.lastIndexOf('.'))}.jpg`; 1806 else filename += '.jpg'; 1807 urlComponents[urlComponents.length - 1] = filename; 1808 // We need to add so_0,eo_0 transformation to the url to target the first frame. 1809 // we want to find the position at which we want to insert it as a chained transformation 1810 const firstFrameTransformation = 'so_0,eo_0'; 1811 let firstFrameTransformationPosition = 3; 1812 // checking cases for SEO-friendly URLs 1813 if (urlComponents[1].toLowerCase() === 'videos' && urlComponents[2] !== '') firstFrameTransformationPosition = 2; 1814 // checking the last transformation position in the url 1815 // https://cloudinary.com/documentation/transformation_reference 1816 // https://regex101.com/r/lE3W6u/1 1817 const transformationRegex = /^(?:[a-z]{1,3}|\$\w+)_\S+$/; 1818 while(firstFrameTransformationPosition < urlComponents.length - 1 && transformationRegex.test(urlComponents[firstFrameTransformationPosition]))firstFrameTransformationPosition++; 1819 urlComponents.splice(firstFrameTransformationPosition, 0, firstFrameTransformation); 1820 return CLOUDINARY_URL + urlComponents.join('/'); 1821 } 1822}; 1823 1824 1825/** 1826 * Create helpers with given Handlebars instance 1827 * 1828 * @param {Object} HandlebarsInstance 1829 * @param {Function} isEqual - we use different implementation if isEqual on server and on client 1830 * @return {Object} 1831 */ function $53de3c160faf5a81$var$handlebarsHelpersFactory(HandlebarsInstance, { isEqual: isEqual }) { 1832 // notice!: code below assumes list is ordered lowest to highest width 1833 const MEDIA_SIZES = [ 1834 { 1835 field: 'thumbnailUrl', 1836 w: 320 1837 }, 1838 { 1839 field: 'smallUrl', 1840 w: 960 1841 }, 1842 { 1843 field: 'mediumUrl', 1844 w: 1280 1845 }, 1846 { 1847 field: 'largeUrl', 1848 w: 1920 1849 }, 1850 { 1851 field: 'xLargeUrl', 1852 w: 2560 1853 }, 1854 { 1855 field: 'xxLargeUrl', 1856 w: 3456 1857 } 1858 ]; 1859 const MEDIA_SIZE_FOR_SRC = 1280; 1860 const lpFormatNumber = function(number, unit, precision) { 1861 const localization = 'en-US'; 1862 if (!number) return ''; 1863 if (typeof number === 'string') { 1864 const trimmed = number.trim(); 1865 if (/[^+\-0-9.]/.test(trimmed)) return number; // returning text 'as is' assuming it already has all formatting 1866 // eslint-disable-next-line 1867 number = parseFloat(trimmed); 1868 if (!number) return ''; 1869 } 1870 const currencyPrecision = typeof precision === 'number' ? precision : 0; 1871 const currencyFractionDigits = Number.isInteger(number) ? 0 : currencyPrecision; 1872 const currencyFractionOptions = { 1873 minimumFractionDigits: currencyFractionDigits, 1874 maximumFractionDigits: currencyFractionDigits 1875 };
1876 if (unit === 'USD') return `$${number.toLocaleString(localization, currencyFractionOptions)}`; 1877 if (unit === 'CAD') return `$${number.toLocaleString(localization, currencyFractionOptions)} CAD`; 1878 if (unit === 'EUR') return `\u{20AC}${number.toLocaleString(localization, currencyFractionOptions)}`; 1879 if (unit === 'GBP') return `\xa3${number.toLocaleString(localization, currencyFractionOptions)}`; 1880 if (unit === 'PERCENT') return `${number}%`; 1881 if (typeof precision === 'number' && precision > -1) return number.toLocaleString(localization, { 1882 maximumFractionDigits: precision 1883 }); 1884 return number.toLocaleString(localization); 1885 }; 1886 const formatFrequency = function(freqUnit) { 1887 switch(freqUnit){ 1888 case 'DAY': 1889 return 'daily'; 1890 case 'MONTH': 1891 return 'monthly'; 1892 case 'WEEK': 1893 return 'weekly'; 1894 case 'YEAR': 1895 return 'yearly'; 1896 case 'QUARTER': 1897 return 'quarterly'; 1898 case 'HALF_YEAR': 1899 return 'semi-annually'; 1900 case 'NIGHTLY': 1901 return 'nightly'; 1902 case 'SEASONAL': 1903 return 'seasonally'; 1904 default: 1905 return ''; 1906 } 1907 }; 1908 const formatFrequencyShort = function(freqUnit) { 1909 switch(freqUnit){ 1910 case 'DAY': 1911 return 'day'; 1912 case 'WEEK': 1913 return 'wk'; 1914 case 'MONTH': 1915 return 'mo'; 1916 case 'YEAR': 1917 return 'yr'; 1918 case 'QUARTER': 1919 return '3 mos'; 1920 case 'HALF_YEAR': 1921 return '6 mos'; 1922 case 'NIGHTLY': 1923 return 'night'; 1924 case 'SEASONAL': 1925 return 'season'; 1926 default: 1927 return ''; 1928 } 1929 }; 1930 const formatFrequencyStd = function(freqUnit) { 1931 switch(freqUnit){ 1932 case 'DAY': 1933 return 'day'; 1934 case 'WEEK': 1935 return 'week'; 1936 case 'MONTH': 1937 return 'month'; 1938 case 'YEAR': 1939 return 'year'; 1940 case 'QUARTER': 1941 return 'quarter'; 1942 case 'HALF_YEAR': 1943 return '6 months'; 1944 case 'NIGHTLY': 1945 return 'night'; 1946 case 'SEASONAL': 1947 return 'season'; 1948 default: 1949 return ''; 1950 } 1951 }; 1952 const formatFrequencyExt = function(unit, options) { 1953 let val; 1954 let separator; 1955 const opts = options || {}; 1956 switch(opts.mode){ 1957 case 'short': 1958 val = formatFrequencyShort(unit); 1959 separator = opts.frequencySeparator || '/'; 1960 break; 1961 case 'standard': 1962 case 'std': 1963 val = formatFrequencyStd(unit); 1964 separator = opts.frequencySeparator || '/'; 1965 break; 1966 case 'long': 1967 default: 1968 val = formatFrequency(unit); 1969 separator = opts.frequencySeparator || ' '; 1970 } 1971 if (!val) return ''; 1972 if (!opts.frequencyTag && !opts.frequencyClass) return separator + val; 1973 return `${separator}<${opts.frequencyTag || 'span'}${opts.frequencyClass ? ` class="${opts.frequencyClass}"` : ''}>${val}</${opts.frequencyTag || 'span'}>`; 1974 }; 1975 return { 1976 isEmpty (arg1, options) { 1977 const result = !arg1 || (typeof arg1 === 'string' ? !arg1.trim() : false) || !Object.keys(arg1).length; 1978 if (options.fn) return result ? options.fn(this) : options.inverse(this); 1979 return result; 1980 }, 1981 ifEquals (arg1, arg2, options) { 1982 return isEqual(arg1, arg2) ? options.fn(this) : options.inverse(this); 1983 }, 1984 'raw-helper': function(options) { 1985 return options.fn(); 1986 }, 1987 striptags (txt) { 1988 if (!txt) return ''; 1989 // Remove HTML Comments (escaping something to not make real html comment by expression) 1990 // eslint-disable-next-line no-useless-escape,no-param-reassign 1991 txt = txt.replace(/<\!--(.|[\r\n])*?-\->/g, ''); 1992 // Remove XML fragments and <style> and <svg> tags with content 1993 // eslint-disable-next-line 1994 txt = txt.replace(/<(xml|style|svg)("[^"]*"|'[^']*'|[^>])*>(.|[\r\n])*?<\/\1>/gi, ''); 1995 // Replace with space 1996 // eslint-disable-next-line no-param-reassign 1997 txt = txt.replace(/ /g, ' '); 1998 // Remove HTML Tags 1999 const regexp = /<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g; 2000 return txt.replace(regexp, ''); 2001 },
2002 striptagsLineBreaks (txt) { 2003 if (!txt) return ''; 2004 // Remove HTML Comments (escaping something to not make real html comment by expression) 2005 // eslint-disable-next-line no-useless-escape,no-param-reassign 2006 txt = txt.replace(/<\!--(.|[\r\n])*?-\->/g, ''); 2007 // Remove XML fragments and <style> and <svg> tags with content 2008 // eslint-disable-next-line no-param-reassign 2009 txt = txt.replace(/<(xml|style|svg)("[^"]*"|'[^']*'|[^>])*>(.|[\r\n])*?<\/\1>/gi, ''); 2010 // Replace <br> and </p> tags with line break char, skipping last </p> which is not followed by <br> or </p> 2011 // eslint-disable-next-line no-param-reassign 2012 txt = txt.replace(/(<br\s*\/?>)|(<\/p\s*>)(?=.*(<\/p\s*>|<br\s*\/?>))/g, ' '); 2013 // Replace with space 2014 // eslint-disable-next-line no-param-reassign 2015 txt = txt.replace(/ /g, ' '); 2016 // Remove HTML Tags 2017 const regexp = /<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g; 2018 return txt.replace(regexp, ''); 2019 }, 2020 truncate (text, limit, suffix) { 2021 if (!text) return ''; 2022 if (text.length > limit) return typeof suffix === 'string' ? text.slice(0, limit - suffix.length) + suffix : text.slice(0, limit); 2023 return text; 2024 }, 2025 // eslint-disable-next-line 2026 setSubArray (items = [], start, end, subArrayName, options) { 2027 // eslint-disable-next-line 2028 options.data.root[subArrayName] = items.slice(start, end); 2029 }, 2030 formatAreaUnit (areaUnit) { 2031 switch(areaUnit){ 2032 case 'ACRE': 2033 return 'Acres'; 2034 case 'SQUARE_METER': 2035 return 'Sq.M.'; 2036 case 'SQUARE_YARD': 2037 return 'Sq.Yd.'; 2038 default: 2039 return 'Sq.Ft.'; 2040 } 2041 }, 2042 formatFrequency: formatFrequency, 2043 formatFrequencyShort: formatFrequencyShort, 2044 lpFormatFrequency (freqUnit, options) { 2045 return formatFrequencyExt(freqUnit, options && options.hash); 2046 }, 2047 subArray (index, start, end, options) { 2048 return index >= start && index < end ? options.fn(this) : options.inverse(this); 2049 }, 2050 formatPropertyStatus (status, showSoldDate, date) { 2051 let formattedStatus = ''; 2052 switch(status){ 2053 case 'SOLD': 2054 formattedStatus = 'Sold'; 2055 break; 2056 case 'FOR_SALE': 2057 formattedStatus = 'For Sale'; 2058 break; 2059 case 'COMING_SOON': 2060 formattedStatus = 'Coming Soon'; 2061 break; 2062 case 'INACTIVE': 2063 formattedStatus = 'Inactive'; 2064 break; 2065 case 'POCKET_LISTING': 2066 formattedStatus = 'Pocket Listing'; 2067 break; 2068 case 'PENDING': 2069 formattedStatus = 'Pending'; 2070 break; 2071 case 'UNDER_CONTRACT': 2072 formattedStatus = 'Under Contract'; 2073 break; 2074 case 'ACTIVE_UNDER_CONTRACT': 2075 formattedStatus = 'Active Under Contract'; 2076 break; 2077 default: 2078 formattedStatus = status; 2079 } 2080 // `typeof date === 'string'` matters: when called as 2081 // `{{formatPropertyStatus status}}` Handlebars passes its options object 2082 // as `showSoldDate`/`date`, and this guard keeps the legacy output. 2083 if ((formattedStatus === 'Sold' || formattedStatus === 'Leased') && showSoldDate && typeof date === 'string' && date) formattedStatus += ` on ${date}`; 2084 return formattedStatus; 2085 }, 2086 formatGrade (gradeValue) { 2087 switch(gradeValue){ 2088 case 'UNDERGRADUATE_COURSES': 2089 return 'Undergrad'; 2090 case 'PRE_KINDERGARTEN': 2091 return 'PreK'; 2092 case 'KINDERGARTEN': 2093 return 'K'; 2094 case 'FIRST_GRADE': 2095 return '1st'; 2096 case 'SECOND_GRADE': 2097 return '2nd'; 2098 case 'THIRD_GRADE': 2099 return '3rd'; 2100 case 'FOURTH_GRADE': 2101 return '4th'; 2102 case 'FIFTH_GRADE': 2103 return '5th'; 2104 case 'SIXTH_GRADE': 2105 return '6th'; 2106 case 'SEVENTH_GRADE': 2107 return '7th'; 2108 case 'EIGHTH_GRADE': 2109 return '8th'; 2110 case 'NINTH_GRADE': 2111 return '9th'; 2112 case 'TENTH_GRADE': 2113 return '10th'; 2114 case 'ELEVENTH_GRADE': 2115 return '11th'; 2116 case 'TWELFTH_GRADE': 2117 return '12th'; 2118 default: 2119 return ''; 2120 } 2121 }, 2122 encodeURI (uri) { 2123 return encodeURI(uri); 2124 }, 2125 encodeURIComponent (txt) { 2126 return encodeURIComponent(txt); 2127 }, 2128 hbFormatDate (date, type) { 2129 if (!date) return ''; 2130 const newDate = date === 'current' ? new Date() : new Date(date); 2131 if (Number.isNaN(newDate.getTime())) return ''; 2132 const months = [ 2133 'January', 2134 'February', 2135 'March', 2136 'April', 2137 'May', 2138 'June', 2139 'July', 2140 'August', 2141 'September', 2142 'October',
2143 'November', 2144 'December' 2145 ]; 2146 if (type === 'YYYY' || type === 'year') return `${newDate.getFullYear()}`; 2147 if (type === 'MM/DD/YY') { 2148 let month = newDate.getMonth() + 1; 2149 if (month < 10) month = `0${month.toString()}`; 2150 return `${month}/${newDate.getDate()}/${newDate.getFullYear().toString().substr(-2)}`; 2151 } 2152 return `${months[newDate.getMonth()]} ${newDate.getDate()}, ${newDate.getFullYear()}`; 2153 }, 2154 openHousesFormat (startDate, endDate, timeZone) { 2155 if (!startDate || !endDate) return ''; 2156 /** 2157 * return formatted time. 2158 * @param {date} date 2159 * @return {time} time. 2160 */ const getTime = (date)=>{ 2161 let hours = date.getHours(); 2162 if (hours > 12) hours -= 12; 2163 const prefix = '0'; 2164 let time = `${hours}:${date.getMinutes() > 9 ? date.getMinutes() : prefix + date.getMinutes()}`; 2165 if (date.getHours() > 11) time += 'PM'; 2166 else time += 'AM'; 2167 return time; 2168 }; 2169 let tz = ''; 2170 let startFDate = startDate; 2171 let endFDate = endDate; 2172 if (timeZone) { 2173 startFDate = new Date(startDate).toLocaleString('en-US', { 2174 timeZone: timeZone 2175 }); 2176 endFDate = new Date(endDate).toLocaleString('en-US', { 2177 timeZone: timeZone 2178 }); 2179 [, , , tz] = new Date(endDate).toLocaleString('en-US', { 2180 timeZone: timeZone, 2181 timeZoneName: 'short' 2182 }).split(' '); 2183 } 2184 const date = new Date(startFDate); 2185 const openHouseDate = date.toLocaleDateString('en-US'); 2186 const time1 = getTime(date); 2187 const date2 = new Date(endFDate); 2188 const time2 = getTime(date2); 2189 return `${openHouseDate} ${time1} - ${time2} ${tz}`; 2190 }, 2191 math (lvalue, operator, rvalue) { 2192 // eslint-disable-next-line 2193 lvalue = parseFloat(lvalue); 2194 // eslint-disable-next-line 2195 rvalue = parseFloat(rvalue); 2196 return ({ 2197 '+': lvalue + rvalue, 2198 '-': lvalue - rvalue, 2199 '*': lvalue * rvalue, 2200 '/': lvalue / rvalue, 2201 '%': lvalue % rvalue 2202 })[operator]; 2203 }, 2204 findByKey (values, key, value, options) { 2205 const result = (values || []).find((entry)=>entry[key] === value); 2206 return options.fn(result); 2207 }, 2208 capitalize (string, split, options) { 2209 let capitalized; 2210 if (typeof string === 'string' && string.length) capitalized = string.toLowerCase().split(split).map((w)=>w.charAt(0).toUpperCase() + w.slice(1)).join(' ').toString(); 2211 return capitalized; 2212 }, 2213 and (...arg) { 2214 return Array.prototype.slice.call(arg).every(Boolean); 2215 }, 2216 or (...arg) { 2217 return Array.prototype.slice.call(arg, 0, -1).some(Boolean); 2218 }, 2219 not (arg) { 2220 return !arg; 2221 }, 2222 orderByIds (items, orderedIds, options) { 2223 let ret = ''; 2224 let data = null; 2225 if (options.data) data = HandlebarsInstance.createFrame(options.data); 2226 // When passed orderedIds, filter out empty items including empty strings and 2227 // only show items (and in that order) in a loop 2228 // If no orderedIds provided, show all items 2229 const filteredIds = (orderedIds || []).filter(Boolean); 2230 if (filteredIds && filteredIds.length) { 2231 let skippedItems = 0; 2232 ret = filteredIds.reduce((res, id, idx)=>{ 2233 const item = (items || []).find((item)=>item.id === id); 2234 // ID doesn't exist so ditch it 2235 if (!item) { 2236 skippedItems += 1; 2237 return res; 2238 } 2239 if (data) data.index = idx - skippedItems; 2240 return res + options.fn(item, { 2241 data: data 2242 }); 2243 }, ''); 2244 } else for(let i = 0, j = (items || []).length; i < j; i++){ 2245 if (data) data.index = i; 2246 ret += options.fn(items[i], { 2247 data: data 2248 }); 2249 } 2250 return ret; 2251 }, 2252 ifIn (elem, list, options) { 2253 if (list && list.indexOf(elem) > -1) return options.fn(this); 2254 return options.inverse(this); 2255 }, 2256 partial (name, options) { 2257 // Register a partial and output the content in a script for clientside rendering 2258 HandlebarsInstance.registerPartial(name, HandlebarsInstance.compile(options.fn())); 2259 // eslint-disable-next-line 2260 const script = `
2260<script type="text/x-handlebars-template" class="${name} pagination-script">${options.fn()}</${'script'}>`; 2261 return script; 2262 }, 2263 numCompare (l, r, operator, options) { 2264 const operators = { 2265 '==': function(l, r) { 2266 // eslint-disable-next-line 2267 return l == r; 2268 }, 2269 '===': function(l, r) { 2270 return l === r; 2271 }, 2272 '!=': function(l, r) { 2273 // eslint-disable-next-line 2274 return l != r; 2275 }, 2276 '<': function(l, r) { 2277 return l < r; 2278 }, 2279 '>': function(l, r) { 2280 return l > r; 2281 }, 2282 '<=': function(l, r) { 2283 return l <= r; 2284 }, 2285 '>=': function(l, r) { 2286 return l >= r; 2287 } 2288 }; 2289 const result = operators[operator](l, r); 2290 if (result) return options.fn ? options.fn(this) : true; 2291 return options.fn ? options.inverse(this) : false; 2292 }, 2293 lpFormatNumber: lpFormatNumber, 2294 arrayToHtmlList (arr, options) { 2295 // eslint-disable-next-line 2296 return arr.reduce((acc, current)=>{ 2297 try { 2298 if (typeof current === 'object' || current === null) return acc; 2299 // eslint-disable-next-line 2300 return acc += `<li>${current}</li>`; 2301 } catch (e) { 2302 /* empty */ } 2303 }, ''); 2304 }, 2305 join (array, separator, options) { 2306 if (!array || !array.join) return ''; 2307 return array.join(typeof separator === 'string' ? separator : ', '); 2308 }, 2309 dedupe (items, key, options) { 2310 let data = null; 2311 let skippedItems = 0; 2312 const list = new Set(); 2313 if (options.data) data = HandlebarsInstance.createFrame(options.data); 2314 return (items || []).reduce((res, item, idx)=>{ 2315 const val = key ? item[key] : item; 2316 // Item is unique if we're passed a key that is not defined 2317 const isUnique = !list.has(val) || key && val === undefined; 2318 if (isUnique) list.add(val); 2319 else { 2320 skippedItems += 1; 2321 return res; 2322 } 2323 if (data) data.index = idx - skippedItems; 2324 return res + options.fn(item, { 2325 data: data 2326 }); 2327 }, ''); 2328 }, 2329 JSONstringify (obj, options) { 2330 return JSON.stringify(obj); 2331 }, 2332 // eslint-disable-next-line sonarjs/cognitive-complexity 2333 formatPropertyPrice (...args) { 2334 const options = args[args.length - 1]; 2335 const opts = options.hash; 2336 const property = args.length > 1 ? args[0] : opts.property; 2337 const precision = opts.precision || 0; 2338 if (args.length > 2) // eslint-disable-next-line 2339 opts.mode = args[1]; 2340 if (!opts.mode) opts.mode = 'short'; 2341 let separator = args.length > 3 ? args[2] : opts.separator; 2342 if (typeof separator !== 'string') separator = ' | '; 2343 if (property.isPasswordProtected) return 'Exclusive Listing'; 2344 let priceUponRequestText = args.length > 4 ? args[3] : opts.priceUponRequestText; 2345 if (typeof priceUponRequestText !== 'string') priceUponRequestText = 'Price Upon Request'; 2346 if (property.priceUponRequest) return priceUponRequestText; 2347 let price = property.salesPrice; 2348 let reduced = null; 2349 // eslint-disable-next-line sonarjs/no-collapsible-if 2350 if (property.status !== 'SOLD' && property.status !== 'Leased') { 2351 if (property.reducedPrice) { 2352 if (!opts.reducedClass) price = property.reducedPrice; 2353 else reduced = property.reducedPrice; 2354 } 2355 } 2356 let result = ''; 2357 if (reduced) result += `<${opts.reducedTag || 'span'} class="${opts.reducedClass}">${lpFormatNumber(reduced, property.currency, precision)}</${opts.reducedTag || 'span'}>`; 2358 if (price) { 2359 price = lpFormatNumber(price, property.currency, precision); 2360 if (opts.priceTag || opts.priceClass) result += `<${opts.priceTag || 'span'}${opts.priceClass ? ` class="${opts.priceClass}"` : ''}>${price}</${opts.priceTag || 'span'}>`; 2361 else result += price; 2362 } 2363 const leasePrice = property.leasePrice && lpFormatNumber(property.leasePrice, property.currency, precision); 2364 if (leasePrice) { 2365 if (result) result += separator; 2366 const leaseText = `${leasePrice}${formatFrequencyExt(property.leasePeriod, opts)}`; 2367 if (opts.leaseTag || opts.leaseClass) result += `<${opts.leaseTag || 'span'}${opts.leaseClass ? ` class="${opts.leaseClass}"` : ''}>${leaseText}</${opts.leaseTag || 'span'}>`; 2368 else result += leaseText; 2369 } 2370 return new HandlebarsInstance.SafeString(result); 2371 }, 2372 // eslint-disable-next-line sonarjs/cognitive-complexity 2373 mediaImage (mediaSource, options = {}) { 2374 if (!mediaSource) return; 2375 const { lazy: lazy, ...attributes } = options.hash; 2376 let src = ''; 2377 let srcset = ''; 2378 if (typeof mediaSource === 'string') src = mediaSource; 2379 else { 2380 const srcMap = {}; 2381 const { height: height, width: width, altTagText: altTagText } = mediaSource; 2382 MEDIA_SIZES.forEach((src)=>{ 2383 if (mediaSource[src.field] && !srcMap[mediaSource[src.field]]) srcMap[mediaSource[src.field]] = src.w; 2384 }); 2385 const srcs = Object.keys(srcMap); 2386 if (!srcs.length) return; 2387 if (altTagText) attributes.alt = altTagText; 2388 if (height && width) { 2389 if (height >= width) { 2390 if (attributes.class) attributes.class += ' portrait'; 2391 else attributes.class = 'portrait'; 2392 } 2393 if ('setDims' in options.hash) { 2394 attributes.width = width; 2395 attributes.height = height; 2396 } 2397 } 2398 if (srcs.length > 1 && width && width < srcMap[srcs[srcs.length - 1]]) { 2399 const maxSrc = srcs.findIndex((src)=>
2399srcMap[src] >= width); 2400 srcs.splice(maxSrc + 1); 2401 srcMap[srcs[srcs.length - 1]] = width; 2402 } 2403 if (srcs.length > 1) { 2404 srcset = srcs.map((s)=>`${s} ${srcMap[s]}w`).join(', '); 2405 srcs.sort((a, b)=>Math.abs(srcMap[a] - MEDIA_SIZE_FOR_SRC) - Math.abs(srcMap[b] - MEDIA_SIZE_FOR_SRC)); 2406 } 2407 // eslint-disable-next-line 2408 src = srcs[0]; 2409 } 2410 delete attributes.setDims; 2411 if (!srcset) delete attributes.sizes; 2412 if (!('alt' in attributes)) attributes.alt = ''; 2413 if (!('loading' in attributes) && (options?.data?.root?.sectionIndex > 1 || lazy)) attributes.loading = 'lazy'; 2414 const attrs = Object.keys(attributes).map((k)=>`${HandlebarsInstance.escapeExpression(k)}="${HandlebarsInstance.escapeExpression(attributes[k])}"`).join(' '); 2415 return new HandlebarsInstance.SafeString(// eslint-disable-next-line sonarjs/no-nested-template-literals 2416 `<img src="${src}"${srcset ? ` srcset="${srcset}"` : ''}${attrs ? ` ${attrs}` : ''}>`); 2417 }, 2418 bgImage (mediaSource) { 2419 if (!mediaSource) return ''; 2420 if (typeof mediaSource === 'string') return mediaSource; 2421 return mediaSource.largeUrl || mediaSource.url || ''; 2422 }, 2423 concat (...rest) { 2424 let outStr = ''; 2425 // rest params are Array instances while arguments object is not 2426 for(const arg in rest)if (rest[arg] !== null && rest[arg] !== undefined && typeof rest[arg] !== 'object') outStr += rest[arg]; 2427 return outStr; 2428 }, 2429 setVideoExtension (uri, format) { 2430 if (!uri || !format) return ''; 2431 const decodedUri = new URL(uri); 2432 if (decodedUri.host !== 'res.cloudinary.com') { 2433 // Not a cloudinary uri, do not rewrite 2434 if (decodedUri.pathname.endsWith(`.${format}`)) return uri; 2435 return ''; 2436 } 2437 // Rewrite the cloudinary uri 2438 const lastPeriodIdx = decodedUri.pathname.lastIndexOf('.'); 2439 let pathWithoutFormat = decodedUri.pathname; 2440 if (lastPeriodIdx !== -1) pathWithoutFormat = decodedUri.pathname.substr(0, lastPeriodIdx); 2441 decodedUri.pathname = `${pathWithoutFormat}.${format}`; 2442 return decodedUri.toString(); 2443 }, 2444 addVideoSources (uri) { 2445 if (!uri) return ''; 2446 const VIDEO_VARIANTS = [ 2447 { 2448 format: 'webm', 2449 codec: 'vp9', 2450 htmlCodecs: ';codecs=vp9' 2451 }, 2452 { 2453 format: 'mp4', 2454 codec: 'h265', 2455 htmlCodecs: ';codecs=hvc1' 2456 }, 2457 { 2458 format: 'mp4', 2459 codec: 'h264', 2460 htmlCodecs: '' 2461 } 2462 ]; 2463 const VIDEO_EXT_REGEXP = /\.(?:3gp|mpeg|mp4|m4v|m4p|ogv|ogg|mov|webm)$/; 2464 if (!uri.includes('res.cloudinary.com')) // keep existing or no extension for non Cloudinary urls 2465 return `<source data-src="${uri}">`; 2466 // Cap delivery at 1080p (1920px wide) while preserving aspect ratio. Width-only: 2467 // c_limit never upscales, so portrait sources are left at their native size. 2468 // No q_auto: quality is left to Cloudinary's default rather than forced down. 2469 // Note the regex below consumes any q_auto in the source URL, so it is dropped 2470 // rather than carried through. 2471 const CONSTRAINED_DELIVERY = 'w_1920,c_limit'; 2472 const uriNoExt = uri.replace(VIDEO_EXT_REGEXP, ''); 2473 const sources = VIDEO_VARIANTS.map((type)=>{ 2474 const cloudinaryFormatUrl = `${uriNoExt.replace(/f_auto(?::video)?(?:,q_auto(?::\w+)?)?/, `f_${type.format},vc_${type.codec},${CONSTRAINED_DELIVERY}`)}.${type.format}`; 2475 return `<source data-src="${cloudinaryFormatUrl}" type="video/${type.format}${type.htmlCodecs}">`; 2476 }); 2477 return sources.join('\n'); 2478 }, 2479 cloudinaryVideoFirstFrame: $0ce6edea77f7b81a$exports.getVideoFirstFrame, 2480 initials (text, options) { 2481 if (!text) return ''; 2482 if (options?.hash?.endChar) // eslint-disable-next-line 2483 text = text.split(options.hash.endChar)[0]; 2484 // eslint-disable-next-line 2485 const maxChars = +options?.hash?.maxChars || 2; // we do not allow this to be 0 2486 let result = text.match(/\b\w/g)?.slice(0, maxChars); 2487 if (!result) return ''; 2488 if (options?.hash?.addText) result = result.map((item)=>item + options.hash.addText); 2489 return result.join(options?.hash?.joinWith || '').toUpperCase(); 2490 }, 2491 normalizePhone (phone) { 2492 if (!phone) return ''; 2493 const str = String(phone).trim(); 2494 return (str.startsWith('+') ? '+' : '') + str.replace(/\D/g, ''); 2495 } 2496 }; 2497} 2498$53de3c160faf5a81$exports = $53de3c160faf5a81$var$handlebarsHelpersFactory; 2499 2500 2501/* global window, document */ // eslint-disable-next-line import/prefer-default-export 2502class $dc851cf3939b6ef5$export$ff0712c26d5458f7 { 2503 /** 2504 * Initialize Modal Controller 2505 * @param {Object} options 2506 */ constructor(options){ 2507 this.isBuilder = false;
2508 this.companyId = null; 2509 this.websiteId = null; 2510 this.pageId = null; 2511 this.shareId = null; 2512 this.pageMeta = null; 2513 this.websiteApiGatewayUrl = null; 2514 this.buyerSellerServiceUrl = null; 2515 this.leadIngesterUrl = null; 2516 this.divolteServiceUrl = null; 2517 this.eventBus = null; 2518 this.templateId = null; 2519 this.myhomeDashboardEnabled = false; 2520 this.mlsEnabled = false; 2521 this.hstValuationRedirectEnabled = false; 2522 this.googleMapsAPIKey = null; 2523 } 2524 /** 2525 * Controllers must implement a "destroy" method to be called 2526 * after page navigation to remove event handlers / cleanup 2527 */ destroy() {} 2528 /** 2529 * Set page and supporting data 2530 * @param {string} pageId 2531 * @param {Object} options 2532 */ setPage(pageId, options = {}) { 2533 this.pageId = pageId; 2534 this.shareId = options.shareId || null; 2535 this.pageMeta = { 2536 sourceResource: options.sourceResource, 2537 pageElementId: options.pageElementId, 2538 pageQueryVariables: options.pageQueryVariables || {} 2539 }; 2540 } 2541 /** 2542 * Sets if we are in pagebuilder context or not 2543 * @param {boolean} isBuilder 2544 */ setIsBuilder(isBuilder) { 2545 this.isBuilder = isBuilder; 2546 } 2547 /** 2548 * Set Company and supporting data 2549 * @param {string} companyId 2550 * @param {Object} options 2551 */ setCompany(companyId, options = {}) { 2552 this.companyId = companyId; 2553 } 2554 /** 2555 * Set website and supporting data 2556 * @param {string} websiteId 2557 * @param {Object} options 2558 */ setWebsite(websiteId, options = {}) { 2559 this.websiteId = websiteId; 2560 if (options.myhomeDashboardEnabled) this.myhomeDashboardEnabled = options.myhomeDashboardEnabled; 2561 if (options.mlsEnabled) this.mlsEnabled = options.mlsEnabled; 2562 if (options.hstValuationRedirectEnabled) this.hstValuationRedirectEnabled = options.hstValuationRedirectEnabled; 2563 } 2564 /** 2565 * Set websiteApiGatewayUrl 2566 * @param {string} websiteApiGatewayUrl 2567 * @param {Object} options 2568 */ setWebsiteApiGatewayUrl(websiteApiGatewayUrl, options = {}) { 2569 this.websiteApiGatewayUrl = websiteApiGatewayUrl; 2570 } 2571 /** 2572 * Set buyerSellerServiceUrl 2573 * @param {string} buyerSellerServiceUrl 2574 * @param {Object} options 2575 */ setBuyerSellerServiceUrl(buyerSellerServiceUrl, options = {}) { 2576 this.buyerSellerServiceUrl = buyerSellerServiceUrl; 2577 } 2578 /** 2579 * Set divolteServiceUrl and supporting data 2580 * @param {string} divolteServiceUrl 2581 * @param {Object} options 2582 */ setDivolteServiceUrl(divolteServiceUrl, options = {}) { 2583 this.divolteServiceUrl = divolteServiceUrl; 2584 } 2585 /** 2586 * Set eventBusUrl 2587 * @param {string} eventBusUrl 2588 * @param {Object} options 2589 */ setEventBusUrl(eventBusUrl, options = {}) { 2590 this.eventBusUrl = eventBusUrl; 2591 } 2592 /** 2593 * Set templateId and supporting data 2594 * @param {string} templateId 2595 * @param {Object} options 2596 */ setTemplateId(templateId, options = {}) { 2597 this.templateId = templateId; 2598 } 2599 /** 2600 * Set leadIngesterUrl 2601 * @param {string} leadIngesterUrl 2602 * @param {Object} options 2603 */ setLeadIngesterUrl(leadIngesterUrl, options = {}) { 2604 this.leadIngesterUrl = leadIngesterUrl; 2605 } 2606 /** 2607 * Set googleMapsAPIKey 2608 * @param {string} googleMapsAPIKey 2609 * @param {Object} options 2610 */ setGoogleMapsAPIKey(googleMapsAPIKey, options = {}) { 2611 this.googleMapsAPIKey = googleMapsAPIKey; 2612 } 2613 /** 2614 * Set eventBus 2615 * @param {Object} options 2616 */ setEventBus({ enabled: enabled, apiKey: apiKey, url: url }) { 2617 this.eventBus = { 2618 enabled: enabled, 2619 apiKey: apiKey, 2620 url: url 2621 }; 2622 } 2623} 2624 2625 2626/* eslint-disable import/prefer-default-export */ // eslint-disable-next-line import/prefer-default-export 2627class $7c391e2f7931d60d$export$3b5bd9381a52554c { 2628 /** 2629 * Initialize Base Controller at build time 2630 * @param { ConfigController } config 2631 * @param {Window} window 2632 * @param {Document} document 2633 */ constructor(config, window, document){ 2634 // TODO: Listen for events from configController to update configuration 2635 this.config = config; 2636 this.window = window; 2637 this.document = document; 2638 if (!this.destroy) // With turbolinks, we want to ensure that on each page load we have the latest version of the sdk 2639 // Controllers are deconstructed and replaced (on the window object) per request 2640 // Controllers must use the destory method to remove event handlers to prevent undefined behavior 2641 throw new Error('Controllers must implement a deconstructor'); 2642 } 2643} 2644 2645 2646// eslint-disable-next-line import/prefer-default-export 2647const $a3e97e89bbc2a366$export$f037eeffb5561205 = 2000; 2648 2649 2650class $0ead03fdb95fa9ce$export$d507f25e63650365 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 2651 /** 2652 * Initialize Modal Controller at build time 2653 * @param { ConfigController } config 2654 * @param {Window} window 2655 * @param {Document} document 2656 */ constructor(config, window, document){ 2657 super(config, window, document); 2658 this.setLoginState = this.setLoginState.bind(this); 2659 this.pageId = null; 2660 this.modals = []; 2661 this.exitModalTriggered = {}; 2662 this.exitModalEventListeners = []; 2663 } 2664 /** 2665 * Initialize Modal Controller at run time 2666 * Attach handlers and events to DOM 2667 * @param {Object} options 2668 */ initialize(options) { 2669 try { 2670 const { config: config, document: document } = this; 2671 this.pageId = config.pageId; 2672 this.modals = document.querySelectorAll('body > #modals > .modal');
2673 options.modals.forEach((m)=>{ 2674 this._attachModalHandler(m); 2675 }); 2676 } catch (e) { 2677 // eslint-disable-next-line no-console 2678 console.log(e); 2679 } 2680 } 2681 /** 2682 * Controllers must implement a "destroy" method to be called 2683 * after page navigation to remove event handlers / cleanup 2684 */ destroy() { 2685 const { document: document } = this; 2686 this.exitModalEventListeners.forEach((listener)=>{ 2687 document.removeEventListener('mouseout', listener); 2688 }); 2689 this.modals = []; 2690 this.exitModalTriggered = {}; 2691 this.exitModalEventListeners = []; 2692 } 2693 /** 2694 * Set modal to local storage with expiration 2695 * @param {string} modalId 2696 */ setModalWithExpiry(modalId) { 2697 const { window: window } = this; 2698 const TTL = 86400000; // 24 hours 2699 const now = new Date(); 2700 const expiry = now.getTime() + TTL; 2701 const key = `modal-controller-${modalId}`; 2702 try { 2703 window.localStorage.setItem(key, JSON.stringify(expiry)); 2704 } catch (err) { 2705 // catch error when setting item to storage on iOS private browser 2706 } 2707 } 2708 /** 2709 * Save success login modal to local storage 2710 */ setLoginState() { 2711 const { window: window } = this; 2712 try { 2713 window.localStorage.setItem('isSignedUp', 'true'); 2714 } catch (err) { 2715 // catch error when setting item to storage on iOS private browser 2716 } 2717 } 2718 /** 2719 * Get modal and check expiration 2720 * @param {string} modalId 2721 * @return {boolean} 2722 */ getModalWithExpiry(modalId) { 2723 const { window: window } = this; 2724 const storage = window.localStorage; 2725 const expirationTime = storage.getItem(`modal-controller-${modalId}`); 2726 if (!expirationTime) return false; 2727 const expiry = JSON.parse(expirationTime); 2728 const now = new Date(); 2729 if (now.getTime() > expiry) { 2730 storage.removeItem(`modal-controller-${modalId}`); 2731 return false; 2732 } 2733 return true; 2734 } 2735 /** 2736 * Make a modal visible 2737 * @param {string} modalId 2738 * @param {Object} options 2739 */ show(modalId, options = {}) { 2740 // TODO: migrate logic from page.handlebars 2741 const { window: window } = this; 2742 const modalViewed = this.getModalWithExpiry(modalId); 2743 // Only show a modal if it has not been seen 2744 // Does not affect "show modal on button click" 2745 if (modalId && !modalViewed || options.forced === true) { 2746 window.lpUI.showModal(`modal-${modalId}`, options); 2747 this.setModalWithExpiry(modalId); 2748 } 2749 } 2750 /** 2751 * Attach events based on Modal type and page settings 2752 * @param {Modal} modal 2753 */ _attachModalHandler(modal) { 2754 const { pageId: pageId } = this; 2755 const { trigger: trigger, pageSpecific: pageSpecific } = modal; 2756 if (pageSpecific) { 2757 const pageIds = modal.pages.map((p)=>p.pageId); 2758 if (!pageIds.includes(pageId)) // Modal does not belong to this page 2759 return; 2760 } 2761 if (trigger === 'EXIT') this._exitModalHandler(modal); 2762 else if (trigger === 'TIMER') this._timerModalHandler(modal); 2763 else if (trigger === 'FORCED') this._forcedModalHandler(modal); 2764 } 2765 /** 2766 * Attach events for exit Modals 2767 * @param {Modal} modal 2768 */ _exitModalHandler(modal) { 2769 // eslint-disable-next-line 2770 const that = this; 2771 const { document: document, exitModalTriggered: exitModalTriggered } = this; 2772 const { modalId: modalId } = modal; 2773 /** 2774 * Handle the mouseout dom event 2775 * @param {Event} event 2776 */ function triggerExitModal(event) { 2777 if (exitModalTriggered[modalId]) return; 2778 if (!event.toElement && !event.relatedTarget) { 2779 that.show(modalId); 2780 exitModalTriggered[modalId] = true; 2781 } 2782 } 2783 document.addEventListener('mouseout', triggerExitModal); 2784 this.exitModalEventListeners.push(triggerExitModal); 2785 } 2786 /** 2787 * Attach events for timer Modals
2788 * @param {Modal} modal 2789 */ _timerModalHandler(modal) { 2790 const { modalId: modalId, timerDelay: timerDelay } = modal; 2791 setTimeout(()=>{ 2792 this.show(modalId); 2793 }, timerDelay); 2794 } 2795 /** 2796 * Attach events for Forced Modals 2797 * @param {Modal} modal 2798 */ _forcedModalHandler(modal) { 2799 const { modalId: modalId } = modal; 2800 const { window: window, document: document } = this; 2801 const isLoggedIn = window.localStorage.getItem('isSignedUp') === 'true'; 2802 if (!isLoggedIn) { 2803 // watch for event triggering success login 2804 const forcedModal = document.querySelector(`#modal-${modalId}`); 2805 const contactForm = forcedModal?.querySelector('form'); 2806 const MODAL_CLOSE_DELAY = contactForm?.dataset.delay || (0, $a3e97e89bbc2a366$export$f037eeffb5561205); 2807 // form submit autoclose is handled by contactForms controller 2808 contactForm.addEventListener('formsubmitted', ()=>{ 2809 this.setLoginState(); 2810 }); 2811 window.addEventListener('oauthSuccess', ()=>{ 2812 this.setLoginState(); 2813 contactForm.classList.add('success'); 2814 setTimeout(()=>{ 2815 window.lpUI.hideModal(`modal-${modalId}`); 2816 contactForm.reset(); 2817 contactForm.classList.remove('success'); 2818 }, MODAL_CLOSE_DELAY); 2819 }); 2820 this.show(modalId, { 2821 forced: true 2822 }); 2823 } 2824 } 2825} 2826 2827 2828/* eslint-disable import/prefer-default-export */ /* global window */ /* eslint-disable import/prefer-default-export */ /** 2829 * Handle navigation push 2830 * @param {string} href 2831 * @param {boolean} _blank 2832 */ const $fc0a058ae42af628$export$95e8d77caafa3e06 = (href, _blank = false)=>{ 2833 if (!href) return; 2834 if (_blank) { 2835 window.open(href); 2836 return; 2837 } 2838 window.location.assign(href); 2839}; 2840const $fc0a058ae42af628$export$267a1435fe18b8d4 = (obj, path, defValue)=>{ 2841 if (!path) return undefined; 2842 const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g); 2843 const result = pathArray.reduce((prevObj, key)=>prevObj && prevObj[key], obj); 2844 return result === undefined ? defValue : result; 2845}; 2846 2847 2848 2849class $d48f9f944810f613$export$ca3218b7861b9cb0 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 2850 /** 2851 * Initialize Button Controller at build time 2852 * @param { ConfigController } config 2853 * @param {Window} window 2854 * @param {Document} document 2855 */ constructor(config, window, document){ 2856 super(config, window, document); 2857 this._boundClickHandler = this._buttonClickHandler.bind(this); 2858 } 2859 /** 2860 * Initialize Button Controller at run time 2861 * Attach handlers and events to DOM 2862 * @param {Object} options 2863 */ initialize(options = {}) { 2864 try { 2865 const { document: document } = this; 2866 document.body.removeEventListener('click', this._boundClickHandler); 2867 document.body.addEventListener('click', this._boundClickHandler); 2868 } catch (e) { 2869 // eslint-disable-next-line no-console 2870 console.error(e); 2871 } 2872 } 2873 /** 2874 * Controllers must implement a "destroy" method to be called 2875 * after page navigation to remove event handlers / cleanup 2876 */ destroy() { 2877 const { document: document } = this; 2878 document.body.removeEventListener('click', this._boundClickHandler); 2879 } 2880 /** 2881 * Buttons click handler 2882 * @param {event} e 2883 */ _buttonClickHandler(e) { 2884 this._handleButtonClick(e).catch((e)=>console.error(e)); 2885 } 2886 /** 2887 * Handle button click 2888 * We need special function to have easy way to detach listener 2889 * @param {Event} e 2890 */ async _handleButtonClick(e) { 2891 const { window: window, document: document } = this; 2892 const button = e.target.closest('button, a'); 2893 if (!button) return; 2894 const type = button.dataset.type || ''; 2895 const href = button.href || button.dataset.href || ''; 2896 const target = button.target || ''; 2897 const { submit: submit } = button.dataset; 2898 if (submit) { 2899 try { 2900 await this._handleSubmit(button); 2901 } catch (err) { 2902 // eslint-disable-next-line no-console 2903 console.error(err); 2904 } 2905 (0, $fc0a058ae42af628$export$95e8d77caafa3e06)(href, target === '_blank'); 2906 } 2907 this._trackConversion(button); 2908 if (type === 'VIDEO') { 2909 this._handleVideoButton(button); 2910 return; 2911 } 2912 if (type === 'CONTACT_US') { 2913 this._handleContactUsButton(button); 2914 return; 2915 } 2916 if (type === 'SUBSCRIBE') { 2917 // TODO: Extend for an overwritten subscribe 2918 window.lpUI.showModal('modal-global-subscribe'); 2919 return; 2920 } 2921 if (type === 'MY_ACCOUNT') { 2922 // TODO: Extend for an overwritten subscribe 2923 window.lpUI.showModal('modal-global-my-account'); 2924 return; 2925 } 2926 if (type === 'SHARE_POPUP') { 2927 // TODO: Extend for an overwritten subscribe 2928 const sharePopup = button.querySelector('.share-popup'); 2929 if (sharePopup) sharePopup.style.display = 'flex'; 2930 e.stopPropagation(); // this may not work in current 'delegate' mode 2931 return; 2932 } 2933 // Custom modals 2934 if (type.substring(0, 6) === 'MODAL_') { 2935 const modalId = type.substring(6); 2936 window.lpUI.showModal(`modal-${modalId}`); 2937 return; 2938 } 2939 // MAILTO / TEL Event 2940 if (href?.startsWith('mailto:')) { 2941 const email = href.substring(7); 2942 // TODO: Replace with SDK method 2943 document.sendGoogleAnalyticsEvent({ 2944 hitType: 'event', 2945 eventCategory: 'button', 2946 eventAction: 'click', 2947 eventLabel: 'Email', 2948 eventValue: email 2949 }); 2950 } else if (href?.startsWith('tel:')) { 2951 const phoneNumber = href.substring(4); 2952 // TODO: Replace with SDK method 2953 document.sendGoogleAnalyticsEvent({ 2954 hitType: 'event', 2955 eventCategory: 'button', 2956 eventAction: 'click', 2957 eventLabel: 'Phone', 2958 eventValue: phoneNumber 2959 }); 2960 } 2961 } 2962 /** 2963 * Handle submit 2964 * @param {HTMLButtonElement|HTMLAnchorElement} button 2965 */ async _handleSubmit(button) { 2966 const form = button.closest('form'); 2967 const { window: window } = this; 2968 if (form) return await window.luxuryPresence.contactForms.submitForm(form); 2969 return null; 2970 } 2971 _getVimeoSrc(link) { 2972 if (!link || !link.includes('vimeo.com') || link.length > 2000) return null; 2973 const matchResult = link.match(/(?:(?:www\.)?vimeo\.com\/(?:showcase\/\d+(?:\/video\/|\?video[=/])|channels\/(?:\w+\/)?|groups\/(?:[^/]*)\/videos\/|)|player\.vimeo\.com\/video\/)(\d+)(?:(?:\?.*&*h=|\/)+([\d,a-f]+))?/); 2974 if (!matchResult) return null; 2975 const [, vimeoId, vimeoHashParameter] = matchResult; 2976 let src = `https://player.vimeo.com/video/${vimeoId}?`; 2977 if (vimeoHashParameter) src += `h=${vimeoHashParameter}&`; 2978 src += 'autoplay=1'; 2979 return src; 2980 } 2981 /** 2982 * Handle type video click 2983 * @param {HTMLElement} button 2984 */ // eslint-disable-next-line sonarjs/cognitive-complexity 2985 _handleVideoButton(button) { 2986 const { document: document } = this; 2987 const section = button.closest('section'); 2988 // Embed youtube/vimeo video url 2989 let { src: src } = button.dataset; 2990 let youtubeId = ''; 2991 if (src && (src.includes('youtube.com') || src.includes('youtu.be')) && !src.includes('youtube.com/embed')) { 2992 // test link: https://regexr.com/3anm9 2993 const youtubeRegex = /(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\?(?:\S*?&?v=)
2993)|youtu.be\/)([a-zA-Z0-9_-]{6,11})/; 2994 const youtubeResult = src.match(youtubeRegex); 2995 // eslint-disable-next-line 2996 if (youtubeResult) youtubeId = youtubeResult[1]; 2997 } 2998 const vimeoSrc = this._getVimeoSrc(src); 2999 if (youtubeId) src = `https://youtube.com/embed/${youtubeId}?autoplay=1&controls=0`; 3000 else if (vimeoSrc) src = vimeoSrc; 3001 if (!src || !section) return; 3002 const isVideoFile = src.endsWith('.mp4') || src.endsWith('.webm') || src.includes('cloudinary.com'); 3003 const modalHtml = ` 3004 <div id="modal-${section.id}" class="modal visible"> 3005 <div class="modal-content"> 3006 <div class="lightbox-video"> 3007 <div class="video-player"> 3008 <div class="embed-container"> 3009 ${isVideoFile ? `<video controls autoplay src="${src}"></video>` : `<iframe frameborder="0" allowfullscreen="1" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" title="YouTube video player" width="100%" height="100%" src="${src}"></iframe>`} 3010 </div> 3011 </div> 3012 </div> 3013 </div> 3014 <button class="close lp-close" type="button" aria-label="close modal"><span class="lp-close-icon" aria-hidden="true"></span></button> 3015 </div> 3016 `; 3017 document.body.insertAdjacentHTML('beforeend', modalHtml); 3018 const modal = document.getElementById(`modal-${section.id}`); 3019 const closeModal = modal.querySelector('.close'); 3020 closeModal.addEventListener('click', ()=>{ 3021 modal.remove(); 3022 }); 3023 } 3024 /** 3025 * Handle type contact us click 3026 * @param {HTMLElement} button 3027 */ _handleContactUsButton(button) { 3028 const { window: window, document: document } = this; 3029 // TODO: Extend for an overwritten contact us 3030 document.sendGoogleAnalyticsEvent({ 3031 hitType: 'event', 3032 eventCategory: 'button', 3033 eventAction: 'click', 3034 eventLabel: 'contact' 3035 }); 3036 window.lpUI.showModal('modal-global-contact-us', { 3037 scrollLock: true 3038 }); 3039 } 3040 /** 3041 * Track conversion 3042 * @param {HTMLElement} button 3043 */ _trackConversion(button) { 3044 const { window: window, document: document } = this; 3045 // Conversion Tracking Options 3046 const { gtagConversionId: gtagConversionId, gtagConversionLabel: gtagConversionLabel, fbEventName: fbEventName } = button.dataset; 3047 if (gtagConversionId && gtagConversionLabel) { 3048 if (window.dataLayer && window.dataLayer.length) { 3049 const configured = window.dataLayer.some((layer)=>layer.length && layer[0] === 'config' && layer[1] === gtagConversionId); 3050 if (!configured) document.sendGoogleTagManagerEvent('config', gtagConversionId); 3051 } 3052 const sentTo = `${gtagConversionId}/${gtagConversionLabel}`; 3053 document.sendGoogleTagManagerEvent('event', 'conversion', { 3054 send_to: sentTo 3055 }); 3056 } 3057 if (window.fbq && fbEventName) window.fbq('track', fbEventName, {}); 3058 } 3059} 3060 3061 3062/* eslint-disable import/prefer-default-export */ 3063class $68a2d4aa500c7a05$export$61ec8f2b6291ec31 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 3064 /** 3065 * Initialize Validation Controller at build time 3066 * @param { ConfigController } config 3067 * @param {Window} window 3068 * @param {Document} document 3069 */ constructor(config, window, document){ 3070 super(config, window, document); 3071 this.validatedForms = []; 3072 } 3073 /** 3074 * Initialize Contact Form Controller at run time 3075 * Attach handlers and events to DOM 3076 * @param {Object} options 3077 */ initialize(options = {}) { 3078 try { 3079 const { window: window, document: document } = this; 3080 const { selector: selector } = options; 3081 let validatedForms = []; 3082 if (selector) validatedForms = document.querySelectorAll(`${selector} form[data-type="contact-form"]`); 3083 else validatedForms = document.querySelectorAll('form[data-type="contact-form"]'); 3084 const isPhoneValidationLibRequired = !!document.querySelectorAll('input[type="tel"]').length; 3085 // we are loading the phone validation lib from the globally defined list of libs 3086 if (isPhoneValidationLibRequired && !window.libphonenumber && window?.luxuryPresence?.libs) { 3087 const { loadJs: loadJs, jsLibsMap: jsLibsMap } = window.luxuryPresence.libs; 3088 const { libphonenumber: libphonenumber } = jsLibsMap; 3089 loadJs(libphonenumber.jsSrc, this.attachValidation.bind(this, validatedForms)); 3090 }
3090 else this.attachValidation(validatedForms); 3091 this.validatedForms = this.validatedForms.concat(validatedForms); 3092 } catch (e) { 3093 // eslint-disable-next-line no-console 3094 console.log(e); 3095 } 3096 } 3097 /** 3098 * Controllers must implement a "destroy" method to be called 3099 * after page navigation to remove event handlers / cleanup 3100 */ destroy() { 3101 this.validatedForms = []; 3102 } 3103 /** 3104 * Validate all forms in the document 3105 * @param {NodeListOf<HTMLFormElement>} forms 3106 */ attachValidation(forms) { 3107 forms.forEach((form)=>{ 3108 const inputs = form.querySelectorAll('input, select, textarea'); 3109 inputs.forEach((input)=>{ 3110 this.applyFieldValidation(input); 3111 }); 3112 }); 3113 } 3114 /** 3115 * Field Validation Handler from global context 3116 * @param {HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement} inputField 3117 */ applyFieldValidation(inputField) { 3118 const fieldType = inputField.getAttribute('type'); 3119 if (fieldType === 'tel') this._applyPhoneValidation(inputField); 3120 } 3121 /** 3122 * Phone Field Validation Handler 3123 * @param {HTMLInputElement} inputField 3124 */ _applyPhoneValidation(inputField) { 3125 const { window: window } = this; 3126 if (window.libphonenumber) { 3127 // https://codepen.io/coinscope/pen/BaXBvBp?editors=1010 3128 const phoneUtil = window.libphonenumber.isValidPhoneNumber; 3129 inputField.addEventListener('keyup', function() { 3130 if (this.hasAttribute('required') || this.value.replace(/\s/g, '').length) try { 3131 const phoneNumber = this.value; 3132 const region = 'US'; 3133 const isValidNumber = phoneUtil(phoneNumber, region); 3134 if (!isValidNumber) this.setCustomValidity('Please enter a valid phone number.'); 3135 else this.setCustomValidity(''); 3136 } catch (e) { 3137 this.setCustomValidity('Please enter a valid phone number.'); 3138 } 3139 else this.setCustomValidity(''); 3140 }); 3141 } 3142 } 3143} 3144 3145 3146 3147 3148/** 3149 * Fires the `generate_lead` Google Ads conversion on any marketing-site lead 3150 * event â lead-form submits (all routed through ContactFormController) and 3151 * social sign-in (oauth.js) â at most once per session. 3152 * 3153 * Reuses the same `generate_lead` event the Home Search Tool fires; the page 3154 * template already configures the LP Google tags, so no new Google Ads setup is 3155 * needed. Cross-tab/visitor dedupe is left to the conversion action's 3156 * Count="One" â localStorage is intentionally avoided as it would suppress a 3157 * returning visitor's later lead. 3158 */ const $3ec2bf3965f87ecc$export$78b64890ea40f4e4 = 'generate_lead'; 3159const $3ec2bf3965f87ecc$export$568da12be2433b06 = 'lp_lead_form_conversion_fired'; 3160function $3ec2bf3965f87ecc$var$alreadyFired(window) { 3161 try { 3162 return window.sessionStorage.getItem($3ec2bf3965f87ecc$export$568da12be2433b06) === 'true'; 3163 } catch { 3164 // sessionStorage can throw in private browsing; fail open so we still fire. 3165 return false; 3166 } 3167} 3168function $3ec2bf3965f87ecc$var$markFired(window) { 3169 try { 3170 window.sessionStorage.setItem($3ec2bf3965f87ecc$export$568da12be2433b06, 'true'); 3171 } catch { 3172 // Ignore â see alreadyFired(). 3173 } 3174} 3175function $3ec2bf3965f87ecc$export$e70565180c0e6950(window, document) { 3176 if (!window || !document) return; 3177 // GA bootstrap may not have run yet (or no pixel on this page); don't throw, 3178 // and don't burn the once-per-session flag if we can't actually fire. 3179 if (typeof document.sendGoogleTagManagerEvent !== 'function') return; 3180 if ($3ec2bf3965f87ecc$var$alreadyFired(window)) return; 3181 try { 3182 // Mark fired only AFTER a successful send, so a thrown GTM call doesn't 3183 // permanently suppress the conversion for the rest of the session â and 3184 // never let an analytics failure break the caller's success flow. 3185 document.sendGoogleTagManagerEvent('event', $3ec2bf3965f87ecc$export$78b64890ea40f4e4); 3186 $3ec2bf3965f87ecc$var$markFired(window); 3187 } catch { 3188 // Swallow â analytics must not break form submit / sign-in. 3189 } 3190} 3191 3192 3193 3194const $2aefad83322125c9$var$homeValuationRoute = '/api/v1/home-valuation'; 3195class $2aefad83322125c9$export$2e2bcd8739ae039 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 3196 destroy() { 3197 // 3198 } 3199 /** 3200 * Clean address string by removing call time frame suffix and extra whitespace 3201 * 3202 * Handles 17 templates that append ", call time frame: [value]" to the address: 3203 * - TheTrailblazerSir_2, TheMasterpiece (2x), TheInspirationSir_1, TheIconSir_3
3204 * - Influencer, GlobalCollective, Evolution, CorcoranAgent_1 3205 * - CompassSE (2x), CompassPrestige (2x), CompassNavigator 3206 * - ColdwellBanker (2x), Classic 3207 * 3208 * @param {string} address - Raw address string that may contain time frame info 3209 * @return {string} - Cleaned address string 3210 */ _cleanAddressString(address) { 3211 if (!address || typeof address !== 'string') return ''; 3212 let cleaned = address.trim(); 3213 // Fix 1: Handle "User entered address:\n..." pattern from TheProducer templates 3214 // Extract only the user entered address, ignore geocoded part 3215 if (cleaned.includes('User entered address:')) { 3216 const match = cleaned.match(/User entered address:\s*\n?\s*([^\n]+)/); 3217 if (match && match[1]) cleaned = match[1].trim(); 3218 } 3219 // Fix 2: Remove ", call time frame: ..." suffix if present (affects 17 templates) 3220 const timeFrameIndex = cleaned.indexOf(', call time frame:'); 3221 if (timeFrameIndex !== -1) cleaned = cleaned.substring(0, timeFrameIndex).trim(); 3222 return cleaned; 3223 } 3224 /** 3225 * Transform Google Maps address components to structured format 3226 * @param {Array} addressComponents - Google Maps address components 3227 * @return {Object} - Structured address object 3228 */ _transformAddressComponents(addressComponents) { 3229 const get = (t)=>(addressComponents.find((c)=>c.componentType === t) || {}).componentName?.text; 3230 const structuredAddress = {}; 3231 const streetNumber = get('street_number'); 3232 const streetName = get('route'); 3233 const state = get('administrative_area_level_1'); 3234 const zipcode = get('postal_code'); 3235 const addressLine2 = get('subpremise'); 3236 // explicit precedence for city 3237 const city = get('locality') || get('sublocality_level_1') || get('neighborhood'); 3238 if (streetNumber) structuredAddress.streetNumber = streetNumber; 3239 if (streetName) structuredAddress.streetName = streetName; 3240 if (city) structuredAddress.city = city; 3241 if (state) structuredAddress.state = state; 3242 if (zipcode) structuredAddress.zipcode = zipcode; 3243 if (addressLine2) structuredAddress.addressLine2 = addressLine2; 3244 return structuredAddress; 3245 } 3246 /** 3247 * Extract address and coordinates from Google Maps validation data 3248 * @param {Object} validatedAddressData - Google Maps validation result 3249 * @return {Object} - Object containing structuredAddress and coordinates 3250 */ _extractAddressAndCoordinates(validatedAddressData) { 3251 let structuredAddress = null; 3252 let coordinates = null; 3253 if (validatedAddressData?.result) { 3254 const { result: result } = validatedAddressData; 3255 // Extract structured address components 3256 if (result.address?.addressComponents) structuredAddress = this._transformAddressComponents(result.address.addressComponents); 3257 // Extract coordinates 3258 if (result.geocode?.location) coordinates = { 3259 latitude: result.geocode.location.latitude, 3260 longitude: result.geocode.location.longitude 3261 }; 3262 } 3263 return { 3264 structuredAddress: structuredAddress, 3265 coordinates: coordinates 3266 }; 3267 } 3268 /** 3269 * Filter out empty string values from an object, keeping only non-empty values 3270 * @param {Object} obj - Object to filter 3271 * @return {Object} - Filtered object without empty strings 3272 */ _filterEmptyStrings(obj) { 3273 const filtered = {}; 3274 for (const [key, value] of Object.entries(obj))if (value !== '' && value !== null && value !== undefined) filtered[key] = value; 3275 return filtered; 3276 } 3277 /** 3278 * Extract raw address from form data with priority fallback chain. 3279 * Order is critical to handle 38 home valuation templates with different field naming: 3280 * 3281 * IMPORTANT: contactForms.js (line 189) stores name="message" in comments_attributes[0].text 3282 * because 'message' is in DEFAULT_LEAD_FIELDS. Fields NOT in DEFAULT_LEAD_FIELDS go to content. 3283 * 3284 * Priority (most specific â most generic): 3285 * 1. address - Pattern 1: 9 templates (explicit address, stored in content) 3286 * 2. property-address - Pattern 3: 4 templates (dash variant with JS, stored in content) 3287 * 3. property_address - Pattern 4: 3 templates (underscore, stored in content - handles VanguardProperties!) 3288 * 4. Property_Address - Pattern 5: 1 template (capital P - TheProducer/HomeValuationRansomHouse, stored in content)
3289 * 5. comments_attributes[0].text - Pattern 2: ALL 17 templates with name="message" store HERE! 3290 * (e.g., Evolution/HomeValuation, TheProducer/HomeValuation, etc.) 3291 * 6. message - Pattern 6: 4 templates with JS-populated message (rare, checked last) 3292 * 7-8. homeValuationAddress, propertyAddress - Legacy/unknown formats 3293 * 3294 * Critical: Each field is cleaned BEFORE checking, so dropdown values are skipped and we try next field 3295 * 3296 * @param {Object} data - Form data 3297 * @return {string} - Raw address string (may contain trailing text like ", call time frame: ...") 3298 */ _getRawAddress(data) { 3299 const content = data.activity.content || {}; 3300 const comments = data.activity.comments_attributes?.[0]?.text; 3301 const possibleFields = [ 3302 content.address, 3303 content['property-address'], 3304 content.property_address, 3305 content.Property_Address, 3306 comments, 3307 content.message, 3308 content.homeValuationAddress, 3309 content.propertyAddress 3310 ]; 3311 return possibleFields.map((field)=>field && this._cleanAddressString(field)).find(Boolean) || ''; 3312 } 3313 /** 3314 * Logs lead-related events for monitoring 3315 * @param {string} eventType - Type of event 3316 * @param {Object} data - Form data 3317 * @param {Error} error - Optional error object 3318 */ _logLeadEvent(eventType, data, error = null) { 3319 const eventPayload = { 3320 event: eventType, 3321 companyId: this.config.companyId, 3322 websiteId: this.config.websiteId, 3323 timestamp: new Date().toISOString(), 3324 hasEmail: !!data.activity?.author_email, 3325 hasAddress: !!this._getRawAddress(data) 3326 }; 3327 if (error) { 3328 // Use userMessage (sanitized) instead of raw message to prevent PII exposure 3329 // userMessage is set by _getUserFriendlyErrorMessage() which provides safe messages 3330 eventPayload.errorMessage = error.userMessage || (error.status ? `Request failed with status ${error.status}` : 'An error occurred'); 3331 eventPayload.errorName = error.name; 3332 eventPayload.errorStatus = error.status; 3333 } 3334 // Log to console with structured format for log aggregation 3335 // eslint-disable-next-line no-console 3336 console.error(`[HomeValuation] ${eventType}`, JSON.stringify(eventPayload)); 3337 // If PostHog is available, send event for analytics 3338 // Wrap in try/catch to prevent SDK failures from blocking submissions 3339 if (this.window.posthog) try { 3340 this.window.posthog.capture(eventType, eventPayload); 3341 } catch (posthogError) { 3342 // eslint-disable-next-line no-console 3343 console.error('[HomeValuation] PostHog capture failed:', posthogError); 3344 } 3345 } 3346 /** 3347 * Maps error types to user-friendly messages 3348 * @param {Error} error - The error object 3349 * @returns {string} - User-friendly message 3350 */ _getUserFriendlyErrorMessage(error) { 3351 if (error.name === 'AbortError' || error.message?.includes('timeout')) return 'Connection timed out. Please try again.'; 3352 if (error.name === 'TypeError' && error.message?.includes('fetch')) return 'Unable to connect. Please check your internet connection and try again.'; 3353 if (error.status === 503 || error.status === 502 || error.status === 504) return 'Service temporarily unavailable. Please try again in a moment.'; 3354 if (error.status === 400) return 'Please check your information and try again.'; 3355 return 'Something went wrong. Please try again or contact us directly.'; 3356 } 3357 /** 3358 * Build formatted address string from structured address components 3359 * @param {Object} structuredAddress - Structured address object 3360 * @return {string} - Formatted address string 3361 */ _formatStructuredAddress(structuredAddress) { 3362 if (!structuredAddress || Object.keys(structuredAddress).length === 0) return ''; 3363 const parts = []; 3364 // Line 1: streetNumber streetName addressLine2 3365 const line1 = [ 3366 structuredAddress.streetNumber, 3367 structuredAddress.streetName, 3368 structuredAddress.addressLine2
3369 ].filter(Boolean).join(' '); 3370 parts.push(line1); 3371 // Line 2: city, state zipcode 3372 const cityState = [ 3373 structuredAddress.city, 3374 structuredAddress.state 3375 ].filter(Boolean).join(', '); 3376 const line2 = [ 3377 cityState, 3378 structuredAddress.zipcode 3379 ].filter(Boolean).join(' '); 3380 parts.push(line2); 3381 return parts.filter(Boolean).join(', '); 3382 } 3383 /** 3384 * Build home valuation data object 3385 * @param {Object} data - Form data 3386 * @param {string} homeValuationEstimate - Home valuation estimate 3387 * @param {Object} structuredAddress - Structured address object 3388 * @param {Object} coordinates - Coordinates object 3389 * @return {Object} - Home valuation data object 3390 */ _buildHomeValuationData(data, homeValuationEstimate, structuredAddress, coordinates) { 3391 // Build homeValuationAddress from structured address (validated by Google) if available 3392 // Format: streetNumber streetName, city, state zipcode, addressLine2 3393 const homeValuationAddress = this._formatStructuredAddress(structuredAddress) || this._getRawAddress(data); 3394 // Validate that we have an address before proceeding 3395 if (!homeValuationAddress) throw new Error('Unable to extract home valuation address from form data'); 3396 // Required fields that must always be included 3397 const requiredFields = { 3398 companyId: data.companyId, 3399 homeValuationAddress: homeValuationAddress, 3400 homeValuationEstimate: homeValuationEstimate ? new Intl.NumberFormat('en-US', { 3401 style: 'currency', 3402 currency: 'USD', 3403 maximumFractionDigits: 0, 3404 minimumFractionDigits: 0 3405 }).format(homeValuationEstimate) : null, 3406 websiteId: data.page.websiteId, 3407 sourceUrl: data.activity.source_url 3408 }; 3409 // Optional fields that will be filtered if empty 3410 const optionalFields = { 3411 leadEmailAddress: data.activity.author_email, 3412 leadFullName: data.activity.author_name, 3413 leadPhoneNumber: data.activity.author_phone, 3414 parcelId: data.activity.content?.parcelId, 3415 resourceId: data.page.pageMeta?.resourceId, 3416 pageId: data.page.pageId,
3417 sourceResource: data.page.pageMeta?.sourceResource, 3418 pageElementId: data.page.pageMeta?.pageElementId, 3419 formId: data.page.pageMeta?.formId, 3420 utmSource: data.activity.content?.utm_source, 3421 utmMedium: data.activity.content?.utm_medium, 3422 utmCampaign: data.activity.content?.utm_campaign, 3423 utmTerm: data.activity.content?.utm_term, 3424 utmContent: data.activity.content?.utm_content, 3425 utmId: data.activity.content?.utm_id, 3426 timeToSell: data.activity.content?.timeToSell, 3427 lookingToBuy: data.activity.content?.lookingToBuy, 3428 referrer: data.referrer, 3429 content: data.activity.content || {}, 3430 fields: data.fields || {} 3431 }; 3432 // Filter out empty strings from optional fields 3433 const filteredOptionalFields = this._filterEmptyStrings(optionalFields); 3434 return { 3435 ...requiredFields, 3436 ...filteredOptionalFields, 3437 // Add structured address and coordinates if they exist 3438 ...structuredAddress && { 3439 address: structuredAddress 3440 }, 3441 ...coordinates && { 3442 coordinates: coordinates 3443 } 3444 }; 3445 } 3446 /** 3447 * Validate address with Google Maps 3448 * @param {string} rawAddress - Raw address string 3449 * @returns {Promise<Object|null>} - Validated address data or null 3450 * @throws {Error} - If validation fails, error is thrown with userMessage 3451 */ async _validateAddressSafely(rawAddress) { 3452 if (!rawAddress) { 3453 // eslint-disable-next-line no-console 3454 console.error('Home valuation: No address found in form data'); 3455 return null; 3456 } 3457 try { 3458 return await this._validateAddressWithGoogleMaps(rawAddress); 3459 } catch (error) { 3460 // eslint-disable-next-line no-console 3461 console.error('Error validating address with Google Maps:', error); 3462 // Attach user-friendly message and throw so user sees the error 3463 error.userMessage = this._getUserFriendlyErrorMessage(error); 3464 throw error; 3465 } 3466 } 3467 /** 3468 * Get home valuation estimate 3469 * @param {Object} validatedAddressData - Validated address data 3470 * @returns {Promise<number|null>} - Home valuation estimate or null 3471 * @throws {Error} - If estimate fetch fails, error is thrown with userMessage 3472 */ async _getHomeValuationEstimateSafely(validatedAddressData) { 3473 try { 3474 return await this._getHomeValuationEstimate(validatedAddressData); 3475 } catch (error) { 3476 // eslint-disable-next-line no-console 3477 console.error('Error getting home valuation estimate:', error); 3478 // Attach user-friendly message and throw so user sees the error 3479 error.userMessage = this._getUserFriendlyErrorMessage(error); 3480 throw error; 3481 } 3482 } 3483 /** 3484 * Parse response text into payload object 3485 * @param {string} text - Response text 3486 * @returns {Object} - Parsed payload 3487 */ _parseResponsePayload(text) { 3488 try { 3489 return text ? JSON.parse(text) : {}; 3490 } catch { 3491 return { 3492 raw: text 3493 }; 3494 } 3495 } 3496 /** 3497 * Create error from failed response 3498 * @param {Object} payload - Response payload 3499 * @param {number} status - HTTP status code 3500 * @returns {Error} - Error object with status and payload 3501 */ _createResponseError(payload, status) { 3502 const errorMessage = payload && typeof payload === 'object' && Object.keys(payload).length ? payload.message || JSON.stringify(payload) : 'Request failed'; 3503 const error = new Error(errorMessage); 3504 // Preserve payload properties if it's an object 3505 if (payload && typeof payload === 'object' && Object.keys(payload).length) Object.assign(error, payload); 3506 // Preserve numeric HTTP status - must be set after Object.assign 3507 // to ensure it takes precedence over any status in payload 3508 error.status = status; 3509 return error; 3510 } 3511 /** 3512 * Submit lead to API endpoint 3513 * @param {string} leadRoute - API endpoint URL 3514 * @param {Object} homeValuationData - Data to submit 3515 * @returns {Promise<Object>} - Submission result 3516 */ async _submitLead(leadRoute, homeValuationData) { 3517 const controller = new AbortController(); 3518 const timeoutId = setTimeout(()=>controller.abort(), 10000); 3519 try { 3520 const response = await fetch(leadRoute, { 3521 method: 'POST', 3522 headers: { 3523 'Content-Type': 'application/json' 3524 }, 3525 body: JSON.stringify(homeValuationData), 3526 signal: controller.signal 3527 }); 3528 clearTimeout(timeoutId); 3529 const text = await response.text(); 3530 const payload = this._parseResponsePayload(text); 3531 if (!response.ok) throw this._createResponseError(payload, response.status); 3532 if (payload && payload.status === 'success' && payload.redirectUrl) { 3533 this.window.location.href = payload.redirectUrl; 3534 return { 3535 redirected: true, 3536 url: payload.redirectUrl 3537 }; 3538 } 3539 return payload; 3540 } catch (error) { 3541 clearTimeout(timeoutId); 3542 throw error; 3543 } 3544 } 3545 /** 3546 * Submit home valuation request with Google Maps validation 3547 * @param {Object} data 3548 * @return {Promise<Object>} 3549 */ async _submitHomeValuationRequest(data) { 3550 const { config: config } = this; 3551 // Use websiteApiGatewayUrl from config 3552 if (!config.websiteApiGatewayUrl) throw new Error('websiteApiGatewayUrl not configured for home valuation'); 3553 // Log submission started 3554 this._logLeadEvent('home_valuation_submission_started', data); 3555 try { 3556 // Validate address with Google Maps 3557 const rawAddress = this._getRawAddress(data); 3558 let validatedAddressData = null; 3559 try {
3560 validatedAddressData = await this._validateAddressSafely(rawAddress); 3561 } catch (error) { 3562 // Error already has userMessage from _validateAddressSafely 3563 this._logLeadEvent('home_valuation_address_validation_failed', data, error); 3564 throw error; 3565 } 3566 // Get home valuation estimate. 3567 // The estimate is best-effort: many valid properties (e.g. commercial 3568 // parcels or addresses without AVM coverage) have no estimate and the 3569 // estimate endpoint returns a non-OK status for them. A missing estimate 3570 // must never block lead capture, so we log the failure and continue with 3571 // a null estimate rather than aborting the whole submission. 3572 let homeValuationEstimate = null; 3573 try { 3574 homeValuationEstimate = await this._getHomeValuationEstimateSafely(validatedAddressData); 3575 } catch (error) { 3576 // Error already has userMessage from _getHomeValuationEstimateSafely 3577 this._logLeadEvent('home_valuation_estimate_failed', data, error); 3578 homeValuationEstimate = null; 3579 } 3580 // Extract structured address and coordinates from Google Maps validation 3581 const { structuredAddress: structuredAddress, coordinates: coordinates } = this._extractAddressAndCoordinates(validatedAddressData); 3582 const leadRoute = `${config.websiteApiGatewayUrl}${$2aefad83322125c9$var$homeValuationRoute}`; 3583 const homeValuationData = this._buildHomeValuationData(data, homeValuationEstimate, structuredAddress, coordinates); 3584 const result = await this._submitLead(leadRoute, homeValuationData); 3585 // Log success 3586 this._logLeadEvent('home_valuation_submission_success', data); 3587 return result; 3588 } catch (error) { 3589 // Ensure error has user-friendly message (may already be set by helper methods) 3590 if (!error.userMessage) error.userMessage = this._getUserFriendlyErrorMessage(error); 3591 this._logLeadEvent('home_valuation_submission_failed', data, error); 3592 throw error; 3593 } 3594 } 3595 /** 3596 * Validate address using Google Maps Address Validation API 3597 * @param {string} addressStr - The address string to validate 3598 * @returns {Promise<Object|null>} - Validated address data or null if validation fails 3599 */ async _validateAddressWithGoogleMaps(addressStr) { 3600 const { config: config, window: window } = this; 3601 // Ensure Google Maps API key is loaded 3602 let apiKey = config.googleMapsAPIKey; 3603 if (!apiKey && window.luxuryPresence?.mapApiLoader) apiKey = await window.luxuryPresence.mapApiLoader.getMapApiKey(); 3604 if (!apiKey) throw new Error('Google Maps API key not configured'); 3605 const controller = new AbortController(); 3606 const timeoutId = setTimeout(()=>controller.abort(), 10000); 3607 try { 3608 const response = await fetch(`https://addressvalidation.googleapis.com/v1:validateAddress?key=${apiKey}`, { 3609 method: 'POST', 3610 headers: { 3611 'Content-Type': 'application/json' 3612 }, 3613 body: JSON.stringify({ 3614 address: { 3615 addressLines: [ 3616 addressStr 3617 ] 3618 }, 3619 enableUspsCass: false 3620 }), 3621 signal: controller.signal 3622 }); 3623 clearTimeout(timeoutId); 3624 if (!response.ok) { 3625 const error = new Error(`Address validation failed: ${response.status}`); 3626 error.status = response.status; 3627 throw error; 3628 } 3629 return response.json(); 3630 } catch (error) { 3631 clearTimeout(timeoutId); 3632 throw error; 3633 } 3634 } 3635 /** 3636 * Check if structured address has all mandatory fields 3637 * @param {Object} structuredAddress - Structured address object 3638 * @return {boolean} 3639 */ _hasMandatoryAddressFields(structuredAddress) { 3640 return !!(structuredAddress.streetNumber && structuredAddress.streetName && structuredAddress.city && structuredAddress.state && structuredAddress.zipcode); 3641 } 3642 /** 3643 * Log missing mandatory address fields 3644 * @param {Object} structuredAddress - Structured address object 3645 */ _logMissingAddressFields(structuredAddress) { 3646 const missingFields = [];
3647 if (!structuredAddress.streetNumber) missingFields.push('streetNumber'); 3648 if (!structuredAddress.streetName) missingFields.push('streetName'); 3649 if (!structuredAddress.city) missingFields.push('city'); 3650 if (!structuredAddress.state) missingFields.push('state'); 3651 if (!structuredAddress.zipcode) missingFields.push('zipcode'); 3652 // eslint-disable-next-line no-console 3653 console.log('Home valuation estimate skipped - missing required fields:', missingFields.join(', '), 'Available fields:', Object.keys(structuredAddress).join(', ')); 3654 } 3655 /** 3656 * Build query string from structured address 3657 * @param {Object} structuredAddress - Structured address object 3658 * @return {string} 3659 */ _buildAddressQueryString(structuredAddress) { 3660 return Object.entries(structuredAddress).map(([key, value])=>`${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'); 3661 } 3662 /** 3663 * GET home valuation estimate 3664 * @param {string} address 3665 * @param {Object} validatedAddressData - Google Maps validated address data 3666 * @return {Promise<number|null>} 3667 */ async _getHomeValuationEstimate(validatedAddressData = null) { 3668 const { config: config } = this; 3669 if (!config.websiteApiGatewayUrl) throw new Error('websiteApiGatewayUrl not configured'); 3670 const base = `${config.websiteApiGatewayUrl}${$2aefad83322125c9$var$homeValuationRoute}`; 3671 // Check if we have validated address data 3672 if (!validatedAddressData?.result?.address?.addressComponents) return null; 3673 const structuredAddress = this._transformAddressComponents(validatedAddressData.result.address.addressComponents); 3674 // Check if all mandatory fields exist 3675 if (!this._hasMandatoryAddressFields(structuredAddress)) { 3676 this._logMissingAddressFields(structuredAddress); 3677 return null; 3678 } 3679 // Build URL with query string 3680 const qs = this._buildAddressQueryString(structuredAddress); 3681 const homeValURL = `${base}?${qs}`; 3682 const controller = new AbortController(); 3683 const timeoutId = setTimeout(()=>controller.abort(), 10000); 3684 try { 3685 const response = await fetch(homeValURL, { 3686 headers: { 3687 Accept: 'application/json' 3688 }, 3689 signal: controller.signal 3690 }); 3691 clearTimeout(timeoutId); 3692 if (!response.ok) { 3693 const error = new Error(`Home valuation estimate failed: ${response.status}`); 3694 error.status = response.status; 3695 throw error; 3696 } 3697 const data = await response.json(); 3698 return data?.valueDollars ?? null; 3699 } catch (error) { 3700 clearTimeout(timeoutId); 3701 // Re-throw to allow retry logic to handle it 3702 throw error; 3703 } 3704 } 3705} 3706 3707 3708const $e10bd00497be8876$export$97de66002300ed70 = 'middleName'; 3709// Default lead fields 3710const $e10bd00497be8876$var$DEFAULT_LEAD_FIELDS = [ 3711 'name', 3712 'firstName', 3713 'lastName', 3714 $e10bd00497be8876$export$97de66002300ed70, 3715 'email', 3716 'phone', 3717 'phoneNumber', 3718 'source', 3719 'message', 3720 'mlsId', 3721 'sourceUrl' 3722]; 3723class $e10bd00497be8876$export$3c5380623cf51249 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 3724 /** 3725 * Initialize Contact Form Controller at build time 3726 * @param { ConfigController } config 3727 * @param {Window} window 3728 * @param {Document} document 3729 */ constructor(config, window, document){ 3730 super(config, window, document); 3731 this.forms = []; 3732 this.homeValuationService = new (0, $2aefad83322125c9$export$2e2bcd8739ae039)(config, window, document); 3733 } 3734 /** 3735 * Initialize Contact Form Controller at run time 3736 * Attach handlers and events to DOM 3737 * @param {Object} options 3738 */ initialize(options = {}) { 3739 try { 3740 const { document: document } = this; 3741 const { selector: selector } = options; 3742 let forms = []; 3743 if (selector) forms = document.querySelectorAll(`${selector} form[data-type="contact-form"]`); 3744 else forms = document.querySelectorAll('form[data-type="contact-form"]');
3745 forms.forEach((form)=>{ 3746 this._attachSubmitHandler(form); 3747 // this._attachValidation(form); 3748 }); 3749 this.forms = this.forms.concat(forms); 3750 } catch (e) { 3751 // eslint-disable-next-line no-console 3752 console.log(e); 3753 } 3754 } 3755 /** 3756 * Controllers must implement a "destroy" method to be called 3757 * after page navigation to remove event handlers / cleanup 3758 */ destroy() { 3759 this.forms = []; 3760 } 3761 /** 3762 * Handle submit from global context 3763 * @param {HTMLFormElement} form 3764 */ submitForm(form) { 3765 this._handleSubmit(null, form).catch((e)=>console.error(e)); 3766 } 3767 /** 3768 * Attach submit event for form 3769 * @param {HTMLFormElement} contactForm 3770 */ _attachValidation(contactForm) { 3771 const { window: window } = this; 3772 const inputs = contactForm.querySelectorAll('input, select, textarea'); 3773 inputs.forEach((input)=>{ 3774 window.luxuryPresence.validation.applyFieldValidation(input); 3775 }); 3776 } 3777 /** 3778 * Attach submit event for form 3779 * @param {HTMLFormElement} contactForm 3780 */ _attachSubmitHandler(contactForm) { 3781 contactForm.addEventListener('submit', (e)=>this._handleSubmit(e, contactForm)); 3782 } 3783 /** 3784 * Extract and process form values 3785 * @param {HTMLFormElement} contactForm 3786 * @return {Object} - Processed form values 3787 */ _extractFormValues(contactForm) { 3788 const formData = new FormData(contactForm); 3789 const values = {}; 3790 const nameParts = []; 3791 const nameKeyRegex = /^name(?:-\d+)?$/; 3792 formData.forEach((value, key)=>{ 3793 if (typeof value === 'string') { 3794 const curr = value.trim(); 3795 if (nameKeyRegex.test(key) && curr) nameParts.push(curr); 3796 const prev = values[key]; 3797 values[key] = prev ? `${prev} ${curr}` : curr; 3798 } else values[key] = value; 3799 }); 3800 if (nameParts.length) values.name = nameParts.join(' ').trim(); 3801 else if (!values.name && values.firstName) { 3802 values.name = values.firstName; 3803 if (values.lastName) values.name += ` ${values.lastName}`; 3804 } 3805 return values; 3806 } 3807 /** 3808 * Build submission data object 3809 * @param {Object} values - Form values 3810 * @param {Object} fields - Form fields 3811 * @param {HTMLFormElement} contactForm - Form element 3812 * @return {Object} - Submission data 3813 */ _buildSubmissionData(values, fields, contactForm) { 3814 const { window: window, config: config } = this; 3815 const content = Object.keys(values).filter((key)=>!$e10bd00497be8876$var$DEFAULT_LEAD_FIELDS.includes(key)).reduce((result, key)=>{ 3816 // eslint-disable-next-line 3817 result[key] = values[key]; 3818 return result; 3819 }, {}); 3820 const { pageId: pageId, companyId: companyId, websiteId: websiteId, pageMeta: pageMeta } = config; 3821 const utm = window.localStorage.getItem('utm_vars') || '{}'; 3822 const referrer = window.localStorage.getItem('referrer') || ''; 3823 const formId = this._getFormId(contactForm); 3824 return { 3825 activity: { 3826 author_email: values.email, 3827 author_name: values.name, 3828 author_phone: values.phone || values.phoneNumber, 3829 activity_source: values.source || 'CONTACT_INQUIRY', 3830 comments_attributes: [ 3831 { 3832 text: values.message || undefined 3833 } 3834 ], 3835 source_url: window.location.href, 3836 content: { 3837 ...content, 3838 ...JSON.parse(utm) 3839 } 3840 }, 3841 page: { 3842 pageId: pageId, 3843 companyId: companyId, 3844 websiteId: websiteId, 3845 pageMeta: { 3846 ...pageMeta, 3847 formId: formId 3848 } 3849 }, 3850 companyId: companyId, 3851 referrer: referrer, 3852 fields: fields 3853 }; 3854 } 3855 /** 3856 * Handle successful form submission 3857 * @param {HTMLFormElement} contactForm - Form element 3858 */ _handleSubmissionSuccess(contactForm) { 3859 const { window: window } = this; 3860 const closeDelay = contactForm.dataset.delay || (0, $a3e97e89bbc2a366$export$f037eeffb5561205); 3861 contactForm.classList.remove('loading'); 3862 contactForm.classList.remove('error'); 3863 contactForm.classList.add('success'); 3864 // TODO: Review producer and classic to deprecate "hide" 3865 contactForm.querySelectorAll('.success').forEach((el)=>el.classList.remove('hide')); 3866 contactForm.dispatchEvent(new Event('formsubmitted')); 3867 // Any successful lead submit credits the Google Ads lead conversion 3868 // (reuses the existing `generate_lead` action), once per session. 3869 (0, $3ec2bf3965f87ecc$export$e70565180c0e6950)(this.window, this.document); 3870 setTimeout(()=>{ 3871 window.lpUI.hideClosestModal(contactForm); 3872 contactForm.reset(); 3873 window.lpUI.sideMenuHide(); 3874 contactForm.querySelectorAll('.success').forEach((el)=>el.classList.add('hide')); 3875 contactForm.classList.remove('success'); 3876 }, closeDelay); 3877 } 3878 /** 3879 * Submit Contact Form Handler 3880 * @param {Event} e 3881 * @param {HTMLFormElement} contactForm 3882 * @return {Promise<Object>} 3883 */ async _handleSubmit(e, contactForm) { 3884 if (e) e.preventDefault(); 3885 if (contactForm.classList.contains('loading')) // Form already submitting 3886 return; 3887 // Hide any previous error message and clear error state 3888 this._hideSubmissionError(contactForm); 3889 contactForm.classList.remove('error'); 3890 contactForm.classList.add('loading'); 3891 try { 3892 // Extract form values first (before async operations) 3893 const values = this._extractFormValues(contactForm); 3894 // TODO: HoneyPot should still send request 3895 if (values.middleName) { 3896 contactForm.classList.remove('loading'); 3897 return; 3898 } 3899 const fields = this._getFields(contactForm); 3900 const data = this._buildSubmissionData(values, fields, contactForm); 3901 await this._submitLeadRequest(data); 3902 this._sendGAEvent(data); 3903 this._handleSubmissionSuccess(contactForm); 3904 } catch (err) { 3905 // eslint-disable-next-line no-console 3906 console.error('Form submission failed:', err); 3907 contactForm.dispatchEvent(new Event('formsubmiterror')); 3908 contactForm.classList.remove('loading'); 3909 contactForm.classList.add('error'); 3910 // Show user-friendly error message if available (from home valuation service)
3911 if (err.userMessage) this._showSubmissionError(contactForm, err.userMessage); 3912 else this._showSubmissionError(contactForm, 'Something went wrong. Please try again.'); 3913 } 3914 } 3915 /** 3916 * Alias anonymous user with canonical ID using event bus 3917 * Links the user's anonymous browsing session to their canonical identity 3918 * @param {Object} data - Form submission data 3919 * @private 3920 */ _aliasUserWithEventBus(data) { 3921 try { 3922 // Check if event bus library and required methods are available 3923 if (!this.window.eventBusProvider?.alias || !this.window.eventBusProvider?.isIdentified || !this.window.eventBusProvider?.getDistinctId || !this.window.LuxuryPresenceEventBus?.generateUUIDv5FromCompanyEmail) return; // Event bus or required methods not available 3924 // Skip if user is already identified 3925 if (this.window.eventBusProvider.isIdentified()) { 3926 console.log('[EventBus] User already identified, skipping alias'); 3927 return; 3928 } 3929 const email = data.activity?.author_email; 3930 const { companyId: companyId } = this.config; 3931 if (!email || !companyId) { 3932 console.warn('[EventBus] Missing required data for user alias'); 3933 return; 3934 } 3935 // Get the anonymous distinct ID from PostHog 3936 const anonId = this.window.eventBusProvider.getDistinctId(); 3937 if (!anonId) { 3938 console.warn('[EventBus] No anonymous ID available for alias'); 3939 return; 3940 } 3941 // Generate deterministic canonical ID from company + email 3942 const canonicalId = this.window.LuxuryPresenceEventBus.generateUUIDv5FromCompanyEmail(companyId, email); 3943 // Create alias linking anonymous ID to canonical ID 3944 this.window.eventBusProvider.alias({ 3945 anonId: anonId, 3946 canonicalId: canonicalId 3947 }); 3948 console.log('[EventBus] User aliased with canonical ID'); 3949 } catch (error) { 3950 // Never block form submission due to analytics errors 3951 console.error('[EventBus] User alias failed:', error); 3952 } 3953 } 3954 /** 3955 * Send Lead Request 3956 * @param {Object} data 3957 * @return {Promise<Object>} 3958 */ async _submitLeadRequest(data) { 3959 const { config: config } = this; 3960 // Alias user with event bus before submitting the lead 3961 this._aliasUserWithEventBus(data); 3962 if (config.myhomeDashboardEnabled && (data.activity?.activity_source === 'HOME_VALUATION' || data.activity?.activity_source === 'HOME_VALUE')) return this.homeValuationService._submitHomeValuationRequest(data); 3963 const leadRoute = `${config.leadIngesterUrl}/api/v1/leads`; 3964 return fetch(leadRoute, { 3965 method: 'POST', 3966 headers: { 3967 'Content-Type': 'application/json' 3968 }, 3969 body: JSON.stringify(data) 3970 }).then((response)=>{ 3971 if (!response.ok) return response.json().then((error)=>{ 3972 throw error; 3973 }); 3974 return response.json(); 3975 }); 3976 } 3977 /** 3978 * Send GA event 3979 * @param {Object} data 3980 */ _sendGAEvent(data) { 3981 const { document: document } = this; 3982 let event = { 3983 hitType: 'event', 3984 eventCategory: 'button', 3985 eventAction: 'click' 3986 }; 3987 switch(data.activity.activity_source){ 3988 case 'NEWSLETTER_SIGNUP': 3989 event.eventLabel = 'Newsletter'; 3990 document.sendGoogleTagManagerEvent('event', 'newsletter_signup'); 3991 break; 3992 case 'HOME_SEARCH': 3993 event.eventLabel = 'HomeSearch'; 3994 document.sendGoogleTagManagerEvent('event', 'home_search'); 3995 break; 3996 case 'HOME_VALUE': 3997 case 'HOME_VALUATION': 3998 event.eventLabel = 'HomeValue'; 3999 document.sendGoogleTagManagerEvent('event', 'home_valuation'); 4000 break; 4001 case 'EBOOK': 4002 event.eventLabel = 'Ebook'; 4003 document.sendGoogleTagManagerEvent('event', 'ebook_download'); 4004 break; 4005 case 'CONTACT_INQUIRY': 4006 default: 4007 // for contact forms, Marketing has requested that they see a page-view of 'thank-you' as indication of success 4008 // Note that this will break if we have actual page with url of /thank-you 4009 event = { 4010 hitType: 'pageview', 4011 page: '/thank-you' 4012 }; 4013 document.sendGoogleTagManagerEvent('event', 'contact_inquiry'); 4014 break; 4015 } 4016 document.sendGoogleAnalyticsEvent(event); 4017 } 4018 /** 4019 * Gather fields / schema for form, used for display in CRM 4020 * @param {HTMLFormElement} form 4021 * @return {Object} 4022 */ _getFields(form) { 4023 const inputs = form.querySelectorAll('input, select, textarea'); 4024 const fields = {};
4025 inputs.forEach((input)=>{ 4026 const { id: id, name: name, type: inputType } = input; 4027 if (name === $e10bd00497be8876$export$97de66002300ed70) // Honeypot continue 4028 return true; 4029 let label = ''; 4030 if (id) { 4031 const labelNode = form.querySelector(`label[for='${id}']`); 4032 if (labelNode) label = labelNode.textContent.trim(); 4033 else if (input.placeholder) label = input.placeholder.trim(); 4034 } 4035 fields[name] = { 4036 label: label, 4037 type: input.tagName, 4038 inputType: input.tagName === 'INPUT' ? inputType : 'text' 4039 }; 4040 }); 4041 return fields; 4042 } 4043 /** 4044 * Figure out relevant section or div ID for form 4045 * @param {HTMLFormElement} form 4046 * @return {string} 4047 */ _getFormId(form) { 4048 const SELECTORS = "section[id^='section-'], footer[id], .modal[id^='modal-']"; 4049 const parent = form.closest(SELECTORS); 4050 return parent?.id ? this._cleanFormId(parent.id) : ''; 4051 } 4052 /** 4053 * Remove prefix from formID 4054 * @param {string} formId 4055 * @return {string} 4056 */ _cleanFormId(formId) { 4057 const PREFIXES = [ 4058 'section-', 4059 'modal-' 4060 ]; 4061 for (const prefix of PREFIXES){ 4062 if (formId.startsWith(prefix)) return formId.substring(prefix.length); 4063 } 4064 return formId; 4065 } 4066 /** 4067 * Show submission error message on form 4068 * @param {HTMLFormElement} form 4069 * @param {string} message 4070 */ _showSubmissionError(form, message) { 4071 const errorEl = form.querySelector('.submission-error-message'); 4072 if (errorEl) { 4073 errorEl.textContent = message || 'Something went wrong. Please try again.'; 4074 errorEl.style.display = 'block'; 4075 } 4076 } 4077 /** 4078 * Hide submission error message on form 4079 * @param {HTMLFormElement} form 4080 */ _hideSubmissionError(form) { 4081 const errorEl = form.querySelector('.submission-error-message'); 4082 if (errorEl) errorEl.style.display = 'none'; 4083 } 4084} 4085 4086 4087 4088const $ea6901fdf47e0ec1$var$CALLBACK = '__googleMapsCallback'; 4089const $ea6901fdf47e0ec1$var$GOOGLE_MAPS_URL = 'https://maps.googleapis.com/maps/api/js'; 4090const $ea6901fdf47e0ec1$export$76299006759be400 = 1024; 4091const $ea6901fdf47e0ec1$var$KEY_FETCH_ATTEMPTS = 3; 4092const $ea6901fdf47e0ec1$var$KEY_RETRY_BASE_DELAY_MS = 300; 4093const $ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG = 'lp_map_key_failed'; 4094class $ea6901fdf47e0ec1$export$3c19195edca3fa5c extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 4095 /** 4096 * Initialize Button Controller at build time 4097 * @param { ConfigController } config 4098 * @param {Window} window 4099 * @param {Document} document 4100 */ constructor(config, window, document){ 4101 super(config, window, document); 4102 this.retries = 3; 4103 this.callbacks = []; 4104 this.id = `__googleMapsScriptId${Date.now()}`; 4105 this._apiKey = ''; 4106 this.reset(); 4107 } 4108 /** 4109 * Set the Google Maps api key 4110 * @param {string} apiKey 4111 */ set apiKey(apiKey) { 4112 this._apiKey = apiKey; 4113 this.config.setGoogleMapsAPIKey(apiKey); 4114 } 4115 /** 4116 * Get the Google Maps api key 4117 * @return {string} 4118 */ get apiKey() { 4119 return this._apiKey; 4120 } 4121 /** 4122 * Reset the loader state. 4123 */ reset() { 4124 this.deleteScript(); 4125 this.done = false; 4126 this.loading = false; 4127 this.failed = false; 4128 this.errors = []; 4129 this.onerrorEvent = null; 4130 } 4131 /** 4132 * Destroy 4133 */ destroy() { 4134 this.reset(); 4135 } 4136 /** 4137 * get map api Key 4138 * @return {Promise<string>} 4139 */ async getMapApiKey() { 4140 if (this.apiKey) return this.apiKey; 4141 const hadPreviousFailure = this._hadPreviousFailure(); 4142 let recoveryReported = false; 4143 for(let attempt = 1; attempt <= $ea6901fdf47e0ec1$var$KEY_FETCH_ATTEMPTS; attempt += 1){ 4144 const reportRecovery = hadPreviousFailure && !recoveryReported; 4145 try { 4146 // eslint-disable-next-line no-await-in-loop 4147 const response = await fetch(this._getMapKeyUrl(attempt, reportRecovery));
4148 // The request reached the server, so a recovery marker on it was 4149 // delivered and must not be repeated on later attempts or pages. A 4150 // rejected fetch never arrived, so the marker moves to the next 4151 // attempt. 4152 recoveryReported = recoveryReported || reportRecovery; 4153 this._setFailureFlag(false); 4154 if (!response.ok) throw new Error(`Failed to fetch API key: ${response.status}`); 4155 // eslint-disable-next-line no-await-in-loop 4156 const code = await response.text(); 4157 if (!code) return ''; 4158 this.apiKey = code; 4159 return this.apiKey; 4160 } catch (e) { 4161 // eslint-disable-next-line no-console 4162 console.error(e); 4163 if (attempt < $ea6901fdf47e0ec1$var$KEY_FETCH_ATTEMPTS) // eslint-disable-next-line no-await-in-loop 4164 await this._delay($ea6901fdf47e0ec1$var$KEY_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1)); 4165 } 4166 } 4167 this._setFailureFlag(true); 4168 return ''; 4169 } 4170 /** 4171 * Build the map key request url. Retries carry their attempt number, and a 4172 * single request per session carries the recovery marker, so both are 4173 * countable in existing request logs without new infrastructure. 4174 * @param {number} attempt 1-based attempt number 4175 * @param {boolean} reportRecovery tag this request as following a session 4176 * in which every attempt failed 4177 * @return {string} 4178 */ _getMapKeyUrl(attempt, reportRecovery) { 4179 const params = []; 4180 if (attempt > 1) params.push(`attempt=${attempt}`); 4181 if (reportRecovery) params.push('recovered_after_failure=1'); 4182 const query = params.length ? `?${params.join('&')}` : ''; 4183 return `${this._getBaseUrl()}/api/v1/map${query}`; 4184 } 4185 /** 4186 * Whether an earlier attempt in this session exhausted all retries. 4187 * @return {boolean} 4188 */ _hadPreviousFailure() { 4189 try { 4190 return this.window.sessionStorage.getItem($ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG) === '1'; 4191 } catch (e) { 4192 // Storage can throw when disabled (private browsing); absence of the 4193 // flag is the safe default. 4194 return false; 4195 } 4196 } 4197 /** 4198 * Record or clear the session-level key fetch failure flag. 4199 * @param {boolean} failed 4200 */ _setFailureFlag(failed) { 4201 try { 4202 if (failed) this.window.sessionStorage.setItem($ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG, '1'); 4203 else this.window.sessionStorage.removeItem($ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG); 4204 } catch (e) { 4205 // Storage unavailable - reporting is best effort, never fatal. 4206 } 4207 } 4208 /** 4209 * @param {number} ms 4210 * @return {Promise} 4211 */ _delay(ms) { 4212 return new Promise((resolve)=>{ 4213 this.window.setTimeout(resolve, ms); 4214 }); 4215 } 4216 /** 4217 * CreateUrl returns the Google Maps JavaScript API script url ]. 4218 * @return {string} 4219 */ async createUrl() { 4220 const apiKey = await this.getMapApiKey(); 4221 // Google Maps loads successfully without a key and then fails at call time 4222 // with NoApiKeys, which produces a broken map and no load error. Refuse 4223 // instead, so the failure surfaces to the caller. 4224 if (!apiKey) throw new Error('Refusing to load Google Maps without an API key'); 4225 let url = $ea6901fdf47e0ec1$var$GOOGLE_MAPS_URL; 4226 url += `?callback=${$ea6901fdf47e0ec1$var$CALLBACK}`; 4227 url += `&key=${apiKey}`; 4228 url += `&libraries=places`; 4229 return url; 4230 } 4231 /** 4232 * Set the script on document. 4233 */ async setScript() { 4234 if (this.document.getElementById(this.id)) { 4235 this.callback(); 4236 return; 4237 } 4238 let url; 4239 try { 4240 url = await this.createUrl(); 4241 } catch (e) { 4242 // eslint-disable-next-line no-console 4243 console.error(e); 4244 this.failed = true; 4245 this.loading = false; 4246 this.onerrorEvent = e; 4247 this.callback(); 4248 return; 4249 } 4250 const script = this.document.createElement('script'); 4251 script.id = this.id; 4252 script.type = 'text/javascript'; 4253 script.src = url; 4254 script.onerror = this.loadErrorCallback.bind(this); 4255 script.defer = true; 4256 script.async = true; 4257 this.document.head.appendChild(script); 4258 } 4259 /** 4260 * Function to be called if script tag fails 4261 * @param {Error} e 4262 */ loadErrorCallback(e) { 4263 this.errors.push(e); 4264 if (this.errors.length <= this.retries) {
4265 const delay = this.errors.length * 2 ** this.errors.length; 4266 // eslint-disable-next-line no-console 4267 console.log(`Failed to load Google Maps script, retrying in ${delay} ms.`); 4268 setTimeout(()=>{ 4269 this.deleteScript(); 4270 this.setScript().catch((e)=>console.error(e)); 4271 }, delay); 4272 } else { 4273 this.failed = true; 4274 this.onerrorEvent = e; 4275 this.callback(); 4276 } 4277 } 4278 /** 4279 * Delete the script tag 4280 */ deleteScript() { 4281 const script = this.document.getElementById(this.id); 4282 if (script) script.remove(); 4283 } 4284 /** 4285 * Load the Google Maps JavaScript API script and return a Promise. 4286 * @return {Promise} 4287 */ load() { 4288 return this.loadPromise(); 4289 } 4290 /** 4291 * Load the Google Maps JavaScript API script and return a Promise. 4292 * @return {Promise} 4293 */ loadPromise() { 4294 return new Promise((resolve, reject)=>{ 4295 this.loadCallback((err)=>{ 4296 if (!err) resolve(); 4297 else reject(err); 4298 }); 4299 }); 4300 } 4301 /** 4302 * Load the Google Maps JavaScript API script with a callback. 4303 * @param {Function<Event>} fn 4304 */ loadCallback(fn) { 4305 this.callbacks.push(fn); 4306 this.execute(); 4307 } 4308 /** 4309 * Sets the callback function that will be sent as part of the script URL. 4310 */ setCallback() { 4311 this.window.__googleMapsCallback = this.callback.bind(this); 4312 } 4313 /** 4314 * Reset if failed 4315 */ resetIfRetryingFailed() { 4316 if (this.failed) this.reset(); 4317 } 4318 /** 4319 * This is the function that we set the callback parameter to. 4320 */ callback() { 4321 this.done = true; 4322 this.loading = false; 4323 this.callbacks.forEach((cb)=>{ 4324 cb(this.onerrorEvent); 4325 }); 4326 this.callbacks = []; 4327 } 4328 /** 4329 * Set the script a if needed; set the callback 4330 */ execute() { 4331 if (this.window.google && this.window.google.maps && this.window.google.maps.version) // Google Maps already loaded 4332 this.callback(); 4333 this.resetIfRetryingFailed(); 4334 if (this.done) this.callback(); 4335 else if (this.loading) ; 4336 else { 4337 this.loading = true; 4338 this.setCallback(); 4339 this.setScript().catch((e)=>console.error(e)); 4340 } 4341 } 4342 /** 4343 * get base url based on current config 4344 * @return {string} 4345 */ _getBaseUrl() { 4346 // Special handling for page builder since no wag available 4347 const { isBuilder: isBuilder, websiteApiGatewayUrl: websiteApiGatewayUrl } = this.config; 4348 return isBuilder ? websiteApiGatewayUrl : ''; 4349 } 4350 /** 4351 * Resize static map requests to the max 1024px while preserving aspect ratio 4352 * @param {number} width 4353 * @param {number} height 4354 * @return {{width, height}} 4355 */ resizeStaticMapDimensions(width, height) { 4356 if (width <= $ea6901fdf47e0ec1$export$76299006759be400 && height <= $ea6901fdf47e0ec1$export$76299006759be400) return { 4357 width: width, 4358 height: height 4359 }; 4360 // Size param ignored if dimensions exceed STATIC_MAP_MAX_DIM 4361 const ratio = Math.min($ea6901fdf47e0ec1$export$76299006759be400 / width, $ea6901fdf47e0ec1$export$76299006759be400 / height); 4362 return { 4363 width: parseInt(width * ratio), 4364 height: parseInt(height * ratio) 4365 }; 4366 } 4367 /** 4368 * Convert theme to static api param object 4369 * @param {Object} theme 4370 * @return {Object} 4371 */ convertThemeToStaticApiUrl(theme) { 4372 // https://developers.google.com/maps/documentation/maps-static/style-reference 4373 // Google Maps Static API uses a special syntax for it's urls based on the interactive map styles 4374 return theme.map((t)=>{ 4375 const styles = t.stylers.reduce((acc, s)=>{ 4376 const visibility = s.visibility ? `visibility:${s.visibility}` : ''; 4377 const color = s.color ? `color:${s.color.replace('#', '0x')}` : ''; 4378 const lightness = s.lightness ? `lightness:${s.lightness}` : ''; 4379 return `${acc}|${visibility}${color}${lightness}`; 4380 }, ''); 4381 const element = t.elementType ? `|element:${t.elementType}` : ''; 4382 return `feature:${t.featureType}${element}${styles}`; 4383 }); 4384 } 4385 /** 4386 * generate digital signature for url 4387 * @param {string} queryString to sign 4388 * @return {Promise<string>} digitally signed url 4389 */ async getMapApiSignedUrl(queryString) { 4390 try { 4391 const response = await fetch(`${this._getBaseUrl()}/api/v1/map/signature?${queryString}`); 4392 if (!response.ok) throw new Error('Failed to fetch signed URL'); 4393 const { url: url } = await response.json(); 4394 return url; 4395 } catch (e) { 4396 // eslint-disable-next-line no-console 4397 console.error(e); 4398 return ''; 4399 } 4400 } 4401 /** 4402 * Generate static map url 4403 * @param {number} lat 4404 * @param {number} lng 4405 * @param {number} zoom 4406 * @param {Object} theme 4407 * @param {number} srcWidth 4408 * @param {number} srcHeight 4409 * @return {string} 4410 */ generateStaticMapUrl(lat, lng, zoom, theme, srcWidth, srcHeight) {
4411 const baseUrl = 'https://maps.googleapis.com/maps/api/staticmap'; 4412 const { width: width, height: height } = this.resizeStaticMapDimensions(srcWidth, srcHeight); 4413 const query = { 4414 center: `${lat},${lng}`, 4415 zoom: zoom, 4416 scale: 2, 4417 size: `${width}x${height}`, 4418 key: this.apiKey 4419 }; 4420 if (theme) query.style = this.convertThemeToStaticApiUrl(theme); 4421 const params = new URLSearchParams(); 4422 Object.entries(query).forEach(([key, value])=>{ 4423 if (Array.isArray(value)) value.forEach((v)=>params.append(key, v.toString())); 4424 else params.append(key, value.toString()); 4425 }); 4426 return `${baseUrl}?${params.toString()}`; 4427 } 4428 /** 4429 * Generate static map url with digital signature 4430 * @param {Object} { 4431 * srcWidth {number}, required 4432 * srcHeight {number}, required 4433 * theme {array}, 4434 * center: `${lat},${lng}`, required 4435 * zoom: number, required 4436 * markers: `${lat},${lng}`, 4437 * scale: number, 4438 * otherQueryParams... (these must match what is compatible with google maps static api query params) 4439 * } 4440 * @return {Promise<string>} digitally signed url 4441 */ async generateDigitallySignedStaticMapUrl({ srcWidth: srcWidth, srcHeight: srcHeight, theme: theme, ...query }) { 4442 const { width: width, height: height } = this.resizeStaticMapDimensions(srcWidth, srcHeight); 4443 const queryParams = { 4444 ...query, 4445 size: `${width}x${height}` 4446 }; 4447 if (theme) queryParams.style = this.convertThemeToStaticApiUrl(theme); 4448 const params = new URLSearchParams(); 4449 Object.entries(queryParams).forEach(([key, value])=>{ 4450 if (Array.isArray(value)) value.forEach((v)=>params.append(key, v.toString())); 4451 else params.append(key, value.toString()); 4452 }); 4453 const queryString = params.toString(); 4454 try { 4455 // fetch digitally signed url 4456 return await this.getMapApiSignedUrl(queryString); 4457 } catch (e) { 4458 console.error(e); 4459 return ''; 4460 } 4461 } 4462} 4463 4464 4465/* eslint-disable import/prefer-default-export */ 4466 4467class $0a0ad49f13c0b8fd$export$ba9afeb75f20f616 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 4468 // constructor is not needed as it is inherited from BaseController 4469 /** 4470 * Controllers must implement a "destroy" method to be called 4471 * after page navigation to remove event handlers / cleanup 4472 */ destroy() {} 4473 /** 4474 * Places (re-places) a value into the query string under specified key 4475 * or removes it if new value is null or undefined 4476 * @param {string} key 4477 * @param {string|null|undefined|object|array} value 4478 * @param {string} url - defaults to window.location.href 4479 * @return {string} 4480 */ // eslint-disable-next-line sonarjs/cognitive-complexity 4481 updateQueryString(key, value, url) { 4482 // https://stackoverflow.com/questions/5999118/how-can-i-add-or-update-a-query-string-parameter 4483 if (!url) // eslint-disable-next-line 4484 url = this.window.location.href; 4485 let re = new RegExp(`([?&])${key}=.*?(&|#|$)`, 'i'); 4486 let replacement = ''; 4487 if (typeof value !== 'undefined' && value !== null) { 4488 if (Array.isArray(value)) { 4489 if (value.length) replacement = this.serializeArray(key, value); 4490 } else if (typeof value === 'object') { 4491 re = new RegExp(`([?&])${key}\\[[^=]*\\]=.*?(&|#|$)`, 'i'); 4492 replacement = this.serializeObj(value, '', key); 4493 } else replacement = `${key}=${encodeURIComponent(value)}`; 4494 } 4495 const hash = url.split('#'); 4496 let result = hash[0]; 4497 if (re.test(url)) { 4498 let clean = result; 4499 replacement = replacement ? `$1${replacement}$2` : '$1'; 4500 while(re.test(clean)){ 4501 result = clean.replace(re, replacement); 4502 clean = clean.replace(re, '$1'); 4503 } 4504 result = result.replace(/(&|\?)$/, ''); 4505 } else if (replacement) { 4506 const separator = result.indexOf('?') !== -1 ? '&' : '?'; 4507 result += `${separator}${replacement}`; 4508 } 4509 if (typeof hash[1] !== 'undefined' && hash[1] !== null) result += `#${hash[1]}`; 4510 return result; 4511 } 4512 /** 4513 * Returns variable from query string specified by parameter name 4514 * @param {string} name 4515 * @param {string} url defaults to window.location.href 4516 * @return {string|null} 4517 */ getParameterByName(name, url) { 4518 if (!url) // eslint-disable-next-line 4519 url = this.window.location.href; 4520 // eslint-disable-next-line 4521 name = name.replace(/[[\]]/g, '\\$&'); 4522 const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); 4523 let results = Array.from(RegExp.prototype[Symbol.matchAll].call(regex, url)).flat(); 4524 // check for object like syntax where the last value can be an array eg. advancedFilters[query][statusIds][in][0] or advancedFilters[query][city] 4525 if (!results.length) { 4526 const objRegex = new RegExp(`[?&]${name}(\\[.*?\\])=(.*?)(?=&|#|$)`, 'g'); 4527 results = Array.from(RegExp.prototype[Symbol.matchAll].call(objRegex, url)).flat(); 4528 return this._parseParamToObject(results, name === 'advancedFilters'); 4529 } 4530 // For multiple param values, eg arrays 4531 /* Results from regex match all come in this form: 4532 [ '&advancedFilters[query][statusIds][in]=uuid-segundo-123', '[query][statusIds][in]', 'uuid-segundo-123' ] 4533 So using every third value will be the actual value and the second value will be the path 4534 */ if (results.length > 3) return results.reduce((acc, value, index)=>{ 4535 if ((index + 1) % 3 === 0) acc.push(decodeURIComponent(value.replace(/\+/g, ' '))); 4536 return acc; 4537 }, []); 4538 if (!results[2]) return ''; 4539 return decodeURIComponent(results[2].replace(/\+/g, ' ')); 4540 } 4541 /** 4542 * Generates section specific key to store page number in the URL 4543 * @param {string} sectionDomId 4544 * @return {string} 4545 */ makePageKey(sectionDomId) { 4546 return sectionDomId.replace('section-', '').replace(/-/g, ''); 4547 } 4548 /** 4549 * Generates specific key to store parameter in the URL 4550 * uses prevsiouly calculated baseKey for section specific parameters 4551 * @param {Object} formParam 4552 * @param {string} baseKey pre-calculated base for section specific parameters 4553 * @return {string} 4554 */ makeParamKey(formParam, baseKey) { 4555 return formParam.global ? formParam.urlKey : `${baseKey}-${formParam.urlKey}`; 4556 } 4557 /** 4558 * Gets a set of parameters from window query string 4559 * always returns value of "page" parameter if present 4560 * @param {Object[]} formConfig 4561 * @param {string} sectionDomId 4562 * @return {Object} 4563 */ deserializeParams(formConfig, sectionDomId) { 4564 const params = {}; 4565 const urlPageKey = this.makePageKey(sectionDomId); 4566 const page = this.getParameterByName(urlPageKey); 4567 if (page) params.page = parseInt(page); 4568 if (Array.isArray(formConfig)) formConfig.forEach((formParam)=>{
4569 const key = this.makeParamKey(formParam, urlPageKey); 4570 let urlValue = this.getParameterByName(key); 4571 if (formParam.type === 'int') { 4572 urlValue = parseInt(urlValue); 4573 // eslint-disable-next-line 4574 if (!isFinite(urlValue)) urlValue = null; 4575 } else if (formParam.type === 'bool' || formParam.type === 'boolean') urlValue = // eslint-disable-next-line 4576 urlValue === 'true' ? true : urlValue === 'false' ? false : null; 4577 else if (formParam.type === 'json') try { 4578 urlValue = JSON.parse(urlValue); 4579 } catch (e) { 4580 // no need to do anything 4581 } 4582 params[formParam.formKey || formParam.param] = urlValue; 4583 }); 4584 return params; 4585 } 4586 /** 4587 * Serializes set of parameters defined by formConfig into the URL 4588 * adding or replacing or removing required parameters 4589 * @param {Object[]} formConfig 4590 * @param {string} sectionDomId 4591 * @param {Object} params 4592 * @return {string} 4593 */ serializeParams(formConfig, sectionDomId, params) { 4594 let result = this.window.location.href; 4595 const urlPageKey = this.makePageKey(sectionDomId); 4596 result = this.updateQueryString(urlPageKey, params.page, result); 4597 if (Array.isArray(formConfig)) formConfig.forEach((formParam)=>{ 4598 const key = this.makeParamKey(formParam, urlPageKey); 4599 let value = params[formParam.formKey || formParam.param]; 4600 if (formParam.type === 'json' && value !== null && typeof value !== 'undefined') value = JSON.stringify(value); 4601 result = this.updateQueryString(key, value, result); 4602 }); 4603 return result; 4604 } 4605 /** 4606 * Formats small number for slider values 4607 * @param {number} value 4608 * @param {string} currency 4609 * @return {string} 4610 */ formatSliderAtom(value, currency = '') { 4611 const formattedValue = Number.isInteger(value) ? value : value.toFixed(2); 4612 return currency + formattedValue; 4613 } 4614 /** 4615 * Formats a number for slider values 4616 * @param {number} value 4617 * @param {string} currency 4618 * @param {string} delimiter 4619 * @return {string} 4620 */ formatSliderValue(value, currency = '', delimiter = '') { 4621 if (value < 1000) return this.formatSliderAtom(value, currency); 4622 if (value < 1000000) return `${this.formatSliderAtom(value / 1000, currency)}${delimiter}K`; 4623 return `${this.formatSliderAtom(value / 1000000, currency)}${delimiter}M`; 4624 } 4625 /** 4626 * Format price slider range 4627 * @param {number} value 4628 * @param {Object} range 4629 * @param {string} currency 4630 * @param {Object} options 4631 * @return {string} 4632 */ formatSliderPriceRange(value, range, currency, options) { 4633 if (range.min === value && value !== 0) return `${options.lowPrefix}${this.formatSliderValue(value, currency, ' ')}`; 4634 if (range.max === value) return `${this.formatSliderValue(value, currency, ' ')}${options.highSuffix}`; 4635 return `${this.formatSliderValue(value, currency, ' ')}`; 4636 } 4637 /** 4638 * Format area slider range 4639 * @param {number} value 4640 * @param {Object} range 4641 * @param {string} suffix 4642 * @param {Object} options 4643 * @return {string} 4644 */ formatSliderAreaRange(value, range, suffix, options) { 4645 if (range.min === value && value !== 0) return `${options.lowPrefix}${this.formatSliderValue(value)} ${suffix}`; 4646 if (range.max === value) return `${this.formatSliderValue(value)}${options.highSuffix} ${suffix}`; 4647 return `${this.formatSliderValue(value)} ${suffix}`; 4648 } 4649 /** 4650 * Utility function to get properties search parameters from a set of jQuery objects 4651 * @param {Object} options 4652 * @param {jQuery|HTMLElement} [options.queryElement] 4653 * @param {jQuery|HTMLElement} [options.priceSliderElement] 4654 * @param {jQuery|HTMLElement} [options.areaSliderElement] 4655 * @param {jQuery|HTMLElement} [options.neighborhoodSelect] 4656 * @return {Object} 4657 */ // eslint-disable-next-line sonarjs/cognitive-complexity 4658 getSearchFormValues(options) { 4659 const { queryElement: queryElement, priceSliderElement: priceSliderElement, areaSli
4659derElement: areaSliderElement, neighborhoodSelect: neighborhoodSelect } = options; 4660 const result = {}; 4661 if (queryElement) result.search = queryElement.value || null; 4662 if (priceSliderElement) { 4663 const priceValues = priceSliderElement.value.split(';'); 4664 const priceMinLimit = parseInt(priceSliderElement.dataset.min); 4665 const priceMaxLimit = parseInt(priceSliderElement.dataset.max); 4666 const priceMin = parseInt(priceValues[0]); 4667 const priceMax = parseInt(priceValues[1]); 4668 result.priceMin = priceMin !== priceMinLimit ? priceMin : null; 4669 result.priceMax = priceMax !== priceMaxLimit ? priceMax : null; 4670 } 4671 if (areaSliderElement) { 4672 const areaValues = areaSliderElement.value.split(';'); 4673 const areaMinLimit = parseInt(areaSliderElement.dataset.min); 4674 const areaMaxLimit = parseInt(areaSliderElement.dataset.max); 4675 const areaMin = parseInt(areaValues[0]); 4676 const areaMax = parseInt(areaValues[1]); 4677 result.areaMin = areaMin !== areaMinLimit ? areaMin : null; 4678 result.areaMax = areaMax !== areaMaxLimit ? areaMax : null; 4679 } 4680 if (neighborhoodSelect) result.neighborhoodId = neighborhoodSelect.value || null; 4681 return result; 4682 } 4683 /** 4684 * Add supports for object typeof values to be encoded on URL 4685 * Ref: https://stackoverflow.com/questions/1714786/query-string-encoding-of-a-javascript-object 4686 * @param {*} obj 4687 * @param {string} prefix 4688 * @param {string} baseParam used for grouping in case of nested objects 4689 * @returns 4690 */ // eslint-disable-next-line sonarjs/cognitive-complexity 4691 serializeObj(obj, prefix = '', baseParam = '') { 4692 const result = []; 4693 for(const prop in obj)if (obj.hasOwnProperty(prop)) { 4694 const value = obj[prop]; 4695 let k; 4696 if (baseParam) { 4697 const newPrefix = prefix ? `[${prefix}][${prop}]` : `[${prop}]`; 4698 k = `${baseParam}${newPrefix}`; 4699 } else k = prefix ? `${prefix}[${prop}]` : prop; 4700 if (value !== null && Array.isArray(value)) { 4701 if (value.length) result.push(this.serializeArray(k, value)); 4702 } else if (value !== null && typeof value === 'object') result.push(this.serializeObj(value, k)); 4703 else result.push(`${k}=${encodeURIComponent(value)}`); 4704 } 4705 return result.join('&'); 4706 } 4707 /** 4708 * Adds support for array values to be encoded on URL 4709 * @param {string} key 4710 * @param {Array} value 4711 * @param {string} baseParam 4712 */ serializeArray(key, value, baseParam = '') { 4713 const result = []; 4714 value.forEach((val)=>{ 4715 const paramName = baseParam ? `${baseParam}${key}` : key; 4716 result.push(`${paramName}=${encodeURIComponent(val)}`); 4717 }); 4718 return result.join('&'); 4719 } 4720 /** 4721 * Private method to process string search values. 4722 * @param {Array} results comes from regex matchAll. 4723 * @param {Boolean} isAdvancedFilters flag to determine if the search is for advanced filters. 4724 * @returns 4725 */ _parseParamToObject(results, isAdvancedFilters = false) { 4726 if (!results.length) return null; 4727 const obj = {}; 4728 for(let i = 0; i < results.length; i++)/* Results from regex match all come in this form: 4729 [ '&advancedFilters[query][statusIds][in]=uuid-segundo-123', '[query][statusIds][in]', 'uuid-segundo-123' ] 4730 So using every third value will be the actual value and the second value will be the path 4731 */ if ((i + 1) % 3 === 0) { 4732 const value = decodeURIComponent(results[i].replace(/\+/g, ' ')); 4733 const path = results[i - 1]; 4734 Object.assign(obj, this._setObjectPath(path, value, obj, isAdvancedFilters)); 4735 } 4736 return obj; 4737 } 4738 /** * 4739 * Private method to set object value given a path 4740 * @param {String} path 4741 * @param {*} value 4742 * @param {Object} baseObj 4743 * @param {Boolean} isAdvancedFilters flag to determine if the search is for advanced filters. 4744 */ _setObjectPath(path, value, baseObj, isAdvancedFilters = false) { 4745 // eslint-disable-next-line
4746 const keys = path.split(/[\[\]]/).filter(Boolean); 4747 const afArrayKeys = [ 4748 'in', 4749 'nin', 4750 'btw', 4751 'ciin', 4752 'cinin' 4753 ]; 4754 const obj = {}; 4755 let ref = obj; 4756 const valueExists = (0, $fc0a058ae42af628$export$267a1435fe18b8d4)(baseObj, keys.join('.')); 4757 keys.forEach((key, index)=>{ 4758 if (index === keys.length - 1) { 4759 if (valueExists) ref[key] = Array.isArray(valueExists) ? [ 4760 ...valueExists, 4761 value 4762 ] : [ 4763 valueExists, 4764 value 4765 ]; 4766 else ref[key] = isAdvancedFilters && afArrayKeys.includes(key) ? [ 4767 value 4768 ] : value; 4769 } else { 4770 ref[key] = baseObj[key] ? baseObj[key] : {}; 4771 ref = ref[key]; 4772 } 4773 }); 4774 return obj; 4775 } 4776} 4777 4778 4779/* eslint-disable import/prefer-default-export */ 4780class $2b1790aa32f109d1$export$43e435c053a109f6 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 4781 /** 4782 * Initialize Expand Slider Controller at build time 4783 * @param { ConfigController } config 4784 * @param {Window} window 4785 * @param {Document} document 4786 */ constructor(config, window, document){ 4787 super(config, window, document); 4788 this._createLightbox = this._createLightbox.bind(this); 4789 this.expandSliders = []; 4790 } 4791 /** 4792 * Initialize Expand Slider Controller at run time 4793 * Attach handlers and events to DOM 4794 * @param {Object} options 4795 */ initialize(options = {}) { 4796 try { 4797 const { document: document } = this; 4798 const expandSliders = document.querySelectorAll('.has-mobile-expand'); 4799 expandSliders.forEach((block)=>{ 4800 this._addExpandButton(block); 4801 }); 4802 this.expandSliders = this.expandSliders.concat(expandSliders); 4803 } catch (e) { 4804 // eslint-disable-next-line no-console 4805 console.log(e); 4806 } 4807 } 4808 /** 4809 * Controllers must implement a "destroy" method to be called 4810 * after page navigation to remove event handlers / cleanup 4811 */ destroy() { 4812 const { document: document } = this; 4813 document.querySelectorAll('.lp-expand-btn, .lp-expand-btn-wrapper').forEach((element)=>element.remove()); 4814 this.expandSliders = []; 4815 } 4816 /** 4817 * Create expand button for sliders 4818 * @param {HTMLElement} slider 4819 */ _addExpandButton(slider) { 4820 const { document: document } = this; 4821 const section = slider.closest('section[id]'); 4822 const appendTargetSelector = slider.dataset.append; 4823 let expandBtn = section.querySelector('.lp-expand-btn'); 4824 if (!expandBtn) { 4825 expandBtn = document.createElement('button'); 4826 expandBtn.className = 'lp-expand-btn'; 4827 expandBtn.setAttribute('aria-label', 'Open a lightbox'); 4828 expandBtn.innerHTML = `<span class="lp-i lp-i--expand-alt" aria-hidden="true"></span>`; 4829 if (appendTargetSelector) { 4830 const appendTarget = section.querySelector(appendTargetSelector); 4831 if (appendTarget) appendTarget.appendChild(expandBtn); 4832 } else { 4833 const wrapper = document.createElement('div'); 4834 wrapper.className = 'lp-expand-btn-wrapper'; 4835 wrapper.style.position = 'relative'; 4836 wrapper.appendChild(expandBtn); 4837 slider.parentNode.insertBefore(wrapper, slider.nextSibling); 4838 } 4839 } 4840 expandBtn.addEventListener('click', ()=>{ 4841 this._createLightbox({ 4842 slider: slider, 4843 section: section 4844 }); 4845 }); 4846 } 4847 /** 4848 * Creates a lightbox modal for displaying slider images in a larger view. 4849 * 4850 * @param {Object} params - The parameters for the function. 4851 * @param {HTMLElement} params.slider - The slider element containing images. 4852 * @param {HTMLElement} params.section - The section element related to the slider. 4853 * @param {number} [params.initialIndex] - Optional index of the image to show initially. 4854 */ _createLightbox({ slider: slider, section: section, initialIndex: initialIndex }) { 4855 const { window: window, document: document } = this; 4856 const modalId = `lightbox-for-${section?.id}`; 4857 const isSlickAvailable = window.$ && window.$.fn.slick; 4858 const isSectionSlickInitialized = isSlickAvailable && slider.slick; 4859 const isSplideAvailable = typeof window.Splide === 'function'; 4860 const isSectionSplideInitialized = slider.classList.contains('is-initialized') && slider.classList.contains('splide'); 4861 if (typeof window.lpUI.requestScrollLock === 'function') window.lpUI.requestScrollLock(modalId); 4862 else document.body.style.overflow = 'hidden'; 4863 function createSlickLightbox() { 4864 const slickOverlayOptions = { 4865 arrows: true, 4866 dots: false, 4867 infinite: true, 4868 draggable: true, 4869 prevArrow: '<button type="button" class="lp-lightbox-arrow--prev lp-lightbox-arrow" aria-label="Previous"></button>', 4870 nextArrow: '<button type="button" class="lp-lightbox-arrow--next lp-lightbox-arrow" aria-label="Next"></button>' 4871 }; 4872 const modal = document.createElement('div'); 4873 modal.id = modalId; 4874 modal.className = 'lp-lightbox'; 4875 modal.setAttribute('tabindex', '-1'); 4876 modal.setAttribute('role', 'dialog'); 4877 modal.setAttribute('aria-modal', 'true'); 4878 modal.innerHTML = ` 4879 <button class="lp-lightbox__close" aria-label="close modal"></button> 4880 <div class="lp-lightbox__content"> 4881 <div class="lp-lightbox__carousel"></div> 4882 </div> 4883 `; 4884 document.body.appendChild(modal); 4885 const overlaySlider = modal.querySelector('.lp-lightbox__carousel'); 4886 modal.classList.add('show'); 4887 let sourceImages; 4888 if (isSectionSlickInitialized) { 4889 sourceImages = slider.slick.$slides.find('img'); 4890 slickOverlayOptions.initialSlide = slider.slick?.currentSlide || 0; 4891 sourceImages.each(function() { 4892 window.$('.lp-lightbox__carousel').append(window.$(this).clone(false).removeAttr('style').wrap('<div class="lp-lightbox__slide"></div>').parent()); 4893 }); 4894 } else { 4895 sourceImages = slider.querySelectorAll('img');
4896 sourceImages.forEach((img)=>{ 4897 const imgClone = img.cloneNode(true); 4898 imgClone.removeAttribute('style'); 4899 const slide = document.createElement('div'); 4900 slide.className = 'lp-lightbox__slide'; 4901 slide.appendChild(imgClone); 4902 overlaySlider.appendChild(slide); 4903 }); 4904 } 4905 window.$(overlaySlider).slick(slickOverlayOptions); 4906 // Focus modal after it's created 4907 setTimeout(()=>{ 4908 modal.focus(); 4909 }, 100); 4910 // Keyboard navigation handler 4911 const handleKeydown = (e)=>{ 4912 if (!modal.classList.contains('show')) return; 4913 const prevArrow = modal.querySelector('.lp-lightbox-arrow--prev'); 4914 const nextArrow = modal.querySelector('.lp-lightbox-arrow--next'); 4915 const closeBtn = modal.querySelector('.lp-lightbox__close'); 4916 if (e.key === 'ArrowLeft' && prevArrow) { 4917 e.preventDefault(); 4918 prevArrow.click(); 4919 } else if (e.key === 'ArrowRight' && nextArrow) { 4920 e.preventDefault(); 4921 nextArrow.click(); 4922 } else if (e.key === 'Escape' && closeBtn) { 4923 e.preventDefault(); 4924 closeBtn.click(); 4925 } 4926 }; 4927 document.addEventListener('keydown', handleKeydown); 4928 modal.querySelector('.lp-lightbox__close').addEventListener('click', ()=>{ 4929 document.removeEventListener('keydown', handleKeydown); 4930 modal.classList.remove('show'); 4931 const currentSlide = overlaySlider?.slick ? window.$(overlaySlider).slick('slickCurrentSlide') : 0; 4932 if (overlaySlider?.slick) window.$(overlaySlider).slick('unslick'); 4933 if (isSectionSlickInitialized) window.$(slider).slick('slickGoTo', currentSlide); 4934 if (typeof window.lpUI.releaseScrollLock === 'function') window.lpUI.releaseScrollLock(modalId); 4935 else document.body.style.overflow = ''; 4936 modal.remove(); 4937 }); 4938 } 4939 function createSplideLightbox() { 4940 const splideOptions = { 4941 rewind: true, 4942 arrows: true, 4943 arrowPath: '', 4944 type: 'loop', 4945 clones: 1, 4946 pagination: false, 4947 perPage: 1, 4948 perMove: 1 4949 }; 4950 const modal = document.createElement('div'); 4951 modal.id = modalId; 4952 modal.className = 'lp-lightbox'; 4953 modal.setAttribute('tabindex', '-1'); 4954 modal.setAttribute('role', 'dialog'); 4955 modal.setAttribute('aria-modal', 'true'); 4956 modal.innerHTML = ` 4957 <button class="lp-lightbox__close" aria-label="close modal"></button> 4958 <div class="lp-lightbox__content"> 4959 <div class="lp-lightbox__carousel splide" role="group" aria-label="Image Gallery"> 4960 <div class="splide__arrows"> 4961 <button class="splide__arrow splide__arrow--prev lp-lightbox-arrow lp-lightbox-arrow--prev"></button> 4962 <button class="splide__arrow splide__arrow--next lp-lightbox-arrow lp-lightbox-arrow--next"></button> 4963 </div> 4964 <div class="splide__track"> 4965 <ul class="splide__list"></ul> 4966 </div> 4967 </div> 4968 </div> 4969 `; 4970 if (typeof window.lpUI.requestScrollLock === 'function') window.lpUI.requestScrollLock(modalId); 4971 else document.body.style.overflow = 'hidden'; 4972 document.body.appendChild(modal); 4973 const overlaySlider = modal.querySelector('.lp-lightbox__carousel'); 4974 const overlaySliderList = overlaySlider.querySelector('.splide__list'); 4975 modal.classList.add('show'); 4976 let sourceImages; 4977 if (isSectionSplideInitialized) sourceImages = slider.querySelectorAll('.splide__slide:not(.splide__slide--clone) img'); 4978 else sourceImages = slider.querySelectorAll('img');
4979 sourceImages.forEach((img)=>{ 4980 const imgClone = img.cloneNode(true); 4981 imgClone.removeAttribute('style'); 4982 const slide = document.createElement('li'); 4983 slide.className = 'lp-lightbox__slide splide__slide'; 4984 slide.appendChild(imgClone); 4985 overlaySliderList.appendChild(slide); 4986 }); 4987 const overlaySplide = new window.Splide(overlaySlider, splideOptions); 4988 overlaySplide.mount(); 4989 // Navigate to initial index if provided 4990 if (typeof initialIndex !== 'undefined' && initialIndex >= 0) overlaySplide.go(initialIndex); 4991 // Focus modal after it's created and mounted 4992 setTimeout(()=>{ 4993 modal.focus(); 4994 }, 100); 4995 // Keyboard navigation handler 4996 const handleKeydown = (e)=>{ 4997 if (!modal.classList.contains('show')) return; 4998 const prevArrow = modal.querySelector('.splide__arrow--prev'); 4999 const nextArrow = modal.querySelector('.splide__arrow--next'); 5000 const closeBtn = modal.querySelector('.lp-lightbox__close'); 5001 if (e.key === 'ArrowLeft' && prevArrow) { 5002 e.preventDefault(); 5003 prevArrow.click(); 5004 } else if (e.key === 'ArrowRight' && nextArrow) { 5005 e.preventDefault(); 5006 nextArrow.click(); 5007 } else if (e.key === 'Escape' && closeBtn) { 5008 e.preventDefault(); 5009 closeBtn.click(); 5010 } 5011 }; 5012 document.addEventListener('keydown', handleKeydown); 5013 modal.querySelector('.lp-lightbox__close').addEventListener('click', ()=>{ 5014 document.removeEventListener('keydown', handleKeydown); 5015 modal.classList.remove('show'); 5016 if (overlaySplide) overlaySplide.destroy(); 5017 if (typeof window.lpUI.releaseScrollLock === 'function') window.lpUI.releaseScrollLock(modalId); 5018 else document.body.style.overflow = ''; 5019 modal.remove(); 5020 }); 5021 } 5022 if (isSlickAvailable && !isSectionSplideInitialized) createSlickLightbox(); 5023 else if (isSplideAvailable) createSplideLightbox(); 5024 else { 5025 window.luxuryPresence.libs.loadCss(window.luxuryPresence.libs.jsLibsMap.splide.cssSrc); 5026 window.luxuryPresence.libs.loadJs(window.luxuryPresence.libs.jsLibsMap.splide.jsSrc, ()=>{ 5027 createSplideLightbox(); 5028 window.luxuryPresence.libs.jsLibsMap.splide.isLoaded = true; 5029 }); 5030 } 5031 } 5032} 5033 5034 5035/* eslint-disable import/prefer-default-export */ 5036class $4f184d9bd3037f15$export$7a6215890afba974 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5037 // constructor is not needed as it is inherited from BaseController 5038 /** 5039 * Destroy 5040 */ destroy() { 5041 if (!this.window.divolte) this.window.divolteLp = function() { 5042 (this.window.divolteLp.q = this.window.divolteLp.q || []).push(// eslint-disable-next-line prefer-rest-params 5043 arguments); 5044 }; 5045 } 5046 /** 5047 * Initialize divolte controller 5048 * @param {Object} options 5049 */ initialize(options = {}) { 5050 const { divolteServiceUrl: divolteServiceUrl } = this.config; 5051 if (!divolteServiceUrl || this.window.divolte) return; 5052 this.loadScript(); 5053 } 5054 /** 5055 * loads divolte 5056 */ loadScript() { 5057 const { divolteServiceUrl: divolteServiceUrl } = this.config; 5058 const script = this.document.createElement('script'); 5059 script.id = 'divolte-script'; 5060 script.type = 'text/javascript'; 5061 script.defer = true; 5062 script.async = true; 5063 script.src = `${divolteServiceUrl}/divolte.js`; 5064 this.document.head.appendChild(script); 5065 script.addEventListener('load', this.executeQueue.bind(this)); 5066 } 5067 /** 5068 * executeQueue 5069 */ executeQueue() { 5070 (this.window.divolteLp.q || []).forEach(([methodName, params])=>{ 5071 this[methodName](params); 5072 }); 5073 this.window.divolteLp = this.divolteLp.bind(this); 5074 } 5075 /** 5076 * divolteLp 5077 * @param {string} name 5078 * @param {Object} params 5079 */ divolteLp(name, params) { 5080 try { 5081 this[name](params); 5082 } catch (error) { 5083 // eslint-disable-next-line no-console 5084 console.log(error); 5085 } 5086 } 5087 /** 5088 * sendLpEvent 5089 * @param {string} name 5090 * @param {Object} params 5091 */ sendLpEvent(name, params) { 5092 // Events must be defined in divolte schema! To ensure correct usage, event names are validated here. 5093 if (!name.includes('pageView')) { 5094 // Event not defined 5095 // eslint-disable-next-line no-console 5096 console.log(`${name} IS NOT SUPPORTED`); 5097 return; 5098 } 5099 const { companyId: companyId, templateId: templateId, websiteId: websiteId, pageId: pageId, shareId: shareId, pageMeta: pageMeta } = this.config; 5100 const baseParams = { 5101 companyId: companyId, 5102 templateId: templateId, 5103 websiteId: websiteId, 5104 pageId: pageId, 5105 shareId: shareId, 5106 pageMeta: pageMeta 5107 }; 5108 this.window.divolte.signal(name, Object.assign(baseParams, params)); 5109 } 5110 /** 5111 * sendLpPageView 5112 */ sendLpPageView() { 5113 this.sendLpEvent('pageView', {}); 5114 } 5115} 5116 5117 5118/* eslint-disable import/prefer-default-export */ 5119const $102039871668a1df$var$EVENT_BUS_SCRIPT = 'event-bus-js.js'; 5120const $102039871668a1df$var$EVENT_BUS_VERSION = 'v2.8.0'; 5121const $102039871668a1df$var$EVENT_BUS_DEFAULT_SOURCE = 'frontend://website-render-engine'; 5122class $102039871668a1df$export$e22e4b1be0bb6c61 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5123 // eslint-disable-next-line @typescript-eslint/no-useless-constructor 5124 constructor(config, window, document){ 5125 super(config, window, document); 5126 } 5127 /** 5128 * Initialize EventBus controller 5129 * @param {Object} options 5130 */ initialize(options = {}) { 5131 const enabled = options.enabled !== undefined ? options.enabled : this.config.eventBus?.enabled; 5132 if (enabled && this.config.eventBus?.apiKey && this.config.eventBus?.url) this.loadScript(); 5133 } 5134 /** 5135 * loads eventBus script 5136 */ loadScript() { 5137 const { eventBusUrl: eventBusUrl } = this.config; 5138 const script = this.document.createElement('script'); 5139 script.id = 'posthog-script'; 5140 script.type = 'text/javascript'; 5141 script.defer = true; 5142 script.async = true; 5143 script.src = `${eventBusUrl}/${$102039871668a1df$var$EVENT_BUS_VERSION}/${$102039871668a1df$var$EVENT_BUS_SCRIPT}`; 5144 this.document.head.appendChild(script); 5145 script.addEventListener('load', this.executeQueue.bind(this)); 5146 } 5147 /** 5148 * executeQueue - Process queued eventBusLp calls 5149 */ executeQueue() { 5150 // Initialize the event bus provider using the global EventBusJS 5151 if (this.window.LuxuryPresenceEventBus) this.window.eventBusProvider = this.window.LuxuryPresenceEventBus.createEventBusProvider({ 5152 apiKey: this.config.eventBus.apiKey, 5153 host: this.config.eventBus.url, 5154 defaultSource: $102039871668a1df$var$EVENT_BUS_DEFAULT_SOURCE 5155 });
5156 (this.window.eventBusLp.q || []).forEach(([methodName, params])=>{ 5157 this[methodName](params); 5158 }); 5159 // Replace queue function with real function 5160 this.window.eventBusLp = this.eventBusLp.bind(this); 5161 } 5162 /** 5163 * Destroy 5164 */ destroy() { 5165 if (!this.window.eventBusProvider) { 5166 // Reset to queue function if no provider exists 5167 this.window.eventBusLp = function() { 5168 (this.window.eventBusLp.q = this.window.eventBusLp.q || []).push(// eslint-disable-next-line prefer-rest-params 5169 arguments); 5170 }; 5171 return; 5172 } 5173 this.window.eventBusProvider.shutdown(); 5174 } 5175 /** 5176 * sendLpEvent 5177 * @param {string} eventType 5178 * @param {Object} data 5179 */ sendLpEvent(eventType, data) { 5180 // Events must be defined in event-bus schema! To ensure correct usage, event types are validated here. 5181 if (eventType !== 'user.activity.page.viewed') { 5182 // Event type not defined 5183 // eslint-disable-next-line no-console 5184 console.log(`${eventType} IS NOT SUPPORTED`); 5185 return; 5186 } 5187 if (!this.window.eventBusProvider) return; 5188 const { companyId: companyId } = this.config; 5189 const eventData = { 5190 company: companyId, 5191 data: {} 5192 }; 5193 try { 5194 this.window.eventBusProvider.capture(eventType, eventData); 5195 } catch (error) { 5196 // eslint-disable-next-line no-console 5197 console.log('EventBus capture error:', error); 5198 } 5199 } 5200 /** 5201 * eventBusLp 5202 * @param {string} name 5203 * @param {Object} params 5204 */ eventBusLp(name, params) { 5205 try { 5206 this[name](params); 5207 } catch (error) { 5208 // eslint-disable-next-line no-console 5209 console.log(error); 5210 } 5211 } 5212 /** 5213 * sendLpPageView 5214 */ sendLpPageView() { 5215 this.sendLpEvent('user.activity.page.viewed', {}); 5216 } 5217} 5218 5219 5220/* eslint-disable import/prefer-default-export */ 5221 5222const $0d25a3fa2e0f4f92$var$EVENT_NAME = 'oauthSuccess'; 5223class $0d25a3fa2e0f4f92$export$b718a981691eae5c extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5224 /** 5225 * Initialize Button Controller at build time 5226 * @param { ConfigController } config 5227 * @param {Window} window 5228 * @param {Document} document 5229 */ constructor(config, window, document){ 5230 super(config, window, document); 5231 this.successListeners = []; 5232 this._listenToMessages = this._listenToMessages.bind(this); 5233 this._listenToOneTapMessage = this._listenToOneTapMessage.bind(this); 5234 } 5235 /** 5236 * Initialize OAuth Controller at run time 5237 * Swap out special buttons for the iframe 5238 * @param {Object} options 5239 */ initialize(options = {}) { 5240 try { 5241 // handle google one tap 5242 if (options.googleSignOnEnabled && !options.iframe) this._renderGoogleOneTap(); 5243 // handle google sign in buttons 5244 this.document.querySelectorAll('div[data-signin-type="google-sign-in"]').forEach((el)=>this._convertGoogleSignIn(el)); 5245 // handle facebook sign in buttons 5246 this.document.querySelectorAll('div[data-signin-type="facebook-sign-in"]').forEach((el)=>this._convertFacebookSignIn(el)); 5247 } catch (e) { 5248 // eslint-disable-next-line no-console 5249 console.log(e); 5250 } 5251 } 5252 /** 5253 * Controllers must implement a "destroy" method to be called 5254 * after page navigation to remove event handlers / cleanup 5255 */ destroy() { 5256 this.successListeners.forEach((callback)=>{ 5257 this.window.removeEventListener('message', this._listenToMessages); 5258 this.window.removeEventListener('message', this._listenToOneTapMessage); 5259 this.window.removeEventListener($0d25a3fa2e0f4f92$var$EVENT_NAME, this.window[callback]); 5260 }); 5261 } 5262 /** 5263 * Convert google one tap 5264 */ _renderGoogleOneTap() { 5265 if (!this._isGoogleOneTapOnCooldown()) { 5266 const dummyEl = this.document.createElement('div'); 5267 // eslint-disable-next-line no-undef 5268 google.accounts.id.initializeIntermediate({ 5269 src: this._buildUrlAndCopyAttributes(dummyEl, dummyEl, 'googleOneTap') 5270 }); 5271 this.window.localStorage.removeItem('googleOneTapExpiration'); 5272 this.window.addEventListener('message', this._listenToOneTapMessage); 5273 } 5274 } 5275 /** 5276 * Listening for messages from BSS one tap iframes 5277 * @param {MessageEvent} e 5278 */ _listenToOneTapMessage(e) { 5279 const messageTypes = { 5280 SHOW_INTERMEDIATE_IFRAME: 'show_intermediate_iframe', 5281 HIDE_INTERMEDIATE_IFRAME: 'hide_intermediate_iframe' 5282 };
5283 const iframeId = 'onetap_google_intermediate_iframe'; 5284 const { buyerSellerServiceUrl: buyerSellerServiceUrl } = this.config; 5285 const { data: data, origin: origin } = e; 5286 const { type: type, height: height, event: event, source: source, token: token } = data; 5287 if (type === messageTypes.SHOW_INTERMEDIATE_IFRAME || type === messageTypes.HIDE_INTERMEDIATE_IFRAME) { 5288 const bssIframe = this.document.getElementById(iframeId); 5289 if (bssIframe) { 5290 bssIframe.style.height = height; 5291 bssIframe.style.display = type === messageTypes.SHOW_INTERMEDIATE_IFRAME ? 'unset' : 'none'; 5292 } 5293 } 5294 // these events are generated by our code in the bss iframe 5295 if (origin === buyerSellerServiceUrl && source === 'GOOGLE_SIGN_ON') { 5296 if (event === 'success') { 5297 this._setExpirationLsItem(86400000); // 24 hours 5298 this._handleQualifyingQuestionsModal(token); 5299 } else if (event === 'cancel') this._setExpirationLsItem(7200000); // 2 hours 5300 } 5301 } 5302 /** 5303 * Set expiration local storage item for google one tap 5304 * @param {number} ms 5305 */ _setExpirationLsItem(ms) { 5306 const expiration = new Date().getTime() + ms; 5307 this.window.localStorage.setItem('googleOneTapExpiration', expiration); 5308 } 5309 /** 5310 * Check if google one tap is expired 5311 * @return {boolean} 5312 */ _isGoogleOneTapOnCooldown() { 5313 const expirationTime = this.window.localStorage.getItem('googleOneTapExpiration'); 5314 return Number(expirationTime) > new Date().getTime(); 5315 } 5316 /** 5317 * Convert google sign in buttons 5318 * @param {HTMLElement} el 5319 */ _convertGoogleSignIn(el) { 5320 this._replaceWithIframe('googleSignIn', el); 5321 } 5322 /** 5323 * Convert google sign in buttons 5324 * @param {HTMLElement} el 5325 */ _convertFacebookSignIn(el) { 5326 this._replaceWithIframe('facebookSignIn', el); 5327 } 5328 /** 5329 * Convert google sign in buttons 5330 * @param {'googleSignIn' | 'facebookSignIn'} provider 5331 * @param {HTMLElement} el 5332 */ _replaceWithIframe(provider, el) { 5333 this._attachSuccessCallback(el); 5334 const iframe = this.document.createElement('iframe'); 5335 iframe.src = this._buildUrlAndCopyAttributes(el, iframe, provider); 5336 iframe.dataset.isSocialOauthButton = true; 5337 el.replaceWith(iframe); 5338 } 5339 /** 5340 * Listening for messages from BSS iframes 5341 * @param {Event} e 5342 */ _listenToMessages(e) { 5343 const { buyerSellerServiceUrl: buyerSellerServiceUrl } = this.config; 5344 // eslint-disable-next-line sonarjs/no-collapsible-if 5345 if (e.origin === buyerSellerServiceUrl) { 5346 if (e.data.event === 'success') { 5347 const event = new Event($0d25a3fa2e0f4f92$var$EVENT_NAME); 5348 this.window.dispatchEvent(event); 5349 // Registration / social sign-in is a lead event â credit the conversion. 5350 (0, $3ec2bf3965f87ecc$export$e70565180c0e6950)(this.window, this.document); 5351 this.successListeners.forEach((callback)=>{ 5352 if (this.window[callback]) this.window[callback](event); 5353 else // eslint-disable-next-line no-console 5354 console.error(`Callback function ${callback} not found on window object`); 5355 }); 5356 this.document.documentElement.classList.add('is-login-success'); 5357 } 5358 } 5359 } 5360 /** 5361 * Attach callback to iframe 5362 * @param {HTMLElement} el 5363 */ _attachSuccessCallback(el) { 5364 this.window.addEventListener('message', this._listenToMessages); 5365 const callbackFunction = el.dataset.onSuccessFunctionName; 5366 if (callbackFunction) this.successListeners.push(callbackFunction); 5367 } 5368 /** 5369 * Build Iframe URL 5370 * @param {HTMLElement} source 5371 * @param {HTMLElement} target 5372 * @param {string} provider 5373 * @return {string} 5374 */ _buildUrlAndCopyAttributes(source, target, provider) { 5375 const { buyerSellerServiceUrl: buyerSellerServiceUrl, companyId: companyId, websiteId: websiteId, pageId: pageId, pageMeta: pageMeta } = this.config; 5376 const { location: location } = this.window; 5377 const sourceUrl = location.origin + location.pathname; 5378 const destination = new URL(`${buyerSellerServiceUrl}/buttons/${provider}`); 5379 const utm = this.window.localStorage.getItem('utm_vars'); 5380 const referrer = this.window.localStorage.getItem('referrer'); 5381 destination.searchParams.append('companyId', companyId); 5382 destination.searchParams.append('websiteId', websiteId); 5383 destination.searchParams.append('pageId', pageId); 5384 destination.searchParams.append('sourceUrl', sourceUrl); 5385 destination.searchParams.append('pageMeta', JSON.stringify(pageMeta)); 5386 if (utm) destination.searchParams.append('utm', utm); 5387 if (referrer) destination.searchParams.append('referrer', referrer); 5388 // Google and Facebook Attributes used to style the social button 5389 const RESERVED_ATTRIBUTES = [ 5390 'data-size', 5391 'data-width', 5392 'data-text', 5393 'data-button-type', 5394 'data-shape', 5395 'data-layout', 5396 'data-max-rows', 5397 'data-use-continue-as', 5398 'data-type', 5399 'data-theme', 5400 'data-logo_alignment', 5401 'data-locale' 5402 ];
5403 Array.from(source.attributes).forEach((attribute)=>{ 5404 if (RESERVED_ATTRIBUTES.includes(attribute.nodeName)) destination.searchParams.append(attribute.nodeName, attribute.nodeValue); 5405 else target.setAttribute(attribute.nodeName === 'id' ? 'data-id' : attribute.nodeName, attribute.nodeValue); 5406 }); 5407 return destination.toString(); 5408 } 5409 /** 5410 * Decode a JWT token to extract payload information 5411 * @param {string} token - The JWT token to decode 5412 * @return {Object|null} The decoded payload object or null if decoding fails 5413 */ _decodeToken(token) { 5414 try { 5415 const parts = token.split('.'); 5416 const payload = parts[1]; 5417 const base64 = payload.replace(/-/g, '+').replace(/_/g, '/'); 5418 const padding = 4 - base64.length % 4; 5419 const padded = padding === 4 ? base64 : base64 + '='.repeat(padding); 5420 return JSON.parse(atob(padded)); 5421 } catch (error) { 5422 return null; 5423 } 5424 } 5425 /** 5426 * Handle qualifying questions modal showing for Google Sign On 5427 * Decodes the JWT token to extract user email and shows the modal if available 5428 * @param {string} token - The JWT token containing user information 5429 */ _handleQualifyingQuestionsModal(token) { 5430 if (token && this.window.luxuryPresence && this.window.luxuryPresence.qualifyingQuestionsModal) { 5431 // Decoding only for lead attribution, fine to skip signature verification 5432 const decoded = this._decodeToken(token); 5433 if (decoded && decoded.email) this.window.luxuryPresence.qualifyingQuestionsModal.showModal(decoded.email, 'Google Sign On'); 5434 } 5435 } 5436} 5437 5438 5439/* eslint-disable import/prefer-default-export */ 5440class $dcf72769f009ff26$export$b900d6fe921fd49c extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5441 /** 5442 * Initialize Qualifying Questions Modal Controller at build time 5443 * @param { ConfigController } config 5444 * @param {Window} window 5445 * @param {Document} document 5446 */ constructor(config, window, document){ 5447 super(config, window, document); 5448 this.showModal = this.showModal.bind(this); 5449 this.hasModalBeenSubmitted = this.hasModalBeenSubmitted.bind(this); 5450 this.modalId = 'qualifying-questions-modal'; 5451 this.cookieKey = 'qualifyingQuestionsModalSubmitted'; 5452 this.qualifyingQuestionsModalEnabled = true; 5453 // Store references for cleanup 5454 this.eventListeners = []; 5455 this.timeouts = []; 5456 } 5457 initialize(options = {}) { 5458 this.qualifyingQuestionsModalEnabled = options.qualifyingQuestionsModalEnabled ?? this.qualifyingQuestionsModalEnabled; 5459 if (!this.qualifyingQuestionsModalEnabled) return; 5460 this.attachModalCloseListeners(); 5461 } 5462 destroy() { 5463 // Remove all stored event listeners 5464 this.eventListeners.forEach(({ element: element, event: event, handler: handler })=>{ 5465 if (element && element.removeEventListener) element.removeEventListener(event, handler); 5466 }); 5467 this.timeouts.forEach((timeoutId)=>{ 5468 clearTimeout(timeoutId); 5469 }); 5470 this.restoreBodyScroll(); 5471 this.eventListeners = []; 5472 this.timeouts = []; 5473 } 5474 /** 5475 * Check if modal has been submitted using cookie-based deduplication 5476 * @return {boolean} 5477 */ hasModalBeenSubmitted() { 5478 const cookieValue = this.getCookie(this.cookieKey); 5479 return cookieValue === 'true'; 5480 } 5481 /** 5482 * Set cookie to prevent modal from showing again 5483 */ setModalSubmittedCookie() { 5484 this.setCookie(this.cookieKey, 'true', 365); // 1 year 5485 } 5486 showModal(email, triggerSource) { 5487 if (!this.qualifyingQuestionsModalEnabled || this.hasModalBeenSubmitted()) return; 5488 this.updateEmailValue(email); 5489 this.updateTriggerSourceValue(triggerSource); 5490 this.showModalElement(); 5491 } 5492 /** 5493 * Get modal element with error handling 5494 * @return {Element|null} 5495 */ getModalElement() { 5496 const modal = this.document.getElementById(this.modalId); 5497 if (!modal) console.error('Modal element not found:', this.modalId); 5498 return modal; 5499 } 5500 updateEmailValue(email) { 5501 const modal = this.getModalElement(); 5502 if (!modal) return; 5503 const emailInput = modal.querySelector('input[name="email"]'); 5504 if (emailInput && typeof email === 'string') emailInput.value = email; 5505 } 5506 updateTriggerSourceValue(triggerSource) { 5507 const modal = this.getModalElement(); 5508 if (!modal) return;
5509 const triggerSourceInput = modal.querySelector(`#${this.modalId}-triggerSource`); 5510 if (triggerSourceInput && typeof triggerSource === 'string') triggerSourceInput.value = triggerSource; 5511 } 5512 showModalElement() { 5513 const modal = this.getModalElement(); 5514 if (!modal) return; 5515 modal.style.display = 'flex'; 5516 this.blockBodyScroll(); 5517 } 5518 /** 5519 * Helper method to get cookie value 5520 * @param {string} name 5521 * @return {string|null} 5522 */ getCookie(name) { 5523 const value = `; ${this.document.cookie}`; 5524 const parts = value.split(`; ${name}=`); 5525 if (parts.length === 2) return decodeURIComponent(parts.pop().split(';').shift()); 5526 return null; 5527 } 5528 /** 5529 * Helper method to set cookie 5530 * @param {string} name 5531 * @param {string} value 5532 * @param {number} days 5533 */ setCookie(name, value, days) { 5534 let expires = ''; 5535 if (days) { 5536 const date = new Date(); 5537 date.setTime(date.getTime() + days * 86400000); 5538 expires = `; expires=${date.toUTCString()}`; 5539 } 5540 let attrs = '; path=/; SameSite=Lax'; 5541 if (this.window && this.window.location && this.window.location.protocol === 'https:') attrs += '; Secure'; 5542 this.document.cookie = `${name}=${encodeURIComponent(value || '')}${expires}${attrs}`; 5543 } 5544 blockBodyScroll() { 5545 this._prevOverflow = this.document.body.style.overflow; 5546 this.document.body.style.overflow = 'hidden'; 5547 } 5548 restoreBodyScroll() { 5549 this.document.body.style.overflow = this._prevOverflow || ''; 5550 this._prevOverflow = null; 5551 } 5552 attachModalCloseListeners() { 5553 const modal = this.getModalElement(); 5554 if (!modal) return; 5555 // Listen for form submission success (when modal closes automatically) 5556 const form = this.document.getElementById(`${this.modalId}-form`); 5557 if (form) { 5558 const formSubmittedHandler = ()=>{ 5559 // Set cookie to prevent showing again and hide modal 5560 this.setModalSubmittedCookie(); 5561 const timeoutId = setTimeout(()=>{ 5562 modal.style.display = 'none'; 5563 this.restoreBodyScroll(); 5564 }, 100); 5565 this.timeouts.push(timeoutId); 5566 }; 5567 form.addEventListener('formsubmitted', formSubmittedHandler); 5568 this.eventListeners.push({ 5569 element: form, 5570 event: 'formsubmitted', 5571 handler: formSubmittedHandler 5572 }); 5573 } 5574 // Listen for close button clicks 5575 const closeButton = modal.querySelector('[data-dismiss="modal"]'); 5576 if (closeButton) { 5577 const closeButtonHandler = ()=>{ 5578 modal.style.display = 'none'; 5579 this.restoreBodyScroll(); 5580 }; 5581 closeButton.addEventListener('click', closeButtonHandler); 5582 this.eventListeners.push({ 5583 element: closeButton, 5584 event: 'click', 5585 handler: closeButtonHandler 5586 }); 5587 } 5588 // Listen for backdrop clicks 5589 const backdropClickHandler = (e)=>{ 5590 // Check if click is on the modal backdrop (not on the modal content) 5591 if (e.target === modal || e.target.id === this.modalId) { 5592 modal.style.display = 'none'; 5593 this.restoreBodyScroll(); 5594 } 5595 }; 5596 modal.addEventListener('click', backdropClickHandler); 5597 this.eventListeners.push({ 5598 element: modal, 5599 event: 'click', 5600 handler: backdropClickHandler 5601 }); 5602 } 5603} 5604 5605 5606/* eslint-disable import/prefer-default-export */ 5607class $50eefeef8d1f2372$export$8a2bf06fbae4dde extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5608 constructor(configController, window, document){ 5609 super(configController, window, document); 5610 this.isValidating = false; 5611 this.lastValidationResult = null; 5612 this.lastValidationTime = null; 5613 this.validationCacheDuration = 300000; // 5 minutes 5614 } 5615 /** 5616 * Destroy 5617 */ destroy() { 5618 this.isValidating = false;
5619 this.lastValidationResult = null; 5620 this.lastValidationTime = null; 5621 } 5622 /** 5623 * Validate user session using GraphQL validSession query 5624 * @param {Object} options - Options for session validation 5625 * @param {boolean} options.useCache - Whether to use cached validation result 5626 * @returns {Promise<boolean>} - true if session is valid, false otherwise 5627 */ async validateSession(options = {}) { 5628 const { useCache: useCache = true } = options; 5629 if (useCache && this.lastValidationResult !== null && this.lastValidationTime) { 5630 const timeSinceLastValidation = Date.now() - this.lastValidationTime; 5631 if (timeSinceLastValidation < this.validationCacheDuration) return this.lastValidationResult; 5632 } 5633 if (this.isValidating) return this.lastValidationResult !== null ? this.lastValidationResult : false; 5634 this.isValidating = true; 5635 const query = ` 5636 query { 5637 validSession { 5638 success 5639 } 5640 } 5641 `; 5642 try { 5643 // query from same domain as the website 5644 const response = await this.window.fetch(`/graphql`, { 5645 method: 'POST', 5646 headers: { 5647 'Content-Type': 'application/json' 5648 }, 5649 credentials: 'include', 5650 body: JSON.stringify({ 5651 query: query 5652 }) 5653 }); 5654 if (!response.ok) { 5655 // eslint-disable-next-line no-console 5656 console.error('SessionController: HTTP error during session validation', response.status); 5657 this.lastValidationResult = false;
5658 this.lastValidationTime = Date.now(); 5659 return false; 5660 } 5661 const data = await response.json(); 5662 if (data.errors) { 5663 this.lastValidationResult = false; 5664 this.lastValidationTime = Date.now(); 5665 return false; 5666 } 5667 const isValid = data.data?.validSession?.success === true; 5668 this.lastValidationResult = isValid; 5669 this.lastValidationTime = Date.now(); 5670 return isValid; 5671 } catch (error) { 5672 // eslint-disable-next-line no-console 5673 console.error('SessionController: Error validating session', error); 5674 this.lastValidationResult = false; 5675 this.lastValidationTime = Date.now(); 5676 return false; 5677 } finally{ 5678 this.isValidating = false; 5679 } 5680 } 5681 /** 5682 * Clear validation cache 5683 */ clearCache() { 5684 this.lastValidationResult = null; 5685 this.lastValidationTime = null; 5686 } 5687} 5688 5689 5690/* eslint-disable import/prefer-default-export */ 5691function $396d9f0ca7465335$export$48d5542b9e3ba39(document) { 5692 const match = document.cookie.match(/cookieyes-consent=([^;]+)/); 5693 if (!match) return false; 5694 try { 5695 const cookieValue = decodeURIComponent(match[1]); 5696 if (cookieValue.includes(',')) { 5697 const segments = cookieValue.split(',').map((c)=>c.trim()); 5698 if (segments.some((s)=>s.includes(':'))) return segments.some((s)=>s === 'analytics:yes'); 5699 return segments.includes('analytics'); 5700 } 5701 return cookieValue.includes('analytics'); 5702 } catch (error) { 5703 return false; 5704 } 5705} 5706/** 5707 * Consent providers. Each entry isolates the only things that differ between 5708 * integrations: the change-event name, how to read the *initial* analytics 5709 * consent, and how to interpret a change event's detail. Everything else 5710 * (loading/removing trackers, lifecycle) is shared by the controller. 5711 */ const $396d9f0ca7465335$var$PROVIDERS = { 5712 // Third-party CookieYes banner. 5713 cookieyes: { 5714 eventName: 'cookieyes_consent_update', 5715 hasAnalyticsConsent: (document)=>$396d9f0ca7465335$export$48d5542b9e3ba39(document), 5716 isAnalyticsAccepted: (detail)=>Array.isArray(detail?.accepted) && detail.accepted.includes('analytics') 5717 }, 5718 // LP in-house consent widget (lp-consent-widget). It exposes resolved state on 5719 // window.__lpConsent and emits `lp_consent_update` with detail.choices. 5720 'lp-consent': { 5721 eventName: 'lp_consent_update', 5722 hasAnalyticsConsent: (_document, window)=>!!window.__lpConsent?.state?.c?.analytics, 5723 isAnalyticsAccepted: (detail)=>!!detail?.choices?.analytics 5724 } 5725}; 5726class $396d9f0ca7465335$export$bb018224876724b9 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5727 constructor(config, window, document){ 5728 super(config, window, document); 5729 this.consentListener = null; 5730 this.eventName = null; 5731 } 5732 /** 5733 * Destroy and cleanup event listeners 5734 */ destroy() { 5735 if (this.consentListener && this.eventName) { 5736 this.document.removeEventListener(this.eventName, this.consentListener); 5737 this.consentListener = null; 5738 } 5739 } 5740 /** 5741 * Load PostHog and Divolte scripts (idempotent â guarded by element id). 5742 */ loadScript() { 5743 if (!this.document.getElementById('posthog-script')) this.window.luxuryPresence.eventBus.initialize({ 5744 enabled: this.config.eventBus?.enabled 5745 }); 5746 if (!this.document.getElementById('divolte-script')) this.window.luxuryPresence.divolte.initialize({}); 5747 } 5748 /** 5749 * Remove PostHog and Divolte scripts (used on consent withdrawal). 5750 */ removeScripts() { 5751 this.window.luxuryPresence?.eventBus?.destroy?.(); 5752 this.window.luxuryPresence?.divolte?.destroy?.(); 5753 this.document.getElementById('posthog-script')?.remove(); 5754 this.document.getElementById('divolte-script')?.remove(); 5755 } 5756 /** 5757 * Initialize the consent controller for a given provider. 5758 * @param {{ provider: 'cookieyes' | 'lp-consent' }} options 5759 */ async initialize(options = {}) { 5760 const provider = $396d9f0ca7465335$var$PROVIDERS[options.provider]; 5761 if (!provider) return; 5762 this.eventName = provider.eventName; 5763 const isAuthenticated = await this.window.luxuryPresence.session.validateSession(); 5764 if (provider.hasAnalyticsConsent(this.document, this.window) || isAuthenticated) this.loadScript(); 5765 if (!this.consentListener) { 5766 this.consentListener = (eventData)=>{ 5767 if (provider.isAnalyticsAccepted(eventData.detail)) this.loadScript(); 5768 else this.removeScripts(); 5769 }; 5770 this.document.addEventListener(provider.eventName, this.consentListener); 5771 } 5772 } 5773} 5774 5775 5776/* global window */ /* eslint-disable import/prefer-default-export */ /** 5777 * Checks if the current site should redirect homeowner valuation submissions to HST. 5778 * Returns true and performs the redirect if all three gate conditions are met. 5779 * Returns false if the redirect did not fire (caller should continue with existing flow). 5780 * 5781 * @param {string} address - The human-readable address string from the form 5782 * @returns {boolean} 5783 */ function $0ae243a777665fd3$var$checkHstRedirect(address) { 5784 const { config: config } = window.luxuryPresence; 5785 if (config.hstValuationRedirectEnabled && config.mlsEnabled && config.myhomeDashboardEnabled) { 5786 window.location.href = `/home-search/home-valuation?address=${encodeURIComponent(address)}`; 5787 return true; 5788 } 5789 return false;
5790} 5791const $0ae243a777665fd3$export$4225ff17959c7313 = { 5792 checkHstRedirect: $0ae243a777665fd3$var$checkHstRedirect, 5793 destroy () {} 5794}; 5795 5796 5797// ROUTER-CLEANUP: delete controller when elements are federation-native 5798/* eslint-disable import/prefer-default-export */ 5799// ROUTER-CLEANUP: deletable once all resources are federation-native. 5800// Pure, dependency-free legacy<->router transforms shared by RouterAPIClient 5801// (server) and the browser SDK. Must stay import-free so it bundles into the 5802// client (a test enforces this). The properties MLS response flatten stays in 5803// RouterAPIClient (PLAT-4073). 5804/** GraphQL variables in legacy shape, reconciled in place to the router format. */ /** Narrow an unknown response value to a plain object so a transform can read it. */ function $17bc59838bec5f1a$var$isObject(value) { 5805 return typeof value === 'object' && value !== null && !Array.isArray(value); 5806} 5807// --------------------------------------------------------------------------- 5808// Variable transforms (legacy -> router) 5809// --------------------------------------------------------------------------- 5810/** Delete keys holding an empty array â an empty [ID!] means "match nothing" to the router. */ function $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, keys) { 5811 keys.forEach((key)=>{ 5812 const value = variables[key]; 5813 if (Array.isArray(value) && value.length === 0) /* eslint-disable-next-line no-param-reassign */ delete variables[key]; 5814 }); 5815} 5816/** Normalize an id filter to an array, splitting the legacy space-delimited form. */ function $17bc59838bec5f1a$var$toIdArray(value) { 5817 if (Array.isArray(value)) return value.flatMap((item)=>$17bc59838bec5f1a$var$toIdArray(item)); 5818 if (typeof value === 'string') return value.split(/\s+/).filter(Boolean); 5819 return value == null ? [] : [ 5820 value 5821 ]; 5822} 5823/** 5824 * Move legacy id key(s) onto a router list arg. `sources` is a precedence list 5825 * (first non-empty wins; `merge` unions them). Target stays absent when empty. 5826 */ function $17bc59838bec5f1a$var$promoteIdFilter(variables, sources, target, options) { 5827 const lists = sources.map((key)=>$17bc59838bec5f1a$var$toIdArray(variables[key])); 5828 const ids = options?.merge ? lists.flat() : lists.find((list)=>list.length > 0) ?? []; 5829 /* eslint-disable no-param-reassign */ sources.forEach((key)=>{ 5830 delete variables[key]; 5831 }); 5832 if (ids.length > 0) variables[target] = [ 5833 ...new Set(ids) 5834 ]; 5835/* eslint-enable no-param-reassign */ } 5836/** Multi-key sortDir enum name (`DESC_DESC`) â router string form (`DESC DESC`). */ function $17bc59838bec5f1a$var$normalizeSortDir(variables) { 5837 const { sortDir: sortDir } = variables; 5838 if (typeof sortDir === 'string' && sortDir.includes('_')) /* eslint-disable-next-line no-param-reassign */ variables.sortDir = sortDir.replace(/_/g, ' '); 5839} 5840/** Apply legacy default limits; drop `limit: 0` (router rejects it, legacy read it as "no limit"). */ function $17bc59838bec5f1a$var$setDefaultLimitIfNeeded(variables, resource) { 5841 if (variables.limit === 0) /* eslint-disable-next-line no-param-reassign */ delete variables.limit; 5842 const hasNoLimit = variables.limit === undefined || variables.limit === null; 5843 if (!hasNoLimit) return; 5844 // testimonials: 50 5845 if (resource === 'testimonials' || resource === 'testimonialsCount') /* eslint-disable-next-line no-param-reassign */ variables.limit = 50; 5846 // agents, neighborhoods, pressReleases: 100 5847 if (resource === 'agents' || resource === 'agentsCount' || resource === 'neighborhoods' || resource === 'neighborhoodsCount' || resource === 'pressReleases' || resource === 'pressReleasesCount') /* eslint-disable-next-line no-param-reassign */ variables.limit = 100; 5848} 5849/** agents: officeId/teamId/developmentId â the router's plural list args. */ function $17bc59838bec5f1a$var$transformAgentsVariables(variables) { 5850 $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 5851 'officeId', 5852 'teamId', 5853 'developmentId', 5854 'agentIds', 5855 'tags' 5856 ]); 5857 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5858 'officeId' 5859 ], 'officeIds'); 5860 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5861 'teamId' 5862 ], 'teamIds'); 5863 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5864 'developmentId' 5865 ], 'developmentIds'); 5866} 5867/** neighborhoods: neighborhoodId/neighborhoodIds â neighborhoodId ([String!], plural wins). */ function $17bc59838bec5f1a$var$transformNeighborhoodsVariables(variables) { 5868 $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 5869 'neighborhoodIds', 5870 'neighborhoodId' 5871 ]); 5872 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5873 'neighborhoodIds', 5874 'neighborhoodId' 5875 ], 'neighborhoodId'); 5876} 5877/** properties: rename/promote id filters, split the space-delimited form, coerce ranges to Int. */ function $17bc59838bec5f1a$var$transformPropertiesVariables(variables) { 5878 /* eslint-disable no-param-reassign */ $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 5879 'statusIds', 5880 'statusId', 5881 'propertyTypeIds', 5882 'propertyTypeId', 5883 'propertyId', 5884 'networkId', 5885 'propertyIds', 5886 'agentIds', 5887 'teamIds', 5888 'officeIds', 5889 'neighborhoodIds', 5890 'spaceTypeIds', 5891 'addressState', 5892 'addressCity', 5893 'backfillProviders', 5894 'backfillMLSListingIds', 5895 'backfillMLSAgentIds', 5896 'backfillMLSOfficeIds' 5897 ]); 5898 // Split space-delimited ids that keep their own name (free-text lists excluded). 5899 [ 5900 'propertyIds', 5901 'agentIds', 5902 'teamIds', 5903 'officeIds', 5904 'neighborhoodIds', 5905 'spaceTypeIds', 5906 'backfillMLSListingIds', 5907 'backfillMLSAgentIds', 5908 'backfillMLSOfficeIds' 5909 ].forEach((key)=>$17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5910 key 5911 ], key)); 5912 // statusIds/statusId â propertyStatusId (plural wins). 5913 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5914 'statusIds', 5915 'statusId' 5916 ], 'propertyStatusId'); 5917 // excludeStatusId â excludePropertyStatusId 5918 if (variables.excludeStatusId) { 5919 variables.excludePropertyStatusId = variables.excludeStatusId; 5920 delete variables.excludeStatusId; 5921 }
5922 // propertyTypeIds/propertyTypeId â propertyTypeId; networkId/propertyId â arrays. 5923 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5924 'propertyTypeIds', 5925 'propertyTypeId' 5926 ], 'propertyTypeId'); 5927 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5928 'networkId' 5929 ], 'networkId'); 5930 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5931 'propertyId' 5932 ], 'propertyIds'); 5933 // Price/area ranges Float â Int (bath/bed counts stay Float). 5934 const intRangeKeys = [ 5935 'salesPriceGTE', 5936 'salesPriceLTE', 5937 'leasePriceGTE', 5938 'leasePriceLTE', 5939 'livingSpaceSizeGTE', 5940 'livingSpaceSizeLTE' 5941 ]; 5942 intRangeKeys.forEach((key)=>{ 5943 if (variables[key] != null) variables[key] = Math.trunc(Number(variables[key])); 5944 }); 5945/* eslint-enable no-param-reassign */ } 5946/** developments: agentId array â scalar; neighborhoodId/Ids â neighborhoodIds. */ function $17bc59838bec5f1a$var$transformDevelopmentsVariables(variables) { 5947 /* eslint-disable no-param-reassign */ $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 5948 'agentId', 5949 'neighborhoodIds', 5950 'neighborhoodId', 5951 'developmentIds', 5952 'tag' 5953 ]); 5954 // Router agentId is a scalar String; take the first element of the legacy array. 5955 if (variables.agentId && Array.isArray(variables.agentId)) [variables.agentId] = variables.agentId; 5956 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5957 'neighborhoodIds', 5958 'neighborhoodId' 5959 ], 'neighborhoodIds'); 5960/* eslint-enable no-param-reassign */ } 5961/** posts: order â sort; categoryIds/categoryId â categoryId; drop unsupported postId. */ function $17bc59838bec5f1a$var$transformPostsVariables(variables) { 5962 /* eslint-disable no-param-reassign */ $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 5963 'categoryIds', 5964 'categoryId', 5965 'neighborhoodId' 5966 ]); 5967 if (variables.order !== undefined) { 5968 variables.sort = variables.order; 5969 delete variables.order; 5970 } 5971 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5972 'categoryIds', 5973 'categoryId' 5974 ], 'categoryId'); 5975 if (variables.postId !== undefined) delete variables.postId; 5976/* eslint-enable no-param-reassign */ } 5977/** postCategories: order â sort; categoryId scalar â [String!] (fold legacy categoryIds). */ function $17bc59838bec5f1a$var$transformPostCategoriesVariables(variables) { 5978 /* eslint-disable no-param-reassign */ $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 5979 'categoryId', 5980 'categoryIds' 5981 ]); 5982 if (variables.order !== undefined) { 5983 variables.sort = variables.order; 5984 delete variables.order; 5985 } 5986 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 5987 'categoryIds', 5988 'categoryId' 5989 ], 'categoryId'); 5990/* eslint-enable no-param-reassign */ } 5991/** pressReleases: pressReleaseId â pressReleaseIds. */ function $17bc59838bec5f1a$var$transformPressReleasesVariables(variables) { 5992 $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 5993 'pressReleaseId', 5994 'categories', 5995 'propertyId', 5996 'developmentId', 5997 'agentId', 5998 'teamId' 5999 ]); 6000 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 6001 'pressReleaseId' 6002 ], 'pressReleaseIds'); 6003} 6004/** offices: officeId â officeIds. */ function $17bc59838bec5f1a$var$transformOfficesVariables(variables) { 6005 $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 6006 'officeId', 6007 'officeIds', 6008 'tags' 6009 ]); 6010 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 6011 'officeId' 6012 ], 'officeIds'); 6013} 6014/** teams: teamId â teamIds. */ function $17bc59838bec5f1a$var$transformTeamsVariables(variables) { 6015 $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 6016 'teamId', 6017 'teamIds' 6018 ]); 6019 $17bc59838bec5f1a$var$promoteIdFilter(variables, [ 6020 'teamId' 6021 ], 'teamIds'); 6022} 6023/** testimonials: drop an empty testimonialIds (the singular rename runs in transformVariables). */ function $17bc59838bec5f1a$var$transformTestimonialsVariables(variables) { 6024 $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 6025 'testimonialIds' 6026 ]); 6027} 6028/** pois: lowercase categories/sortBy â the router enums are lowercase. */ function $17bc59838bec5f1a$var$transformPoisVariables(variables) { 6029 /* eslint-disable no-param-reassign */ $17bc59838bec5f1a$var$dropEmptyArrayFilters(variables, [ 6030 'categories' 6031 ]); 6032 if (Array.isArray(variables.categories)) variables.categories = variables.categories.map((category)=>category.toLowerCase()); 6033 if (typeof variables.sortBy === 'string') variables.sortBy = variables.sortBy.toLowerCase(); 6034/* eslint-enable no-param-reassign */ } 6035/** Dispatch to the per-resource variable transform (a *Count resource shares its list transform). */ function $17bc59838bec5f1a$var$applyResourceSpecificTransforms(variables, resource) { 6036 switch(resource){ 6037 case 'agent': 6038 break; 6039 case 'testimonials': 6040 case 'testimonialsCount': 6041 $17bc59838bec5f1a$var$transformTestimonialsVariables(variables); 6042 break; 6043 case 'agents': 6044 case 'agentsCount': 6045 $17bc59838bec5f1a$var$transformAgentsVariables(variables); 6046 break; 6047 case 'neighborhoods': 6048 case 'neighborhoodsCount': 6049 $17bc59838bec5f1a$var$transformNeighborhoodsVariables(variables); 6050 break; 6051 case 'developments': 6052 case 'developmentsCount': 6053 $17bc59838bec5f1a$var$transformDevelopmentsVariables(variables); 6054 break; 6055 case 'properties': 6056 case 'propertiesCount': 6057 $17bc59838bec5f1a$var$transformPropertiesVariables(variables); 6058 break; 6059 case 'posts': 6060 case 'postsCount': 6061 $17bc59838bec5f1a$var$transformPostsVariables(variables); 6062 break; 6063 case 'postCategories': 6064 $17bc59838bec5f1a$var$transformPostCategoriesVariables(variables); 6065 break; 6066 case 'pressReleases': 6067 case 'pressReleasesCount': 6068 $17bc59838bec5f1a$var$transformPressReleasesVariables(variables); 6069 break; 6070 case 'offices': 6071 case 'officesCount': 6072 $17bc59838bec5f1a$var$transformOfficesVariables(variables); 6073 break;
6074 case 'teams': 6075 case 'teamsCount': 6076 $17bc59838bec5f1a$var$transformTeamsVariables(variables); 6077 break; 6078 case 'pois': 6079 $17bc59838bec5f1a$var$transformPoisVariables(variables); 6080 break; 6081 default: 6082 break; 6083 } 6084} 6085function $17bc59838bec5f1a$export$f690fb09fc81d1c(variables, resource) { 6086 const transformed = { 6087 ...variables 6088 }; 6089 // testimonialId â testimonialIds, for every resource. 6090 $17bc59838bec5f1a$var$dropEmptyArrayFilters(transformed, [ 6091 'testimonialId' 6092 ]); 6093 $17bc59838bec5f1a$var$promoteIdFilter(transformed, [ 6094 'testimonialId' 6095 ], 'testimonialIds'); 6096 $17bc59838bec5f1a$var$setDefaultLimitIfNeeded(transformed, resource); 6097 $17bc59838bec5f1a$var$normalizeSortDir(transformed); 6098 $17bc59838bec5f1a$var$applyResourceSpecificTransforms(transformed, resource); 6099 return transformed; 6100} 6101function $17bc59838bec5f1a$export$dad7b3135f67f541(agent) { 6102 const transformed = { 6103 ...agent 6104 }; 6105 // urlWebsite is a direct router field; null the rest for legacy compatibility. 6106 if (!transformed.urlWebsite) transformed.urlWebsite = null; 6107 transformed.urlYoutube = null; 6108 transformed.urlFacebook = null; 6109 transformed.urlInstagram = null; 6110 transformed.urlLinkedin = null; 6111 transformed.urlPodcast = null; 6112 transformed.urlTwitter = null; 6113 if (Array.isArray(agent.socialLinks)) { 6114 // Sorted by type for deterministic legacy/router comparison. 6115 const sortedSocialLinks = [ 6116 ...agent.socialLinks 6117 ].sort((a, b)=>{ 6118 const typeA = a.type?.toLowerCase() || ''; 6119 const typeB = b.type?.toLowerCase() || ''; 6120 return typeA.localeCompare(typeB); 6121 }); 6122 transformed.socialLinks = sortedSocialLinks; 6123 // website is skipped â urlWebsite is a direct field. 6124 const typeToFieldMap = { 6125 youtube: 'urlYoutube', 6126 facebook: 'urlFacebook', 6127 instagram: 'urlInstagram', 6128 linkedin: 'urlLinkedin', 6129 podcast: 'urlPodcast', 6130 twitter: 'urlTwitter' 6131 }; 6132 sortedSocialLinks.forEach((link)=>{ 6133 const fieldName = typeToFieldMap[link.type?.toLowerCase() ?? '']; 6134 if (fieldName) transformed[fieldName] = link.link; 6135 }); 6136 } 6137 return transformed; 6138} 6139function $17bc59838bec5f1a$export$83dd45c763153019(data) { 6140 if (!data || !Array.isArray(data)) return data; 6141 return data.map((agent)=>$17bc59838bec5f1a$export$dad7b3135f67f541(agent)); 6142} 6143function $17bc59838bec5f1a$export$a64ea901e0b976d8(neighborhood) { 6144 const { region: region } = neighborhood; 6145 if (!$17bc59838bec5f1a$var$isObject(region)) return neighborhood; 6146 const { schools: schools, pois: pois, ...restRegion } = region; 6147 const transformedRegion = { 6148 ...restRegion, 6149 schools: $17bc59838bec5f1a$var$isObject(schools) ? schools.data ?? [] : [], 6150 ...Array.isArray(pois) ? { 6151 pois: pois.map((poi)=>({ 6152 ...poi, 6153 category: typeof poi.category === 'string' ? poi.category.toUpperCase() : poi.category 6154 })) 6155 } : {} 6156 }; 6157 return { 6158 ...neighborhood, 6159 region: transformedRegion 6160 }; 6161} 6162function $17bc59838bec5f1a$export$bf09c1c4193bce88(data) { 6163 if (!data || !Array.isArray(data)) return data; 6164 return data.map((neighborhood)=>$17bc59838bec5f1a$export$a64ea901e0b976d8(neighborhood)); 6165} 6166function $17bc59838bec5f1a$export$9430877892a177f4(development) { 6167 const features = development.featuresAndAmenities; 6168 if (!Array.isArray(features)) return development; 6169 const transformedFeaturesAndAmenities = features.map((item)=>({ 6170 featureIds: item.featureIds ?? [],
6171 features: item.features ?? [], 6172 description: item.description 6173 })); 6174 return { 6175 ...development, 6176 featuresAndAmenities: transformedFeaturesAndAmenities 6177 }; 6178} 6179function $17bc59838bec5f1a$export$6c3435e3b453c05e(data) { 6180 if (!data || !Array.isArray(data)) return data; 6181 return data.map((development)=>$17bc59838bec5f1a$export$9430877892a177f4(development)); 6182} 6183/** Run an object transform only when `data` is a plain object; else pass through. */ function $17bc59838bec5f1a$var$reshapeObject(data, transform) { 6184 return $17bc59838bec5f1a$var$isObject(data) ? transform(data) : data; 6185} 6186/** Run a list transform only when `data` is an array; else pass through. */ function $17bc59838bec5f1a$var$reshapeList(data, transform) { 6187 return Array.isArray(data) ? transform(data) : data; 6188} 6189function $17bc59838bec5f1a$export$76cf84e97b98c4f2(data, resource) { 6190 if (resource === 'agent') return $17bc59838bec5f1a$var$reshapeObject(data, $17bc59838bec5f1a$export$dad7b3135f67f541); 6191 if (resource === 'agents' || resource === 'agentsCount') return $17bc59838bec5f1a$var$reshapeList(data, $17bc59838bec5f1a$export$83dd45c763153019); 6192 if (resource === 'neighborhood') return $17bc59838bec5f1a$var$reshapeObject(data, $17bc59838bec5f1a$export$a64ea901e0b976d8); 6193 if (resource === 'neighborhoods' || resource === 'neighborhoodsCount') return $17bc59838bec5f1a$var$reshapeList(data, $17bc59838bec5f1a$export$bf09c1c4193bce88); 6194 if (resource === 'development') return $17bc59838bec5f1a$var$reshapeObject(data, $17bc59838bec5f1a$export$9430877892a177f4); 6195 if (resource === 'developments' || resource === 'developmentsCount') return $17bc59838bec5f1a$var$reshapeList(data, $17bc59838bec5f1a$export$6c3435e3b453c05e); 6196 return data; 6197} 6198 6199 6200class $906836d742071e41$export$d2e054bb0b406919 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 6201 destroy() {} 6202 /** Legacy GraphQL variables -> router format. Returns a new object. */ transformVariables(resource, vars) { 6203 return (0, $17bc59838bec5f1a$export$f690fb09fc81d1c)(vars, resource); 6204 } 6205 /** Router response payload -> legacy shape for the resource. */ transformResponse(resource, page) { 6206 return (0, $17bc59838bec5f1a$export$76cf84e97b98c4f2)(page, resource); 6207 } 6208 /** 6209 * Unwrap a router list field ({ items, total }) to the legacy pair 6210 * ({ items[], count }) the section renders from. Single owner of the router 6211 * page-envelope shape for inlined section scripts. 6212 */ transformPage(page) { 6213 return { 6214 items: page && page.items || [], 6215 count: page && page.total || 0 6216 }; 6217 } 6218} 6219 6220 6221const $fa0280e505379701$export$1fd2b467a3644d37 = new (0, $dc851cf3939b6ef5$export$ff0712c26d5458f7)({}); 6222const $fa0280e505379701$export$e12694e911a05f40 = new (0, $0ead03fdb95fa9ce$export$d507f25e63650365)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6223const $fa0280e505379701$export$3de614e59a842917 = new (0, $d48f9f944810f613$export$ca3218b7861b9cb0)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6224const $fa0280e505379701$export$fb9b298fdbf31455 = new (0, $68a2d4aa500c7a05$export$61ec8f2b6291ec31)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6225const $fa0280e505379701$export$178cc3119b453c2a = new (0, $e10bd00497be8876$export$3c5380623cf51249)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6226const $fa0280e505379701$export$9376af1a01686f2 = new (0, $ea6901fdf47e0ec1$export$3c19195edca3fa5c)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6227const $fa0280e505379701$export$94d36f806562393e = new (0, $0a0ad49f13c0b8fd$export$ba9afeb75f20f616)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6228const $fa0280e505379701$export$89e66d1faf94651e = new (0, $2b1790aa32f109d1$export$43e435c053a109f6)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6229const $fa0280e505379701$export$7743b07270cd6d6c = new (0, $4f184d9bd3037f15$export$7a6215890afba974)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6230const $fa0280e505379701$export$40a7039551318c37 = new (0, $102039871668a1df$export$e22e4b1be0bb6c61)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6231const $fa0280e505379701$export$8a0bbf7e7652fcfc = new (0, $0d25a3fa2e0f4f92$export$b718a981691eae5c)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6232const $fa0280e505379701$export$b313b3f6544c97a3 = new (0, $dcf72769f009ff26$export$b900d6fe921fd49c)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6233const $fa0280e505379701$export$b526bc4ac03268ef = new (0, $50eefeef8d1f2372$exp
6233ort$8a2bf06fbae4dde)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6234const $fa0280e505379701$export$c0affdb0a7a2ef6 = new (0, $396d9f0ca7465335$export$bb018224876724b9)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6235const $fa0280e505379701$export$207cf3f7bf26d59b = new (0, $906836d742071e41$export$d2e054bb0b406919)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 6236 6237 6238/** 6239 * Attach controller to window for usage 6240 * @param {string} key 6241 * @param {any} controller 6242 */ function $89a8a84b77163415$var$attachController(key, controller) { 6243 if (window.luxuryPresence[key]) try { 6244 // New version of sdk, destroy previous 6245 window.luxuryPresence[key].destroy(); 6246 } catch (e) { 6247 // eslint-disable-next-line no-console 6248 console.log(e); 6249 } 6250 window.luxuryPresence[key] = controller; 6251} 6252$89a8a84b77163415$var$attachController('config', (0, $fa0280e505379701$export$1fd2b467a3644d37)); 6253$89a8a84b77163415$var$attachController('modals', (0, $fa0280e505379701$export$e12694e911a05f40)); 6254$89a8a84b77163415$var$attachController('buttons', (0, $fa0280e505379701$export$3de614e59a842917)); 6255$89a8a84b77163415$var$attachController('validation', (0, $fa0280e505379701$export$fb9b298fdbf31455)); 6256$89a8a84b77163415$var$attachController('contactForms', (0, $fa0280e505379701$export$178cc3119b453c2a)); 6257$89a8a84b77163415$var$attachController('mapApiLoader', (0, $fa0280e505379701$export$9376af1a01686f2)); 6258$89a8a84b77163415$var$attachController('pagination', (0, $fa0280e505379701$export$94d36f806562393e)); 6259$89a8a84b77163415$var$attachController('expandSliders', (0, $fa0280e505379701$export$89e66d1faf94651e)); 6260$89a8a84b77163415$var$attachController('divolte', (0, $fa0280e505379701$export$7743b07270cd6d6c)); 6261$89a8a84b77163415$var$attachController('eventBus', (0, $fa0280e505379701$export$40a7039551318c37)); 6262$89a8a84b77163415$var$attachController('oauth', (0, $fa0280e505379701$export$8a0bbf7e7652fcfc)); 6263$89a8a84b77163415$var$attachController('qualifyingQuestionsModal', (0, $fa0280e505379701$export$b313b3f6544c97a3)); 6264$89a8a84b77163415$var$attachController('session', (0, $fa0280e505379701$export$b526bc4ac03268ef)); 6265$89a8a84b77163415$var$attachController('consent', (0, $fa0280e505379701$export$c0affdb0a7a2ef6)); 6266$89a8a84b77163415$var$attachController('redirects', (0, $0ae243a777665fd3$export$4225ff17959c7313)); 6267$89a8a84b77163415$var$attachController('routerApi', (0, $fa0280e505379701$export$207cf3f7bf26d59b)); 6268// methods for existing elements (can be removed later after elements updated) 6269window.luxuryPresence.formatSliderPriceRange = (0, $fa0280e505379701$export$94d36f806562393e).formatSliderPriceRange.bind((0, $fa0280e505379701$export$94d36f806562393e)); 6270window.luxuryPresence.formatSliderAreaRange = (0, $fa0280e505379701$export$94d36f806562393e).formatSliderAreaRange.bind((0, $fa0280e505379701$export$94d36f806562393e)); 6271// method below doesn't use 'this', but just to be safe in case of further method updates 6272window.luxuryPresence.getSearchFormValues = (0, $fa0280e505379701$export$94d36f806562393e).getSearchFormValues.bind((0, $fa0280e505379701$export$94d36f806562393e)); 6273window.luxuryPresence.handlebarsHelpersFactory = function(handlebarsInstance) { 6274 return (0, (/*@__PURE__*/$parcel$interopDefault($53de3c160faf5a81$exports
6274)))(handlebarsInstance, { 6275 isEqual (a, b) { 6276 // eslint-disable-next-line 6277 return a == b; 6278 } 6279 }); 6280}; 6281 6282 6283 6284})(); 6285//# sourceMappingURL=lp-sdk.js.map 6286 6287 </script>
6287 6288 6289
6289<script> 6290 var lpGlobalInitialized = false; 6291 6292 function lpGlobalInit () { 6293 if (lpGlobalInitialized) { 6294 return; 6295 } 6296 lpGlobalInitialized = true; 6297 // Initialize wow animation plugin only according to turbolinks 6298 var wow; 6299 if (window.WOW) { 6300 wow = new WOW({ 6301 animateClass: 'animated', 6302 offset: wowOffset, 6303 live: false, 6304 callback: function(box) {} 6305 }); 6306 } 6307 // Initialize handlebar helpers only once 6308 function handlebarsInit() { 6309 if (!window.Handlebars) { 6310 return; 6311 } 6312 HandlebarsIntl.registerWith(Handlebars); 6313 Handlebars.registerHelper(window.luxuryPresence.handlebarsHelpersFactory(Handlebars)); 6314 } 6315 6316 handlebarsInit(); 6317 6318 var modalContentUrl = "/modals.html"; 6319 const modalsContainer = document.getElementById('modals'); 6320 if (modalsContainer) { 6321 fetch(modalContentUrl).then(function(res) { 6322 if (!res.ok) { 6323 throw new Error(`HTTP error! Status: ${res.status}`); 6324 } 6325 return res.text(); 6326 }).then(function(resultText) { 6327 modalsContainer.innerHTML = resultText; 6328 6329 // now we need to execute all script elements 6330 Array.from(modalsContainer.getElementsByTagName('script')).forEach(function (s) { 6331 const script = document.createElement("script"); 6332 script.text = s.innerHTML; 6333 Array.from(s.attributes).forEach(function (a) { 6334 script.setAttribute(a.name, a.value); 6335 }) 6336 s.parentNode.replaceChild(script, s); 6337 }); 6338 6339 try { 6340 window.luxuryPresence.modals.initialize(window.luxuryPresence._modalIncludes); 6341 window.luxuryPresence.contactForms.initialize({ selector: '#modals' }); 6342 window.luxuryPresence.validation.initialize({ selector: '#modals' }); 6343 window.luxuryPresence.oauth.initialize({ 6344 googleSignOnEnabled: true, 6345 iframe: false }); 6346 } catch (e) { 6347 console.log(e); 6348 } 6349 document.querySelectorAll('.modals > .modal .close').forEach(closeModalBtn => { 6350 closeModalBtn.addEventListener('click', function() { 6351 window.lpUI.hideClosestModal(closeModalBtn); 6352 }); 6353 }); 6354 }).catch((e) => console.log(e)); 6355 } 6356 /* Initialize Luxury Presence SDK */ 6357 try { 6358 window.luxuryPresence.config.setCompany("cccfad5c-784f-4d3e-8950-0449a0ebf171", {}); 6359 window.luxuryPresence.config.setWebsite("069c1329-5dd0-46bd-b643-b325e5b978a5", { 6360 myhomeDashboardEnabled: true, 6361 mlsEnabled: true, 6362 hstValuationRedirectEnabled: true 6363 }); 6364 const url = new URL(window.location.href); 6365 const shareId = url.searchParams.get('shareId'); 6366 window.luxuryPresence.config.setPage("6daa43f6-4fd2-4205-8272-16b414a65774", { 6367 sourceResource: "", 6368 pageElementId: "", 6369 pageQueryVariables: {}, 6370 shareId: "", 6371 }); 6372 window.luxuryPresence.config.setWebsiteApiGatewayUrl("https://wgw.luxurypresence.com", {}); 6373 window.luxuryPresence.config.setBuyerSellerServiceUrl("https://bss.luxurypresence.com", {}); 6374 window.luxuryPresence.config.setDivolteServiceUrl("https://t.luxurypresence.com", {}); 6375 window.luxuryPresence.config.setEventBusUrl("https://cdn.luxurypresence.com/scripts/event-bus-js", {}); 6376 window.luxuryPresence.config.setEventBus({ 6377 enabled: true, 6378 apiKey: "phc_PMYT31xlmXBaTCwpIRx1v6RrpLVZIuP47N3mOT6KLnr", 6379 url: "https://p.luxurypresence.com", 6380 }); 6381 window.luxuryPresence.config.setTemplateId("0c2b9641-6f2a-40f2-a2e0-dabc022eb278", {}); 6382 window.luxuryPresence.config.setLeadIngesterUrl("https://leads.luxurypresence.com", {}); 6383 window.luxuryPresence.buttons.initialize({}); 6384 window.luxuryPresence.consent.initialize({ provider: 'lp-consent' }); 6385 window.luxuryPresence.contactForms.initialize({}); 6386 window.luxuryPresence.validation.initialize({}); 6387 window.luxuryPresence.expandSliders.initialize({}); 6388 window.luxuryPresence.oauth.initialize({ googleSignOnEnabled: true, iframe: false }); 6389 window.luxuryPresence.qualifyingQuestionsModal.initialize({ qualifyingQuestionsModalEnabled: true }); 6390 } catch (e) { 6391 console.log(e); 6392 } 6393 6394 /* Inject Section Specific Javascript */ 6395 try { 6396(function init(sectionDomId) { 6397 const disclaimerLabel = document.querySelector('#' + sectionDomId + ' .lp-tcr-content'); 6398 if (disclaimerLabel) { 6399 const input = disclaimerLabel.querySelector('input'); 6400 if (input) { 6401 input.setAttribute('id', `${sectionDomId}-termsAccepted`); 6402 input.value = 'true'; 6403 const label = document.createElement('label'); 6404 label.setAttribute('for', `${sectionDomId}-termsAccepted`); 6405 label.classList.add('lp-visually-hidden'); 6406 label.textContent = 'Opt in/Disclaimer Consent:'; 6407 disclaimerLabel.prepend(label); 6408 } 6409 } 6410 function setHttp(link) { 6411 if (link.search(/^http[s]?\:\/\/|\//) == -1) { 6412 link = 'https://' + link; 6413 } 6414 return link; 6415 } 6416 const socialLinks = document.querySelectorAll('#' + sectionDomId + ' .socials__link, #' + sectionDomId + ' .lp-socials__link'); 6417 socialLinks.forEach(linkElement => { 6418 const href = linkElement.getAttribute('href'); 6419 if (href) { 6420 linkElement.setAttribute('href', setHttp(href)); 6421 } 6422 }); 6423 const redirectLink = $('#' + sectionDomId + ' .redirect-link'); 6424 if (redirectLink.length) { 6425 const rawHref = setHttp(redirectLink.attr('href')); 6426 let formEvent; 6427 if (rawHref) { 6428 formEvent = redirectLink.data('redirect') ? 'formsubmitted' : 'reset'; 6429 $('#' + sectionDomId + ' .contact-form').find('form').on(formEvent, function () { 6430 redirectLink.attr('href', rawHref); 6431 redirectLink[0].click(); 6432 }); 6433 } 6434 } 6435})('modal-global-contact-us'); 6436} catch(e) { 6437console.log(e); 6438} 6439 6440 try { 6441(function init(sectionDomId) { 6442 const $section = $('#' + sectionDomId); 6443 const $hamburger = $section.find('.hamburger-component'); 6444 function onSideMenuShow() { 6445 if (!$hamburger.hasClass('active')) { 6446 $hamburger.addClass('active'); 6447 } 6448 } 6449 function onSideMenuHide() { 6450 $hamburger.removeClass('active'); 6451 } 6452 const $window = $(window); 6453 $window.on('lpui-sidemenu-show.lpui-auto-clean', onSideMenuShow); 6454 $window.on('lpui-sidemenu-hide.lpui-auto-clean', onSideMenuHide); 6455 const $subContainers = $section.find('.navigation__item.sub-nav-container'); 6456 $subContainers.hover(function () { 6457 $(this).find('.sub-nav').addClass('visible'); 6458 }, function () { 6459 $(this).find('.sub-nav').removeClass('visible'); 6460 }); 6461 $window.on('click.lpui-auto-clean', function () { 6462 $('.sub-nav-container.visible-dropdown').removeClass('visible-dropdown'); 6463 }); 6464 let fixedWidth = 0; 6465 const rightPad = 20; 6466 function fixSubsPosition() { 6467 const wWidth = window.innerWidth; 6468 if (innerWidth === fixedWidth) { 6469 return; 6470 } 6471 fixedWidth = wWidth; 6472 $subContainers.each(function () { 6473 const $sub = $(this).find('.sub-nav'); 6474 $sub[0].style.right = '';
6475 const sRect = $sub[0].getBoundingClientRect(); 6476 const sRight = sRect.left + sRect.width; 6477 if (sRight > wWidth - rightPad) { 6478 const parentRect = $sub[0].offsetParent.getBoundingClientRect(); 6479 const parentRight = parentRect.left + parentRect.width; 6480 $sub[0].style.right = `${parentRight - wWidth + rightPad}px`; 6481 } 6482 }); 6483 } 6484 var debouncer; 6485 $window.on('resize.lpui-auto-clean', function () { 6486 clearTimeout(debouncer); 6487 debouncer = setTimeout(fixSubsPosition, 500); 6488 }); 6489 fixSubsPosition(); 6490 if ($('.property-intro').length || $('.property-intro-2').length) { 6491 $('nav').addClass('dark-opening'); 6492 $("#global-navbar").css({ 6493 "background-color": "rgb(26, 26, 26)", 6494 "color": "rgb(255, 255, 255)" 6495 }); 6496 } 6497 function initAutoTruncateMenu() { 6498 const $navbar = $section.find('.navbar'); 6499 const $navList = $section.find('.navigation > ul'); 6500 if (!$navbar.length || !$navList.length) { 6501 return; 6502 } 6503 const $logo = $section.find('.logo'); 6504 const $buttonsWrapper = $section.find('.buttons-wrapper'); 6505 const $allItems = $navList.children('.navigation__item'); 6506 const $phoneItem = $allItems.filter(function () { 6507 return $(this).find('a[href^="tel:"]').length > 0; 6508 }); 6509 const $menuItems = $allItems.not($phoneItem); 6510 if (!$menuItems.length) { 6511 return; 6512 } 6513 const buffer = 8; 6514 function measureFixedWidth() { 6515 let width = buffer; 6516 if ($logo.length) { 6517 width += $logo.outerWidth(true) || 0; 6518 } 6519 if ($buttonsWrapper.length) { 6520 width += $buttonsWrapper.outerWidth(true) || 0; 6521 } 6522 if ($phoneItem.length) { 6523 width += $phoneItem.outerWidth(true) || 0; 6524 } 6525 return width; 6526 } 6527 function truncateMenu() { 6528 if (!$navList.is(':visible')) { 6529 return; 6530 } 6531 $menuItems.css('display', ''); 6532 const availableWidth = $navbar[0].getBoundingClientRect().width - measureFixedWidth(); 6533 let widthSoFar = 0; 6534 let overflowed = false; 6535 $menuItems.each(function () { 6536 const $item = $(this); 6537 if (overflowed) { 6538 $item.css('display', 'none'); 6539 return; 6540 } 6541 widthSoFar += $item.outerWidth(true); 6542 if (widthSoFar > availableWidth) { 6543 $item.css('display', 'none'); 6544 overflowed = true; 6545 } 6546 }); 6547 } 6548 let truncateFrame; 6549 function scheduleTruncate() { 6550 if (truncateFrame) { 6551 return; 6552 } 6553 truncateFrame = window.requestAnimationFrame(function () { 6554 truncateFrame = null; 6555 truncateMenu(); 6556 }); 6557 } 6558 scheduleTruncate(); 6559 if (window.ResizeObserver) { 6560 const resizeObserver = new ResizeObserver(scheduleTruncate); 6561 resizeObserver.observe($navbar[0]); 6562 } else { 6563 $(window).on('resize.lpui-auto-truncate', scheduleTruncate); 6564 } 6565 $section.find('img').on('load.lpui-auto-truncate', scheduleTruncate); 6566 $(window).on('load.lpui-auto-truncate', scheduleTruncate); 6567 if (document.fonts && document.fonts.ready) { 6568 document.fonts.ready.then(scheduleTruncate); 6569 } 6570 } 6571 initAutoTruncateMenu(); 6572})('global-navbar'); 6573} catch(e) { 6574console.log(e); 6575} 6576 try { 6577(function init(sectionDomId, options) { 6578 var elementSelector = options.elementSelector || 'nav'; 6579 var element = document.querySelector(elementSelector); 6580 var sections = document.querySelectorAll('body > section'); 6581 var subNavContainers = element.querySelectorAll('.sub-nav'); 6582 var initialBackgroundColor = options.initialBackgroundColor || element.style.backgroundColor; 6583 var backgroundColorScroll = options.backgroundColorScroll || '#191919'; 6584 var fontColor = options.fontColor || '#fff'; 6585 var fontColorScroll = options.fontColorScroll || '#000'; 6586 var didScroll = false; 6587 var lastScrollTop = 0; 6588 var delta = 5; 6589 6590 // eslint-disable-next-line sonarjs/no-collapsible-if 6591 if (wow) { 6592 // Wowjs might not trigger for position fixed elements 6593 if (window.scrollY > 0) { 6594 element.querySelectorAll('.wow').forEach(el => wow.show(el)); 6595 } 6596 } 6597 function adjustNavPinState() { 6598 // Remove 'visible' class from all subNavContainers 6599 for (let i = 0; i < subNavContainers.length; i++) { 6600 subNavContainers[i].classList.remove('visible'); 6601 } 6602 if (window.scrollY > 0) { 6603 element.style.backgroundColor = backgroundColorScroll; 6604 element.style.color = fontColorScroll; 6605 element.classList.add('scroll'); 6606 } else {
6607 element.style.backgroundColor = initialBackgroundColor; 6608 element.style.color = fontColor; 6609 element.classList.remove('scroll'); 6610 } 6611 } 6612 adjustNavPinState(); 6613 function onScroll() { 6614 didScroll = true; 6615 } 6616 window.addEventListener('scroll', onScroll); 6617 6618 // eslint-disable-next-line 6619 var debounceInterval = setInterval(() => { 6620 if (didScroll) { 6621 // eslint-disable-next-line 6622 hasScrolled(); 6623 didScroll = false; 6624 } 6625 }, 250); 6626 function hasScrolled() { 6627 adjustNavPinState(); 6628 // eslint-disable-next-line 6629 var navbarHeight = element.offsetHeight; 6630 // eslint-disable-next-line 6631 var st = window.scrollY; 6632 6633 // Make sure they scroll more than delta 6634 if (Math.abs(lastScrollTop - st) <= delta) { 6635 return; 6636 } 6637 if (st > lastScrollTop && st > navbarHeight) { 6638 // Scroll Down 6639 element.style.transform = `translateY(-${navbarHeight}px) scaleY(0)`; 6640 document.documentElement.style.setProperty('--global-header-height', '0px'); 6641 6642 // Some sections "follow" the navbar with class sticky (i.e. Producer search) 6643 sections.forEach(section => { 6644 if (section.classList.contains('sticky')) { 6645 section.style.top = '0px'; 6646 } 6647 }); 6648 } else { 6649 // Scroll Up 6650 // eslint-disable-next-line 6651 if (st + window.innerHeight < document.documentElement.scrollHeight) { 6652 element.style.transform = `translateY(0) scaleY(1)`; 6653 document.documentElement.style.setProperty('--global-header-height', `${navbarHeight}px`); 6654 sections.forEach(section => { 6655 if (section.classList.contains('sticky')) { 6656 section.style.top = `${navbarHeight}px`; 6657 } 6658 }); 6659 } 6660 } 6661 lastScrollTop = st; 6662 } 6663})('NAVBAR', JSON.parse("{\"fontColor\":\"#fff\",\"elementSelector\":\"nav\",\"fontColorScroll\":\"#fff\",\"initialFontColor\":\"#fff\",\"backgroundColorScroll\":\"#1a1a1a\",\"initialBackgroundColor\":\"rgba(0,0,0,0)\"}")); 6664} catch(e) { 6665console.log(e); 6666} 6667 try { 6668(function init(sectionDomId) { 6669 var sidemenu = $('#' + sectionDomId); 6670 sidemenu.on('lpui-sidemenu-show.lpui-auto-clean', function () { 6671 window.lpUI.requestScrollLock(sectionDomId); 6672 }); 6673 $(window).on('lpui-sidemenu-hide.lpui-auto-clean', function () { 6674 window.lpUI.releaseScrollLock(sectionDomId); 6675 }); 6676 $(window).click(function (e) { 6677 let targetContactForm = $(e.target).closest('#modal-global-contact-us').length; 6678 let targetSideMenu = $(e.target).closest('.sidemenu').length; 6679 let targetContactItem = $(e.target).closest('[data-type="CONTACT_US"]').length; 6680 let targetHamburger = $(e.target).closest('.hamburger-component').length; 6681 if (!(targetContactForm || targetSideMenu || targetContactItem || targetHamburger)) { 6682 $('body').removeClass('locked'); 6683 $('.hamburger').removeClass('active'); 6684 $('.sidemenu').removeClass('visible'); 6685 $('#modal-global-contact-us').removeClass('visible'); 6686 } 6687 }); 6688})('global-sidemenu'); 6689} catch(e) { 6690console.log(e); 6691} 6692 6693 try { 6694(function init(footerId) { 6695 var textContent = $(".text_content_wrap p").text().trim().length; 6696 const socialLinks = $(`#${footerId} .lp-socials__link`); 6697 if (textContent < 1) { 6698 $(".text_content_wrap").remove(); 6699 $(".second_text_footer").css({ 6700 'margin-bottom': 0 6701 }); 6702 } 6703 if (socialLinks.length > 0) { 6704 socialLinks.attr('data-wow-offset', '10'); 6705 } 6706 if ($(window).width() > 1280) { 6707 let footer = document.querySelector("#" + footerId); 6708 let copyrightElem = footer.querySelector(".copy_zone"); 6709 if (copyrightElem) { 6710 copyrightElem.style.whiteSpace = "nowrap"; 6711 let nowrapElemWidth = copyrightElem.clientWidth; 6712 copyrightElem.style.whiteSpace = ""; 6713 let normalElemWidth = copyrightElem.clientWidth; 6714 if (nowrapElemWidth > normalElemWidth) { 6715 footer.querySelector(".form-col--socials").classList.add("form-col--xl-auto"); 6716 } 6717 } 6718 } 6719 const form = $("#" + footerId).find("form"); 6720 const redirectLink = $('#' + footerId + ' .redirect-link'); 6721 form.on("reset", function () { 6722 redirectPage(redirectLink); 6723 }); 6724 function redirectPage(link) { 6725 if (link.length) { 6726 const rawHref = link.attr('href'); 6727 link.attr('href', setHttp(rawHref)); 6728 link[0].click(); 6729 } 6730 } 6731 function setHttp(link) { 6732 if (link.search(/^http[s]?\:\/\/|\//) == -1) { 6733 link = 'http://' + link; 6734 } 6735 return link; 6736 } 6737})('global-footer'); 6738} catch(e) { 6739console.log(e); 6740} 6741 6742 try { 6743(function init(sectionDomId) { 6744 var _section = $('#' + sectionDomId); 6745 var _footer = document.getElementById('global-footer'); 6746 const redirectLink = _section.find('.js-redirect-link'); 6747 function setHttp(link) { 6748 if (link.search(/^(http[s]?\:\/\/|\/)/) == -1) { 6749 link = 'https://' + link; 6750 } 6751 return link; 6752 } 6753 function redirectPage(link) { 6754 if (link.length) { 6755 window.location.href = setHttp(link.attr('href')); 6756 } 6757 } 6758 const emailInput = _section.find('.js-email-input'); 6759 const emailRegex = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~\-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+/; 6760 emailInput.on('input', function () { 6761 if (emailRegex.test(this.value)) { 6762 this.setCustomValidity(''); 6763 } else { 6764 this.setCustomValidity('Please enter a valid email address.'); 6765 } 6766 this.reportValidity(); 6767 }); 6768 _section.find('input[name="name"]').on("keyup", function () { 6769 if (this.value.replaceAll(/\d/g, "").trim().split(" ").length < 2 || this.value.replaceAll(/\d/g, "").trim() === "") { 6770 this.setCustomValidity("Please input your first name and last name."); 6771 } else { 6772 this.setCustomValidity(""); 6773 } 6774 }); 6775 _section.find('form').on("reset", function () { 6776 $(this).addClass("show-success"); 6777 redirectPage(redirectLink); 6778 }); 6779 $(window).scroll(function () { 6780 if ($(this).scrollTop() >= 150) _section.find('.btn-holder').addClass('visible');else _section.find('.btn-holder').removeClass('visible'); 6781 }); 6782 _section.find('.close-btn, .connect-btn').click(function () { 6783 _section.find('.pop-up').toggle(); 6784 _section.find('.btn-holder').toggle(); 6785 }); 6786 if (!_footer) return; 6787 const observer = new IntersectionObserver(entries => {
6788 entries.forEach(entry => { 6789 if (entry.isIntersecting) _section.hide();else _section.show(); 6790 }); 6791 }, { 6792 threshold: 0.1 6793 }); 6794 observer.observe(_footer); 6795 function selectToDropdown(selectItem) { 6796 let customDropdown = ` 6797 <div class="custom-select" role="presentation"> 6798 <button class="custom-select-toggle is-placeholder" type="button" aria-haspopup="true" aria-expanded="false"></button> 6799 <div class="custom-select-menu" style="display: none;max-height: none;"> 6800 <div class="custom-select-content"> 6801 </div> 6802 </div> 6803 </div>`; 6804 $(customDropdown).insertAfter(selectItem); 6805 let $dropdown = $($(selectItem).next()); 6806 let $dropdownToggle = $dropdown.find(".custom-select-toggle"); 6807 let $dropdownMenu = $dropdown.find(".custom-select-menu"); 6808 let $dropdownContent = $dropdown.find(".custom-select-content"); 6809 $dropdownToggle.addClass($(selectItem).attr("class")).removeClass("dropdown-select"); 6810 $dropdownToggle.attr("id", $(selectItem).attr("id") + "custom"); 6811 $dropdownMenu.attr("aria-labelledby", $dropdownToggle.attr("id")); 6812 appendOptionButtons(selectItem, $dropdownContent); 6813 $(selectItem).removeClass().addClass("sr-only"); 6814 var toggleText = $(selectItem).find(":selected").first().text() || $(selectItem).children().first().text(); 6815 $dropdownToggle.html(toggleText); 6816 $dropdown.on("click", ".custom-select-item", function (e) { 6817 if ($(this).hasClass("is-disabled")) return; 6818 let elementNumber = $(this).index(); 6819 let $originalSelect = $(this).closest(".custom-select").siblings("select"); 6820 let $linkedOption = $originalSelect.find("option").eq(elementNumber); 6821 if (!$linkedOption.prop("selected")) { 6822 $linkedOption.prop("selected", true); 6823 $originalSelect.change(); 6824 $(this).addClass("is-selected").siblings(".custom-select-item").removeClass("is-selected"); 6825 $dropdownToggle.html($(this).html()); 6826 closeSelectMenu($(this).closest(".custom-select-menu")); 6827 } 6828 $dropdownToggle.removeClass("is-placeholder"); 6829 }); 6830 function convertOptionToButton(option) { 6831 var optionText = $(option).text(); 6832 var optionValue = $(option).attr("value") || $(option).text(); 6833 var optionIsDisabled = $(option).prop("disabled"); 6834 var outputButton = `<button value="${optionValue}" class="custom-select-item" type="button" ${optionIsDisabled ? "disabled" : ""}>${optionText}</button>`; 6835 return outputButton; 6836 } 6837 function appendOptionButtons(selectItem, appendTarget) { 6838 $(selectItem).find("option").each(function () { 6839 let currentButton = convertOptionToButton(this); 6840 $(appendTarget).append(currentButton); 6841 }); 6842 } 6843 function showSelectMenu(selectMenu) { 6844 var customSelect = $(selectMenu).closest(".custom-select")[0]; 6845 $(customSelect).addClass("open"); 6846 $(selectMenu).slideDown(); 6847 } 6848 function closeSelectMenu(selectMenu) { 6849 var customSelect = $(selectMenu).closest(".custom-select")[0]; 6850 $(customSelect).removeClass("open"); 6851 $(selectMenu).slideUp(); 6852 } 6853 $dropdown.on("click", ".custom-select-toggle", function (e) { 6854 var $customSelect = $(this).closest(".custom-select"); 6855 var selectMenu = $customSelect.find(".custom-select-menu")[0]; 6856 if ($customSelect.hasClass("open")) { 6857 closeSelectMenu(selectMenu); 6858 } else { 6859 showSelectMenu(selectMenu); 6860 } 6861 }); 6862 $(document).on("click", function (e) { 6863 if ($(e.target).closest(".custom-select").length < 1 && $(".custom-select").hasClass("open")) { 6864 $(".custom-select.open").each(function () { 6865 var selectMenu = $(this).find(".custom-select-menu")[0]; 6866 closeSelectMenu(selectMenu); 6867 }); 6868 } 6869 }); 6870 } 6871 $(".pop-up select[name='interest']").each(function () { 6872 selectToDropdown(this); 6873 }); 6874})('global-mobile-contact'); 6875} catch(e) { 6876console.log(e); 6877} 6878 6879 try { 6880(function init(sectionDomId) {})('section-aaaa421e-7c8d-4472-bfab-8e962f13cf02', 'undefined'); 6881} catch(e) { 6882console.log(e); 6883} 6884 try { 6885(function init(sectionDomId) { 6886 const $section = $('#' + sectionDomId); 6887 const $form = $section.find('.custom-form__download-form'); 6888 const redirectLink = $section.find('.js-redirect-link'); 6889 function redirectPage(link) { 6890 if (link.length) { 6891 const rawHref = link.attr('href'); 6892 link.attr('href', setHttp(rawHref)); 6893 link[0].click(); 6894 } 6895 } 6896 function setHttp(link) { 6897 if (link.search(/^http[s]?\:\/\/|\//) == -1) { 6898 link = 'https://' + link; 6899 } 6900 return link; 6901 } 6902 $form.on('reset', function () { 6903 redirectPage(redirectLink); 6904 }); 6905 var backupEmailField = $section.find('.js-backup-email'); 6906 if (backupEmailField) { 6907 var dynEmailField = $section.find('input.js-form-element[name="email"]:not(.js-backup-field)'); 6908 if (dynEmailField.length === 0) { 6909 backupEmailField.removeClass('js-backup-email'); 6910 } else { 6911 backupEmailField.remove(); 6912 } 6913 } 6914 var $allElements = $section.find('.js-form-element'); 6915 const putAllInMessage = false;
6916 var hasCustomFields = false; 6917 const standardFields = { 6918 'name': true, 6919 'email': true, 6920 'phone': true, 6921 'message': true, 6922 'interest': true 6923 }; 6924 const busyFormNames = { 6925 'address': true, 6926 'city': true, 6927 'state': true, 6928 'postalCode': true, 6929 'mlsId': true, 6930 'sourceUrl': true 6931 }; 6932 $allElements.each(function () { 6933 var $el = $(this); 6934 var name = this.hasAttribute('data-name') ? $el.attr('data-name') : $el.attr('name'); 6935 if (!name) { 6936 return; 6937 } 6938 if (!standardFields[name]) { 6939 hasCustomFields = true; 6940 } 6941 let newName = /[^a-z\d-_]/.test(name) ? name.trim().toLowerCase().replace(/[^a-z\d-_]/g, '-') : name; 6942 if (!/^[a-z]/.test(newName)) { 6943 newName = 'fld-' + newName; 6944 } 6945 if (busyFormNames[newName]) { 6946 let idx = 1; 6947 while (busyFormNames[`${newName}-${idx}`] && idx < 100) { 6948 idx++; 6949 } 6950 newName = `${newName}-${idx}`; 6951 } 6952 busyFormNames[newName] = $el; 6953 if (name !== newName) { 6954 $el.attr('name', newName); 6955 } 6956 }); 6957 let $customFields = []; 6958 if (putAllInMessage && hasCustomFields) { 6959 $allElements.each(function () { 6960 var name = this.getAttribute('name'); 6961 if (name && (!standardFields[name] || name === 'message' && !$(this).hasClass('js-composed-message'))) { 6962 this.setAttribute('data-name', name); 6963 this.removeAttribute('name'); 6964 } 6965 if (this.hasAttribute('data-name')) { 6966 $customFields.push($(this)); 6967 } 6968 }); 6969 if (!$form[0].elements['message']) { 6970 $('<input type="hidden" name="message" class="js-composed-message" value="">').appendTo($form); 6971 } 6972 } 6973 $selects = $section.find('select.js-select'); 6974 var $checkboxGroups = $section.find('.js-checkboxes-group'); 6975 if ($checkboxGroups.length) { 6976 $checkboxGroups.each(function () { 6977 var $group = $(this); 6978 if (!$group.data('required')) return; 6979 var $checkboxes = $group.find('.js-multi-checkbox'); 6980 function updateValidity() { 6981 var anyChecked = $group.find('.js-multi-checkbox:checked').length > 0; 6982 $checkboxes.each(function () { 6983 this.setCustomValidity(anyChecked ? '' : 'Please select at least one option.'); 6984 }); 6985 } 6986 updateValidity(); 6987 $checkboxes.on('change', updateValidity); 6988 }); 6989 $form.on('submit', function () { 6990 $checkboxGroups.each(function () { 6991 var $group = $(this); 6992 var name = $group.data('name'); 6993 if (!name) return; 6994 var checked = $group.find('.js-multi-checkbox:checked').map(function () { 6995 return this.value; 6996 }).get().join(', '); 6997 $form.find('input[type="hidden"][data-checkbox-group="' + name + '"]').remove(); 6998 $('<input type="hidden">').attr('name', name).val(checked).attr('data-checkbox-group', name).appendTo($form); 6999 var $groupCheckboxes = $group.find('.js-multi-checkbox'); 7000 $groupCheckboxes.prop('disabled', true); 7001 setTimeout(function () { 7002 $groupCheckboxes.prop('disabled', false); 7003 }, 0); 7004 }); 7005 }); 7006 } 7007 let selectsInitialized = false; 7008 function initializeSelects() { 7009 if (selectsInitialized) { 7010 return; 7011 } 7012 selectsInitialized = true; 7013 $selects.each(function () { 7014 if (this.id) { 7015 $label = $section.find('[for="' + this.id + '"]'); 7016 if ($label.length) { 7017 var rect = $label[0].getBoundingClientRect(); 7018 if (rect && rect.width < 30) { 7019 var firstOption = $(this).find('option').first(); 7020 firstOption.attr('label', firstOption.data('label')); 7021 } 7022 } 7023 $gr = $(this).closest('.lp-input-group'); 7024 var b = $gr.css('border-left-width'); 7025 if (b && b !== '0px') { 7026 $gr[0].style.setProperty('--uf-border-left', b); 7027 } 7028 b = $gr.css('border-right-width'); 7029 if (b && b !== '0px') { 7030 $gr[0].style.setProperty('--uf-border-right', b); 7031 } 7032 } 7033 }); 7034 var csPrefix = 'uf-cus-sel'; 7035 function convertSelectToDropdown(selectItem) { 7036 const $selectItem = $(selectItem); 7037 const selectId = $selectItem.attr('id'); 7038 const id = $selectItem.attr('id') + '-custom-select'; 7039 let $dropdown = $selectItem.next(); 7040 let initialized = true; 7041 if ($dropdown.attr('id') !== id) { 7042 $selectItem.addClass("sr-only"); 7043 initialized = false;
7044 let customDropdown = ` 7045 <div class="${csPrefix}" role="presentation"> 7046 <button class="${csPrefix}-toggle" type="button" aria-haspopup="true" aria-expanded="false"></button> 7047 <div class="${csPrefix}-menu"> 7048 <div class="${csPrefix}-content"> 7049 </div> 7050 </div> 7051 </div>`; 7052 $(customDropdown).insertAfter(selectItem); 7053 $dropdown = $selectItem.next(); 7054 $dropdown.attr('id', id); 7055 } 7056 let $dropdownToggle = $dropdown.find('.' + csPrefix + '-toggle'); 7057 let $dropdownMenu = $dropdown.find('.' + csPrefix + '-menu'); 7058 let $dropdownContent = $dropdown.find('.' + csPrefix + '-content'); 7059 if (!initialized) { 7060 $dropdownToggle.addClass($selectItem.attr("class")).removeClass(['dropdown-select', 'js-select', 'js-form-element', 'sr-only']); 7061 $dropdownToggle.attr("id", id + '-toggle'); 7062 $dropdownMenu.attr("aria-labelledby", $dropdownToggle.attr("id")); 7063 appendOptionButtons(selectItem, $dropdownContent); 7064 } 7065 $selectItem.on("focus", function () { 7066 showSelectMenu($dropdownMenu[0]); 7067 $dropdownToggle.focus(); 7068 }); 7069 function setInitialValue() { 7070 $dropdownMenu.find('.' + csPrefix + '-item').removeClass('is-selected'); 7071 var $selectedOption = $selectItem.find(':selected').first(); 7072 if (!$selectedOption.length) { 7073 $selectedOption = $selectItem.children().first(); 7074 } 7075 var defaultText = ' '; 7076 var isPlaceholder = true; 7077 if ($selectedOption.length) { 7078 defaultText = ($selectedOption[0].hasAttribute('label') ? $selectedOption.attr('label') : $selectedOption.text()) || ' '; 7079 isPlaceholder = !!$selectedOption.prop("disabled"); 7080 } 7081 $dropdownToggle.html(defaultText); 7082 if (isPlaceholder) { 7083 $dropdownToggle.addClass('is-placeholder'); 7084 } 7085 } 7086 setInitialValue(); 7087 $dropdown.on("click", '.' + csPrefix + '-item', function (e) { 7088 const $button = $(this); 7089 if ($button.hasClass("is-disabled")) return; 7090 let elementNumber = $button.index(); 7091 let $linkedOption = $selectItem.find("option").eq(elementNumber); 7092 if (!$linkedOption.prop("selected")) { 7093 $linkedOption.prop("selected", true); 7094 $selectItem.change(); 7095 $button.addClass("is-selected").siblings('.' + csPrefix + '-item').removeClass("is-selected"); 7096 $dropdownToggle.removeClass("is-placeholder").html($button.html()); 7097 closeSelectMenu($button.closest('.' + csPrefix + '-menu')); 7098 } 7099 }); 7100 $(selectItem.form).on('reset', function () { 7101 setTimeout(function () { 7102 setInitialValue(); 7103 }); 7104 }); 7105 function convertOptionToButton(option) { 7106 const $option = $(option); 7107 var optionText = $option.text(); 7108 var optionValue = $option.attr("value"); 7109 var optionIsDisabled = $option.prop("disabled"); 7110 var outputButton = `<button value="${optionValue}" class="${csPrefix}-item" type="button" ${optionIsDisabled ? "disabled" : ""}>${optionText}</button>`; 7111 return outputButton; 7112 } 7113 function appendOptionButtons(selectItem, appendTarget) { 7114 const $appendTarget = $(appendTarget); 7115 $(selectItem).find("option").each(function () { 7116 let currentButton = convertOptionToButton(this); 7117 $appendTarget.append(currentButton); 7118 }); 7119 } 7120 function showSelectMenu(selectMenu) { 7121 var $customSelect = $(selectMenu).closest('.' + csPrefix); 7122 $customSelect.addClass("open"); 7123 $(selectMenu).slideDown(); 7124 } 7125 function closeSelectMenu(selectMenu) { 7126 var $customSelect = $(selectMenu).closest('.' + csPrefix); 7127 $customSelect.removeClass("open"); 7128 $(selectMenu).slideUp(); 7129 } 7130 $dropdown.on("click", '.' + csPrefix + '-toggle', function (e) { 7131 var $customSelect = $(this).closest('.' + csPrefix); 7132 var selectMenu = $customSelect.find('.' + csPrefix + '-menu')[0]; 7133 if ($customSelect.hasClass("open")) { 7134 closeSelectMenu(selectMenu); 7135 } else { 7136 showSelectMenu(selectMenu); 7137 } 7138 }); 7139 $(document.body).on("click", function (e) { 7140 var $closestCustomSelect = $(e.target).closest('.lp-input-group').find('.' + csPrefix); 7141 $section.find('.' + csPrefix + '.open').not($closestCustomSelect).each(function () { 7142 closeSelectMenu($(this).find('.' + csPrefix + '-menu')[0]); 7143 }); 7144 }); 7145 } 7146 $selects.each(function () { 7147 convertSelectToDropdown(this); 7148 }); 7149 if (putAllInMessage && hasCustomFields) { 7150 $allElements.on('change', function () { 7151 if (!this.hasAttribute('data-name')) { 7152 return; 7153 } 7154 var message = ''; 7155 var customMessages = []; 7156 $customFields.forEach(function ($el) { 7157 var value = $el.val(); 7158 if (!value) { 7159 return; 7160 } 7161 if ($el.attr('data-name') === 'message') { 7162 message = value; 7163 return; 7164 } 7165 var label = $section.find(`label[for='${$el[0].id}']`).text(); 7166 customMessages.push(label + ': ' + ($el[0].tagName === 'TEXTAREA' ? '\n' : '') + value); 7167 }); 7168 if (customMessages.length) { 7169 if (message) { 7170 customMessages.push('Message: \n' + message); 7171 } 7172 $form[0].elements['message'].value = customMessages.join('\n'); 7173 } else { 7174 $form[0].elements['message'].value = message; 7175 } 7176 }); 7177 } 7178 } 7179 function initModalColors() { 7180 try { 7181 if (!$section.css('--bgColor')) { 7182 var colorStr = $section.css('background-color'); 7183 var bgColor = makeColor(colorStr); 7184 var isDark = (bgColor.rgba.r * 299 + bgColor.rgba.g * 587 + bgColor.rgba.b * 114) / 1000 < 128; 7185 $section[0].style.setProperty('--bgColor', colorStr); 7186 $section[0].style.setProperty('--bgColor_H', bgColor.hsla.h + 'deg'); 7187 $section[0].style.setProperty('--bgColor_S', bgColor.hsla.s + '%'); 7188 $section[0].style.setProperty('--bgColor_L', bgColor.hsla.l + '%'); 7189 $section[0].style.setProperty('--bgColor_A', bgColor.hsla.a); 7190 $section[0].style.setProperty('--bgColor_darkenDir', isDark ? 1 : -1); 7191 $section.addClass('is-background-color-' + (isDark ? 'dark' : 'light')); 7192 } 7193 } catch (e) {} 7194 } 7195 function makeColor(str) { 7196 var color = { 7197 rgba: { 7198 r: 0, 7199 g: 0, 7200 b: 0, 7201 a: 0 7202 } 7203 }; 7204 if (str && str.match) { 7205 var m = str.match(/rgba?\s*\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\.0-9]+))?\)/); 7206 if (m) { 7207 color.rgba.r = parseInt(m[1]); 7208 color.rgba.g = parseInt(m[2]); 7209 color.rgba.b = parseInt(m[3]); 7210 color.rgba.a = parseFloat(m[4]); 7211 if (isNaN(color.rgba.a)) { 7212 color.rgba.a = 1; 7213 } 7214 } 7215 } 7216 color.hsla = makeHSLA(color.rgba); 7217 return color; 7218 } 7219 function makeHSLA(rgba) { 7220 var r = rgba.r / 255, 7221 g = rgba.g / 255, 7222 b = rgba.b / 255, 7223 a = rgba.a; 7224 var min = Math.min(r, g, b), 7225 max = Math.max(r, g, b), 7226 l = (max + min) / 2, 7227 d = max - min, 7228 h, 7229 s; 7230 switch (max) { 7231 case min: 7232 h = 0; 7233 break; 7234 case r: 7235 h = 60 * (g - b) / d; 7236 break; 7237 case g: 7238 h = 60 * (b - r) / d + 120; 7239 break; 7240 case b: 7241 h = 60 * (r - g) / d + 240; 7242 break; 7243 } 7244 if (max == min) { 7245 s = 0; 7246 } else if (l < .5) { 7247 s = d / (2 * l); 7248 } else { 7249 s = d / (2 - 2 * l); 7250 } 7251 s *= 100; 7252 l *= 100; 7253 return { 7254 h: h, 7255 s: s, 7256 l: l, 7257 a: a 7258 }; 7259 } 7260 if ($section.is('.modal')) { 7261 initModalColors(); 7262 $section.on('lpui-show', function () { 7263 window.lpUI.requestScrollLock(sectionDomId); 7264 }); 7265 $section.on('lpui-hide', function () { 7266 window.lpUI.releaseScrollLock(sectionDomId); 7267 }); 7268 } 7269 initializeSelects(); 7270 var $addressInputs = $section.find('.js-address-autocomplete'); 7271 if ($addressInputs.length && window.luxuryPresence && window.luxuryPresence.mapApiLoader) { 7272 window.luxuryPresence.mapApiLoader.load().then(function () { 7273 var autocompleteOptions = { 7274 types: ['geocode'], 7275 fields: ['formatted_address'] 7276 }; 7277 $addressInputs.each(function () { 7278 var input = this; 7279 var autocomplete = new google.maps.places.Autocomplete(input, autocompleteOptions); 7280 autocomplete.addListener('place_changed', function () { 7281 var place = autocomplete.getPlace(); 7282 if (place && place.formatted_address) { 7283 input.value = place.formatted_address; 7284 } 7285 }); 7286 }); 7287 }); 7288 } 7289})('section-a0b227b5-4d77-45c4-9ae4-c8b55e185a72', 'undefined'); 7290} catch(e) { 7291console.log(e); 7292} 7293 try { 7294(function init(sectionDomId) {})('section-7819d273-7c47-485a-a46c-0941f4a0491f', 'undefined'); 7295} catch(e) { 7296console.log(e); 7297} 7298 try { 7299(function init(sectionDomId, options) { 7300 let section = null; 7301 switch (sectionDomId) { 7302 case 'NAVBAR': 7303 section = document.querySelector('body > nav, #global-navbar'); 7304 break; 7305 case 'FOOTER': 7306 section = document.querySelector('body > footer, #global-footer'); 7307 break; 7308 case 'SIDEMENU': 7309 section = document.querySelector('body > div.sidemenu, #global-sidemenu'); 7310 break; 7311 case 'CONTACT':
7312 section = document.querySelector('#modal-global-contact-us'); 7313 break; 7314 case 'MOBILE_CONTACT': 7315 section = document.querySelector('body > div.mobile-contact-wrapper, #global-mobile-contact'); 7316 break; 7317 case 'SUBSCRIBE': 7318 // Subscribe Not Implemented 7319 section = null; 7320 break; 7321 case 'ACCOUNT': 7322 // Account Not Implemented 7323 section = null; 7324 break; 7325 default: 7326 section = document.querySelector('#' + sectionDomId); 7327 } 7328 if (!section) { 7329 return; 7330 } 7331 var url = window.luxuryPresence.defaults.routerUrl; 7332 var companyId = window.luxuryPresence.defaults.companyId; 7333 var limit = options.limit || 8; 7334 if (typeof limit === 'string') { 7335 limit = parseInt(limit, 10) || 8; // this NaN protection also filters out 0 - this is expected 7336 } 7337 var templateSelector = options.templateSelector || '.jsIGTemplate'; 7338 var containerSelector = options.containerSelector || '.jsIGContainer'; 7339 var hasDataClass = options.hasDataClass || 'has-data'; 7340 var hideActivateMessage = options.hasDataClass || false; 7341 var payload = { 7342 companyId: companyId, 7343 limit: limit 7344 }; 7345 if (options.resourceId && typeof options.resourceId === 'string' && !options.resourceId.match(/^{{.*}}$/)) { 7346 payload.resourceId = options.resourceId; 7347 // Federated enum values are uppercase (AGENT/TEAM); element configs carry lowercase 7348 payload.resource = String(options.resource || 'agent').toUpperCase(); 7349 payload.fallbackToNoResource = options.fallbackToNoResource === 'true' || options.fallbackToNoResource === true; 7350 } 7351 var query = 'query InstagramFeed (\n' + ' $companyId: ID!\n' + ' $instagramAuthorizationId: ID\n' + ' $username: String\n' + (payload.resourceId ? '$resource: InstagramContentAuthResourceEnum\n $resourceId: ID\n $fallbackToNoResource: Boolean' : '') + ' $limit: Int\n' + ') {\n' + ' instagramContentFeed (\n' + ' companyId: $companyId\n' + ' instagramAuthorizationId: $instagramAuthorizationId\n' + ' username: $username\n' + (payload.resourceId ? 'resource: $resource\n resourceId: $resourceId\n fallbackToNoResource: $fallbackToNoResource' : '') + ' limit: $limit\n' + ' ) {\n' + ' active\n' + ' feedUrl\n' + ' username\n' + ' items {\n' + ' id\n' + ' caption\n' + ' commentsCount\n' + ' likeCount\n' + ' mediaType\n' + ' mediaUrl\n' + ' permalink\n' + ' shortcode\n' + ' thumbnailUrl\n' + ' timestamp\n' + ' username\n' + ' }\n' + ' }\n' + '}\n'; 7352 var templateHTML = section.querySelector(templateSelector)?.innerHTML || ''; 7353 var template = Handlebars.compile(templateHTML); 7354 var container = section.querySelector(containerSelector); 7355 if (options.variables) { 7356 Object.keys(options.variables).forEach(function (key) { 7357 if (options.variables.hasOwnProperty(key) && (typeof options.variables[key] !== 'string' || !options.variables[key].match(/^{{.*}}$/))) { 7358 payload[key] = options.variables[key]; 7359 } 7360 }); 7361 } 7362 function getData() { 7363 var feed = { 7364 error: true 7365 }; 7366 if (payload.companyId == null || payload.companyId === '') { 7367 // instagramContentFeed requires companyId (ID!) â nothing to fetch without it. 7368 // Checked after the options.variables merge, which may override the default. 7369 // Deferred so element listeners (attached after this template runs) still receive it. 7370 setTimeout(function () { 7371 section.dispatchEvent(new CustomEvent('ig-data', { 7372 detail: feed 7373 })); 7374 }, 0); 7375 return; 7376 } 7377 superagent.post(url + '/graphql').send({ 7378 query: query, 7379 variables: payload 7380 }).then(res => { 7381 try { 7382 if (!res.body.errors) { 7383 feed = res.body.data.instagramContentFeed; 7384 if (!feed.active) { 7385 if (!hideActivateMessage && sectionDomId === 'section-temp' && container) { 7386 if (payload.resourceId) { 7387 container.innerHTML = '<div style="text-align: center">Instagram account is not connected to selected ' + payload.resource + '.<br /> Connect it on the ' + payload.resource + ' page</div>'; 7388 } else { 7389 container.innerHTML = '<div style="text-align: center">Instagram account is not connected.<br /> Connect it on <a href="/profile">Profile page</a></div>'; 7390 } 7391 } 7392 } else { 7393 if (feed.items.length) { 7394 if (hasDataClass) { 7395 section.classList.add(hasDataClass); 7396 } 7397 const feedName = feed.username; 7398 section.querySelectorAll('.jsIGLink').forEach(link => link.setAttribute('href', feed.feedUrl)); 7399 section.querySelectorAll('.jsIGName').forEach(name => { 7400 name.textContent = '@' + feedName; 7401 name.setAttribute('title', '@' + feedName); 7402 }); 7403 if (container && template) { 7404 container.innerHTML = template(feed); 7405 } 7406 } 7407 } 7408 } 7409 } catch (e) {} 7410 section.dispatchEvent(new CustomEvent('ig-data', { 7411 detail: feed 7412 })); 7413 }).catch(e => { 7414 console.log('err', e); 7415 section.dispatchEvent(new CustomEvent('ig-data', { 7416 detail: feed 7417 })); 7418 }); 7419 } 7420 getData(); 7421})('section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b', JSON.parse("{\"limit\":33,\"resource\":\"agent\",\"resourceId\":\"\",\"fallbackToNoResource\":\"true\",\"companyId\":\"cccfad5c-784f-4d3e-8950-0449a0ebf171\",\"usePageResource\":false,\"sectionIndex\":5,\"useRouterApi\":false,\"routerApiAux\":{\"neighborhoods\":false,\"postCategories\":false,\"offices\":false}}")); 7422} catch(e) { 7423console.log(e); 7424} 7425 try { 7426(function init(sectionDomId) { 7427 const $section = $('#' + sectionDomId); 7428 var templateHTML = $section.find('.jsIGItem').html(); 7429 var itemTemplate = templateHTML && Handlebars.compile(templateHTML); 7430 const $container = $section.find('.ig-feed-feed'); 7431 const $topPrev = $section.find('.top-nav-prev'); 7432 const $topNext = $section.find('.top-nav-next'); 7433 const $bottomPrev = $section.find('.bottom-nav-prev'); 7434 const $bottomNext = $section.find('.bottom-nav-next'); 7435 let limit = 33; 7436 try { 7437 limit = parseInt($container[0].dataset['limit']); 7438 } catch (e) {} 7439 if (!limit) { 7440 limit = 33; 7441 } 7442 let igFeed = {}; 7443 let usedWidth = 0; 7444 let slider = null; 7445 $section.on('ig-data', function (ev, feed) { 7446 feed = ev.detail || feed; 7447 igFeed = feed; 7448 if (feed.active && feed.items.length) { 7449 buildSlider(); 7450 } 7451 }); 7452 $(window).on('resize.lpui-auto-clean', onResize); 7453 let timer = null; 7454 function onResize() { 7455 clearTimeout(timer); 7456 timer = window.setTimeout(buildSlider, 50); 7457 } 7458 function getLayout(w, n) { 7459 if (w > 1100) { 7460 if (n > 7) { 7461 return { 7462 type: 'type1', 7463 single: 1, 7464 multi: n, 7465 slides: 3, 7466 slider: n > 9 7467 }; 7468 } 7469 if (n > 5) { 7470 return { 7471 type: 'type1', 7472 single: 2, 7473 multi: n, 7474 slides: 3, 7475 slider: false 7476 }; 7477 } 7478 return { 7479 type: 'type1', 7480 single: n, 7481 multi: n, 7482 slides: 3, 7483 slider: n > 3 7484 }; 7485 } else if (w > 880) { 7486 if (n > 4) { 7487 return { 7488 type: 'type2', 7489 single: 1, 7490 multi: n, 7491 slides: 2.5, 7492 slider: n > 7 7493 }; 7494 } 7495 return { 7496 type: 'type1', 7497 single: n, 7498 multi: n, 7499 slides: 3, 7500 slider: n > 3 7501 }; 7502 } else if (w > 767) { 7503 if (n > 4) { 7504 return { 7505 type: 'type3', 7506 single: 1, 7507 multi: n, 7508 slides: 2, 7509 slider: n > 5 7510 }; 7511 } 7512 return { 7513 type: 'type4', 7514 single: n, 7515 multi: n, 7516 slides: 2, 7517 slider: n > 2 7518 }; 7519 } else if (w > 460) { 7520 return { 7521 type: 'type4', 7522 single: n, 7523 multi: n, 7524 slides: 2, 7525 slider: n > 2 7526 }; 7527 } 7528 return { 7529 type: 'type5', 7530 single: n, 7531 multi: n, 7532 slides: 1, 7533 slider: n > 1 7534 }; 7535 } 7536 function ensureClass($el, className) { 7537 if ($el.hasClass(className)) { 7538 return; 7539 } 7540 $el.addClass(className); 7541 } 7542 function makeSquare($el) { 7543 const el = $el[0]; 7544 el.style.width = ''; 7545 el.style.height = ''; 7546 const rect = el.getBoundingClientRect(); 7547 if (rect.width !== rect.height) { 7548 el.style.width = rect.height + 'px'; 7549 } 7550 } 7551 function buildSlider() { 7552 const cWidth = $container[0].getBoundingClientRect().width; 7553 if (cWidth === usedWidth) { 7554 return; 7555 } 7556 $container.empty();
7557 slider = $('<div class="ig-feed-slider"></div>'); 7558 const items = igFeed.items.slice(0, limit); 7559 const layout = getLayout(cWidth, items.length); 7560 let i = 0; 7561 let slide = null; 7562 while (i < layout.single) { 7563 slide = $(`<div class="slide-single ${layout.type}"></div>`).append(itemTemplate(items[i])).appendTo(slider); 7564 i++; 7565 } 7566 while (i < layout.multi) { 7567 slide = $(`<div class="slide-multi ${layout.type}"></div>`).appendTo(slider); 7568 let slideContent = $('<div class="slide-multi-content"></div>').appendTo(slide); 7569 const lim = i + 4; 7570 while (i < lim && i < layout.multi) { 7571 slideContent.append(itemTemplate(items[i])); 7572 i++; 7573 } 7574 } 7575 $container.append(slider); 7576 if (layout.slider) { 7577 $topPrev.removeClass('hidden-control'); 7578 $topNext.removeClass('hidden-control'); 7579 $bottomPrev.removeClass('hidden-control'); 7580 $bottomNext.removeClass('hidden-control'); 7581 let prev, next; 7582 if ($bottomPrev.parent()[0].getBoundingClientRect().width) { 7583 prev = $bottomPrev; 7584 next = $bottomNext; 7585 } else { 7586 prev = $topPrev; 7587 next = $topNext; 7588 makeSquare($topPrev); 7589 makeSquare($topNext); 7590 } 7591 slider.children().each(function () { 7592 this.style.width = this.getBoundingClientRect().width + 'px'; 7593 }); 7594 slider.slick({ 7595 dots: false, 7596 prevArrow: prev, 7597 nextArrow: next, 7598 slidesToScroll: 1, 7599 infinite: false, 7600 slidesToShow: layout.slides 7601 }); 7602 } else { 7603 ensureClass($topPrev, 'hidden-control'); 7604 ensureClass($topNext, 'hidden-control'); 7605 ensureClass($bottomPrev, 'hidden-control'); 7606 ensureClass($bottomNext, 'hidden-control'); 7607 } 7608 } 7609})('section-5fa24384-6e5f-44ed-b3e8-b9124d76c69b', JSON.parse("{\"resource\":\"agent\",\"useRouterApi\":false,\"companyId\":\"cccfad5c-784f-4d3e-8950-0449a0ebf171\",\"usePageResource\":false,\"sectionIndex\":5,\"routerApiAux\":{\"neighborhoods\":false,\"postCategories\":false,\"offices\":false}}")); 7610} catch(e) { 7611console.log(e); 7612} 7613 7614 var { body } = document; 7615 var globalNav = body.querySelector(':scope > nav'); 7616 var globalSideMenu = body.querySelector(':scope > div.sidemenu'); 7617 7618 document.querySelectorAll('body > .modal .close').forEach(modalCloseBtn => { 7619 modalCloseBtn.addEventListener('click', function() { 7620 window.lpUI.hideClosestModal(modalCloseBtn); 7621 }); 7622 }); 7623 7624 window.addEventListener('click', function() { 7625 document.querySelectorAll('.share-popup').forEach(sharedPopup => { 7626 sharedPopup.style.display = 'none' ; 7627 }); 7628 }); 7629 7630 /* Misc Partials / Addons */ 7631 function initWOW() { 7632 if (wow) { 7633 wow.init(); 7634 wow.scrollHandler(); 7635 setTimeout(function () { 7636 const wowHideStyle = document.getElementById('wow-hide-elements'); 7637 if(wowHideStyle) { 7638 wowHideStyle.disabled = true; 7639 } 7640 }, 1); 7641 } 7642 } 7643 7644 const wowHideElements = document.getElementById('wow-hide-elements'); 7645 if (wowHideElements) { 7646 wowHideElements.disabled = false; 7647 } 7648 7649 initWOW(); 7650 7651 /* Generic Navbar Handling */ 7652 globalNav?.querySelectorAll('.hamburger-component').forEach(hamburgerComponent => { 7653 hamburgerComponent.addEventListener('click', function() { 7654 window.lpUI.sideMenuToggle(); 7655 }); 7656 }); 7657 globalSideMenu?.querySelectorAll('.toggle').forEach(toggleEl => { 7658 toggleEl.addEventListener('click', function() { 7659 window.lpUI.sideMenuToggle(); 7660 }); 7661 }); 7662 7663 document.querySelectorAll('body > nav .sub-nav-container > a, body > div.sidemenu .sub-nav-container > a').forEach(linkEl => { 7664 linkEl.addEventListener('click', function(e) { 7665 e.preventDefault(); 7666 e.stopPropagation();
7667 var subNav = linkEl.parentElement.querySelector(':scope > .sub-nav'); 7668 if (subNav && subNav.classList.contains('visible')){ 7669 subNav.classList.remove('visible'); 7670 } else { 7671 globalNav?.querySelectorAll('.sub-nav-container .sub-nav').forEach(globalSubNav => { 7672 globalSubNav.classList.remove('visible'); 7673 }); 7674 globalSideMenu?.querySelectorAll('.sub-nav').forEach(sideMenuSubNav => { 7675 sideMenuSubNav.classList.remove('visible'); 7676 }); 7677 subNav?.classList.add('visible'); 7678 } 7679 }); 7680 }); 7681 window.addEventListener('click', function() { 7682 document.querySelectorAll('nav .sub-nav.visible, .sidemenu .sub-nav.visible').forEach(subNavEl => { 7683 subNavEl.classList.remove('visible'); 7684 }); 7685 }); 7686 7687 } 7688 7689 document.addEventListener('DOMContentLoaded', lpGlobalInit); 7690 7691 </script>
7691 7692 7693
7693<script type="module"> 7694 function selectorExists(selector) { 7695 return document.querySelector(selector) !== null; 7696 } 7697 7698 // Function to initialize the third-party library 7699 function initParoller(selector = '.my-paroller') { 7700 var $parollerElements = $(selector); 7701 if ($parollerElements.length > 0 && typeof $parollerElements.paroller === 'function') { 7702 $parollerElements.paroller(); 7703 } 7704 } 7705 7706 const parollerSelector = '.my-paroller'; 7707 7708 if (selectorExists(parollerSelector)) { 7709 window.luxuryPresence.libs.loadJs(window.luxuryPresence.libs.jsLibsMap.paroller.jsSrc, function() { 7710 initParoller(parollerSelector); 7711 window.luxuryPresence.libs.jsLibsMap.paroller.isLoaded = true; 7712 }); 7713 } 7714 </script>
7714 7715 7716 <!-- Google Tag Manager (noscript) -->
vendor: 80 bytes, lines 7716-7717
7716 7717 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
7717GTM-NQNDW7N8
vendor: 107 bytes, lines 7717-7719
7717" 7718 height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 7719
7719<!-- End Google Tag Manager --> 7720 <!-- Google Tag Manager (noscript) -->
vendor: 80 bytes, lines 7720-7721
7720 7721 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
7721GTM-T9SFQGHZ
vendor: 107 bytes, lines 7721-7723
7721" 7722 height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 7723
7723<!-- End Google Tag Manager --> 7724 <!-- Google Tag Manager (noscript) -->
vendor: 78 bytes, lines 7724-7727
7724 7725<noscript> 7726 <iframe 7727 src="https://www.googletagmanager.com/ns.html?id=
7727GTM-NQNDW7N8
vendor: 105 bytes, lines 7727-7732
7727" 7728 height="0" 7729 width="0" 7730 style="display:none;visibility:hidden"> 7731 </iframe> 7732</noscript>
7733<!-- End Google Tag Manager (noscript) --> 7734
7735<script> 7736(function () { 7737 7738 function openMarcoTidio() { 7739 7740 if ( 7741 window.tidioChatApi && 7742 typeof window.tidioChatApi.open === 'function' 7743 ) { 7744 window.tidioChatApi.open(); 7745 return; 7746 } 7747 7748 document.addEventListener( 7749 'tidioChat-ready', 7750 function () { 7751 if ( 7752 window.tidioChatApi && 7753 typeof window.tidioChatApi.open === 'function' 7754 ) { 7755 window.tidioChatApi.open(); 7756 } 7757 }, 7758 { once: true } 7759 ); 7760 } 7761 7762 document.addEventListener('click', function (e) { 7763 7764 var button = e.target.closest('#marco-tidio-button'); 7765 7766 if (!button) { 7767 return; 7768 } 7769 7770 e.preventDefault(); 7771 7772 openMarcoTidio(); 7773 7774 }); 7775 7776})(); 7777</script>
7777 7778
7778<script 7779 src="https://cdn.luxurypresence.com/scripts/a11y-widget/latest/widget.js" 7780 data-website-id="069c1329-5dd0-46bd-b643-b325e5b978a5" 7781 7782 defer></script>
vendor: 1 bytes, line 7782
7782
7783<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"d2a8f4b3d65944edb8fcd6ffce49ee5e","spa":2}' crossorigin="anonymous"></script>
vendor: 1 bytes, line 7783
7783
7784<script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a4021861f952a3e2',t:'MTc5MDI1NjExOA=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>
7784</body> 7785</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.