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>Your Path to Remarkable Experiences | Corcoran Premier Realty</title> 10 <meta property="og:title" content="Your Path to Remarkable Experiences | Corcoran Premier Realty"> 11 <meta name="twitter:title" content="Your Path to Remarkable Experiences | Corcoran Premier Realty"> 12 <meta name="description" content="Discover top FL real estate agents at Corcoran Premier Realty, guiding you on your path to remarkable experiences. Find your dream home with us today!"> 13 <meta property="og:description" content="Discover top FL real estate agents at Corcoran Premier Realty, guiding you on your path to remarkable experiences. Find your dream home with us today!"> 14 <meta name="twitter:description" content="Discover top FL real estate agents at Corcoran Premier Realty, guiding you on your path to remarkable experiences. Find your dream home with us today!"> 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/3614c947-ba7c-4fc4-922b-a00f7af967c9"> 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/3614c947-ba7c-4fc4-922b-a00f7af967c9"> 17 <meta property="og:url" content="https://corcoranpremier.com/contact"> 18 <link rel="canonical" href="https://corcoranpremier.com/contact"> 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 <style>@font-face {font-family: 'ChronicleDisplay';src: url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/ChronicleDisplayRoman/ChronicleDisplay-Roman.woff2') format('woff2'),url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/ChronicleDisplayRoman/ChronicleDisplay-Roman.woff') format('woff');font-weight: 400;font-style: normal;}@font-face {font-family: 'ChronicleDisplay';src: url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/ChronicleDisplayRoman/ChronicleDisplay-Bold.woff2') format('woff2'),url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/ChronicleDisplayRoman/ChronicleDisplay-Bold.woff') format('woff');font-weight: 700;font-style: normal;}</style><style>@font-face {font-family: 'Avenir';src: url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/Avenir/Avenir-Book.woff2') format('woff2'),url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/Avenir/Avenir-Book.woff') format('woff');font-weight: 400;font-style: normal;}@font-face {font-family: 'Avenir';src: url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/Avenir/Avenir-Medium.woff2') format('woff2'),url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/Avenir/Avenir-Medium.woff') format('woff');font-weight: 500;font-style: normal;}@font-face {font-family: 'Avenir';src: url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/Avenir/Avenir-Black.woff2') format('woff2'),url('https://d1e1jt2fj4r8r.cloudfront.net/fonts/Avenir/Avenir-Black.woff') format('woff');font-weight: 900;font-style: normal;}</style> 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:ChronicleDisplay,serif;--global-primary-font-family-short:ChronicleDisplay;--global-secondary-font-family:Avenir,sans-serif;--global-secondary-font-family-short:Avenir;--global-body-padding:0px;--global-background-color:#fff;--global-body-font-size:16px;--global-h1-font-size:65px;--global-h2-font-size:50px;--global-h3-font-size:40px;--global-h4-font-size:28px;--global-h5-font-size:22px;--global-h6-font-size:20px;--global-section-padding:96px;}@media (max-width: 768px){:root{--global-section-padding:64px;}}body{padding:0px;background-color:#fff;font-family:Avenir,sans-serif;font-size:16px;}@media (min-width: 768px){body{padding:0px 0px 0px 0px;}}h1,h2,h3,h4,h5,h6,button{font-family:ChronicleDisplay,serif;}h1{font-size:65px;}h2{font-size:50px;}h3{font-size:40px;}h4{font-size:28px;}h5{font-size:22px;}h6{font-size:20px;}</style> 30 <link rel="stylesheet" type="text/css" href="https://styles.luxurypresence.com/masterpiece/index.css" /> 31 <style id="website-css">:root{--primary:#231F20;--secondary:#231F20;--light:#fff;--dark:#231F20;--accent:#231F20;--light-gray:#ccc;--case:none;--trans:transparent;}.lp-tcr-message{opacity:.6;}h1,h2,h3,h4,h5,.lp-h1,.lp-h2,.lp-h3,.lp-h4{text-transform:none!important;letter-spacing:2px;}@media (max-width: 768px){h2,.lp-h2{font-size:31px!important;}}div#global-sidemenu.sidemenu a{text-transform:none;}div#global-sidemenu.sidemenu button{text-transform:none;}.redesign .lp-btn,.lp-btn,.redesign .btn--small,.redesign .btn{padding:18px 26px;text-overflow:clip;letter-spacing:1px;font-weight:500;border-width:1px;}#modal-global-contact-us .contact-form .section-message form .submitButton{padding:18px 26px;text-overflow:clip;letter-spacing:1px;font-weight:500;border-width:1px;}#global-mobile-contact .mobile-contact .item{z-index:9999;background-color:#231F20;color:#fff;border:1px solid #231F20;}#global-mobile-contact .mobile-contact .item svg{fill:#fff;}div.cta-block .text-block{max-width:100%;}div.cta-block .text-block p,div.cta-block .text-block h2{margin-bottom:0;}@media only screen and (max-width: 768px){div#global-sidemenu .lp-socials li{margin-right:5px;}}div#global-sidemenu a.navigation__link{padding-bottom:5px;padding-top:5px;padding-left:0;padding-right:0;display:block;letter-spacing:2px;text-align:center;}div#global-sidemenu a.navigation__link:hover{color:#5E5E5E;}div#global-sidemenu a.sub-nav__link{letter-spacing:2px;text-align:center;}div#global-sidemenu a.sub-nav__link:hover{color:#5E5E5E;}div#global-sidemenu .sidemenu__img{-webkit-background-position:top;background-position:top;}div#global-sidemenu .sidemenu__wrapper .sidemenu__toggle{letter-spacing:1px;}div#global-sidemenu .sidemenu__wrapper .sidemenu__header{padding-bottom:5px;}div#global-sidemenu .sidemenu__wrapper .navigation__item{border-bottom:1px solid transparent;margin:10px 100px 10px 100px;text-align:center;}@media only screen and (max-width: 768px){div#global-sidemenu .sidemenu__wrapper .navigation__item{margin:10px 20px 10px 20px;}}div#global-sidemenu .sidemenu__wrapper .sub-nav{padding:0;}div#global-sidemenu .sidemenu__socials{margin-right:auto;padding-right:0;}nav#global-navbar{-webkit-transition:top 0.2s ease-in-out!important;transition:top 0.2s ease-in-out!important;}nav#global-navbar .header .logo .logo__img{margin-bottom:0;max-height:90px!important;max-width:170px!important;}@media (max-width: 768px){nav#global-navbar .header .logo .logo__img{max-width:200
31px;}}@media screen and (min-width: 1024px){nav#global-navbar .header__container{max-width:1400px;}}nav#global-navbar .navigation__link{font-size:14px;letter-spacing:2px;max-width:230px!important;}nav#global-navbar .header.theme-light{background-color:transparent;}nav#global-navbar .header.theme-light .header__hamburger circle{fill:#fff!important;}nav#global-navbar .header.theme-light .header__hamburger svg rect{fill:#231F20!important;}nav#global-navbar .header.theme-light ul.navigation li.navigation__item{color:#fff;text-transform:none;}nav#global-navbar .header.theme-light ul.navigation li.navigation__item .sub-nav__link{max-width:300px;color:#231F20;background-color:#fff;font-weight:normal;}nav#global-navbar .header.theme-light ul.navigation li.navigation__item .sub-nav__link:hover{color:#fff;background-color:#231F20;}nav#global-navbar .header.theme-light ul.navigation li.navigation__item .navigation__link:after{background:#fff;}nav#global-navbar .header.theme-light .search__btn svg{color:#fff!important;}nav#global-navbar .header.theme-light .logo__img.dark{display:none;}nav#global-navbar .header.theme-light .logo__img.light{display:block;}nav#global-navbar .header{background-color:#fff;}nav#global-navbar .header .header__hamburger circle{fill:#231F20!important;}nav#global-navbar .header .header__hamburger svg rect{fill:#fff!important;}nav#global-navbar .header ul.navigation li.navigation__item{color:#231F20;text-transform:none;}nav#global-navbar .header ul.navigation li.navigation__item .sub-nav__link{max-width:300px;color:#231F20;font-weight:400;background-color:#fff;}nav#global-navbar .header ul.navigation li.navigation__item .sub-nav__link:hover{color:#fff;background-color:#231F20;}nav#global-navbar .header ul.navigation li.navigation__item .navigation__link:after{background:#231F20;}nav#global-navbar .header .search__btn svg{color:#231F20!important;}nav#global-navbar .header .logo__img.dark{display:block;}nav#global-navbar .header .logo__img.light{display:none;}nav#global-navbar.scroll .header{background-color:#fff;}nav#global-navbar.scroll .header .header__hamburger circle{fill:#231F20!important;}nav#global-navbar.scroll .header .header__hamburger svg rect{fill:#fff!important;}nav#global-navbar.scroll .header ul.navigation li.navigation__item{color:#231F20;}nav#global-navbar.scroll .header ul.navigation li.navigation__item .sub-nav__link{max-width:300px;color:#231F20;background-color:#fff;font-weight:400;}nav#global-navbar.scroll .header ul.navigation li.navigation__item .sub-nav__link:hover{color:#fff;background-color:#231F20;}nav#global-navbar.scroll .header ul.navigation li.navigation__item .navigation__link:after{background:#231F20;}nav#global-navbar.scroll .header .search__btn svg{color:#231F20;}nav#global-navbar.scroll .header .logo__img.dark{display:block;}nav#global-navbar.scroll .header .logo__img.light{display:none;}footer#global-footer .site-footer__col-content{opacity:1;}footer#global-footer .site-footer__disclaimer{opacity:1;}footer#global-footer .site-footer__disclaimer:after{background-color:var(--accent)!important;opacity:1;}footer#global-footer .footer-navigation__link:hover{color:var(--dark);}footer#global-footer .site-footer__copy-lp a:after{background:var(--accent);}footer#global-footer .site-footer__copy a:hover{color:var(--dark);}footer#global-footer .site-footer__logo-container img{max-height:150px;}@media only screen and (max-width:768px){footer#global-footer .site-footer__socials{margin:auto;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}footer#global-footer .site-footer__socials li{margin-bottom:16px;margin-left:5px;margin-right:5px;}footer#global-footer .site-footer__logo-container img{max-height:140px;}}footer#global-footer .site-footer__col-content a:after{background:var(--accent);}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a),footer#global-footer .link,footer#global-footer .footer-navigation__link,footer#global-footer .site-footer__copy a{text-transform:var(--case);position:relative!important;color:var(--dark)!important;}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__c
31opy a):hover,footer#global-footer .link:hover,footer#global-footer .footer-navigation__link:hover,footer#global-footer .site-footer__copy a:hover{color:var(--dark)!important;opacity:1!important;}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):before,footer#global-footer .link:before,footer#global-footer .footer-navigation__link:before,footer#global-footer .site-footer__copy a:before,footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):after,footer#global-footer .link:after,footer#global-footer .footer-navigation__link:after,footer#global-footer .site-footer__copy 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;}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):before,footer#global-footer .link:before,footer#global-footer .footer-navigation__link:before,footer#global-footer .site-footer__copy a:before{width:100%!important;background-color:var(--light-gray)!important;opacity:1;}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):after,footer#global-footer .link:after,footer#global-footer .footer-navigation__link:after,footer#global-footer .site-footer__copy a:after{width:0%!important;background-color:var(--accent)!important;}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):hover:after,footer#global-footer .link:hover:after,footer#global-footer .footer-navigation__link:hover:after,footer#global-footer .site-footer__copy a:hover:after{width:100%!important;}@media only screen and (max-width: 1280px){footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a),footer#global-footer .link,footer#global-footer .footer-navigation__link,footer#global-footer .site-footer__copy a{overflow-wrap:anywhere;-webkit-text-decoration:underline!important;text-decoration:underline!important;white-space:normal!important;}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):before,footer#global-footer .link:before,footer#global-footer .footer-navigation__link:before,footer#global-footer .site-footer__copy a:before{background-color:var(--trans);width:0%!important;}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):after,footer#global-footer .link:after,footer#global-footer .footer-navigation__link:after,footer#global-footer .site-footer__copy a:after{background-color:var(--trans);}footer#global-footer a:not(.socials__item, .lp-tcr-message a, .site-footer__copy a):hover:after,footer#global-footer .link:hover:after,footer#global-footer .footer-navigation__link:hover:after,footer#global-footer .site-footer__copy a:hover:after{width:0%!important;}}@media only screen and (max-width: 1024px){footer#global-footer .site-footer__navigation-wrap{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}footer#global-footer .lp-socials{margin:25px auto 0 auto!important;}footer#global-footer .site-footer__logo-bar{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}footer#global-footer .site-footer__info{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}}@media only screen and (max-width: 820px){footer#global-footer .footer-navigation__item{margin:0 5px 5px;}footer#global-footer .site-footer__logo-bar{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}footer#global-footer .site-footer__info{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}}@media only screen and (max-width: 768px){footer#global-footer .site-footer__logo-bar{-webkit-box-pack:left;-ms-flex-pack:left;-webkit-justify-content:left;justify-content:left;}footer#global-footer .footer-navigation__item{margin:0 5px 10px;}}footer#global-footer .site-footer__logo-bar .site-footer__logo-container img{max-width:unset;width:220px;content:url('');}@media (max-width: 768px){footer#global-footer .site-footer__logo-bar .site-footer__logo-container img{width:unset;max-width:100%;max-height:90px;}}footer#global-footer .site-footer__disclaimer:after{background-color:var(--accent);}#global-footer>div>div.site-footer__bottom>div>
31div.site-footer__copy>div.lp-a.site-footer__copy-lp>div>img{max-height:50px;-webkit-filter:invert(0);filter:invert(0);}@media only screen and (max-width: 768px){footer#global-footer a:not(.socials__item),footer#global-footer .link,footer#global-footer .footer-navigation__link{text-underline-offset:5px;}}@media (max-width: 768px){footer#global-footer>div>div>div>div.site-footer__copy>div:nth-child(2){margin-bottom:30px;}}#global-footer div.site-footer__bottom div.site-footer__copy a{position:relative!important;text-transform:none!important;color:var(--dark)!important;}#global-footer div.site-footer__bottom div.site-footer__copy a:hover{color:var(--dark)!important;}#global-footer div.site-footer__bottom div.site-footer__copy a:before,#global-footer div.site-footer__bottom div.site-footer__copy a:after{-webkit-transition:0.4s;transition:0.4s;-webkit-text-decoration:var(--case)!important;text-decoration:var(--case)!important;line-height:1;content:"";height:1px;position:absolute!important;bottom:0;left:0;}#global-footer div.site-footer__bottom div.site-footer__copy a:before{width:100%!important;background-color:var(--light-gray)!important;opacity:0.9;}#global-footer div.site-footer__bottom div.site-footer__copy a:after{width:0%!important;background-color:var(--accent)!important;}#global-footer div.site-footer__bottom div.site-footer__copy a:hover:after{width:100%!important;}@media only screen and (max-width: 768px){#global-footer div.site-footer__bottom div.site-footer__copy a{-webkit-text-decoration:var(--dark)!important;text-decoration:var(--dark)!important;}}footer#global-footer div.container{overflow:hidden!important;}@media only screen and (max-width:767px){footer#global-footer div.container{height:260px!important;}}footer#global-footer td,footer#global-footer th{border-color:transparent!important;padding-top:0;padding-right:0!important;}@media only screen and (max-width:767px){footer#global-footer td,footer#global-footer th{width:100%!important;display:block;padding-left:0!important;}}footer#global-footer .site-footer__bottom .site-footer__info div:nth-child(2) h5{margin-bottom:16px!important;}#modal-global-contact-us div.input-container input.lp-input,#modal-global-contact-us div.input-container textarea{text-transform:var(--case);color:var(--dark);border-color:var(--dark);}#modal-global-contact-us div.input-container input.lp-input:-webkit-autofill,#modal-global-contact-us div.input-container textarea:-webkit-autofill{-webkit-text-fill-color:var(--dark);}#modal-global-contact-us div.input-container input.lp-input:-webkit-autofill:focus,#modal-global-contact-us div.input-container textarea:-webkit-autofill:focus{color:var(--dark);}#modal-global-contact-us div.input-container span.input-icon{-webkit-filter:brightness(0) saturate(100%) invert(0%) sepia(86%) saturate(7500%) hue-rotate(303deg) brightness(105%) contrast(112%);filter:brightness(0) saturate(100%) invert(0%) sepia(86%) saturate(7500%) hue-rotate(303deg) brightness(105%) contrast(112%);}@media only screen and (max-width:768px){#modal-global-contact-us .lp-close{top:1vh;-webkit-filter:invert(0);filter:invert(0);}}#modal-global-contact-us .contact-form__close.close{-webkit-filter:invert(0);filter:invert(0);opacity:1;}@media only screen and (max-width:768px){#modal-global-contact-us .contact-form__close.close{-webkit-filter:invert(0);filter:invert(0);top:1vh!important;}}#modal-global-contact-us p{color:var(--light);}@media only screen and (max-width: 768px){#modal-global-contact-us .socials li{padding:8px 4px 8px 4px!important;}#modal-global-contact-us .lp-socials{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}#modal-global-contact-us .lp-socials li{margin-right:0;}}#modal-global-contact-us .contact-form{background-color:var(--primary)!important;}#modal-global-contact-us .button-holder{-webkit-box-pack:center!important;-ms-flex-pack:center!important;-webkit-justify-content:center!important;justify-content:center!important;}#modal-global-contact-us .left .lp-h2{text-align:center;color:var(--primary);}#modal-global-contact-us .contact-form__details .contact-form__title2{color:var(--light);}#modal-global-contact-us .company .lp-a a,.lp-link{position:relative!important;color:var(--light)!important;-webkit-transition:0.4s;transition:0.4s;opacity:1!important;font-weight:400;text-transform:uppercase!important;}#modal-global-contact-us .company .lp-a a:hover,.lp-link:hover{color:var(--light)!important;}#modal-global-contact-us .company .lp-a a:before,.lp-link:before,#modal-global-contact-us .company .lp-a a:after,.lp-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;}#modal-global-contact-us .company .lp-a a:before,.lp-link:before{width:100%!important;background-color:#ccc!important;}#modal-global-contact-us .company .lp-a a:after,.lp-link:after{width:0%!important;background-color:var(--light)!important;}#modal-global-contact-us .company .lp-a a:hover:after,.lp-link:hover:after{width:100%!important;}.contact-form .lp-disclaimer a{-webkit-text-decoration:none!important;text-decoration:none!important;position:relative;display:inline-block;vertical-align:top;}.contact-form .lp-disclaimer a:after,.contact-form .lp-disclaimer a:before{content:"";height:1px;position:absolute;bottom:0;left:0;box-sizing:border-box;outline:none;-webkit-transition:0.4s;transition:0.4s;}.contact-form .lp-disclaimer a:before{background-color:#ccc;width:100%;}.contact-form .lp-disclaimer a:after{width:0%;background-color:var(--light);-webkit-transition:0.4s;transition:0.4s;}.contact-form .lp-disclaimer a:hover{-webkit-text-decoration:none!important;text-decoration:none!important;opacity:1;}.contact-form .lp-disclaimer a:hover:after{width:100%;}@media only screen and (max-width: 1024px){div#modal-global-contact-us div.contact-form__container{min-height:100vh;}div#modal-global-contact-us form.contact-form__form,div#modal-global-contact-us div.contact-form__details{-webkit-flex:1;-ms-flex:1;flex:1;}}.lp-socials a span.lp-i--podcast:before{-webkit-mask-image:url(https://media-production.lp-cdn.com/media/6f4e31e8-babb-428e-b70a-acce064ba69a)!important;mask-image:url(https://media-production.lp-cdn.com/media/6f4e31e8-babb-428e-b70a-acce064ba69a)!important;content:"";width:13px;height:13px;display:block;-webkit-background-size:contain;background-size:contain;white-space:pre;background-repeat:no-repeat;}</style> 32 <style id="wow-hide-elements">.wow{visibility:hidden!important}</style> 33 <style id="page-css"> 34 #section-f0cc46ac-4d4b-426a-a54d-6d7555c49280{color:#ffffff;--fontColor:#ffffff;--fontColor_H:0;--fontColor_S:0%;--fontColor_L:100%;--fontColor_A:1;--fontColor_darkenDir:-1;--bgColor:#000000;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:0%;--bgColor_A:1;--bgColor_darkenDir:1;background-color:#000000;--gradient-color:var(--overlay-color, rgba(0, 0, 0, 0.4));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/3614c947-ba7c-4fc4-922b-a00f7af967c9');background-repeat:no-repeat;-webkit-background-position:center;background-position:center;-webkit-background-size:cover;background-size:cover;}@media (min-width: 1300px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search{height:700px;}}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .video-wrapper .full-screen-video-component .video-wrapper::before{content:'';position:absolute;width:100%;height:100%;top:0;left:0;background-color:#000;z-index:-1000;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .video-wrapper .full-screen-video-component .video-wrapper video{-webkit-transition:opacity 2s cubic-bezier(0.835, 0, 0.19, 1);transition:opacity 2s cubic-bezier(0.835, 0, 0.19, 1);opacity:0!important;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .video-wrapper .full-screen-video-component .video-wrapper.playing video{opacity:1!important;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .lp-play{opacity:0;background-color:transparent;display:inline-block;border:none;position:absolute;bottom:50px;right:50px;width:27px;height:24px;z-index:3;-webkit-transition:opacity .2s ease-in-out;transition:opacity .2s ease-in-out;cursor:unset;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .lp-play.visible{opacity:1;cursor:pointer;}@media (max-width: 900px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .lp-play.visible{display:none;}}@media (max-width: 900px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .lp-play{display:none;}}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled{z-index:unset;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled .lp-container{position:relative;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled>div.video-wrapper{position:fixed;left:var(--global-body-padding, 0);top:var(--global-body-padding, 0);width:calc(100% - var(--global-body-padding, 0px) * 2);z-index:-1001;}@media (max-width: 767px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled>
34div.video-wrapper{left:0;top:0;width:100%;}}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled>div.overlay-component{position:fixed;left:var(--global-body-padding, 0);top:var(--global-body-padding, 0);right:unset;width:calc(100% - var(--global-body-padding, 0px) * 2);}@media (max-width: 767px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled>div.overlay-component{left:0;top:0;width:100%;}}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled .opening-with-search:before{display:block;content:'';left:var(--global-body-padding, 0);top:var(--global-body-padding, 0);width:calc(100% - var(--global-body-padding, 0px) * 2);background:var(--sectionBackground) center no-repeat;-webkit-background-size:cover;background-size:cover;background-position-y:22%;position:fixed;z-index:-1001;height:100%;}@media (max-width: 767px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.parallax-enabled .opening-with-search:before{left:0;top:0;width:100%;}}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search{position:relative;--top-padding:170px;--bottom-padding:30px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-height:770px;padding-top:var(--top-padding);padding-bottom:var(--bottom-padding);}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search:before{display:none;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-Full{min-height:100vh;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-Full>div.video-wrapper{height:100vh;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-Full:before{min-height:100vh;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-770px{min-height:770px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-770px>div.video-wrapper{height:770px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-770px:before{min-height:770px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-600px{min-height:600px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-600px>div.video-wrapper{height:600px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search.height-class-600px:before{min-height:600px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .bottom-spacer{-webkit-flex:1 0 0%;-ms-flex:1 0 0%;flex:1 0 0%;max-height:calc(var(--top-padding) - var(--bottom-padding));}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .center-block{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 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;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;text-align:center;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .opening-description{letter-spacing:.1em;margin-bottom:15px;max-width:640px;margin-left:auto;margin-right:auto;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .opening-description a,#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .opening-description a[x-apple-data-detectors]{color:inherit!important;-webkit-text-decoration:none!important;text-decoration:none!important;font-size:inherit!important;font-family:inherit!important;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .opening-pretitle{margin-bottom:15px;max-width:860px;margin-left:auto;margin-right:auto;white-space:pre-line;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .opening-title{margin-bottom:15px;max-width:860px;margin-left:auto;margin-right:auto;white-space:pre-line;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .opening-button{margin:0 15px;}@media (max-width: 768px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .opening-button{margin:0;}}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-form{margin-top:30px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:center;-ms-flex-pack:center;
34-webkit-justify-content:center;justify-content:center;-webkit-align-items:stretch;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-form.with-filters{padding-top:32px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-button{margin:5px;border:none;border-radius:0;outline:none;background-color:#000;color:#fff;height:44px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:50px;padding-right:50px;-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;cursor:pointer;-webkit-transition:all .3s ease;transition:all .3s ease;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-button:hover{background-color:#fff;color:#000;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-lease-tabs{position:absolute;left:0;bottom:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-lease-tab{padding:4px 20px;background-color:#000;color:#fff;cursor:pointer;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-lease-tab.active{background-color:#fff;color:#000;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-wrapper{margin:5px;letter-spacing:normal;width:100%;max-width:444px;position:relative;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-input-container{width:100%;border:none;height:43px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:0 16px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#fff;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-input-container .search-icon{color:#c0c0c0;margin-right:10px;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:20px;line-height:0;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-input-container .search-input{color:#000;-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;width:50px;border:none;border-radius:0;outline:none;background:transparent;font-size:16px;padding:0;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-results{line-height:normal;text-align:left;background-color:rgba(0, 0, 0, 0.8);position:absolute;width:100%;left:0;top:100%;border:none;overflow:hidden;-webkit-transition:height 0.3s ease;transition:height 0.3s ease;height:0;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-container,#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .predefined-links{padding:10px 0;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-container a,#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .predefined-links a{color:#b6b6b6;-webkit-transition:color 0.3s ease;transition:color 0.3s ease;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-container a:hover,#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .predefined-links a:hover{color:#fff;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .predefined-links{max-height:400px;overflow:auto;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-block{margin:15px 0;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-block-title{margin:0;padding:0 48px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-block-title .results-title-label{margin:0 20px 10px 0;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-block-title .search-near-container{margin-bottom:15px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-block:nth-child(n + 2) .search-near-container{display:none;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-link{display:block;padding:4px 48px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .results-link.selected-link{color:#fff;background-color:rgba(255, 255, 255, 0.2);}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-in-progress{padding:30px 0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-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;font-size:30px;opacity:0.5;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .not-visible{display:none!important;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .nothing-found{width:100%;padding:20px;}@media (max-width: 560px){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-form{-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-button{width:100%;max-width:444px;}}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .opening-with-search .search-near{cursor:pointer;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;-webkit-transition:background-color 0.3s ease;transition:background-color 0.3s ease;background-color:transparent;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-wrap{width:100%;height:100%;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:20px;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-clip-path:polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%);clip-path:polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%);-webkit-transition:clip-path 0.4s ease;transition:clip-path 0.4s ease;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-modal{border-radius:20px;padding:10px 20px 20px;max-width:400px;min-width:100px;background-color:rgba(0,0,0,0.9);color:#fff;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;position:relative;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;max-height:100%;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-close{position:absolute;width:40px;height:40px;top:10px;right:10px;cursor:pointer;-webkit-transition:all 0.3s ease;transition:all 0.3s ease;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-close:before{content:'';width:20px;height:2px;background-color:#fff;position:absolute;left:10px;top:19px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-close:after{content:'';width:20px;height:2px;background-color:#fff;position:absolute;left:10px;top:19px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-close:hover{-webkit-transform:scale(1.2);-moz-transform:scale(1.2);-ms-transform:scale(1.2);transform:scale(1.2);}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .search-near-hidden .search-near-container{display:none;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-title{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;margin-bottom:20px;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-container{-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;overflow:auto;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-container p{margin:0;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280 .loc-msg-container p+p{margin-top:1em;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.visible-loc-msg{z-index:1000;}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.visible-loc-msg .loc-msg-backdrop{background-color:rgba(255,255,255,0.4);}#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280.visible-loc-msg .loc-msg-wrap{-webkit-clip-path:polygon(0 0, 0 100%, 100% 100%, 100% 0%);clip-path:polygon(0 0, 0 100%, 100% 100%, 100% 0%);}@media (min-width: 960px) and (orientation: landscape){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280{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/3614c947-ba7c-4fc4-922b-a00f7af967c9');}}@media (min-width: 1280px) and (orientation: landscape){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280{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/3614c947-ba7c-4fc4-922b-a00f7af967c9');}}@media (min-width: 1920px) and (orientation: landscape){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280{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/3614c947-ba7c-4fc4-922b-a00f7af967c9');}}@media (min-width: 2560px) and (orientation: landscape){#section-f0cc46ac-4d4b-426a-a54d-6d7555c49280{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/3614c947-ba7c-4fc4-922b-a00f7af967c9');}}#section-effb862d-3cb0-4174-960c-c1cca02380a8{color:#231F20;--fontColor:#231F20;--fontColor_H:345;--fontColor_S:6%;--fontColor_L:13%;--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(2 / 4 * var(--global-section-padding));background-color:#ffffff;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__header{max-width:1200px!important;}@media (max-width: 767px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__img-block{height:100%!important;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__footer{margin:0 auto;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__img-block{background:#fff!important;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__img-block img{object-position:50% 0%;height:550px!important;}@media (max-width: 768px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__img-block img{height:400px!important;}}@media (max-width: 767px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 div.uf-cus-sel .uf-cus-sel-toggle{white-space:unset;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-input--dark{color:#000;border-color:#888;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-input-group .lp-input:-webkit-autofill{-webkit-text-fill-color:#000!important;border:1px solid #888;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 div.uf-cus-sel-menu .uf-cus-sel-content .uf-cus-sel-item{color:#000;background-color:#fff;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 div.uf-cus-sel-menu .uf-cus-sel-content .uf-cus-sel-item:hover{color:#fff!important;background-color:#000!important;}#section-effb862d-3cb0-4174-960c-c1cca02380a8.modal.is-background-color-light>button.close{padding:5px;}#section-effb862d-3cb0-4174-960c-c1cca02380a8.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-effb862d-3cb0-4174-960c-c1cca02380a8.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-effb862d-3cb0-4174-960c-c1cca02380a8.modal.is-background-color-light>button.close>img,#section-effb862d-3cb0-4174-960c-c1cca02380a8.modal.is-background-color-light>button.close .lp-close-icon{display:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .elem-row{-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}}
34#section-effb862d-3cb0-4174-960c-c1cca02380a8 .elem-col{min-height:1px;padding-left:16px;padding-right:16px;}@media (max-width: 767px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .elem-col{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;max-width:unset;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .form-col{padding-left:16px;padding-right:16px;-webkit-flex:1 1 400px;-ms-flex:1 1 400px;flex:1 1 400px;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .form-col:last-child .custom-form__group{margin-bottom:20px;}@media (min-width: 768px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .form-col:last-child .custom-form__group{margin-bottom:30px;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-label{text-transform:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-label.field-required:after{content:' *';}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form{padding-top:80px;padding-bottom:80px;}@media (max-width: 767px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form{padding-top:50px;padding-bottom:50px;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__img-col{margin-bottom:30px;}@media (min-width: 768px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__form-col{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;}}@media (min-width: 992px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__form-col{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__header{max-width:600px;margin-left:auto;margin-right:auto;margin-bottom:50px;text-align:center;}@media (max-width: 767px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__header{margin-bottom:30px;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__heading{margin-bottom:24px;}@media (max-width: 767px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__heading{margin-bottom:13px;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__description{margin-bottom:0;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__img-block{width:100%;height:430px;background:currentColor center/cover no-repeat;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__img-block img{height:100%;width:100%;object-fit:cover;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__download-form{width:100%;margin-bottom:0;}@media (min-width: 992px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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;-webkit-justify-content:flex-start;justify-content:flex-start;}}@media (min-width: 768px){#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__container{max-width:1160px;margin-left:auto;margin-right:auto;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .form-field-descr{opacity:0.5;margin-top:8px;font-size:82%;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-btn-icons:before{content:'';display:inline-block;width:0px;height:1em;vertical-align:middle;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .loading input,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .success input,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .loading select,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .success select,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .loading button,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .success button{pointer-events:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .loading .lp-btn-icons,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .success .lp-btn-icons{width:27px;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .loading .lp-btn-icons .lp-btn-icon-loading,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .success .lp-btn-icons .lp-btn-icon-loading{width:17px;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .loading .lp-btn-icons .lp-btn-icon-success,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .success .lp-btn-icons .lp-btn-icon-success{width:17px;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .loading .lp-btn-icons .lp-btn-icon-loading{opacity:1;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .loading .lp-btn-icons .lp-btn-icon-loading:before{content:'';}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .success .lp-btn-icons .lp-btn-icon-success{opacity:1;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .js-backup-email{display:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-h-pot{height:0;overflow:hidden;visibility:hidden;position:absolute;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .visually-hidden{position:absolute;overflow:hidden;clip:rect(0 0 0 0);width:1px;height:1px;margin:-1px;padding:0;border:0;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-content{max-height:210px;overflow-y:auto;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-input-group .uf-cus-sel-toggle{width:100%;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-toggle.is-placeholder{color:#999;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-toggle:after{right:25px;}}.uf-cus-sel.open #section-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-toggle:after{-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-menu{position:relative;top:auto;}}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-content{width:100%;background-color:var(--bgColor, #000);border:1px solid #979797;border-top:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-item:focus,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-item:hover{background-color:var(--optionHoverColor, #262222);}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-item.is-selected{font-weight:700;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-item.is-disabled,#section-effb862d-3cb0-4174-960c-c1cca02380a8 .uf-cus-sel-item:disabled{display:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-text--subtitle{margin-left:auto;margin-right:auto;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__checkbox-container .lp-label{opacity:1;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__checkboxes-label{font-size:14px;line-height:1.43;font-weight:600;margin-bottom:0;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__checkboxes-description{font-size:14px;line-height:1.43;font-weight:400;margin-bottom:0;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .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-effb862d-3cb0-4174-960c-c1cca02380a8 .custom-form__checkbox-label{cursor:pointer;font-size:inherit;line-height:1.4;margin:0;}#section-effb862d-3cb0-4174-960c-c1cca02380a8>div:last-child{padding-top:calc(4 / 4 * var(--global-section-padding))!important;padding-bottom:calc(2 / 4 * var(--global-section-padding))!important;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-input::-webkit-input-placeholder{text-transform:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-input::-moz-placeholder{text-transform:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-input:-ms-input-placeholder{text-transform:none;}#section-effb862d-3cb0-4174-960c-c1cca02380a8 .lp-input::placeholder{text-transform:none;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888{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;--section-padding-top:calc(2 / 4 * var(--global-section-padding));--section-padding-bottom:calc(0 / 4 * var(--global-section-padding));background-color:#fff;}@media (max-width: 768px){#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-3{margin-bottom:40px!important;}}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container{max-width:1300px;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container .media-card__description{dis
34play:none;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container .media-card{margin-bottom:0!important;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container .media-card__image{background-color:#fff;padding-bottom:60%;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container .media-card__image img{object-fit:contain;max-height:230px;object-position:bottom;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container .media-card__title{margin-bottom:30px;}@media(max-width:768px){#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container .col:nth-child(1){margin-top:-54px;}}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks .lp-container .col:nth-child(2) img{object-position:70% bottom;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888{--colGap:20px;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .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:calc(var(--colGap, 0) / -2);margin-right:calc(var(--colGap, 0) / -2);-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .lp-h2{margin-top:0;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col{position:relative;width:100%;min-height:1px;-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:100%;padding-left:calc(var(--colGap, 0) / 2);padding-right:calc(var(--colGap, 0) / 2);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__image{background-color:#f2f2f2;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-2{-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%;}@media (max-width: 768px){#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-2{-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%;}}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-2 .media-card__image{padding-bottom:63.6%;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-3{-webkit-flex:0 0 33.33%;-ms-flex:0 0 33.33%;flex:0 0 33.33%;max-width:33.33%;}@media (max-width: 768px){#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-3{-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%;}}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-3 .media-card__image{padding-bottom:97%;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-4{-webkit-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%;}@media (max-width: 768px){#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-4{-webkit-flex:0 0 100%;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%;}}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .col-1-4 .media-card__image{padding-bottom:97%;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-blocks{text-align:center;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card{width:100%;text-align:center;display:block;-webkit-text-decoration:none;text-decoration:none;color:inherit;margin-bottom:60px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}@media (max-width: 768px){#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card{margin-bottom:40px;}}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__image{position:relative;padding-bottom:40%;margin-bottom:32px;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__image img{position:absolute;left:0;top:0;width:100%;height:100%;object-fit:cover;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__title{margin-bottom:16px;max-width:380px;margin-left:auto;margin-right:auto;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__description{margin-bottom:32px;overflow:hidden;white-space:pre-line;max-width:380px;margin-left:auto;margin-right:auto;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__description .btn-more{cursor:pointer;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__description .substring{display:none;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__description .more-text{display:block;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__description.cropped{he
34ight:100%;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__description.cropped .substring{display:block;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__description.cropped .more-text{display:none;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .media-card__button{margin-top:auto;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888 .lp-text--subtitle{margin-left:auto;margin-right:auto;}#section-4c321f4f-0d95-40b2-af2a-8aa841d20888>div:last-child{padding-top:calc(2 / 4 * var(--global-section-padding))!important;padding-bottom:calc(0 / 4 * var(--global-section-padding))!important;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71{color:rgba(0, 0, 0, 1);--fontColor:rgba(0, 0, 0, 1);--fontColor_H:0;--fontColor_S:0%;--fontColor_L:0%;--fontColor_A:1;--fontColor_darkenDir:1;--bgColor:rgba(255, 255, 255, 1);--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:1;--bgColor_darkenDir:-1;--section-padding-bottom:calc(4 / 4 * var(--global-section-padding));background-color:rgba(255, 255, 255, 1);}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 div.section h3{color:#000000;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .section{display:none;overflow:hidden;}@media(min-width: 993px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .lp-container{padding-bottom:200px;}}@media(min-width: 769px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .lp-container{padding-bottom:194px;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .title-group{-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;display:block;margin-bottom:48px;}@media(min-width: 769px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .title-group{dis
34play:none;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection{width:100%;min-width:400px;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection:not(.slick-initialized){display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection:not(.slick-initialized) .item-box:nth-child(n+6){display:none;}@media(max-width: 768px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection:not(.slick-initialized){-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-track{margin-left:0;margin-right:0;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-list{overflow:visible;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection img{max-width:100%;}@media(min-width: 1025px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:not(:nth-child(4n-2)){opacity:.3;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(4n-2) .item__img{opacity:.3;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;-webkit-transform:translate(-50%, 45px);-moz-transform:translate(-50%, 45px);-ms-transform:translate(-50%, 45px);transform:translate(-50%, 45px);}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(4n-2) .item__img svg{display:block;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(4n-2) .item__info{-webkit-transform:translate(0, calc(50% + 45px));-moz-transform:translate(0, calc(50% + 45px));-ms-transform:translate(0, calc(50% + 45px));transform:translate(0, calc(50% + 45px));}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(4n-2) .media-type-icon{top:50%;-webkit-transform:translate(0, calc(50% + 35px));-moz-transform:translate(0, calc(50% + 35px));-ms-transform:translate(0, calc(50% + 35px));transform:translate(0, calc(50% + 35px));}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-active:not(:nth-child(4n-2)){opacity:1;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-active:nth-child(4n-2) .item__img{opacity:1;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}}@media (min-width: 769px) and (max-width: 1025px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:not(:nth-child(even)){opacity:.3;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(even) .item__img{opacity:.3;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;-webkit-transform:translate(-50%, 45px);-moz-transform:translate(-50%, 45px);-ms-transform:translate(-50%, 45px);transform:translate(-50%, 45px);}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(even) .item__img svg{display:block;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(even) .item__info{-webkit-transform:translate(0, calc(50% + 45px));-moz-transform:translate(0, calc(50% + 45px));-ms-transform:translate(0, calc(50% + 45px));transform:translate(0, calc(50% + 45px));}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(even) .media-type-icon{top:50%;-webkit-transform:translate(0, calc(50% + 35px));-moz-transform:translate(0, calc(50% + 35px));-ms-transform:translate(0, calc(50% + 35px));transform:translate(0, calc(50% + 35px));}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-active:not(:nth-child(even)){opacity:1;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-active:nth-child(even) .item__img{opacity:1;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}}@media(max-width: 768px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide{opacity:.3;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-active{opacity:1;-webkit-transition:opacity .4s ease-in-out;transition:opacity .4s ease-in-out;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(4n-1),#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection .slick-slide:nth-child(4n){-webkit-transform:translate(-200%, 100%);-moz-transform:translate(-200%, 100%);-ms-transform:translate(-200%, 100%);transform:translate(-200%, 100%);}}@media(min-width: 1440px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .collection{overflow:hidden;height:514px;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .slider-holder{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}@media(max-width: 768px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .slider-holder{height:calc(100vw - 24px);}}@media(min-width: 1440px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .slider-holder{width:1440px;margin-left:auto;margin-right:auto;height:310px;}}
34#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative;z-index:1;width:310px;height:310px;overflow:visible;margin-right:67px;cursor:default;}@media(max-width: 1024px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item{width:298px;height:298px;margin-right:44px;}}@media(max-width: 768px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item{margin-right:0;margin-bottom:0;width:calc(50vw - 48px);height:calc(50vw - 48px);}}@media(max-width: 560px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item{margin-right:0;margin-bottom:0;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__img{top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-moz-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);position:absolute;height:100%;width:100%;background-color:gray;-webkit-background-size:cover;background-size:cover;-webkit-background-position:center center;background-position:center center;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;-webkit-transition:all linear 0.2s;transition:all linear 0.2s;transform-origin:bottom;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__img svg{display:none;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__text{top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-moz-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);position:absolute;overflow:hidden;height:100%;width:100%;word-break:break-all;}@media (max-width: 768px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__text{display:none;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__text .username-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__text .username-group .lp-h5{cursor:pointer;display:inline-block;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__text .username-group .lp-h5 span{-webkit-transition:0.2s all;transition:0.2s all;display:inline-block;}@media (hover: hover) and (pointer: fine){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__text .username-group .lp-h5:hover span{-webkit-transform:translateX(5px);-moz-transform:translateX(5px);-ms-transform:translateX(5px);transform:translateX(5px);}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__text .username-group .arrow-icon{display:inline-block;margin-top:9px;width:21px;}@media (max-width: 768px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item-box{padding:13px;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .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.7);opacity:0;-webkit-transition:opacity .3s ease;transition:opacity .3s ease;cursor:pointer;}@media (hover: hover){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__info:hover{opacity:1;}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .item__caption{text-overflow:ellipsis;-webkit-line-clamp:5;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 h5{color:var(--userColor);text-transform:uppercase;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 h3{color:var(--fontColor);margin-bottom:16px;white-space:pre-line;}@media (max-width: 768px){#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 h3{width:calc(100vw - 50px);}}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 a{-webkit-text-decoration:none;text-decoration:none;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .media-type-icon{position:absolute;top:10px;right:10px;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71 .has-data .section{dis
34play:block;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71.has-data .section{display:block;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71#section-temp .section{display:block;}#section-688bafaa-1ccc-4661-b05d-4c7f46978b71>div:last-child{padding-bottom:calc(4 / 4 * var(--global-section-padding))!important;}#modal-global-contact-us .section{width:100%;min-height:100vh;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;-webkit-box-pack:start!important;-ms-flex-pack:start!important;-webkit-justify-content:flex-start!important;justify-content:flex-start!important;}@media (max-width: 1024px){#modal-global-contact-us .section{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}#modal-global-contact-us .left{width:100%;max-width:600px;padding:80px;}@media (max-width: 1200px){#modal-global-contact-us .left{padding-left:50px;padding-right:50px;}}@media (max-width: 1024px){#modal-global-contact-us .left{max-width:100%;min-height:auto;width:100%;padding:50px;}}@media (max-width: 767px){#modal-global-contact-us .left{padding:50px 24px;}}#modal-global-contact-us .left .lp-h2{margin:0 0 48px;}@media (max-width: 767px){#modal-global-contact-us .left .lp-h2{margin:0 0 32px;}}#modal-global-contact-us .contact-form__form{width:100%;min-width:440px;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;gap:24px;margin:0;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}@media (max-width: 767px){#modal-global-contact-us .contact-form__form{min-width:100%;}}#modal-global-contact-us .contact-form__form .input-container{width:100%;}#modal-global-contact-us .contact-form__form .input-container:not(.textarea){width:calc(50% - 12px);}@media (max-width: 767px){#modal-global-contact-us .contact-form__form .input-container:not(.textarea){width:100%;}}#modal-global-contact-us .contact-form__form .lp-input{padding-left:24px;width:100%;}#modal-global-contact-us .button-holder{width:100%;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;}#modal-global-contact-us .button-holder .btn{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;}#modal-global-contact-us .sync-icon{display:none;margin-right:10px;-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;}#modal-global-contact-us .success-icon{display:none;margin-right:10px;-webkit-transition:0s;transition:0s;visibility:visible;}#modal-global-contact-us .loading{pointer-events:none;}#modal-global-contact-us .loading .sync-icon{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;}#modal-global-contact-us .success-text{display:none;}#modal-global-contact-us .success{pointer-events:none;}#modal-global-contact-us .success .success-icon{display:block;}#modal-global-contact-us .success .success-text{display:inline;}#modal-global-contact-us .input-container{width:calc(50% - 24px);}#modal-global-contact-us .input-container:last-child{width:100%;}#modal-global-contact-us .contact-form__submit{width:175px;}@media (max-width: 767px){#modal-global-contact-us .contact-form__submit{width:100%;}}#modal-global-contact-us .lp-input{width:100%;}#modal-global-contact-us .pre-title{display:inline-block;padding-right:190px;margin:0 0 48px;position:relative;max-width:440px;}@media (max-width: 767px){#modal-global-contact-us .pre-title{margin:0 0 32px;padding-right:130px;}}#modal-global-contact-us .pre-title:after{content:'';height:1px;width:165px;position:absolute;top:13px;right:0;background-color:#CCB091;}@media (max-width: 767px){#modal-global-contact-us .pre-title:after{width:118px;}}#modal-global-contact-us .right{background-color:var(--bgColor);-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;
34-webkit-justify-content:space-between;justify-content:space-between;position:relative;padding:80px;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}@media (max-width: 1024px){#modal-global-contact-us .right{max-width:100%;min-height:auto;width:100%;padding:50px;}}@media (max-width: 767px){#modal-global-contact-us .right{padding:50px 24px;}}#modal-global-contact-us .right >*{position:relative;z-index:2;}#modal-global-contact-us .right .lp-h3{margin:0 0 48px;}@media (max-width: 767px){#modal-global-contact-us .right .lp-h3{margin-bottom:32px;}}#modal-global-contact-us .right .img-wrapper{overflow:hidden;}#modal-global-contact-us .agent-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:25px;margin-bottom:40px;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}#modal-global-contact-us .agent{word-break:break-all;}#modal-global-contact-us .agent p{margin:0;}#modal-global-contact-us .address{margin:0 0 40px;}#modal-global-contact-us .img-wrapper{position:absolute;top:0;left:0;width:100%;height:100%;}#modal-global-contact-us .img-wrapper .img{position:relative;object-fit:cover;height:100%;width:100%;}#modal-global-contact-us .img-wrapper:after{content:'';position:absolute;background-color:var(--bgOpacity);top:0;left:0;bottom:0;right:0;}#modal-global-contact-us .close img,#modal-global-contact-us .close .lp-close-icon{border-style:none;max-width:100%;}@media (max-width: 1024px){#modal-global-contact-us .close img,#modal-global-contact-us .close .lp-close-icon{margin-top:15px;-webkit-filter:invert(1);filter:invert(1);}}#modal-global-contact-us input,#modal-global-contact-us textarea{color:inherit!important;}nav{-webkit-transition:0.2s all;transition:0.2s all;}nav nav{-webkit-transition:0.2s all;transition:0.2s all;}nav .header{padding-top:30px;padding-bottom:30px;}nav .header__right{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-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-basis:50%;-ms-flex-preferred-size:50%;flex-basis:50%;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;}nav .header__container{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;}nav .header__btn-contact{border:1px solid;border-radius:3px;padding:18px 40px;-webkit-transition:0.2s all;transition:0.2s all;text-transform:none;margin-left:40px;font-size:18px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}@media (hover: hover) and (pointer: fine){nav .header__btn-contact:hover{background-color:var(--themeBlack);color:var(--themeWhite);}}@media (max-width: 768px){nav .header__btn-contact{padding:10px;margin-left:5px;margin-right:12px;}}nav .header__hamburger{background-color:transparent;cursor:pointer;outline:none;position:relative;padding: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;margin-left:41px;width:60px;height:60px;border:none;}@media (max-width: 768px){nav .header__hamburger{width:40px;height:40px;margin-left:15px;}}@media (hover: hover) and (pointer: fine){nav .header__hamburger:hover .line--top{width:12px;x:30px;}nav .header__hamburger:hover .line--bottom{width:24px;x:18px;}}nav .header__hamburger svg{width:100%;height:100%;}nav .header__hamburger circle{fill:var(--themeBeige);}nav .header__hamburger .line{fill:var(--themeWhite);height:2px;width:24px;x:18px;y:26px;-webkit-transition:0.2s all;transition:0.2s all;}nav .header__hamburger .line--bottom{width:12px;x:30px;y:32px;}nav .sub-nav{position:absolute;left:0;top:100%;padding:0;max-height:0;z-index:5;margin:0;list-style-type:none;overflow:hidden;visibility:hidden;-webkit-transition:visibility 0s linear 0.3s,max-height 0.3s ease;transition:visibility 0s linear 0.3s,max-height 0.3s ease;}nav .sub-nav.visible{-webkit-transition:visibility 0s linear 0s,max-height 0.3s ease-in;transition:visibility 0s linear 0s,max-height 0.3s ease-in;max-height:100vh;visibility:visible;}nav .sub-nav__item{position:relative;display:block;margin:0;text-align:left;}nav .sub-nav__link{display:block;color:var(--themeWhite);font-size:14px;font-weight:600;padding:10px 18px;position:relative;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:178px;min-width:100%;cursor:pointer;-webkit-text-decoration:none;text-decoration:none;background-color:var(--themeBlack);}@media (hover: hover) and (pointer: fine){nav .sub-nav__link:hover{color:var(--themeWhite);background-color:rgba(75, 75, 75, 1);}}nav .logo{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;outline:none;max-width:234px;height:60px;}@media (max-width: 768px){nav .logo{width:145px;}}nav .logo__img{object-fit:contain;object-position:left;max-width:100%;max-height:100%;}nav .logo__img.light{display:none;}nav .logo__img.dark{display:block;}nav .scroll .header{padding-top:22px;padding-bottom:22px;}@media (hover: hover) and (pointer: fine){nav .scroll .header__btn-contact:hover{background-color:var(--themeWhite);color:var(--themeBlack);}}nav .scroll .search__btn{color:var(--themeWhite);}nav .scroll .logo__img.dark{display:none;}nav .scroll .logo__img.light{display:block;}nav .header.theme-light{color:#fff;}nav .header.theme-light .lp-btn.lp-btn--dark.lp-btn--outline{color:var(--themeWhite, #fff);border-color:var(--themeWhite, #fff);}nav .header.theme-light .lp-btn.lp-btn--dark.lp-btn--outline:hover{color:var(--themeBlack, #fff);border-color:var(--themeBlack, #fff);background-color:var(--themeWhite, #fff);}nav .header.theme-light .logo__img.dark{display:none;}nav .header.theme-light .logo__img.light{display:block;}nav.scroll .header{padding-top:22px;padding-bottom:22px;}nav.scroll .lp-btn.lp-btn--dark.lp-btn--outline{color:var(--themeWhite, #fff);border-color:var(--themeWhite, #fff);}nav.scroll .lp-btn.lp-btn--dark.lp-btn--outline:hover{color:var(--themeBlack, #fff);border-color:var(--themeBlack, #fff);background-color:var(--themeWhite, #fff);}nav.scroll .search__btn{color:var(--themeWhite);}nav.scroll .logo__img.dark{display:none;}nav.scroll .logo__img.light{display:block;}
34nav .navigation{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;list-style-type:none;margin:0;padding:0;-webkit-box-flex-wrap:wrap;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex:1;-ms-flex:1;flex:1;}@media (max-width: 1024px){nav .navigation{display:none;}}nav .navigation__item{padding:0;margin:0;visibility:hidden;height:0;}nav .navigation__item+.navigation__item{padding-left:20px;}@media (hover: hover) and (pointer: fine){nav .navigation .navigation__item:not(.sub-nav-container) .navigation__link:after{content:'';position:absolute;display:block;width:0;height:2px;-webkit-transition:width .3s linear;transition:width .3s linear;background:var(--themeBeige);bottom:0;left:0;}nav .navigation .navigation__item:not(.sub-nav-container) .navigation__link:hover:after{width:100%;}}nav .navigation__link{display:block;position:relative;font-size:18px;line-height:18px;background-color:transparent;border:none;border-bottom:2px solid transparent;border-top:2px solid transparent;cursor:pointer;padding:21px 10px;max-width:180px;z-index:2;outline:none;color:inherit;-webkit-text-decoration:none;text-decoration:none;white-space:nowrap;-webkit-font-smoothing:unset;-webkit-transition:color .3s linear;transition:color .3s linear;}nav .navigation__link:focus,nav .navigation__link:active{outline:none;}nav .sub-nav-container{position:relative;padding-right:21px;}nav .sub-nav-container:after{display:block;content:'';width:8px;height:8px;border-right:2px solid;border-bottom:2px solid;position:absolute;right:3px;top:50%;-webkit-transform:translate(0, calc(-50% - 3px)) rotate(45deg);-moz-transform:translate(0, calc(-50% - 3px)) rotate(45deg);-ms-transform:translate(0, calc(-50% - 3px)) rotate(45deg);transform:translate(0, calc(-50% - 3px)) rotate(45deg);-webkit-transition:-webkit-transform 0.2s linear;transition:transform 0.2s linear;}nav .sub-nav-container.active:after{-webkit-transform:translate(0, calc(-50% + 3px)) rotate(-135deg);-moz-transform:translate(0, calc(-50% + 3px)) rotate(-135deg);-ms-transform:translate(0, calc(-50% + 3px)) rotate(-135deg);transform:translate(0, calc(-50% + 3px)) rotate(-135deg);}nav .search{position:relative;}nav .search__btn{border:none;background-color:transparent;margin-left:20px;cursor:pointer;display:block;color:inherit;}@media (max-width: 768px){nav .search__btn{margin-left:0;}}nav .search__btn svg{display:block;}@media (max-width: 768px){nav .hide-mobile{display:none;}}body>div.sidemenu{background-color:rgba(255, 255, 255, 1);color:rgba(35, 31, 32, 1);--fontColor:rgba(35, 31, 32, 1);--fontColor_H:345;--fontColor_S:6%;--fontColor_L:13%;--fontColor_A:1;--fontColor_darkenDir:1;--bgColor:rgba(255, 255, 255, 1);--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:1;--bgColor_darkenDir:-1;}body>div.sidemenu{--colorLighter1:hsla(var(--fontColor_H), var(--fontColor_S), var(--fontColor_L), 0.1);}body>div.sidemenu{width:100%;max-width:520px;left:auto;right:0;top:0;-webkit-transform:translateX(100%);-moz-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%);-webkit-transition:0.3s -webkit-transform ease,0s visibility linear 0.3s;transition:0.3s transform ease,0s visibility linear 0.3s;display:block;}body>div.sidemenu.visible{-webkit-transform:translateX(0);-moz-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0);visibility:visible;-webkit-transition:0.3s -webkit-transform ease,0s visibility linear 0s;transition:0.3s transform ease,0s visibility linear 0s;}@media (max-width: 768px){body>div.sidemenu{max-width:320px;}}body>div.sidemenu .sidemenu__wrapper{background-color:var(--bgColor, #211F1F);-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;height:100vh;padding:80px 0 66px 0;overflow-y:auto;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}body>div.sidemenu .sidemenu__wrapper::-webkit-scrollbar{width:4px;background-color:transparent;}body>div.sidemenu .sidemenu__wrapper::-webkit-scrollbar-thumb{background-color:var(--fontColor, #ffffff);}body>div.sidemenu .sidemenu__wrapper::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 4px rgba(0,0,0,0.3);background-color:var(--bgColor, #211F1F);}@media (max-width: 768px){body>div.sidemenu .sidemenu__wrapper{padding:40px 0 66px 0;}}body>div.sidemenu .sidemenu__toggle{height:48px;margin-right:auto;margin-left:70px;position:relative;border:none;background-color:transparent;outline:none;color:var(--fontColor, #ffffff);padding-right:50px;font-family:inherit;cursor:pointer;}@media (max-width: 768px){body>div.sidemenu .sidemenu__toggle{margin-left:20px;}}body>div.sidemenu .sidemenu__toggle--right{margin-left:auto;margin-right:70px;}@media (max-width: 768px){body>div.sidemenu .sidemenu__toggle--right{margin-right:20px;}}body>div.sidemenu .sidemenu__toggle:focus{outline:none;}body>div.sidemenu .sidemenu__toggle:before,body>div.sidemenu .sidemenu__toggle:after{content:'';display:block;position:absolute;width:20px;height:2px;background-color:currentColor;right:0;top:50%;}body>div.sidemenu .sidemenu__toggle: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 .sidemenu__toggle:after{-webkit-transform:translate(-50%, -50%) rotate(-225deg);-moz-transform:translate(-50%, -50%) rotate(-225deg);-ms-transform:translate(-50%, -50%) rotate(-225deg);transform:translate(-50%, -50%) rotate(-225deg);}body>div.sidemenu .sidemenu__nav{margin-bottom:auto;padding:0;}body>div.sidemenu .sidemenu__socials{margin-left:auto;padding-top:30px;padding-right:70px;}@media (max-width: 768px){body>div.sidemenu .sidemenu__socials{padding-right:20px;padding-left:20px;}}body>div.sidemenu .sidemenu__socials .lp-socials li{margin-bottom:14px;}body>div.sidemenu .sidemenu__header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;
34-webkit-justify-content:space-between;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-bottom:93px;}@media (max-width: 768px){body>div.sidemenu .sidemenu__header{padding-bottom:59px;}}body>div.sidemenu .sidemenu__logo{display:none;}@media (max-width: 768px){body>div.sidemenu .sidemenu__logo{display:block;}}body>div.sidemenu .sidemenu__logo-img{display:block;max-height:50px;}body>div.sidemenu .navigation{list-style-type:none;margin:0;padding:0;max-width:100%;}body>div.sidemenu .navigation__item{border-bottom:1px solid var(--colorLighter1);margin:0;}body>div.sidemenu .navigation__link{padding:12px 12px 12px 70px;display:block;font-size:22px;font-weight:400;line-height:48px;color:var(--fontColor, #ffffff);-webkit-transition:0.2s all;transition:0.2s all;cursor:pointer;-webkit-text-decoration:none;text-decoration:none;font-family:var(--global-primary-font-family);}@media(max-width: 768px){body>div.sidemenu .navigation__link{padding-left:20px;padding-right:20px;padding-bottom:16px;}}@media (hover: hover) and (pointer: fine){body>div.sidemenu .navigation__link:hover{color:var(--fontColor, #ffffff);}}body>div.sidemenu .sub-nav{list-style-type:none;display:none;margin:0;padding:10px 0 30px 85px;}@media(max-width: 768px){body>div.sidemenu .sub-nav{padding-bottom:16px;padding-left:35px;}}body>div.sidemenu .sub-nav__item{padding-bottom:10px;margin:0;}body>div.sidemenu .sub-nav__link{font-size:16px;font-weight:400;color:var(--fontColor, #ffffff);font-family:var(--global-secondary-font-family);-webkit-text-decoration:none;text-decoration:none;}body>div.sidemenu .sub-nav-container.active{border-bottom:none;}body>div.sidemenu .sub-nav-container.active>.navigation__link:after{-webkit-transform:rotate(225deg);-moz-transform:rotate(225deg);-ms-transform:rotate(225deg);transform:rotate(225deg);top:0;}body>div.sidemenu .sub-nav-container.active>.sub-nav{display:block;}body>div.sidemenu .sub-nav-container>.navigation__link{position:relative;padding-right:30px;}body>div.sidemenu .sub-nav-container>.navigation__link:after{display:inline-block;content:'';width:8px;height:8px;border-right:2.5px solid;border-bottom:2.5px solid;margin-left:17px;top:2px;position:relative;-webkit-transform:translate(0, calc(-50% - 3px)) rotate(45deg);-moz-transform:translate(0, calc(-50% - 3px)) rotate(45deg);-ms-transform:translate(0, calc(-50% - 3px)) rotate(45deg);-webkit-transform:translate(0, calc(-50% - 3px)) rotate(45deg);-moz-transform:translate(0, calc(-50% - 3px)) rotate(45deg);-ms-transform:translate(0, calc(-50% - 3px)) rotate(45deg);transform:translate(0, calc(-50% - 3px)) rotate(45deg);-webkit-transition:0.2s all;-webkit-transition:0.2s all;transition:0.2s all;}body>div.sidemenu body>div.sidemenu{width:100%;max-width:520px;left:auto;right:0;top:0;}@media (max-width: 768px){body>div.sidemenu body>div.sidemenu{max-width:320px;}}footer{background-color:#ffffff;color:rgba(35, 31, 32, 1);--fontColor:rgba(35, 31, 32, 1);--fontColor_H:345;--fontColor_S:6%;--fontColor_L:13%;--fontColor_A:1;--fontColor_darkenDir:1;--bgColor:#ffffff;--bgColor_H:0;--bgColor_S:0%;--bgColor_L:100%;--bgColor_A:1;--bgColor_darkenDir:-1;}footer .lp-input--dark{background-color:#fff;}footer .site-footer__subscribe{padding-top:92px;padding-bottom:92px;background-color:rgba(0,0,0,0.1);}@media (max-width: 768px){footer .site-footer__subscribe{padding-top:64px;padding-bottom:64px;}}footer .site-footer__logo-bar{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;padding-bottom:64px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}@media (max-width: 768px){footer .site-footer__logo-bar{padding-bottom:24px;}}footer .site-footer__logo-container img{max-width:268px;max-height:56px;object-fit:contain;display:block;object-position:left top;}footer .site-footer__logo-container+.site-footer__logo-container{margin-left:50px;}@media (max-width: 768px){footer .site-footer__logo-container+.site-footer__logo-container{margin-left:0;margin-top:16px;width:100%;}}footer .site-footer__info{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;}@media (max-width: 768px){footer .site-footer__info{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}footer .site-footer__info .lp-a a{white-space:nowrap;}
34footer .site-footer__col{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-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-right:32px;}footer .site-footer__col-title{width:100%;margin-bottom:16px;min-height:29px;}footer .site-footer__col-content{opacity:0.5;padding-bottom:16px;}footer .site-footer__col-content p{margin-bottom:0;}footer .site-footer__col-content a{color:inherit;}footer .site-footer__col-content+.site-footer__col-content{padding-left:40px;}@media (max-width: 768px){footer .site-footer__col-content+.site-footer__col-content{padding-left:0;}}footer .site-footer__navigation-wrap{width:100%;padding-top:32px;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;}@media (max-width: 992px){footer .site-footer__navigation-wrap{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-bottom:18px;}}@media (max-width: 768px){footer .site-footer__navigation-wrap{padding-top:24px;padding-bottom:0;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}}footer .site-footer__socials{margin-left:auto;}@media (max-width: 992px){footer .site-footer__socials{margin-left:0;}}@media (max-width: 768px){footer .site-footer__socials{margin-right:auto;}}footer .site-footer__socials li{margin-bottom:0;}footer .site-footer__disclaimer{padding-top:64px;padding-bottom:32px;position:relative;opacity:0.5;}@media (max-width: 768px){footer .site-footer__disclaimer{padding-top:18px;padding-bottom:25px;}}footer .site-footer__disclaimer:after{content:'';display:block;position:absolute;left:0;bottom:0;right:0;height:1px;background-color:currentColor;opacity:0.2;}footer .site-footer__copy{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-top:32px;font-size:18px;}@media (max-width: 768px){footer .site-footer__copy{padding-top:15px;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}footer .site-footer__copy>div:first-child{margin-bottom:15px;}}footer .site-footer__copy a{color:inherit;}footer .site-footer__copy-lp span{margin-right:5px;}footer .site-footer__copy-lp img{margin-right:30px;}@media (max-width: 768px){footer .site-footer__copy-lp img{margin-right:0;margin-bottom:15px;}}@media (min-width: 769px){footer .site-footer__copy-lp{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;}}footer .site-footer__bottom{padding-top:96px;padding-bottom:96px;}@media (max-width: 768px){footer .site-footer__bottom{padding-top:64px;padding-bottom:64px;}}footer .footer-contact{margin-bottom:13px;}footer .footer-contact p{margin-bottom:0;opacity:.7;}footer .footer-contact ul{list-style:none;padding-left:0;margin:0;}footer .footer-subscribe{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}@media (max-width: 768px){footer .footer-subscribe{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}}footer .footer-subscribe__title-wrap{padding-right:50px;}@media (max-width: 768px){footer .footer-subscribe__title-wrap{padding-right:0;padding-bottom:32px;}}footer .footer-subscribe__title{margin-bottom:8px;}footer .footer-subscribe__sub-title{margin-bottom:0;}footer .footer-subscribe__form{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;max-width:330px;margin-bottom:0;position:relative;}footer .footer-subscribe__submit{margin-top:16px;}footer .footer-subscribe__success-msg{position:absolute;top:100%;width:100%;text-align:center;opacity:.7;padding-top:10px;}footer .footer-navigation{list-style:none;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;padding:0 20px 0 0;margin:0 -30px;}@media (max-width: 992px){footer .footer-navigation{margin-bottom:36px;}}@media (max-width: 768px){footer .footer-navigation{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin:0 0 36px;}}footer .footer-navigation__item{margin:0 30px;}@media (max-width: 768px){footer .footer-navigation__item{margin:0 0 10px;}}
34footer .footer-navigation__link{color:inherit;-webkit-text-decoration:none;text-decoration:none;font-size:14px;line-height:14px;background-color:transparent;border:none;font-family:inherit;cursor:pointer;padding-left:0;padding-right:0;-webkit-transition:0.2s all;transition:0.2s all;}@media (hover: hover) and (pointer: fine){footer .footer-navigation__link:hover{color:var(--themeBeige);}}footer .lp-socials li{margin-bottom:14px;}footer .sync-icon{display:none;margin-right:10px;-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;}footer .success-icon{display:none;margin-right:10px;-webkit-transition:0s;transition:0s;visibility:visible;}footer .loading{pointer-events:none;}footer .loading .sync-icon{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;}footer .success .success-icon{display:block;}footer .lp-footer-disclaimers{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:20px;margin-top:32px;padding-top:32px;}@media (max-width: 768px){footer .lp-footer-disclaimers{padding-top:15px;margin-top:15px;}}body>div.mobile-contact-wrapper .mobile-contact{display:none;position:fixed;width:100%;height:100vh;z-index:5;pointer-events:none;bottom:0;right:0;}body>div.mobile-contact-wrapper .mobile-contact .item{outline:none;width:50px;height:50px;box-shadow:4px 4px 10px 0 rgba(0, 0, 0, 0.1);background-color:#f1f1f1;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;border-radius:50%;color:#484b4e;border:none;font-size:20px;}body>div.mobile-contact-wrapper .mobile-contact .item svg{fill:#484b4e;}body>div.mobile-contact-wrapper .mobile-contact .item:nth-child(n + 2){margin-top:15px;}body>div.mobile-contact-wrapper .mobile-contact .buttons-holder{pointer-events:all;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;position:absolute;right:25px;bottom:70px;}body>div.mobile-contact-wrapper .mobile-contact .search-close-icon{display:none;}body>div.mobile-contact-wrapper .mobile-contact .active .search-show-icon{display:none;}body>div.mobile-contact-wrapper .mobile-contact .active .search-close-icon{display:block;}body>div.mobile-contact-wrapper .mobile-contact .search-wrapper{pointer-events:all;position:absolute;bottom:30px;right:90px;overflow:hidden;width:0;-webkit-transition:width 0.4s ease;transition:width 0.4s ease;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;}body>div.mobile-contact-wrapper .mobile-contact .search-wrapper.active{width:calc(100% - 110px);}body>div.mobile-contact-wrapper .mobile-contact .search-inner{width:calc(100vw - 110px);-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-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;}body>div.mobile-contact-wrapper .mobile-contact .search-input-container{width:100%;border:solid 1px #d8d8d8;height:50px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:0 12px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#fff;box-shadow:0 0 7px 0 rgba(0, 0, 0, 0.12);}body>div.mobile-contact-wrapper .mobile-contact .search-input-container .search-icon{margin-right:10px;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;font-size:18px;}body>div.mobile-contact-wrapper .mobile-contact .search-input-container .search-input{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;border:none;border-radius:0;outline:none;color:#000;background:transparent;font-size:16px;}body>div.mobile-contact-wrapper .mobile-contact .search-results{width:100%;background-color:rgba(0, 0, 0, 0.85);border:none;color:#fff;font-size:16px;overflow:hidden;-webkit-transition:height 0.3s ease;transition:height 0.3s ease;height:0;}body>div.mobile-contact-wrapper .mobile-contact .results-container{padding:10px 0;}body>div.mobile-contact-wrapper .mobile-contact .results-container a{-webkit-transition:all 0.5s ease;transition:all 0.5s ease;color:#fff;}body>div.mobile-contact-wrapper .mobile-contact .results-container a:hover{color:inherit;opacity:0.8;}body>div.mobile-contact-wrapper .mobile-contact .results-link{display:block;padding:4px 20px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}body>div.mobile-contact-wrapper .mobile-contact .result-self{position:relative;}body>div.mobile-contact-wrapper .mobile-contact .result-self::before{content:'';position:absolute;width:7px;height:7px;border-radius:50%;border:none;background-color:currentColor;-webkit-transition:all .3s ease;transition:all .3s ease;left:9px;top:calc(50% - 4px);}body>div.mobile-contact-wrapper .mobile-contact .search-in-progress{width:100%;padding:30px;opacity:0.5;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-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;font-size:30px;}body>div.mobile-contact-wrapper .mobile-contact .search-in-progress.not-visible{display:none;}body>div.mobile-contact-wrapper .mobile-contact .nothing-found{width:100%;padding:20px;}body>div.mobile-contact-wrapper .mobile-contact.dark .item{background-color:black;color:#f1f1f1;}body>div.mobile-contact-wrapper .mobile-contact.dark .item svg{fill:#f1f1f1;}body>div.mobile-contact-wrapper .mobile-contact.dark .search-input-container{border:none;background-color:#1a1a1a;color:#f1f1f1;}body>div.mobile-contact-wrapper .mobile-contact.dark .search-input-container .search-input{color:#fff;}body>div.mobile-contact-wrapper .mobile-contact.with-search .buttons-holder{bottom:30px;}@media (max-width: 500px){body>div.mobile-contact-wrapper .mobile-contact{display:block;}} 35 </style> 36 <style id="custom-style-css">.social_icons-style-1 a{border-color:#231F20!important;background-color:rgba(0, 0, 0, 0)!important;color:#231F20!important;}.social_icons-style-1 a:hover{border-color:#231F20!important;background-color:#231F20!important;color:#FFFFFF!important;}.social_icons-style-1 a i{color:inherit!important;}
36.social_icons-style-1 a svg,.social_icons-style-1 a svg path{fill:currentColor!important;}.button-style-1{color:#231F20!important;background-color:rgba(0, 0, 0, 0)!important;border-color:#231F20!important;}.button-style-1:hover{color:#FFFFFF!important;background-color:#231F20!important;border-color:#231F20!important;}.pagination-style-1 li a{color:#231F20!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!important;}.pagination-style-1 li a:hover{color:#5E5E5E!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!important;}.pagination-style-1 li.active a{color:#5E5E5E!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!important;}.button-style-2{color:#FFFFFF!important;background-color:rgba(0, 0, 0, 0)!important;border-color:#FFFFFF!important;}.button-style-2:hover{color:#231F20!important;background-color:#FFFFFF!important;border-color:#FFFFFF!important;}.pagination-style-2 li a{color:#FFFFFF!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!important;}.pagination-style-2 li a:hover{color:#F5F5F5!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!important;}.pagination-style-2 li.active a{color:#F5F5F5!important;background-color:rgba(0, 0, 0, 0)!important;border-color:rgba(0, 0, 0, 0)!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:#231F20!important;}.social_icons-style-2 a i{color:inherit!important;}
36.social_icons-style-2 a svg,.social_icons-style-2 a svg path{fill:currentColor!important;}.hyperlink-style-3{color:#231F20!important;}.hyperlink-style-3:hover{color:#5E5E5E!important;}.button-style-3{color:#FFFFFF!important;background-color:#231F20!important;border-color:#231F20!important;}.button-style-3:hover{color:#231F20!important;background-color:rgba(0, 0, 0, 0)!important;border-color:#231F20!important;}.hyperlink-style-4{color:#FFFFFF!important;}.hyperlink-style-4:hover{color:#FFFFFF!important;}.button-style-4{color:#231F20!important;background-color:#FFFFFF!important;border-color:#FFFFFF!important;}.button-style-4:hover{color:#FFFFFF!important;background-color:rgba(0, 0, 0, 0)!important;border-color:#FFFFFF!important;}</style> 37 38 39
39<script> 40 (function utmParse() { 41 const url = new URL(window.location.href); 42 if (url.search) { 43 const utm = url.search.split(/\?|&/g).reduce((acc, current) => { 44 const matched = current.match(/utm_(content|campaign|medium|source|term|id)|gclid/g); 45 if (matched) { 46 acc[matched[0]] = current.replace(`${matched[0]}=`, ''); 47 } 48 return acc; 49 }, {}); 50 if (Object.keys(utm).length) { 51 window.localStorage.setItem('utm_vars', JSON.stringify(utm)); 52 } else { 53 // Remove old utm vars 54 window.localStorage.removeItem('utm_vars'); 55 } 56 } 57 // Set referrer in local storage 58 // This is meant to be stored once to avoid self-referrals and to have the first referrer only. 59 if (!window.localStorage.getItem('referrer')) { 60 // Capture the Referrer URL 61 const referrer = document.referrer; 62 if (referrer) { 63 // Only store the referrer if it comes from outside the current domain (to avoid self-referrals) 64 const currentDomain = window.location.hostname; 65 const referrerDomain = new URL(referrer).hostname; 66 67 if (referrerDomain !== currentDomain) { 68 // Store it in localStorage 69 localStorage.setItem('referrer', referrer); 70 } 71 } 72 } 73 })(); 74 </script>
74 75 <!-- Bing Webmaster Tools Verification -->
76<script> 77 // Check if on the homepage before the body loads 78 if (window.location.pathname === '/' || window.location.pathname === '/index.html') { 79 document.write('<meta name="msvalidate.01" content="FF55484A4BB02534A920E3081D2A91D0" />'); 80 } 81</script>
81 82 83<meta name="google-site-verification" content="UjGXcmOypCHnVkE6SMuYzpXnZfL2rhrxFikiaQrkvCA" /> 84 <!-- GOOGLE TRANSLATE STYLES are moved to external CSS --> 85</head> 86<body> 87 <div id="google_translate_element" style="display: none"></div> 88 89 <nav id="global-navbar" data-el-id="b395957e-29e6-4bd5-99ee-352fbee7732a"> 90 <div class="header theme-auto"> 91 <div class="lp-container header__container"> 92 <div class="header__logo"> 93 <a href="/" class="logo"> 94 <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/715ab712-fa22-4242-8fec-2dd60c1e2378" 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/715ab712-fa22-4242-8fec-2dd60c1e2378 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/715ab712-fa22-4242-8fec-2dd60c1e2378 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/715ab712-fa22-4242-8fec-2dd60c1e2378 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/715ab712-fa22-4242-8fec-2dd60c1e2378 1920w, 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/715ab712-fa22-4242-8fec-2dd60c1e2378 2560w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/715ab712-fa22-4242-8fec-2dd60c1e2378 2608w" sizes="500px" class="logo__img dark" alt=""> 95 <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/47cbe89b-d590-4d01-b204-ca531c553359" 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/47cbe89b-d590-4d01-b204-ca531c553359 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/47cbe89b-d590-4d01-b204-ca531c553359 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/47cbe89b-d590-4d01-b204-ca531c553359 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/47cbe89b-d590-4d01-b204-ca531c553359 1920w, 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/47cbe89b-d590-4d01-b204-ca531c553359 2560w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/47cbe89b-d590-4d01-b204-ca531c553359 2608w" sizes="500px" class="logo__img light" alt=""> 96 </a> 97 </div> 98 99 <div class="header__right"> 100 <ul class="navigation"> 101 <li class="navigation__item sub-nav-container"> 102 <a href="#" class="navigation__link">About Us</a> 103 <ul class="sub-nav"> 104 <li class="sub-nav__item"><a href="/who-we-are" class="sub-nav__link">Who We Are</a></li> 105 <li class="sub-nav__item"><a href="/team" class="sub-nav__link">Meet the Team</a></li> 106 <li class="sub-nav__item"><a href="/join-our-team" class="sub-nav__link">Join Our Team</a></li> 107 </ul> 108 </li> 109 <li class="navigation__item sub-nav-container"> 110 <a href="#" class="navigation__link">Properties</a> 111 <ul class="sub-nav"> 112 <li class="sub-nav__item"><a href="/properties/sale" class="sub-nav__link">Featured Properties</a></li> 113 <li class="sub-nav__item"><a href="/properties/open-house" class="sub-nav__link">Open House</a></li> 114 </ul> 115 </li> 116 <li class="navigation__item"> 117 <a href="/newcommunities" class="navigation__link">New Communities</a> 118 </li> 119 <li class="navigation__item"> 120 <a href="/home-search/listings" class="navigation__link">Home Search</a> 121 </li> 122 <li class="navigation__item"> 123 <a href="/properties/sold" class="navigation__link">Recent Sales</a> 124 </li> 125 <li class="navigation__item"> 126 <a href="/home-valuation" class="navigation__link">Home Valuation</a> 127 </li> 128 <li class="navigation__item"> 129 <a href="/neighborhoods" class="navigation__link">Neighborhoods</a> 130 </li> 131 <li class="navigation__item"> 132 <a data-type="CONTACT_US" class="navigation__link">Contact Us</a> 133 </li> 134 135 </ul> 136 137 138 139 140 141 <button class="hamburger-component header__hamburger">
142 <svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"> 143 <circle cx="30" cy="30" r="30" /> 144 <rect class="line line--top" x="18" y="26" width="24" height="2" /> 145 <rect class="line line--bottom" x="30" y="32" width="12" height="2" /> 146 </svg> 147 </button> 148 </div> 149 150 </div> 151</div> 152 </nav> 153 <div id="global-sidemenu" class="sidemenu" data-el-id="13ed2164-aa15-4995-819b-c0e4eb112325"> 154 <div class="sidemenu__wrapper"> 155 <div class="sidemenu__header"> 156 <button class="sidemenu__toggle toggle sidemenu__toggle--right">Close Menu</button> 157</div> 158<div class="sidemenu__nav"> 159 <ul class="navigation"> 160 <li class="navigation__item"> 161 <a href="/" class="navigation__link" data-wow-delay="2.0">Home</a> 162 </li> 163 <li class="navigation__item sub-nav-container"> 164 <a href="#" class="navigation__link">About Us</a> 165 <ul class="sub-nav"> 166 <li class="sub-nav__item"><a href="/who-we-are" class="sub-nav__link feature">Who We Are</a></li> 167 <li class="sub-nav__item"><a href="/team" class="sub-nav__link feature">Meet the Team</a></li> 168 <li class="sub-nav__item"><a href="/join-our-team" class="sub-nav__link feature">Join Our Team</a></li> 169 </ul> 170 171 </li> 172 <li class="navigation__item sub-nav-container"> 173 <a href="#" class="navigation__link">Properties</a> 174 <ul class="sub-nav"> 175 <li class="sub-nav__item"><a href="/properties/sale" class="sub-nav__link feature">Featured Properties</a></li> 176 <li class="sub-nav__item"><a href="/properties/sold" class="sub-nav__link feature">Recent Sales</a></li> 177 <li class="sub-nav__item"><a href="/properties/open-house" class="sub-nav__link feature">Open House</a></li> 178 </ul> 179 180 </li> 181 <li class="navigation__item"> 182 <a href="/newcommunities" class="navigation__link" data-wow-delay="2.3">New Communities</a> 183 </li> 184 <li class="navigation__item"> 185 <a href="/home-search/listings" class="navigation__link" data-wow-delay="2.4">Home Search</a> 186 </li> 187 <li class="navigation__item"> 188 <a href="/blog" class="navigation__link" data-wow-delay="2.5">Blog</a> 189 </li> 190 <li class="navigation__item"> 191 <a href="/home-valuation" class="navigation__link" data-wow-delay="2.6">Home Valuation</a> 192 </li> 193 <li class="navigation__item"> 194 <a href="/neighborhoods" class="navigation__link" data-wow-delay="2.7">Neighborhoods</a> 195 </li> 196 <li class="navigation__item sub-nav-container"> 197 <a href="#" class="navigation__link">Resources</a> 198 <ul class="sub-nav"> 199 <li class="sub-nav__item"><a href="/buyers-guide" class="sub-nav__link feature">Buyer's Guide</a></li> 200 <li class="sub-nav__item"><a href="/sellers-guide" class="sub-nav__link feature">Seller's Guide</a></li> 201 <li class="sub-nav__item"><a href="/mortgage-calculator" class="sub-nav__link feature">Mortgage Calculator</a></li> 202 </ul> 203 204 </li> 205 <li class="navigation__item"> 206 <a href="/contact" class="navigation__link" data-wow-delay="2.9">Contact Us</a> 207 </li> 208 <li class="navigation__item"> 209 <a href="/home-search/account" class="navigation__link" data-wow-delay="2.10">Client Search Portal</a> 210 </li> 211 </ul> 212</div> 213 214<div class="sidemenu__socials"> 215 <ul class="lp-socials social_icons-style-1 sidemenu-social-links"> 216 217 <li> 218 <a 219 href="https://www.facebook.com/corcoranpremier" 220 class="lp-socials__link socials__item" 221 data-wow-delay="0s" 222 target="_blank" 223 aria-label="FACEBOOK" 224 > 225 <span class="lp-i lp-i--facebook" aria-hidden="true"></span> 226 </a> 227 </li> 228 <li> 229 <a 230 href="https://www.instagram.com/corcoranpremier/" 231 class="lp-socials__link socials__item" 232 data-wow-delay="0.1s" 233 target="_blank" 234 aria-label="INSTAGRAM" 235 >
236 <span class="lp-i lp-i--instagram" aria-hidden="true"></span> 237 </a> 238 </li> 239 <li> 240 <a 241 href="https://www.linkedin.com/company/corcoran-premier-realty/" 242 class="lp-socials__link socials__item" 243 data-wow-delay="0.2s" 244 target="_blank" 245 aria-label="LINKEDIN" 246 > 247 <span class="lp-i lp-i--linkedin" aria-hidden="true"></span> 248 </a> 249 </li> 250 <li> 251 <a 252 href="https://www.youtube.com/@CorcoranPremierRealty" 253 class="lp-socials__link socials__item" 254 data-wow-delay="0.3s" 255 target="_blank" 256 aria-label="YOUTUBE" 257 > 258 <span class="lp-i lp-i--youtube" aria-hidden="true"></span> 259 </a> 260 </li> 261 <li> 262 <a 263 href="https://www.tiktok.com/@corcoranpremier" 264 class="lp-socials__link socials__item" 265 data-wow-delay="0.4s" 266 target="_blank" 267 aria-label="TIKTOK" 268 > 269 <span class="lp-i lp-i--tiktok" aria-hidden="true"></span> 270 </a> 271 </li> 272 <li> 273 <a 274 href="https://www.google.com/search?q=Corcoran+Premier+Realty+Windermere%2C+FL&sca_esv=c9e7664699c3aa09&rlz=1C1KNTJ_enPH1066PH1066&ei=xBCEaLzUNNiuseMPqIrL6QU&ved=0ahUKEwi8xv_GktmOAxVYV2wGHSjFMl0Q4dUDCBA&uact=5&oq=Corcoran+Premier+Realty+Windermere%2C+FL&gs_lp=Egxnd3Mtd2l6LXNlcnAiJkNvcmNvcmFuIFByZW1pZXIgUmVhbHR5IFdpbmRlcm1lcmUsIEZMMgUQABjvBTIFEAAY7wUyCBAAGIAEGKIEMgUQABjvBTIIEAAYogQYiQVI2x5QuwFYwB1wAXgBkAEAmAFzoAHsB6oBBDEwLjK4AQPIAQD4AQGYAg2gApoIwgIKEAAYsAMY1gQYR8ICCBAhGKABGMMEwgIEECEYFcICChAhGKABGMMEGArCAgYQABgNGB6YAwCIBgGQBgiSBwQxMC4zoAehJrIHAzkuM7gHkwjCBwUxLjYuNsgHIA&sclient=gws-wiz-serp#lrd=0x88e77fa02fc53b8b:0x1c57ffe44f482a61,1,,,," 275 class="lp-socials__link socials__item" 276 data-wow-delay="0.5s" 277 target="_blank" 278 aria-label="GOOGLE" 279 > 280 <span class="lp-i lp-i--google" aria-hidden="true"></span> 281 </a> 282 </li> 283 <li> 284 <a 285 href="https://share.google/iaOB0PBakQVmptMFE" 286 class="lp-socials__link socials__item" 287 data-wow-delay="0.6s" 288 target="_blank" 289 aria-label="PODCAST" 290 > 291 <span class="lp-i lp-i--podcast" aria-hidden="true"></span> 292 </a> 293 </li> 294 </ul></div> 295</div> 296 297 </div> 298 <div id="global-mobile-contact" class="mobile-contact-wrapper" data-el-id="ae1d2620-ed7f-458b-85a6-30bb62650e72"> 299 <div class="mobile-contact redesign"> 300 <div class="buttons-holder"> 301 <a class="item" href="/cdn-cgi/l/email-protection#1360727f766053707c61707c61727d6361767e7a76613d707c7e"> 302 <svg xmlns="http://www.w3.org/2000/svg" width="26" height="18" fill="none" viewBox="0 0 26 18"> 303 <path fill-rule="evenodd" d="M1.273 18l7.734-7.735c.395.352.838.647 1.32.87.592.275 1.233.44 1.885.488.779.055 1.567-.059 2.297-.334.62-.235 1.189-.584 1.684-1.023L23.927 18H1.273zm6.454-9L0 16.727V1.273L7.727 9zM25.2 1.3v15.427l-7.71-7.71c2.603-2.54 5.154-5.13 7.71-7.717zM23.927 0l-8.78 8.78c-.343.339-.744.61-1.192.792-.903.367-1.942.349-2.831-.05-.37-.167-.707-.398-1.003-.675l-.403-.389c-.01-.014-.021-.029-.034-.042-.049-.058-.104-.109-.166-.152-2.8-2.714-5.54-5.49-8.28-8.264h22.69z" clip-rule="evenodd"/> 304 </svg> 305 </a> 306 <a class="item" href="tel:(407) 749-6200"> 307 <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="none" viewBox="0 0 25 25"> 308 <path d="M24.1 18.172l-5.109-2.635c-.71-.369-1.606-.185-2.106.448l-1.87 2.397c-1.817-.974-3.213-1.923-4.82-3.53-1.71-1.713-2.633-3.136-3.58-4.9l2.37-1.845c.631-.5.842-1.397.447-2.108L6.8.914C6.325.018 5.192-.272 4.376.28l-3.24 2.16C.374 2.944-.047 3.813.005 4.709.057 5.63.19 6.789.4 7.606c.948 3.636 3.213 7.404 6.4 10.592 3.186 3.188 6.952 5.454 10.586 6.403.816.21 1.975.316 2.923.395.922.053 1.79-.395 2.291-1.16l2.107-3.293c.58-.817.263-1.923-.606-2.371z"/> 309 </svg> 310 </a> 311 </div> 312 313</div> 314 315 </div> 316 <section class="image-section is-font-color-light is-background-color-dark" id="section-f0cc46ac-4d4b-426a-a54d-6d7555c49280" data-el-id="bce33bae-7388-4ccc-abff-e0ce18ec46d2">
vendor: 114 bytes, lines 316-318
316 317 318<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
318<script> 319 (function(){ 320 const sectionId = 'section-f0cc46ac-4d4b-426a-a54d-6d7555c49280' 321 const section = document.querySelector(`#${sectionId}`); 322 var sectionBg = window.getComputedStyle(section, null).getPropertyValue('background-image'); 323 324 if('true' === 'true') { 325 section.classList.add('parallax-enabled'); 326 section.style.setProperty('--sectionBackground', sectionBg); 327 section.style.setProperty('background', 'transparent'); 328 } 329 })() 330</script>
330 331 332 333<div class="opening-with-search height-class-770px parallax"> 334 <div class="center-block"> 335 <button class='lp-play video-section__play-button js-play-btn'></button> 336 <div class="container lp-container"> 337 338 <div class="lp-title-group"> 339 340 341 <h1 class="h1 lp-h1 opening-title lp-pre-line" style="color: #ffffff">Contact Us</h1> 342 343 344 </div> 345 346 <div class="buttons"></div> 347 348 </div> 349 </div> 350 <div class="bottom-spacer"></div> 351</div> 352</section> 353<section id="section-effb862d-3cb0-4174-960c-c1cca02380a8" class="solid-section is-font-color-dark is-background-color-light" data-el-id="ee03b9c1-ce78-4c15-86a1-10124375dc59"> 354 <div class="custom-form redesign" id="js-contact-form"> 355 <div class="lp-container custom-form__container"> 356 357 <div class="custom-form__header"> 358 <h2 class="lp-h2 custom-form__heading">Your Question, Our Answer</h2> 359 <div class="custom-form__lead lp-text--subtitle"><p>Fill out the form below to learn more about buying or selling a house in your area.</p></div> 360 </div> 361 <div class="elem-row custom-form__row"> 362 <div class="elem-col custom-form__form-col"> 363 <form class="custom-form__download-form" data-type="contact-form" data-delay="6000"> 364 <div class="form-row custom-form__form-row"> 365 366 <div class="h-pot lp-h-pot"> 367 <label for="section-effb862d-3cb0-4174-960c-c1cca02380a8-middleName">Middle Name</label> 368 <input id="section-effb862d-3cb0-4174-960c-c1cca02380a8-middleName" name="middleName" value="" autocomplete="off" tabindex="-1"> 369 </div> 370 371 <div class="form-col js-backup-email"> 372 <div class="lp-form-group custom-form__group"> 373 <div class="lp-input-group"> 374 <label for="section-effb862d-3cb0-4174-960c-c1cca02380a8-required-email-field" class="lp-label field-required">Email</label> 375 <input type="email" id="section-effb862d-3cb0-4174-960c-c1cca02380a8-required-email-field" name="email" class="lp-input lp-input--dark js-form-element js-backup-field" placeholder="Email *" required> 376 </div> 377 </div> 378 </div> 379 380 381 <div class="form-col"> 382 <div class="lp-form-group custom-form__group"> 383 <div class="lp-input-group"> 384 <label for="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-0" class="lp-label field-required">First Name</label> 385 <input type="text" id="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-0" name="name" class="lp-input lp-input--dark js-form-element" placeholder="First Name *" required> 386 </div> 387 </div> 388 </div> 389 <div class="form-col"> 390 <div class="lp-form-group custom-form__group"> 391 <div class="lp-input-group"> 392 <label for="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-1" class="lp-label field-required">Last Name</label> 393 <input type="text" id="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-1" name="name" class="lp-input lp-input--dark js-form-element" placeholder="Last Name *" required> 394 </div> 395 </div> 396 </div> 397 <div class="form-col"> 398 <div class="lp-form-group custom-form__group"> 399 <div class="lp-input-group"> 400 <label for="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-2" class="lp-label">Phone</label> 401 <input type="tel" id="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-2" name="phone" class="lp-input lp-input--dark js-form-element" placeholder="Phone"> 402 </div> 403 </div> 404 </div> 405 <div class="form-col"> 406 <div class="lp-form-group custom-form__group"> 407 <div class="lp-input-group"> 408 <label for="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-3" class="lp-label field-required">Email</label> 409 <input type="email" id="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-3" name="email" class="lp-in
409put lp-input--dark js-form-element" placeholder="Email *" required> 410 </div> 411 </div> 412 </div> 413 <div class="form-col"> 414 <div class="lp-form-group custom-form__group"> 415 <div class="lp-input-group"> 416 <label for="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-4" class="lp-label field-required">Message</label> 417 <textarea name="message" rows="4" id="section-effb862d-3cb0-4174-960c-c1cca02380a8-field-4" class="lp-input lp-input--dark js-form-element" placeholder="Message *" required></textarea> 418 </div> 419 </div> 420 </div> 421 </div> 422 423 <div class="lp-disclaimer"> <label style='display: none;' for='section-effb862d-3cb0-4174-960c-c1cca02380a8-termsAccepted'>Opt In/Disclaimer Consent:</label> 424 <label class='lp-tcr-content'> 425 <span class='lp-tcr-checkbox'> 426 <input 427 type='checkbox' 428 id='section-effb862d-3cb0-4174-960c-c1cca02380a8-termsAccepted' 429 name='termsAccepted' 430 oninvalid="this.setCustomValidity('Please accept the terms and conditions')" 431 oninput="this.setCustomValidity('')" 432 required 433 /></span> 434 <span class='lp-tcr-message'> 435 By providing your name, signature and phone number, you consent to receiving sales calls and texts from or on behalf of The Corcoran Group at the number provided. Consent to such communications is not a condition of purchasing any property, goods, or services. Message and data rates may apply. </span> 436 </label> 437 438</div> 439 440 <div class="custom-form__footer"> 441 <button type="submit" class="lp-btn lp-btn--dark lp-btn--filled lp-btn--mob-full-width custom-form__submit-btn button-style-1"> 442 <span class="lp-btn-icons"> 443 <span class="lp-btn-icon-loading"></span> 444 <span class="lp-btn-icon-success"></span> 445 </span> 446 Submit 447 </button> 448 </div> 449 </form> 450 </div> 451 </div> 452 </div> 453 454</div> 455 456 457</section> 458<section id="section-4c321f4f-0d95-40b2-af2a-8aa841d20888" class="solid-section is-font-color-dark is-background-color-light" data-el-id="6120297b-2131-4bf4-ac23-206d01b963ec"> 459 460<div class="media-blocks lp-vertical-paddings redesign"> 461 <div class="lp-container"> 462 463 <div class="row"> 464 465 <div class="col col-1-3"> 466 467 <div class="media-card"> 468 <div class="media-card__image"> 469 <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/a5ea6fff-7dac-415f-b223-325b196830bb" 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/a5ea6fff-7dac-415f-b223-325b196830bb 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/a5ea6fff-7dac-415f-b223-325b196830bb 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/a5ea6fff-7dac-415f-b223-325b196830bb 1280w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/a5ea6fff-7dac-415f-b223-325b196830bb 1814w" sizes="(max-width: 768px) 100vw, 33vw" alt="Home Search" loading="lazy"> 470 </div> 471 <h4 class="lp-h4 media-card__title">Home Search</h4> 472 <div class="media-card__description lp-a"></div> 473 <div> 474 <a 475 href="/home-search/listings" 476 477 class="lp-btn lp-btn--outline lp-btn--dark media-card__button button-style-1" 478 479 480 481 482 483 > 484 Browse All Properties 485 </a> 486 </div> 487 488 </div> 489 </div> 490 <div class="col col-1-3"> 491 492 <div class="media-card"> 493 <div class="media-card__image"> 494 <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/ad69696b-ed6b-4bd1-90d6-bdc9831d70b8" 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/ad69696b-ed6b-4bd1-90d6-bdc9831d70b8 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/ad69696b-ed6b-4bd1-90d6-bdc9831d70b8 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/ad69696b-ed6b-4bd1-90d6-bdc9831d70b8 1280w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/ad69696b-ed6b-4bd1-90d6-bdc9831d70b8 1814w" sizes="(max-width: 768px) 100vw, 33vw" alt="Home Valuation" loading="lazy"> 495 </div> 496 <h4 class="lp-h4 media-card__title">Home Valuation</h4> 497 <div class="media-card__description lp-a"></div> 498 <div> 499 <a 500 href="/home-valuation" 501 502 class="lp-btn lp-btn--outline lp-btn--dark media-card__button button-style-1" 503 504 505 506 507 508 > 509 Get Home Value 510 </a> 511 </div> 512 513 </div> 514 </div> 515 <div class="col col-1-3"> 516 517 <div class="media-card"> 518 <div class="media-card__image"> 519 <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/87973f04-7d72-4c02-807d-c57d491d7c95" 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/87973f04-7d72-4c02-807d-c57d491d7c95 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/87973f04-7d72-4c02-807d-c57d491d7c95 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/87973f04-7d72-4c02-807d-c57d491d7c95 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/87973f04-7d72-4c02-807d-c57d491d7c95 1920w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/87973f04-7d72-4c02-807d-c57d491d7c95 2027w" sizes="(max-width: 768px) 100vw, 33vw" alt="Recent Sales" loading="lazy"> 520 </div> 521 <h4 class="lp-h4 media-card__title">Recent Sales</h4> 522 <div class="media-card__description lp-a"></div> 523 <div> 524 <a 525 href="/properties/sold" 526 527 class="lp-btn lp-btn--outline lp-btn--dark media-card__button button-style-1" 528 529 530 531 532 533 > 534 View Sold Properties 535 </a> 536 </div> 537 538 </div> 539 </div> 540 </div> 541 542 </div> 543</div> 544 545 546</section> 547<section id="section-688bafaa-1ccc-4661-b05d-4c7f46978b71" class="solid-section is-font-color-dark is-background-color-light" data-el-id="3614c9e1-cfd9-4976-8483-8f4b825fd098"> 548
548<script type="text/x-handlebars-template" class="jsIGTemplate"> 549 <a href="https://www.instagram.com/{{username}}" target="_blank" class="title-group js-title-group"> 550 <h3 class="lp-h3 js-h3"></h3> 551 <div class="username-group"><h5 class="lp-h5">@{{username}}</h5><svg class="arrow-icon" width="18" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M-.002 7h14.085l-3.558 3.59L11.926 12l5.965-6-5.965-6-1.401 1.41L14.084 5H-.002v2Z" fill="#CCB091"/></svg></div> 552 </a> 553 554 {{#each items}} 555 {{#if mediaUrl}} 556 <div class="item-box"> 557 <a href="https://www.instagram.com/{{../username}}" target="_blank" class="item insta-type-{{mediaType}}"> 558 <div class="item__text"> 559 <h3 class="lp-h3 js-h3"></h3> 560 <div class="username-group"> <h5 class="lp-h5">@{{../username}}</h5> <svg class="arrow-icon" width="18" height="12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M-.002 7h14.085l-3.558 3.59L11.926 12l5.965-6-5.965-6-1.401 1.41L14.084 5H-.002v2Z" fill="#CCB091"/></svg></div> 561 </div> 562 <div class="item__img" style="background-image: url('{{#ifEquals mediaType 'VIDEO'}}{{thumbnailUrl}}{{else}}{{mediaUrl}}{{/ifEquals}}');"></div> 563 {{#ifEquals mediaType 'VIDEO'}} 564 <div class="media-type-icon"> 565 <svg width="30px" height="30px" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M19.369 6.042H2.082A2.086 2.086 0 000 8.125v13.71a2.086 2.086 0 002.083 2.083h17.285a2.086 2.086 0 002.084-2.083V8.125a2.086 2.086 0 00-2.084-2.083zM22.84 17.833l7.16 3.91V8.262l-7.16 3.908v5.662z"/></svg> 566 </div> 567 {{/ifEquals}} 568 {{#if caption}} 569 <div class="item__info"><div class="item__caption">{{caption}}</div></div> 570 {{/if}} 571 </a> 572 </div> 573 {{/if}} 574 {{/each}} 575</script>
575 576 577 578<div class="section"> 579 <div class="lp-container lp-container--l lp-vertical-paddings" style="--userColor: #ccb091;"> 580 <div class="slider-holder js-slider-holder" data-title="Follow Us On 581Instagram" > 582 <div class="collection js-collection jsIGContainer"></div> 583 </div> 584 </div> 585</div> 586 587 588</section> 589 590 <div id="modals" class="modals"></div> 591 <footer id="global-footer" class="is-font-color-dark is-background-color-light" data-el-id="f3892c1c-f128-483a-b998-cb1ea48c25c1"> 592 <div class="site-footer"> 593 594 <div class="site-footer__bottom"> 595 <div class="lp-container"> 596 597 <div class="site-footer__logo-bar"> 598 <div class="site-footer__logo-container"> 599 <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/715ab712-fa22-4242-8fec-2dd60c1e2378" 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/715ab712-fa22-4242-8fec-2dd60c1e2378 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/715ab712-fa22-4242-8fec-2dd60c1e2378 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/715ab712-fa22-4242-8fec-2dd60c1e2378 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/715ab712-fa22-4242-8fec-2dd60c1e2378 1920w, 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/715ab712-fa22-4242-8fec-2dd60c1e2378 2560w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/715ab712-fa22-4242-8fec-2dd60c1e2378 2608w" sizes="268px" alt=""> 600 </div> 601 <div class="site-footer__logo-container"> 602 603 </div> 604 </div> 605 606 <div class="site-footer__info"> 607 <div class="site-footer__col"> 608 <h5 class="lp-h5 site-footer__col-title">Corcoran Premier Realty</h5> 609 610 <div class="site-footer__col-content lp-a"><p><a href="/cdn-cgi/l/email-protection#fe8d9f929b8dbe9d918c9d918c9f908e8c9b93979b8cd09d9193"><span class="__cf_email__" data-cfemail="c0b3a1aca5b380a3afb2a3afb2a1aeb0b2a5ada9a5b2eea3afad">[email protected]</span></a></p></div> 611 </div> 612 613 <div class="site-footer__col"> 614 <h5 class="lp-h5 site-footer__col-title">Windermere Office</h5> 615 616 <div class="site-footer__col-content lp-a"><p><a href="tel:(407) 749-6200">(407) 749-6200</a></p> 617<p>1921 MAGUIRE RD STE 104<br>WINDERMERE FL 34786</p></div> 618 </div> 619 620 <div class="site-footer__col"> 621 <h5 class="lp-h5 site-footer__col-title">Winter Park Office </h5> 622 623 <div class="site-footer__col-content lp-a"><p><a href="tel:4073785585">(407) 378-5585</a></p> 624<p>341 N PENNSYLVANIA AVE<br>WINTER PARK FL 32789</p></div> 625 </div> 626 627 <div class="site-footer__navigation-wrap"> 628 <ul class="footer-navigation"> 629 <li class="footer-navigation__item"> 630 <a href="/" class="footer-navigation__link">Home</a> 631 </li> 632 <li class="footer-navigation__item"> 633 <a href="/team" class="footer-navigation__link">Meet the Team</a> 634 </li> 635 <li class="footer-navigation__item"> 636 <a href="/home-search/listings" class="footer-navigation__link">Home Search</a> 637 </li> 638 <li class="footer-navigation__item"> 639 <a href="/neighborhoods" class="footer-navigation__link">Neighborhoods</a> 640 </li> 641 <li class="footer-navigation__item"> 642 <button data-type="CONTACT_US" class="footer-navigation__link" type="button">Contact Us</button> 643 </li> 644 </ul> 645 646 <ul class="lp-socials social_icons-style-1 site-footer__socials socials"> 647 648 <li> 649 <a 650 href="https://www.facebook.com/corcoranpremier" 651 class="lp-socials__link socials__item" 652 data-wow-delay="0s" 653 target="_blank" 654 aria-label="FACEBOOK" 655 >
656 <span class="lp-i lp-i--facebook" aria-hidden="true"></span> 657 </a> 658 </li> 659 <li> 660 <a 661 href="https://www.instagram.com/corcoranpremier/" 662 class="lp-socials__link socials__item" 663 data-wow-delay="0.1s" 664 target="_blank" 665 aria-label="INSTAGRAM" 666 > 667 <span class="lp-i lp-i--instagram" aria-hidden="true"></span> 668 </a> 669 </li> 670 <li> 671 <a 672 href="https://www.linkedin.com/company/corcoran-premier-realty/" 673 class="lp-socials__link socials__item" 674 data-wow-delay="0.2s" 675 target="_blank" 676 aria-label="LINKEDIN" 677 > 678 <span class="lp-i lp-i--linkedin" aria-hidden="true"></span> 679 </a> 680 </li> 681 <li> 682 <a 683 href="https://www.youtube.com/@CorcoranPremierRealty" 684 class="lp-socials__link socials__item" 685 data-wow-delay="0.3s" 686 target="_blank" 687 aria-label="YOUTUBE" 688 > 689 <span class="lp-i lp-i--youtube" aria-hidden="true"></span> 690 </a> 691 </li> 692 <li> 693 <a 694 href="https://www.tiktok.com/@corcoranpremier" 695 class="lp-socials__link socials__item" 696 data-wow-delay="0.4s" 697 target="_blank" 698 aria-label="TIKTOK" 699 > 700 <span class="lp-i lp-i--tiktok" aria-hidden="true"></span> 701 </a> 702 </li> 703 <li> 704 <a 705 href="https://www.google.com/search?q=Corcoran+Premier+Realty+Windermere%2C+FL&sca_esv=c9e7664699c3aa09&rlz=1C1KNTJ_enPH1066PH1066&ei=xBCEaLzUNNiuseMPqIrL6QU&ved=0ahUKEwi8xv_GktmOAxVYV2wGHSjFMl0Q4dUDCBA&uact=5&oq=Corcoran+Premier+Realty+Windermere%2C+FL&gs_lp=Egxnd3Mtd2l6LXNlcnAiJkNvcmNvcmFuIFByZW1pZXIgUmVhbHR5IFdpbmRlcm1lcmUsIEZMMgUQABjvBTIFEAAY7wUyCBAAGIAEGKIEMgUQABjvBTIIEAAYogQYiQVI2x5QuwFYwB1wAXgBkAEAmAFzoAHsB6oBBDEwLjK4AQPIAQD4AQGYAg2gApoIwgIKEAAYsAMY1gQYR8ICCBAhGKABGMMEwgIEECEYFcICChAhGKABGMMEGArCAgYQABgNGB6YAwCIBgGQBgiSBwQxMC4zoAehJrIHAzkuM7gHkwjCBwUxLjYuNsgHIA&sclient=gws-wiz-serp#lrd=0x88e77fa02fc53b8b:0x1c57ffe44f482a61,1,,,," 706 class="lp-socials__link socials__item" 707 data-wow-delay="0.5s" 708 target="_blank" 709 aria-label="GOOGLE" 710 > 711 <span class="lp-i lp-i--google" aria-hidden="true"></span> 712 </a> 713 </li> 714 <li> 715 <a 716 href="https://share.google/iaOB0PBakQVmptMFE" 717 class="lp-socials__link socials__item" 718 data-wow-delay="0.6s" 719 target="_blank" 720 aria-label="PODCAST" 721 > 722 <span class="lp-i lp-i--podcast" aria-hidden="true"></span> 723 </a> 724 </li> 725 </ul> 726 727 </div> 728 </div> 729 730 <div class="site-footer__disclaimer"><p style="font-size: 12px;">©2025 Corcoran Premier Realty. All rights reserved. Corcoran® and the Corcoran Logo are registered service marks owned by Corcoran Group LLC. Corcoran Premier Realty fully supports the principles of the Fair Housing Act and the Equal Opportunity Act. Each franchise is independently owned and operated.<br><img style="filter: invert(0); margin-top: 20px; height: auto;" src="https://res.cloudinary.com/luxuryp/images/f_auto,q_auto/g5qzbyky8ifp5w0ex0ik/realtor-eho-logo-07232021-update-dark" width="100px"></p></div> 731
732 <div class="site-footer__copy"> 733 <div class="lp-a site-footer__copy-lp"> 734 <div class="site-footer__logo-container"> 735 <img src="https://media-production.lp-cdn.com/media/f78e371f-8cef-4648-9d4d-fb6d0cdbee59" alt=""> 736 </div> 737 <span>Website designed and developed by</span> 738 <a href="https://www.luxurypresence.com/" class="" target="_blank">Luxury Presence</a> 739 </div> 740 <div>Copyright © <span class="auto-year-update">2026</span> | <a href="/terms-and-conditions">Privacy Policy</a></div> 741 </div> 742 743 </div> 744 </div> 745 746 747 748</div> 749 750 </footer> 751 752 <div id="modal-global-contact-us" class="modal " 753 data-el-id="" 754 style="background-color: ;" 755 > 756 <div class="modal-content"> 757 <div class="section opening" style="background-color: #ffffff; --bgOpacity: rgba(0, 0, 0, 0.5); "> 758 <div class="left" style="color: rgba(35, 31, 32, 1);"> 759 760 <h2 class="lp-h2">Get in Touch</h2> 761 762 <form class="contact-form__form" data-type="contact-form"> 763 <div class="input-container"> 764 <input id="-cmp-name" name="firstName" type="text" class="lp-input lp-input--dark contact-form__input" placeholder="First Name" required> 765 </div> 766 767 <div class="input-container"> 768 <input id="-cmp-name" name="lastName" type="text" class="lp-input lp-input--dark contact-form__input" placeholder="Last Name" required> 769 </div> 770 771 <div class="input-container"> 772 <input id="-cmp-email" name="email" type="email" class="lp-input lp-input--dark contact-form__input" placeholder="Email" required pattern="[a-zA-Z0-9.!#$%&â*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+"> 773 </div> 774 775 <div class="input-container"> 776 <input id="-cmp-phone" name="phone" type="tel" class="lp-input lp-input--dark contact-form__input" placeholder="Phone" required> 777 </div> 778 779 <div class="input-container textarea"> 780 <textarea id="-cmp-contactMessage" placeholder="Message" name="message" required type="text" class="lp-input lp-input--dark contact-form__input"></textarea> 781 </div> 782 783 <div class="h-pot"> 784 <label for="-cmp-middleName">Middle Name</label> 785 <input id="-cmp-middleName" name="middleName" value="" autocomplete="off" tabindex="-1"> 786 </div> 787 788 <div class="lp-disclaimer"> <label style='display: none;' for='-termsAccepted'>Opt In/Disclaimer Consent:</label> 789 <label class='lp-tcr-content'> 790 <span class='lp-tcr-checkbox'> 791 <input 792 type='checkbox' 793 id='-termsAccepted' 794 name='termsAccepted' 795 oninvalid="this.setCustomValidity('Please accept the terms and conditions')" 796 oninput="this.setCustomValidity('')" 797 required 798 /></span> 799 <span class='lp-tcr-message'> 800 By providing your name, signature and phone number, you consent to receiving sales calls and texts from or on behalf of The Corcoran Group at the number provided. Consent to such communications is not a condition of purchasing any property, goods, or services. Message and data rates may apply. </span> 801 </label> 802 803 </div> 804 805 <input type="hidden" name="source" value="CONTACT_INQUIRY"> 806 807 <div class="button-holder"> 808 <button class="contact-form__submit btn lp-btn lp-btn--filled button-style-1" type="submit"> 809 <span class="sync-icon lp-i--spin"> 810 <svg width="20" height="15" viewBox="0 0 20 15" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> 811 <path d="M16.3636 3.66667L12.7273 7.33333H15.4545C15.4545 10.3675 13.0091 12.8333 10 12.8333C9.08182 12.8333 8.20909 12.6042 7.45455 12.1917L6.12727 13.53C7.24545 14.245 8.57273 14.6667 10 14.6667C14.0182 14.6667 17.2727 11.385 17.2727 7.33333H20L16.3636 3.66667ZM4.54545 7.33333C4.54545 4.29917 6.99091 1.83333 10 1.83333C10.9182 1.83333 11.7909 2.0625 12.5455 2.475L13.8727 1.13667C12.7545 0.421666 11.4273 0 10 0C5.98182 0 2.72727 3.28167 2.72727 7.33333H0L3.63636 11L7.27273 7.33333H4.54545Z" /> 812 </svg> 813 </span> 814
815 <span class="success-icon"> 816 <svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> 817 <path d="M10 0C4.48 0 0 4.48 0 10C0 15.52 4.48 20 10 20C15.52 20 20 15.52 20 10C20 4.48 15.52 0 10 0ZM10 18C5.59 18 2 14.41 2 10C2 5.59 5.59 2 10 2C14.41 2 18 5.59 18 10C18 14.41 14.41 18 10 18ZM14.59 5.58L8 12.17L5.41 9.59L4 11L8 15L16 7L14.59 5.58Z" /> 818 </svg> 819 </span> 820 821 Submit<span class="success-text">ted</span> 822 </button> 823 </div> 824 825 </form> 826 827 </div> 828 <div class="right" style="color: #ffffff;"> 829 <div class="img-wrapper"> 830 <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/0ec0117c-27d7-4485-a078-bb39bfb9a510" 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/0ec0117c-27d7-4485-a078-bb39bfb9a510 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/0ec0117c-27d7-4485-a078-bb39bfb9a510 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/0ec0117c-27d7-4485-a078-bb39bfb9a510 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/0ec0117c-27d7-4485-a078-bb39bfb9a510 1920w, https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/0ec0117c-27d7-4485-a078-bb39bfb9a510 2500w" class="img" alt="contact-form-background"> 831 </div> 832 833 <h3 class="lp-h3">Contact Details</h3> 834 835 <div class="top-holder"> 836 <div class="agent-row lp-a"> 837 <div class="agent"> 838 <p>CORCORAN PREMIER REALTY</p> 839 840 <p class="lp-pre-line"><p><a href="/cdn-cgi/l/email-protection#e59684898096a5868a97868a97848b959780888c8097cb868a88"><span class="__cf_email__" data-cfemail="d8abb9b4bdab98bbb7aabbb7aab9b6a8aabdb5b1bdaaf6bbb7b5">[email protected]</span></a></p></p> 841 </div> 842 843 <div class="agent"> 844 <p>WINDERMERE OFFICE</p> 845 <p class="lp-pre-line"><p><a class="lp-link" href="tel:(407) 749-6200">(407) 749-6200</a><br>1921 MAGUIRE RD STE 104<br>WINDERMERE FL 34786</p></p> 846 </div> 847 848 <div class="agent"> 849 <p>WINTER PARK OFFICE</p> 850 <p class="lp-pre-line"><p><a href="tel:4073785585">(407) 378-5585</a></p> 851 <p>341 N PENNSYLVANIA AVE<br>WINTER PARK FL 32789</p></p> 852 </div> 853 </div> 854 855 </div> 856 857 <ul class="lp-socials social_icons-style-2 site-footer__socials socials"> 858 859 <li> 860 <a 861 href="https://www.facebook.com/corcoranpremier" 862 class="lp-socials__link socials__item" 863 data-wow-delay="0s" 864 target="_blank" 865 aria-label="FACEBOOK" 866 > 867 <span class="lp-i lp-i--facebook" aria-hidden="true"></span> 868 </a> 869 </li> 870 <li> 871 <a 872 href="https://www.instagram.com/corcoranpremier/" 873 class="lp-socials__link socials__item" 874 data-wow-delay="0.1s" 875 target="_blank" 876 aria-label="INSTAGRAM" 877 >
878 <span class="lp-i lp-i--instagram" aria-hidden="true"></span> 879 </a> 880 </li> 881 <li> 882 <a 883 href="https://www.linkedin.com/company/corcoran-premier-realty/" 884 class="lp-socials__link socials__item" 885 data-wow-delay="0.2s" 886 target="_blank" 887 aria-label="LINKEDIN" 888 > 889 <span class="lp-i lp-i--linkedin" aria-hidden="true"></span> 890 </a> 891 </li> 892 <li> 893 <a 894 href="https://www.youtube.com/@CorcoranPremierRealty" 895 class="lp-socials__link socials__item" 896 data-wow-delay="0.3s" 897 target="_blank" 898 aria-label="YOUTUBE" 899 > 900 <span class="lp-i lp-i--youtube" aria-hidden="true"></span> 901 </a> 902 </li> 903 <li> 904 <a 905 href="https://www.tiktok.com/@corcoranpremier" 906 class="lp-socials__link socials__item" 907 data-wow-delay="0.4s" 908 target="_blank" 909 aria-label="TIKTOK" 910 > 911 <span class="lp-i lp-i--tiktok" aria-hidden="true"></span> 912 </a> 913 </li> 914 <li> 915 <a 916 href="https://www.google.com/search?q=Corcoran+Premier+Realty+Windermere%2C+FL&sca_esv=c9e7664699c3aa09&rlz=1C1KNTJ_enPH1066PH1066&ei=xBCEaLzUNNiuseMPqIrL6QU&ved=0ahUKEwi8xv_GktmOAxVYV2wGHSjFMl0Q4dUDCBA&uact=5&oq=Corcoran+Premier+Realty+Windermere%2C+FL&gs_lp=Egxnd3Mtd2l6LXNlcnAiJkNvcmNvcmFuIFByZW1pZXIgUmVhbHR5IFdpbmRlcm1lcmUsIEZMMgUQABjvBTIFEAAY7wUyCBAAGIAEGKIEMgUQABjvBTIIEAAYogQYiQVI2x5QuwFYwB1wAXgBkAEAmAFzoAHsB6oBBDEwLjK4AQPIAQD4AQGYAg2gApoIwgIKEAAYsAMY1gQYR8ICCBAhGKABGMMEwgIEECEYFcICChAhGKABGMMEGArCAgYQABgNGB6YAwCIBgGQBgiSBwQxMC4zoAehJrIHAzkuM7gHkwjCBwUxLjYuNsgHIA&sclient=gws-wiz-serp#lrd=0x88e77fa02fc53b8b:0x1c57ffe44f482a61,1,,,," 917 class="lp-socials__link socials__item" 918 data-wow-delay="0.5s" 919 target="_blank" 920 aria-label="GOOGLE" 921 > 922 <span class="lp-i lp-i--google" aria-hidden="true"></span> 923 </a> 924 </li> 925 <li> 926 <a 927 href="https://share.google/iaOB0PBakQVmptMFE" 928 class="lp-socials__link socials__item" 929 data-wow-delay="0.6s" 930 target="_blank" 931 aria-label="PODCAST" 932 > 933 <span class="lp-i lp-i--podcast" aria-hidden="true"></span> 934 </a> 935 </li> 936 </ul> 937 938 </div> 939 </div> 940 941 </div> 942 <button class="close lp-close" type="button" aria-label="close modal"> 943 <span class="lp-close-icon" aria-hidden="true"></span> 944 </button> 945 </div> 946 <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;"> 947 <style> 948 #qualifying-questions-modal .custom-select-toggle { 949 border: 1px solid #848484; 950 border-radius: 8px; 951 padding: 12px 16px; 952 } 953 954 #qualifying-questions-modal .custom-select-toggle.is-placeholder { 955 color: #848484; 956 } 957 958 #qualifying-questions-modal #qualifying-questions-modal-phoneNumber::placeholder { 959 color: #848484; 960 opacity: 1; 961 } 962 963 #qualifying-questions-modal .disclaimer-more { 964 display: none; 965 } 966 967 #qualifying-questions-modal #qualifying-questions-modal-disclaimer-text:not(.collapsed) .disclaimer-more { 968 display: inline; 969 } 970 971 #qualifying-questions-modal #qualifying-questions-modal-disclaimer-text:not(.collapsed) .disclaimer-ellipsis { 972 display: none; 973 } 974 </style>
vendor: 119 bytes, lines 974-975
974 975 <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
975<script> 976 function toggleDisclaimerQualifyingQuestionsModal() { 977 const disclaimerText = document.getElementById('qualifying-questions-modal-disclaimer-text'); 978 const toggleButton = document.getElementById('qualifying-questions-modal-toggle-disclaimer'); 979 980 if (disclaimerText.classList.contains('collapsed')) { 981 disclaimerText.classList.remove('collapsed'); 982 toggleButton.textContent = 'Read less'; 983 toggleButton.setAttribute('aria-expanded', 'true'); 984 } else { 985 disclaimerText.classList.add('collapsed'); 986 toggleButton.textContent = 'Read more'; 987 toggleButton.setAttribute('aria-expanded', 'false'); 988 } 989 } 990 </script>
990 991 <div style="max-width: 400px; width: 95%; margin: 0 auto;"> 992 <div style="background: #fff; border: none; border-radius: 16px; color: black; box-shadow: none; position: relative;"> 993 <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;"> 994 <span aria-hidden="true">×</span> 995 </button> 996 <div style="padding: 40px 30px 32px;"> 997 <div style="text-align: left; margin-bottom: 32px;"> 998 <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;"> 999 Thanks, please provide more information to help serve you 1000 </h2> 1001 </div> 1002 <form id="qualifying-questions-modal-form" data-type="contact-form"> 1003 <input type="hidden" name="source" value="PROFILE_UPDATE" /> 1004 <input type="hidden" name="email" value="" id="qualifying-questions-modal-email" /> 1005 <input type="hidden" name="triggerSource" id="qualifying-questions-modal-triggerSource" value="" /> 1006 <label for="qualifying-questions-modal-email" style="display:none;"> 1007 Email 1008 </label> 1009 <label for="qualifying-questions-modal-triggerSource" style="display:none;"> 1010 Trigger Source 1011 </label> 1012 1013 <div style="margin-bottom: 20px;"> 1014 <label for="qualifying-questions-modal-phoneNumber" style="display:none;"> 1015 Phone Number 1016 </label> 1017 <input 1018 type="tel" 1019 id="qualifying-questions-modal-phoneNumber" 1020 name="phoneNumber" 1021 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;" 1022 pattern="^\+?1?[-.\s]?\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}$" 1023 required 1024 placeholder="Phone" 1025 aria-label="Phone Number" 1026 inputmode="tel" 1027 autocomplete="tel" 1028 onfocus="this.style.borderColor='black';" 1029 onblur="this.style.borderColor='#848484';" 1030 /> 1031 </div> 1032 1033 <div style="margin-bottom: 20px;"> 1034 <label for="qualifying-questions-modal-interest" style="display:none;"> 1035 Interest 1036 </label> 1037 <select 1038 id="qualifying-questions-modal-interest" 1039 name="interest" 1040 required 1041 data-label="Interest" 1042 aria-label="Interest" 1043 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;" 1044 onfocus="this.style.borderColor='black'; this.style.color='black';" 1045 onblur="this.style.borderColor='#848484'; if(this.value === '') this.style.color='#848484'; else this.style.color='black';" 1046 > 1047 <option value="" style="background: #fff; color: #848484;" disabled selected>Interested in...</option> 1048 <option value="Selling & Buying" style="background: #fff; color: black;">Selling & Buying</option> 1049 <option value="Selling" style="background: #fff; color: black;">Selling</option> 1050 <option value="Buying" style="background: #fff; color: black;">Buying</option> 1051 <option value="Renting" style="background: #fff; color: black;">Renting</option> 1052 <option value="Other" style="background: #fff; color: black;">Other</option> 1053 </select> 1054 </div> 1055 1056 <div style="margin-bottom: 32px; font-size: 12px; line-height: 1.2;"> 1057 <label style='display: none;' for='qualifying-questions-modal-qualifying-questions-termsAccepted'>Opt In/Disclaimer Consent:</label> 1058 <label class='lp-tcr-content'>
1059 <span class='lp-tcr-checkbox'> 1060 <input 1061 type='checkbox' 1062 id='qualifying-questions-modal-qualifying-questions-termsAccepted' 1063 name='termsAccepted' 1064 aria-describedby='qualifying-questions-modal-disclaimer-text' 1065 oninvalid="this.setCustomValidity('Please accept the terms and conditions')" 1066 oninput="this.setCustomValidity('')" 1067 required 1068 /></span> 1069 <span class='lp-tcr-message'> 1070 <div id="qualifying-questions-modal-disclaimer-text" class="collapsed" style="color: #848484;"> 1071 By providing your name, signature and phone number, you consent to receiving sales calls and texts from or on behalf of The Corcoran Group at the number provided. Consent to such communications is not a condition of purchasing any property, goods, or services. Message and data rates may apply. </div> 1072 <button 1073 id="qualifying-questions-modal-toggle-disclaimer" 1074 type="button" 1075 style="background: none; border: none; color: #848484; font-size: inherit; font-weight: bold; padding: 0; margin-top: 4px; cursor: pointer;" 1076 aria-expanded="false" 1077 onclick="toggleDisclaimerQualifyingQuestionsModal()" 1078 > 1079 Read more 1080 </button> 1081 </span> 1082 </label> 1083 </div> 1084 1085 <div> 1086 <button 1087 type="submit" 1088 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;" 1089 onmouseover="this.style.background='transparent'; this.style.color='black';" 1090 onmouseout="this.style.background='black'; this.style.color='white';" 1091 > 1092 Submit 1093 </button> 1094 </div> 1095 </form> 1096 </div> 1097 </div> 1098 </div> 1099 </div> 1100 1101
1101<script> 1102 (function() { 1103 var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy")); 1104 1105 if ("IntersectionObserver" in window && lazyVideos.length > 0) { 1106 var lazyVideoObserver = new IntersectionObserver(function(entries, observer) { 1107 entries.forEach(function(video) { 1108 if (video.isIntersecting) { 1109 for (var source in video.target.children) { 1110 var videoSource = video.target.children[source]; 1111 if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") { 1112 videoSource.src = videoSource.dataset.src; 1113 } 1114 } 1115 1116 video.target.load(); 1117 video.target.classList.remove("lazy"); 1118 lazyVideoObserver.unobserve(video.target); 1119 } 1120 }); 1121 }); 1122 1123 lazyVideos.forEach(function(lazyVideo) { 1124 lazyVideoObserver.observe(lazyVideo); 1125 }); 1126 } 1127 })(); 1128 </script>
1128 1129 1130 <!-- Global site tag (gtag.js) - Google Analytics --> 1131
1131<script defer src="https://www.googletagmanager.com/gtag/js"></script>
1131 1132 1133 <!-- Google Tag Manager --> 1134
1134<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 1135 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 1136 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.defer=true;j.async=false;j.src= 1137 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 1138 })(window,document,'script','dataLayer','GTM-T9SFQGHZ');</script>
1138 1139 <!-- End Google Tag Manager --> 1140 1141 1142 <!-- LP Tracker (divolte.js) - LP Divolte --> 1143
1143<script>window.divolteLp=window.divolteLp||function(){(divolteLp.q=divolteLp.q||[]).push(arguments)}</script>
1143 1144 <!-- LP Tracker (eventBus) - LP EventBus --> 1145
1145<script>window.eventBusLp=window.eventBusLp||function(){(eventBusLp.q=eventBusLp.q||[]).push(arguments)}</script>
1145 1146 1147
1147<script> 1148 window.dataLayer = window.dataLayer || []; 1149 document.sendGoogleTagManagerEvent = function() { 1150 /* Honor GPC-enabled browsers and prevent GTM event if GPC is enabled. More details: https://global-privacy-control.glitch.me/ */ 1151 if (window.navigator.globalPrivacyControl) { 1152 return; 1153 } 1154 1155 dataLayer.push(arguments); 1156 } 1157 1158 document.sendGoogleTagManagerEvent('js', new Date()); 1159 document.sendGoogleTagManagerEvent('config', 'G-X39D0QMYDC', { page: location.pathname, location: location.href }); 1160 document.sendGoogleAnalyticsEvent = function(googleEvent) { 1161 document.sendGoogleTagManagerEvent('event', googleEvent.eventAction || googleEvent.hitType, { 1162 event_category: googleEvent.eventCategory, 1163 event_label: googleEvent.eventLabel, 1164 value: googleEvent.eventValue, 1165 page: googleEvent.page, 1166 location: googleEvent.location 1167 }) 1168 }; 1169 1170 document.addEventListener("DOMContentLoaded", function() { 1171 (function() { 1172 //If the page has an element with ID of auto-year-update the element will be populated with the current year. 1173 var date = new Date(); 1174 var elements = document.getElementsByClassName('auto-year-update'); 1175 var i; 1176 for (i = 0; i < elements.length; i++) { 1177 elements[i].innerText = date.getFullYear(); 1178 } 1179 })(); 1180 if (window.divolteLp) { 1181 window.divolteLp('sendLpPageView', {}); 1182 } 1183 if (window.eventBusLp) { 1184 window.eventBusLp('sendLpPageView', {}); 1185 } 1186 }); 1187 </script>
1187 1188 1189 1190
1190<script> 1191 // Function to dynamically load a script 1192 function loadScript(url, callback) { 1193 var script = document.createElement('script'); 1194 script.type = 'text/javascript'; 1195 script.src = url; 1196 script.defer = true; 1197 script.async = true; 1198 script.onload = callback; 1199 document.head.appendChild(script); 1200 } 1201 1202 // Function to dynamically load CSS file 1203 function loadCSS(url) { 1204 var link = document.createElement("link"); 1205 link.rel = "stylesheet"; 1206 link.href = url; 1207 document.head.appendChild(link); 1208 } 1209 1210 // Global methods / variables that can be accessed by element js 1211 window.luxuryPresence = { 1212 libs: { 1213 loadJs: loadScript, 1214 loadCss: loadCSS, 1215 jsLibsMap: { 1216 paroller: { 1217 jsSrc: 'https://d1e1jt2fj4r8r.cloudfront.net/javascript/jquery.paroller.min.js', 1218 isLoaded: false, 1219 }, 1220 ionRangeSlider: { 1221 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js', 1222 cssSrc: 'https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css', 1223 isLoaded: false, 1224 requires: ['jquery'], 1225 }, 1226 splide: { 1227 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/splidejs/4.1.4/js/splide.min.js', 1228 cssSrc: 'https://cdnjs.cloudflare.com/ajax/libs/splidejs/4.1.4/css/splide-core.min.css', 1229 isLoaded: false, 1230 }, 1231 wow: { 1232 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js', 1233 isLoaded: false, 1234 }, 1235 jquery: { 1236 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js', 1237 isLoaded: false, 1238 }, 1239 slick: { 1240 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js', 1241 isLoaded: false, 1242 requires: ['jquery'], 1243 }, 1244 libphonenumber: { 1245 jsSrc: 'https://cdnjs.cloudflare.com/ajax/libs/libphonenumber-js/1.11.8/libphonenumber-js.min.js', 1246 isLoaded: false, 1247 }, 1248 }, 1249 }, 1250 }; 1251 </script>
1251 1252
1252<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>
1252 1253
1253<script defer src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js"></script>
1253 1254
1254<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/handlebars-intl.min.js"></script>
1254 1255
1255<script defer src="https://cdnjs.cloudflare.com/ajax/libs/superagent/4.1.0/superagent.min.js"></script>
1255 1256
1256<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>
1256 1257
1257<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>
1257 1258
1258<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>
1258 1259 1260 <!-- GOOGLE TRANSLATE SCRIPT --> 1261
1261<script> 1262 function googleTranslateElementInit() { 1263 // list of languages can be overridden by setting window.customLanguages in the head JS. example `window.customLanguages = 'en,de,fr,ro,sk,pl'` 1264 // Language codes can be taken from here https://cloud.google.com/translate/docs/languages 1265 const DEFAULT_LANGUAGES = 'en,es,zh-CN,zh-TW,tl,vi,ar,ko,ru,de,fr,hi,pt'; 1266 document.querySelectorAll('[data-type="TRANSLATE"]').forEach(function(translate){ 1267 translate.innerText = ''; 1268 new google.translate.TranslateElement({ 1269 pageLanguage: 'en', 1270 layout: google.translate.TranslateElement.InlineLayout.SIMPLE, 1271 includedLanguages: window.customLanguages || DEFAULT_LANGUAGES, 1272 }, translate); 1273 }); 1274 } 1275 </script>
1275 1276
1276<script defer src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
1276 1277
1277<script defer src="https://accounts.google.com/gsi/intermediate"></script>
1277 1278 1279 <!-- GOOGLE TRANSLATE SCRIPT END--> 1280
1280<script> 1281 1282 // UI helpers 1283 (function () { 1284 1285 function getSideMenu () { 1286 return document.querySelector('body > div.sidemenu'); 1287 } 1288 1289 function sideMenuHide (instant) { 1290 var sideMenu = getSideMenu(); 1291 if (!sideMenu || !sideMenu.classList.contains('visible')) { 1292 return; 1293 } 1294 sideMenu.classList.remove('visible'); 1295 sideMenu.dispatchEvent(new CustomEvent('lpui-hide', { detail: { instant: !!instant } })); 1296 window.dispatchEvent(new CustomEvent('lpui-sidemenu-hide', { detail: {instant: !!instant} })); 1297 } 1298 1299 function sideMenuShow () { 1300 var sideMenu = getSideMenu(); 1301 if (!sideMenu || sideMenu.classList.contains('visible')) { 1302 return; 1303 } 1304 sideMenu.classList.add('visible'); 1305 sideMenu.dispatchEvent(new Event('lpui-show')); 1306 window.dispatchEvent(new Event('lpui-sidemenu-show')); 1307 } 1308 1309 function sideMenuToggle () { 1310 var sideMenu = getSideMenu(); 1311 if (!sideMenu) { 1312 return; 1313 } 1314 var isSideMenuVisible = sideMenu.classList.contains('visible'); 1315 if (isSideMenuVisible) { 1316 sideMenuHide(); 1317 } else { 1318 sideMenuShow(); 1319 } 1320 } 1321 1322 var scrollLockRequests = {}; 1323 window.__debug_scrollLockRequests = scrollLockRequests; 1324 var hideScrollStyles = ''+ 1325 'body {'+ 1326 'overflow: hidden;' + 1327 '}'; 1328 var hideScrollId = 'hide-body-scroll-style'; 1329 1330 function scrollLock () { 1331 var style = document.createElement('style'); 1332 style.id = hideScrollId; 1333 style.textContent = hideScrollStyles; 1334 document.head.appendChild(style); 1335 window.dispatchEvent(new Event('lpui-scroll-locked')); 1336 } 1337 1338 function scrollUnlock () { 1339 document.getElementById(hideScrollId)?.remove(); 1340 window.dispatchEvent(new Event('lpui-scroll-unlocked')); 1341 } 1342 1343 function requestScrollLock (lockId) { 1344 var wasLocked = Object.keys(scrollLockRequests).length > 0; 1345 scrollLockRequests[lockId || '__anonymous_lock'] = true; 1346 if (!wasLocked) { 1347 scrollLock(); 1348 } 1349 } 1350 1351 function releaseScrollLock (lockId) { 1352 if (lockId) { 1353 delete scrollLockRequests[lockId]; 1354 if (!Object.keys(scrollLockRequests).length) { 1355 scrollUnlock(); 1356 } 1357 } else { 1358 scrollLockRequests = {}; 1359 window.__debug_scrollLockRequests = scrollLockRequests; 1360 scrollUnlock(); 1361 } 1362 } 1363 1364 function showModal (modalId, options) { 1365 var modal = document.getElementById(modalId); 1366 if (!modal) { 1367 return; 1368 } 1369 1370 if (!modal.classList.contains('visible')) { 1371 modal.classList.add('visible'); 1372 if (options && options.scrollLock) { 1373 window.lpUI.requestScrollLock(modalId); 1374 } 1375 modal.dispatchEvent(new Event('lpui-show')); 1376 window.dispatchEvent(new CustomEvent('lpui-modal-show', { detail: { id: modalId } })); 1377 } 1378 1379 const visibleModals = document.querySelectorAll('.modal.visible'); 1380 1381 if (visibleModals.length > 1) { 1382 1383 const maxZIndex = Array.from(visibleModals).reduce((maxZIndex, modal) => { 1384 const zIndex = window.getComputedStyle(modal).zIndex; 1385 const parsedZIndex = zIndex !== 'auto' ? parseInt(zIndex) : 0; 1386 return Math.max(maxZIndex, parsedZIndex); 1387 }, 0); 1388 1389 modal.style.zIndex = maxZIndex + 1; 1390 } 1391 1392 } 1393 1394 function _hideModal (modalEl) { 1395 if (!modalEl) { 1396 return; 1397 } 1398 if (!modalEl.classList.contains('visible')) { 1399 return; 1400 } 1401 modalEl.classList.remove('visible'); 1402 modalEl.style.zIndex = '';
1403 modalEl.dispatchEvent(new Event('lpui-hide')); 1404 var modalId = modalEl.getAttribute('id'); 1405 if (modalId) { 1406 window.lpUI.releaseScrollLock(modalId); 1407 window.dispatchEvent(new CustomEvent('lpui-modal-hide', { detail: { id: modalId } })); 1408 } 1409 } 1410 1411 function hideModal (modalId) { 1412 _hideModal(document.getElementById(modalId)); 1413 } 1414 1415 function hideClosestModal (el) { 1416 const modal = el?.closest('.modal'); 1417 if (!modal) { 1418 return; 1419 } 1420 if (modal.classList) { 1421 _hideModal(modal); 1422 return; 1423 } 1424 if (modal.length && modal[0].classList) { 1425 _hideModal(modal[0]); 1426 } 1427 } 1428 1429 window.lpUI = { 1430 sideMenuHide: sideMenuHide, 1431 sideMenuShow: sideMenuShow, 1432 sideMenuToggle: sideMenuToggle, 1433 requestScrollLock: requestScrollLock, 1434 releaseScrollLock: releaseScrollLock, 1435 showModal: showModal, 1436 hideModal: hideModal, 1437 hideClosestModal: hideClosestModal 1438 } 1439 })(); 1440 1441 var stringifyPrimitive = function(v) { 1442 switch (typeof v) { 1443 case 'string': 1444 return v; 1445 1446 case 'boolean': 1447 return v ? 'true' : 'false'; 1448 1449 case 'number': 1450 return isFinite(v) ? v : ''; 1451 1452 default: 1453 return ''; 1454 } 1455 }; 1456 1457 function objectToQuerystring(obj, sep, eq, name) { 1458 // https://github.com/Gozala/querystring/blob/master/encode.js 1459 sep = sep || '&'; 1460 eq = eq || '='; 1461 if (obj === null) { 1462 obj = undefined; 1463 } 1464 1465 if (typeof obj === 'object') { 1466 return Object.keys(obj).map(function(k) { 1467 var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; 1468 if (Array.isArray(obj[k])) { 1469 return obj[k].map(function(v) { 1470 return ks + encodeURIComponent(stringifyPrimitive(v)); 1471 }).join(sep); 1472 } else { 1473 return ks + encodeURIComponent(stringifyPrimitive(obj[k])); 1474 } 1475 }).filter(Boolean).join(sep); 1476 1477 } 1478 1479 if (!name) return ''; 1480 return encodeURIComponent(stringifyPrimitive(name)) + eq + 1481 encodeURIComponent(stringifyPrimitive(obj)); 1482 } 1483 1484 function getPath(url, options) { 1485 var parser = document.createElement('a'); 1486 parser.href = url || ''; 1487 var path = parser.pathname || ''; 1488 if (path[0] !== '/') { 1489 // IE does not return path starting with a slash 1490 path = '/' + path; 1491 } 1492 1493 if (options && options.queryString) { 1494 path += parser.search; 1495 } 1496 1497 return path; 1498 } 1499 1500 function getMLSAutocomplete(keyword) { 1501 var searchURL = window.location.protocol + '//' + window.location.hostname + '/home-search/auto_complete'; 1502 var query = { 1503 kind: 'listings', 1504 query: keyword 1505 }; 1506 1507 return superagent 1508 .get(searchURL) 1509 .query(query) 1510 .then(function(res) { 1511 var data = res.body || []; 1512 /* 1513 Of the format: 1514 [{ 1515 "_index": "listing_auto_completes_production_20190723232720775", 1516 "_type": "listing_auto_complete", 1517 "_id": "235875624", 1518 "_score": 0, 1519 "status_modified_at": 1553250708, 1520 "city": "Jupiter", 1521 "price": 1335743, 1522 "display_address": "10088 Calabrese Trail Unit: 9 Jupiter FL 33478", 1523 "sold_price": null, 1524 "id": 235875624, 1525 "state": "FL", 1526 "photo_urls": [ 1527 "http://cdn.photos.sparkplatform.com/fl/20190322153144208228000000-o.jpg" 1528 ], 1529 "status": "Pending" 1530 }, ...] 1531 */ 1532 1533 return data; 1534 }); 1535 } 1536 1537 function getMLSAutocompleteWithFilters(keyword, filters = {}) { 1538 var searchURL = window.location.protocol + '//' + window.location.hostname + '/home-search/auto_complete'; 1539 1540 return superagent 1541 .get(searchURL) 1542 .query({ kind: 'listings', query: keyword, ...filters }) 1543 .then(function(res) { 1544 /* 1545 Of the format: 1546 [{ 1547 "_index": "listing_auto_completes_production_20190723232720775", 1548 "_type": "listing_auto_complete", 1549 "_id": "235875624", 1550 "_score": 0, 1551 "status_modified_at": 1553250708, 1552 "city": "Jupiter", 1553 "price": 1335743, 1554 "display_address": "10088 Calabrese Trail Unit: 9 Jupiter FL 33478", 1555 "sold_price": null, 1556 "id": 235875624, 1557 "state": "FL", 1558 "photo_urls": [ 1559 "http://cdn.photos.sparkplatform.com/fl/20190322153144208228000000-o.jpg" 1560 ], 1561 "status": "Pending" 1562 }, ...] 1563 */ 1564 return res.body || []; 1565 }); 1566 } 1567 1568 function makeMlsLink(data) { 1569 // Code Dupe from utils/googlePlace 1570 // mapping of google data type to mls data type 1571 var mapping = { 1572 neighborhood: 'neighborhood', 1573 locality: 'place', 1574 administrative_area_level_2: 'county', 1575 administrative_area_level_1: 'state', 1576 postal_code: 'postalcode', 1577 }; 1578 1579 function _filterTypes(types) { 1580 return types.filter(function(type) { return type !== 'political' }); 1581 } 1582 1583 if (!data || !Object.keys(data).length) { 1584 return '/home-search/listings'; 1585 } 1586 1587 var newData = {};
1588 _filterTypes(data.types).forEach(function(type) { 1589 if (mapping[type]) { 1590 newData.search_type = mapping[type]; 1591 } 1592 }); 1593 newData.omnibox = data.formatted_address; 1594 data.address_components.forEach(function(component) { 1595 _filterTypes(component.types).forEach(function(type) { 1596 if (mapping[type]) { 1597 newData[mapping[type]] = component.long_name; 1598 } 1599 }); 1600 }); 1601 var bounds = data.geometry.bounds; 1602 var convertedData = Object.assign(bounds, newData); 1603 1604 return '/home-search/listings?' + objectToQuerystring(convertedData); 1605 } 1606 1607 function debounce(func, wait) { 1608 let timeout; 1609 return function(...args) { 1610 const context = this; 1611 clearTimeout(timeout); 1612 timeout = setTimeout(() => func.apply(context, args), wait) 1613 } 1614 } 1615 1616 // Global methods / variables that can be accessed by element js 1617 window.luxuryPresence = { 1618 ...window.luxuryPresence, 1619 defaults: { 1620 companyId: 'c192c24d-68d5-41fb-b04a-e3c9703e46be', 1621 apiGatewayUrl: '/api-gw', 1622 routerUrl: '/api-nv', 1623 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\
1623n }\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 ) {\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 ) {\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 ) {\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-
1623abb7-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
1623onId,\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}"}, 1624 propertyPlaceholderImage: {"id":"980f9748-b419-40b4-be3e-2a31f882cfbb","alt":null,"bytes":30056,"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/5392e1e4-98d9-4eb3-a08e-755ba0a4506e","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/5392e1e4-98d9-4eb3-a08e-755ba0a4506e","authorUrl":null,"createdAt":"2025-07-25T23:54:13.089Z","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/5392e1e4-98d9-4eb3-a08e-755ba0a4506e","sourceUrl":null,"updatedAt":"2025-07-25T23:54:13.089Z","xLargeUrl":"https://media-production.lp-cdn.com/cdn-cgi/image/format=auto,quality=85/https://media-production.lp-cdn.com/media/5392e1e4-98d9-4eb3-a08e-755ba0a4506e","__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/5392e1e4-98d9-4eb3-a08e-755ba0a4506e","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/5392e1e4-98d9-4eb3-a08e-755ba0a4506e","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/5392e1e4-98d9-4eb3-a08e-755ba0a4506e","originalFileName":"Property-placeholder","cloudinaryPublicId":"5392e1e4-98d9-4eb3-a08e-755ba0a4506e"} 1625 }, 1626 objectToQuerystring: objectToQuerystring, 1627 getPath: getPath, 1628 getMLSAutocomplete: getMLSAutocomplete, 1629 getMLSAutocompleteWithFilters: getMLSAutocompleteWithFilters, 1630 makeMlsLink: makeMlsLink, 1631 debounce: debounce, 1632 }; 1633 1634 var wowOffset = 100; 1635 </script>
1635 1636
1636<script> 1637 (() => { 1638 1639function $parcel$interopDefault(a) { 1640 return a && a.__esModule ? a.default : a; 1641} 1642// Entry point for lp-sdk bundle 1643// This file exists to ensure Parcel v2 outputs the correct filename 1644/* global window */ var $53de3c160faf5a81$exports = {}; 1645/* 1646WARNING!!! This file is used both on the server and in client's web-browser 1647please don't require/import any server-side related config/functions here 1648If we need something, let's pass it as a parameter of the factory 1649*/ var $0ce6edea77f7b81a$exports = {}; 1650$0ce6edea77f7b81a$exports = { 1651 getVideoFirstFrame (videoUrl) { 1652 // 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> 1653 // https://cloudinary.com/documentation/video_manipulation_and_delivery#transformation_url_structure 1654 // The problem is that <transformations> and <version> are optional, and <transformations> can be chained separated by '/' 1655 // One more issue to be handled https://cloudinary.com/documentation/advanced_url_delivery_options#seo_friendly_media_asset_urls 1656 const CLOUDINARY_URL = 'https://res.cloudinary.com/'; 1657 const invalid = !videoUrl || !videoUrl.startsWith(CLOUDINARY_URL); 1658 if (invalid) return null; 1659 const urlComponents = videoUrl.replace(CLOUDINARY_URL, '').replace('f_auto:video', 'f_auto').split('/'); 1660 // checking if <asset_type> is not video or videos 1661 if (urlComponents[1].toLowerCase().indexOf('video') === -1) return null; 1662 // Filename is last urlComponent <public_id>.<extension> 1663 let filename = urlComponents[urlComponents.length - 1]; 1664 if (filename.lastIndexOf('.') > -1) filename = `${filename.slice(0, filename.lastIndexOf('.'))}.jpg`; 1665 else filename += '.jpg'; 1666 urlComponents[urlComponents.length - 1] = filename; 1667 // We need to add so_0,eo_0 transformation to the url to target the first frame. 1668 // we want to find the position at which we want to insert it as a chained transformation 1669 const firstFrameTransformation = 'so_0,eo_0'; 1670 let firstFrameTransformationPosition = 3; 1671 // checking cases for SEO-friendly URLs 1672 if (urlComponents[1].toLowerCase() === 'videos' && urlComponents[2] !== '') firstFrameTransformationPosition = 2; 1673 // checking the last transformation position in the url 1674 // https://cloudinary.com/documentation/transformation_reference 1675 // https://regex101.com/r/lE3W6u/1 1676 const transformationRegex = /^(?:[a-z]{1,3}|\$\w+)_\S+$/; 1677 while(firstFrameTransformationPosition < urlComponents.length - 1 && transformationRegex.test(urlComponents[firstFrameTransformationPosition]))firstFrameTransformationPosition++; 1678 urlComponents.splice(firstFrameTransformationPosition, 0, firstFrameTransformation); 1679 return CLOUDINARY_URL + urlComponents.join('/'); 1680 } 1681}; 1682 1683 1684/** 1685 * Create helpers with given Handlebars instance 1686 * 1687 * @param {Object} HandlebarsInstance 1688 * @param {Function} isEqual - we use different implementation if isEqual on server and on client 1689 * @return {Object} 1690 */ function $53de3c160faf5a81$var$handlebarsHelpersFactory(HandlebarsInstance, { isEqual: isEqual }) { 1691 // notice!: code below assumes list is ordered lowest to highest width 1692 const MEDIA_SIZES = [ 1693 { 1694 field: 'thumbnailUrl', 1695 w: 320 1696 }, 1697 { 1698 field: 'smallUrl', 1699 w: 960 1700 }, 1701 { 1702 field: 'mediumUrl', 1703 w: 1280 1704 }, 1705 { 1706 field: 'largeUrl', 1707 w: 1920 1708 }, 1709 { 1710 field: 'xLargeUrl', 1711 w: 2560 1712 }, 1713 { 1714 field: 'xxLargeUrl', 1715 w: 3456 1716 } 1717 ]; 1718 const MEDIA_SIZE_FOR_SRC = 1280; 1719 const lpFormatNumber = function(number, unit, precision) { 1720 const localization = 'en-US'; 1721 if (!number) return ''; 1722 if (typeof number === 'string') { 1723 const trimmed = number.trim(); 1724 if (/[^+\-0-9.]/.test(trimmed)) return number; // returning text 'as is' assuming it already has all formatting 1725 // eslint-disable-next-line 1726 number = parseFloat(trimmed); 1727 if (!number) return ''; 1728 } 1729 const currencyPrecision = typeof precision === 'number' ? precision : 0; 1730 const currencyFractionDigits = Number.isInteger(number) ? 0 : currencyPrecision; 1731 const currencyFractionOptions = { 1732 minimumFractionDigits: currencyFractionDigits, 1733 maximumFractionDigits: currencyFractionDigits 1734 };
1735 if (unit === 'USD') return `$${number.toLocaleString(localization, currencyFractionOptions)}`; 1736 if (unit === 'CAD') return `$${number.toLocaleString(localization, currencyFractionOptions)} CAD`; 1737 if (unit === 'EUR') return `\u{20AC}${number.toLocaleString(localization, currencyFractionOptions)}`; 1738 if (unit === 'GBP') return `\xa3${number.toLocaleString(localization, currencyFractionOptions)}`; 1739 if (unit === 'PERCENT') return `${number}%`; 1740 if (typeof precision === 'number' && precision > -1) return number.toLocaleString(localization, { 1741 maximumFractionDigits: precision 1742 }); 1743 return number.toLocaleString(localization); 1744 }; 1745 const formatFrequency = function(freqUnit) { 1746 switch(freqUnit){ 1747 case 'DAY': 1748 return 'daily'; 1749 case 'MONTH': 1750 return 'monthly'; 1751 case 'WEEK': 1752 return 'weekly'; 1753 case 'YEAR': 1754 return 'yearly'; 1755 case 'QUARTER': 1756 return 'quarterly'; 1757 case 'HALF_YEAR': 1758 return 'semi-annually'; 1759 case 'NIGHTLY': 1760 return 'nightly'; 1761 case 'SEASONAL': 1762 return 'seasonally'; 1763 default: 1764 return ''; 1765 } 1766 }; 1767 const formatFrequencyShort = function(freqUnit) { 1768 switch(freqUnit){ 1769 case 'DAY': 1770 return 'day'; 1771 case 'WEEK': 1772 return 'wk'; 1773 case 'MONTH': 1774 return 'mo'; 1775 case 'YEAR': 1776 return 'yr'; 1777 case 'QUARTER': 1778 return '3 mos'; 1779 case 'HALF_YEAR': 1780 return '6 mos'; 1781 case 'NIGHTLY': 1782 return 'night'; 1783 case 'SEASONAL': 1784 return 'season'; 1785 default: 1786 return ''; 1787 } 1788 }; 1789 const formatFrequencyStd = function(freqUnit) { 1790 switch(freqUnit){ 1791 case 'DAY': 1792 return 'day'; 1793 case 'WEEK': 1794 return 'week'; 1795 case 'MONTH': 1796 return 'month'; 1797 case 'YEAR': 1798 return 'year'; 1799 case 'QUARTER': 1800 return 'quarter'; 1801 case 'HALF_YEAR': 1802 return '6 months'; 1803 case 'NIGHTLY': 1804 return 'night'; 1805 case 'SEASONAL': 1806 return 'season'; 1807 default: 1808 return ''; 1809 } 1810 }; 1811 const formatFrequencyExt = function(unit, options) { 1812 let val; 1813 let separator; 1814 const opts = options || {}; 1815 switch(opts.mode){ 1816 case 'short': 1817 val = formatFrequencyShort(unit); 1818 separator = opts.frequencySeparator || '/'; 1819 break; 1820 case 'standard': 1821 case 'std': 1822 val = formatFrequencyStd(unit); 1823 separator = opts.frequencySeparator || '/'; 1824 break; 1825 case 'long': 1826 default: 1827 val = formatFrequency(unit); 1828 separator = opts.frequencySeparator || ' '; 1829 } 1830 if (!val) return ''; 1831 if (!opts.frequencyTag && !opts.frequencyClass) return separator + val; 1832 return `${separator}<${opts.frequencyTag || 'span'}${opts.frequencyClass ? ` class="${opts.frequencyClass}"` : ''}>${val}</${opts.frequencyTag || 'span'}>`; 1833 }; 1834 return { 1835 isEmpty (arg1, options) { 1836 const result = !arg1 || (typeof arg1 === 'string' ? !arg1.trim() : false) || !Object.keys(arg1).length; 1837 if (options.fn) return result ? options.fn(this) : options.inverse(this); 1838 return result; 1839 }, 1840 ifEquals (arg1, arg2, options) { 1841 return isEqual(arg1, arg2) ? options.fn(this) : options.inverse(this); 1842 }, 1843 'raw-helper': function(options) { 1844 return options.fn(); 1845 }, 1846 striptags (txt) { 1847 if (!txt) return ''; 1848 // Remove HTML Comments (escaping something to not make real html comment by expression) 1849 // eslint-disable-next-line no-useless-escape,no-param-reassign 1850 txt = txt.replace(/<\!--(.|[\r\n])*?-\->/g, ''); 1851 // Remove XML fragments and <style> and <svg> tags with content 1852 // eslint-disable-next-line 1853 txt = txt.replace(/<(xml|style|svg)("[^"]*"|'[^']*'|[^>])*>(.|[\r\n])*?<\/\1>/gi, ''); 1854 // Replace with space 1855 // eslint-disable-next-line no-param-reassign 1856 txt = txt.replace(/ /g, ' '); 1857 // Remove HTML Tags 1858 const regexp = /<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g; 1859 return txt.replace(regexp, ''); 1860 },
1861 striptagsLineBreaks (txt) { 1862 if (!txt) return ''; 1863 // Remove HTML Comments (escaping something to not make real html comment by expression) 1864 // eslint-disable-next-line no-useless-escape,no-param-reassign 1865 txt = txt.replace(/<\!--(.|[\r\n])*?-\->/g, ''); 1866 // Remove XML fragments and <style> and <svg> tags with content 1867 // eslint-disable-next-line no-param-reassign 1868 txt = txt.replace(/<(xml|style|svg)("[^"]*"|'[^']*'|[^>])*>(.|[\r\n])*?<\/\1>/gi, ''); 1869 // Replace <br> and </p> tags with line break char, skipping last </p> which is not followed by <br> or </p> 1870 // eslint-disable-next-line no-param-reassign 1871 txt = txt.replace(/(<br\s*\/?>)|(<\/p\s*>)(?=.*(<\/p\s*>|<br\s*\/?>))/g, ' '); 1872 // Replace with space 1873 // eslint-disable-next-line no-param-reassign 1874 txt = txt.replace(/ /g, ' '); 1875 // Remove HTML Tags 1876 const regexp = /<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g; 1877 return txt.replace(regexp, ''); 1878 }, 1879 truncate (text, limit, suffix) { 1880 if (!text) return ''; 1881 if (text.length > limit) return typeof suffix === 'string' ? text.slice(0, limit - suffix.length) + suffix : text.slice(0, limit); 1882 return text; 1883 }, 1884 // eslint-disable-next-line 1885 setSubArray (items = [], start, end, subArrayName, options) { 1886 // eslint-disable-next-line 1887 options.data.root[subArrayName] = items.slice(start, end); 1888 }, 1889 formatAreaUnit (areaUnit) { 1890 switch(areaUnit){ 1891 case 'ACRE': 1892 return 'Acres'; 1893 case 'SQUARE_METER': 1894 return 'Sq.M.'; 1895 case 'SQUARE_YARD': 1896 return 'Sq.Yd.'; 1897 default: 1898 return 'Sq.Ft.'; 1899 } 1900 }, 1901 formatFrequency: formatFrequency, 1902 formatFrequencyShort: formatFrequencyShort, 1903 lpFormatFrequency (freqUnit, options) { 1904 return formatFrequencyExt(freqUnit, options && options.hash); 1905 }, 1906 subArray (index, start, end, options) { 1907 return index >= start && index < end ? options.fn(this) : options.inverse(this); 1908 }, 1909 formatPropertyStatus (status, showSoldDate, date) { 1910 let formattedStatus = ''; 1911 switch(status){ 1912 case 'SOLD': 1913 formattedStatus = 'Sold'; 1914 break; 1915 case 'FOR_SALE': 1916 formattedStatus = 'For Sale'; 1917 break; 1918 case 'COMING_SOON': 1919 formattedStatus = 'Coming Soon'; 1920 break; 1921 case 'INACTIVE': 1922 formattedStatus = 'Inactive'; 1923 break; 1924 case 'POCKET_LISTING': 1925 formattedStatus = 'Pocket Listing'; 1926 break; 1927 case 'PENDING': 1928 formattedStatus = 'Pending'; 1929 break; 1930 case 'UNDER_CONTRACT': 1931 formattedStatus = 'Under Contract'; 1932 break; 1933 case 'ACTIVE_UNDER_CONTRACT': 1934 formattedStatus = 'Active Under Contract'; 1935 break; 1936 default: 1937 formattedStatus = status; 1938 } 1939 // `typeof date === 'string'` matters: when called as 1940 // `{{formatPropertyStatus status}}` Handlebars passes its options object 1941 // as `showSoldDate`/`date`, and this guard keeps the legacy output. 1942 if ((formattedStatus === 'Sold' || formattedStatus === 'Leased') && showSoldDate && typeof date === 'string' && date) formattedStatus += ` on ${date}`; 1943 return formattedStatus; 1944 }, 1945 formatGrade (gradeValue) { 1946 switch(gradeValue){ 1947 case 'UNDERGRADUATE_COURSES': 1948 return 'Undergrad'; 1949 case 'PRE_KINDERGARTEN': 1950 return 'PreK'; 1951 case 'KINDERGARTEN': 1952 return 'K'; 1953 case 'FIRST_GRADE': 1954 return '1st'; 1955 case 'SECOND_GRADE': 1956 return '2nd'; 1957 case 'THIRD_GRADE': 1958 return '3rd'; 1959 case 'FOURTH_GRADE': 1960 return '4th'; 1961 case 'FIFTH_GRADE': 1962 return '5th'; 1963 case 'SIXTH_GRADE': 1964 return '6th'; 1965 case 'SEVENTH_GRADE': 1966 return '7th'; 1967 case 'EIGHTH_GRADE': 1968 return '8th'; 1969 case 'NINTH_GRADE': 1970 return '9th'; 1971 case 'TENTH_GRADE': 1972 return '10th'; 1973 case 'ELEVENTH_GRADE': 1974 return '11th'; 1975 case 'TWELFTH_GRADE': 1976 return '12th'; 1977 default: 1978 return ''; 1979 } 1980 }, 1981 encodeURI (uri) { 1982 return encodeURI(uri); 1983 }, 1984 encodeURIComponent (txt) { 1985 return encodeURIComponent(txt); 1986 }, 1987 hbFormatDate (date, type) { 1988 if (!date) return ''; 1989 const newDate = date === 'current' ? new Date() : new Date(date); 1990 if (Number.isNaN(newDate.getTime())) return ''; 1991 const months = [ 1992 'January', 1993 'February', 1994 'March', 1995 'April', 1996 'May', 1997 'June', 1998 'July', 1999 'August', 2000 'September', 2001 'October',
2002 'November', 2003 'December' 2004 ]; 2005 if (type === 'YYYY' || type === 'year') return `${newDate.getFullYear()}`; 2006 if (type === 'MM/DD/YY') { 2007 let month = newDate.getMonth() + 1; 2008 if (month < 10) month = `0${month.toString()}`; 2009 return `${month}/${newDate.getDate()}/${newDate.getFullYear().toString().substr(-2)}`; 2010 } 2011 return `${months[newDate.getMonth()]} ${newDate.getDate()}, ${newDate.getFullYear()}`; 2012 }, 2013 openHousesFormat (startDate, endDate, timeZone) { 2014 if (!startDate || !endDate) return ''; 2015 /** 2016 * return formatted time. 2017 * @param {date} date 2018 * @return {time} time. 2019 */ const getTime = (date)=>{ 2020 let hours = date.getHours(); 2021 if (hours > 12) hours -= 12; 2022 const prefix = '0'; 2023 let time = `${hours}:${date.getMinutes() > 9 ? date.getMinutes() : prefix + date.getMinutes()}`; 2024 if (date.getHours() > 11) time += 'PM'; 2025 else time += 'AM'; 2026 return time; 2027 }; 2028 let tz = ''; 2029 let startFDate = startDate; 2030 let endFDate = endDate; 2031 if (timeZone) { 2032 startFDate = new Date(startDate).toLocaleString('en-US', { 2033 timeZone: timeZone 2034 }); 2035 endFDate = new Date(endDate).toLocaleString('en-US', { 2036 timeZone: timeZone 2037 }); 2038 [, , , tz] = new Date(endDate).toLocaleString('en-US', { 2039 timeZone: timeZone, 2040 timeZoneName: 'short' 2041 }).split(' '); 2042 } 2043 const date = new Date(startFDate); 2044 const openHouseDate = date.toLocaleDateString('en-US'); 2045 const time1 = getTime(date); 2046 const date2 = new Date(endFDate); 2047 const time2 = getTime(date2); 2048 return `${openHouseDate} ${time1} - ${time2} ${tz}`; 2049 }, 2050 math (lvalue, operator, rvalue) { 2051 // eslint-disable-next-line 2052 lvalue = parseFloat(lvalue); 2053 // eslint-disable-next-line 2054 rvalue = parseFloat(rvalue); 2055 return ({ 2056 '+': lvalue + rvalue, 2057 '-': lvalue - rvalue, 2058 '*': lvalue * rvalue, 2059 '/': lvalue / rvalue, 2060 '%': lvalue % rvalue 2061 })[operator]; 2062 }, 2063 findByKey (values, key, value, options) { 2064 const result = (values || []).find((entry)=>entry[key] === value); 2065 return options.fn(result); 2066 }, 2067 capitalize (string, split, options) { 2068 let capitalized; 2069 if (typeof string === 'string' && string.length) capitalized = string.toLowerCase().split(split).map((w)=>w.charAt(0).toUpperCase() + w.slice(1)).join(' ').toString(); 2070 return capitalized; 2071 }, 2072 and (...arg) { 2073 return Array.prototype.slice.call(arg).every(Boolean); 2074 }, 2075 or (...arg) { 2076 return Array.prototype.slice.call(arg, 0, -1).some(Boolean); 2077 }, 2078 not (arg) { 2079 return !arg; 2080 }, 2081 orderByIds (items, orderedIds, options) { 2082 let ret = ''; 2083 let data = null; 2084 if (options.data) data = HandlebarsInstance.createFrame(options.data); 2085 // When passed orderedIds, filter out empty items including empty strings and 2086 // only show items (and in that order) in a loop 2087 // If no orderedIds provided, show all items 2088 const filteredIds = (orderedIds || []).filter(Boolean); 2089 if (filteredIds && filteredIds.length) { 2090 let skippedItems = 0; 2091 ret = filteredIds.reduce((res, id, idx)=>{ 2092 const item = (items || []).find((item)=>item.id === id); 2093 // ID doesn't exist so ditch it 2094 if (!item) { 2095 skippedItems += 1; 2096 return res; 2097 } 2098 if (data) data.index = idx - skippedItems; 2099 return res + options.fn(item, { 2100 data: data 2101 }); 2102 }, ''); 2103 } else for(let i = 0, j = (items || []).length; i < j; i++){ 2104 if (data) data.index = i; 2105 ret += options.fn(items[i], { 2106 data: data 2107 }); 2108 } 2109 return ret; 2110 }, 2111 ifIn (elem, list, options) { 2112 if (list && list.indexOf(elem) > -1) return options.fn(this); 2113 return options.inverse(this); 2114 }, 2115 partial (name, options) { 2116 // Register a partial and output the content in a script for clientside rendering 2117 HandlebarsInstance.registerPartial(name, HandlebarsInstance.compile(options.fn())); 2118 // eslint-disable-next-line 2119 const script = `
2119<script type="text/x-handlebars-template" class="${name} pagination-script">${options.fn()}</${'script'}>`; 2120 return script; 2121 }, 2122 numCompare (l, r, operator, options) { 2123 const operators = { 2124 '==': function(l, r) { 2125 // eslint-disable-next-line 2126 return l == r; 2127 }, 2128 '===': function(l, r) { 2129 return l === r; 2130 }, 2131 '!=': function(l, r) { 2132 // eslint-disable-next-line 2133 return l != r; 2134 }, 2135 '<': function(l, r) { 2136 return l < r; 2137 }, 2138 '>': function(l, r) { 2139 return l > r; 2140 }, 2141 '<=': function(l, r) { 2142 return l <= r; 2143 }, 2144 '>=': function(l, r) { 2145 return l >= r; 2146 } 2147 }; 2148 const result = operators[operator](l, r); 2149 if (result) return options.fn ? options.fn(this) : true; 2150 return options.fn ? options.inverse(this) : false; 2151 }, 2152 lpFormatNumber: lpFormatNumber, 2153 arrayToHtmlList (arr, options) { 2154 // eslint-disable-next-line 2155 return arr.reduce((acc, current)=>{ 2156 try { 2157 if (typeof current === 'object' || current === null) return acc; 2158 // eslint-disable-next-line 2159 return acc += `<li>${current}</li>`; 2160 } catch (e) { 2161 /* empty */ } 2162 }, ''); 2163 }, 2164 join (array, separator, options) { 2165 if (!array || !array.join) return ''; 2166 return array.join(typeof separator === 'string' ? separator : ', '); 2167 }, 2168 dedupe (items, key, options) { 2169 let data = null; 2170 let skippedItems = 0; 2171 const list = new Set(); 2172 if (options.data) data = HandlebarsInstance.createFrame(options.data); 2173 return (items || []).reduce((res, item, idx)=>{ 2174 const val = key ? item[key] : item; 2175 // Item is unique if we're passed a key that is not defined 2176 const isUnique = !list.has(val) || key && val === undefined; 2177 if (isUnique) list.add(val); 2178 else { 2179 skippedItems += 1; 2180 return res; 2181 } 2182 if (data) data.index = idx - skippedItems; 2183 return res + options.fn(item, { 2184 data: data 2185 }); 2186 }, ''); 2187 }, 2188 JSONstringify (obj, options) { 2189 return JSON.stringify(obj); 2190 }, 2191 // eslint-disable-next-line sonarjs/cognitive-complexity 2192 formatPropertyPrice (...args) { 2193 const options = args[args.length - 1]; 2194 const opts = options.hash; 2195 const property = args.length > 1 ? args[0] : opts.property; 2196 const precision = opts.precision || 0; 2197 if (args.length > 2) // eslint-disable-next-line 2198 opts.mode = args[1]; 2199 if (!opts.mode) opts.mode = 'short'; 2200 let separator = args.length > 3 ? args[2] : opts.separator; 2201 if (typeof separator !== 'string') separator = ' | '; 2202 if (property.isPasswordProtected) return 'Exclusive Listing'; 2203 let priceUponRequestText = args.length > 4 ? args[3] : opts.priceUponRequestText; 2204 if (typeof priceUponRequestText !== 'string') priceUponRequestText = 'Price Upon Request'; 2205 if (property.priceUponRequest) return priceUponRequestText; 2206 let price = property.salesPrice; 2207 let reduced = null; 2208 // eslint-disable-next-line sonarjs/no-collapsible-if 2209 if (property.status !== 'SOLD' && property.status !== 'Leased') { 2210 if (property.reducedPrice) { 2211 if (!opts.reducedClass) price = property.reducedPrice; 2212 else reduced = property.reducedPrice; 2213 } 2214 } 2215 let result = ''; 2216 if (reduced) result += `<${opts.reducedTag || 'span'} class="${opts.reducedClass}">${lpFormatNumber(reduced, property.currency, precision)}</${opts.reducedTag || 'span'}>`; 2217 if (price) { 2218 price = lpFormatNumber(price, property.currency, precision); 2219 if (opts.priceTag || opts.priceClass) result += `<${opts.priceTag || 'span'}${opts.priceClass ? ` class="${opts.priceClass}"` : ''}>${price}</${opts.priceTag || 'span'}>`; 2220 else result += price; 2221 } 2222 const leasePrice = property.leasePrice && lpFormatNumber(property.leasePrice, property.currency, precision); 2223 if (leasePrice) { 2224 if (result) result += separator; 2225 const leaseText = `${leasePrice}${formatFrequencyExt(property.leasePeriod, opts)}`; 2226 if (opts.leaseTag || opts.leaseClass) result += `<${opts.leaseTag || 'span'}${opts.leaseClass ? ` class="${opts.leaseClass}"` : ''}>${leaseText}</${opts.leaseTag || 'span'}>`; 2227 else result += leaseText; 2228 } 2229 return new HandlebarsInstance.SafeString(result); 2230 }, 2231 // eslint-disable-next-line sonarjs/cognitive-complexity 2232 mediaImage (mediaSource, options = {}) { 2233 if (!mediaSource) return; 2234 const { lazy: lazy, ...attributes } = options.hash; 2235 let src = ''; 2236 let srcset = ''; 2237 if (typeof mediaSource === 'string') src = mediaSource; 2238 else { 2239 const srcMap = {}; 2240 const { height: height, width: width, altTagText: altTagText } = mediaSource; 2241 MEDIA_SIZES.forEach((src)=>{ 2242 if (mediaSource[src.field] && !srcMap[mediaSource[src.field]]) srcMap[mediaSource[src.field]] = src.w; 2243 }); 2244 const srcs = Object.keys(srcMap); 2245 if (!srcs.length) return; 2246 if (altTagText) attributes.alt = altTagText; 2247 if (height && width) { 2248 if (height >= width) { 2249 if (attributes.class) attributes.class += ' portrait'; 2250 else attributes.class = 'portrait'; 2251 } 2252 if ('setDims' in options.hash) { 2253 attributes.width = width; 2254 attributes.height = height; 2255 } 2256 } 2257 if (srcs.length > 1 && width && width < srcMap[srcs[srcs.length - 1]]) { 2258 const maxSrc = srcs.findIndex((src)=>
2258srcMap[src] >= width); 2259 srcs.splice(maxSrc + 1); 2260 srcMap[srcs[srcs.length - 1]] = width; 2261 } 2262 if (srcs.length > 1) { 2263 srcset = srcs.map((s)=>`${s} ${srcMap[s]}w`).join(', '); 2264 srcs.sort((a, b)=>Math.abs(srcMap[a] - MEDIA_SIZE_FOR_SRC) - Math.abs(srcMap[b] - MEDIA_SIZE_FOR_SRC)); 2265 } 2266 // eslint-disable-next-line 2267 src = srcs[0]; 2268 } 2269 delete attributes.setDims; 2270 if (!srcset) delete attributes.sizes; 2271 if (!('alt' in attributes)) attributes.alt = ''; 2272 if (!('loading' in attributes) && (options?.data?.root?.sectionIndex > 1 || lazy)) attributes.loading = 'lazy'; 2273 const attrs = Object.keys(attributes).map((k)=>`${HandlebarsInstance.escapeExpression(k)}="${HandlebarsInstance.escapeExpression(attributes[k])}"`).join(' '); 2274 return new HandlebarsInstance.SafeString(// eslint-disable-next-line sonarjs/no-nested-template-literals 2275 `<img src="${src}"${srcset ? ` srcset="${srcset}"` : ''}${attrs ? ` ${attrs}` : ''}>`); 2276 }, 2277 bgImage (mediaSource) { 2278 if (!mediaSource) return ''; 2279 if (typeof mediaSource === 'string') return mediaSource; 2280 return mediaSource.largeUrl || mediaSource.url || ''; 2281 }, 2282 concat (...rest) { 2283 let outStr = ''; 2284 // rest params are Array instances while arguments object is not 2285 for(const arg in rest)if (rest[arg] !== null && rest[arg] !== undefined && typeof rest[arg] !== 'object') outStr += rest[arg]; 2286 return outStr; 2287 }, 2288 setVideoExtension (uri, format) { 2289 if (!uri || !format) return ''; 2290 const decodedUri = new URL(uri); 2291 if (decodedUri.host !== 'res.cloudinary.com') { 2292 // Not a cloudinary uri, do not rewrite 2293 if (decodedUri.pathname.endsWith(`.${format}`)) return uri; 2294 return ''; 2295 } 2296 // Rewrite the cloudinary uri 2297 const lastPeriodIdx = decodedUri.pathname.lastIndexOf('.'); 2298 let pathWithoutFormat = decodedUri.pathname; 2299 if (lastPeriodIdx !== -1) pathWithoutFormat = decodedUri.pathname.substr(0, lastPeriodIdx); 2300 decodedUri.pathname = `${pathWithoutFormat}.${format}`; 2301 return decodedUri.toString(); 2302 }, 2303 addVideoSources (uri) { 2304 if (!uri) return ''; 2305 const VIDEO_VARIANTS = [ 2306 { 2307 format: 'webm', 2308 codec: 'vp9', 2309 htmlCodecs: ';codecs=vp9' 2310 }, 2311 { 2312 format: 'mp4', 2313 codec: 'h265', 2314 htmlCodecs: ';codecs=hvc1' 2315 }, 2316 { 2317 format: 'mp4', 2318 codec: 'h264', 2319 htmlCodecs: '' 2320 } 2321 ]; 2322 const VIDEO_EXT_REGEXP = /\.(?:3gp|mpeg|mp4|m4v|m4p|ogv|ogg|mov|webm)$/; 2323 if (!uri.includes('res.cloudinary.com')) // keep existing or no extension for non Cloudinary urls 2324 return `<source data-src="${uri}">`; 2325 // Cap delivery at 1080p (1920px wide) while preserving aspect ratio. Width-only: 2326 // c_limit never upscales, so portrait sources are left at their native size. 2327 // No q_auto: quality is left to Cloudinary's default rather than forced down. 2328 // Note the regex below consumes any q_auto in the source URL, so it is dropped 2329 // rather than carried through. 2330 const CONSTRAINED_DELIVERY = 'w_1920,c_limit'; 2331 const uriNoExt = uri.replace(VIDEO_EXT_REGEXP, ''); 2332 const sources = VIDEO_VARIANTS.map((type)=>{ 2333 const cloudinaryFormatUrl = `${uriNoExt.replace(/f_auto(?::video)?(?:,q_auto(?::\w+)?)?/, `f_${type.format},vc_${type.codec},${CONSTRAINED_DELIVERY}`)}.${type.format}`; 2334 return `<source data-src="${cloudinaryFormatUrl}" type="video/${type.format}${type.htmlCodecs}">`; 2335 }); 2336 return sources.join('\n'); 2337 }, 2338 cloudinaryVideoFirstFrame: $0ce6edea77f7b81a$exports.getVideoFirstFrame, 2339 initials (text, options) { 2340 if (!text) return ''; 2341 if (options?.hash?.endChar) // eslint-disable-next-line 2342 text = text.split(options.hash.endChar)[0]; 2343 // eslint-disable-next-line 2344 const maxChars = +options?.hash?.maxChars || 2; // we do not allow this to be 0 2345 let result = text.match(/\b\w/g)?.slice(0, maxChars); 2346 if (!result) return ''; 2347 if (options?.hash?.addText) result = result.map((item)=>item + options.hash.addText); 2348 return result.join(options?.hash?.joinWith || '').toUpperCase(); 2349 }, 2350 normalizePhone (phone) { 2351 if (!phone) return ''; 2352 const str = String(phone).trim(); 2353 return (str.startsWith('+') ? '+' : '') + str.replace(/\D/g, ''); 2354 } 2355 }; 2356} 2357$53de3c160faf5a81$exports = $53de3c160faf5a81$var$handlebarsHelpersFactory; 2358 2359 2360/* global window, document */ // eslint-disable-next-line import/prefer-default-export 2361class $dc851cf3939b6ef5$export$ff0712c26d5458f7 { 2362 /** 2363 * Initialize Modal Controller 2364 * @param {Object} options 2365 */ constructor(options){ 2366 this.isBuilder = false;
2367 this.companyId = null; 2368 this.websiteId = null; 2369 this.pageId = null; 2370 this.shareId = null; 2371 this.pageMeta = null; 2372 this.websiteApiGatewayUrl = null; 2373 this.buyerSellerServiceUrl = null; 2374 this.leadIngesterUrl = null; 2375 this.divolteServiceUrl = null; 2376 this.eventBus = null; 2377 this.templateId = null; 2378 this.myhomeDashboardEnabled = false; 2379 this.mlsEnabled = false; 2380 this.hstValuationRedirectEnabled = false; 2381 this.googleMapsAPIKey = null; 2382 } 2383 /** 2384 * Controllers must implement a "destroy" method to be called 2385 * after page navigation to remove event handlers / cleanup 2386 */ destroy() {} 2387 /** 2388 * Set page and supporting data 2389 * @param {string} pageId 2390 * @param {Object} options 2391 */ setPage(pageId, options = {}) { 2392 this.pageId = pageId; 2393 this.shareId = options.shareId || null; 2394 this.pageMeta = { 2395 sourceResource: options.sourceResource, 2396 pageElementId: options.pageElementId, 2397 pageQueryVariables: options.pageQueryVariables || {} 2398 }; 2399 } 2400 /** 2401 * Sets if we are in pagebuilder context or not 2402 * @param {boolean} isBuilder 2403 */ setIsBuilder(isBuilder) { 2404 this.isBuilder = isBuilder; 2405 } 2406 /** 2407 * Set Company and supporting data 2408 * @param {string} companyId 2409 * @param {Object} options 2410 */ setCompany(companyId, options = {}) { 2411 this.companyId = companyId; 2412 } 2413 /** 2414 * Set website and supporting data 2415 * @param {string} websiteId 2416 * @param {Object} options 2417 */ setWebsite(websiteId, options = {}) { 2418 this.websiteId = websiteId; 2419 if (options.myhomeDashboardEnabled) this.myhomeDashboardEnabled = options.myhomeDashboardEnabled; 2420 if (options.mlsEnabled) this.mlsEnabled = options.mlsEnabled; 2421 if (options.hstValuationRedirectEnabled) this.hstValuationRedirectEnabled = options.hstValuationRedirectEnabled; 2422 } 2423 /** 2424 * Set websiteApiGatewayUrl 2425 * @param {string} websiteApiGatewayUrl 2426 * @param {Object} options 2427 */ setWebsiteApiGatewayUrl(websiteApiGatewayUrl, options = {}) { 2428 this.websiteApiGatewayUrl = websiteApiGatewayUrl; 2429 } 2430 /** 2431 * Set buyerSellerServiceUrl 2432 * @param {string} buyerSellerServiceUrl 2433 * @param {Object} options 2434 */ setBuyerSellerServiceUrl(buyerSellerServiceUrl, options = {}) { 2435 this.buyerSellerServiceUrl = buyerSellerServiceUrl; 2436 } 2437 /** 2438 * Set divolteServiceUrl and supporting data 2439 * @param {string} divolteServiceUrl 2440 * @param {Object} options 2441 */ setDivolteServiceUrl(divolteServiceUrl, options = {}) { 2442 this.divolteServiceUrl = divolteServiceUrl; 2443 } 2444 /** 2445 * Set eventBusUrl 2446 * @param {string} eventBusUrl 2447 * @param {Object} options 2448 */ setEventBusUrl(eventBusUrl, options = {}) { 2449 this.eventBusUrl = eventBusUrl; 2450 } 2451 /** 2452 * Set templateId and supporting data 2453 * @param {string} templateId 2454 * @param {Object} options 2455 */ setTemplateId(templateId, options = {}) { 2456 this.templateId = templateId; 2457 } 2458 /** 2459 * Set leadIngesterUrl 2460 * @param {string} leadIngesterUrl 2461 * @param {Object} options 2462 */ setLeadIngesterUrl(leadIngesterUrl, options = {}) { 2463 this.leadIngesterUrl = leadIngesterUrl; 2464 } 2465 /** 2466 * Set googleMapsAPIKey 2467 * @param {string} googleMapsAPIKey 2468 * @param {Object} options 2469 */ setGoogleMapsAPIKey(googleMapsAPIKey, options = {}) { 2470 this.googleMapsAPIKey = googleMapsAPIKey; 2471 } 2472 /** 2473 * Set eventBus 2474 * @param {Object} options 2475 */ setEventBus({ enabled: enabled, apiKey: apiKey, url: url }) { 2476 this.eventBus = { 2477 enabled: enabled, 2478 apiKey: apiKey, 2479 url: url 2480 }; 2481 } 2482} 2483 2484 2485/* eslint-disable import/prefer-default-export */ // eslint-disable-next-line import/prefer-default-export 2486class $7c391e2f7931d60d$export$3b5bd9381a52554c { 2487 /** 2488 * Initialize Base Controller at build time 2489 * @param { ConfigController } config 2490 * @param {Window} window 2491 * @param {Document} document 2492 */ constructor(config, window, document){ 2493 // TODO: Listen for events from configController to update configuration 2494 this.config = config; 2495 this.window = window; 2496 this.document = document; 2497 if (!this.destroy) // With turbolinks, we want to ensure that on each page load we have the latest version of the sdk 2498 // Controllers are deconstructed and replaced (on the window object) per request 2499 // Controllers must use the destory method to remove event handlers to prevent undefined behavior 2500 throw new Error('Controllers must implement a deconstructor'); 2501 } 2502} 2503 2504 2505// eslint-disable-next-line import/prefer-default-export 2506const $a3e97e89bbc2a366$export$f037eeffb5561205 = 2000; 2507 2508 2509class $0ead03fdb95fa9ce$export$d507f25e63650365 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 2510 /** 2511 * Initialize Modal Controller at build time 2512 * @param { ConfigController } config 2513 * @param {Window} window 2514 * @param {Document} document 2515 */ constructor(config, window, document){ 2516 super(config, window, document); 2517 this.setLoginState = this.setLoginState.bind(this); 2518 this.pageId = null; 2519 this.modals = []; 2520 this.exitModalTriggered = {}; 2521 this.exitModalEventListeners = []; 2522 } 2523 /** 2524 * Initialize Modal Controller at run time 2525 * Attach handlers and events to DOM 2526 * @param {Object} options 2527 */ initialize(options) { 2528 try { 2529 const { config: config, document: document } = this; 2530 this.pageId = config.pageId; 2531 this.modals = document.querySelectorAll('body > #modals > .modal');
2532 options.modals.forEach((m)=>{ 2533 this._attachModalHandler(m); 2534 }); 2535 } catch (e) { 2536 // eslint-disable-next-line no-console 2537 console.log(e); 2538 } 2539 } 2540 /** 2541 * Controllers must implement a "destroy" method to be called 2542 * after page navigation to remove event handlers / cleanup 2543 */ destroy() { 2544 const { document: document } = this; 2545 this.exitModalEventListeners.forEach((listener)=>{ 2546 document.removeEventListener('mouseout', listener); 2547 }); 2548 this.modals = []; 2549 this.exitModalTriggered = {}; 2550 this.exitModalEventListeners = []; 2551 } 2552 /** 2553 * Set modal to local storage with expiration 2554 * @param {string} modalId 2555 */ setModalWithExpiry(modalId) { 2556 const { window: window } = this; 2557 const TTL = 86400000; // 24 hours 2558 const now = new Date(); 2559 const expiry = now.getTime() + TTL; 2560 const key = `modal-controller-${modalId}`; 2561 try { 2562 window.localStorage.setItem(key, JSON.stringify(expiry)); 2563 } catch (err) { 2564 // catch error when setting item to storage on iOS private browser 2565 } 2566 } 2567 /** 2568 * Save success login modal to local storage 2569 */ setLoginState() { 2570 const { window: window } = this; 2571 try { 2572 window.localStorage.setItem('isSignedUp', 'true'); 2573 } catch (err) { 2574 // catch error when setting item to storage on iOS private browser 2575 } 2576 } 2577 /** 2578 * Get modal and check expiration 2579 * @param {string} modalId 2580 * @return {boolean} 2581 */ getModalWithExpiry(modalId) { 2582 const { window: window } = this; 2583 const storage = window.localStorage; 2584 const expirationTime = storage.getItem(`modal-controller-${modalId}`); 2585 if (!expirationTime) return false; 2586 const expiry = JSON.parse(expirationTime); 2587 const now = new Date(); 2588 if (now.getTime() > expiry) { 2589 storage.removeItem(`modal-controller-${modalId}`); 2590 return false; 2591 } 2592 return true; 2593 } 2594 /** 2595 * Make a modal visible 2596 * @param {string} modalId 2597 * @param {Object} options 2598 */ show(modalId, options = {}) { 2599 // TODO: migrate logic from page.handlebars 2600 const { window: window } = this; 2601 const modalViewed = this.getModalWithExpiry(modalId); 2602 // Only show a modal if it has not been seen 2603 // Does not affect "show modal on button click" 2604 if (modalId && !modalViewed || options.forced === true) { 2605 window.lpUI.showModal(`modal-${modalId}`, options); 2606 this.setModalWithExpiry(modalId); 2607 } 2608 } 2609 /** 2610 * Attach events based on Modal type and page settings 2611 * @param {Modal} modal 2612 */ _attachModalHandler(modal) { 2613 const { pageId: pageId } = this; 2614 const { trigger: trigger, pageSpecific: pageSpecific } = modal; 2615 if (pageSpecific) { 2616 const pageIds = modal.pages.map((p)=>p.pageId); 2617 if (!pageIds.includes(pageId)) // Modal does not belong to this page 2618 return; 2619 } 2620 if (trigger === 'EXIT') this._exitModalHandler(modal); 2621 else if (trigger === 'TIMER') this._timerModalHandler(modal); 2622 else if (trigger === 'FORCED') this._forcedModalHandler(modal); 2623 } 2624 /** 2625 * Attach events for exit Modals 2626 * @param {Modal} modal 2627 */ _exitModalHandler(modal) { 2628 // eslint-disable-next-line 2629 const that = this; 2630 const { document: document, exitModalTriggered: exitModalTriggered } = this; 2631 const { modalId: modalId } = modal; 2632 /** 2633 * Handle the mouseout dom event 2634 * @param {Event} event 2635 */ function triggerExitModal(event) { 2636 if (exitModalTriggered[modalId]) return; 2637 if (!event.toElement && !event.relatedTarget) { 2638 that.show(modalId); 2639 exitModalTriggered[modalId] = true; 2640 } 2641 } 2642 document.addEventListener('mouseout', triggerExitModal); 2643 this.exitModalEventListeners.push(triggerExitModal); 2644 } 2645 /** 2646 * Attach events for timer Modals
2647 * @param {Modal} modal 2648 */ _timerModalHandler(modal) { 2649 const { modalId: modalId, timerDelay: timerDelay } = modal; 2650 setTimeout(()=>{ 2651 this.show(modalId); 2652 }, timerDelay); 2653 } 2654 /** 2655 * Attach events for Forced Modals 2656 * @param {Modal} modal 2657 */ _forcedModalHandler(modal) { 2658 const { modalId: modalId } = modal; 2659 const { window: window, document: document } = this; 2660 const isLoggedIn = window.localStorage.getItem('isSignedUp') === 'true'; 2661 if (!isLoggedIn) { 2662 // watch for event triggering success login 2663 const forcedModal = document.querySelector(`#modal-${modalId}`); 2664 const contactForm = forcedModal?.querySelector('form'); 2665 const MODAL_CLOSE_DELAY = contactForm?.dataset.delay || (0, $a3e97e89bbc2a366$export$f037eeffb5561205); 2666 // form submit autoclose is handled by contactForms controller 2667 contactForm.addEventListener('formsubmitted', ()=>{ 2668 this.setLoginState(); 2669 }); 2670 window.addEventListener('oauthSuccess', ()=>{ 2671 this.setLoginState(); 2672 contactForm.classList.add('success'); 2673 setTimeout(()=>{ 2674 window.lpUI.hideModal(`modal-${modalId}`); 2675 contactForm.reset(); 2676 contactForm.classList.remove('success'); 2677 }, MODAL_CLOSE_DELAY); 2678 }); 2679 this.show(modalId, { 2680 forced: true 2681 }); 2682 } 2683 } 2684} 2685 2686 2687/* eslint-disable import/prefer-default-export */ /* global window */ /* eslint-disable import/prefer-default-export */ /** 2688 * Handle navigation push 2689 * @param {string} href 2690 * @param {boolean} _blank 2691 */ const $fc0a058ae42af628$export$95e8d77caafa3e06 = (href, _blank = false)=>{ 2692 if (!href) return; 2693 if (_blank) { 2694 window.open(href); 2695 return; 2696 } 2697 window.location.assign(href); 2698}; 2699const $fc0a058ae42af628$export$267a1435fe18b8d4 = (obj, path, defValue)=>{ 2700 if (!path) return undefined; 2701 const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g); 2702 const result = pathArray.reduce((prevObj, key)=>prevObj && prevObj[key], obj); 2703 return result === undefined ? defValue : result; 2704}; 2705 2706 2707 2708class $d48f9f944810f613$export$ca3218b7861b9cb0 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 2709 /** 2710 * Initialize Button Controller at build time 2711 * @param { ConfigController } config 2712 * @param {Window} window 2713 * @param {Document} document 2714 */ constructor(config, window, document){ 2715 super(config, window, document); 2716 this._boundClickHandler = this._buttonClickHandler.bind(this); 2717 } 2718 /** 2719 * Initialize Button Controller at run time 2720 * Attach handlers and events to DOM 2721 * @param {Object} options 2722 */ initialize(options = {}) { 2723 try { 2724 const { document: document } = this; 2725 document.body.removeEventListener('click', this._boundClickHandler); 2726 document.body.addEventListener('click', this._boundClickHandler); 2727 } catch (e) { 2728 // eslint-disable-next-line no-console 2729 console.error(e); 2730 } 2731 } 2732 /** 2733 * Controllers must implement a "destroy" method to be called 2734 * after page navigation to remove event handlers / cleanup 2735 */ destroy() { 2736 const { document: document } = this; 2737 document.body.removeEventListener('click', this._boundClickHandler); 2738 } 2739 /** 2740 * Buttons click handler 2741 * @param {event} e 2742 */ _buttonClickHandler(e) { 2743 this._handleButtonClick(e).catch((e)=>console.error(e)); 2744 } 2745 /** 2746 * Handle button click 2747 * We need special function to have easy way to detach listener 2748 * @param {Event} e 2749 */ async _handleButtonClick(e) { 2750 const { window: window, document: document } = this; 2751 const button = e.target.closest('button, a'); 2752 if (!button) return; 2753 const type = button.dataset.type || ''; 2754 const href = button.href || button.dataset.href || ''; 2755 const target = button.target || ''; 2756 const { submit: submit } = button.dataset; 2757 if (submit) { 2758 try { 2759 await this._handleSubmit(button); 2760 } catch (err) { 2761 // eslint-disable-next-line no-console 2762 console.error(err); 2763 } 2764 (0, $fc0a058ae42af628$export$95e8d77caafa3e06)(href, target === '_blank'); 2765 } 2766 this._trackConversion(button); 2767 if (type === 'VIDEO') { 2768 this._handleVideoButton(button); 2769 return; 2770 } 2771 if (type === 'CONTACT_US') { 2772 this._handleContactUsButton(button); 2773 return; 2774 } 2775 if (type === 'SUBSCRIBE') { 2776 // TODO: Extend for an overwritten subscribe 2777 window.lpUI.showModal('modal-global-subscribe'); 2778 return; 2779 } 2780 if (type === 'MY_ACCOUNT') { 2781 // TODO: Extend for an overwritten subscribe 2782 window.lpUI.showModal('modal-global-my-account'); 2783 return; 2784 } 2785 if (type === 'SHARE_POPUP') { 2786 // TODO: Extend for an overwritten subscribe 2787 const sharePopup = button.querySelector('.share-popup'); 2788 if (sharePopup) sharePopup.style.display = 'flex'; 2789 e.stopPropagation(); // this may not work in current 'delegate' mode 2790 return; 2791 } 2792 // Custom modals 2793 if (type.substring(0, 6) === 'MODAL_') { 2794 const modalId = type.substring(6); 2795 window.lpUI.showModal(`modal-${modalId}`); 2796 return; 2797 } 2798 // MAILTO / TEL Event 2799 if (href?.startsWith('mailto:')) { 2800 const email = href.substring(7); 2801 // TODO: Replace with SDK method 2802 document.sendGoogleAnalyticsEvent({ 2803 hitType: 'event', 2804 eventCategory: 'button', 2805 eventAction: 'click', 2806 eventLabel: 'Email', 2807 eventValue: email 2808 }); 2809 } else if (href?.startsWith('tel:')) { 2810 const phoneNumber = href.substring(4); 2811 // TODO: Replace with SDK method 2812 document.sendGoogleAnalyticsEvent({ 2813 hitType: 'event', 2814 eventCategory: 'button', 2815 eventAction: 'click', 2816 eventLabel: 'Phone', 2817 eventValue: phoneNumber 2818 }); 2819 } 2820 } 2821 /** 2822 * Handle submit 2823 * @param {HTMLButtonElement|HTMLAnchorElement} button 2824 */ async _handleSubmit(button) { 2825 const form = button.closest('form'); 2826 const { window: window } = this; 2827 if (form) return await window.luxuryPresence.contactForms.submitForm(form); 2828 return null; 2829 } 2830 _getVimeoSrc(link) { 2831 if (!link || !link.includes('vimeo.com') || link.length > 2000) return null; 2832 const matchResult = link.match(/(?:(?:www\.)?vimeo\.com\/(?:showcase\/\d+(?:\/video\/|\?video[=/])|channels\/(?:\w+\/)?|groups\/(?:[^/]*)\/videos\/|)|player\.vimeo\.com\/video\/)(\d+)(?:(?:\?.*&*h=|\/)+([\d,a-f]+))?/); 2833 if (!matchResult) return null; 2834 const [, vimeoId, vimeoHashParameter] = matchResult; 2835 let src = `https://player.vimeo.com/video/${vimeoId}?`; 2836 if (vimeoHashParameter) src += `h=${vimeoHashParameter}&`; 2837 src += 'autoplay=1'; 2838 return src; 2839 } 2840 /** 2841 * Handle type video click 2842 * @param {HTMLElement} button 2843 */ // eslint-disable-next-line sonarjs/cognitive-complexity 2844 _handleVideoButton(button) { 2845 const { document: document } = this; 2846 const section = button.closest('section'); 2847 // Embed youtube/vimeo video url 2848 let { src: src } = button.dataset; 2849 let youtubeId = ''; 2850 if (src && (src.includes('youtube.com') || src.includes('youtu.be')) && !src.includes('youtube.com/embed')) { 2851 // test link: https://regexr.com/3anm9 2852 const youtubeRegex = /(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\?(?:\S*?&?v=)
2852)|youtu.be\/)([a-zA-Z0-9_-]{6,11})/; 2853 const youtubeResult = src.match(youtubeRegex); 2854 // eslint-disable-next-line 2855 if (youtubeResult) youtubeId = youtubeResult[1]; 2856 } 2857 const vimeoSrc = this._getVimeoSrc(src); 2858 if (youtubeId) src = `https://youtube.com/embed/${youtubeId}?autoplay=1&controls=0`; 2859 else if (vimeoSrc) src = vimeoSrc; 2860 if (!src || !section) return; 2861 const isVideoFile = src.endsWith('.mp4') || src.endsWith('.webm') || src.includes('cloudinary.com'); 2862 const modalHtml = ` 2863 <div id="modal-${section.id}" class="modal visible"> 2864 <div class="modal-content"> 2865 <div class="lightbox-video"> 2866 <div class="video-player"> 2867 <div class="embed-container"> 2868 ${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>`} 2869 </div> 2870 </div> 2871 </div> 2872 </div> 2873 <button class="close lp-close" type="button" aria-label="close modal"><span class="lp-close-icon" aria-hidden="true"></span></button> 2874 </div> 2875 `; 2876 document.body.insertAdjacentHTML('beforeend', modalHtml); 2877 const modal = document.getElementById(`modal-${section.id}`); 2878 const closeModal = modal.querySelector('.close'); 2879 closeModal.addEventListener('click', ()=>{ 2880 modal.remove(); 2881 }); 2882 } 2883 /** 2884 * Handle type contact us click 2885 * @param {HTMLElement} button 2886 */ _handleContactUsButton(button) { 2887 const { window: window, document: document } = this; 2888 // TODO: Extend for an overwritten contact us 2889 document.sendGoogleAnalyticsEvent({ 2890 hitType: 'event', 2891 eventCategory: 'button', 2892 eventAction: 'click', 2893 eventLabel: 'contact' 2894 }); 2895 window.lpUI.showModal('modal-global-contact-us', { 2896 scrollLock: true 2897 }); 2898 } 2899 /** 2900 * Track conversion 2901 * @param {HTMLElement} button 2902 */ _trackConversion(button) { 2903 const { window: window, document: document } = this; 2904 // Conversion Tracking Options 2905 const { gtagConversionId: gtagConversionId, gtagConversionLabel: gtagConversionLabel, fbEventName: fbEventName } = button.dataset; 2906 if (gtagConversionId && gtagConversionLabel) { 2907 if (window.dataLayer && window.dataLayer.length) { 2908 const configured = window.dataLayer.some((layer)=>layer.length && layer[0] === 'config' && layer[1] === gtagConversionId); 2909 if (!configured) document.sendGoogleTagManagerEvent('config', gtagConversionId); 2910 } 2911 const sentTo = `${gtagConversionId}/${gtagConversionLabel}`; 2912 document.sendGoogleTagManagerEvent('event', 'conversion', { 2913 send_to: sentTo 2914 }); 2915 } 2916 if (window.fbq && fbEventName) window.fbq('track', fbEventName, {}); 2917 } 2918} 2919 2920 2921/* eslint-disable import/prefer-default-export */ 2922class $68a2d4aa500c7a05$export$61ec8f2b6291ec31 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 2923 /** 2924 * Initialize Validation Controller at build time 2925 * @param { ConfigController } config 2926 * @param {Window} window 2927 * @param {Document} document 2928 */ constructor(config, window, document){ 2929 super(config, window, document); 2930 this.validatedForms = []; 2931 } 2932 /** 2933 * Initialize Contact Form Controller at run time 2934 * Attach handlers and events to DOM 2935 * @param {Object} options 2936 */ initialize(options = {}) { 2937 try { 2938 const { window: window, document: document } = this; 2939 const { selector: selector } = options; 2940 let validatedForms = []; 2941 if (selector) validatedForms = document.querySelectorAll(`${selector} form[data-type="contact-form"]`); 2942 else validatedForms = document.querySelectorAll('form[data-type="contact-form"]'); 2943 const isPhoneValidationLibRequired = !!document.querySelectorAll('input[type="tel"]').length; 2944 // we are loading the phone validation lib from the globally defined list of libs 2945 if (isPhoneValidationLibRequired && !window.libphonenumber && window?.luxuryPresence?.libs) { 2946 const { loadJs: loadJs, jsLibsMap: jsLibsMap } = window.luxuryPresence.libs; 2947 const { libphonenumber: libphonenumber } = jsLibsMap; 2948 loadJs(libphonenumber.jsSrc, this.attachValidation.bind(this, validatedForms)); 2949 }
2949 else this.attachValidation(validatedForms); 2950 this.validatedForms = this.validatedForms.concat(validatedForms); 2951 } catch (e) { 2952 // eslint-disable-next-line no-console 2953 console.log(e); 2954 } 2955 } 2956 /** 2957 * Controllers must implement a "destroy" method to be called 2958 * after page navigation to remove event handlers / cleanup 2959 */ destroy() { 2960 this.validatedForms = []; 2961 } 2962 /** 2963 * Validate all forms in the document 2964 * @param {NodeListOf<HTMLFormElement>} forms 2965 */ attachValidation(forms) { 2966 forms.forEach((form)=>{ 2967 const inputs = form.querySelectorAll('input, select, textarea'); 2968 inputs.forEach((input)=>{ 2969 this.applyFieldValidation(input); 2970 }); 2971 }); 2972 } 2973 /** 2974 * Field Validation Handler from global context 2975 * @param {HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement} inputField 2976 */ applyFieldValidation(inputField) { 2977 const fieldType = inputField.getAttribute('type'); 2978 if (fieldType === 'tel') this._applyPhoneValidation(inputField); 2979 } 2980 /** 2981 * Phone Field Validation Handler 2982 * @param {HTMLInputElement} inputField 2983 */ _applyPhoneValidation(inputField) { 2984 const { window: window } = this; 2985 if (window.libphonenumber) { 2986 // https://codepen.io/coinscope/pen/BaXBvBp?editors=1010 2987 const phoneUtil = window.libphonenumber.isValidPhoneNumber; 2988 inputField.addEventListener('keyup', function() { 2989 if (this.hasAttribute('required') || this.value.replace(/\s/g, '').length) try { 2990 const phoneNumber = this.value; 2991 const region = 'US'; 2992 const isValidNumber = phoneUtil(phoneNumber, region); 2993 if (!isValidNumber) this.setCustomValidity('Please enter a valid phone number.'); 2994 else this.setCustomValidity(''); 2995 } catch (e) { 2996 this.setCustomValidity('Please enter a valid phone number.'); 2997 } 2998 else this.setCustomValidity(''); 2999 }); 3000 } 3001 } 3002} 3003 3004 3005 3006 3007/** 3008 * Fires the `generate_lead` Google Ads conversion on any marketing-site lead 3009 * event â lead-form submits (all routed through ContactFormController) and 3010 * social sign-in (oauth.js) â at most once per session. 3011 * 3012 * Reuses the same `generate_lead` event the Home Search Tool fires; the page 3013 * template already configures the LP Google tags, so no new Google Ads setup is 3014 * needed. Cross-tab/visitor dedupe is left to the conversion action's 3015 * Count="One" â localStorage is intentionally avoided as it would suppress a 3016 * returning visitor's later lead. 3017 */ const $3ec2bf3965f87ecc$export$78b64890ea40f4e4 = 'generate_lead'; 3018const $3ec2bf3965f87ecc$export$568da12be2433b06 = 'lp_lead_form_conversion_fired'; 3019function $3ec2bf3965f87ecc$var$alreadyFired(window) { 3020 try { 3021 return window.sessionStorage.getItem($3ec2bf3965f87ecc$export$568da12be2433b06) === 'true'; 3022 } catch { 3023 // sessionStorage can throw in private browsing; fail open so we still fire. 3024 return false; 3025 } 3026} 3027function $3ec2bf3965f87ecc$var$markFired(window) { 3028 try { 3029 window.sessionStorage.setItem($3ec2bf3965f87ecc$export$568da12be2433b06, 'true'); 3030 } catch { 3031 // Ignore â see alreadyFired(). 3032 } 3033} 3034function $3ec2bf3965f87ecc$export$e70565180c0e6950(window, document) { 3035 if (!window || !document) return; 3036 // GA bootstrap may not have run yet (or no pixel on this page); don't throw, 3037 // and don't burn the once-per-session flag if we can't actually fire. 3038 if (typeof document.sendGoogleTagManagerEvent !== 'function') return; 3039 if ($3ec2bf3965f87ecc$var$alreadyFired(window)) return; 3040 try { 3041 // Mark fired only AFTER a successful send, so a thrown GTM call doesn't 3042 // permanently suppress the conversion for the rest of the session â and 3043 // never let an analytics failure break the caller's success flow. 3044 document.sendGoogleTagManagerEvent('event', $3ec2bf3965f87ecc$export$78b64890ea40f4e4); 3045 $3ec2bf3965f87ecc$var$markFired(window); 3046 } catch { 3047 // Swallow â analytics must not break form submit / sign-in. 3048 } 3049} 3050 3051 3052 3053const $2aefad83322125c9$var$homeValuationRoute = '/api/v1/home-valuation'; 3054class $2aefad83322125c9$export$2e2bcd8739ae039 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 3055 destroy() { 3056 // 3057 } 3058 /** 3059 * Clean address string by removing call time frame suffix and extra whitespace 3060 * 3061 * Handles 17 templates that append ", call time frame: [value]" to the address: 3062 * - TheTrailblazerSir_2, TheMasterpiece (2x), TheInspirationSir_1, TheIconSir_3
3063 * - Influencer, GlobalCollective, Evolution, CorcoranAgent_1 3064 * - CompassSE (2x), CompassPrestige (2x), CompassNavigator 3065 * - ColdwellBanker (2x), Classic 3066 * 3067 * @param {string} address - Raw address string that may contain time frame info 3068 * @return {string} - Cleaned address string 3069 */ _cleanAddressString(address) { 3070 if (!address || typeof address !== 'string') return ''; 3071 let cleaned = address.trim(); 3072 // Fix 1: Handle "User entered address:\n..." pattern from TheProducer templates 3073 // Extract only the user entered address, ignore geocoded part 3074 if (cleaned.includes('User entered address:')) { 3075 const match = cleaned.match(/User entered address:\s*\n?\s*([^\n]+)/); 3076 if (match && match[1]) cleaned = match[1].trim(); 3077 } 3078 // Fix 2: Remove ", call time frame: ..." suffix if present (affects 17 templates) 3079 const timeFrameIndex = cleaned.indexOf(', call time frame:'); 3080 if (timeFrameIndex !== -1) cleaned = cleaned.substring(0, timeFrameIndex).trim(); 3081 return cleaned; 3082 } 3083 /** 3084 * Transform Google Maps address components to structured format 3085 * @param {Array} addressComponents - Google Maps address components 3086 * @return {Object} - Structured address object 3087 */ _transformAddressComponents(addressComponents) { 3088 const get = (t)=>(addressComponents.find((c)=>c.componentType === t) || {}).componentName?.text; 3089 const structuredAddress = {}; 3090 const streetNumber = get('street_number'); 3091 const streetName = get('route'); 3092 const state = get('administrative_area_level_1'); 3093 const zipcode = get('postal_code'); 3094 const addressLine2 = get('subpremise'); 3095 // explicit precedence for city 3096 const city = get('locality') || get('sublocality_level_1') || get('neighborhood'); 3097 if (streetNumber) structuredAddress.streetNumber = streetNumber; 3098 if (streetName) structuredAddress.streetName = streetName; 3099 if (city) structuredAddress.city = city; 3100 if (state) structuredAddress.state = state; 3101 if (zipcode) structuredAddress.zipcode = zipcode; 3102 if (addressLine2) structuredAddress.addressLine2 = addressLine2; 3103 return structuredAddress; 3104 } 3105 /** 3106 * Extract address and coordinates from Google Maps validation data 3107 * @param {Object} validatedAddressData - Google Maps validation result 3108 * @return {Object} - Object containing structuredAddress and coordinates 3109 */ _extractAddressAndCoordinates(validatedAddressData) { 3110 let structuredAddress = null; 3111 let coordinates = null; 3112 if (validatedAddressData?.result) { 3113 const { result: result } = validatedAddressData; 3114 // Extract structured address components 3115 if (result.address?.addressComponents) structuredAddress = this._transformAddressComponents(result.address.addressComponents); 3116 // Extract coordinates 3117 if (result.geocode?.location) coordinates = { 3118 latitude: result.geocode.location.latitude, 3119 longitude: result.geocode.location.longitude 3120 }; 3121 } 3122 return { 3123 structuredAddress: structuredAddress, 3124 coordinates: coordinates 3125 }; 3126 } 3127 /** 3128 * Filter out empty string values from an object, keeping only non-empty values 3129 * @param {Object} obj - Object to filter 3130 * @return {Object} - Filtered object without empty strings 3131 */ _filterEmptyStrings(obj) { 3132 const filtered = {}; 3133 for (const [key, value] of Object.entries(obj))if (value !== '' && value !== null && value !== undefined) filtered[key] = value; 3134 return filtered; 3135 } 3136 /** 3137 * Extract raw address from form data with priority fallback chain. 3138 * Order is critical to handle 38 home valuation templates with different field naming: 3139 * 3140 * IMPORTANT: contactForms.js (line 189) stores name="message" in comments_attributes[0].text 3141 * because 'message' is in DEFAULT_LEAD_FIELDS. Fields NOT in DEFAULT_LEAD_FIELDS go to content. 3142 * 3143 * Priority (most specific â most generic): 3144 * 1. address - Pattern 1: 9 templates (explicit address, stored in content) 3145 * 2. property-address - Pattern 3: 4 templates (dash variant with JS, stored in content) 3146 * 3. property_address - Pattern 4: 3 templates (underscore, stored in content - handles VanguardProperties!) 3147 * 4. Property_Address - Pattern 5: 1 template (capital P - TheProducer/HomeValuationRansomHouse, stored in content)
3148 * 5. comments_attributes[0].text - Pattern 2: ALL 17 templates with name="message" store HERE! 3149 * (e.g., Evolution/HomeValuation, TheProducer/HomeValuation, etc.) 3150 * 6. message - Pattern 6: 4 templates with JS-populated message (rare, checked last) 3151 * 7-8. homeValuationAddress, propertyAddress - Legacy/unknown formats 3152 * 3153 * Critical: Each field is cleaned BEFORE checking, so dropdown values are skipped and we try next field 3154 * 3155 * @param {Object} data - Form data 3156 * @return {string} - Raw address string (may contain trailing text like ", call time frame: ...") 3157 */ _getRawAddress(data) { 3158 const content = data.activity.content || {}; 3159 const comments = data.activity.comments_attributes?.[0]?.text; 3160 const possibleFields = [ 3161 content.address, 3162 content['property-address'], 3163 content.property_address, 3164 content.Property_Address, 3165 comments, 3166 content.message, 3167 content.homeValuationAddress, 3168 content.propertyAddress 3169 ]; 3170 return possibleFields.map((field)=>field && this._cleanAddressString(field)).find(Boolean) || ''; 3171 } 3172 /** 3173 * Logs lead-related events for monitoring 3174 * @param {string} eventType - Type of event 3175 * @param {Object} data - Form data 3176 * @param {Error} error - Optional error object 3177 */ _logLeadEvent(eventType, data, error = null) { 3178 const eventPayload = { 3179 event: eventType, 3180 companyId: this.config.companyId, 3181 websiteId: this.config.websiteId, 3182 timestamp: new Date().toISOString(), 3183 hasEmail: !!data.activity?.author_email, 3184 hasAddress: !!this._getRawAddress(data) 3185 }; 3186 if (error) { 3187 // Use userMessage (sanitized) instead of raw message to prevent PII exposure 3188 // userMessage is set by _getUserFriendlyErrorMessage() which provides safe messages 3189 eventPayload.errorMessage = error.userMessage || (error.status ? `Request failed with status ${error.status}` : 'An error occurred'); 3190 eventPayload.errorName = error.name; 3191 eventPayload.errorStatus = error.status; 3192 } 3193 // Log to console with structured format for log aggregation 3194 // eslint-disable-next-line no-console 3195 console.error(`[HomeValuation] ${eventType}`, JSON.stringify(eventPayload)); 3196 // If PostHog is available, send event for analytics 3197 // Wrap in try/catch to prevent SDK failures from blocking submissions 3198 if (this.window.posthog) try { 3199 this.window.posthog.capture(eventType, eventPayload); 3200 } catch (posthogError) { 3201 // eslint-disable-next-line no-console 3202 console.error('[HomeValuation] PostHog capture failed:', posthogError); 3203 } 3204 } 3205 /** 3206 * Maps error types to user-friendly messages 3207 * @param {Error} error - The error object 3208 * @returns {string} - User-friendly message 3209 */ _getUserFriendlyErrorMessage(error) { 3210 if (error.name === 'AbortError' || error.message?.includes('timeout')) return 'Connection timed out. Please try again.'; 3211 if (error.name === 'TypeError' && error.message?.includes('fetch')) return 'Unable to connect. Please check your internet connection and try again.'; 3212 if (error.status === 503 || error.status === 502 || error.status === 504) return 'Service temporarily unavailable. Please try again in a moment.'; 3213 if (error.status === 400) return 'Please check your information and try again.'; 3214 return 'Something went wrong. Please try again or contact us directly.'; 3215 } 3216 /** 3217 * Build formatted address string from structured address components 3218 * @param {Object} structuredAddress - Structured address object 3219 * @return {string} - Formatted address string 3220 */ _formatStructuredAddress(structuredAddress) { 3221 if (!structuredAddress || Object.keys(structuredAddress).length === 0) return ''; 3222 const parts = []; 3223 // Line 1: streetNumber streetName addressLine2 3224 const line1 = [ 3225 structuredAddress.streetNumber, 3226 structuredAddress.streetName, 3227 structuredAddress.addressLine2
3228 ].filter(Boolean).join(' '); 3229 parts.push(line1); 3230 // Line 2: city, state zipcode 3231 const cityState = [ 3232 structuredAddress.city, 3233 structuredAddress.state 3234 ].filter(Boolean).join(', '); 3235 const line2 = [ 3236 cityState, 3237 structuredAddress.zipcode 3238 ].filter(Boolean).join(' '); 3239 parts.push(line2); 3240 return parts.filter(Boolean).join(', '); 3241 } 3242 /** 3243 * Build home valuation data object 3244 * @param {Object} data - Form data 3245 * @param {string} homeValuationEstimate - Home valuation estimate 3246 * @param {Object} structuredAddress - Structured address object 3247 * @param {Object} coordinates - Coordinates object 3248 * @return {Object} - Home valuation data object 3249 */ _buildHomeValuationData(data, homeValuationEstimate, structuredAddress, coordinates) { 3250 // Build homeValuationAddress from structured address (validated by Google) if available 3251 // Format: streetNumber streetName, city, state zipcode, addressLine2 3252 const homeValuationAddress = this._formatStructuredAddress(structuredAddress) || this._getRawAddress(data); 3253 // Validate that we have an address before proceeding 3254 if (!homeValuationAddress) throw new Error('Unable to extract home valuation address from form data'); 3255 // Required fields that must always be included 3256 const requiredFields = { 3257 companyId: data.companyId, 3258 homeValuationAddress: homeValuationAddress, 3259 homeValuationEstimate: homeValuationEstimate ? new Intl.NumberFormat('en-US', { 3260 style: 'currency', 3261 currency: 'USD', 3262 maximumFractionDigits: 0, 3263 minimumFractionDigits: 0 3264 }).format(homeValuationEstimate) : null, 3265 websiteId: data.page.websiteId, 3266 sourceUrl: data.activity.source_url 3267 }; 3268 // Optional fields that will be filtered if empty 3269 const optionalFields = { 3270 leadEmailAddress: data.activity.author_email, 3271 leadFullName: data.activity.author_name, 3272 leadPhoneNumber: data.activity.author_phone, 3273 parcelId: data.activity.content?.parcelId, 3274 resourceId: data.page.pageMeta?.resourceId, 3275 pageId: data.page.pageId,
3276 sourceResource: data.page.pageMeta?.sourceResource, 3277 pageElementId: data.page.pageMeta?.pageElementId, 3278 formId: data.page.pageMeta?.formId, 3279 utmSource: data.activity.content?.utm_source, 3280 utmMedium: data.activity.content?.utm_medium, 3281 utmCampaign: data.activity.content?.utm_campaign, 3282 utmTerm: data.activity.content?.utm_term, 3283 utmContent: data.activity.content?.utm_content, 3284 utmId: data.activity.content?.utm_id, 3285 timeToSell: data.activity.content?.timeToSell, 3286 lookingToBuy: data.activity.content?.lookingToBuy, 3287 referrer: data.referrer, 3288 content: data.activity.content || {}, 3289 fields: data.fields || {} 3290 }; 3291 // Filter out empty strings from optional fields 3292 const filteredOptionalFields = this._filterEmptyStrings(optionalFields); 3293 return { 3294 ...requiredFields, 3295 ...filteredOptionalFields, 3296 // Add structured address and coordinates if they exist 3297 ...structuredAddress && { 3298 address: structuredAddress 3299 }, 3300 ...coordinates && { 3301 coordinates: coordinates 3302 } 3303 }; 3304 } 3305 /** 3306 * Validate address with Google Maps 3307 * @param {string} rawAddress - Raw address string 3308 * @returns {Promise<Object|null>} - Validated address data or null 3309 * @throws {Error} - If validation fails, error is thrown with userMessage 3310 */ async _validateAddressSafely(rawAddress) { 3311 if (!rawAddress) { 3312 // eslint-disable-next-line no-console 3313 console.error('Home valuation: No address found in form data'); 3314 return null; 3315 } 3316 try { 3317 return await this._validateAddressWithGoogleMaps(rawAddress); 3318 } catch (error) { 3319 // eslint-disable-next-line no-console 3320 console.error('Error validating address with Google Maps:', error); 3321 // Attach user-friendly message and throw so user sees the error 3322 error.userMessage = this._getUserFriendlyErrorMessage(error); 3323 throw error; 3324 } 3325 } 3326 /** 3327 * Get home valuation estimate 3328 * @param {Object} validatedAddressData - Validated address data 3329 * @returns {Promise<number|null>} - Home valuation estimate or null 3330 * @throws {Error} - If estimate fetch fails, error is thrown with userMessage 3331 */ async _getHomeValuationEstimateSafely(validatedAddressData) { 3332 try { 3333 return await this._getHomeValuationEstimate(validatedAddressData); 3334 } catch (error) { 3335 // eslint-disable-next-line no-console 3336 console.error('Error getting home valuation estimate:', error); 3337 // Attach user-friendly message and throw so user sees the error 3338 error.userMessage = this._getUserFriendlyErrorMessage(error); 3339 throw error; 3340 } 3341 } 3342 /** 3343 * Parse response text into payload object 3344 * @param {string} text - Response text 3345 * @returns {Object} - Parsed payload 3346 */ _parseResponsePayload(text) { 3347 try { 3348 return text ? JSON.parse(text) : {}; 3349 } catch { 3350 return { 3351 raw: text 3352 }; 3353 } 3354 } 3355 /** 3356 * Create error from failed response 3357 * @param {Object} payload - Response payload 3358 * @param {number} status - HTTP status code 3359 * @returns {Error} - Error object with status and payload 3360 */ _createResponseError(payload, status) { 3361 const errorMessage = payload && typeof payload === 'object' && Object.keys(payload).length ? payload.message || JSON.stringify(payload) : 'Request failed'; 3362 const error = new Error(errorMessage); 3363 // Preserve payload properties if it's an object 3364 if (payload && typeof payload === 'object' && Object.keys(payload).length) Object.assign(error, payload); 3365 // Preserve numeric HTTP status - must be set after Object.assign 3366 // to ensure it takes precedence over any status in payload 3367 error.status = status; 3368 return error; 3369 } 3370 /** 3371 * Submit lead to API endpoint 3372 * @param {string} leadRoute - API endpoint URL 3373 * @param {Object} homeValuationData - Data to submit 3374 * @returns {Promise<Object>} - Submission result 3375 */ async _submitLead(leadRoute, homeValuationData) { 3376 const controller = new AbortController(); 3377 const timeoutId = setTimeout(()=>controller.abort(), 10000); 3378 try { 3379 const response = await fetch(leadRoute, { 3380 method: 'POST', 3381 headers: { 3382 'Content-Type': 'application/json' 3383 }, 3384 body: JSON.stringify(homeValuationData), 3385 signal: controller.signal 3386 }); 3387 clearTimeout(timeoutId); 3388 const text = await response.text(); 3389 const payload = this._parseResponsePayload(text); 3390 if (!response.ok) throw this._createResponseError(payload, response.status); 3391 if (payload && payload.status === 'success' && payload.redirectUrl) { 3392 this.window.location.href = payload.redirectUrl; 3393 return { 3394 redirected: true, 3395 url: payload.redirectUrl 3396 }; 3397 } 3398 return payload; 3399 } catch (error) { 3400 clearTimeout(timeoutId); 3401 throw error; 3402 } 3403 } 3404 /** 3405 * Submit home valuation request with Google Maps validation 3406 * @param {Object} data 3407 * @return {Promise<Object>} 3408 */ async _submitHomeValuationRequest(data) { 3409 const { config: config } = this; 3410 // Use websiteApiGatewayUrl from config 3411 if (!config.websiteApiGatewayUrl) throw new Error('websiteApiGatewayUrl not configured for home valuation'); 3412 // Log submission started 3413 this._logLeadEvent('home_valuation_submission_started', data); 3414 try { 3415 // Validate address with Google Maps 3416 const rawAddress = this._getRawAddress(data); 3417 let validatedAddressData = null; 3418 try {
3419 validatedAddressData = await this._validateAddressSafely(rawAddress); 3420 } catch (error) { 3421 // Error already has userMessage from _validateAddressSafely 3422 this._logLeadEvent('home_valuation_address_validation_failed', data, error); 3423 throw error; 3424 } 3425 // Get home valuation estimate. 3426 // The estimate is best-effort: many valid properties (e.g. commercial 3427 // parcels or addresses without AVM coverage) have no estimate and the 3428 // estimate endpoint returns a non-OK status for them. A missing estimate 3429 // must never block lead capture, so we log the failure and continue with 3430 // a null estimate rather than aborting the whole submission. 3431 let homeValuationEstimate = null; 3432 try { 3433 homeValuationEstimate = await this._getHomeValuationEstimateSafely(validatedAddressData); 3434 } catch (error) { 3435 // Error already has userMessage from _getHomeValuationEstimateSafely 3436 this._logLeadEvent('home_valuation_estimate_failed', data, error); 3437 homeValuationEstimate = null; 3438 } 3439 // Extract structured address and coordinates from Google Maps validation 3440 const { structuredAddress: structuredAddress, coordinates: coordinates } = this._extractAddressAndCoordinates(validatedAddressData); 3441 const leadRoute = `${config.websiteApiGatewayUrl}${$2aefad83322125c9$var$homeValuationRoute}`; 3442 const homeValuationData = this._buildHomeValuationData(data, homeValuationEstimate, structuredAddress, coordinates); 3443 const result = await this._submitLead(leadRoute, homeValuationData); 3444 // Log success 3445 this._logLeadEvent('home_valuation_submission_success', data); 3446 return result; 3447 } catch (error) { 3448 // Ensure error has user-friendly message (may already be set by helper methods) 3449 if (!error.userMessage) error.userMessage = this._getUserFriendlyErrorMessage(error); 3450 this._logLeadEvent('home_valuation_submission_failed', data, error); 3451 throw error; 3452 } 3453 } 3454 /** 3455 * Validate address using Google Maps Address Validation API 3456 * @param {string} addressStr - The address string to validate 3457 * @returns {Promise<Object|null>} - Validated address data or null if validation fails 3458 */ async _validateAddressWithGoogleMaps(addressStr) { 3459 const { config: config, window: window } = this; 3460 // Ensure Google Maps API key is loaded 3461 let apiKey = config.googleMapsAPIKey; 3462 if (!apiKey && window.luxuryPresence?.mapApiLoader) apiKey = await window.luxuryPresence.mapApiLoader.getMapApiKey(); 3463 if (!apiKey) throw new Error('Google Maps API key not configured'); 3464 const controller = new AbortController(); 3465 const timeoutId = setTimeout(()=>controller.abort(), 10000); 3466 try { 3467 const response = await fetch(`https://addressvalidation.googleapis.com/v1:validateAddress?key=${apiKey}`, { 3468 method: 'POST', 3469 headers: { 3470 'Content-Type': 'application/json' 3471 }, 3472 body: JSON.stringify({ 3473 address: { 3474 addressLines: [ 3475 addressStr 3476 ] 3477 }, 3478 enableUspsCass: false 3479 }), 3480 signal: controller.signal 3481 }); 3482 clearTimeout(timeoutId); 3483 if (!response.ok) { 3484 const error = new Error(`Address validation failed: ${response.status}`); 3485 error.status = response.status; 3486 throw error; 3487 } 3488 return response.json(); 3489 } catch (error) { 3490 clearTimeout(timeoutId); 3491 throw error; 3492 } 3493 } 3494 /** 3495 * Check if structured address has all mandatory fields 3496 * @param {Object} structuredAddress - Structured address object 3497 * @return {boolean} 3498 */ _hasMandatoryAddressFields(structuredAddress) { 3499 return !!(structuredAddress.streetNumber && structuredAddress.streetName && structuredAddress.city && structuredAddress.state && structuredAddress.zipcode); 3500 } 3501 /** 3502 * Log missing mandatory address fields 3503 * @param {Object} structuredAddress - Structured address object 3504 */ _logMissingAddressFields(structuredAddress) { 3505 const missingFields = [];
3506 if (!structuredAddress.streetNumber) missingFields.push('streetNumber'); 3507 if (!structuredAddress.streetName) missingFields.push('streetName'); 3508 if (!structuredAddress.city) missingFields.push('city'); 3509 if (!structuredAddress.state) missingFields.push('state'); 3510 if (!structuredAddress.zipcode) missingFields.push('zipcode'); 3511 // eslint-disable-next-line no-console 3512 console.log('Home valuation estimate skipped - missing required fields:', missingFields.join(', '), 'Available fields:', Object.keys(structuredAddress).join(', ')); 3513 } 3514 /** 3515 * Build query string from structured address 3516 * @param {Object} structuredAddress - Structured address object 3517 * @return {string} 3518 */ _buildAddressQueryString(structuredAddress) { 3519 return Object.entries(structuredAddress).map(([key, value])=>`${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'); 3520 } 3521 /** 3522 * GET home valuation estimate 3523 * @param {string} address 3524 * @param {Object} validatedAddressData - Google Maps validated address data 3525 * @return {Promise<number|null>} 3526 */ async _getHomeValuationEstimate(validatedAddressData = null) { 3527 const { config: config } = this; 3528 if (!config.websiteApiGatewayUrl) throw new Error('websiteApiGatewayUrl not configured'); 3529 const base = `${config.websiteApiGatewayUrl}${$2aefad83322125c9$var$homeValuationRoute}`; 3530 // Check if we have validated address data 3531 if (!validatedAddressData?.result?.address?.addressComponents) return null; 3532 const structuredAddress = this._transformAddressComponents(validatedAddressData.result.address.addressComponents); 3533 // Check if all mandatory fields exist 3534 if (!this._hasMandatoryAddressFields(structuredAddress)) { 3535 this._logMissingAddressFields(structuredAddress); 3536 return null; 3537 } 3538 // Build URL with query string 3539 const qs = this._buildAddressQueryString(structuredAddress); 3540 const homeValURL = `${base}?${qs}`; 3541 const controller = new AbortController(); 3542 const timeoutId = setTimeout(()=>controller.abort(), 10000); 3543 try { 3544 const response = await fetch(homeValURL, { 3545 headers: { 3546 Accept: 'application/json' 3547 }, 3548 signal: controller.signal 3549 }); 3550 clearTimeout(timeoutId); 3551 if (!response.ok) { 3552 const error = new Error(`Home valuation estimate failed: ${response.status}`); 3553 error.status = response.status; 3554 throw error; 3555 } 3556 const data = await response.json(); 3557 return data?.valueDollars ?? null; 3558 } catch (error) { 3559 clearTimeout(timeoutId); 3560 // Re-throw to allow retry logic to handle it 3561 throw error; 3562 } 3563 } 3564} 3565 3566 3567const $e10bd00497be8876$export$97de66002300ed70 = 'middleName'; 3568// Default lead fields 3569const $e10bd00497be8876$var$DEFAULT_LEAD_FIELDS = [ 3570 'name', 3571 'firstName', 3572 'lastName', 3573 $e10bd00497be8876$export$97de66002300ed70, 3574 'email', 3575 'phone', 3576 'phoneNumber', 3577 'source', 3578 'message', 3579 'mlsId', 3580 'sourceUrl' 3581]; 3582class $e10bd00497be8876$export$3c5380623cf51249 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 3583 /** 3584 * Initialize Contact Form Controller at build time 3585 * @param { ConfigController } config 3586 * @param {Window} window 3587 * @param {Document} document 3588 */ constructor(config, window, document){ 3589 super(config, window, document); 3590 this.forms = []; 3591 this.homeValuationService = new (0, $2aefad83322125c9$export$2e2bcd8739ae039)(config, window, document); 3592 } 3593 /** 3594 * Initialize Contact Form Controller at run time 3595 * Attach handlers and events to DOM 3596 * @param {Object} options 3597 */ initialize(options = {}) { 3598 try { 3599 const { document: document } = this; 3600 const { selector: selector } = options; 3601 let forms = []; 3602 if (selector) forms = document.querySelectorAll(`${selector} form[data-type="contact-form"]`); 3603 else forms = document.querySelectorAll('form[data-type="contact-form"]');
3604 forms.forEach((form)=>{ 3605 this._attachSubmitHandler(form); 3606 // this._attachValidation(form); 3607 }); 3608 this.forms = this.forms.concat(forms); 3609 } catch (e) { 3610 // eslint-disable-next-line no-console 3611 console.log(e); 3612 } 3613 } 3614 /** 3615 * Controllers must implement a "destroy" method to be called 3616 * after page navigation to remove event handlers / cleanup 3617 */ destroy() { 3618 this.forms = []; 3619 } 3620 /** 3621 * Handle submit from global context 3622 * @param {HTMLFormElement} form 3623 */ submitForm(form) { 3624 this._handleSubmit(null, form).catch((e)=>console.error(e)); 3625 } 3626 /** 3627 * Attach submit event for form 3628 * @param {HTMLFormElement} contactForm 3629 */ _attachValidation(contactForm) { 3630 const { window: window } = this; 3631 const inputs = contactForm.querySelectorAll('input, select, textarea'); 3632 inputs.forEach((input)=>{ 3633 window.luxuryPresence.validation.applyFieldValidation(input); 3634 }); 3635 } 3636 /** 3637 * Attach submit event for form 3638 * @param {HTMLFormElement} contactForm 3639 */ _attachSubmitHandler(contactForm) { 3640 contactForm.addEventListener('submit', (e)=>this._handleSubmit(e, contactForm)); 3641 } 3642 /** 3643 * Extract and process form values 3644 * @param {HTMLFormElement} contactForm 3645 * @return {Object} - Processed form values 3646 */ _extractFormValues(contactForm) { 3647 const formData = new FormData(contactForm); 3648 const values = {}; 3649 const nameParts = []; 3650 const nameKeyRegex = /^name(?:-\d+)?$/; 3651 formData.forEach((value, key)=>{ 3652 if (typeof value === 'string') { 3653 const curr = value.trim(); 3654 if (nameKeyRegex.test(key) && curr) nameParts.push(curr); 3655 const prev = values[key]; 3656 values[key] = prev ? `${prev} ${curr}` : curr; 3657 } else values[key] = value; 3658 }); 3659 if (nameParts.length) values.name = nameParts.join(' ').trim(); 3660 else if (!values.name && values.firstName) { 3661 values.name = values.firstName; 3662 if (values.lastName) values.name += ` ${values.lastName}`; 3663 } 3664 return values; 3665 } 3666 /** 3667 * Build submission data object 3668 * @param {Object} values - Form values 3669 * @param {Object} fields - Form fields 3670 * @param {HTMLFormElement} contactForm - Form element 3671 * @return {Object} - Submission data 3672 */ _buildSubmissionData(values, fields, contactForm) { 3673 const { window: window, config: config } = this; 3674 const content = Object.keys(values).filter((key)=>!$e10bd00497be8876$var$DEFAULT_LEAD_FIELDS.includes(key)).reduce((result, key)=>{ 3675 // eslint-disable-next-line 3676 result[key] = values[key]; 3677 return result; 3678 }, {}); 3679 const { pageId: pageId, companyId: companyId, websiteId: websiteId, pageMeta: pageMeta } = config; 3680 const utm = window.localStorage.getItem('utm_vars') || '{}'; 3681 const referrer = window.localStorage.getItem('referrer') || ''; 3682 const formId = this._getFormId(contactForm); 3683 return { 3684 activity: { 3685 author_email: values.email, 3686 author_name: values.name, 3687 author_phone: values.phone || values.phoneNumber, 3688 activity_source: values.source || 'CONTACT_INQUIRY', 3689 comments_attributes: [ 3690 { 3691 text: values.message || undefined 3692 } 3693 ], 3694 source_url: window.location.href, 3695 content: { 3696 ...content, 3697 ...JSON.parse(utm) 3698 } 3699 }, 3700 page: { 3701 pageId: pageId, 3702 companyId: companyId, 3703 websiteId: websiteId, 3704 pageMeta: { 3705 ...pageMeta, 3706 formId: formId 3707 } 3708 }, 3709 companyId: companyId, 3710 referrer: referrer, 3711 fields: fields 3712 }; 3713 } 3714 /** 3715 * Handle successful form submission 3716 * @param {HTMLFormElement} contactForm - Form element 3717 */ _handleSubmissionSuccess(contactForm) { 3718 const { window: window } = this; 3719 const closeDelay = contactForm.dataset.delay || (0, $a3e97e89bbc2a366$export$f037eeffb5561205); 3720 contactForm.classList.remove('loading'); 3721 contactForm.classList.remove('error'); 3722 contactForm.classList.add('success'); 3723 // TODO: Review producer and classic to deprecate "hide" 3724 contactForm.querySelectorAll('.success').forEach((el)=>el.classList.remove('hide')); 3725 contactForm.dispatchEvent(new Event('formsubmitted')); 3726 // Any successful lead submit credits the Google Ads lead conversion 3727 // (reuses the existing `generate_lead` action), once per session. 3728 (0, $3ec2bf3965f87ecc$export$e70565180c0e6950)(this.window, this.document); 3729 setTimeout(()=>{ 3730 window.lpUI.hideClosestModal(contactForm); 3731 contactForm.reset(); 3732 window.lpUI.sideMenuHide(); 3733 contactForm.querySelectorAll('.success').forEach((el)=>el.classList.add('hide')); 3734 contactForm.classList.remove('success'); 3735 }, closeDelay); 3736 } 3737 /** 3738 * Submit Contact Form Handler 3739 * @param {Event} e 3740 * @param {HTMLFormElement} contactForm 3741 * @return {Promise<Object>} 3742 */ async _handleSubmit(e, contactForm) { 3743 if (e) e.preventDefault(); 3744 if (contactForm.classList.contains('loading')) // Form already submitting 3745 return; 3746 // Hide any previous error message and clear error state 3747 this._hideSubmissionError(contactForm); 3748 contactForm.classList.remove('error'); 3749 contactForm.classList.add('loading'); 3750 try { 3751 // Extract form values first (before async operations) 3752 const values = this._extractFormValues(contactForm); 3753 // TODO: HoneyPot should still send request 3754 if (values.middleName) { 3755 contactForm.classList.remove('loading'); 3756 return; 3757 } 3758 const fields = this._getFields(contactForm); 3759 const data = this._buildSubmissionData(values, fields, contactForm); 3760 await this._submitLeadRequest(data); 3761 this._sendGAEvent(data); 3762 this._handleSubmissionSuccess(contactForm); 3763 } catch (err) { 3764 // eslint-disable-next-line no-console 3765 console.error('Form submission failed:', err); 3766 contactForm.dispatchEvent(new Event('formsubmiterror')); 3767 contactForm.classList.remove('loading'); 3768 contactForm.classList.add('error'); 3769 // Show user-friendly error message if available (from home valuation service)
3770 if (err.userMessage) this._showSubmissionError(contactForm, err.userMessage); 3771 else this._showSubmissionError(contactForm, 'Something went wrong. Please try again.'); 3772 } 3773 } 3774 /** 3775 * Alias anonymous user with canonical ID using event bus 3776 * Links the user's anonymous browsing session to their canonical identity 3777 * @param {Object} data - Form submission data 3778 * @private 3779 */ _aliasUserWithEventBus(data) { 3780 try { 3781 // Check if event bus library and required methods are available 3782 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 3783 // Skip if user is already identified 3784 if (this.window.eventBusProvider.isIdentified()) { 3785 console.log('[EventBus] User already identified, skipping alias'); 3786 return; 3787 } 3788 const email = data.activity?.author_email; 3789 const { companyId: companyId } = this.config; 3790 if (!email || !companyId) { 3791 console.warn('[EventBus] Missing required data for user alias'); 3792 return; 3793 } 3794 // Get the anonymous distinct ID from PostHog 3795 const anonId = this.window.eventBusProvider.getDistinctId(); 3796 if (!anonId) { 3797 console.warn('[EventBus] No anonymous ID available for alias'); 3798 return; 3799 } 3800 // Generate deterministic canonical ID from company + email 3801 const canonicalId = this.window.LuxuryPresenceEventBus.generateUUIDv5FromCompanyEmail(companyId, email); 3802 // Create alias linking anonymous ID to canonical ID 3803 this.window.eventBusProvider.alias({ 3804 anonId: anonId, 3805 canonicalId: canonicalId 3806 }); 3807 console.log('[EventBus] User aliased with canonical ID'); 3808 } catch (error) { 3809 // Never block form submission due to analytics errors 3810 console.error('[EventBus] User alias failed:', error); 3811 } 3812 } 3813 /** 3814 * Send Lead Request 3815 * @param {Object} data 3816 * @return {Promise<Object>} 3817 */ async _submitLeadRequest(data) { 3818 const { config: config } = this; 3819 // Alias user with event bus before submitting the lead 3820 this._aliasUserWithEventBus(data); 3821 if (config.myhomeDashboardEnabled && (data.activity?.activity_source === 'HOME_VALUATION' || data.activity?.activity_source === 'HOME_VALUE')) return this.homeValuationService._submitHomeValuationRequest(data); 3822 const leadRoute = `${config.leadIngesterUrl}/api/v1/leads`; 3823 return fetch(leadRoute, { 3824 method: 'POST', 3825 headers: { 3826 'Content-Type': 'application/json' 3827 }, 3828 body: JSON.stringify(data) 3829 }).then((response)=>{ 3830 if (!response.ok) return response.json().then((error)=>{ 3831 throw error; 3832 }); 3833 return response.json(); 3834 }); 3835 } 3836 /** 3837 * Send GA event 3838 * @param {Object} data 3839 */ _sendGAEvent(data) { 3840 const { document: document } = this; 3841 let event = { 3842 hitType: 'event', 3843 eventCategory: 'button', 3844 eventAction: 'click' 3845 }; 3846 switch(data.activity.activity_source){ 3847 case 'NEWSLETTER_SIGNUP': 3848 event.eventLabel = 'Newsletter'; 3849 document.sendGoogleTagManagerEvent('event', 'newsletter_signup'); 3850 break; 3851 case 'HOME_SEARCH': 3852 event.eventLabel = 'HomeSearch'; 3853 document.sendGoogleTagManagerEvent('event', 'home_search'); 3854 break; 3855 case 'HOME_VALUE': 3856 case 'HOME_VALUATION': 3857 event.eventLabel = 'HomeValue'; 3858 document.sendGoogleTagManagerEvent('event', 'home_valuation'); 3859 break; 3860 case 'EBOOK': 3861 event.eventLabel = 'Ebook'; 3862 document.sendGoogleTagManagerEvent('event', 'ebook_download'); 3863 break; 3864 case 'CONTACT_INQUIRY': 3865 default: 3866 // for contact forms, Marketing has requested that they see a page-view of 'thank-you' as indication of success 3867 // Note that this will break if we have actual page with url of /thank-you 3868 event = { 3869 hitType: 'pageview', 3870 page: '/thank-you' 3871 }; 3872 document.sendGoogleTagManagerEvent('event', 'contact_inquiry'); 3873 break; 3874 } 3875 document.sendGoogleAnalyticsEvent(event); 3876 } 3877 /** 3878 * Gather fields / schema for form, used for display in CRM 3879 * @param {HTMLFormElement} form 3880 * @return {Object} 3881 */ _getFields(form) { 3882 const inputs = form.querySelectorAll('input, select, textarea'); 3883 const fields = {};
3884 inputs.forEach((input)=>{ 3885 const { id: id, name: name, type: inputType } = input; 3886 if (name === $e10bd00497be8876$export$97de66002300ed70) // Honeypot continue 3887 return true; 3888 let label = ''; 3889 if (id) { 3890 const labelNode = form.querySelector(`label[for='${id}']`); 3891 if (labelNode) label = labelNode.textContent.trim(); 3892 else if (input.placeholder) label = input.placeholder.trim(); 3893 } 3894 fields[name] = { 3895 label: label, 3896 type: input.tagName, 3897 inputType: input.tagName === 'INPUT' ? inputType : 'text' 3898 }; 3899 }); 3900 return fields; 3901 } 3902 /** 3903 * Figure out relevant section or div ID for form 3904 * @param {HTMLFormElement} form 3905 * @return {string} 3906 */ _getFormId(form) { 3907 const SELECTORS = "section[id^='section-'], footer[id], .modal[id^='modal-']"; 3908 const parent = form.closest(SELECTORS); 3909 return parent?.id ? this._cleanFormId(parent.id) : ''; 3910 } 3911 /** 3912 * Remove prefix from formID 3913 * @param {string} formId 3914 * @return {string} 3915 */ _cleanFormId(formId) { 3916 const PREFIXES = [ 3917 'section-', 3918 'modal-' 3919 ]; 3920 for (const prefix of PREFIXES){ 3921 if (formId.startsWith(prefix)) return formId.substring(prefix.length); 3922 } 3923 return formId; 3924 } 3925 /** 3926 * Show submission error message on form 3927 * @param {HTMLFormElement} form 3928 * @param {string} message 3929 */ _showSubmissionError(form, message) { 3930 const errorEl = form.querySelector('.submission-error-message'); 3931 if (errorEl) { 3932 errorEl.textContent = message || 'Something went wrong. Please try again.'; 3933 errorEl.style.display = 'block'; 3934 } 3935 } 3936 /** 3937 * Hide submission error message on form 3938 * @param {HTMLFormElement} form 3939 */ _hideSubmissionError(form) { 3940 const errorEl = form.querySelector('.submission-error-message'); 3941 if (errorEl) errorEl.style.display = 'none'; 3942 } 3943} 3944 3945 3946 3947const $ea6901fdf47e0ec1$var$CALLBACK = '__googleMapsCallback'; 3948const $ea6901fdf47e0ec1$var$GOOGLE_MAPS_URL = 'https://maps.googleapis.com/maps/api/js'; 3949const $ea6901fdf47e0ec1$export$76299006759be400 = 1024; 3950const $ea6901fdf47e0ec1$var$KEY_FETCH_ATTEMPTS = 3; 3951const $ea6901fdf47e0ec1$var$KEY_RETRY_BASE_DELAY_MS = 300; 3952const $ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG = 'lp_map_key_failed'; 3953class $ea6901fdf47e0ec1$export$3c19195edca3fa5c extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 3954 /** 3955 * Initialize Button Controller at build time 3956 * @param { ConfigController } config 3957 * @param {Window} window 3958 * @param {Document} document 3959 */ constructor(config, window, document){ 3960 super(config, window, document); 3961 this.retries = 3; 3962 this.callbacks = []; 3963 this.id = `__googleMapsScriptId${Date.now()}`; 3964 this._apiKey = ''; 3965 this.reset(); 3966 } 3967 /** 3968 * Set the Google Maps api key 3969 * @param {string} apiKey 3970 */ set apiKey(apiKey) { 3971 this._apiKey = apiKey; 3972 this.config.setGoogleMapsAPIKey(apiKey); 3973 } 3974 /** 3975 * Get the Google Maps api key 3976 * @return {string} 3977 */ get apiKey() { 3978 return this._apiKey; 3979 } 3980 /** 3981 * Reset the loader state. 3982 */ reset() { 3983 this.deleteScript(); 3984 this.done = false; 3985 this.loading = false; 3986 this.failed = false; 3987 this.errors = []; 3988 this.onerrorEvent = null; 3989 } 3990 /** 3991 * Destroy 3992 */ destroy() { 3993 this.reset(); 3994 } 3995 /** 3996 * get map api Key 3997 * @return {Promise<string>} 3998 */ async getMapApiKey() { 3999 if (this.apiKey) return this.apiKey; 4000 const hadPreviousFailure = this._hadPreviousFailure(); 4001 let recoveryReported = false; 4002 for(let attempt = 1; attempt <= $ea6901fdf47e0ec1$var$KEY_FETCH_ATTEMPTS; attempt += 1){ 4003 const reportRecovery = hadPreviousFailure && !recoveryReported; 4004 try { 4005 // eslint-disable-next-line no-await-in-loop 4006 const response = await fetch(this._getMapKeyUrl(attempt, reportRecovery));
4007 // The request reached the server, so a recovery marker on it was 4008 // delivered and must not be repeated on later attempts or pages. A 4009 // rejected fetch never arrived, so the marker moves to the next 4010 // attempt. 4011 recoveryReported = recoveryReported || reportRecovery; 4012 this._setFailureFlag(false); 4013 if (!response.ok) throw new Error(`Failed to fetch API key: ${response.status}`); 4014 // eslint-disable-next-line no-await-in-loop 4015 const code = await response.text(); 4016 if (!code) return ''; 4017 this.apiKey = code; 4018 return this.apiKey; 4019 } catch (e) { 4020 // eslint-disable-next-line no-console 4021 console.error(e); 4022 if (attempt < $ea6901fdf47e0ec1$var$KEY_FETCH_ATTEMPTS) // eslint-disable-next-line no-await-in-loop 4023 await this._delay($ea6901fdf47e0ec1$var$KEY_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1)); 4024 } 4025 } 4026 this._setFailureFlag(true); 4027 return ''; 4028 } 4029 /** 4030 * Build the map key request url. Retries carry their attempt number, and a 4031 * single request per session carries the recovery marker, so both are 4032 * countable in existing request logs without new infrastructure. 4033 * @param {number} attempt 1-based attempt number 4034 * @param {boolean} reportRecovery tag this request as following a session 4035 * in which every attempt failed 4036 * @return {string} 4037 */ _getMapKeyUrl(attempt, reportRecovery) { 4038 const params = []; 4039 if (attempt > 1) params.push(`attempt=${attempt}`); 4040 if (reportRecovery) params.push('recovered_after_failure=1'); 4041 const query = params.length ? `?${params.join('&')}` : ''; 4042 return `${this._getBaseUrl()}/api/v1/map${query}`; 4043 } 4044 /** 4045 * Whether an earlier attempt in this session exhausted all retries. 4046 * @return {boolean} 4047 */ _hadPreviousFailure() { 4048 try { 4049 return this.window.sessionStorage.getItem($ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG) === '1'; 4050 } catch (e) { 4051 // Storage can throw when disabled (private browsing); absence of the 4052 // flag is the safe default. 4053 return false; 4054 } 4055 } 4056 /** 4057 * Record or clear the session-level key fetch failure flag. 4058 * @param {boolean} failed 4059 */ _setFailureFlag(failed) { 4060 try { 4061 if (failed) this.window.sessionStorage.setItem($ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG, '1'); 4062 else this.window.sessionStorage.removeItem($ea6901fdf47e0ec1$var$KEY_FAILURE_FLAG); 4063 } catch (e) { 4064 // Storage unavailable - reporting is best effort, never fatal. 4065 } 4066 } 4067 /** 4068 * @param {number} ms 4069 * @return {Promise} 4070 */ _delay(ms) { 4071 return new Promise((resolve)=>{ 4072 this.window.setTimeout(resolve, ms); 4073 }); 4074 } 4075 /** 4076 * CreateUrl returns the Google Maps JavaScript API script url ]. 4077 * @return {string} 4078 */ async createUrl() { 4079 const apiKey = await this.getMapApiKey(); 4080 // Google Maps loads successfully without a key and then fails at call time 4081 // with NoApiKeys, which produces a broken map and no load error. Refuse 4082 // instead, so the failure surfaces to the caller. 4083 if (!apiKey) throw new Error('Refusing to load Google Maps without an API key'); 4084 let url = $ea6901fdf47e0ec1$var$GOOGLE_MAPS_URL; 4085 url += `?callback=${$ea6901fdf47e0ec1$var$CALLBACK}`; 4086 url += `&key=${apiKey}`; 4087 url += `&libraries=places`; 4088 return url; 4089 } 4090 /** 4091 * Set the script on document. 4092 */ async setScript() { 4093 if (this.document.getElementById(this.id)) { 4094 this.callback(); 4095 return; 4096 } 4097 let url; 4098 try { 4099 url = await this.createUrl(); 4100 } catch (e) { 4101 // eslint-disable-next-line no-console 4102 console.error(e); 4103 this.failed = true; 4104 this.loading = false; 4105 this.onerrorEvent = e; 4106 this.callback(); 4107 return; 4108 } 4109 const script = this.document.createElement('script'); 4110 script.id = this.id; 4111 script.type = 'text/javascript'; 4112 script.src = url; 4113 script.onerror = this.loadErrorCallback.bind(this); 4114 script.defer = true; 4115 script.async = true; 4116 this.document.head.appendChild(script); 4117 } 4118 /** 4119 * Function to be called if script tag fails 4120 * @param {Error} e 4121 */ loadErrorCallback(e) { 4122 this.errors.push(e); 4123 if (this.errors.length <= this.retries) {
4124 const delay = this.errors.length * 2 ** this.errors.length; 4125 // eslint-disable-next-line no-console 4126 console.log(`Failed to load Google Maps script, retrying in ${delay} ms.`); 4127 setTimeout(()=>{ 4128 this.deleteScript(); 4129 this.setScript().catch((e)=>console.error(e)); 4130 }, delay); 4131 } else { 4132 this.failed = true; 4133 this.onerrorEvent = e; 4134 this.callback(); 4135 } 4136 } 4137 /** 4138 * Delete the script tag 4139 */ deleteScript() { 4140 const script = this.document.getElementById(this.id); 4141 if (script) script.remove(); 4142 } 4143 /** 4144 * Load the Google Maps JavaScript API script and return a Promise. 4145 * @return {Promise} 4146 */ load() { 4147 return this.loadPromise(); 4148 } 4149 /** 4150 * Load the Google Maps JavaScript API script and return a Promise. 4151 * @return {Promise} 4152 */ loadPromise() { 4153 return new Promise((resolve, reject)=>{ 4154 this.loadCallback((err)=>{ 4155 if (!err) resolve(); 4156 else reject(err); 4157 }); 4158 }); 4159 } 4160 /** 4161 * Load the Google Maps JavaScript API script with a callback. 4162 * @param {Function<Event>} fn 4163 */ loadCallback(fn) { 4164 this.callbacks.push(fn); 4165 this.execute(); 4166 } 4167 /** 4168 * Sets the callback function that will be sent as part of the script URL. 4169 */ setCallback() { 4170 this.window.__googleMapsCallback = this.callback.bind(this); 4171 } 4172 /** 4173 * Reset if failed 4174 */ resetIfRetryingFailed() { 4175 if (this.failed) this.reset(); 4176 } 4177 /** 4178 * This is the function that we set the callback parameter to. 4179 */ callback() { 4180 this.done = true; 4181 this.loading = false; 4182 this.callbacks.forEach((cb)=>{ 4183 cb(this.onerrorEvent); 4184 }); 4185 this.callbacks = []; 4186 } 4187 /** 4188 * Set the script a if needed; set the callback 4189 */ execute() { 4190 if (this.window.google && this.window.google.maps && this.window.google.maps.version) // Google Maps already loaded 4191 this.callback(); 4192 this.resetIfRetryingFailed(); 4193 if (this.done) this.callback(); 4194 else if (this.loading) ; 4195 else { 4196 this.loading = true; 4197 this.setCallback(); 4198 this.setScript().catch((e)=>console.error(e)); 4199 } 4200 } 4201 /** 4202 * get base url based on current config 4203 * @return {string} 4204 */ _getBaseUrl() { 4205 // Special handling for page builder since no wag available 4206 const { isBuilder: isBuilder, websiteApiGatewayUrl: websiteApiGatewayUrl } = this.config; 4207 return isBuilder ? websiteApiGatewayUrl : ''; 4208 } 4209 /** 4210 * Resize static map requests to the max 1024px while preserving aspect ratio 4211 * @param {number} width 4212 * @param {number} height 4213 * @return {{width, height}} 4214 */ resizeStaticMapDimensions(width, height) { 4215 if (width <= $ea6901fdf47e0ec1$export$76299006759be400 && height <= $ea6901fdf47e0ec1$export$76299006759be400) return { 4216 width: width, 4217 height: height 4218 }; 4219 // Size param ignored if dimensions exceed STATIC_MAP_MAX_DIM 4220 const ratio = Math.min($ea6901fdf47e0ec1$export$76299006759be400 / width, $ea6901fdf47e0ec1$export$76299006759be400 / height); 4221 return { 4222 width: parseInt(width * ratio), 4223 height: parseInt(height * ratio) 4224 }; 4225 } 4226 /** 4227 * Convert theme to static api param object 4228 * @param {Object} theme 4229 * @return {Object} 4230 */ convertThemeToStaticApiUrl(theme) { 4231 // https://developers.google.com/maps/documentation/maps-static/style-reference 4232 // Google Maps Static API uses a special syntax for it's urls based on the interactive map styles 4233 return theme.map((t)=>{ 4234 const styles = t.stylers.reduce((acc, s)=>{ 4235 const visibility = s.visibility ? `visibility:${s.visibility}` : ''; 4236 const color = s.color ? `color:${s.color.replace('#', '0x')}` : ''; 4237 const lightness = s.lightness ? `lightness:${s.lightness}` : ''; 4238 return `${acc}|${visibility}${color}${lightness}`; 4239 }, ''); 4240 const element = t.elementType ? `|element:${t.elementType}` : ''; 4241 return `feature:${t.featureType}${element}${styles}`; 4242 }); 4243 } 4244 /** 4245 * generate digital signature for url 4246 * @param {string} queryString to sign 4247 * @return {Promise<string>} digitally signed url 4248 */ async getMapApiSignedUrl(queryString) { 4249 try { 4250 const response = await fetch(`${this._getBaseUrl()}/api/v1/map/signature?${queryString}`); 4251 if (!response.ok) throw new Error('Failed to fetch signed URL'); 4252 const { url: url } = await response.json(); 4253 return url; 4254 } catch (e) { 4255 // eslint-disable-next-line no-console 4256 console.error(e); 4257 return ''; 4258 } 4259 } 4260 /** 4261 * Generate static map url 4262 * @param {number} lat 4263 * @param {number} lng 4264 * @param {number} zoom 4265 * @param {Object} theme 4266 * @param {number} srcWidth 4267 * @param {number} srcHeight 4268 * @return {string} 4269 */ generateStaticMapUrl(lat, lng, zoom, theme, srcWidth, srcHeight) {
4270 const baseUrl = 'https://maps.googleapis.com/maps/api/staticmap'; 4271 const { width: width, height: height } = this.resizeStaticMapDimensions(srcWidth, srcHeight); 4272 const query = { 4273 center: `${lat},${lng}`, 4274 zoom: zoom, 4275 scale: 2, 4276 size: `${width}x${height}`, 4277 key: this.apiKey 4278 }; 4279 if (theme) query.style = this.convertThemeToStaticApiUrl(theme); 4280 const params = new URLSearchParams(); 4281 Object.entries(query).forEach(([key, value])=>{ 4282 if (Array.isArray(value)) value.forEach((v)=>params.append(key, v.toString())); 4283 else params.append(key, value.toString()); 4284 }); 4285 return `${baseUrl}?${params.toString()}`; 4286 } 4287 /** 4288 * Generate static map url with digital signature 4289 * @param {Object} { 4290 * srcWidth {number}, required 4291 * srcHeight {number}, required 4292 * theme {array}, 4293 * center: `${lat},${lng}`, required 4294 * zoom: number, required 4295 * markers: `${lat},${lng}`, 4296 * scale: number, 4297 * otherQueryParams... (these must match what is compatible with google maps static api query params) 4298 * } 4299 * @return {Promise<string>} digitally signed url 4300 */ async generateDigitallySignedStaticMapUrl({ srcWidth: srcWidth, srcHeight: srcHeight, theme: theme, ...query }) { 4301 const { width: width, height: height } = this.resizeStaticMapDimensions(srcWidth, srcHeight); 4302 const queryParams = { 4303 ...query, 4304 size: `${width}x${height}` 4305 }; 4306 if (theme) queryParams.style = this.convertThemeToStaticApiUrl(theme); 4307 const params = new URLSearchParams(); 4308 Object.entries(queryParams).forEach(([key, value])=>{ 4309 if (Array.isArray(value)) value.forEach((v)=>params.append(key, v.toString())); 4310 else params.append(key, value.toString()); 4311 }); 4312 const queryString = params.toString(); 4313 try { 4314 // fetch digitally signed url 4315 return await this.getMapApiSignedUrl(queryString); 4316 } catch (e) { 4317 console.error(e); 4318 return ''; 4319 } 4320 } 4321} 4322 4323 4324/* eslint-disable import/prefer-default-export */ 4325 4326class $0a0ad49f13c0b8fd$export$ba9afeb75f20f616 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 4327 // constructor is not needed as it is inherited from BaseController 4328 /** 4329 * Controllers must implement a "destroy" method to be called 4330 * after page navigation to remove event handlers / cleanup 4331 */ destroy() {} 4332 /** 4333 * Places (re-places) a value into the query string under specified key 4334 * or removes it if new value is null or undefined 4335 * @param {string} key 4336 * @param {string|null|undefined|object|array} value 4337 * @param {string} url - defaults to window.location.href 4338 * @return {string} 4339 */ // eslint-disable-next-line sonarjs/cognitive-complexity 4340 updateQueryString(key, value, url) { 4341 // https://stackoverflow.com/questions/5999118/how-can-i-add-or-update-a-query-string-parameter 4342 if (!url) // eslint-disable-next-line 4343 url = this.window.location.href; 4344 let re = new RegExp(`([?&])${key}=.*?(&|#|$)`, 'i'); 4345 let replacement = ''; 4346 if (typeof value !== 'undefined' && value !== null) { 4347 if (Array.isArray(value)) { 4348 if (value.length) replacement = this.serializeArray(key, value); 4349 } else if (typeof value === 'object') { 4350 re = new RegExp(`([?&])${key}\\[[^=]*\\]=.*?(&|#|$)`, 'i'); 4351 replacement = this.serializeObj(value, '', key); 4352 } else replacement = `${key}=${encodeURIComponent(value)}`; 4353 } 4354 const hash = url.split('#'); 4355 let result = hash[0]; 4356 if (re.test(url)) { 4357 let clean = result; 4358 replacement = replacement ? `$1${replacement}$2` : '$1'; 4359 while(re.test(clean)){ 4360 result = clean.replace(re, replacement); 4361 clean = clean.replace(re, '$1'); 4362 } 4363 result = result.replace(/(&|\?)$/, ''); 4364 } else if (replacement) { 4365 const separator = result.indexOf('?') !== -1 ? '&' : '?'; 4366 result += `${separator}${replacement}`; 4367 } 4368 if (typeof hash[1] !== 'undefined' && hash[1] !== null) result += `#${hash[1]}`; 4369 return result; 4370 } 4371 /** 4372 * Returns variable from query string specified by parameter name 4373 * @param {string} name 4374 * @param {string} url defaults to window.location.href 4375 * @return {string|null} 4376 */ getParameterByName(name, url) { 4377 if (!url) // eslint-disable-next-line 4378 url = this.window.location.href; 4379 // eslint-disable-next-line 4380 name = name.replace(/[[\]]/g, '\\$&'); 4381 const regex = new RegExp(`[?&]${name}(=([^&#]*)|&|#|$)`); 4382 let results = Array.from(RegExp.prototype[Symbol.matchAll].call(regex, url)).flat(); 4383 // check for object like syntax where the last value can be an array eg. advancedFilters[query][statusIds][in][0] or advancedFilters[query][city] 4384 if (!results.length) { 4385 const objRegex = new RegExp(`[?&]${name}(\\[.*?\\])=(.*?)(?=&|#|$)`, 'g'); 4386 results = Array.from(RegExp.prototype[Symbol.matchAll].call(objRegex, url)).flat(); 4387 return this._parseParamToObject(results, name === 'advancedFilters'); 4388 } 4389 // For multiple param values, eg arrays 4390 /* Results from regex match all come in this form: 4391 [ '&advancedFilters[query][statusIds][in]=uuid-segundo-123', '[query][statusIds][in]', 'uuid-segundo-123' ] 4392 So using every third value will be the actual value and the second value will be the path 4393 */ if (results.length > 3) return results.reduce((acc, value, index)=>{ 4394 if ((index + 1) % 3 === 0) acc.push(decodeURIComponent(value.replace(/\+/g, ' '))); 4395 return acc; 4396 }, []); 4397 if (!results[2]) return ''; 4398 return decodeURIComponent(results[2].replace(/\+/g, ' ')); 4399 } 4400 /** 4401 * Generates section specific key to store page number in the URL 4402 * @param {string} sectionDomId 4403 * @return {string} 4404 */ makePageKey(sectionDomId) { 4405 return sectionDomId.replace('section-', '').replace(/-/g, ''); 4406 } 4407 /** 4408 * Generates specific key to store parameter in the URL 4409 * uses prevsiouly calculated baseKey for section specific parameters 4410 * @param {Object} formParam 4411 * @param {string} baseKey pre-calculated base for section specific parameters 4412 * @return {string} 4413 */ makeParamKey(formParam, baseKey) { 4414 return formParam.global ? formParam.urlKey : `${baseKey}-${formParam.urlKey}`; 4415 } 4416 /** 4417 * Gets a set of parameters from window query string 4418 * always returns value of "page" parameter if present 4419 * @param {Object[]} formConfig 4420 * @param {string} sectionDomId 4421 * @return {Object} 4422 */ deserializeParams(formConfig, sectionDomId) { 4423 const params = {}; 4424 const urlPageKey = this.makePageKey(sectionDomId); 4425 const page = this.getParameterByName(urlPageKey); 4426 if (page) params.page = parseInt(page); 4427 if (Array.isArray(formConfig)) formConfig.forEach((formParam)=>{
4428 const key = this.makeParamKey(formParam, urlPageKey); 4429 let urlValue = this.getParameterByName(key); 4430 if (formParam.type === 'int') { 4431 urlValue = parseInt(urlValue); 4432 // eslint-disable-next-line 4433 if (!isFinite(urlValue)) urlValue = null; 4434 } else if (formParam.type === 'bool' || formParam.type === 'boolean') urlValue = // eslint-disable-next-line 4435 urlValue === 'true' ? true : urlValue === 'false' ? false : null; 4436 else if (formParam.type === 'json') try { 4437 urlValue = JSON.parse(urlValue); 4438 } catch (e) { 4439 // no need to do anything 4440 } 4441 params[formParam.formKey || formParam.param] = urlValue; 4442 }); 4443 return params; 4444 } 4445 /** 4446 * Serializes set of parameters defined by formConfig into the URL 4447 * adding or replacing or removing required parameters 4448 * @param {Object[]} formConfig 4449 * @param {string} sectionDomId 4450 * @param {Object} params 4451 * @return {string} 4452 */ serializeParams(formConfig, sectionDomId, params) { 4453 let result = this.window.location.href; 4454 const urlPageKey = this.makePageKey(sectionDomId); 4455 result = this.updateQueryString(urlPageKey, params.page, result); 4456 if (Array.isArray(formConfig)) formConfig.forEach((formParam)=>{ 4457 const key = this.makeParamKey(formParam, urlPageKey); 4458 let value = params[formParam.formKey || formParam.param]; 4459 if (formParam.type === 'json' && value !== null && typeof value !== 'undefined') value = JSON.stringify(value); 4460 result = this.updateQueryString(key, value, result); 4461 }); 4462 return result; 4463 } 4464 /** 4465 * Formats small number for slider values 4466 * @param {number} value 4467 * @param {string} currency 4468 * @return {string} 4469 */ formatSliderAtom(value, currency = '') { 4470 const formattedValue = Number.isInteger(value) ? value : value.toFixed(2); 4471 return currency + formattedValue; 4472 } 4473 /** 4474 * Formats a number for slider values 4475 * @param {number} value 4476 * @param {string} currency 4477 * @param {string} delimiter 4478 * @return {string} 4479 */ formatSliderValue(value, currency = '', delimiter = '') { 4480 if (value < 1000) return this.formatSliderAtom(value, currency); 4481 if (value < 1000000) return `${this.formatSliderAtom(value / 1000, currency)}${delimiter}K`; 4482 return `${this.formatSliderAtom(value / 1000000, currency)}${delimiter}M`; 4483 } 4484 /** 4485 * Format price slider range 4486 * @param {number} value 4487 * @param {Object} range 4488 * @param {string} currency 4489 * @param {Object} options 4490 * @return {string} 4491 */ formatSliderPriceRange(value, range, currency, options) { 4492 if (range.min === value && value !== 0) return `${options.lowPrefix}${this.formatSliderValue(value, currency, ' ')}`; 4493 if (range.max === value) return `${this.formatSliderValue(value, currency, ' ')}${options.highSuffix}`; 4494 return `${this.formatSliderValue(value, currency, ' ')}`; 4495 } 4496 /** 4497 * Format area slider range 4498 * @param {number} value 4499 * @param {Object} range 4500 * @param {string} suffix 4501 * @param {Object} options 4502 * @return {string} 4503 */ formatSliderAreaRange(value, range, suffix, options) { 4504 if (range.min === value && value !== 0) return `${options.lowPrefix}${this.formatSliderValue(value)} ${suffix}`; 4505 if (range.max === value) return `${this.formatSliderValue(value)}${options.highSuffix} ${suffix}`; 4506 return `${this.formatSliderValue(value)} ${suffix}`; 4507 } 4508 /** 4509 * Utility function to get properties search parameters from a set of jQuery objects 4510 * @param {Object} options 4511 * @param {jQuery|HTMLElement} [options.queryElement] 4512 * @param {jQuery|HTMLElement} [options.priceSliderElement] 4513 * @param {jQuery|HTMLElement} [options.areaSliderElement] 4514 * @param {jQuery|HTMLElement} [options.neighborhoodSelect] 4515 * @return {Object} 4516 */ // eslint-disable-next-line sonarjs/cognitive-complexity 4517 getSearchFormValues(options) { 4518 const { queryElement: queryElement, priceSliderElement: priceSliderElement, areaSli
4518derElement: areaSliderElement, neighborhoodSelect: neighborhoodSelect } = options; 4519 const result = {}; 4520 if (queryElement) result.search = queryElement.value || null; 4521 if (priceSliderElement) { 4522 const priceValues = priceSliderElement.value.split(';'); 4523 const priceMinLimit = parseInt(priceSliderElement.dataset.min); 4524 const priceMaxLimit = parseInt(priceSliderElement.dataset.max); 4525 const priceMin = parseInt(priceValues[0]); 4526 const priceMax = parseInt(priceValues[1]); 4527 result.priceMin = priceMin !== priceMinLimit ? priceMin : null; 4528 result.priceMax = priceMax !== priceMaxLimit ? priceMax : null; 4529 } 4530 if (areaSliderElement) { 4531 const areaValues = areaSliderElement.value.split(';'); 4532 const areaMinLimit = parseInt(areaSliderElement.dataset.min); 4533 const areaMaxLimit = parseInt(areaSliderElement.dataset.max); 4534 const areaMin = parseInt(areaValues[0]); 4535 const areaMax = parseInt(areaValues[1]); 4536 result.areaMin = areaMin !== areaMinLimit ? areaMin : null; 4537 result.areaMax = areaMax !== areaMaxLimit ? areaMax : null; 4538 } 4539 if (neighborhoodSelect) result.neighborhoodId = neighborhoodSelect.value || null; 4540 return result; 4541 } 4542 /** 4543 * Add supports for object typeof values to be encoded on URL 4544 * Ref: https://stackoverflow.com/questions/1714786/query-string-encoding-of-a-javascript-object 4545 * @param {*} obj 4546 * @param {string} prefix 4547 * @param {string} baseParam used for grouping in case of nested objects 4548 * @returns 4549 */ // eslint-disable-next-line sonarjs/cognitive-complexity 4550 serializeObj(obj, prefix = '', baseParam = '') { 4551 const result = []; 4552 for(const prop in obj)if (obj.hasOwnProperty(prop)) { 4553 const value = obj[prop]; 4554 let k; 4555 if (baseParam) { 4556 const newPrefix = prefix ? `[${prefix}][${prop}]` : `[${prop}]`; 4557 k = `${baseParam}${newPrefix}`; 4558 } else k = prefix ? `${prefix}[${prop}]` : prop; 4559 if (value !== null && Array.isArray(value)) { 4560 if (value.length) result.push(this.serializeArray(k, value)); 4561 } else if (value !== null && typeof value === 'object') result.push(this.serializeObj(value, k)); 4562 else result.push(`${k}=${encodeURIComponent(value)}`); 4563 } 4564 return result.join('&'); 4565 } 4566 /** 4567 * Adds support for array values to be encoded on URL 4568 * @param {string} key 4569 * @param {Array} value 4570 * @param {string} baseParam 4571 */ serializeArray(key, value, baseParam = '') { 4572 const result = []; 4573 value.forEach((val)=>{ 4574 const paramName = baseParam ? `${baseParam}${key}` : key; 4575 result.push(`${paramName}=${encodeURIComponent(val)}`); 4576 }); 4577 return result.join('&'); 4578 } 4579 /** 4580 * Private method to process string search values. 4581 * @param {Array} results comes from regex matchAll. 4582 * @param {Boolean} isAdvancedFilters flag to determine if the search is for advanced filters. 4583 * @returns 4584 */ _parseParamToObject(results, isAdvancedFilters = false) { 4585 if (!results.length) return null; 4586 const obj = {}; 4587 for(let i = 0; i < results.length; i++)/* Results from regex match all come in this form: 4588 [ '&advancedFilters[query][statusIds][in]=uuid-segundo-123', '[query][statusIds][in]', 'uuid-segundo-123' ] 4589 So using every third value will be the actual value and the second value will be the path 4590 */ if ((i + 1) % 3 === 0) { 4591 const value = decodeURIComponent(results[i].replace(/\+/g, ' ')); 4592 const path = results[i - 1]; 4593 Object.assign(obj, this._setObjectPath(path, value, obj, isAdvancedFilters)); 4594 } 4595 return obj; 4596 } 4597 /** * 4598 * Private method to set object value given a path 4599 * @param {String} path 4600 * @param {*} value 4601 * @param {Object} baseObj 4602 * @param {Boolean} isAdvancedFilters flag to determine if the search is for advanced filters. 4603 */ _setObjectPath(path, value, baseObj, isAdvancedFilters = false) { 4604 // eslint-disable-next-line
4605 const keys = path.split(/[\[\]]/).filter(Boolean); 4606 const afArrayKeys = [ 4607 'in', 4608 'nin', 4609 'btw', 4610 'ciin', 4611 'cinin' 4612 ]; 4613 const obj = {}; 4614 let ref = obj; 4615 const valueExists = (0, $fc0a058ae42af628$export$267a1435fe18b8d4)(baseObj, keys.join('.')); 4616 keys.forEach((key, index)=>{ 4617 if (index === keys.length - 1) { 4618 if (valueExists) ref[key] = Array.isArray(valueExists) ? [ 4619 ...valueExists, 4620 value 4621 ] : [ 4622 valueExists, 4623 value 4624 ]; 4625 else ref[key] = isAdvancedFilters && afArrayKeys.includes(key) ? [ 4626 value 4627 ] : value; 4628 } else { 4629 ref[key] = baseObj[key] ? baseObj[key] : {}; 4630 ref = ref[key]; 4631 } 4632 }); 4633 return obj; 4634 } 4635} 4636 4637 4638/* eslint-disable import/prefer-default-export */ 4639class $2b1790aa32f109d1$export$43e435c053a109f6 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 4640 /** 4641 * Initialize Expand Slider Controller at build time 4642 * @param { ConfigController } config 4643 * @param {Window} window 4644 * @param {Document} document 4645 */ constructor(config, window, document){ 4646 super(config, window, document); 4647 this._createLightbox = this._createLightbox.bind(this); 4648 this.expandSliders = []; 4649 } 4650 /** 4651 * Initialize Expand Slider Controller at run time 4652 * Attach handlers and events to DOM 4653 * @param {Object} options 4654 */ initialize(options = {}) { 4655 try { 4656 const { document: document } = this; 4657 const expandSliders = document.querySelectorAll('.has-mobile-expand'); 4658 expandSliders.forEach((block)=>{ 4659 this._addExpandButton(block); 4660 }); 4661 this.expandSliders = this.expandSliders.concat(expandSliders); 4662 } catch (e) { 4663 // eslint-disable-next-line no-console 4664 console.log(e); 4665 } 4666 } 4667 /** 4668 * Controllers must implement a "destroy" method to be called 4669 * after page navigation to remove event handlers / cleanup 4670 */ destroy() { 4671 const { document: document } = this; 4672 document.querySelectorAll('.lp-expand-btn, .lp-expand-btn-wrapper').forEach((element)=>element.remove()); 4673 this.expandSliders = []; 4674 } 4675 /** 4676 * Create expand button for sliders 4677 * @param {HTMLElement} slider 4678 */ _addExpandButton(slider) { 4679 const { document: document } = this; 4680 const section = slider.closest('section[id]'); 4681 const appendTargetSelector = slider.dataset.append; 4682 let expandBtn = section.querySelector('.lp-expand-btn'); 4683 if (!expandBtn) { 4684 expandBtn = document.createElement('button'); 4685 expandBtn.className = 'lp-expand-btn'; 4686 expandBtn.setAttribute('aria-label', 'Open a lightbox'); 4687 expandBtn.innerHTML = `<span class="lp-i lp-i--expand-alt" aria-hidden="true"></span>`; 4688 if (appendTargetSelector) { 4689 const appendTarget = section.querySelector(appendTargetSelector); 4690 if (appendTarget) appendTarget.appendChild(expandBtn); 4691 } else { 4692 const wrapper = document.createElement('div'); 4693 wrapper.className = 'lp-expand-btn-wrapper'; 4694 wrapper.style.position = 'relative'; 4695 wrapper.appendChild(expandBtn); 4696 slider.parentNode.insertBefore(wrapper, slider.nextSibling); 4697 } 4698 } 4699 expandBtn.addEventListener('click', ()=>{ 4700 this._createLightbox({ 4701 slider: slider, 4702 section: section 4703 }); 4704 }); 4705 } 4706 /** 4707 * Creates a lightbox modal for displaying slider images in a larger view. 4708 * 4709 * @param {Object} params - The parameters for the function. 4710 * @param {HTMLElement} params.slider - The slider element containing images. 4711 * @param {HTMLElement} params.section - The section element related to the slider. 4712 * @param {number} [params.initialIndex] - Optional index of the image to show initially. 4713 */ _createLightbox({ slider: slider, section: section, initialIndex: initialIndex }) { 4714 const { window: window, document: document } = this; 4715 const modalId = `lightbox-for-${section?.id}`; 4716 const isSlickAvailable = window.$ && window.$.fn.slick; 4717 const isSectionSlickInitialized = isSlickAvailable && slider.slick; 4718 const isSplideAvailable = typeof window.Splide === 'function'; 4719 const isSectionSplideInitialized = slider.classList.contains('is-initialized') && slider.classList.contains('splide'); 4720 if (typeof window.lpUI.requestScrollLock === 'function') window.lpUI.requestScrollLock(modalId); 4721 else document.body.style.overflow = 'hidden'; 4722 function createSlickLightbox() { 4723 const slickOverlayOptions = { 4724 arrows: true, 4725 dots: false, 4726 infinite: true, 4727 draggable: true, 4728 prevArrow: '<button type="button" class="lp-lightbox-arrow--prev lp-lightbox-arrow" aria-label="Previous"></button>', 4729 nextArrow: '<button type="button" class="lp-lightbox-arrow--next lp-lightbox-arrow" aria-label="Next"></button>' 4730 }; 4731 const modal = document.createElement('div'); 4732 modal.id = modalId; 4733 modal.className = 'lp-lightbox'; 4734 modal.setAttribute('tabindex', '-1'); 4735 modal.setAttribute('role', 'dialog'); 4736 modal.setAttribute('aria-modal', 'true'); 4737 modal.innerHTML = ` 4738 <button class="lp-lightbox__close" aria-label="close modal"></button> 4739 <div class="lp-lightbox__content"> 4740 <div class="lp-lightbox__carousel"></div> 4741 </div> 4742 `; 4743 document.body.appendChild(modal); 4744 const overlaySlider = modal.querySelector('.lp-lightbox__carousel'); 4745 modal.classList.add('show'); 4746 let sourceImages; 4747 if (isSectionSlickInitialized) { 4748 sourceImages = slider.slick.$slides.find('img'); 4749 slickOverlayOptions.initialSlide = slider.slick?.currentSlide || 0; 4750 sourceImages.each(function() { 4751 window.$('.lp-lightbox__carousel').append(window.$(this).clone(false).removeAttr('style').wrap('<div class="lp-lightbox__slide"></div>').parent()); 4752 }); 4753 } else { 4754 sourceImages = slider.querySelectorAll('img');
4755 sourceImages.forEach((img)=>{ 4756 const imgClone = img.cloneNode(true); 4757 imgClone.removeAttribute('style'); 4758 const slide = document.createElement('div'); 4759 slide.className = 'lp-lightbox__slide'; 4760 slide.appendChild(imgClone); 4761 overlaySlider.appendChild(slide); 4762 }); 4763 } 4764 window.$(overlaySlider).slick(slickOverlayOptions); 4765 // Focus modal after it's created 4766 setTimeout(()=>{ 4767 modal.focus(); 4768 }, 100); 4769 // Keyboard navigation handler 4770 const handleKeydown = (e)=>{ 4771 if (!modal.classList.contains('show')) return; 4772 const prevArrow = modal.querySelector('.lp-lightbox-arrow--prev'); 4773 const nextArrow = modal.querySelector('.lp-lightbox-arrow--next'); 4774 const closeBtn = modal.querySelector('.lp-lightbox__close'); 4775 if (e.key === 'ArrowLeft' && prevArrow) { 4776 e.preventDefault(); 4777 prevArrow.click(); 4778 } else if (e.key === 'ArrowRight' && nextArrow) { 4779 e.preventDefault(); 4780 nextArrow.click(); 4781 } else if (e.key === 'Escape' && closeBtn) { 4782 e.preventDefault(); 4783 closeBtn.click(); 4784 } 4785 }; 4786 document.addEventListener('keydown', handleKeydown); 4787 modal.querySelector('.lp-lightbox__close').addEventListener('click', ()=>{ 4788 document.removeEventListener('keydown', handleKeydown); 4789 modal.classList.remove('show'); 4790 const currentSlide = overlaySlider?.slick ? window.$(overlaySlider).slick('slickCurrentSlide') : 0; 4791 if (overlaySlider?.slick) window.$(overlaySlider).slick('unslick'); 4792 if (isSectionSlickInitialized) window.$(slider).slick('slickGoTo', currentSlide); 4793 if (typeof window.lpUI.releaseScrollLock === 'function') window.lpUI.releaseScrollLock(modalId); 4794 else document.body.style.overflow = ''; 4795 modal.remove(); 4796 }); 4797 } 4798 function createSplideLightbox() { 4799 const splideOptions = { 4800 rewind: true, 4801 arrows: true, 4802 arrowPath: '', 4803 type: 'loop', 4804 clones: 1, 4805 pagination: false, 4806 perPage: 1, 4807 perMove: 1 4808 }; 4809 const modal = document.createElement('div'); 4810 modal.id = modalId; 4811 modal.className = 'lp-lightbox'; 4812 modal.setAttribute('tabindex', '-1'); 4813 modal.setAttribute('role', 'dialog'); 4814 modal.setAttribute('aria-modal', 'true'); 4815 modal.innerHTML = ` 4816 <button class="lp-lightbox__close" aria-label="close modal"></button> 4817 <div class="lp-lightbox__content"> 4818 <div class="lp-lightbox__carousel splide" role="group" aria-label="Image Gallery"> 4819 <div class="splide__arrows"> 4820 <button class="splide__arrow splide__arrow--prev lp-lightbox-arrow lp-lightbox-arrow--prev"></button> 4821 <button class="splide__arrow splide__arrow--next lp-lightbox-arrow lp-lightbox-arrow--next"></button> 4822 </div> 4823 <div class="splide__track"> 4824 <ul class="splide__list"></ul> 4825 </div> 4826 </div> 4827 </div> 4828 `; 4829 if (typeof window.lpUI.requestScrollLock === 'function') window.lpUI.requestScrollLock(modalId); 4830 else document.body.style.overflow = 'hidden'; 4831 document.body.appendChild(modal); 4832 const overlaySlider = modal.querySelector('.lp-lightbox__carousel'); 4833 const overlaySliderList = overlaySlider.querySelector('.splide__list'); 4834 modal.classList.add('show'); 4835 let sourceImages; 4836 if (isSectionSplideInitialized) sourceImages = slider.querySelectorAll('.splide__slide:not(.splide__slide--clone) img'); 4837 else sourceImages = slider.querySelectorAll('img');
4838 sourceImages.forEach((img)=>{ 4839 const imgClone = img.cloneNode(true); 4840 imgClone.removeAttribute('style'); 4841 const slide = document.createElement('li'); 4842 slide.className = 'lp-lightbox__slide splide__slide'; 4843 slide.appendChild(imgClone); 4844 overlaySliderList.appendChild(slide); 4845 }); 4846 const overlaySplide = new window.Splide(overlaySlider, splideOptions); 4847 overlaySplide.mount(); 4848 // Navigate to initial index if provided 4849 if (typeof initialIndex !== 'undefined' && initialIndex >= 0) overlaySplide.go(initialIndex); 4850 // Focus modal after it's created and mounted 4851 setTimeout(()=>{ 4852 modal.focus(); 4853 }, 100); 4854 // Keyboard navigation handler 4855 const handleKeydown = (e)=>{ 4856 if (!modal.classList.contains('show')) return; 4857 const prevArrow = modal.querySelector('.splide__arrow--prev'); 4858 const nextArrow = modal.querySelector('.splide__arrow--next'); 4859 const closeBtn = modal.querySelector('.lp-lightbox__close'); 4860 if (e.key === 'ArrowLeft' && prevArrow) { 4861 e.preventDefault(); 4862 prevArrow.click(); 4863 } else if (e.key === 'ArrowRight' && nextArrow) { 4864 e.preventDefault(); 4865 nextArrow.click(); 4866 } else if (e.key === 'Escape' && closeBtn) { 4867 e.preventDefault(); 4868 closeBtn.click(); 4869 } 4870 }; 4871 document.addEventListener('keydown', handleKeydown); 4872 modal.querySelector('.lp-lightbox__close').addEventListener('click', ()=>{ 4873 document.removeEventListener('keydown', handleKeydown); 4874 modal.classList.remove('show'); 4875 if (overlaySplide) overlaySplide.destroy(); 4876 if (typeof window.lpUI.releaseScrollLock === 'function') window.lpUI.releaseScrollLock(modalId); 4877 else document.body.style.overflow = ''; 4878 modal.remove(); 4879 }); 4880 } 4881 if (isSlickAvailable && !isSectionSplideInitialized) createSlickLightbox(); 4882 else if (isSplideAvailable) createSplideLightbox(); 4883 else { 4884 window.luxuryPresence.libs.loadCss(window.luxuryPresence.libs.jsLibsMap.splide.cssSrc); 4885 window.luxuryPresence.libs.loadJs(window.luxuryPresence.libs.jsLibsMap.splide.jsSrc, ()=>{ 4886 createSplideLightbox(); 4887 window.luxuryPresence.libs.jsLibsMap.splide.isLoaded = true; 4888 }); 4889 } 4890 } 4891} 4892 4893 4894/* eslint-disable import/prefer-default-export */ 4895class $4f184d9bd3037f15$export$7a6215890afba974 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 4896 // constructor is not needed as it is inherited from BaseController 4897 /** 4898 * Destroy 4899 */ destroy() { 4900 if (!this.window.divolte) this.window.divolteLp = function() { 4901 (this.window.divolteLp.q = this.window.divolteLp.q || []).push(// eslint-disable-next-line prefer-rest-params 4902 arguments); 4903 }; 4904 } 4905 /** 4906 * Initialize divolte controller 4907 * @param {Object} options 4908 */ initialize(options = {}) { 4909 const { divolteServiceUrl: divolteServiceUrl } = this.config; 4910 if (!divolteServiceUrl || this.window.divolte) return; 4911 this.loadScript(); 4912 } 4913 /** 4914 * loads divolte 4915 */ loadScript() { 4916 const { divolteServiceUrl: divolteServiceUrl } = this.config; 4917 const script = this.document.createElement('script'); 4918 script.id = 'divolte-script'; 4919 script.type = 'text/javascript'; 4920 script.defer = true; 4921 script.async = true; 4922 script.src = `${divolteServiceUrl}/divolte.js`; 4923 this.document.head.appendChild(script); 4924 script.addEventListener('load', this.executeQueue.bind(this)); 4925 } 4926 /** 4927 * executeQueue 4928 */ executeQueue() { 4929 (this.window.divolteLp.q || []).forEach(([methodName, params])=>{ 4930 this[methodName](params); 4931 }); 4932 this.window.divolteLp = this.divolteLp.bind(this); 4933 } 4934 /** 4935 * divolteLp 4936 * @param {string} name 4937 * @param {Object} params 4938 */ divolteLp(name, params) { 4939 try { 4940 this[name](params); 4941 } catch (error) { 4942 // eslint-disable-next-line no-console 4943 console.log(error); 4944 } 4945 } 4946 /** 4947 * sendLpEvent 4948 * @param {string} name 4949 * @param {Object} params 4950 */ sendLpEvent(name, params) { 4951 // Events must be defined in divolte schema! To ensure correct usage, event names are validated here. 4952 if (!name.includes('pageView')) { 4953 // Event not defined 4954 // eslint-disable-next-line no-console 4955 console.log(`${name} IS NOT SUPPORTED`); 4956 return; 4957 } 4958 const { companyId: companyId, templateId: templateId, websiteId: websiteId, pageId: pageId, shareId: shareId, pageMeta: pageMeta } = this.config; 4959 const baseParams = { 4960 companyId: companyId, 4961 templateId: templateId, 4962 websiteId: websiteId, 4963 pageId: pageId, 4964 shareId: shareId, 4965 pageMeta: pageMeta 4966 }; 4967 this.window.divolte.signal(name, Object.assign(baseParams, params)); 4968 } 4969 /** 4970 * sendLpPageView 4971 */ sendLpPageView() { 4972 this.sendLpEvent('pageView', {}); 4973 } 4974} 4975 4976 4977/* eslint-disable import/prefer-default-export */ 4978const $102039871668a1df$var$EVENT_BUS_SCRIPT = 'event-bus-js.js'; 4979const $102039871668a1df$var$EVENT_BUS_VERSION = 'v2.8.0'; 4980const $102039871668a1df$var$EVENT_BUS_DEFAULT_SOURCE = 'frontend://website-render-engine'; 4981class $102039871668a1df$export$e22e4b1be0bb6c61 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 4982 // eslint-disable-next-line @typescript-eslint/no-useless-constructor 4983 constructor(config, window, document){ 4984 super(config, window, document); 4985 } 4986 /** 4987 * Initialize EventBus controller 4988 * @param {Object} options 4989 */ initialize(options = {}) { 4990 const enabled = options.enabled !== undefined ? options.enabled : this.config.eventBus?.enabled; 4991 if (enabled && this.config.eventBus?.apiKey && this.config.eventBus?.url) this.loadScript(); 4992 } 4993 /** 4994 * loads eventBus script 4995 */ loadScript() { 4996 const { eventBusUrl: eventBusUrl } = this.config; 4997 const script = this.document.createElement('script'); 4998 script.id = 'posthog-script'; 4999 script.type = 'text/javascript'; 5000 script.defer = true; 5001 script.async = true; 5002 script.src = `${eventBusUrl}/${$102039871668a1df$var$EVENT_BUS_VERSION}/${$102039871668a1df$var$EVENT_BUS_SCRIPT}`; 5003 this.document.head.appendChild(script); 5004 script.addEventListener('load', this.executeQueue.bind(this)); 5005 } 5006 /** 5007 * executeQueue - Process queued eventBusLp calls 5008 */ executeQueue() { 5009 // Initialize the event bus provider using the global EventBusJS 5010 if (this.window.LuxuryPresenceEventBus) this.window.eventBusProvider = this.window.LuxuryPresenceEventBus.createEventBusProvider({ 5011 apiKey: this.config.eventBus.apiKey, 5012 host: this.config.eventBus.url, 5013 defaultSource: $102039871668a1df$var$EVENT_BUS_DEFAULT_SOURCE 5014 });
5015 (this.window.eventBusLp.q || []).forEach(([methodName, params])=>{ 5016 this[methodName](params); 5017 }); 5018 // Replace queue function with real function 5019 this.window.eventBusLp = this.eventBusLp.bind(this); 5020 } 5021 /** 5022 * Destroy 5023 */ destroy() { 5024 if (!this.window.eventBusProvider) { 5025 // Reset to queue function if no provider exists 5026 this.window.eventBusLp = function() { 5027 (this.window.eventBusLp.q = this.window.eventBusLp.q || []).push(// eslint-disable-next-line prefer-rest-params 5028 arguments); 5029 }; 5030 return; 5031 } 5032 this.window.eventBusProvider.shutdown(); 5033 } 5034 /** 5035 * sendLpEvent 5036 * @param {string} eventType 5037 * @param {Object} data 5038 */ sendLpEvent(eventType, data) { 5039 // Events must be defined in event-bus schema! To ensure correct usage, event types are validated here. 5040 if (eventType !== 'user.activity.page.viewed') { 5041 // Event type not defined 5042 // eslint-disable-next-line no-console 5043 console.log(`${eventType} IS NOT SUPPORTED`); 5044 return; 5045 } 5046 if (!this.window.eventBusProvider) return; 5047 const { companyId: companyId } = this.config; 5048 const eventData = { 5049 company: companyId, 5050 data: {} 5051 }; 5052 try { 5053 this.window.eventBusProvider.capture(eventType, eventData); 5054 } catch (error) { 5055 // eslint-disable-next-line no-console 5056 console.log('EventBus capture error:', error); 5057 } 5058 } 5059 /** 5060 * eventBusLp 5061 * @param {string} name 5062 * @param {Object} params 5063 */ eventBusLp(name, params) { 5064 try { 5065 this[name](params); 5066 } catch (error) { 5067 // eslint-disable-next-line no-console 5068 console.log(error); 5069 } 5070 } 5071 /** 5072 * sendLpPageView 5073 */ sendLpPageView() { 5074 this.sendLpEvent('user.activity.page.viewed', {}); 5075 } 5076} 5077 5078 5079/* eslint-disable import/prefer-default-export */ 5080 5081const $0d25a3fa2e0f4f92$var$EVENT_NAME = 'oauthSuccess'; 5082class $0d25a3fa2e0f4f92$export$b718a981691eae5c extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5083 /** 5084 * Initialize Button Controller at build time 5085 * @param { ConfigController } config 5086 * @param {Window} window 5087 * @param {Document} document 5088 */ constructor(config, window, document){ 5089 super(config, window, document); 5090 this.successListeners = []; 5091 this._listenToMessages = this._listenToMessages.bind(this); 5092 this._listenToOneTapMessage = this._listenToOneTapMessage.bind(this); 5093 } 5094 /** 5095 * Initialize OAuth Controller at run time 5096 * Swap out special buttons for the iframe 5097 * @param {Object} options 5098 */ initialize(options = {}) { 5099 try { 5100 // handle google one tap 5101 if (options.googleSignOnEnabled && !options.iframe) this._renderGoogleOneTap(); 5102 // handle google sign in buttons 5103 this.document.querySelectorAll('div[data-signin-type="google-sign-in"]').forEach((el)=>this._convertGoogleSignIn(el)); 5104 // handle facebook sign in buttons 5105 this.document.querySelectorAll('div[data-signin-type="facebook-sign-in"]').forEach((el)=>this._convertFacebookSignIn(el)); 5106 } catch (e) { 5107 // eslint-disable-next-line no-console 5108 console.log(e); 5109 } 5110 } 5111 /** 5112 * Controllers must implement a "destroy" method to be called 5113 * after page navigation to remove event handlers / cleanup 5114 */ destroy() { 5115 this.successListeners.forEach((callback)=>{ 5116 this.window.removeEventListener('message', this._listenToMessages); 5117 this.window.removeEventListener('message', this._listenToOneTapMessage); 5118 this.window.removeEventListener($0d25a3fa2e0f4f92$var$EVENT_NAME, this.window[callback]); 5119 }); 5120 } 5121 /** 5122 * Convert google one tap 5123 */ _renderGoogleOneTap() { 5124 if (!this._isGoogleOneTapOnCooldown()) { 5125 const dummyEl = this.document.createElement('div'); 5126 // eslint-disable-next-line no-undef 5127 google.accounts.id.initializeIntermediate({ 5128 src: this._buildUrlAndCopyAttributes(dummyEl, dummyEl, 'googleOneTap') 5129 }); 5130 this.window.localStorage.removeItem('googleOneTapExpiration'); 5131 this.window.addEventListener('message', this._listenToOneTapMessage); 5132 } 5133 } 5134 /** 5135 * Listening for messages from BSS one tap iframes 5136 * @param {MessageEvent} e 5137 */ _listenToOneTapMessage(e) { 5138 const messageTypes = { 5139 SHOW_INTERMEDIATE_IFRAME: 'show_intermediate_iframe', 5140 HIDE_INTERMEDIATE_IFRAME: 'hide_intermediate_iframe' 5141 };
5142 const iframeId = 'onetap_google_intermediate_iframe'; 5143 const { buyerSellerServiceUrl: buyerSellerServiceUrl } = this.config; 5144 const { data: data, origin: origin } = e; 5145 const { type: type, height: height, event: event, source: source, token: token } = data; 5146 if (type === messageTypes.SHOW_INTERMEDIATE_IFRAME || type === messageTypes.HIDE_INTERMEDIATE_IFRAME) { 5147 const bssIframe = this.document.getElementById(iframeId); 5148 if (bssIframe) { 5149 bssIframe.style.height = height; 5150 bssIframe.style.display = type === messageTypes.SHOW_INTERMEDIATE_IFRAME ? 'unset' : 'none'; 5151 } 5152 } 5153 // these events are generated by our code in the bss iframe 5154 if (origin === buyerSellerServiceUrl && source === 'GOOGLE_SIGN_ON') { 5155 if (event === 'success') { 5156 this._setExpirationLsItem(86400000); // 24 hours 5157 this._handleQualifyingQuestionsModal(token); 5158 } else if (event === 'cancel') this._setExpirationLsItem(7200000); // 2 hours 5159 } 5160 } 5161 /** 5162 * Set expiration local storage item for google one tap 5163 * @param {number} ms 5164 */ _setExpirationLsItem(ms) { 5165 const expiration = new Date().getTime() + ms; 5166 this.window.localStorage.setItem('googleOneTapExpiration', expiration); 5167 } 5168 /** 5169 * Check if google one tap is expired 5170 * @return {boolean} 5171 */ _isGoogleOneTapOnCooldown() { 5172 const expirationTime = this.window.localStorage.getItem('googleOneTapExpiration'); 5173 return Number(expirationTime) > new Date().getTime(); 5174 } 5175 /** 5176 * Convert google sign in buttons 5177 * @param {HTMLElement} el 5178 */ _convertGoogleSignIn(el) { 5179 this._replaceWithIframe('googleSignIn', el); 5180 } 5181 /** 5182 * Convert google sign in buttons 5183 * @param {HTMLElement} el 5184 */ _convertFacebookSignIn(el) { 5185 this._replaceWithIframe('facebookSignIn', el); 5186 } 5187 /** 5188 * Convert google sign in buttons 5189 * @param {'googleSignIn' | 'facebookSignIn'} provider 5190 * @param {HTMLElement} el 5191 */ _replaceWithIframe(provider, el) { 5192 this._attachSuccessCallback(el); 5193 const iframe = this.document.createElement('iframe'); 5194 iframe.src = this._buildUrlAndCopyAttributes(el, iframe, provider); 5195 iframe.dataset.isSocialOauthButton = true; 5196 el.replaceWith(iframe); 5197 } 5198 /** 5199 * Listening for messages from BSS iframes 5200 * @param {Event} e 5201 */ _listenToMessages(e) { 5202 const { buyerSellerServiceUrl: buyerSellerServiceUrl } = this.config; 5203 // eslint-disable-next-line sonarjs/no-collapsible-if 5204 if (e.origin === buyerSellerServiceUrl) { 5205 if (e.data.event === 'success') { 5206 const event = new Event($0d25a3fa2e0f4f92$var$EVENT_NAME); 5207 this.window.dispatchEvent(event); 5208 // Registration / social sign-in is a lead event â credit the conversion. 5209 (0, $3ec2bf3965f87ecc$export$e70565180c0e6950)(this.window, this.document); 5210 this.successListeners.forEach((callback)=>{ 5211 if (this.window[callback]) this.window[callback](event); 5212 else // eslint-disable-next-line no-console 5213 console.error(`Callback function ${callback} not found on window object`); 5214 }); 5215 this.document.documentElement.classList.add('is-login-success'); 5216 } 5217 } 5218 } 5219 /** 5220 * Attach callback to iframe 5221 * @param {HTMLElement} el 5222 */ _attachSuccessCallback(el) { 5223 this.window.addEventListener('message', this._listenToMessages); 5224 const callbackFunction = el.dataset.onSuccessFunctionName; 5225 if (callbackFunction) this.successListeners.push(callbackFunction); 5226 } 5227 /** 5228 * Build Iframe URL 5229 * @param {HTMLElement} source 5230 * @param {HTMLElement} target 5231 * @param {string} provider 5232 * @return {string} 5233 */ _buildUrlAndCopyAttributes(source, target, provider) { 5234 const { buyerSellerServiceUrl: buyerSellerServiceUrl, companyId: companyId, websiteId: websiteId, pageId: pageId, pageMeta: pageMeta } = this.config; 5235 const { location: location } = this.window; 5236 const sourceUrl = location.origin + location.pathname; 5237 const destination = new URL(`${buyerSellerServiceUrl}/buttons/${provider}`); 5238 const utm = this.window.localStorage.getItem('utm_vars'); 5239 const referrer = this.window.localStorage.getItem('referrer'); 5240 destination.searchParams.append('companyId', companyId); 5241 destination.searchParams.append('websiteId', websiteId); 5242 destination.searchParams.append('pageId', pageId); 5243 destination.searchParams.append('sourceUrl', sourceUrl); 5244 destination.searchParams.append('pageMeta', JSON.stringify(pageMeta)); 5245 if (utm) destination.searchParams.append('utm', utm); 5246 if (referrer) destination.searchParams.append('referrer', referrer); 5247 // Google and Facebook Attributes used to style the social button 5248 const RESERVED_ATTRIBUTES = [ 5249 'data-size', 5250 'data-width', 5251 'data-text', 5252 'data-button-type', 5253 'data-shape', 5254 'data-layout', 5255 'data-max-rows', 5256 'data-use-continue-as', 5257 'data-type', 5258 'data-theme', 5259 'data-logo_alignment', 5260 'data-locale' 5261 ];
5262 Array.from(source.attributes).forEach((attribute)=>{ 5263 if (RESERVED_ATTRIBUTES.includes(attribute.nodeName)) destination.searchParams.append(attribute.nodeName, attribute.nodeValue); 5264 else target.setAttribute(attribute.nodeName === 'id' ? 'data-id' : attribute.nodeName, attribute.nodeValue); 5265 }); 5266 return destination.toString(); 5267 } 5268 /** 5269 * Decode a JWT token to extract payload information 5270 * @param {string} token - The JWT token to decode 5271 * @return {Object|null} The decoded payload object or null if decoding fails 5272 */ _decodeToken(token) { 5273 try { 5274 const parts = token.split('.'); 5275 const payload = parts[1]; 5276 const base64 = payload.replace(/-/g, '+').replace(/_/g, '/'); 5277 const padding = 4 - base64.length % 4; 5278 const padded = padding === 4 ? base64 : base64 + '='.repeat(padding); 5279 return JSON.parse(atob(padded)); 5280 } catch (error) { 5281 return null; 5282 } 5283 } 5284 /** 5285 * Handle qualifying questions modal showing for Google Sign On 5286 * Decodes the JWT token to extract user email and shows the modal if available 5287 * @param {string} token - The JWT token containing user information 5288 */ _handleQualifyingQuestionsModal(token) { 5289 if (token && this.window.luxuryPresence && this.window.luxuryPresence.qualifyingQuestionsModal) { 5290 // Decoding only for lead attribution, fine to skip signature verification 5291 const decoded = this._decodeToken(token); 5292 if (decoded && decoded.email) this.window.luxuryPresence.qualifyingQuestionsModal.showModal(decoded.email, 'Google Sign On'); 5293 } 5294 } 5295} 5296 5297 5298/* eslint-disable import/prefer-default-export */ 5299class $dcf72769f009ff26$export$b900d6fe921fd49c extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5300 /** 5301 * Initialize Qualifying Questions Modal Controller at build time 5302 * @param { ConfigController } config 5303 * @param {Window} window 5304 * @param {Document} document 5305 */ constructor(config, window, document){ 5306 super(config, window, document); 5307 this.showModal = this.showModal.bind(this); 5308 this.hasModalBeenSubmitted = this.hasModalBeenSubmitted.bind(this); 5309 this.modalId = 'qualifying-questions-modal'; 5310 this.cookieKey = 'qualifyingQuestionsModalSubmitted'; 5311 this.qualifyingQuestionsModalEnabled = true; 5312 // Store references for cleanup 5313 this.eventListeners = []; 5314 this.timeouts = []; 5315 } 5316 initialize(options = {}) { 5317 this.qualifyingQuestionsModalEnabled = options.qualifyingQuestionsModalEnabled ?? this.qualifyingQuestionsModalEnabled; 5318 if (!this.qualifyingQuestionsModalEnabled) return; 5319 this.attachModalCloseListeners(); 5320 } 5321 destroy() { 5322 // Remove all stored event listeners 5323 this.eventListeners.forEach(({ element: element, event: event, handler: handler })=>{ 5324 if (element && element.removeEventListener) element.removeEventListener(event, handler); 5325 }); 5326 this.timeouts.forEach((timeoutId)=>{ 5327 clearTimeout(timeoutId); 5328 }); 5329 this.restoreBodyScroll(); 5330 this.eventListeners = []; 5331 this.timeouts = []; 5332 } 5333 /** 5334 * Check if modal has been submitted using cookie-based deduplication 5335 * @return {boolean} 5336 */ hasModalBeenSubmitted() { 5337 const cookieValue = this.getCookie(this.cookieKey); 5338 return cookieValue === 'true'; 5339 } 5340 /** 5341 * Set cookie to prevent modal from showing again 5342 */ setModalSubmittedCookie() { 5343 this.setCookie(this.cookieKey, 'true', 365); // 1 year 5344 } 5345 showModal(email, triggerSource) { 5346 if (!this.qualifyingQuestionsModalEnabled || this.hasModalBeenSubmitted()) return; 5347 this.updateEmailValue(email); 5348 this.updateTriggerSourceValue(triggerSource); 5349 this.showModalElement(); 5350 } 5351 /** 5352 * Get modal element with error handling 5353 * @return {Element|null} 5354 */ getModalElement() { 5355 const modal = this.document.getElementById(this.modalId); 5356 if (!modal) console.error('Modal element not found:', this.modalId); 5357 return modal; 5358 } 5359 updateEmailValue(email) { 5360 const modal = this.getModalElement(); 5361 if (!modal) return; 5362 const emailInput = modal.querySelector('input[name="email"]'); 5363 if (emailInput && typeof email === 'string') emailInput.value = email; 5364 } 5365 updateTriggerSourceValue(triggerSource) { 5366 const modal = this.getModalElement(); 5367 if (!modal) return;
5368 const triggerSourceInput = modal.querySelector(`#${this.modalId}-triggerSource`); 5369 if (triggerSourceInput && typeof triggerSource === 'string') triggerSourceInput.value = triggerSource; 5370 } 5371 showModalElement() { 5372 const modal = this.getModalElement(); 5373 if (!modal) return; 5374 modal.style.display = 'flex'; 5375 this.blockBodyScroll(); 5376 } 5377 /** 5378 * Helper method to get cookie value 5379 * @param {string} name 5380 * @return {string|null} 5381 */ getCookie(name) { 5382 const value = `; ${this.document.cookie}`; 5383 const parts = value.split(`; ${name}=`); 5384 if (parts.length === 2) return decodeURIComponent(parts.pop().split(';').shift()); 5385 return null; 5386 } 5387 /** 5388 * Helper method to set cookie 5389 * @param {string} name 5390 * @param {string} value 5391 * @param {number} days 5392 */ setCookie(name, value, days) { 5393 let expires = ''; 5394 if (days) { 5395 const date = new Date(); 5396 date.setTime(date.getTime() + days * 86400000); 5397 expires = `; expires=${date.toUTCString()}`; 5398 } 5399 let attrs = '; path=/; SameSite=Lax'; 5400 if (this.window && this.window.location && this.window.location.protocol === 'https:') attrs += '; Secure'; 5401 this.document.cookie = `${name}=${encodeURIComponent(value || '')}${expires}${attrs}`; 5402 } 5403 blockBodyScroll() { 5404 this._prevOverflow = this.document.body.style.overflow; 5405 this.document.body.style.overflow = 'hidden'; 5406 } 5407 restoreBodyScroll() { 5408 this.document.body.style.overflow = this._prevOverflow || ''; 5409 this._prevOverflow = null; 5410 } 5411 attachModalCloseListeners() { 5412 const modal = this.getModalElement(); 5413 if (!modal) return; 5414 // Listen for form submission success (when modal closes automatically) 5415 const form = this.document.getElementById(`${this.modalId}-form`); 5416 if (form) { 5417 const formSubmittedHandler = ()=>{ 5418 // Set cookie to prevent showing again and hide modal 5419 this.setModalSubmittedCookie(); 5420 const timeoutId = setTimeout(()=>{ 5421 modal.style.display = 'none'; 5422 this.restoreBodyScroll(); 5423 }, 100); 5424 this.timeouts.push(timeoutId); 5425 }; 5426 form.addEventListener('formsubmitted', formSubmittedHandler); 5427 this.eventListeners.push({ 5428 element: form, 5429 event: 'formsubmitted', 5430 handler: formSubmittedHandler 5431 }); 5432 } 5433 // Listen for close button clicks 5434 const closeButton = modal.querySelector('[data-dismiss="modal"]'); 5435 if (closeButton) { 5436 const closeButtonHandler = ()=>{ 5437 modal.style.display = 'none'; 5438 this.restoreBodyScroll(); 5439 }; 5440 closeButton.addEventListener('click', closeButtonHandler); 5441 this.eventListeners.push({ 5442 element: closeButton, 5443 event: 'click', 5444 handler: closeButtonHandler 5445 }); 5446 } 5447 // Listen for backdrop clicks 5448 const backdropClickHandler = (e)=>{ 5449 // Check if click is on the modal backdrop (not on the modal content) 5450 if (e.target === modal || e.target.id === this.modalId) { 5451 modal.style.display = 'none'; 5452 this.restoreBodyScroll(); 5453 } 5454 }; 5455 modal.addEventListener('click', backdropClickHandler); 5456 this.eventListeners.push({ 5457 element: modal, 5458 event: 'click', 5459 handler: backdropClickHandler 5460 }); 5461 } 5462} 5463 5464 5465/* eslint-disable import/prefer-default-export */ 5466class $50eefeef8d1f2372$export$8a2bf06fbae4dde extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5467 constructor(configController, window, document){ 5468 super(configController, window, document); 5469 this.isValidating = false; 5470 this.lastValidationResult = null; 5471 this.lastValidationTime = null; 5472 this.validationCacheDuration = 300000; // 5 minutes 5473 } 5474 /** 5475 * Destroy 5476 */ destroy() { 5477 this.isValidating = false;
5478 this.lastValidationResult = null; 5479 this.lastValidationTime = null; 5480 } 5481 /** 5482 * Validate user session using GraphQL validSession query 5483 * @param {Object} options - Options for session validation 5484 * @param {boolean} options.useCache - Whether to use cached validation result 5485 * @returns {Promise<boolean>} - true if session is valid, false otherwise 5486 */ async validateSession(options = {}) { 5487 const { useCache: useCache = true } = options; 5488 if (useCache && this.lastValidationResult !== null && this.lastValidationTime) { 5489 const timeSinceLastValidation = Date.now() - this.lastValidationTime; 5490 if (timeSinceLastValidation < this.validationCacheDuration) return this.lastValidationResult; 5491 } 5492 if (this.isValidating) return this.lastValidationResult !== null ? this.lastValidationResult : false; 5493 this.isValidating = true; 5494 const query = ` 5495 query { 5496 validSession { 5497 success 5498 } 5499 } 5500 `; 5501 try { 5502 // query from same domain as the website 5503 const response = await this.window.fetch(`/graphql`, { 5504 method: 'POST', 5505 headers: { 5506 'Content-Type': 'application/json' 5507 }, 5508 credentials: 'include', 5509 body: JSON.stringify({ 5510 query: query 5511 }) 5512 }); 5513 if (!response.ok) { 5514 // eslint-disable-next-line no-console 5515 console.error('SessionController: HTTP error during session validation', response.status); 5516 this.lastValidationResult = false;
5517 this.lastValidationTime = Date.now(); 5518 return false; 5519 } 5520 const data = await response.json(); 5521 if (data.errors) { 5522 this.lastValidationResult = false; 5523 this.lastValidationTime = Date.now(); 5524 return false; 5525 } 5526 const isValid = data.data?.validSession?.success === true; 5527 this.lastValidationResult = isValid; 5528 this.lastValidationTime = Date.now(); 5529 return isValid; 5530 } catch (error) { 5531 // eslint-disable-next-line no-console 5532 console.error('SessionController: Error validating session', error); 5533 this.lastValidationResult = false; 5534 this.lastValidationTime = Date.now(); 5535 return false; 5536 } finally{ 5537 this.isValidating = false; 5538 } 5539 } 5540 /** 5541 * Clear validation cache 5542 */ clearCache() { 5543 this.lastValidationResult = null; 5544 this.lastValidationTime = null; 5545 } 5546} 5547 5548 5549/* eslint-disable import/prefer-default-export */ 5550function $396d9f0ca7465335$export$48d5542b9e3ba39(document) { 5551 const match = document.cookie.match(/cookieyes-consent=([^;]+)/); 5552 if (!match) return false; 5553 try { 5554 const cookieValue = decodeURIComponent(match[1]); 5555 if (cookieValue.includes(',')) { 5556 const segments = cookieValue.split(',').map((c)=>c.trim()); 5557 if (segments.some((s)=>s.includes(':'))) return segments.some((s)=>s === 'analytics:yes'); 5558 return segments.includes('analytics'); 5559 } 5560 return cookieValue.includes('analytics'); 5561 } catch (error) { 5562 return false; 5563 } 5564} 5565/** 5566 * Consent providers. Each entry isolates the only things that differ between 5567 * integrations: the change-event name, how to read the *initial* analytics 5568 * consent, and how to interpret a change event's detail. Everything else 5569 * (loading/removing trackers, lifecycle) is shared by the controller. 5570 */ const $396d9f0ca7465335$var$PROVIDERS = { 5571 // Third-party CookieYes banner. 5572 cookieyes: { 5573 eventName: 'cookieyes_consent_update', 5574 hasAnalyticsConsent: (document)=>$396d9f0ca7465335$export$48d5542b9e3ba39(document), 5575 isAnalyticsAccepted: (detail)=>Array.isArray(detail?.accepted) && detail.accepted.includes('analytics') 5576 }, 5577 // LP in-house consent widget (lp-consent-widget). It exposes resolved state on 5578 // window.__lpConsent and emits `lp_consent_update` with detail.choices. 5579 'lp-consent': { 5580 eventName: 'lp_consent_update', 5581 hasAnalyticsConsent: (_document, window)=>!!window.__lpConsent?.state?.c?.analytics, 5582 isAnalyticsAccepted: (detail)=>!!detail?.choices?.analytics 5583 } 5584}; 5585class $396d9f0ca7465335$export$bb018224876724b9 extends (0, $7c391e2f7931d60d$export$3b5bd9381a52554c) { 5586 constructor(config, window, document){ 5587 super(config, window, document); 5588 this.consentListener = null; 5589 this.eventName = null; 5590 } 5591 /** 5592 * Destroy and cleanup event listeners 5593 */ destroy() { 5594 if (this.consentListener && this.eventName) { 5595 this.document.removeEventListener(this.eventName, this.consentListener); 5596 this.consentListener = null; 5597 } 5598 } 5599 /** 5600 * Load PostHog and Divolte scripts (idempotent â guarded by element id). 5601 */ loadScript() { 5602 if (!this.document.getElementById('posthog-script')) this.window.luxuryPresence.eventBus.initialize({ 5603 enabled: this.config.eventBus?.enabled 5604 }); 5605 if (!this.document.getElementById('divolte-script')) this.window.luxuryPresence.divolte.initialize({}); 5606 } 5607 /** 5608 * Remove PostHog and Divolte scripts (used on consent withdrawal). 5609 */ removeScripts() { 5610 this.window.luxuryPresence?.eventBus?.destroy?.(); 5611 this.window.luxuryPresence?.divolte?.destroy?.(); 5612 this.document.getElementById('posthog-script')?.remove(); 5613 this.document.getElementById('divolte-script')?.remove(); 5614 } 5615 /** 5616 * Initialize the consent controller for a given provider. 5617 * @param {{ provider: 'cookieyes' | 'lp-consent' }} options 5618 */ async initialize(options = {}) { 5619 const provider = $396d9f0ca7465335$var$PROVIDERS[options.provider]; 5620 if (!provider) return; 5621 this.eventName = provider.eventName; 5622 const isAuthenticated = await this.window.luxuryPresence.session.validateSession(); 5623 if (provider.hasAnalyticsConsent(this.document, this.window) || isAuthenticated) this.loadScript(); 5624 if (!this.consentListener) { 5625 this.consentListener = (eventData)=>{ 5626 if (provider.isAnalyticsAccepted(eventData.detail)) this.loadScript(); 5627 else this.removeScripts(); 5628 }; 5629 this.document.addEventListener(provider.eventName, this.consentListener); 5630 } 5631 } 5632} 5633 5634 5635/* global window */ /* eslint-disable import/prefer-default-export */ /** 5636 * Checks if the current site should redirect homeowner valuation submissions to HST. 5637 * Returns true and performs the redirect if all three gate conditions are met. 5638 * Returns false if the redirect did not fire (caller should continue with existing flow). 5639 * 5640 * @param {string} address - The human-readable address string from the form 5641 * @returns {boolean} 5642 */ function $0ae243a777665fd3$var$checkHstRedirect(address) { 5643 const { config: config } = window.luxuryPresence; 5644 if (config.hstValuationRedirectEnabled && config.mlsEnabled && config.myhomeDashboardEnabled) { 5645 window.location.href = `/home-search/home-valuation?address=${encodeURIComponent(address)}`; 5646 return true; 5647 } 5648 return false;
5649} 5650const $0ae243a777665fd3$export$4225ff17959c7313 = { 5651 checkHstRedirect: $0ae243a777665fd3$var$checkHstRedirect, 5652 destroy () {} 5653}; 5654 5655 5656const $fa0280e505379701$export$1fd2b467a3644d37 = new (0, $dc851cf3939b6ef5$export$ff0712c26d5458f7)({}); 5657const $fa0280e505379701$export$e12694e911a05f40 = new (0, $0ead03fdb95fa9ce$export$d507f25e63650365)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5658const $fa0280e505379701$export$3de614e59a842917 = new (0, $d48f9f944810f613$export$ca3218b7861b9cb0)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5659const $fa0280e505379701$export$fb9b298fdbf31455 = new (0, $68a2d4aa500c7a05$export$61ec8f2b6291ec31)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5660const $fa0280e505379701$export$178cc3119b453c2a = new (0, $e10bd00497be8876$export$3c5380623cf51249)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5661const $fa0280e505379701$export$9376af1a01686f2 = new (0, $ea6901fdf47e0ec1$export$3c19195edca3fa5c)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5662const $fa0280e505379701$export$94d36f806562393e = new (0, $0a0ad49f13c0b8fd$export$ba9afeb75f20f616)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5663const $fa0280e505379701$export$89e66d1faf94651e = new (0, $2b1790aa32f109d1$export$43e435c053a109f6)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5664const $fa0280e505379701$export$7743b07270cd6d6c = new (0, $4f184d9bd3037f15$export$7a6215890afba974)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5665const $fa0280e505379701$export$40a7039551318c37 = new (0, $102039871668a1df$export$e22e4b1be0bb6c61)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5666const $fa0280e505379701$export$8a0bbf7e7652fcfc = new (0, $0d25a3fa2e0f4f92$export$b718a981691eae5c)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5667const $fa0280e505379701$export$b313b3f6544c97a3 = new (0, $dcf72769f009ff26$export$b900d6fe921fd49c)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5668const $fa0280e505379701$export$b526bc4ac03268ef = new (0, $50eefeef8d1f2372$export$8a2bf06fbae4dde)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5669const $fa0280e505379701$export$c0affdb0a7a2ef6 = new (0, $396d9f0ca7465335$export$bb018224876724b9)($fa0280e505379701$export$1fd2b467a3644d37, window, document); 5670 5671 5672/** 5673 * Attach controller to window for usage 5674 * @param {string} key 5675 * @param {any} controller 5676 */ function $89a8a84b77163415$var$attachController(key, controller) { 5677 if (window.luxuryPresence[key]) try { 5678 // New version of sdk, destroy previous 5679 window.luxuryPresence[key].destroy(); 5680 } catch (e) { 5681 // eslint-disable-next-line no-console 5682 console.log(e); 5683 } 5684 window.luxuryPresence[key] = controller; 5685} 5686$89a8a84b77163415$var$attachController('config', (0, $fa0280e505379701$export$1fd2b467a3644d37)); 5687$89a8a84b77163415$var$attachController('modals', (0, $fa0280e505379701$export$e12694e911a05f40)); 5688$89a8a84b77163415$var$attachController('buttons', (0, $fa0280e505379701$export$3de614e59a842917)); 5689$89a8a84b77163415$var$attachController('validation', (0, $fa0280e505379701$export$fb9b298fdbf31455)); 5690$89a8a84b77163415$var$attachController('contactForms', (0, $fa0280e505379701$export$178cc3119b453c2a)); 5691$89a8a84b77163415$var$attachController('mapApiLoader', (0, $fa0280e505379701$export$9376af1a01686f2)); 5692$89a8a84b77163415$var$attachController('pagination', (0, $fa0280e505379701$export$94d36f806562393e)); 5693$89a8a84b77163415$var$attachController('expandSliders', (0, $fa0280e505379701$export$89e66d1faf94651e)); 5694$89a8a84b77163415$var$attachController('divolte', (0, $fa0280e505379701$export$7743b07270cd6d6c)); 5695$89a8a84b77163415$var$attachController('eventBus', (0, $fa0280e505379701$export$40a7039551318c37)); 5696$89a8a84b77163415$var$attachController('oauth', (0, $fa0280e505379701$export$8a0bbf7e7652fcfc)); 5697$89a8a84b77163415$var$attachController('qualifyingQuestionsModal', (0, $fa0280e505379701$export$b313b3f6544c97a3)); 5698$89a8a84b77163415$var$attachController('session', (0, $fa0280e505379701$export$b526bc4ac03268ef)); 5699$89a8a84b77163415$var$attachController('consent', (0, $fa0280e505379701$export$c0affdb0a7a2ef6)); 5700$89a8a84b77163415$var$attachController('redirects', (0, $0ae243a777665fd3$export$4225ff17959c7313)); 5701// methods for existing elements (can be removed later after elements updated) 5702window.luxuryPresence.formatSliderPriceRange = (0, $fa0280e505379701$export$94d36f806562393e).formatSliderPriceRange.bind((0, $fa0280e505379701$export$94d36f806562393e)); 5703window.luxuryPresence.formatSliderAreaRange = (0, $fa0280e505379701$export$94d36f806562393e).formatSliderAreaRange.bind((0, $fa0280e505379701$export$94d36f806562393e)); 5704// method below doesn't use 'this', but just to be safe in case of further method updates 5705window.luxuryPresence.getSearchFormValues = (0, $fa0280e505379701$export$94d36f806562393e).getSearchFormValues.bind((0, $fa0280e505379701$export$94d36f806562393e)); 5706window.luxuryPresence.handlebarsHelpersFactory = function(handlebarsInstance) { 5707 return (0, (/*@__PURE__*/$parcel$interopDefault($53de3c160faf5a81$exports
5707)))(handlebarsInstance, { 5708 isEqual (a, b) { 5709 // eslint-disable-next-line 5710 return a == b; 5711 } 5712 }); 5713}; 5714 5715 5716 5717})(); 5718//# sourceMappingURL=lp-sdk.js.map 5719 5720 </script>
5720 5721 5722
5722<script> 5723 var lpGlobalInitialized = false; 5724 5725 function lpGlobalInit () { 5726 if (lpGlobalInitialized) { 5727 return; 5728 } 5729 lpGlobalInitialized = true; 5730 // Initialize wow animation plugin only according to turbolinks 5731 var wow; 5732 if (window.WOW) { 5733 wow = new WOW({ 5734 animateClass: 'animated', 5735 offset: wowOffset, 5736 live: false, 5737 callback: function(box) {} 5738 }); 5739 } 5740 // Initialize handlebar helpers only once 5741 function handlebarsInit() { 5742 if (!window.Handlebars) { 5743 return; 5744 } 5745 HandlebarsIntl.registerWith(Handlebars); 5746 Handlebars.registerHelper(window.luxuryPresence.handlebarsHelpersFactory(Handlebars)); 5747 } 5748 5749 handlebarsInit(); 5750 5751 var modalContentUrl = "/modals.html"; 5752 const modalsContainer = document.getElementById('modals'); 5753 if (modalsContainer) { 5754 fetch(modalContentUrl).then(function(res) { 5755 if (!res.ok) { 5756 throw new Error(`HTTP error! Status: ${res.status}`); 5757 } 5758 return res.text(); 5759 }).then(function(resultText) { 5760 modalsContainer.innerHTML = resultText; 5761 5762 // now we need to execute all script elements 5763 Array.from(modalsContainer.getElementsByTagName('script')).forEach(function (s) { 5764 const script = document.createElement("script"); 5765 script.text = s.innerHTML; 5766 Array.from(s.attributes).forEach(function (a) { 5767 script.setAttribute(a.name, a.value); 5768 }) 5769 s.parentNode.replaceChild(script, s); 5770 }); 5771 5772 try { 5773 window.luxuryPresence.modals.initialize(window.luxuryPresence._modalIncludes); 5774 window.luxuryPresence.contactForms.initialize({ selector: '#modals' }); 5775 window.luxuryPresence.validation.initialize({ selector: '#modals' }); 5776 window.luxuryPresence.oauth.initialize({ 5777 googleSignOnEnabled: true, 5778 iframe: false }); 5779 } catch (e) { 5780 console.log(e); 5781 } 5782 document.querySelectorAll('.modals > .modal .close').forEach(closeModalBtn => { 5783 closeModalBtn.addEventListener('click', function() { 5784 window.lpUI.hideClosestModal(closeModalBtn); 5785 }); 5786 }); 5787 }).catch((e) => console.log(e)); 5788 } 5789 /* Initialize Luxury Presence SDK */ 5790 try { 5791 window.luxuryPresence.config.setCompany("c192c24d-68d5-41fb-b04a-e3c9703e46be", {}); 5792 window.luxuryPresence.config.setWebsite("3dfcdeb5-d5fa-4659-a16f-19b36b8f2e9c", { 5793 myhomeDashboardEnabled: false, 5794 mlsEnabled: true, 5795 hstValuationRedirectEnabled: true 5796 }); 5797 const url = new URL(window.location.href); 5798 const shareId = url.searchParams.get('shareId'); 5799 window.luxuryPresence.config.setPage("5f9be058-e520-4a70-90e6-1eb622bddb2c", { 5800 sourceResource: "", 5801 pageElementId: "", 5802 pageQueryVariables: {}, 5803 shareId: "", 5804 }); 5805 window.luxuryPresence.config.setWebsiteApiGatewayUrl("https://wgw.luxurypresence.com", {}); 5806 window.luxuryPresence.config.setBuyerSellerServiceUrl("https://bss.luxurypresence.com", {}); 5807 window.luxuryPresence.config.setDivolteServiceUrl("https://t.luxurypresence.com", {}); 5808 window.luxuryPresence.config.setEventBusUrl("https://cdn.luxurypresence.com/scripts/event-bus-js", {}); 5809 window.luxuryPresence.config.setEventBus({ 5810 enabled: true, 5811 apiKey: "phc_PMYT31xlmXBaTCwpIRx1v6RrpLVZIuP47N3mOT6KLnr", 5812 url: "https://p.luxurypresence.com", 5813 }); 5814 window.luxuryPresence.config.setTemplateId("34ae9410-e2da-4ccb-947e-bdaa3b48f731", {}); 5815 window.luxuryPresence.config.setLeadIngesterUrl("https://leads.luxurypresence.com", {}); 5816 window.luxuryPresence.buttons.initialize({}); 5817 window.luxuryPresence.eventBus.initialize({}); 5818 window.luxuryPresence.contactForms.initialize({}); 5819 window.luxuryPresence.validation.initialize({}); 5820 window.luxuryPresence.expandSliders.initialize({}); 5821 window.luxuryPresence.oauth.initialize({ googleSignOnEnabled: true, iframe: false }); 5822 window.luxuryPresence.qualifyingQuestionsModal.initialize({ qualifyingQuestionsModalEnabled: true }); 5823 window.luxuryPresence.divolte.initialize({}); 5824 } catch (e) { 5825 console.log(e); 5826 } 5827 5828 /* Inject Section Specific Javascript */ 5829 try { 5830(function init(sectionDomId) { 5831 function setHttp(link) { 5832 if (link.search(/^http[s]?\:\/\/|\//) == -1) { 5833 link = 'https://' + link; 5834 } 5835 return link; 5836 } 5837 const socialLinks = document.querySelectorAll('#' + sectionDomId + ' .socials__item, #' + sectionDomId + ' .lp-socials__link'); 5838 socialLinks.forEach(linkElement => { 5839 const href = linkElement.getAttribute('href'); 5840 if (href) { 5841 linkElement.setAttribute('href', setHttp(href)); 5842 } 5843 }); 5844 $("#" + sectionDomId + " form").on("reset", function () { 5845 const redirectLink = $('#' + sectionDomId + ' .redirect-link'); 5846 if (redirectLink.length) { 5847 const rawHref = redirectLink.attr('href'); 5848 redirectLink.attr('href', setHttp(rawHref)); 5849 redirectLink[0].click(); 5850 } 5851 }); 5852})('modal-global-contact-us'); 5853} catch(e) { 5854console.log(e); 5855} 5856 5857 try { 5858(function init(sectionDomId) { 5859 var resizeMenu = function () { 5860 var widthSoFar = 0; 5861 var availableWidth = $('#' + sectionDomId + ' .navigation').width(); 5862 if ($(window).width() > 1024) { 5863 $('#' + sectionDomId + ' .navigation > li').each(function () { 5864 $(this).hide(); 5865 const currentItemWidth = $(this).outerWidth(); 5866 if (availableWidth - widthSoFar >= currentItemWidth) $(this).css({ 5867 "visibility": "visible", 5868 "display": "list-item", 5869 "height": "auto" 5870 }); 5871 widthSoFar += $(this).outerWidth(); 5872 }); 5873 } 5874 }; 5875 $(window).on('resize.lpui-auto-clean', resizeMenu); 5876 const mediaQuery = window.matchMedia('(hover: hover) and (pointer: fine)'); 5877 var $subNavTrigger = $('body > nav .sub-nav-container a'); 5878 var $subNavContainer = $('body > nav .sub-nav-container'); 5879 if (mediaQuery.matches) { 5880 $subNavTrigger.off('click'); 5881 $subNavContainer.mouseout(function () { 5882 var self = $(this); 5883 self.removeClass('active').find('.sub-nav').removeClass('visible'); 5884 }).mouseover(function () { 5885 $(this).siblings('.sub-nav-container').removeClass('active').find('.sub-nav').removeClass('visible'); 5886 $(this).addClass('active').find('.sub-nav').addClass('visible'); 5887 }).mouseup(function () { 5888 var self = $(this); 5889 self.toggleClass('active'); 5890 }); 5891 } 5892 function isSectionLight(sect) { 5893 if (!sect || !sect.style) { 5894 return true; 5895 } 5896 if (sect.style.backgroundImage) { 5897 return false;
5898 } 5899 if ($(sect).children('.video-wrapper').length) { 5900 return false; 5901 } 5902 return sect.classList.contains('is-background-color-light'); 5903 } 5904 const $header = $(`#${sectionDomId} > .header`); 5905 if ($header.hasClass('theme-auto')) { 5906 if (isSectionLight($('body > section')[0])) { 5907 $header.removeClass('theme-light'); 5908 } else { 5909 $header.addClass('theme-light'); 5910 } 5911 } 5912 var resizeTimeout; 5913 clearTimeout(resizeTimeout); 5914 resizeTimeout = setTimeout(function () { 5915 resizeMenu(); 5916 }, 1000); 5917})('global-navbar'); 5918} catch(e) { 5919console.log(e); 5920} 5921 try { 5922(function init(sectionDomId, options) { 5923 var elementSelector = options.elementSelector || 'nav'; 5924 var element = document.querySelector(elementSelector); 5925 var sections = document.querySelectorAll('body > section'); 5926 var subNavContainers = element.querySelectorAll('.sub-nav'); 5927 var initialBackgroundColor = options.initialBackgroundColor || element.style.backgroundColor; 5928 var backgroundColorScroll = options.backgroundColorScroll || '#191919'; 5929 var fontColor = options.fontColor || '#fff'; 5930 var fontColorScroll = options.fontColorScroll || '#000'; 5931 var didScroll = false; 5932 var lastScrollTop = 0; 5933 var delta = 5; 5934 5935 // eslint-disable-next-line sonarjs/no-collapsible-if 5936 if (wow) { 5937 // Wowjs might not trigger for position fixed elements 5938 if (window.scrollY > 0) { 5939 element.querySelectorAll('.wow').forEach(el => wow.show(el)); 5940 } 5941 } 5942 function adjustNavPinState() { 5943 // Remove 'visible' class from all subNavContainers 5944 for (let i = 0; i < subNavContainers.length; i++) { 5945 subNavContainers[i].classList.remove('visible'); 5946 } 5947 if (window.scrollY > 0) { 5948 element.style.backgroundColor = backgroundColorScroll; 5949 element.style.color = fontColorScroll; 5950 element.classList.add('scroll'); 5951 } else { 5952 element.style.backgroundColor = initialBackgroundColor; 5953 element.style.color = fontColor; 5954 element.classList.remove('scroll'); 5955 } 5956 } 5957 adjustNavPinState(); 5958 function onScroll() { 5959 didScroll = true; 5960 } 5961 window.addEventListener('scroll', onScroll); 5962 5963 // eslint-disable-next-line 5964 var debounceInterval = setInterval(() => { 5965 if (didScroll) { 5966 // eslint-disable-next-line 5967 hasScrolled(); 5968 didScroll = false; 5969 } 5970 }, 250); 5971 function hasScrolled() { 5972 adjustNavPinState(); 5973 // eslint-disable-next-line 5974 var navbarHeight = element.offsetHeight; 5975 // eslint-disable-next-line 5976 var st = window.scrollY; 5977 5978 // Make sure they scroll more than delta 5979 if (Math.abs(lastScrollTop - st) <= delta) { 5980 return; 5981 } 5982 if (st > lastScrollTop && st > navbarHeight) { 5983 // Scroll Down 5984 element.style.transform = `translateY(-${navbarHeight}px) scaleY(0)`; 5985 document.documentElement.style.setProperty('--global-header-height', '0px'); 5986 5987 // Some sections "follow" the navbar with class sticky (i.e. Producer search) 5988 sections.forEach(section => { 5989 if (section.classList.contains('sticky')) { 5990 section.style.top = '0px'; 5991 } 5992 }); 5993 } else { 5994 // Scroll Up 5995 // eslint-disable-next-line 5996 if (st + window.innerHeight < document.documentElement.scrollHeight) { 5997 element.style.transform = `translateY(0) scaleY(1)`; 5998 document.documentElement.style.setProperty('--global-header-height', `${navbarHeight}px`); 5999 sections.forEach(section => { 6000 if (section.classList.contains('sticky')) { 6001 section.style.top = `${navbarHeight}px`; 6002 } 6003 }); 6004 } 6005 } 6006 lastScrollTop = st; 6007 } 6008})('NAVBAR', JSON.parse("{\"fontColor\":\"#211F1F\",\"elementSelector\":\"nav\",\"fontColorScroll\":\"#ffffff\",\"backgroundColorScroll\":\"#2C3426\",\"initialBackgroundColor\":\"transparent\"}")); 6009} catch(e) { 6010console.log(e); 6011} 6012 try { 6013(function init(sectionDomId) { 6014 $('body > div.sidemenu .sub-nav-container > a').click(function (e) { 6015 $(this).closest('.sub-nav-container').toggleClass('active'); 6016 }); 6017 var $sidemenu = $('#' + sectionDomId); 6018 var shown = false; 6019 function onShow() { 6020 if (shown) { 6021 return; 6022 } 6023 shown = true; 6024 window.lpUI.requestScrollLock(sectionDomId); 6025 } 6026 function onHide() { 6027 if (!shown) { 6028 return; 6029 } 6030 shown = false;
6031 window.lpUI.releaseScrollLock(sectionDomId); 6032 } 6033 $sidemenu.on('lpui-show', onShow); 6034 $sidemenu.on('lpui-hide', onHide); 6035 function handleLinkClick(href) { 6036 if (href && href.match(/^#[^#].*$/)) { 6037 window.lpUI.sideMenuHide(); 6038 } 6039 } 6040 $sidemenu.find('.navigation__link, .sub-nav__link').on('click', function () { 6041 handleLinkClick($(this).attr('href')); 6042 }); 6043})('global-sidemenu'); 6044} catch(e) { 6045console.log(e); 6046} 6047 6048 try { 6049(function init(sectionDomId) { 6050 function setHttp(link) { 6051 if (link.search(/^http[s]?\:\/\/|\//) == -1) { 6052 link = 'http://' + link; 6053 } 6054 return link; 6055 } 6056 $(`#${sectionDomId} form`).on("reset", function () { 6057 const redirectLink = $('#' + sectionDomId + ' .redirect-link'); 6058 if (redirectLink.length) { 6059 const rawHref = redirectLink.attr('href'); 6060 redirectLink.attr('href', setHttp(rawHref)); 6061 redirectLink[0].click(); 6062 } 6063 }); 6064})('global-footer'); 6065} catch(e) { 6066console.log(e); 6067} 6068 6069 try { 6070(function init(sectionDomId) { 6071 window.luxuryPresence.mapApiLoader.load().then(() => { 6072 const $section = $('#' + sectionDomId); 6073 const $mobileContacts = $section.find('.mobile-contact'); 6074 const $searchButton = $section.find('.search-button'); 6075 if (!$searchButton.length) { 6076 return; 6077 } 6078 const searchMls = $searchButton[0].dataset.searchMode === 'Search MLS' || $searchButton[0].dataset.searchMode === 'Search My Properties and MLS'; 6079 const searchProperties = $searchButton[0].dataset.searchMode === 'Search My Properties' || $searchButton[0].dataset.searchMode === 'Search My Properties and MLS'; 6080 const searchPlaces = searchMls; 6081 if (!searchMls && !searchProperties) { 6082 return; 6083 } 6084 const $searchWrapper = $section.find('.search-wrapper'); 6085 const $searchInput = $section.find('.search-input'); 6086 const $searchResults = $section.find('.search-results'); 6087 const $resultsContainer = $section.find('.results-container'); 6088 const $loader = $section.find('.search-in-progress'); 6089 const $navBar = $section.find('.nav.navbar-nav'); 6090 const $navBarHeader = $section.find('.navbar-header'); 6091 const searchDelay = 300; 6092 const maxPlaces = 3; 6093 const service = new google.maps.places.AutocompleteService(); 6094 const geocoder = new google.maps.Geocoder(); 6095 function updateResultsVisibility() { 6096 if ($resultsContainer.html()) { 6097 $resultsContainer.show(); 6098 } else { 6099 $resultsContainer.hide(); 6100 } 6101 var loaderHeight = $loader[0].getBoundingClientRect().height; 6102 var resultsHeight = $resultsContainer[0].getBoundingClientRect().height; 6103 $searchResults.css('height', loaderHeight + resultsHeight + 'px'); 6104 } 6105 function showLoading() { 6106 if (!$resultsContainer.html()) { 6107 $loader.removeClass('not-visible'); 6108 } 6109 updateResultsVisibility(); 6110 } 6111 function hideLoading() { 6112 $loader.addClass('not-visible'); 6113 updateResultsVisibility(); 6114 } 6115 var newSearchTimer; 6116 function inputChanged() { 6117 window.clearTimeout(newSearchTimer); 6118 newSearchTimer = window.setTimeout(startSearch, searchDelay); 6119 } 6120 var keyword; 6121 function startSearch() { 6122 const term = $searchInput.val(); 6123 if (term === keyword) { 6124 return; 6125 } 6126 keyword = term; 6127 if (term) { 6128 doSearch(term); 6129 } else { 6130 setResults(null); 6131 } 6132 } 6133 function mlsSearch(term) { 6134 return window.luxuryPresence.getMLSAutocomplete(term).then(function (result) { 6135 if (Array.isArray(result)) { 6136 result.forEach(function (item, idx) { 6137 item.__idx = idx; 6138 item.__status_idx = item.status === 'Sold' ? 2 : 1; 6139 }); 6140 result.sort(function (a, b) { 6141 const dif = a.__status_idx - b.__status_idx; 6142 if (dif === 0) { 6143 return a.__idx - b.__idx; 6144 } 6145 return dif; 6146 }); 6147 } 6148 return result; 6149 }).catch(function (e) { 6150 console.log(e); 6151 return []; 6152 }); 6153 } 6154 function resolveGeoBounds(placeId, description) { 6155 return new Promise(function (resolve, reject) { 6156 geocoder.geocode({ 6157 'placeId': placeId 6158 }, function (results, status) { 6159 if (status != 'OK') { 6160 return resolve(null); 6161 } 6162 var result = results[0]; 6163 var bounds = new google.maps.LatLngBounds();
6164 bounds.extend(result.geometry.viewport.getSouthWest()); 6165 bounds.extend(result.geometry.viewport.getNorthEast()); 6166 result.geometry.bounds = bounds.toJSON(); 6167 var placeUrl = window.luxuryPresence.makeMlsLink(result); 6168 return resolve({ 6169 placeUrl: placeUrl, 6170 description: description 6171 }); 6172 }); 6173 }); 6174 } 6175 function placesSearch(term) { 6176 var request = { 6177 input: term, 6178 componentRestrictions: { 6179 country: 'us' 6180 }, 6181 types: ['(regions)'], 6182 limit: 1 6183 }; 6184 return new Promise(function (resolve, reject) { 6185 service.getPlacePredictions(request, function (results, status) { 6186 if (term !== keyword) { 6187 return resolve([]); 6188 } 6189 if (status === google.maps.places.PlacesServiceStatus.OK) { 6190 var geoResultPromises = results.slice(0, maxPlaces).map(function (result) { 6191 return resolveGeoBounds(result.place_id, result.description); 6192 }); 6193 Promise.all(geoResultPromises).then(function (geoLinks) { 6194 return resolve(geoLinks.filter(function (i) { 6195 return i; 6196 })); 6197 }); 6198 } else { 6199 return resolve([]); 6200 } 6201 }); 6202 }); 6203 } 6204 function propertiesSearch(term) { 6205 var payload = { 6206 companyId: window.luxuryPresence.defaults.companyId, 6207 search: term, 6208 offset: 0, 6209 limit: 6, 6210 statusIds: ["5f528253-abb7-484e-95c3-330269ac1105", "959c11cf-8655-4f91-874c-292b0ab7ea6b", "a0012964-4f51-4430-abf8-6547c5ab6441", "df04ccbe-4621-4140-a504-ee1a17430bb7", "88b4ace6-f39b-4b25-a051-8f6dba976833", "96031d77-bbe5-4de3-90d8-1e4e70de8ca8"] 6211 }; 6212 return superagent.post(window.luxuryPresence.defaults.apiGatewayUrl + '/graphql').send({ 6213 query: window.luxuryPresence.defaults.gql.properties, 6214 variables: payload 6215 }).then(function (res) { 6216 return (res.body.data || {}).properties || []; 6217 }, function (err) { 6218 return []; 6219 }); 6220 } 6221 function doSearch(term) { 6222 showLoading(); 6223 Promise.all([searchMls ? mlsSearch(term) : [], searchPlaces ? placesSearch(term) : [], searchProperties ? propertiesSearch(term) : []]).then(function (res) { 6224 if (term !== keyword) { 6225 return; 6226 } 6227 setResults(res[0], res[1], res[2]); 6228 }); 6229 } 6230 function setResults(mlsResults, placesResults, propertiesResults) { 6231 hideLoading(); 6232 if (!mlsResults) { 6233 $resultsContainer.html(''); 6234 updateResultsVisibility(); 6235 return; 6236 } 6237 if (!mlsResults.length && !placesResults.length && !propertiesResults.length) { 6238 $resultsContainer.html('<div class="nothing-found">No results found</div>'); 6239 updateResultsVisibility(); 6240 return; 6241 } 6242 var propertiesHtml = propertiesResults.reduce(function (acc, result) { 6243 acc += `<a href="/properties/${result.slug}" class="results-link result-self">${result.privateAddress ? result.name : result.fullAddress}</a>`; 6244 return acc; 6245 }, ''); 6246 var placesHtml = placesResults.reduce(function (acc, result) { 6247 acc += `<a class="results-link result-place" href="${result.placeUrl}">${result.description}</a>`; 6248 return acc; 6249 }, ''); 6250 var mlsHtml = mlsResults.reduce(function (acc, result) { 6251 acc += `<a href="/home-search/listings/${result.id}" class="results-link result-search">${result.display_address}</a>`; 6252 return acc; 6253 }, ''); 6254 $resultsContainer.html(propertiesHtml + mlsHtml + placesHtml); 6255 updateResultsVisibility(); 6256 } 6257 $searchInput.on('keyup', inputChanged); 6258 function toggleSearch() { 6259 if ($searchButton.hasClass('active')) { 6260 $searchButton.removeClass('active'); 6261 $searchWrapper.removeClass('active'); 6262 $searchInput.val(''); 6263 setResults(null); 6264 $mobileContacts[0].style.zIndex = ''; 6265 } else { 6266 $mobileContacts[0].style.zIndex = '102'; 6267 $searchButton.addClass('active');
6268 $searchWrapper.addClass('active'); 6269 } 6270 } 6271 $searchButton.on('click', toggleSearch); 6272 }); 6273})('global-mobile-contact'); 6274} catch(e) { 6275console.log(e); 6276} 6277 6278 try { 6279(function init(sectionDomId) { 6280 const $section = $('#' + sectionDomId); 6281 const $videoWrap = $section.find('.full-screen-video-component > .video-wrapper'); 6282 const $playButton = $section.find('.js-play-btn'); 6283 if ($videoWrap.length) { 6284 const $video = $videoWrap.find('video'); 6285 $video.each(function () { 6286 var v = this; 6287 if (v.readyState > 0) { 6288 $videoWrap.addClass('playing'); 6289 var promise = v.play(); 6290 if (promise !== undefined) { 6291 promise.catch(error => { 6292 $playButton.addClass('visible'); 6293 }).then(() => {}); 6294 } 6295 } else { 6296 v.addEventListener('canplay', function () { 6297 $videoWrap.addClass('playing'); 6298 }, { 6299 once: true 6300 }); 6301 } 6302 }); 6303 } 6304 $playButton.on('click', function () { 6305 const $video = $videoWrap.find('video'); 6306 this.classList.remove('visible'); 6307 if ($video[0].currentTime === 0) { 6308 $video[0].load(); 6309 $video[0].play(); 6310 } 6311 }); 6312 window.luxuryPresence.mapApiLoader.load().then(() => { 6313 const $searchWrapper = $section.find('.search-wrapper'); 6314 if (!$searchWrapper.length) { 6315 return; 6316 } 6317 const searchMls = $searchWrapper[0].dataset.searchMls === 'true'; 6318 const searchProperties = $searchWrapper[0].dataset.searchProperties === 'true'; 6319 const searchPlaces = searchMls; 6320 const showNeighborhoods = searchMls; 6321 const searchNearEnabled = searchMls; 6322 const $searchInput = $section.find('.search-input'); 6323 const $searchResults = $section.find('.search-results'); 6324 const $resultsContainer = $section.find('.results-container'); 6325 const $loader = $section.find('.search-in-progress'); 6326 const $predefined = $section.find('.predefined-links'); 6327 const $searchBtn = $section.find('.search-button'); 6328 const $leaseFalseButton = $section.find('.jsLeaseFalse'); 6329 const $leaseTrueButton = $section.find('.jsLeaseTrue'); 6330 const $nextSection = $section.next(); 6331 const fixZIndex = $nextSection.length && parseInt($nextSection.css('z-index')) || 1; 6332 const searchDelay = 300; 6333 const maxPlaces = 3; 6334 const maxMls = 5; 6335 const leaseFilter = $leaseFalseButton.length > 0 && $leaseTrueButton.length > 0; 6336 const service = new google.maps.places.AutocompleteService(); 6337 const geocoder = new google.maps.Geocoder(); 6338 var keyword; 6339 var leasePropertyState = false; 6340 var leasePropertySearched; 6341 var searchActive = false; 6342 var isLoading = false; 6343 function showSearchResults() { 6344 searchActive = true; 6345 updateSearchDisplay(); 6346 } 6347 function hideSearchResults() { 6348 searchActive = false; 6349 updateSearchDisplay(); 6350 } 6351 function showLoading() { 6352 isLoading = true; 6353 updateSearchDisplay(); 6354 } 6355 function hideLoading() { 6356 isLoading = false; 6357 updateSearchDisplay(); 6358 } 6359 function updateSearchDisplay() { 6360 if (leaseFilter) { 6361 if (leasePropertyState) { 6362 $leaseTrueButton.addClass('active'); 6363 $leaseFalseButton.removeClass('active'); 6364 } else { 6365 $leaseFalseButton.addClass('active'); 6366 $leaseTrueButton.removeClass('active'); 6367 } 6368 } 6369 if (!searchActive) { 6370 $searchResults.removeClass('show'); 6371 $searchResults.css('height', '0'); 6372 return; 6373 } 6374 var hasResults = !!$resultsContainer.html(); 6375 var hasPredefined = $predefined.find('a:not(.not-processed)').length > 0; 6376 if (hasResults) { 6377 $predefined.addClass('not-visible'); 6378 $loader.addClass('not-visible'); 6379 $resultsContainer.removeClass('not-visible'); 6380 } else if (isLoading) { 6381 $resultsContainer.addClass('not-visible'); 6382 $predefined.addClass('not-visible'); 6383 $loader.removeClass('not-visible'); 6384 } else if (hasPredefined) { 6385 $resultsContainer.addClass('not-visible'); 6386 $loader.addClass('not-visible'); 6387 $predefined.removeClass('not-visible'); 6388 } else { 6389 $resultsContainer.addClass('not-visible'); 6390 $loader.addClass('not-visible'); 6391 $predefined.addClass('not-visible'); 6392 } 6393 var height = 0; 6394 height += $predefined[0].getBoundingClientRect().height; 6395 height += $resultsContainer[0].getBoundingClientRect().height; 6396 height += $loader[0].getBoundingClientRect().height; 6397 if (height > 0) { 6398 $searchResults.addClass('show'); 6399 } else { 6400 $searchResults.removeClass('show'); 6401 } 6402 $searchResults.css('height', height + 'px'); 6403 } 6404 function clearSelection() { 6405 $searchResults.find('.selected-link').removeClass('selected-link'); 6406 } 6407 function moveSelection(up) { 6408 var $cont = $resultsContainer.html() ? $resultsContainer : $predefined; 6409 var $links = $cont.find('.results-link'); 6410 if (!$links.length) { 6411 return; 6412 } 6413 var idx = -1; 6414 $links.each(function (i) { 6415 if (idx === -1 && $(this).is('.selected-link')) { 6416 idx = i; 6417 } 6418 }); 6419 var newIdx; 6420 if (up) { 6421 newIdx = idx - 1; 6422 if (newIdx < 0) { 6423 newIdx = $links.length - 1; 6424 } 6425 } else { 6426 newIdx = idx + 1; 6427 if (newIdx > $links.length - 1) { 6428 newIdx = 0; 6429 } 6430 } 6431 if (newIdx !== idx) { 6432 $searchResults.find('.selected-link').removeClass('selected-link'); 6433 $($links.get(newIdx)).addClass('selected-link'); 6434 } 6435 } 6436 var newSearchTimer; 6437 function inputChanged(ev) { 6438 if (ev.which === 38) { 6439 ev.preventDefault(); 6440 moveSelection(true); 6441 return false;
6442 } 6443 if (ev.which === 40) { 6444 ev.preventDefault(); 6445 moveSelection(); 6446 return false; 6447 } 6448 if (ev.which === 13) { 6449 $lnk = $searchResults.find('.selected-link'); 6450 if ($lnk.length) { 6451 $lnk[0].click(); 6452 hideSearchResults(); 6453 } else { 6454 $searchBtn.click(); 6455 } 6456 } 6457 window.clearTimeout(newSearchTimer); 6458 newSearchTimer = window.setTimeout(startSearch, searchDelay); 6459 } 6460 function startSearch() { 6461 const term = $searchInput.val(); 6462 if (term === keyword && leasePropertySearched === leasePropertyState) { 6463 return; 6464 } 6465 leasePropertySearched = leasePropertyState; 6466 keyword = term; 6467 if (term) { 6468 doSearch(term, leasePropertySearched); 6469 } else { 6470 setResults(null); 6471 } 6472 } 6473 function mlsSearch(term, leaseProperty) { 6474 var query = { 6475 keyword_search: term, 6476 limit: maxMls 6477 }; 6478 if (leaseFilter && leaseProperty) { 6479 query.lease_property = true; 6480 } 6481 return superagent.get(window.location.protocol + '//' + window.location.host + '/home-search/listings.json').query(query).then(function (res) { 6482 if (!Array.isArray(res.body)) { 6483 return []; 6484 } 6485 return res.body.map(function (item) { 6486 return { 6487 id: item.id, 6488 display_address: [item.address_1, item.city, [item.state, item.postal_code].filter(function (i) { 6489 return i; 6490 }).join(' ')].filter(function (i) { 6491 return i; 6492 }).join(', ') 6493 }; 6494 }); 6495 }, function (e) { 6496 console.log(e); 6497 return []; 6498 }); 6499 } 6500 function resolveGeoBounds(placeId, description, terms) { 6501 return new Promise(function (resolve, reject) { 6502 geocoder.geocode({ 6503 'placeId': placeId 6504 }, function (results, status) { 6505 if (status != 'OK') { 6506 return resolve(null); 6507 } 6508 var result = results[0]; 6509 var bounds = new google.maps.LatLngBounds();
6510 bounds.extend(result.geometry.viewport.getSouthWest()); 6511 bounds.extend(result.geometry.viewport.getNorthEast()); 6512 result.geometry.bounds = bounds.toJSON(); 6513 var placeUrl = window.luxuryPresence.makeMlsLink(result); 6514 return resolve({ 6515 placeUrl: placeUrl, 6516 description: description, 6517 cityName: terms[0].value, 6518 stateName: terms[1].value 6519 }); 6520 }); 6521 }); 6522 } 6523 function resolveAutocomplete(term, deeper) { 6524 var request = { 6525 input: term, 6526 componentRestrictions: { 6527 country: 'us' 6528 }, 6529 types: deeper ? ['geocode'] : ['(regions)'], 6530 limit: 1 6531 }; 6532 return new Promise(function (resolve, reject) { 6533 service.getPlacePredictions(request, function (results, status) { 6534 if (status !== google.maps.places.PlacesServiceStatus.OK) { 6535 resolve(null); 6536 return; 6537 } 6538 if (!Array.isArray(results)) { 6539 resolve(null); 6540 return; 6541 } 6542 if (deeper) { 6543 var allowedTypes = { 6544 'neighborhood': true, 6545 'administrative_area_level_3': true, 6546 'administrative_area_level_4': true, 6547 'administrative_area_level_5': true, 6548 'sublocality_level_1': true, 6549 'sublocality_level_2': true, 6550 'sublocality_level_3': true 6551 }; 6552 results = results.filter(function (res) { 6553 return res.types.find(t => allowedTypes[t]); 6554 }); 6555 } 6556 if (!results.length) { 6557 resolve(null); 6558 return; 6559 } 6560 resolve(results); 6561 }); 6562 }); 6563 } 6564 var placesResult = {}; 6565 function placesSearch(term, ignoreInput) { 6566 if (placesResult.term !== term) { 6567 placesResult = { 6568 term: term, 6569 result: resolveAutocomplete(term).then(function (results) { 6570 if (!ignoreInput && term !== keyword) { 6571 return null; 6572 } 6573 if (ignoreInput && !results) { 6574 return resolveAutocomplete(term, true); 6575 } 6576 return results; 6577 }).then(function (results) { 6578 if (!ignoreInput && term !== keyword) { 6579 return []; 6580 } 6581 if (!results) { 6582 return []; 6583 } 6584 var geoResultPromises = results.map(function (result) { 6585 return resolveGeoBounds(result.place_id, result.description, result.terms); 6586 }); 6587 return Promise.all(geoResultPromises).then(function (geoLinks) { 6588 return geoLinks.filter(function (i) { 6589 return i; 6590 }).slice(0, maxPlaces); 6591 }); 6592 }) 6593 }; 6594 } 6595 return placesResult.result; 6596 } 6597 function propertiesSearch(term, leaseProperty) { 6598 var payload = { 6599 companyId: window.luxuryPresence.defaults.companyId, 6600 search: term, 6601 offset: 0, 6602 limit: 6, 6603 statusIds: ["5f528253-abb7-484e-95c3-330269ac1105", "959c11cf-8655-4f91-874c-292b0ab7ea6b", "a0012964-4f51-4430-abf8-6547c5ab6441", "df04ccbe-4621-4140-a504-ee1a17430bb7", "88b4ace6-f39b-4b25-a051-8f6dba976833", "96031d77-bbe5-4de3-90d8-1e4e70de8ca8"] 6604 }; 6605 if (leaseFilter) { 6606 payload.leaseProperty = !!leaseProperty; 6607 } 6608 return superagent.post(window.luxuryPresence.defaults.apiGatewayUrl + '/graphql').send({ 6609 query: window.luxuryPresence.defaults.gql.properties, 6610 variables: payload 6611 }).then(function (res) { 6612 return (res.body.data || {}).properties || []; 6613 }, function (err) { 6614 return []; 6615 }); 6616 } 6617 function doSearch(term, leaseProperty) { 6618 showLoading(); 6619 Promise.all([searchMls ? mlsSearch(term, leaseProperty) : [], searchPlaces ? placesSearch(term) : [], searchProperties ? propertiesSearch(term, leaseProperty) : []]).then(function (res) { 6620 if (term !== keyword) { 6621 return; 6622 } 6623 setResults(res[0], res[1], res[2], leaseProperty); 6624 }); 6625 } 6626 function makeResultsBlockHtml(title, links) { 6627 if (!links || !links.length) { 6628 return ''; 6629 } 6630 var html = '<div class="results-block">'; 6631 html += '<div class="results-block-title">'; 6632 if (searchNearEnabled) { 6633 html += '<div class="search-near-container"><a class="search-near lp-link lp-link--light">Search Near Me</a></div>'; 6634 } 6635 html += '<div class="results-title-label">' + title + '</div></div>'; 6636 html += links.join('') + '</div>'; 6637 return html; 6638 } 6639 function setResults(mlsResults, placesResults, propertiesResults, leaseProperty) { 6640 clearSelection(); 6641 hideLoading(); 6642 if (!mlsResults) { 6643 $resultsContainer.html(''); 6644 updateSearchDisplay(); 6645 return; 6646 } 6647 if (!mlsResults.length && !placesResults.length && !propertiesResults.length) { 6648 $resultsContainer.html('<div class="nothing-found">No results found</div>'); 6649 updateSearchDisplay(); 6650 return; 6651 } 6652 var propertiesHtml = makeResultsBlockHtml('Featured Properties', propertiesResults.map(function (result) { 6653 return `<a href="/properties/${result.slug}" class="results-link">${result.privateAddress ? result.name : result.fullAddress}</a>`; 6654 })); 6655 var placesHtml = makeResultsBlockHtml('Locations', placesResults.map(function (result) { 6656 return `<a class="results-link" href="${result.placeUrl}${leaseProperty ? '&lease_property=true' : ''}&cityName=${result.cityName}&stateName=${result.stateName}">${result.description}</a>`; 6657 })); 6658 var mlsHtml = makeResultsBlockHtml('Address', mlsResults.map(function (result) { 6659 return `<a href="/home-search/listings/${result.id}" class="results-link">${result.display_address}</a>`; 6660 }));
6661 $resultsContainer.html(propertiesHtml + placesHtml + mlsHtml); 6662 updateSearchDisplay(); 6663 } 6664 function searchBtnClicked() { 6665 var resultsBlockHref = $("#" + sectionDomId + " .results-block .results-link").attr("href"); 6666 const term = $searchInput.val(); 6667 if (!term) { 6668 return; 6669 } 6670 if (searchMls) { 6671 window.location.href = resultsBlockHref; 6672 return; 6673 } 6674 if (searchProperties) { 6675 window.location.href = "/properties/sale"; 6676 } 6677 } 6678 var neighborhoods = null; 6679 function fetchNeighborhoods() { 6680 var url = window.luxuryPresence.defaults.apiGatewayUrl; 6681 var gqlQuery = 'query ($companyId: String, $offset: Int, $limit: Int) {' + 'neighborhoods (companyId: $companyId, offset: $offset, limit: $limit) {id, name, mlsLink, googlePlaceData}}'; 6682 var payload = {}; 6683 payload.offset = 0; 6684 payload.limit = 100; 6685 payload.companyId = window.luxuryPresence.defaults.companyId; 6686 return superagent.post(url + '/graphql').withCredentials().send({ 6687 query: gqlQuery, 6688 variables: payload 6689 }).then(function (res) { 6690 neighborhoods = res.body.data && res.body.data.neighborhoods; 6691 if (neighborhoods && !neighborhoods.length) { 6692 neighborhoods = null; 6693 } 6694 }); 6695 } 6696 function setPredefinedNeighborhoods() { 6697 return fetchNeighborhoods().then(function () { 6698 if (!neighborhoods) { 6699 return; 6700 } 6701 var leaseProperty = leaseFilter && leasePropertyState; 6702 var placesHtml = makeResultsBlockHtml('Locations', neighborhoods.map(function (item) { 6703 return `<a class="results-link" href="${item.mlsLink}${leaseProperty ? '&lease_property=true' : ''}">${item.googlePlaceData && item.googlePlaceData.formatted_address || item.name}</a>`; 6704 })); 6705 $predefined.html(placesHtml); 6706 updateSearchDisplay(); 6707 }); 6708 } 6709 if (showNeighborhoods) { 6710 setPredefinedNeighborhoods(); 6711 } 6712 $searchInput.on('focus', showSearchResults); 6713 $searchInput.on('keyup focus', inputChanged); 6714 $searchResults.on('mouseenter', '.results-link', function (ev) { 6715 clearSelection(); 6716 }); 6717 $searchBtn.on('click', searchBtnClicked); 6718 $leaseFalseButton.on('click', function () { 6719 if (leasePropertyState) { 6720 leasePropertyState = false; 6721 if (showNeighborhoods) { 6722 setPredefinedNeighborhoods(); 6723 } 6724 updateSearchDisplay(); 6725 setResults(null); 6726 startSearch(); 6727 } 6728 }); 6729 $leaseTrueButton.on('click', function () { 6730 if (!leasePropertyState) { 6731 leasePropertyState = true; 6732 if (showNeighborhoods) { 6733 setPredefinedNeighborhoods(); 6734 } 6735 updateSearchDisplay(); 6736 setResults(null); 6737 startSearch(); 6738 } 6739 }); 6740 function createPolygonUrl(center, radius, n) { 6741 var step = Math.PI * 2 / n; 6742 var angle = 0 - step / 2; 6743 var points = []; 6744 var kx = 1.0 / Math.cos(center[1] * Math.PI / 180); 6745 for (var i = 0; i < n; i++) { 6746 points.push('[' + (center[0] + radius * Math.sin(angle) * kx).toFixed(5) + ',' + (center[1] - radius * Math.cos(angle)).toFixed(5) + ']'); 6747 angle += step; 6748 } 6749 points.push(points[0]); 6750 var str = '[[' + points.join(',') + ']]'; 6751 return '&polygon=' + encodeURIComponent(str); 6752 } 6753 function makeNearMeUrl(center, leaseProperty) { 6754 var url = '/home-search/listings?search_type=envelope'; 6755 if (leaseProperty) { 6756 url += '&lease_property=true'; 6757 } 6758 var distance = 0.11; 6759 var lat = center[1]; 6760 var lng = center[0]; 6761 url += '&south=' + (lat - distance); 6762 url += '&north=' + (lat + distance); 6763 url += '&west=' + (lng - distance); 6764 url += '&east=' + (lng + distance); 6765 url += createPolygonUrl(center, distance, 54); 6766 return url; 6767 } 6768 var $locMsg = null; 6769 $section.on('click', '.search-near', function () { 6770 showLoading(); 6771 navigator.geolocation.getCurrentPosition(function (position) { 6772 hideLoading(); 6773 hideSearchResults(); 6774 if (!position || !position.coords || !position.coords.latitude || !position.coords.longitude) { 6775 showLocationMessage('Unknown Location', '<p>Getting position of your device failed.</p><p>
6775You can type your address manually in the search field</p>'); 6776 return; 6777 } 6778 var url = makeNearMeUrl([position.coords.longitude, position.coords.latitude], leaseFilter && leasePropertyState); 6779 var link = document.createElement('a'); 6780 link.href = url; 6781 link.class = 'lp-visually-hidden'; 6782 $section[0].appendChild(link); 6783 link.click(); 6784 setTimeout(function () { 6785 $section[0].removeChild(link); 6786 }, 100); 6787 }, function (geoError) { 6788 hideLoading(); 6789 hideSearchResults(); 6790 var title = 'Unknown Location'; 6791 var msg; 6792 if (geoError.code === 1) { 6793 msg = '<p>To be able to search near you we need to know your current location.</p><p>If you don\'t want to give access to your device\'s location, you can type your address in the search field</p>'; 6794 } else { 6795 msg = '<p>Getting position of your device failed.</p><p>You can type your address manually in the search field</p>'; 6796 } 6797 showLocationMessage(title, msg); 6798 }); 6799 }); 6800 var locHideTimer = null; 6801 function showLocationMessage(title, message) { 6802 clearTimeout(locHideTimer); 6803 if (!$locMsg) { 6804 var html = `<div class="loc-msg-backdrop"> 6805 <div class="loc-msg-wrap"> 6806 <div class="loc-msg-modal"> 6807 <div class="loc-msg-close"></div> 6808 <h4 class="loc-msg-title lp-h4"></h4> 6809 <div class="loc-msg-container"></div> 6810 </div> 6811 </div> 6812 </div> 6813 `; 6814 $locMsg = $(html); 6815 $locMsg.on('click', hideLocationMessage); 6816 $section.append($locMsg); 6817 } 6818 $locMsg.find('.loc-msg-container').html(message); 6819 $locMsg.find('.loc-msg-title').html(title); 6820 setTimeout(function () { 6821 if ($locMsg) { 6822 $section.addClass('visible-loc-msg'); 6823 } 6824 }); 6825 } 6826 function hideLocationMessage() { 6827 $section.removeClass('visible-loc-msg'); 6828 locHideTimer = setTimeout(function () { 6829 $locMsg.remove(); 6830 $locMsg = null; 6831 }, 400); 6832 } 6833 function outsideClickHandler(e) { 6834 if ($searchWrapper.find($(e.target)).length > 0) { 6835 return; 6836 } 6837 hideSearchResults(); 6838 } 6839 $(document).on('click', outsideClickHandler); 6840 if ('geolocation' in navigator) { 6841 $searchWrapper.removeClass('search-near-hidden'); 6842 } 6843 updateSearchDisplay(); 6844 }); 6845})('section-f0cc46ac-4d4b-426a-a54d-6d7555c49280', 'undefined'); 6846} catch(e) { 6847console.log(e); 6848} 6849 try { 6850(function init(sectionDomId) { 6851 const $section = $('#' + sectionDomId); 6852 const $form = $section.find('.custom-form__download-form'); 6853 const redirectLink = $section.find('.js-redirect-link'); 6854 function redirectPage(link) { 6855 if (link.length) { 6856 const rawHref = link.attr('href'); 6857 link.attr('href', setHttp(rawHref)); 6858 link[0].click(); 6859 } 6860 } 6861 function setHttp(link) { 6862 if (link.search(/^http[s]?\:\/\/|\//) == -1) { 6863 link = 'https://' + link; 6864 } 6865 return link; 6866 } 6867 $form.on('reset', function () { 6868 redirectPage(redirectLink); 6869 }); 6870 var backupEmailField = $section.find('.js-backup-email'); 6871 if (backupEmailField) { 6872 var dynEmailField = $section.find('input.js-form-element[name="email"]:not(.js-backup-field)'); 6873 if (dynEmailField.length === 0) { 6874 backupEmailField.removeClass('js-backup-email'); 6875 } else { 6876 backupEmailField.remove(); 6877 } 6878 } 6879 var $allElements = $section.find('.js-form-element'); 6880 const putAllInMessage = false; 6881 var hasCustomFields = false; 6882 const standardFields = { 6883 'name': true, 6884 'email': true, 6885 'phone': true, 6886 'message': true, 6887 'interest': true 6888 }; 6889 const busyFormNames = { 6890 'address': true, 6891 'city': true, 6892 'state': true, 6893 'postalCode': true, 6894 'mlsId': true, 6895 'sourceUrl': true 6896 }; 6897 $allElements.each(function () { 6898 var $el = $(this); 6899 var name = this.hasAttribute('data-name') ? $el.attr('data-name') : $el.attr('name'); 6900 if (!name) { 6901 return; 6902 } 6903 if (!standardFields[name]) { 6904 hasCustomFields = true; 6905 } 6906 let newName = /[^a-z\d-_]/.test(name) ? name.trim().toLowerCase().replace(/[^a-z\d-_]/g, '-') : name; 6907 if (!/^[a-z]/.test(newName)) { 6908 newName = 'fld-' + newName; 6909 } 6910 if (busyFormNames[newName]) { 6911 let idx = 1; 6912 while (busyFormNames[`${newName}-${idx}`] && idx < 100) { 6913 idx++; 6914 } 6915 newName = `${newName}-${idx}`; 6916 } 6917 busyFormNames[newName] = $el; 6918 if (name !== newName) { 6919 $el.attr('name', newName); 6920 } 6921 }); 6922 let $customFields = []; 6923 if (putAllInMessage && hasCustomFields) { 6924 $allElements.each(function () { 6925 var name = this.getAttribute('name'); 6926 if (name && (!standardFields[name] || name === 'message' && !$(this).hasClass('js-composed-message'))) { 6927 this.setAttribute('data-name', name); 6928 this.removeAttribute('name'); 6929 } 6930 if (this.hasAttribute('data-name')) { 6931 $customFields.push($(this)); 6932 } 6933 }); 6934 if (!$form[0].elements['message']) { 6935 $('<input type="hidden" name="message" class="js-composed-message" value="">').appendTo($form); 6936 } 6937 } 6938 $selects = $section.find('select.js-select'); 6939 var $checkboxGroups = $section.find('.js-checkboxes-group'); 6940 if ($checkboxGroups.length) { 6941 $checkboxGroups.each(function () { 6942 var $group = $(this); 6943 if (!$group.data('required')) return; 6944 var $checkboxes = $group.find('.js-multi-checkbox'); 6945 function updateValidity() { 6946 var anyChecked = $group.find('.js-multi-checkbox:checked').length > 0; 6947 $checkboxes.each(function () { 6948 this.setCustomValidity(anyChecked ? '' : 'Please select at least one option.'); 6949 }); 6950 }
6951 updateValidity(); 6952 $checkboxes.on('change', updateValidity); 6953 }); 6954 $form.on('submit', function () { 6955 $checkboxGroups.each(function () { 6956 var $group = $(this); 6957 var name = $group.data('name'); 6958 if (!name) return; 6959 var checked = $group.find('.js-multi-checkbox:checked').map(function () { 6960 return this.value; 6961 }).get().join(', '); 6962 $form.find('input[type="hidden"][data-checkbox-group="' + name + '"]').remove(); 6963 $('<input type="hidden">').attr('name', name).val(checked).attr('data-checkbox-group', name).appendTo($form); 6964 var $groupCheckboxes = $group.find('.js-multi-checkbox'); 6965 $groupCheckboxes.prop('disabled', true); 6966 setTimeout(function () { 6967 $groupCheckboxes.prop('disabled', false); 6968 }, 0); 6969 }); 6970 }); 6971 } 6972 let selectsInitialized = false; 6973 function initializeSelects() { 6974 if (selectsInitialized) { 6975 return; 6976 } 6977 selectsInitialized = true; 6978 $selects.each(function () { 6979 if (this.id) { 6980 $label = $section.find('[for="' + this.id + '"]'); 6981 if ($label.length) { 6982 var rect = $label[0].getBoundingClientRect(); 6983 if (rect && rect.width < 30) { 6984 var firstOption = $(this).find('option').first(); 6985 firstOption.attr('label', firstOption.data('label')); 6986 } 6987 } 6988 $gr = $(this).closest('.lp-input-group'); 6989 var b = $gr.css('border-left-width'); 6990 if (b && b !== '0px') { 6991 $gr[0].style.setProperty('--uf-border-left', b); 6992 } 6993 b = $gr.css('border-right-width'); 6994 if (b && b !== '0px') { 6995 $gr[0].style.setProperty('--uf-border-right', b); 6996 } 6997 } 6998 }); 6999 var csPrefix = 'uf-cus-sel'; 7000 function convertSelectToDropdown(selectItem) { 7001 const $selectItem = $(selectItem); 7002 const selectId = $selectItem.attr('id'); 7003 const id = $selectItem.attr('id') + '-custom-select'; 7004 let $dropdown = $selectItem.next(); 7005 let initialized = true; 7006 if ($dropdown.attr('id') !== id) { 7007 $selectItem.addClass("sr-only"); 7008 initialized = false; 7009 let customDropdown = ` 7010 <div class="${csPrefix}" role="presentation"> 7011 <button class="${csPrefix}-toggle" type="button" aria-haspopup="true" aria-expanded="false"></button> 7012 <div class="${csPrefix}-menu"> 7013 <div class="${csPrefix}-content"> 7014 </div> 7015 </div> 7016 </div>`; 7017 $(customDropdown).insertAfter(selectItem); 7018 $dropdown = $selectItem.next(); 7019 $dropdown.attr('id', id); 7020 } 7021 let $dropdownToggle = $dropdown.find('.' + csPrefix + '-toggle'); 7022 let $dropdownMenu = $dropdown.find('.' + csPrefix + '-menu'); 7023 let $dropdownContent = $dropdown.find('.' + csPrefix + '-content'); 7024 if (!initialized) { 7025 $dropdownToggle.addClass($selectItem.attr("class")).removeClass(['dropdown-select', 'js-select', 'js-form-element', 'sr-only']); 7026 $dropdownToggle.attr("id", id + '-toggle'); 7027 $dropdownMenu.attr("aria-labelledby", $dropdownToggle.attr("id")); 7028 appendOptionButtons(selectItem, $dropdownContent); 7029 } 7030 $selectItem.on("focus", function () { 7031 showSelectMenu($dropdownMenu[0]); 7032 $dropdownToggle.focus(); 7033 }); 7034 function setInitialValue() { 7035 $dropdownMenu.find('.' + csPrefix + '-item').removeClass('is-selected'); 7036 var $selectedOption = $selectItem.find(':selected').first(); 7037 if (!$selectedOption.length) { 7038 $selectedOption = $selectItem.children().first(); 7039 } 7040 var defaultText = ' '; 7041 var isPlaceholder = true; 7042 if ($selectedOption.length) { 7043 defaultText = ($selectedOption[0].hasAttribute('label') ? $selectedOption.attr('label') : $selectedOption.text()) || ' '; 7044 isPlaceholder = !!$selectedOption.prop("disabled"); 7045 } 7046 $dropdownToggle.html(defaultText); 7047 if (isPlaceholder) { 7048 $dropdownToggle.addClass('is-placeholder'); 7049 } 7050 } 7051 setInitialValue(); 7052 $dropdown.on("click", '.' + csPrefix + '-item', function (e) { 7053 const $button = $(this); 7054 if ($button.hasClass("is-disabled")) return; 7055 let elementNumber = $button.index(); 7056 let $linkedOption = $selectItem.find("option").eq(elementNumber); 7057 if (!$linkedOption.prop("selected")) { 7058 $linkedOption.prop("selected", true); 7059 $selectItem.change(); 7060 $button.addClass("is-selected").siblings('.' + csPrefix + '-item').removeClass("is-selected"); 7061 $dropdownToggle.removeClass("is-placeholder").html($button.html()); 7062 closeSelectMenu($button.closest('.' + csPrefix + '-menu')); 7063 } 7064 }); 7065 $(selectItem.form).on('reset', function () { 7066 setTimeout(function () { 7067 setInitialValue(); 7068 }); 7069 }); 7070 function convertOptionToButton(option) { 7071 const $option = $(option); 7072 var optionText = $option.text(); 7073 var optionValue = $option.attr("value"); 7074 var optionIsDisabled = $option.prop("disabled"); 7075 var outputButton = `<button value="${optionValue}" class="${csPrefix}-item" type="button" ${optionIsDisabled ? "disabled" : ""}>${optionText}</button>`; 7076 return outputButton; 7077 } 7078 function appendOptionButtons(selectItem, appendTarget) { 7079 const $appendTarget = $(appendTarget); 7080 $(selectItem).find("option").each(function () { 7081 let currentButton = convertOptionToButton(this); 7082 $appendTarget.append(currentButton); 7083 }); 7084 } 7085 function showSelectMenu(selectMenu) { 7086 var $customSelect = $(selectMenu).closest('.' + csPrefix); 7087 $customSelect.addClass("open"); 7088 $(selectMenu).slideDown(); 7089 } 7090 function closeSelectMenu(selectMenu) { 7091 var $customSelect = $(selectMenu).closest('.' + csPrefix); 7092 $customSelect.removeClass("open"); 7093 $(selectMenu).slideUp(); 7094 } 7095 $dropdown.on("click", '.' + csPrefix + '-toggle', function (e) { 7096 var $customSelect = $(this).closest('.' + csPrefix); 7097 var selectMenu = $customSelect.find('.' + csPrefix + '-menu')[0]; 7098 if ($customSelect.hasClass("open")) { 7099 closeSelectMenu(selectMenu); 7100 } else { 7101 showSelectMenu(selectMenu); 7102 } 7103 }); 7104 $(document.body).on("click", function (e) { 7105 var $closestCustomSelect = $(e.target).closest('.lp-input-group').find('.' + csPrefix); 7106 $section.find('.' + csPrefix + '.open').not($closestCustomSelect).each(function () { 7107 closeSelectMenu($(this).find('.' + csPrefix + '-menu')[0]); 7108 }); 7109 }); 7110 } 7111 $selects.each(function () { 7112 convertSelectToDropdown(this); 7113 }); 7114 if (putAllInMessage && hasCustomFields) { 7115 $allElements.on('change', function () { 7116 if (!this.hasAttribute('data-name')) { 7117 return; 7118 } 7119 var message = ''; 7120 var customMessages = []; 7121 $customFields.forEach(function ($el) { 7122 var value = $el.val(); 7123 if (!value) { 7124 return; 7125 } 7126 if ($el.attr('data-name') === 'message') { 7127 message = value; 7128 return; 7129 } 7130 var label = $section.find(`label[for='${$el[0].id}']`).text(); 7131 customMessages.push(label + ': ' + ($el[0].tagName === 'TEXTAREA' ? '\n' : '') + value); 7132 }); 7133 if (customMessages.length) { 7134 if (message) { 7135 customMessages.push('Message: \n' + message); 7136 } 7137 $form[0].elements['message'].value = customMessages.join('\n'); 7138 } else { 7139 $form[0].elements['message'].value = message; 7140 } 7141 }); 7142 } 7143 } 7144 function initModalColors() { 7145 try { 7146 if (!$section.css('--bgColor')) { 7147 var colorStr = $section.css('background-color'); 7148 var bgColor = makeColor(colorStr); 7149 var isDark = (bgColor.rgba.r * 299 + bgColor.rgba.g * 587 + bgColor.rgba.b * 114) / 1000 < 128; 7150 $section[0].style.setProperty('--bgColor', colorStr); 7151 $section[0].style.setProperty('--bgColor_H', bgColor.hsla.h + 'deg'); 7152 $section[0].style.setProperty('--bgColor_S', bgColor.hsla.s + '%'); 7153 $section[0].style.setProperty('--bgColor_L', bgColor.hsla.l + '%'); 7154 $section[0].style.setProperty('--bgColor_A', bgColor.hsla.a); 7155 $section[0].style.setProperty('--bgColor_darkenDir', isDark ? 1 : -1); 7156 $section.addClass('is-background-color-' + (isDark ? 'dark' : 'light')); 7157 } 7158 } catch (e) {} 7159 } 7160 function makeColor(str) { 7161 var color = { 7162 rgba: { 7163 r: 0, 7164 g: 0, 7165 b: 0, 7166 a: 0 7167 } 7168 }; 7169 if (str && str.match) { 7170 var m = str.match(/rgba?\s*\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\.0-9]+))?\)/); 7171 if (m) { 7172 color.rgba.r = parseInt(m[1]); 7173 color.rgba.g = parseInt(m[2]); 7174 color.rgba.b = parseInt(m[3]); 7175 color.rgba.a = parseFloat(m[4]); 7176 if (isNaN(color.rgba.a)) { 7177 color.rgba.a = 1; 7178 } 7179 } 7180 } 7181 color.hsla = makeHSLA(color.rgba); 7182 return color; 7183 } 7184 function makeHSLA(rgba) { 7185 var r = rgba.r / 255, 7186 g = rgba.g / 255, 7187 b = rgba.b / 255, 7188 a = rgba.a; 7189 var min = Math.min(r, g, b), 7190 max = Math.max(r, g, b), 7191 l = (max + min) / 2, 7192 d = max - min, 7193 h, 7194 s; 7195 switch (max) { 7196 case min: 7197 h = 0; 7198 break; 7199 case r: 7200 h = 60 * (g - b) / d; 7201 break; 7202 case g: 7203 h = 60 * (b - r) / d + 120; 7204 break; 7205 case b: 7206 h = 60 * (r - g) / d + 240; 7207 break; 7208 } 7209 if (max == min) { 7210 s = 0; 7211 } else if (l < .5) { 7212 s = d / (2 * l); 7213 } else { 7214 s = d / (2 - 2 * l); 7215 } 7216 s *= 100; 7217 l *= 100; 7218 return { 7219 h: h, 7220 s: s, 7221 l: l, 7222 a: a 7223 }; 7224 } 7225 if ($section.is('.modal')) { 7226 initModalColors(); 7227 $section.on('lpui-show', function () { 7228 window.lpUI.requestScrollLock(sectionDomId); 7229 }); 7230 $section.on('lpui-hide', function () { 7231 window.lpUI.releaseScrollLock(sectionDomId); 7232 }); 7233 } 7234 initializeSelects(); 7235 var $addressInputs = $section.find('.js-address-autocomplete'); 7236 if ($addressInputs.length && window.luxuryPresence && window.luxuryPresence.mapApiLoader) { 7237 window.luxuryPresence.mapApiLoader.load().then(function () { 7238 var autocompleteOptions = { 7239 types: ['geocode'], 7240 fields: ['formatted_address'] 7241 }; 7242 $addressInputs.each(function () { 7243 var input = this; 7244 var autocomplete = new google.maps.places.Autocomplete(input, autocompleteOptions); 7245 autocomplete.addListener('place_changed', function () { 7246 var place = autocomplete.getPlace(); 7247 if (place && place.formatted_address) { 7248 input.value = place.formatted_address; 7249 } 7250 }); 7251 }); 7252 }); 7253 } 7254})('section-effb862d-3cb0-4174-960c-c1cca02380a8', 'undefined'); 7255} catch(e) { 7256console.log(e); 7257} 7258 try { 7259(function init(sectionDomId) { 7260 var $section = $('#' + sectionDomId); 7261 $section.find('.media-card__description').each(function () { 7262 var $desc = $(this); 7263 var fullHtml = $desc.html(); 7264 var text = $desc.text(); 7265 if (text.length > 188) { 7266 var substring = text.substring(0, 188); 7267 $desc.empty().append(`<span class="substring">${substring}... <a class="btn-more">VIEW MORE</a></span>`).append(`<div class="more-text">${fullHtml} <a class="btn-more">VIEW LESS</a></div>`); 7268 $desc.addClass('cropped'); 7269 } 7270 }); 7271 $section.find('.btn-more').on('click', function (e) { 7272 e.preventDefault(); 7273 $(this).closest('.media-card__description').toggleClass('cropped'); 7274 }); 7275})('section-4c321f4f-0d95-40b2-af2a-8aa841d20888', 'undefined'); 7276} catch(e) { 7277console.log(e); 7278} 7279 try { 7280(function init(sectionDomId, options) { 7281 let section = null; 7282 switch (sectionDomId) { 7283 case 'NAVBAR': 7284 section = document.querySelector('body > nav, #global-navbar'); 7285 break; 7286 case 'FOOTER': 7287 section = document.querySelector('body > footer, #global-footer'); 7288 break; 7289 case 'SIDEMENU': 7290 section = document.querySelector('body > div.sidemenu, #global-sidemenu'); 7291 break; 7292 case 'CONTACT':
7293 section = document.querySelector('#modal-global-contact-us'); 7294 break; 7295 case 'MOBILE_CONTACT': 7296 section = document.querySelector('body > div.mobile-contact-wrapper, #global-mobile-contact'); 7297 break; 7298 case 'SUBSCRIBE': 7299 // Subscribe Not Implemented 7300 section = null; 7301 break; 7302 case 'ACCOUNT': 7303 // Account Not Implemented 7304 section = null; 7305 break; 7306 default: 7307 section = document.querySelector('#' + sectionDomId); 7308 } 7309 if (!section) { 7310 return; 7311 } 7312 var url = window.luxuryPresence.defaults.routerUrl; 7313 var companyId = window.luxuryPresence.defaults.companyId; 7314 var limit = options.limit || 8; 7315 if (typeof limit === 'string') { 7316 limit = parseInt(limit, 10) || 8; // this NaN protection also filters out 0 - this is expected 7317 } 7318 var templateSelector = options.templateSelector || '.jsIGTemplate'; 7319 var containerSelector = options.containerSelector || '.jsIGContainer'; 7320 var hasDataClass = options.hasDataClass || 'has-data'; 7321 var hideActivateMessage = options.hasDataClass || false; 7322 var payload = { 7323 companyId: companyId, 7324 limit: limit 7325 }; 7326 if (options.resourceId && typeof options.resourceId === 'string' && !options.resourceId.match(/^{{.*}}$/)) { 7327 payload.resourceId = options.resourceId; 7328 // Federated enum values are uppercase (AGENT/TEAM); element configs carry lowercase 7329 payload.resource = String(options.resource || 'agent').toUpperCase(); 7330 payload.fallbackToNoResource = options.fallbackToNoResource === 'true' || options.fallbackToNoResource === true; 7331 } 7332 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'; 7333 var templateHTML = section.querySelector(templateSelector)?.innerHTML || ''; 7334 var template = Handlebars.compile(templateHTML); 7335 var container = section.querySelector(containerSelector); 7336 if (options.variables) { 7337 Object.keys(options.variables).forEach(function (key) { 7338 if (options.variables.hasOwnProperty(key) && (typeof options.variables[key] !== 'string' || !options.variables[key].match(/^{{.*}}$/))) { 7339 payload[key] = options.variables[key]; 7340 } 7341 }); 7342 } 7343 function getData() { 7344 var feed = { 7345 error: true 7346 }; 7347 if (payload.companyId == null || payload.companyId === '') { 7348 // instagramContentFeed requires companyId (ID!) â nothing to fetch without it. 7349 // Checked after the options.variables merge, which may override the default. 7350 // Deferred so element listeners (attached after this template runs) still receive it. 7351 setTimeout(function () { 7352 section.dispatchEvent(new CustomEvent('ig-data', { 7353 detail: feed 7354 })); 7355 }, 0); 7356 return; 7357 } 7358 superagent.post(url + '/graphql').send({ 7359 query: query, 7360 variables: payload 7361 }).then(res => { 7362 try { 7363 if (!res.body.errors) { 7364 feed = res.body.data.instagramContentFeed; 7365 if (!feed.active) { 7366 if (!hideActivateMessage && sectionDomId === 'section-temp' && container) { 7367 if (payload.resourceId) { 7368 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>'; 7369 } else { 7370 container.innerHTML = '<div style="text-align: center">Instagram account is not connected.<br /> Connect it on <a href="/profile">Profile page</a></div>'; 7371 } 7372 } 7373 } else { 7374 if (feed.items.length) { 7375 if (hasDataClass) { 7376 section.classList.add(hasDataClass); 7377 } 7378 const feedName = feed.username; 7379 section.querySelectorAll('.jsIGLink').forEach(link => link.setAttribute('href', feed.feedUrl)); 7380 section.querySelectorAll('.jsIGName').forEach(name => { 7381 name.textContent = '@' + feedName; 7382 name.setAttribute('title', '@' + feedName); 7383 }); 7384 if (container && template) { 7385 container.innerHTML = template(feed); 7386 } 7387 } 7388 } 7389 } 7390 } catch (e) {} 7391 section.dispatchEvent(new CustomEvent('ig-data', { 7392 detail: feed 7393 })); 7394 }).catch(e => { 7395 console.log('err', e); 7396 section.dispatchEvent(new CustomEvent('ig-data', { 7397 detail: feed 7398 })); 7399 }); 7400 } 7401 getData(); 7402})('section-688bafaa-1ccc-4661-b05d-4c7f46978b71', JSON.parse("{\"companyId\":\"c192c24d-68d5-41fb-b04a-e3c9703e46be\",\"sectionIndex\":4}")); 7403} catch(e) { 7404console.log(e); 7405} 7406 try { 7407(function init(sectionDomId) { 7408 $("#" + sectionDomId).on("ig-data", function () { 7409 let title = $("#" + sectionDomId + " .js-slider-holder").data("title"); 7410 if (title) { 7411 $("#" + sectionDomId + " .js-h3").text(title); 7412 } 7413 if (window.matchMedia("(max-width: 768px)").matches) { 7414 $("#" + sectionDomId + " .js-slider-holder").before($("#" + sectionDomId + " .js-title-group").clone()); 7415 } 7416 $("#" + sectionDomId + " .js-collection .js-title-group").remove(); 7417 function buildSlick() { 7418 $('#' + sectionDomId + ' .js-collection').slick({ 7419 autoplay: true,
7420 arrows: false, 7421 speed: 0, 7422 autoplaySpeed: 6000, 7423 dots: false, 7424 infinite: true, 7425 slidesToShow: 4, 7426 slidesToScroll: 4, 7427 cssEase: 'linear', 7428 variableWidth: true, 7429 centerMode: false, 7430 swipe: false, 7431 responsive: [{ 7432 breakpoint: 1024, 7433 settings: { 7434 slidesToShow: 2, 7435 slidesToScroll: 2 7436 } 7437 }, { 7438 breakpoint: 768, 7439 settings: { 7440 slidesToShow: 4, 7441 slidesToScroll: 4 7442 } 7443 }] 7444 }); 7445 } 7446 if ($("#" + sectionDomId + " .js-collection").length) { 7447 if ($("#" + sectionDomId + " .js-collection").hasClass('slick-initialized')) { 7448 $("#" + sectionDomId + " .js-collection").slick('unslick'); 7449 buildSlick(); 7450 } else { 7451 buildSlick(); 7452 } 7453 } 7454 }); 7455})('section-688bafaa-1ccc-4661-b05d-4c7f46978b71', 'undefined'); 7456} catch(e) { 7457console.log(e); 7458} 7459 7460 var { body } = document; 7461 var globalNav = body.querySelector(':scope > nav'); 7462 var globalSideMenu = body.querySelector(':scope > div.sidemenu'); 7463 7464 document.querySelectorAll('body > .modal .close').forEach(modalCloseBtn => { 7465 modalCloseBtn.addEventListener('click', function() { 7466 window.lpUI.hideClosestModal(modalCloseBtn); 7467 }); 7468 }); 7469 7470 window.addEventListener('click', function() { 7471 document.querySelectorAll('.share-popup').forEach(sharedPopup => { 7472 sharedPopup.style.display = 'none' ; 7473 }); 7474 }); 7475 7476 /* Misc Partials / Addons */ 7477 function initWOW() { 7478 if (wow) { 7479 wow.init(); 7480 wow.scrollHandler(); 7481 setTimeout(function () { 7482 const wowHideStyle = document.getElementById('wow-hide-elements'); 7483 if(wowHideStyle) { 7484 wowHideStyle.disabled = true; 7485 } 7486 }, 1); 7487 } 7488 } 7489 7490 const wowHideElements = document.getElementById('wow-hide-elements'); 7491 if (wowHideElements) { 7492 wowHideElements.disabled = false; 7493 } 7494 7495 initWOW(); 7496 7497 /* Generic Navbar Handling */ 7498 globalNav?.querySelectorAll('.hamburger-component').forEach(hamburgerComponent => { 7499 hamburgerComponent.addEventListener('click', function() { 7500 window.lpUI.sideMenuToggle(); 7501 }); 7502 }); 7503 globalSideMenu?.querySelectorAll('.toggle').forEach(toggleEl => { 7504 toggleEl.addEventListener('click', function() { 7505 window.lpUI.sideMenuToggle(); 7506 }); 7507 }); 7508 7509 document.querySelectorAll('body > nav .sub-nav-container > a, body > div.sidemenu .sub-nav-container > a').forEach(linkEl => { 7510 linkEl.addEventListener('click', function(e) { 7511 e.preventDefault(); 7512 e.stopPropagation(); 7513 var subNav = linkEl.parentElement.querySelector(':scope > .sub-nav'); 7514 if (subNav && subNav.classList.contains('visible')){ 7515 subNav.classList.remove('visible'); 7516 } else { 7517 globalNav?.querySelectorAll('.sub-nav-container .sub-nav').forEach(globalSubNav => { 7518 globalSubNav.classList.remove('visible'); 7519 }); 7520 globalSideMenu?.querySelectorAll('.sub-nav').forEach(sideMenuSubNav => { 7521 sideMenuSubNav.classList.remove('visible'); 7522 }); 7523 subNav?.classList.add('visible'); 7524 } 7525 }); 7526 }); 7527 window.addEventListener('click', function() { 7528 document.querySelectorAll('nav .sub-nav.visible, .sidemenu .sub-nav.visible').forEach(subNavEl => { 7529 subNavEl.classList.remove('visible'); 7530 }); 7531 }); 7532 7533 } 7534 7535 document.addEventListener('DOMContentLoaded', lpGlobalInit); 7536 7537 </script>
7537 7538 7539
7539<script type="module"> 7540 function selectorExists(selector) { 7541 return document.querySelector(selector) !== null; 7542 } 7543 7544 // Function to initialize the third-party library 7545 function initParoller(selector = '.my-paroller') { 7546 var $parollerElements = $(selector); 7547 if ($parollerElements.length > 0 && typeof $parollerElements.paroller === 'function') { 7548 $parollerElements.paroller(); 7549 } 7550 } 7551 7552 const parollerSelector = '.my-paroller'; 7553 7554 if (selectorExists(parollerSelector)) { 7555 window.luxuryPresence.libs.loadJs(window.luxuryPresence.libs.jsLibsMap.paroller.jsSrc, function() { 7556 initParoller(parollerSelector); 7557 window.luxuryPresence.libs.jsLibsMap.paroller.isLoaded = true; 7558 }); 7559 } 7560 </script>
7560 7561 7562 <!-- Google Tag Manager (noscript) -->
vendor: 80 bytes, lines 7562-7563
7562 7563 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
7563GTM-T9SFQGHZ
vendor: 107 bytes, lines 7563-7565
7563" 7564 height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 7565
7565<!-- End Google Tag Manager --> 7566 7567
7567<script 7568 src="https://cdn.luxurypresence.com/scripts/a11y-widget/latest/widget.js" 7569 data-website-id="3dfcdeb5-d5fa-4659-a16f-19b36b8f2e9c" 7570 7571 defer></script>
vendor: 1 bytes, line 7571
7571
7572<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 7572
7572
7573<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:'a46a05221989f833',t:'MTc5MTM0NTg0OA=='};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>
7573</body> 7574</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.