
    var thisScript = document.currentScript;

    ! function() {
        const modal = null;

        var script = document.createElement("script"); // create a script DOM node
        script.src =
            "https://maps.googleapis.com/maps/api/js?key=AIzaSyB5aKUxlSqIedNX9UV_LQmF0j0BHHvfxbQ&libraries=drawing&libraries=places"; // set its src to the provided URL

        script.onreadystatechange = plunkInit;
        script.onload = plunkInit;

        document.head.appendChild(
            script
        ); // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)


    }();

    function plunkInit() {
        const modal = null;
        insertHTML()
        initializeSearchBox()
    };


    function insertHTML() {
        let html =
            `<style>/* NOTE: never use a backtick or a dollar-brace in this file. AppController::embed
   injects it into a JS template literal via addslashes(), which escapes quotes
   but NOT backticks -- one would terminate the string and break the whole widget.

   The widget carries no reset of its own and was quietly relying on the host page
   providing one: box-sizing is not inherited, so only the two elements that opt in
   below were ever border-box. Inside the IDXApps dashboard Tailwind supplies a
   universal border-box rule and everything lines up; on a customer site without a
   reset the Go button\'s 99px width became 99+22+22 = 143px and overran the input.

   The two modals are injected as SIBLINGS of the wrapper, not inside it, so they
   have to be listed separately. */
#plunk-valuation-wrapper,
#plunk-valuation-wrapper *,
#plunk-valuation-wrapper *::before,
#plunk-valuation-wrapper *::after,
#pv-lead-modal,
#pv-lead-modal *,
#pv-valuation,
#pv-valuation * {
    box-sizing: border-box;
}

#plunk-valuation-wrapper {
    max-width: 600px;
    padding: 16px 20px;
    margin: 0px auto;
    background-color: white;
    font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, sans-serif;
    color: #003960;
    box-sizing: border-box;
    border-radius: 16px;
    line-height: normal !important;
    letter-spacing: normal !important;
}

.pv-heading-container {
    font-size: 24px;
    text-align: center;
    margin-top: 0;
    margin-bottom: 24px;
    font-weight: 700;
}

.pv-input-container {
    position: relative;
    min-width: 168px;
    display: block;
    /* The space before the \"powered by\" logo used to come from the label\'s
       bottom margin collapsing out through this form. Owned here now, so the
       label can drop its margin and become a reliable containing block. */
    margin: 0 0 14px;
}

/* The search field is a flex ROW that owns the pill: border, radius, background
   and height all live here, and the icon is a real sibling column rather than an
   absolutely positioned overlay.

   The icon used to sit on top of the input, which meant its position and the
   input\'s left padding were two independent numbers that had to agree. They
   didn\'t: too little padding and the address ran under the glass, and a mask
   sized to cover the gutter hid the start of the text instead. Out here the icon
   is outside the input\'s box entirely, so no value can ever reach it and there
   is no padding for a host page to override.

   Scoped to the direct child of the form -- .pv-label is reused by the four
   lead-capture fields, which must stay column-flow. */
.pv-input-container > .pv-label {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    margin-bottom: 0;
    padding: 0 18px;
    height: 50px;
    background: white;
    border: 1px solid #BFCDD7;
    border-radius: 101px;
}

/* Highlight the whole pill, since the border no longer belongs to the input. */
.pv-input-container > .pv-label:focus-within {
    border-color: #2F82FF;
    box-shadow: 0 0 0 1px #2F82FF;
}

.pv-input-container > .pv-label > .bi {
    flex: 0 0 16px;
    color: #7d95a7;
}


/* The pill (border, radius, height, background) now belongs to the label above.
   This is just the text field inside it.

   min-width:0 is load-bearing: a flex item\'s default min-width is auto, so a
   long address would otherwise force the input wider than the pill and push the
   layout out instead of scrolling inside it. */
.pv-input {
    box-sizing: border-box;
    color: rgba(0, 0, 0, 0.7);
    font-size: 13px;
    flex: 1 1 auto;
    min-width: 0;
    width: 100% !important;
    /* Only the right side needs reserving now, for the Go button\'s real
       footprint -- 99px wide plus its 4px margin, plus breathing room. */
    padding: 4px 100px 2px 0;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    height: auto !important;
    background: transparent;
    border: none;
    border-radius: 0;
}

.pv-input:focus-visible,
.pv-input:focus {
    outline: none;
    border: none;
    box-shadow: none;
}

.pv-lead-input {
    box-sizing: border-box;
    color: rgba(0, 0, 0, 0.7);
    font-size: 13px;
    width: 100% !important;
    padding: 8px 13px;
    appearance: none;
    outline-offset: 0.5px;
    height: 46px !important;
    border: 1px solid rgb(204, 204, 204);
    border-radius: 0.375rem;
    /* 6px */
    z-index: 10;

}

#pv-tel {
    height: 50px;
    font-weight: bold;
    color: #003960;
    font-size: 16px;
}

#pv-tel::placeholder {
    color: #809CAF;
}

#pv-tel:focus-visible {
    outline: none;
    border: 1px solid #2F82FF;
    box-shadow: 0 0 0 1px #2F82FF;
}

@media (min-width: 480px) {
    .pv-input {
        font-size: 16px;
    }
}

.pv-button {
    position: absolute;
    right: 0px;
    top: 0px;
    bottom: 0px;
    display: flex;
    align-items: center;
    /* space-between with exactly two children pins \"Go\" to one edge and the
       arrow to the other, and dumps every pixel of slack in the middle. */
    justify-content: center;
    gap: 8px;
    width: 99px;
    /* The button resolves to 42px tall (top/bottom 0 inside a 50px form, less
       an 4px margin each side). 12px of vertical padding left an 18px content
       box for a 24px arrow, so it overflowed top and bottom. */
    padding: 0 18px;
    border: none;
    border-radius: 26px;
    margin: 4px;
    background-color: #2F82FF;
    color: white !important;
    font-family: inherit;
    font-size: 18px;
    font-weight: bold;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    pointer-events: all;
    cursor: pointer;
    z-index: 20;
}

@media (min-width: 480px) {
    .pv-button {
        font-size: 16px;
    }
}

/* Shown by the Go handler when no address has been resolved. Aligned with the
   input\'s text so it reads as belonging to the field. */
.pv-address-error {
    margin: -8px 0 0;
    padding-left: 20px;
    text-align: left;
}

#pv-cta-button.is-loading {
    pointer-events: none;
    opacity: .50;
}

.pv-powered-container {
    display: flex;
    justify-content: center;
}

.pv-powered-container img {
    width: 250px;
}

.pv-modal {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background-color: rgba(0, 0, 0, 0.7);
    opacity: 0;
    visibility: hidden;
    transform: scale(1.1);
    transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;
    font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, sans-serif;
    z-index: 1000;
}

.pv-modal-content {
    position: absolute;
    color: var(--neutral-3);
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: white;
    padding: 24px;
    border-radius: 8px;
    width: 100%;
    max-width: 100vw;
    max-height: 100vh;
    overflow-y: auto;
    transition: max-height 0.15s ease-out;
}

@media (min-width: 480px){
    .pv-modal-content {
        max-width: 540px;
    }
}

.pv-label {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    margin-bottom: 14px;
}

.pv-radio-hidden {
    display: none;
}

.pv-tabs-interest {
    display: flex;
    justify-content: center;
    width: 100%;
}

.pv-tab-interest {
    width: 100%;
    text-align: center;
    margin-top: 10px;
    padding: 20px 20px;
    border-radius: 8px;
    cursor: pointer;
    font-size: 16px;
    background-color: #f1f5f9;
    color: #003960;
    transition: background-color 0.15s ease-out 0s, color 0.15s ease-out 0s;
    border: 1px solid #e2e8f0;
}

.pv-tab-interest:first-child {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.pv-tab-interest:last-child {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.pv-tab-interest:hover {
    background-color: #e2e8f0;
}

.pv-tab-interest:has(input[type=\"radio\"]:checked) {
    border-color: #2569CC;
    border-width: 2px;
}

.pv-lead-input:focus {
    border-color: green;
    /* Cambia el color del borde cuando el campo está enfocado y es inválido */
}

input:invalid:focus {
    border-color: red;
    /* Cambia el color del borde cuando el campo está enfocado y es inválido */
}



.close-button {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    width: 1.5rem;
    line-height: 1.5rem;
    text-align: center;
    cursor: pointer;
    border-radius: 0.25rem;
    font-size: 20px;
    background-color: #f1f5f9;
}

.close-button:hover {
    background-color: #e2e8f0;
}

.show-modal {
    opacity: 1;
    visibility: visible;
    transform: scale(1.0);
    transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;
}

.pv-full-name {
    display: flex;
    gap: 8px;
    width: 100%;
}

.pv-address-wrapper {
    width: 100%;
    display: flex;
    flex-direction: column;
}

.pv-address-title {
    font-size: 24px;
    font-weight: bold;
    color: #003960 !important;
    margin: 0 !important;
}

.pv-address-subtitle {
    margin-top: 4px;
    margin-bottom: 0;
}

.pv-address-subtitle #pv-city,
.pv-address-subtitle #pv-state {
    font-size: 16px;
    margin: 0 !important;
}

.pv-content {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    width: 100%;
}

.pv-subtitle {
    position: relative;
    text-align: center;
    font-size: 21px;
    text-wrap: balance;
    padding-bottom: 6px;
    margin-bottom: 16px;
    font-weight: bold;
}

.pv-input-group {
    position: relative;
}

.pv-input-group svg {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    right: 10px;
    fill: #003960;
    width: 16px;
    height: 16px;
}

.pv-error {
    display: none;
    margin-top: 0;
    color: red;
    font-size: 12px;
}

.pv-submit {
    background-color: #2569CC;
    color: white;
    border: none;
    padding: 15px 30px;
    border-radius: 8px;
    cursor: pointer;
    font-size: 16px;
    margin-top: 20px;
    float: right;
}

.pv-submit.center {
    align-self: center;

}

.plunk-component {
    display: flex;
    justify-content: center;
    gap: 5px;
    margin-top: 40px;
    margin-bottom: 50px;
    width: 100%;
}

.pv-price-symbol {
    margin-right: 10px;
    font-size: 42px;
    font-weight: bold;
    color: #003960;
    margin: 0;
}

.pv-valuation-price {
    font-size: 72px;
    text-align: center;
    font-weight: bold;
    color: #003960;
    margin: 0;
    line-height: 0.9;
}

/* Market insights */
#market-insights-container {
    padding-top: 30px;
    width: 100%;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.15s ease-out;
}

#market-insights-container.market-insights-expanded {
    grid-template-rows: 1fr;
    border-top: solid 1px #E6EBEF;
}

.pv-callToAction-wrapper {
    overflow: hidden;
}

.pv-callToAction {
    margin-bottom: 15px;
    background: #1488CC;
    /* fallback for old browsers */
    background: -webkit-linear-gradient(to bottom, #2B32B2, #1488CC);
    /* Chrome 10-25, Safari 5.1-6 */
    background: linear-gradient(to bottom, #2B32B2, #1488CC);
    /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
    border-radius: 13px;
    color: white;
    padding: 19px;
    font-size: 14px;
    overflow: hidden;
}

.pv-cta-form {
    box-sizing: inherit;
    position: relative;
    min-width: 168px;
    display: flex;
    justify-content: center;
    margin: 0;
    margin: 15px 0;
}

.pv-callToAction h2 {
    font-size: 22px;
    margin-bottom: 18px;
    font-weight: bold;
    color: white;
}

.pv-callToAction p {
    font-size: 13px;
}

@media (min-width: 480px) {

    .pv-callToAction h2 {
        font-size: 24px;
    }

    .pv-callToAction p {
        font-size: 16px;
    }
}

.pv-email {
    border-radius: 8px;
    padding: 6px 9px;
}

.css-1s4q5ra {
    width: 100%;
}

.pac-container {
    top: 60px !important;
    left: 0px !important;
}

/* Skeleton loader Animations */
.pv-skeleton-wrapper {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.pv-skeleton-animation {
    animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.pv-ticker-big-skeleton {
    margin-top: 35px;
    width: 268px;
    height: 60px;
    background-color: #BFCDD7;
    border-radius: 4px;
}

.pv-ticker-small-skeleton {
    margin-top: 5px;
    width: 124px;
    height: 37px;
    background-color: #E6EBEF;
    border-radius: 4px;
}

@keyframes pulse {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: .5;
    }
}

.plunk-home-no-value-home-value {
    font-family: inherit;
    letter-spacing: -1px;
    font-size: 24px;
    margin-top: 0.3rem;
    font-weight: 700;
    color: #003960;
    text-align: center;
}

.plunk-home-no-value-suffix {
    margin-left: auto;
    margin-right: auto;
    width: 77%;
    text-align: center;
    font-family: inherit;
    color: #406A88;
    font-weight: 500;
    font-size: 18px;
    margin-top: 0.6rem;
}

/* TODO remove */
.site-header {
    z-index: unset;
}</style>
            <div id="plunk-valuation-wrapper">
                <div class="pv-heading-container">
                    <span>How much is your home worth right now?</span>
                </div>
                <form id="pv-form" class="pv-input-container">
                    <label class="pv-label">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi" viewBox="0 0 512 512"><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"></path></svg>
                        <input id="pv-address" name="address" class="pv-input" autocomplete="off" placeholder="Enter an address">
                    </label>
                    <button type="submit" aria-label="search" class="pv-button">
                        <span>Go</span>
                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M12.1004 3.51506C12.4909 3.12454 13.1241 3.12454 13.5146 3.51506L21.2674 11.2678C21.276 11.2758 21.2844 11.284 21.2928 11.2924C21.4882 11.4877 21.5858 11.7438 21.5857 11.9999C21.5858 12.256 21.4882 12.5121 21.2928 12.7074C21.2844 12.7158 21.276 12.724 21.2674 12.732L13.5146 20.4848C13.1241 20.8753 12.4909 20.8753 12.1004 20.4848C11.7099 20.0942 11.7099 19.4611 12.1004 19.0705L18.1711 12.9998L2.9999 12.9998C2.44762 12.9998 1.9999 12.5521 1.9999 11.9998C1.9999 11.4476 2.44762 10.9998 2.9999 10.9998H18.171L12.1004 4.92927C11.7099 4.53875 11.7099 3.90559 12.1004 3.51506Z" fill="white"></path>
                        </svg>
                    </button>
                </form>
                <p class="pv-error pv-address-error" id="pv-address-error">Please choose an address from the suggestions.</p>
                <div class="pv-powered-container">
                    <img src="https://images.leadconnectorhq.com/image/f_webp/q_80/r_1200/u_https://assets.cdn.filesafe.space/LB6pV83yCjjuXJZqjSMq/media/67d07e47de31f45f561eacd6.png" alt="Home Valuation Logo" />
                </div>
            </div>
            <div class="pv-modal" id="pv-lead-modal">
            <form class="pv-modal-content" id="lead-form">
                <h2 class="pv-subtitle">One step closer to getting your free valuation!</h2>
                <span class="close-button">&times;</span>
            <div class="pv-full-name">
                <label class="pv-label"> First name * <div class="pv-input-group"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.1 by @fontawesome  - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z"/></svg><input/ type="text" placeholder="John" name="first_name" class="pv-lead-input" required></div></label>
                <label class="pv-label"> Last name * <div class="pv-input-group"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.1 by @fontawesome  - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z"/></svg><input/ type="text" placeholder="Doe" name="last_name" class="pv-lead-input" required></div></label>
                </div>
                <label class="pv-label"> Email * <div class="pv-input-group"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome  - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"/></svg><input/ type="text" placeholder="example@example.com" name="email" class="pv-lead-input"></div><p class="pv-error">Please submit a valid email</p>
                </label>
                <label class="pv-label">Phone * <div class="pv-input-group"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome  - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M164.9 24.6c-7.7-18.6-28-28.5-47.4-23.2l-88 24C12.1 30.2 0 46 0 64C0 311.4 200.6 512 448 512c18 0 33.8-12.1 38.6-29.5l24-88c5.3-19.4-4.6-39.7-23.2-47.4l-96-40c-16.3-6.8-35.2-2.1-46.3 11.6L304.7 368C234.3 334.7 177.3 277.7 144 207.3L193.3 167c13.7-11.2 18.4-30 11.6-46.3l-40-96z"/></svg><input type="tel" placeholder="(555) 123-4567" name="phone" class="pv-lead-input" maxlength="16" onInput="this.value = phoneFormat(this.value)">     
                    </div>
                    <p class="pv-error">Please submit a valid phone number</p>
                </label>
                <h3 style="margin-bottom: 0;">Select Your Purpose</h3>
                <div class="pv-tabs-interest">
                    <label class="pv-tab-interest">Buying<input type="radio" name="interest" value="buying" checked class="pv-radio-hidden" required/></label>
                    <label class="pv-tab-interest">Selling<input type="radio" name="interest" value="selling" class="pv-radio-hidden"/></label>
                </div>
                <button type="submit" aria-label="search" class="pv-submit">Submit</button>
                </form>
            </div>
            <div class="pv-modal" id="pv-valuation">
            <div class="pv-modal-content">
                <span class="close-button">&times;</span>

                <div class="pv-content">

                <div class="pv-address-wrapper">     
                    <h2 class="pv-address-title" id="pv-address"></h2>
                    <p class="pv-address-subtitle"><span id="pv-city"></span><span id="pv-state"></span></p>
                </div>

                <div class="pv-skeleton-wrapper">
                    <div class="pv-ticker-big-skeleton pv-skeleton-animation">
                    </div>
                    <div class="pv-ticker-small-skeleton pv-skeleton-animation">
                    </div>
                </div>

                <div class="plunk-component" id="rc_home_value" data-component-id="rc_home_value">
                    <p class="pv-price-symbol">$</p>
                    <div id="valuationPrice" class="pv-valuation-price">

                    </div>
                </div>

                <div id="pv-no-results" style="display: none; flex-direction: column;">
                    <div>
                        <div style="display: flex; justify-content: center">
                            <div style="margin-top:20px;">
                                <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path fill-rule="evenodd" clip-rule="evenodd" d="M18 4.8C10.7098 4.8 4.8 10.7098 4.8 18C4.8 25.2902 10.7098 31.2 18 31.2C25.2902 31.2 31.2 25.2902 31.2 18C31.2 10.7098 25.2902 4.8 18 4.8ZM18 1.5C27.1127 1.5 34.5 8.8873 34.5 18C34.5 27.1127 27.1127 34.5 18 34.5C8.8873 34.5 1.5 27.1127 1.5 18C1.5 8.8873 8.8873 1.5 18 1.5ZM16.35 19.65V9.75H19.65V19.65H16.35ZM18 22.95C18.9113 22.95 19.65 23.6887 19.65 24.6C19.65 25.5113 18.9113 26.25 18 26.25C17.0887 26.25 16.35 25.5113 16.35 24.6C16.35 23.6887 17.0887 22.95 18 22.95Z" fill="#406A88"></path>
                                </svg>
                            </div>
                        </div>

                        <div style="display: flex; justify-content: center">
                            <div class="plunk-home-no-value-home-value">
                                Valuation information for <span class="plunk-home-no-value-home-value" id="address-no-value"></span>
                                is currently missing.
                            </div>
                        </div>
                        
                        <div class="plunk-home-value-appreciation-container-no-data">
                            <div class="plunk-home-no-value-suffix">Sorry, HomeValuation.ai does not have enough information to determine an accurate home value</div>
                        </div>
                    </div>   
                </div>

                <div id="pv-service-error" style="display: none; flex-direction: column;">
                    <div>
                        <div style="display: flex; justify-content: center">
                            <div style="margin-top:20px;">
                                <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path fill-rule="evenodd" clip-rule="evenodd" d="M18 4.8C10.7098 4.8 4.8 10.7098 4.8 18C4.8 25.2902 10.7098 31.2 18 31.2C25.2902 31.2 31.2 25.2902 31.2 18C31.2 10.7098 25.2902 4.8 18 4.8ZM18 1.5C27.1127 1.5 34.5 8.8873 34.5 18C34.5 27.1127 27.1127 34.5 18 34.5C8.8873 34.5 1.5 27.1127 1.5 18C1.5 8.8873 8.8873 1.5 18 1.5ZM16.35 19.65V9.75H19.65V19.65H16.35ZM18 22.95C18.9113 22.95 19.65 23.6887 19.65 24.6C19.65 25.5113 18.9113 26.25 18 26.25C17.0887 26.25 16.35 25.5113 16.35 24.6C16.35 23.6887 17.0887 22.95 18 22.95Z" fill="#406A88"></path>
                                </svg>
                            </div>
                        </div>

                        <div style="display: flex; justify-content: center">
                            <div class="plunk-home-no-value-home-value">
                                Something went wrong on our end.
                            </div>
                        </div>

                        <div class="plunk-home-value-appreciation-container-no-data">
                            <div class="plunk-home-no-value-suffix">We could not complete your valuation just now. Please try again in a moment.</div>
                        </div>
                    </div>
                </div>

                <div id="pv-limit" style="display: none; flex-direction: column;">
                    <p style="margin-bottom: 5px;  text-align: center; font-weight: 800; font-size: 24px; color: #003960;">Limit reached</p>
                    <p style="margin: 0; color: #456E8B; text-align: center; font-size: 18px; line-height: 1.4;">The limit of valuations has been reached, <br> contact tania@itstheperfectspot.com to get <br> a Home Valuation.</p>  
                </div>
                
                <div id="sms_results" style="width:100%;overflow-y: hidden;"></div>
                
                <div id="market-insights-container">
                    <div class="pv-callToAction-wrapper">            
                    <div class="pv-callToAction">
                        <h2>Unlock your market insights now</h2>
                        <p style="color: white;">You are just one step away from getting the Market Insights for your home at <span id="pv-address-2"></span>.</p>
                        <p style="color: white;">Please press the confirm button bellow and we will shoot that right over to you. </p>
                        <form id="pv-cta-form" class="pv-cta-form">
                            <button id="pv-cta-button" class="pv-submit center" type="submit" aria-label="search" style="margin-top:0; background: white; color: #2569CC;">Confirm</button>
                        </form>
                        <p style="margin-top: 8px; font-size: 10px; color: white;">Your personal information is strictly confidential and will not be shared with any outside organization. By submitting this form with your telephone number, you authorize us and our authorized representatives to contact you even if your name is on the federal "Do Not Call" list.</p>
                    </div>
                    </div>
                </div>

                <div id="pv-thank-you" style="display: none; flex-direction: column;">
                    <img src="https://idxapps.sfo3.digitaloceanspaces.com/PlunkHomeValuation/mail_wpwyse.png" width="100" style="margin: 0 auto; max-width: 100%; height: auto;">
                    <h3 style="font-size: 25px; color: #003960; font-weight: bold; text-align: center; margin: 10px auto 8px auto;">Thank You</h3>
                    <p>We just sent you a text message with more information about </p>       
                    <p id="pv-thankyou-address"> </p>.
                </div>

                <div class="pv-powered-container">
                    <img src="https://images.leadconnectorhq.com/image/f_webp/q_80/r_1200/u_https://assets.cdn.filesafe.space/LB6pV83yCjjuXJZqjSMq/media/67d07e47de31f45f561eacd6.png" alt="Home Valuation Logo" />
                </div>

                </div>
            </div>
            </div>`;

        thisScript.insertAdjacentHTML('afterend', html);

        const form = document.getElementById('pv-form');
        form.addEventListener('submit', onSubmit);

        const addressInput = document.getElementById('pv-address');
        if (addressInput) {
            addressInput.addEventListener('input', function() {
                setAddressError(false);

                // Editing the text after picking a suggestion invalidates it --
                // otherwise you could select one address, type over it, and get
                // a valuation for the one you replaced.
                //
                // Compared against the value Google itself wrote, because
                // assigning input.value programmatically does not fire 'input';
                // only the user's own typing reaches this.
                if (addressInput.value !== selectedAddressText) {
                    addressObj = {};
                }
            });
        }

        const leadForm = document.getElementById('lead-form');
        leadForm.addEventListener('submit', getLeadData);
        const marketForm = document.getElementById('pv-cta-form');
        marketForm.addEventListener('submit', onMarketInsightsSubmit);

        modal = document.querySelector("#pv-valuation");
        const closeButtons = document.querySelectorAll(".close-button");

        closeButtons.forEach((button) => {
            button.addEventListener("click", toggleModal);
        });
        window.addEventListener("click", windowOnClick);

        function toggleModal() {
            const currentModal = document.querySelector(".pv-modal.show-modal");
            currentModal.classList.remove("show-modal");
        }

        function windowOnClick(event) {
            const currentModal = document.querySelector(".pv-modal.show-modal");
            if (event.target === currentModal) {
                toggleModal();
            }
        }
    }

    async function trackUsage() {

        // call to /plunkvaluation/has-permission/{uid}
        const url = `https://idxapps.com/api/plunkvaluation/has-permission/7ea5b1580e16e`;

        const options = {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
            },
        };

        // Returns null on any failure rather than throwing. A 500 here renders
        // an HTML error page, and calling .json() on that rejects -- which used
        // to abort getPlunkHomeValue() before it ever reached the valuation
        // call, leaving the modal on the skeleton with no error anywhere.
        try {
            const apiRes = await fetch(url, options);

            if (!apiRes.ok) {
                console.error('HomeValuation: permission check responded ' + apiRes.status);
                return null;
            }

            return await apiRes.json();
        } catch (err) {
            console.error('HomeValuation: permission check failed', err);
            return null;
        }
    }

    async function successValuation() {

        const url = `https://idxaddons.com/src/Plunk/Tracking.php?user_id=$id$&success=1`;

        const options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
        };

        const apiRes = await fetch(url, options);
        const response = await apiRes.json();

        return response;
    }


    function phoneFormat(input) { //returns (###) ###-####
        input = input.replace(/\D/g, '');
        var size = input.length;
        if (size > 0) {
            input = "(" + input
        }
        if (size > 3) {
            input = input.slice(0, 4) + ") " + input.slice(4, 11)
        }
        if (size > 6) {
            input = input.slice(0, 9) + "-" + input.slice(9)
        }
        return input;
    }

    // Using all caps with the address string values will help with validation
    let addressObj = {};
    // The input value at the moment a suggestion was accepted, so typing over it
    // can be told apart from Google writing it.
    let selectedAddressText = "";
    let valuationsData = {};
    let home_valuation_id = null;

    // Fetch real home value data from the API using the address in addressObj
    const getPlunkHomeValue = async (addressObj) => {

        valuationsData = await trackUsage();

        // trackUsage() returns null when its own call failed, so treat an
        // unknown permission state as a service error rather than assuming
        // permission -- and never return undefined, which the caller would
        // dereference.
        if (!valuationsData) {
            return { success: false, reason: 'error' };
        }

        if (!valuationsData.hasPermission) {
            console.log('no permission');
            limitReachedMessage();
            return { success: false, reason: 'limit' };
        }

        const params = {
            address: addressObj.addressLineOne,
            cityName: addressObj.city,
            stateAbrv: addressObj.state,
            zipcode: addressObj.zipcode,
            first_name: addressObj.first_name,
            last_name: addressObj.last_name,
            email: addressObj.email,
            phone: addressObj.phone,
            interest: addressObj.interest,
        }
        const query = Object.keys(params).map(key => {
            return `${key}=${encodeURIComponent(params[key])}`;
        }).join('&');
        // TODO replace .test for .com
        console.log(query)
        const url = `https://idxapps.com/api/plunkvaluation/7ea5b1580e16e?${query}`;

        const options = {
            method: "GET",
            headers: {
                // Accept matters: without it Laravel renders an HTML error page
                // for a 500, which .json() below cannot parse.
                "Accept": "application/json",
                "Content-Type": "application/json",
            },
        };

        let apiRes;

        try {
            apiRes = await fetch(url, options);
        } catch (err) {
            console.error('HomeValuation: valuation request failed', err);
            return { success: false, reason: 'error' };
        }

        // A server fault is not the same as "we have no data for this address",
        // and telling the visitor their address is unknown when the service is
        // down sends them chasing the wrong problem.
        if (!apiRes.ok) {
            console.error('HomeValuation: valuation responded ' + apiRes.status);
            return { success: false, reason: 'error' };
        }

        let homeValueData;

        try {
            homeValueData = await apiRes.json();
        } catch (err) {
            console.error('HomeValuation: valuation returned an unreadable body', err);
            return { success: false, reason: 'error' };
        }

        if (homeValueData && homeValueData.success === false) {
            homeValueData.reason = 'no_data';
        }
        console.log(homeValueData);

        sendToGHL(query, homeValueData);

        return homeValueData;
    };

    const sendToGHL = async (query, homeValueData) => {
        let homeValueRecord = homeValueData.homeValuation || {};
        let price = homeValueRecord.valuation_dollars || 0;
        query += `&valuation_dollars=${price}`;
        // Send data to GHL
        const url = `https://idxapps.com/api/plunk-send-ghl/7ea5b1580e16e?${query}`;
        const options = {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
            },
        };
        try {
            const apiRes = await fetch(url, options);
            const responseData = await apiRes.json();

            if (!responseData.success) {
                console.log(responseData.message);
                return {
                    success: false,
                    message: responseData.message
                };
            } else {
                console.log(responseData.message);
                // Additional processing for successful response
                return {
                    success: true,
                    message: responseData.message
                };
            }
        } catch (error) {
            console.error("Error:", error);
            return {
                success: false,
                error: error.message
            };
        }
    };

    const renderHomeValue = async (addressObj) => {

        // Get real Home Value data from Plunk's API
        modal.querySelector('#rc_home_value').style.display = 'none';

        let homeValueData = await getPlunkHomeValue(addressObj);

        // Check BEFORE dereferencing. This used to read .homeValuation and then
        // .home_valuation_id off it two lines before testing success, so any
        // failure threw a TypeError, showNotFoundForm() was unreachable, and the
        // modal sat on the loading skeleton forever.
        if (!homeValueData || homeValueData.success === false) {
            if (homeValueData && homeValueData.reason === 'error') {
                showServiceErrorForm();
            } else if (homeValueData && homeValueData.reason === 'limit') {
                // limitReachedMessage() has already painted.
            } else {
                showNotFoundForm();
            }

            return undefined;
        }

        const homeValuationRecord = homeValueData.homeValuation;

        if (!homeValuationRecord) {
            showNotFoundForm();
            return undefined;
        }

        home_valuation_id = homeValuationRecord.home_valuation_id ?? null;

        modal.querySelector('#rc_home_value').style.display = 'flex';

        // Home Valuation AI home value component
        if (homeValuationRecord) {

            const widget = document.querySelector('.plunk-component');
            const priceDiv = widget.querySelector('#valuationPrice');

            const price = homeValuationRecord.valuation;
            const priceNumber = Number(price); // Convert to number
            const priceFormatted = priceNumber.toLocaleString('en-US', {
                currency: 'USD',
                minimumFractionDigits: 0,
                maximumFractionDigits: 0
            });
            priceDiv.textContent = priceFormatted;

            plunkFillData();

            modal.querySelector('.pv-skeleton-wrapper').style.display = "none";

            modal.querySelector('#market-insights-container').classList.add('market-insights-expanded');
        }
    };


    function plunkFillData() {
        modal.querySelector('#pv-address').textContent = addressObj.addressLineOne;
        modal.querySelector('#pv-address-2').textContent = addressObj.addressLineOne;
        modal.querySelector('#pv-city').textContent = addressObj.city;
        modal.querySelector('#pv-state').textContent = ', ' + addressObj.state;
    }


    function initializeSearchBox() {
        input = document.querySelector('#pv-address');
        options = {
                types: ["address"]
            },

            searchBox = new google.maps.places.Autocomplete(input, options);


        searchBox.setComponentRestrictions({
            "country": "us"
        });
        searchBox.setFields(['address_components', 'name']); //Important
        searchBox.addListener('place_changed', function() {
            // Nothing in here may throw. Google dispatches this listener itself
            // and swallows exceptions, so a single bad read used to leave
            // addressObj empty and make the Go button silently inert.
            try {
                place = searchBox.getPlace();

                // Submitting without picking a suggestion still fires this, but
                // getPlace() then returns a stub carrying only the typed text.
                address = (place && place.address_components) || [];

                // Not every address has a locality. New York boroughs come back
                // as sublocality, unincorporated areas as a county-level
                // component -- and previously any of those threw on .long_name.
                city = componentValue(address, ["locality", "sublocality", "sublocality_level_1",
                    "administrative_area_level_3", "neighborhood"
                ]);
                state = componentValue(address, ["administrative_area_level_1"], "short_name");
                zipcode = componentValue(address, ["postal_code"]);

                const line = (place && place.name) ? place.name : "";

                // A street with no house number ("Santana Row, San Jose, CA")
                // comes back with no postal_code, so require a state plus
                // either a city or a zip rather than demanding all three.
                if (line && state && (city || zipcode)) {
                    addressObj = {
                        addressLineOne: line,
                        aptNum: "",
                        city: city,
                        state: state,
                        zipcode: zipcode,
                    };
                    selectedAddressText = input ? input.value : "";
                    setAddressError(false);
                } else {
                    // Deliberately left empty rather than half-populated: the
                    // valuation lookup needs a real address, and a partial one
                    // would fail further in with a worse message.
                    addressObj = {};
                }
            } catch (err) {
                addressObj = {};
                console.error('HomeValuation: could not read the selected place', err);
            }
        });

        setTimeout(function() {
            const inputContainer = document.querySelector('.pv-input-container');
            const pacContainer = document.querySelector('.pac-container');

            // append(null) would insert a literal "null" text node into the
            // form -- an in-flow child that shifts the absolutely positioned
            // search icon off the input.
            if (inputContainer && pacContainer) {
                inputContainer.append(pacContainer);
            }
        }, 1000)
    }

    // First matching component, or '' -- never undefined, so callers can't blow
    // up reading a property off a miss.
    function componentValue(components, types, key) {
        key = key || "long_name";

        for (let i = 0; i < types.length; i++) {
            const match = getComponent(components || [], types[i]);

            if (match && match[key]) {
                return match[key];
            }
        }

        return "";
    }

    function setAddressError(show) {
        const error = document.querySelector('#pv-address-error');

        if (error) {
            error.style.display = show ? 'block' : 'none';
        }
    }

    function validatePhone(number) {
        const regex = /^\(\d{3}\) \d{3}-\d{4}$/;
        return regex.test(number);
    }

    function validateEmail(email) {
        const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return regex.test(email);
    }


    function getLeadData(e) {
        e.preventDefault();
        const form = document.getElementById('lead-form');
        const formData = new FormData(form);
        for (const pair of formData.entries()) {

            if (pair[0] === 'phone') {
                const input = document.querySelector("[name='phone']");
                if (!validatePhone(pair[1])) {
                    input.parentElement.parentElement.querySelector("p").style.display = "block";
                    input.style.border = "1px solid red";
                    return;
                }
                input.parentElement.parentElement.querySelector("p").style.display = "none";
                input.style.border = "";
            }
            if (pair[0] === 'email') {
                const input = document.querySelector("[name='email']");
                if (!validateEmail(pair[1])) {
                    input.parentElement.parentElement.querySelector("p").style.display = "block";
                    input.style.border = "1px solid red";
                    return;
                }
                input.parentElement.parentElement.querySelector("p").style.display = "none";
                input.style.border = "";
            }
            addressObj[pair[0]] = pair[1];
        }
        document.querySelector("#pv-lead-modal").classList.toggle("show-modal");
        document.querySelector("#pv-valuation").classList.toggle("show-modal");

        renderHomeValue(addressObj);
    }

    function getComponent(array, search) {
        return array.find(function(component) {
            return component.types.includes(search);
        })
    }

    function onSubmit(event) {
        event.preventDefault();

        // Used to be a bare `return`. With no error element and no `required`
        // on the input, pressing Go with an unresolved address produced nothing
        // at all -- no modal, no message, no native validation bubble.
        if (Object.keys(addressObj).length === 0) {
            setAddressError(true);

            const input = document.querySelector('#pv-address');
            if (input) input.focus();

            return;
        }

        setAddressError(false);

        // Reset all the values
        modal.querySelector('#pv-address').textContent = addressObj.addressLineOne;
        modal.querySelector('#pv-city').textContent = addressObj.city;
        modal.querySelector('#pv-state').textContent = ' ' + addressObj.state;
        modal.querySelector('#rc_home_value').style.display = 'block';
        modal.querySelector('.pv-skeleton-wrapper').style.display = "flex";
        modal.querySelector('#market-insights-container').classList.remove('market-insights-expanded');
        modal.querySelector('#pv-no-results').style.display = 'none';
        modal.querySelector('#pv-service-error').style.display = 'none';
        modal.querySelector('#pv-thank-you').style.display = 'none';

        if (document.querySelector("#pv-tel") != null) {
            document.querySelector("#pv-tel").value = ""; //clear phone
        }
        if (document.querySelector("#pv-email") != null) {
            document.querySelector("#pv-email").value = ""; //clear email
        }

        // Show modal at the end
        document.querySelector("#pv-lead-modal").classList.toggle("show-modal");

    }

    async function onMarketInsightsSubmit(event) {
        event.preventDefault();

        modal.querySelector('#pv-cta-button').classList.add('is-loading');

        let phone = addressObj.phone;
        let email = addressObj.email;



        console.log('email', email);
        console.log('phone', phone);


        const url = `https://idxapps.com/api/plunkvaluation/send/7ea5b1580e16e`;

        console.log(url);

        const marketInsightData = {
            phone,
            email,
            home_valuation_id: home_valuation_id,
        }
        console.log(marketInsightData);

        const options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify(marketInsightData)
        };

        let output = '';
        let data = null;

        // Unchecked before: a 500 returns an HTML page, .json() rejects, and the
        // Confirm button stays stuck in its loading state with nothing shown.
        try {
            const response = await fetch(url, options);

            if (response.ok) {
                data = await response.json();
            } else {
                console.error('HomeValuation: market insights responded ' + response.status);
            }
        } catch (err) {
            console.error('HomeValuation: market insights request failed', err);
        }

        if (!data || data.type == 'error') { //load json data from server and output message
            modal.querySelector('#pv-cta-button').classList.remove('is-loading');
            output = '<div class="pv-alert pv-alert-danger">Sorry, we could not send that just now. Please try again in a moment.</div>';
        } else {
            modal.querySelector('#pv-thank-you').style.display = 'flex';
            modal.querySelector('#pv-cta-button').classList.remove('is-loading');
            modal.querySelector('#market-insights-container').classList.remove('market-insights-expanded');
            modal.querySelector('#rc_home_value').style.display = 'none';
            modal.querySelector('.pv-skeleton-wrapper').style.display = "none";
            modal.querySelector('#pv-address').textContent = '';
            modal.querySelector('#pv-city').textContent = '';
            modal.querySelector('#pv-state').textContent = '';
            modal.querySelector('#pv-thankyou-address').textContent = addressObj.addressLineOne;
        }

        const alertDiv = document.querySelector("#sms_results")
        alertDiv.innerHTML = output;

        // firstChild is null whenever output stayed empty (the success path),
        // which threw and skipped everything after this.
        if (alertDiv.firstChild && alertDiv.firstChild.classList) {
            alertDiv.firstChild.classList.add('show');
        }

        modal.querySelector('#pv-cta-button').classList.remove('is-loading');

        setTimeout(function() {
            alertDiv.firstChild.classList.remove('show');
        }, 3000);
    }

    async function showNotFoundForm() {
        // Was `await this.getMarketInsights()` -- `this` is not the object that
        // holds it, and the result was only logged. It also delayed the panel by
        // a whole round trip, so the skeleton kept spinning for no reason.
        modal.querySelector('#pv-service-error').style.display = 'none';
        modal.querySelector('#pv-no-results').style.display = 'flex';
        modal.querySelector('.pv-callToAction-wrapper').style.display = 'none';
        modal.querySelector('#rc_home_value').style.display = 'none';
        modal.querySelector('.pv-skeleton-wrapper').style.display = "none";
        modal.querySelector('#pv-address').textContent = '';
        modal.querySelector('#pv-city').textContent = '';
        modal.querySelector('#pv-state').textContent = '';

        let address = addressObj.addressLineOne;
        modal.querySelector('#address-no-value').textContent = `${address}`

    }

    // The valuation could not be completed for a reason that is ours, not the
    // address's. Kept distinct from #pv-no-results so an outage does not tell
    // the visitor their home does not exist.
    function showServiceErrorForm() {
        modal.querySelector('#pv-service-error').style.display = 'flex';
        modal.querySelector('#pv-no-results').style.display = 'none';
        modal.querySelector('.pv-callToAction-wrapper').style.display = 'none';
        modal.querySelector('#rc_home_value').style.display = 'none';
        modal.querySelector('.pv-skeleton-wrapper').style.display = "none";
        modal.querySelector('#pv-address').textContent = '';
        modal.querySelector('#pv-city').textContent = '';
        modal.querySelector('#pv-state').textContent = '';
    }

    function limitReachedMessage() {
        modal.querySelector('#pv-service-error').style.display = 'none';
        modal.querySelector('#pv-limit').style.display = 'flex';
        modal.querySelector('#pv-no-results').style.display = 'none';
        modal.querySelector('.pv-callToAction-wrapper').style.display = 'none';
        modal.querySelector('#rc_home_value').style.display = 'none';
        modal.querySelector('.pv-skeleton-wrapper').style.display = "none";
        modal.querySelector('#pv-address').textContent = '';
        modal.querySelector('#pv-city').textContent = '';
        modal.querySelector('#pv-state').textContent = '';
    }

    async function getMarketInsights() {
        let zipCode = addressObj.zipcode;
        const market_insights_url = `https://idxapps.com/api/marketInsights/${zipCode}`;
        const response = await fetch(market_insights_url);
        if (response.status !== 200) {
            return null;
        }
        const marketInsights = await response.json();

        return marketInsights;
    }

