
  class PlunkValuation extends HTMLElement
  {
    // Private properties
    root;
    address;
    phone;
    email;
    home_valuation_id;
    userInfo; // Store user info from pre-valuation form
    collectUserInfoTiming = 'after_valuation';

    constructor() {
      super(); // to ensure that this class inherits all of the properties and methods of the HTMLElement class
      this.root = this.attachShadow({ mode: 'open' }); // Create a shadow root
      this.root.innerHTML = this.#htmlContent(); // Add html content to the shadow root

      const fontStyles = document.createElement('link'); // Import font styles
      fontStyles.setAttribute('rel', 'stylesheet');
      fontStyles.setAttribute('href', "https://app.homevaluation.ai/css/sailec.css");
      document.head.appendChild(fontStyles);

      const style = document.createElement('style'); // Apply CSS styling to the component
      style.textContent = `:host{--font-family:"Sailec","Open Sans",sans-serif;--primary:#2dd9a2;--primary-vibrancy:#20be8e;--secondary:#2f82ff;--secondary-vibrancy:#2569cc;--secondary-tints:#eaf3ff;--neutral-3:#003960;--neutral-4:#406a88;--neutral-5:#809caf;--neutral-7:#e6ebef;--error:#f56a58;--error-vibrancy:#e05547;--white:#fff;--text-color:#000}@media only screen and (max-width:500px){.shevron-back{margin-left:0!important}.plunk-home-value-appreciation-container{margin-bottom:0!important}.market-insights-img{height:100%!important;width:45%!important}#pv-report-id{font-size:12px!important}.autocomplete-item{font-size:14px!important}#market-insights-container{grid-template-columns:1fr!important;grid-template-rows:0fr 0fr!important}#market-insights-container.market-insights-expanded{grid-template-rows:1fr 0fr!important}.modal-content{width:85%!important}.pv-heading-container,.report-title{font-size:20px!important}.pv-heading-subheader-container{font-size:15px!important}#main-title{margin-top:10px!important}#title-container{height:85px!important}#report-title-subheader,#reported-title-subheader{margin-top:40px!important}.pv-button{font-size:13px!important;padding:12px 17px!important;width:82px!important}.pv-button-reported{font-size:14px!important;width:175px!important}.pv-button-report{font-size:14px!important;width:158px!important}}#map-skeleton-loader img{height:158%;-o-object-fit:cover;object-fit:cover;width:100%}#forms-content{height:50px;position:relative}#title-container{display:flex;height:50px;justify-content:center}#main-title{position:absolute!important}#report-title-subheader,#reported-title-subheader{margin-top:50px}#pv-report-id{color:#6da8ff;cursor:pointer;font-size:13px;padding-left:4px;padding-top:10px;width:-moz-fit-content;width:fit-content}.position-absolute{position:absolute!important}.transition{transition:.3s ease}.transition-height{transition-property:height}.transition-opacity{transition-property:opacity}.opacity-hidden{opacity:0}.form-autocomplete,.form-report-address{left:10px;right:10px}.button-report{height:48px;margin-top:25px!important;margin:0 auto;position:relative}.pv-button-reported{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:color-mix(in srgb,var(--secondary) 40%,#fff);border:2px solid var(--secondary);border-radius:26px;color:var(--secondary);cursor:pointer;display:flex;font-size:17px;font-weight:600;justify-content:space-between;left:0;margin:0 auto;padding:12px 22px;pointer-events:all;right:0;width:206px;z-index:19}label>.bi{color:#7d95a7;left:18px;position:absolute;top:50%;transform:translateY(-50%);z-index:11}label{position:relative}#plunk-valuation-wrapper{font-family:var(--font-family);letter-spacing:normal!important;line-height:normal!important}#plunk-valuation-wrapper,#plunk-valuation-wrapper-report-address{background-color:#fff;border-radius:16px;box-sizing:border-box;color:var(--text-color);margin:0 auto;max-width:600px;padding:16px 20px}.pv-heading-container{color:var(--text-color);font-size:24px;font-weight:700;margin-bottom:24px;text-align:center}.report-address{margin-bottom:12px!important}.pv-heading-subheader-container{color:var(--secondary);font-size:18px;margin-bottom:24px;text-align:center}.pv-input-container{box-sizing:inherit;display:block;margin:0;min-width:168px;position:relative}.pv-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:1px solid #bfcdd7;border-radius:101px;box-sizing:border-box;color:rgba(0,0,0,.7);font-size:13px;height:50px!important;min-width:84px;outline-offset:.5px;padding:4px 97px 2px 42px;position:relative;width:100%!important;z-index:10}.pv-input:focus-visible{border:1px solid var(--secondary);box-shadow:0 0 0 1px var(--secondary);outline:none}@media (min-width:480px){.pv-input{font-size:16px}}.search-button-label{margin-right:6px}.pv-button{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--secondary);border:none;border-radius:26px;bottom:0;color:#fff!important;cursor:pointer;display:flex;font-family:var(--font-family);font-size:18px;font-weight:700;justify-content:space-between;margin:4px;padding:12px 22px;pointer-events:all;position:absolute;right:0;top:0;width:-moz-fit-content;width:fit-content;z-index:20}.pv-button:hover{background-color:color-mix(in srgb,var(--secondary) 90%,#000)}.pv-button-report:hover{background-color:color-mix(in srgb,var(--secondary) 40%,#fff)}.pv-button-report{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border:2px solid var(--secondary);border-radius:26px;display:flex;font-size:17px;font-weight:600;justify-content:space-between;left:0;margin:0 auto;padding:12px 22px;pointer-events:all;right:0;width:177px;z-index:20}.chevron-left,.pv-button-report{color:var(--secondary);cursor:pointer}.chevron-left{height:24px;margin-left:18px;width:24px}@media (min-width:480px){.pv-button{font-size:16px}}#pv-cta-button.is-loading{opacity:.5;pointer-events:none}.powered-by-container{align-items:center;display:flex;gap:8px;justify-content:center;margin-top:20px}.powered-by-container p{font-family:var(--font-family);margin:0}.powered-by-container img{height:30px;width:200px}.modal{background-color:rgba(0,0,0,.7);height:100%;left:0;letter-spacing:normal!important;line-height:normal!important;opacity:0;position:fixed;top:0;transform:scale(1.1);transition:visibility 0s linear .25s,opacity .25s 0s,transform .25s;visibility:hidden;width:100%;z-index:1000}.show-modal{opacity:1;transform:scale(1);transition:visibility 0s linear 0s,opacity .25s 0s,transform .25s;visibility:visible}.row{display:flex}.column{padding:9px 4px 9px 9px}.address{font-size:16px;font-weight:500}.address,.city{color:var(--text-color);font-family:var(--font-family)!important;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.city{font-size:12px;padding-top:2px}.column2{flex:50%;padding-top:14px}.houseImage{background-position:50%;background-repeat:no-repeat;background-size:175px;border:2px solid #fff;border-radius:50px;box-shadow:0 6px 12px -2px rgba(50,50,93,.25),0 3px 7px -3px rgba(0,0,0,.3);height:45px;width:45px}.show-address-bubble{opacity:1!important;transform:translateY(0)!important}.shevron-back{color:var(--secondary);display:flex;left:0;margin-left:10px;margin-top:33px;place-content:center;position:absolute;width:20%}.shevron-back-img{border-radius:100%;cursor:pointer}.address-bubble{background-color:#fff;border-radius:8px;box-shadow:0 6px 12px -2px rgba(50,50,93,.25),0 3px 7px -3px rgba(0,0,0,.3);color:var(--text-color);height:64px;left:0;margin-left:auto;margin-right:auto;margin-top:23px;opacity:0;position:absolute;right:0;transform:translateY(100%);transition:transform .4s ease,opacity .2s ease;transition-delay:0s,.2s;width:222px}.address-bubble-arrow{border-left:10px solid transparent;border-right:10px solid transparent;border-top:10px solid #fff;bottom:-8px;height:0;left:50%;position:absolute;transform:translateX(-50%);width:0}.modal-content{background-color:#fff;border-radius:8px;color:var(--text-color);left:50%;max-height:100vh;max-width:100vw;overflow-y:auto;padding:24px;position:absolute;top:50%;transform:translate(-50%,-50%);transition:max-height .15s ease-out;width:100%}@media (min-width:480px){.modal-content{max-width:540px}}.modal-footer{margin-top:24px;width:100%}.close-button{background-color:#f1f5f9;border-radius:.25rem;cursor:pointer;float:right;font-size:18px;line-height:1.5rem;text-align:center;width:1.5rem}.close-button:hover{background-color:#e2e8f0}.pv-address-title{color:var(--text-color)!important;font-size:24px;font-weight:700;margin:0!important}.modal-content #pv-city,.modal-content #pv-state{font-size:16px;margin:0!important}.pv-content{align-items:center;display:flex;flex-wrap:wrap}.plunk-component,.pv-content{justify-content:center;width:100%}.plunk-component{font-family:var(--font-family);gap:5px;margin-bottom:50px;margin-top:40px}.pv-price-symbol{color:#003960;font-size:36px;font-weight:700;margin:0}.pv-valuation-price{color:var(--text-color);font-size:62px;font-weight:600;line-height:.9;margin:0;text-align:center}.pv-price-range{color:var(--text-color);display:flex;font-size:18px;font-weight:500;justify-content:center;padding-top:20px}.range-divider{margin:0 10px}.avm-label,.range-divider{color:var(--text-color);font-size:20px}.avm-label{margin:auto 0}#market-insights-container{display:grid;grid-template-columns:repeat(2,1fr);grid-template-rows:0fr;margin-top:20px;padding-top:24px;transition:grid-template-rows .15s ease-out;width:100%}#market-insights-container.market-insights-expanded{border-top:1px solid var(--neutral-7);grid-template-rows:1fr}.market-insights-left{align-items:center;display:none;flex-direction:column;justify-content:center;opacity:0;overflow:hidden;padding-left:2px;padding-right:2px;pointer-events:none}.market-insights-left.visible{display:flex;opacity:1;pointer-events:auto}.market-insights-cta{color:var(--text-color);font-family:var(--font-family);font-size:22px;font-weight:700;margin-bottom:18px;margin-top:0;text-align:center}.shadow-for-phone-input{border-radius:101px;box-shadow:0 4px 5px hsla(0,0%,51%,.14),0 1px 10px hsla(0,0%,51%,.12),0 2px 4px hsla(0,0%,51%,.2)}.phone-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:1px solid #bfcdd7;border-radius:101px;box-sizing:border-box;color:var(--text-color);font-size:16px;font-weight:700;height:50px;min-width:84px;outline-offset:.5px;padding:4px 78px 2px 20px;position:relative;width:100%;z-index:10}#market-insights-form .pv-button{width:auto}.phone-input::-moz-placeholder{color:#809caf}.phone-input::placeholder{color:#809caf}.phone-input:focus-visible{border:1px solid var(--secondary);box-shadow:0 0 0 1px var(--secondary);outline:none}.market-insights-liability-label{color:var(--text-color);font-family:var(--font-family);font-size:11px;font-weight:400;margin-left:15px;width:100%}.market-insights-left-success{align-items:center;display:none;flex-direction:column;justify-content:center;opacity:0;overflow:hidden;padding-left:2px;padding-right:2px;pointer-events:none;transition:opacity .15s ease-out}.market-insights-left-success.visible{display:flex;opacity:1;pointer-events:auto}.market-insights-success-text{color:var(--text-color);font-family:var(--font-family);font-size:22px;font-weight:700;margin-bottom:18px;margin-top:0;text-align:center}.check-icon{margin-left:auto;margin-right:auto;width:50px}.market-insights-resend-label{color:var(--text-color);font-family:var(--font-family);font-size:11px;font-weight:500;margin-left:15px;text-align:center;width:100%}.market-insights-resend-label .resend-link{color:#2f82ff;cursor:pointer;text-decoration:none}.market-insights-right{align-items:center;display:flex;justify-content:center;overflow:hidden}.market-insights-right img{height:260px;width:210px}.skeleton-image-radius{border-radius:8px}.skeleton-wrapper{align-items:center;display:flex;flex-direction:column;width:100%}.skeleton-animation{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.map-skeleton-loader{background-color:var(--neutral-7);border-radius:8px;height:132px;overflow:hidden!important;width:100%}.ticker-big-skeleton{background-color:#bfcdd7;border-radius:4px;height:60px;margin-top:35px;width:268px}.ticker-small-skeleton{background-color:var(--neutral-7);border-radius:4px;height:37px;margin-top:5px;width:124px}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.plunk-home-value-no-valuation-container{align-items:center}.plunk-home-value-complete-valuation-container{align-items:center;margin-top:20px}.plunk-home-value-no-valuation-container .shevron-back{margin-left:0!important;width:15%!important}.plunk-home-no-value-suffix{font-family:var(--font-family);font-size:18px;font-weight:500;margin-top:.6rem;text-align:center;width:77%}.no-value-svg,.plunk-home-no-value-suffix{color:color-mix(in srgb,var(--text-color) 70%,#fff)}.no-value-svg{margin-top:20px}.plunk-home-no-value-home-value{color:var(--text-color);font-family:var(--font-family);font-size:24px;font-weight:700;letter-spacing:-1px;margin-top:.3rem}.plunk-home-value-appreciation-container-no-data,.plunk-home-value-value-container-no-data{display:flex;justify-content:center}.plunk-home-value-appreciation-container-no-data{align-items:baseline;display:flex;margin-bottom:20px}.autocomplete-results{background-color:#fff;border:1px solid #bfcdd7;border-radius:16px;box-shadow:0 4px 5px hsla(0,0%,51%,.14),0 1px 10px hsla(0,0%,51%,.12),0 2px 4px hsla(0,0%,51%,.2);box-sizing:border-box;color:#406a88;display:none;left:0;list-style-type:none;margin-left:auto;margin-right:auto;margin-top:60px;padding:4px 12px 15px;position:absolute;right:0;text-align:left;width:100%;z-index:100}.autocomplete-item{border-bottom:1px solid var(--neutral-7);cursor:pointer;font-size:16px;overflow:hidden;padding:14px 8px;position:relative;text-overflow:ellipsis;white-space:nowrap}.no-results{font-style:italic;padding:14px 8px}.autocomplete-item .text-matched{font-weight:700}.autocomplete-item:hover{background-color:#f2f2f2;border-radius:8px;cursor:pointer}.pv-report{bottom:0;color:#6da8ff;cursor:pointer;font-size:13px;font-weight:500;padding:14px 8px;position:absolute}.pv-report:hover{text-decoration:underline}.animate-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.circle-opacity-25{opacity:.25}.spin-svg{color:#fff;display:none;height:20px;margin-left:4px;width:20px}.arrow-svg{display:block}.pv-button.loading .arrow-svg{display:none}.pv-button.loading .spin-svg{display:block}.pre-valuation-form-container{background-color:#fff;border-radius:8px;box-sizing:border-box;margin:0 auto;max-width:480px;padding:32px 24px;width:100%}.pre-valuation-header{margin-bottom:32px;text-align:center}.pre-valuation-header h2{color:var(--text-color);font-family:var(--font-family);font-size:24px;font-weight:700;margin:0 0 12px}.pre-valuation-header p{color:var(--neutral-5);font-family:var(--font-family);font-size:16px;line-height:1.5;margin:0}.pre-valuation-form{box-sizing:border-box;display:flex;flex-direction:column;gap:20px;width:100%}.pre-valuation-form .form-group{display:flex;flex-direction:column;gap:8px}.pre-valuation-form .form-group label{color:var(--text-color);font-family:var(--font-family);font-size:14px;font-weight:600}.pre-valuation-form .form-group input[type=email],.pre-valuation-form .form-group input[type=tel],.pre-valuation-form .form-group input[type=text]{background-color:#fff;border:1px solid #bfcdd7;border-radius:8px;box-sizing:border-box;color:var(--text-color);font-size:16px;font-weight:600;padding:12px 16px;transition:border-color .2s,box-shadow .2s;width:100%}.pre-valuation-form .form-group input[type=email]:focus,.pre-valuation-form .form-group input[type=tel]:focus,.pre-valuation-form .form-group input[type=text]:focus{border-color:var(--secondary);box-shadow:0 0 0 1px var(--secondary);outline:none}.pre-valuation-form .form-group input::-moz-placeholder{color:#809caf}.pre-valuation-form .form-group input::placeholder{color:#809caf}.pre-valuation-form .radio-group{display:flex;gap:16px;margin-top:4px}.pre-valuation-form .radio-label{align-items:center;color:var(--text-color);cursor:pointer;display:flex;font-family:var(--font-family);font-size:16px;font-weight:400;gap:8px}.pre-valuation-form .radio-label input[type=radio]{accent-color:var(--secondary);cursor:pointer;height:18px;width:18px}.pre-valuation-form .submit-user-info{align-items:center;background-color:var(--secondary);border:none;border-radius:26px;box-sizing:border-box;color:#fff;cursor:pointer;display:flex;font-family:var(--font-family);font-size:18px;font-weight:700;gap:8px;justify-content:center;margin-top:12px;max-width:100%;padding:14px 24px;transition:background-color .2s;width:100%}.pre-valuation-form .submit-user-info:hover{background-color:color-mix(in srgb,var(--secondary) 90%,#000)}.pre-valuation-form .submit-user-info svg{flex-shrink:0}@media (max-width:500px){.pre-valuation-form-container{padding:24px 16px}.pre-valuation-header h2{font-size:20px}.pre-valuation-header p{font-size:14px}.pre-valuation-form .submit-user-info{font-size:16px;padding:12px 20px}}.market-insights-full-form{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;padding-left:2px;padding-right:2px;width:100%}.market-insights-compact-form{box-sizing:border-box;display:flex;flex-direction:column;gap:12px;max-width:400px;width:100%}.market-insights-compact-form .form-row{display:grid;gap:12px;grid-template-columns:1fr 1fr}.market-insights-compact-form .form-group-compact{display:flex;flex-direction:column}.market-insights-compact-form .form-group-compact input[type=email],.market-insights-compact-form .form-group-compact input[type=tel],.market-insights-compact-form .form-group-compact input[type=text]{background-color:#fff;border:1px solid #bfcdd7;border-radius:8px;box-sizing:border-box;color:var(--text-color);font-size:14px;font-weight:600;padding:10px 14px;transition:border-color .2s,box-shadow .2s;width:100%}.market-insights-compact-form .form-group-compact input[type=email]:focus,.market-insights-compact-form .form-group-compact input[type=tel]:focus,.market-insights-compact-form .form-group-compact input[type=text]:focus{border-color:var(--secondary);box-shadow:0 0 0 1px var(--secondary);outline:none}.market-insights-compact-form .form-group-compact input::-moz-placeholder{color:#809caf}.market-insights-compact-form .form-group-compact input::placeholder{color:#809caf}.market-insights-compact-form .radio-compact{align-items:center;display:flex}.market-insights-compact-form .radio-group-inline{display:flex;gap:12px;justify-content:center;width:100%}.market-insights-compact-form .radio-label-compact{align-items:center;color:var(--text-color);cursor:pointer;display:flex;font-family:var(--font-family);font-size:14px;font-weight:500;gap:6px;white-space:nowrap}.market-insights-compact-form .radio-label-compact input[type=radio]{accent-color:var(--secondary);cursor:pointer;height:16px;width:16px}.market-insights-compact-form .submit-market-insights{align-items:center;background-color:var(--secondary);border:none;border-radius:26px;box-sizing:border-box;color:#fff;cursor:pointer;display:flex;font-family:var(--font-family);font-size:16px;font-weight:700;gap:8px;justify-content:center;margin-top:8px;padding:12px 20px;transition:background-color .2s;width:100%}.market-insights-compact-form .submit-market-insights:hover{background-color:color-mix(in srgb,var(--secondary) 90%,#000)}.market-insights-compact-form .submit-market-insights svg{flex-shrink:0}.market-insights-compact-form .submit-market-insights .spin-svg,.market-insights-compact-form .submit-market-insights.loading .arrow-svg{display:none}.market-insights-compact-form .submit-market-insights.loading .spin-svg{display:block}@media (max-width:500px){.market-insights-compact-form .form-row{grid-template-columns:1fr}.market-insights-compact-form .submit-market-insights{font-size:14px;padding:10px 16px}}

            :host {
                --secondary: #2F82FF;
                --text-color: #003960;
            }
            #plunk-valuation-wrapper {
                background: color-mix(in srgb, #FFFFFF, transparent 0%);
                border-radius: 16px;
            }
            .modal {
                background-color: rgba(0, 0, 0, 0.007);
            }
            .modal-content {
                background-color: #FFFFFF;
                border-radius: 16px;
            }
            .address-bubble {
                background-color: #FFFFFF
            }
            .address-bubble-arrow {
                border-top: 10px solid #FFFFFF;
            }
            .pre-valuation-form-container {
                background-color: #FFFFFF
            }
        `;

      this.root.appendChild(style);

      this.#initializeSearchBox();
      this.#addEvents();
    }

    #htmlContent(){
      return `
      <div id="plunk-valuation-wrapper">
        <div id="title-container" class="transition transition-height">
          <div id="main-title" class="pv-heading-container transition transition-opacity">
            <span>How much is your home worth right now?</span>
          </div>
          <div id="report-title" class="report-address pv-heading-container transition transition-opacity opacity-hidden position-absolute">
            <span>Can't find your address?</span>
          </div>
          <div id="report-title-subheader" class="pv-heading-subheader-container transition transition-opacity opacity-hidden position-absolute">
            <span>Enter your address and let Plunk&reg; support know</span>
          </div>
          <div id="reported-title" class="report-address pv-heading-container transition transition-opacity opacity-hidden position-absolute">
            <span>Thank you for notifying us</span>
          </div>
          <div id="reported-title-subheader" class="pv-heading-subheader-container transition transition-opacity opacity-hidden position-absolute">
            <span>Your address has been flagged for review</span>
          </div>
          </div>
          <div id="forms-content" class="autocomplete-input-container transition transition-height">
          <div id="form-autocomplete" class="form-autocomplete position-absolute transition transition-opacity">
            <form id="pv-form" class="test pv-input-container" >
              <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"/></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 class="search-button-label">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"/>
                  </svg>
                </button>
            </form>
            </div>
            <div id="form-report-address" class="form-report-address position-absolute transition transition-opacity opacity-hidden">
            <form id="pv-form-report-address" class="pv-input-container">
              <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"/></svg>
                <input id="pv-address-report-address" name="address-report" class="pv-input" autocomplete="off" placeholder="Enter an address to flag">
              </label>
              <div class="button-report">
                <button type="submit" id="pv-button-report" aria-label="search"  class="pv-button-report position-absolute transition transition-opacity">
                  <span>Flag address</span>
                  <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                  <path d="M21.6003 9.83C21.7197 9.83 21.8341 9.78259 21.9185 9.6982C22.0029 9.61381 22.0503 9.49935 22.0503 9.38V3C22.0503 2.88065 22.0029 2.76619 21.9185 2.6818C21.8341 2.59741 21.7197 2.55 21.6003 2.55H12.7403V1.4C12.7403 1.29391 12.6982 1.19217 12.6232 1.11716C12.5482 1.04214 12.4464 1 12.3403 1H11.6403C11.5342 1 11.4325 1.04214 11.3575 1.11716C11.2825 1.19217 11.2403 1.29391 11.2403 1.4V16.28L2.11033 22.28C2.04435 22.3293 1.99518 22.3978 1.96956 22.476C1.94393 22.5543 1.9431 22.6386 1.96717 22.7174C1.99124 22.7961 2.03903 22.8655 2.10403 22.9161C2.16903 22.9667 2.24807 22.996 2.33033 23H21.6503C21.7352 22.9987 21.8175 22.9705 21.8853 22.9193C21.9531 22.8682 22.0028 22.7968 22.0273 22.7155C22.0518 22.6342 22.0498 22.5472 22.0216 22.4671C21.9934 22.387 21.9404 22.318 21.8703 22.27L12.7403 16.27V9.83H21.6003Z"/>
                  </svg>
                </button>
                <button type="submit" id="pv-button-reported" aria-label="search" class="pv-button-reported opacity-hidden position-absolute transition transition-opacity" disabled>
                  <span>Address flagged</span>
                  <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                  <path fill-rule="evenodd" clip-rule="evenodd" d="M9.14283 16.4284L19.8643 5.70696C20.2548 5.31643 20.888 5.31643 21.2785 5.70696L21.2929 5.72131C21.6834 6.11184 21.6834 6.745 21.2929 7.13553L9.84994 18.5785C9.45941 18.969 8.82625 18.969 8.43572 18.5785L2.70708 12.8498C2.31655 12.4593 2.31655 11.8261 2.70708 11.4356L2.72144 11.4212C3.11196 11.0307 3.74513 11.0307 4.13565 11.4212L9.14283 16.4284Z"/>
                  </svg>
                </button>
              </div>
            </form>

            <div class="chevron-left">
              <svg width="24" height="24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
                <path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/>
              </svg>
            </div>

            </div>
              <ul class="autocomplete-results">
            </ul>
          </div>
                    <div class="powered-by-container">
            <p>Powered by</p> <img src="https://app.homevaluation.ai/images/homevaluationai_logo_color.png">
          </div>
                </div>

      <div class="modal">
        <div class="modal-content">
          <!-- <span class="close-button">&times;</span> -->

          <!-- Pre-Valuation User Info Form -->
          <div id="pre-valuation-form-container" class="pre-valuation-form-container" style="display: none;">
            <div class="pre-valuation-header">
              <h2>Get Your Home Valuation</h2>
              <p>Please provide your information to view your home&#039;s estimated value</p>
            </div>
            <form id="pre-valuation-form" class="pre-valuation-form">
              <div class="form-group">
                <label for="user-name">Full Name *</label>
                <input type="text" id="user-name" name="name" required placeholder="Enter your full name">
              </div>
              <div class="form-group">
                <label for="user-email">Email *</label>
                <input type="email" id="user-email" name="email" required placeholder="Enter your email">
              </div>
              <div class="form-group">
                <label for="user-phone">Phone Number *</label>
                <input type="tel" id="user-phone" name="phone" required placeholder="(555) 123-4567">
              </div>
              <div class="form-group">
                <label>I am interested in *</label>
                <div class="radio-group">
                  <label class="radio-label">
                    <input type="radio" name="intent" value="buying" required>
                    <span>Buying</span>
                  </label>
                  <label class="radio-label">
                    <input type="radio" name="intent" value="selling" required>
                    <span>Selling</span>
                  </label>
                </div>
              </div>
              <button type="submit" class="submit-user-info">
                <span>Continue to Valuation</span>
                <svg width="20" height="20" 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"/>
                </svg>
              </button>
            </form>
          </div>

          <div class="pv-content">
            <div class="skeleton-wrapper">
              <div id="map-skeleton-loader" class="map-skeleton-loader skeleton-animation"></div>
              <div class="ticker-big-skeleton skeleton-animation"></div>
              <div class="ticker-small-skeleton skeleton-animation"></div>

              <div class="plunk-home-value-no-valuation-container" style="display: none;">
                <div class="shevron-back">
                  <svg class="shevron-back-img" width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path class="shevron-close-modal" fill-rule="evenodd" clip-rule="evenodd" d="M7.29215 13.3212C6.90262 13.6964 6.90262 14.3026 7.29215 14.6788L16.5371 23.5928C17.0995 24.1357 18.0144 24.1357 18.5777 23.5928C19.14 23.05 19.14 22.1689 18.5777 21.626L10.6691 13.9995L18.5777 6.37494C19.14 5.8311 19.14 4.95003 18.5777 4.40715C18.0144 3.86428 17.0995 3.86428 16.5371 4.40715L7.29215 13.3212Z" fill="currentColor"/>
                  </svg>
                </div>
              <div>
              <div class="plunk-home-value-value-container-no-data">
                <div class="no-value-svg">
                  <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="currentColor"/>
                  </svg>
                </div>
              </div>
              <div class="plunk-home-value-value-container-no-data">
                <div class="plunk-home-no-value-home-value" id="address-no-value"></div>
                <div class="plunk-home-value-value-container-no-data"></div>
                <div id="missing-data-title" class="plunk-home-no-value-home-value">is missing data</div>
              </div>

              <div class="plunk-home-value-appreciation-container-no-data">
                <div class="plunk-home-no-value-suffix">Sorry, Plunk does not have enough information to determine an accurate home value</div>
              </div>
            </div>
            </div>

            <div class="plunk-home-value-complete-valuation-container" style="display: none;">
              <div class="shevron-back">
                <svg class="shevron-back-img" width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path class="shevron-close-modal" fill-rule="evenodd" clip-rule="evenodd" d="M7.29215 13.3212C6.90262 13.6964 6.90262 14.3026 7.29215 14.6788L16.5371 23.5928C17.0995 24.1357 18.0144 24.1357 18.5777 23.5928C19.14 23.05 19.14 22.1689 18.5777 21.626L10.6691 13.9995L18.5777 6.37494C19.14 5.8311 19.14 4.95003 18.5777 4.40715C18.0144 3.86428 17.0995 3.86428 16.5371 4.40715L7.29215 13.3212Z" fill="currentColor"/>
                </svg>
              </div>

              <div class="plunk-component" id="rc_home_value" data-component-id="rc_home_value">
                <div id="valuationPrice" class="pv-valuation-price"></div>
                <div class=pv-price-range>
                  <p id="avmMin" class="avm-label"></p> <p class="range-divider"> - </p> <p id="avmMax" class="avm-label"></p>
                </div>
              </div>
            </div>

            </div>
              <div id="market-insights-container">
                <!-- Simple form for 'disabled' timing -->
                <div class="market-insights-left visible">
                  <p class="market-insights-cta">Unlock your market insights now</p>
                  <form id="market-insights-form" class="test pv-input-container" >
                    <div class="shadow-for-phone-input">
                                              <input id="phone-input" name="phone" class="phone-input" type="text" autocomplete="off" placeholder="(555) 123-4567">
                                            <button type="submit" aria-label="search" class="pv-button">
                        <span>Send</span>
                        <svg class="arrow-svg" width="20" height="20" 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"/>
                        </svg>
                        <svg class="animate-spin spin-svg" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                          <circle class="circle-opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                          <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                        </svg>
                      </button>
                    </div>
                  </form>
                                    <p class="market-insights-liability-label">*Standard messaging and data rates apply</p>
                                  </div>

                <!-- Compact full form for 'after_valuation' timing -->
                <div class="market-insights-full-form" style="display: none;">
                  <p class="market-insights-cta">Get your market insights</p>
                  <form id="market-insights-full-form" class="market-insights-compact-form">
                    <div class="form-row">
                      <div class="form-group-compact">
                        <input type="text" id="mi-user-name" name="name" required placeholder="Full Name *">
                      </div>
                      <div class="form-group-compact">
                        <input type="email" id="mi-user-email" name="email" required placeholder="Email *">
                      </div>
                    </div>
                      <div class="form-group-compact">
                        <input type="tel" id="mi-user-phone" name="phone" required placeholder="Phone Number *">
                      </div>
                      <div class="form-group-compact radio-compact">
                        <div class="radio-group-inline">
                          <label class="radio-label-compact">
                            <input type="radio" name="mi-intent" value="buying" required>
                            <span>Buying</span>
                          </label>
                          <label class="radio-label-compact">
                            <input type="radio" name="mi-intent" value="selling" required>
                            <span>Selling</span>
                          </label>
                        </div>
                      </div>
                    <button type="submit" class="submit-market-insights">
                      <span>Get Market Insights</span>
                      <svg width="20" height="20" 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"/>
                      </svg>
                      <svg class="animate-spin spin-svg" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                        <circle class="circle-opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                        <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                      </svg>
                    </button>
                  </form>
                </div>

                <div class="market-insights-left-success">
                  <p class="market-insights-success-text">Market insights sent to</p>
                  <div class="check-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                      <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
                    </svg>
                  </div>
                  <p class="market-insights-resend-label">Didn't get a message? <a id="resend-market-insights-link" class="resend-link">Resend</a> <a href="mailto:support@realtycandy.com" id="resend-market-insights-support" style="display: none;" class="resend-link">Contact Plunk® support</a></p>
                </div>
                <div class="market-insights-right">
                  <img class="market-insights-img" src="https://res.cloudinary.com/dscqcqtjn/image/upload/v1684949360/Apps/Plunk/market_insights_preview_ob9ufb.png">
                </div>
              </div>
            </div>

                        <div class="powered-by-container">
              <p>Powered by</p> <img src="https://app.homevaluation.ai/images/homevaluationai_logo_color.png">
            </div>
                      </div>
        </div>
      </div>`;
    }

    async #initializeSearchBox(){
      // Create the search box and link it to the UI element.
      let inputContainer = this.root.querySelector('.autocomplete-input-container');
      let autocomplete_results = this.root.querySelector('.autocomplete-results');
      let autocomplete_input = this.root.getElementById('pv-address');
      let root = this; // <plunk-valuation>

      const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = await google.maps.importLibrary("places");
      const token = new AutocompleteSessionToken();

      // Display suggestions when user types in search box
      let displaySuggestions = function(suggestions) {
        let results_html = [];

        if (!suggestions || suggestions.length === 0) {
          results_html.push(`<li class="no-results" data-type="place">No results</li>`);
          results_html.push(`<div id="pv-report-id" tabIndex="0">Don't see your address?</div>`);
        } else {
          suggestions.forEach(function(suggestion, index, array) {
            const placePrediction = suggestion.placePrediction;
            const address = placePrediction.text.toString();
            const placeId = placePrediction.placeId;

            const mainText = placePrediction.mainText;
            const secondaryText = placePrediction.secondaryText;

            const mainMatches = mainText.matches.map(m => ({
              offset: m.startOffset,
              length: m.endOffset - m.startOffset
            }));
            let wrappedAddress = root.#wrapMatches(mainText.text, mainMatches);

            const secondaryMatches = secondaryText.matches.map(m => ({
              offset: m.startOffset,
              length: m.endOffset - m.startOffset
            }));

            const wrappedSecondary = root.#wrapMatches(secondaryText.text, secondaryMatches);
            wrappedAddress += `, ${wrappedSecondary}`;

            results_html.push(`<li class="autocomplete-item" tabIndex="0" data-type="place" data-address="${address}" data-place-id="${placeId}">
              ${wrappedAddress}
            </li>`);

            if (index == array.length - 1) {
              results_html.push(`<div id="pv-report-id" tabIndex="0">Don't see your address?</div>`);
            }
          });

          autocomplete_results.innerHTML = results_html.join("");
          autocomplete_results.style.display = 'block';

          let autocomplete_items = autocomplete_results.querySelectorAll('.autocomplete-item');
          for (let autocomplete_item of autocomplete_items) {
            autocomplete_item.addEventListener('click', async function() {
              const selected_text = this.dataset.address;
              const place_id = this.getAttribute('data-place-id');

              try {
                const place = new Place({
                  id: place_id,
                  requestedLanguage: 'en',
                });

                await place.fetchFields({
                  fields: ['addressComponents', 'formattedAddress', 'displayName']
                });

                let parsedAddress = '';
                let parsedAptNum = '';
                let parsedCity = '';
                let parsedNeighborhood = '';
                let parsedState = '';
                let parsedZip = '';

                if (place.addressComponents) {
                  for (let component of place.addressComponents) {
                    const types = component.types;

                    if (types.includes("street_number")) {
                      parsedAddress = component.shortText.toUpperCase();
                    }

                    if (types.includes("route")) {
                      parsedAddress = (parsedAddress + " " + component.shortText).toUpperCase();
                    }

                    if (types.includes("subpremise")) {
                      parsedAptNum = component.shortText.toUpperCase();
                    }

                    if (types.includes("neighborhood")) {
                      parsedNeighborhood = component.shortText.toUpperCase();
                    }

                    if (types.includes("locality")) {
                      parsedCity = component.shortText.toUpperCase();
                    }

                    if (types.includes("administrative_area_level_1")) {
                      parsedState = component.shortText.toUpperCase();
                    }

                    if (types.includes("postal_code")) {
                      parsedZip = component.shortText.toUpperCase();
                    }
                  }
                }

                root.address = {
                  addressLineOne: parsedAddress,
                  aptNum: parsedAptNum,
                  city: parsedCity,
                  neighborhood: parsedNeighborhood,
                  state: parsedState,
                  zipcode: parsedZip,
                };

                autocomplete_input.value = selected_text;
                autocomplete_results.style.display = 'none';

              } catch (error) {
                console.error('Error fetching place details:', error);
              }
            });
          }
        }
      };

      // When users starts typing, fetch the autocomplete predictions
      autocomplete_input.addEventListener('input', this.#debounce(async function() {
        let value = this.value;
        let limit = 5;
        value = value.replace('"', '\\"').replace(/^\s+|\s+$/g, '');

        if (value.length >= limit) {
          try {
            let request = {
              input: value,
              includedRegionCodes: ['us'],
              language: 'en-US',
              region: 'us',
              sessionToken: token,
            };

            const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
            displaySuggestions(suggestions);

          } catch (error) {
            console.error('Error fetching suggestions:', error);
            autocomplete_results.innerHTML = '';
            autocomplete_results.style.display = 'none';
          }
        } else {
          autocomplete_results.innerHTML = '';
          autocomplete_results.style.display = 'none';
        }
      }, 150));

      // On input blur hide the autocomplete results
      autocomplete_input.addEventListener('blur', function(event) {
        if(event.relatedTarget && event.relatedTarget.id == 'pv-report-id'){
          let title_container = root.root.querySelector("#title-container");
          title_container.style.height = '90px';
          inputContainer.style.height = '145px';

          let fadeTarget_title = root.root.querySelector("#main-title");

          fadeTarget_title.style.opacity = 0;

          let fadeTarget_report_title = root.root.querySelector("#report-title");
          fadeTarget_report_title.style.opacity = 1;

          let fadeTarget_report_subtitle = root.root.querySelector("#report-title-subheader");
          fadeTarget_report_subtitle.style.opacity = 1;

          let form_autocomplete = root.root.querySelector("#form-autocomplete");
          form_autocomplete.style.opacity = 0;

          let form_report_address = root.root.querySelector("#form-report-address");
          form_report_address.style.opacity = 1;

          autocomplete_results.style.display = 'none';
          return;
        }else if(event.relatedTarget && event.relatedTarget.classList.contains("autocomplete-item")){
          return;
        }

        setTimeout(function() {
          autocomplete_results.style.display = 'none';
        }, 100);

      });
      // On input focus show the autocomplete results
      autocomplete_input.addEventListener('focus', function() {
        if (this.value !== "") {
          autocomplete_results.style.display = 'block';
        }
      });

      root.root.querySelector(".chevron-left").addEventListener('click', function() {
        let title_container = root.root.querySelector("#title-container");
          title_container.style.height = '50px';
          inputContainer.style.height = '65px';

          let fadeTarget_title = root.root.querySelector("#main-title");

          fadeTarget_title.style.opacity = 1;

          let fadeTarget_report_title = root.root.querySelector("#report-title");
          fadeTarget_report_title.style.opacity = 0;

          let fadeTarget_report_subtitle = root.root.querySelector("#report-title-subheader");
          fadeTarget_report_subtitle.style.opacity = 0;

          let fadeTarget_reported_title = root.root.querySelector("#reported-title");
          fadeTarget_reported_title.style.opacity = 0;

          let fadeTarget_reported_subtitle = root.root.querySelector("#reported-title-subheader");
          fadeTarget_reported_subtitle.style.opacity = 0;

          let click_report = root.root.querySelector('#pv-button-report');
          click_report.style.opacity = 1;

          let click_reported = root.root.querySelector('#pv-button-reported');
          click_reported.style.opacity = 0;

          let form_autocomplete = root.root.querySelector("#form-autocomplete");
          form_autocomplete.style.opacity = 1;

          let form_report_address = root.root.querySelector("#form-report-address");
          form_report_address.style.opacity = 0;
      });
    }

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

    #wrapMatches(address, matched_substrings) {
      let output = '';
      let lastIndex = 0;
      let offset = 0;

      for (let match of matched_substrings) {
        const matchStr = address.substring(match.offset, match.offset + match.length);// Get the substring that matches
        output += address.substring(lastIndex, match.offset); // Add the text before the match
        output += `<span class="text-matched">${matchStr}</span>`; // Add the match wrapped in <span> tags
        lastIndex = match.offset + match.length; // Update the lastIndex to the end of the match
        const numMatchesBefore = this.#countMatches(output, '<span>', match.offset); // Update the offset and length of the match
        offset += numMatchesBefore * 6; // Add 6 to account for the length of <span>
        match.offset += offset;
        match.length += offset;
      }

      // Add the remaining text
      output += address.substring(lastIndex);
      return output;
    }

    #countMatches(str, substring, endIndex) {
      let count = 0;
      let index = 0;
      while (index < endIndex) {
        index = str.indexOf(substring, index);
        if (index === -1 || index > endIndex) {
          break;
        }
        count++;
        index += substring.length;
      }
      return count;
    }

    #debounce(func, wait, immediate) {
      let timeout;
      return function() {
        let context = this,
          args = arguments;
        let later = function() {
          timeout = null;
          if (!immediate) func.apply(context, args);
        };
        let callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
      };
    }

    #addEvents(){
      this.root.getElementById('pv-form').addEventListener('submit', (e) => this.#onSubmit(e, this));
      this.root.getElementById('pv-form-report-address').addEventListener('submit', this.#onFlagAddress);
      this.root.querySelector('.modal').addEventListener("click", (event) =>  this.#windowOnClick(event, this) );
      if(this.root.querySelector('#phone-input') != null){
        this.root.querySelector('#phone-input').addEventListener("input", this.#onPhoneInput);
      }
      this.root.querySelector('#market-insights-form').addEventListener("submit",(event) => this.#onSendMarketInsights(event, this));
      this.root.querySelector("#resend-market-insights-link").addEventListener("click", (event) =>  this.#onResendMarketInsights(event, this));

      // Add pre-valuation form events (for 'before_valuation')
      if(this.collectUserInfoTiming === 'before_valuation') {
        this.root.getElementById('pre-valuation-form').addEventListener('submit', (e) => this.#onPreValuationSubmit(e, this));
        if(this.root.querySelector('#user-phone') != null){
          this.root.querySelector('#user-phone').addEventListener("input", this.#onPhoneInput);
        }
      }

      // Add compact market insights full form events (for 'after_valuation')
      if(this.collectUserInfoTiming === 'after_valuation') {
        this.root.getElementById('market-insights-full-form').addEventListener('submit', (e) => this.#onMarketInsightsFullFormSubmit(e, this));
        if(this.root.querySelector('#mi-user-phone') != null){
          this.root.querySelector('#mi-user-phone').addEventListener("input", this.#onPhoneInput);
        }
      }

          }

    #toggleModal() {
      this.root.querySelector(".modal").classList.toggle("show-modal");
    }

    #windowOnClick(event){
      const root = this.shadowRoot;
      if (event.target === root.querySelector(".modal")  || event.target.getAttribute("class") === "shevron-close-modal" || event.target.getAttribute("class") === "shevron-back-img") {

        //if you have a new div you need to hide it here after showing it
        setTimeout(() => {
          root.querySelector("#map-skeleton-loader").innerHTML = ""; //clear map
          root.querySelector("#map-skeleton-loader").classList.add("skeleton-animation");

          root.querySelector("#market-insights-container").classList.remove('market-insights-expanded'); //hide market insights
          root.querySelector(".market-insights-left").classList.add('visible');
          root.querySelector(".market-insights-left").style.display = "";
          root.querySelector(".market-insights-full-form").style.display = 'none';
          root.querySelector(".market-insights-left-success").classList.remove('visible');
          root.querySelector("#resend-market-insights-link").style.display = "inline";
          root.querySelector("#resend-market-insights-support").style.display = "none";

          // Clear simple form inputs
          if(root.querySelector("#phone-input") != null){
            root.querySelector("#phone-input").value = ""; //clear phone
          }
          if(root.querySelector("#email-input") != null){
            root.querySelector("#email-input").value = ""; //clear email
          }

          // Clear compact full form inputs
          if(root.querySelector("#market-insights-full-form") != null){
            root.querySelector("#market-insights-full-form").reset();
          }

          this.phone = null;
          this.email = null;

          // Reset pre-valuation form if it exists (for 'before_valuation')
          if(this.collectUserInfoTiming === 'before_valuation') {
            root.querySelector("#pre-valuation-form-container").style.display = "none";
            root.querySelector(".pv-content").style.display = "block";
            root.querySelector("#pre-valuation-form").reset();
            this.userInfo = null; // Reset user info
          }

          // Reset user info for 'after_valuation' as well
          if(this.collectUserInfoTiming === 'after_valuation') {
            this.userInfo = null;
          }

          root.querySelector('.ticker-big-skeleton').style.display = "block"; //show skeleton
          root.querySelector('.ticker-small-skeleton').style.display = "block"; //show skeleton
          root.querySelector('.map-skeleton-loader').style.display = "block";
          root.querySelector('.shevron-back').style.display = "flex";
          root.querySelector('#market-insights-container').style.display = "grid";

          root.querySelector('.plunk-home-value-no-valuation-container').style.display = "none"; //hide container
          root.querySelector('#address-no-value').style.display = "block";
          root.querySelector('#missing-data-title').textContent = 'Missing data';
          root.querySelector('.plunk-home-no-value-suffix').textContent = 'Sorry, Plunk does not have enough information to determine an accurate home value';
          root.querySelector('.plunk-home-value-complete-valuation-container').style.display = "none"; //hide container
        }, "200");
        root.querySelector(".modal").classList.toggle("show-modal");
      }
    }

    async #sendVerification(){
      const url = "https://app.homevaluation.ai/api/widget/verify/256804716be28"; // Replace with your API endpoint URL

      const response = await fetch(url, {
                        method: 'POST',
                        headers: {
                          'Content-Type': 'application/json'
                        }
                      });
      const data = await response.json();
    }

    async #onFlagAddress(event){
      event.preventDefault();
      // fetch to flag address using api.flag route
      let root = this.getRootNode();
      const address = root.querySelector("#pv-address-report-address").value;
      if(!address) return;

      const url = `https://app.homevaluation.ai/api/flag/256804716be28`; // Replace with your API endpoint URL

      const response = await fetch(url, {
                        method: 'POST',
                        headers: {
                          'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({ address })
                      });

      if (response.status !== 200) {
        return null;
      }

      const data = await response.json();

      let click_report = this.querySelector('#pv-button-report');
      click_report.style.opacity = 0;
      let click_reported = this.querySelector('#pv-button-reported');
      click_reported.style.opacity = 1;

      let fadeTarget_report_title = root.querySelector("#report-title");
      fadeTarget_report_title.style.opacity = 0;

      let fadeTarget_report_subtitle = root.querySelector("#report-title-subheader");
      fadeTarget_report_subtitle.style.opacity = 0;

      let showTarget_reported_title = root.querySelector("#reported-title");
      showTarget_reported_title.style.opacity = 1;

      let showTarget_reported_subtitle = root.querySelector("#reported-title-subheader");
      showTarget_reported_subtitle.style.opacity = 1;
    }

    async #onSendMarketInsights(event) {
      event.preventDefault();
      // fetch to send market insights (for 'disabled' timing - simple form)
      let root = this.shadowRoot;

      root.querySelector("#phone-input") != null ? this.phone = root.querySelector("#phone-input").value : this.phone = null;
      root.querySelector("#email-input") != null ? this.email = root.querySelector("#email-input").value : this.email = null;

      const phone = this.phone;
      const email = this.email;
            if(!this.phone) return;
      
      const marketInsightData = {
        phone: phone,
        email: email,
        address: this.address.addressLineOne,
        home_valuation_id: this.home_valuation_id,
      };

      this.#sendMarketInsightsRequest(marketInsightData);
    }

    async #sendMarketInsightsRequest(marketInsightData) {
      // Common method to send market insights
      let root = this.shadowRoot;
      const url = `https://app.homevaluation.ai/api/send/256804716be28`;

      const response = await fetch(url, {
                        method: 'POST',
                        headers: {
                          'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(marketInsightData)
                      });

      if (response.status !== 200) {
        return null;
      }

      const data = await response.json();

      if (data.status === "success") {
        // Hide whichever form was visible
        let simpleForm = root.querySelector(".market-insights-left");
        if(simpleForm.classList.contains('visible')) {
          simpleForm.classList.remove("visible");
        }

        let fullForm = root.querySelector(".market-insights-full-form");
        if(fullForm.style.display !== 'none') {
          fullForm.style.display = 'none';
        }

        let ctaText = root.querySelector(".market-insights-success-text");
        ctaText.textContent = data.message;

        let showTarget = root.querySelector(".market-insights-left-success");
        showTarget.classList.add("visible");
      }
    }

    async #onResendMarketInsights(event) {
      event.preventDefault();
      // fetch to send market insights
      let root = this.shadowRoot;

      const phone = this.phone;
      if(!phone) return;

      const marketInsightData = {
        phone: phone,
        home_valuation_id: this.home_valuation_id,
      }

      const url = `https://app.homevaluation.ai/api/resend/256804716be28`;

      const response = await fetch(url, {
                      method: 'POST',
                      headers: {
                        'Content-Type': 'application/json'
                      },
                      body: JSON.stringify( marketInsightData )
                    });

      if (response.status !== 200) {
        return null;
      }

      const data = await response.json();

      if (data.status === "success") {
        let supportLinkElement = root.querySelector("#resend-market-insights-support")
        supportLinkElement.style.display = "inline";

        let resendLinkElement = root.querySelector("#resend-market-insights-link")
        resendLinkElement.style.display = "none";
      }
    }

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

      if(!this.address) return;

      // If we need to collect user info BEFORE valuation, show the form first
      if(this.collectUserInfoTiming === 'before_valuation' && !this.userInfo) {
        this.root.querySelector(".modal").classList.toggle("show-modal");
        this.root.querySelector("#pre-valuation-form-container").style.display = "block";
        this.root.querySelector(".pv-content").style.display = "none";
      } else {
        // Otherwise proceed directly to valuation
        this.#getValuation();
        this.root.querySelector(".modal").classList.toggle("show-modal");
      }
    }

    #onPreValuationSubmit(event) {
      event.preventDefault();

      const form = event.target;
      const formData = new FormData(form);

      // Store user information
      this.userInfo = {
        name: formData.get('name'),
        email: formData.get('email'),
        phone: formData.get('phone'),
        intent: formData.get('intent')
      };

      // This is only for 'before_valuation' scenario
      // Hide the form and show the valuation content
      this.root.querySelector("#pre-valuation-form-container").style.display = "none";
      this.root.querySelector(".pv-content").style.display = "block";

      // Now proceed to get the valuation
      this.#getValuation();
    }

    #onMarketInsightsFullFormSubmit(event) {
      event.preventDefault();

      const form = event.target;
      const formData = new FormData(form);

      // Store user information
      this.userInfo = {
        name: formData.get('name'),
        email: formData.get('email'),
        phone: formData.get('phone'),
        intent: formData.get('mi-intent')
      };

      // This is only for 'after_valuation' scenario
      // Save the user info and send market insights
      this.phone = this.userInfo.phone;
      this.email = this.userInfo.email;

      // Save user info to valuation
      this.#saveUserInfoToValuation();

      // Send market insights
      const marketInsightData = {
        phone: this.userInfo.phone,
        email: this.userInfo.email,
        address: this.address.addressLineOne,
        home_valuation_id: this.home_valuation_id,
      };

      this.#sendMarketInsightsRequest(marketInsightData);
    }

    #getValuation(){
      if (!this.#hasPlunkScript()) return this.#importPlunkScript();

      this.setHomeValuationData(); // If already has the script, just get the data
    }

    #hasPlunkScript(){
      return document.head.querySelector('#plunk-components') || false;
    }

    #importPlunkScript(){
      let script = document.createElement('script');
      script.id = 'plunk-components';
      script.src = 'https://idxaddons.com/addons/assets/plunk/scripts-testplunkComponents.js';
      script.onload = this.setHomeValuationData();
      document.head.appendChild(script);
    }

    async getHomeValuationData(){
      let valuationData = null;
      const params = {
        address: this.address.addressLineOne,
        aptNum: this.address.aptNum,
        city: this.address.city,
        neighborhood: this.address.neighborhood,
        stateAbrv: this.address.state,
        zipcode: this.address.zipcode,
        source: window.location.href,
      }

      // Add user info to params if collected
      if(this.userInfo) {
        params.name = this.userInfo.name;
        params.email = this.userInfo.email;
        params.phone = this.userInfo.phone;
        params.intent = this.userInfo.intent;
      }

      const query = Object.keys(params).map(key => {return `${key}=${encodeURIComponent(params[key])}`;}).join('&');

      try {
        // Fetch to api.valuation route
        const response = await fetch(`https://app.homevaluation.ai/api/valuation/256804716be28?${query}`);
        return await response.json();
      } catch (error) {
         // Handle other fetch errors here
        console.error('Fetch Error:', error);
        return null;
      }
    }

    async getMarketInsights(){
      let zipCode = this.address.zipcode;
      // build query based on the address
      let query = `?street=${this.address.addressLineOne}&city=${this.address.city}&state=${this.address.state}&zip=${this.address.zipcode}`;
      const market_insights_url = `https://app.homevaluation.ai/api/marketInsights/${zipCode}` + query;
      const response = await fetch(market_insights_url);
      if (response.status !== 200) {
        return null;
      }
      const marketInsights = await response.json();
      return marketInsights;
    }

    async setHomeValuationData(){
      //delay a second to make sure the script is loaded
      let data = null;
      data = await this.getHomeValuationData();
      // if data.status is error then show error message
      if( data.status === "error" ){
        this.root.querySelector('.ticker-big-skeleton').style.display = "none"; //hide skeleton
        this.root.querySelector('.ticker-small-skeleton').style.display = "none"; //hide skeleton
        this.root.querySelector('.map-skeleton-loader').style.display = "none"; //hide skeleton
        this.root.querySelector('.shevron-back').style.display = "none"; //show container
        this.root.querySelector('#market-insights-container').style.display = "none"; //hide

        this.root.querySelector('.plunk-home-value-no-valuation-container').style.display = "block"; //show container
        this.root.querySelector('#address-no-value').style.display = "none"; //hide
        this.root.querySelector('#missing-data-title').textContent = 'Limit reached';
        this.root.querySelector('.plunk-home-no-value-suffix').textContent = data.message;
        this.root.querySelector('.plunk-home-value-complete-valuation-container').style.display = "none"; //hide container
        return;
      }

      //if(!data) return console.log('no data');
      this.home_valuation_id = data.home_valuation_id;

      let market_insights = null;
      market_insights = await this.getMarketInsights();
      //if(!market_insights) return console.log('no market_insights');

      // Hide skeleton wrapper (loading animation)
        let key = `AIzaSyB5aKUxlSqIedNX9UV_LQmF0j0BHHvfxbQ`;
        let dot_icon = 'https://res.cloudinary.com/dscjvuvb5/image/upload/v1686522046/addressDot___rspik8.png';
        let zoom = '15';
        let address = this.address.addressLineOne + ', ' + (this.address.city || this.address.city.neighborhood ) + ', ' + this.address.state + ' ' + this.address.zipcode;
        let size = '540x210';
        const url = "https://maps.googleapis.com/maps/api/staticmap?center="+address+"&size="+size+"&zoom="+zoom+"&style=feature:landscape%7Celement:labels.icon%7Cvisibility:off&style=feature:poi%7Celement:labels%7Cvisibility:off&style=feature:poi%7Celement:labels%7Cvisibility:off&style=feature:road.highway%7Celement:labels%7Cvisibility:off&style=feature:road.arterial%7Celement:labels%7Cvisibility:off&style=feature:landscape%7Celement:all%7Ccolor:0xF6F6F4&style=feature:water%7Celement:all%7Ccolor:0xCFD6D7&style=feature:poi%7Celement:all%7Ccolor:0xECEEED&style=feature:administrative.locality%7Celement:labels.text.fill%7Ccolor:0x787878&style=feature:road.highway%7Celement:geometry.stroke%7Ccolor:0xE9EEEC&style=feature:road.highway%7Celement:geometry.fill%7Ccolor:0xFFFFFF&markers=anchor:center%7Cicon:"+dot_icon+"%7C"+address+"&key="+key;
        const street_view_url = "https://maps.googleapis.com/maps/api/streetview?size=400x400&location="+address+"%20&key="+key;

        const options = {
          method: "GET"
        }

        let response = await fetch(url, options)

        if (response.status === 200) {
          const imageBlob = await response.blob()
          const imageObjectURL = URL.createObjectURL(imageBlob);

          const image = document.createElement('img');
          image.src = imageObjectURL
          image.classList.add("skeleton-image-radius");

          const div = document.createElement('div');
          div.classList.add("address-bubble");

          let div_row = div.appendChild(document.createElement('div'));
          div_row.classList.add("row");

          let div_column = div_row.appendChild(document.createElement('div'));
          div_column.classList.add("column");

          let house_image = div_column.appendChild(document.createElement('div'));
          house_image.classList.add("houseImage");

          // request the street view
          let response_view = await fetch(street_view_url, options)
          if (response_view.status === 200) {
            let imageBlob2 = await response_view.blob()
            let imageObjectURL2 = URL.createObjectURL(imageBlob2);

            house_image.style.backgroundImage = 'url('+imageObjectURL2+')';
          }
          else {
            //if an error occured we can place something else insted of the image of a house
            console.log("HTTP-Error: " + response_view.status)
          }

          let div_column2 = div_row.appendChild(document.createElement('div'));
          div_column2.classList.add("column2");

          let div_row2 = div_column2.appendChild(document.createElement('div'));
          div_row2.classList.add("address");
          div_row2.innerHTML = this.address.addressLineOne;

          let div_row3 = div_column2.appendChild(document.createElement('div'));
          div_row3.classList.add("city");
          div_row3.innerHTML = (this.address.city || this.address.city.neighborhood ) + ', ' + this.address.state;

          const div_arrow = div.appendChild(document.createElement('div'));
          div_arrow.classList.add("address-bubble-arrow");

          const container = this.root.querySelector("#map-skeleton-loader");
          let content = '';

          content += div.outerHTML;
          content += image.outerHTML;
          container.innerHTML = content;

          this.root.querySelector("#map-skeleton-loader").classList.toggle("skeleton-animation");

          setTimeout(() => {
            this.root.querySelector(".address-bubble").classList.add("show-address-bubble");
          }, "200");

          //if there is market insights data, show the market insights
          if(market_insights){
            const marketInsightsContainer = this.root.querySelector("#market-insights-container");
            marketInsightsContainer.classList.add('market-insights-expanded');

            // Show the appropriate form based on collectUserInfoTiming
            if(this.collectUserInfoTiming === 'after_valuation') {
              // Show the compact full form instead of the simple form
              this.root.querySelector(".market-insights-left").classList.remove('visible');
              this.root.querySelector(".market-insights-full-form").style.display = 'flex';
            } else if (this.collectUserInfoTiming === 'before_valuation' && this.userInfo) {
                // User info is already collected, send market insights directly
                this.root.querySelector(".market-insights-left").classList.remove('visible');
                this.root.querySelector(".market-insights-full-form").style.display = 'none';
                const marketInsightData = {
                    phone: this.userInfo.phone,
                    email: this.userInfo.email,
                    address: this.address.addressLineOne,
                    home_valuation_id: this.home_valuation_id,
                };
                this.#sendMarketInsightsRequest(marketInsightData);
            } else {
              // Show simple form (for 'disabled' and 'before_valuation' without user info)
              this.root.querySelector('.market-insights-left').classList.add('visible');
              this.root.querySelector(".market-insights-full-form").style.display = 'none';
            }
          }else{
            console.log('no market insights data');
          }
        }
        else {
          console.log("HTTP-Error: " + response.status)
        }
      if(data){
        this.#addValueToDOM(data); // Add Plunk Home Value to DOM if it exists
      }else{
        this.#shownoDataToDOM(); // Show No Data if Plunk Home Value does not exist
      }
    }

    // Format Plunk Home Value
    commaFormatted(amount) {
      return amount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    }

    #shownoDataToDOM = () => {
      const root = this.root;

      root.querySelector('.ticker-big-skeleton').style.display = "none";
      root.querySelector('.ticker-small-skeleton').style.display = "none";
      root.querySelector('#address-no-value').innerHTML = '{' + this.address.addressLineOne + '}';
      root.querySelector('.plunk-home-value-no-valuation-container').style.display = "flex";
    };

    #addValueToDOM = (data) => {
      const root = this.root;

      root.querySelector('.ticker-big-skeleton').style.display = "none";
      root.querySelector('.ticker-small-skeleton').style.display = "none";
      root.querySelector('.plunk-home-value-complete-valuation-container').style.display = "flex";

      const formatCurrency = (amount) => {
        return new Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: 'USD',
          minimumFractionDigits: 0,
          maximumFractionDigits: 0,
        }).format(amount);
      };

      if (data) {
        const priceDiv = root.querySelector('#valuationPrice');
        const avmMinLabel = root.querySelector('#avmMin');
        const avmMaxLabel = root.querySelector('#avmMax');

        priceDiv.textContent = formatCurrency(data.valuation);
        avmMinLabel.textContent = formatCurrency(data.avm_min);
        avmMaxLabel.textContent = formatCurrency(data.avm_max);
      }
    };

    #onPhoneInput(event) {//returns (###) ###-####
      var input = event.target.value;
      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)}
      event.target.value = input;
    }

    async #saveUserInfoToValuation() {
      // When user info is collected AFTER valuation, we need to update the record
      if(!this.userInfo || !this.home_valuation_id) return;

      const url = `https://app.homevaluation.ai/api/valuation/256804716be28/update-user-info`;
      const userData = {
        home_valuation_id: this.home_valuation_id,
        name: this.userInfo.name,
        email: this.userInfo.email,
        phone: this.userInfo.phone,
        intent: this.userInfo.intent
      };

      try {
        const response = await fetch(url, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(userData)
        });

        if (response.status === 200) {
          console.log('User info saved successfully');
        }
      } catch (error) {
        console.error('Error saving user info:', error);
      }
    }
  }

  // Define the custom element
  customElements.define('plunk-valuation', PlunkValuation);

  let thisScript = document.currentScript;

  !function () {
    let script = document.createElement("script");  // create a script DOM node
    script.src = `https://maps.googleapis.com/maps/api/js?key=AIzaSyB5aKUxlSqIedNX9UV_LQmF0j0BHHvfxbQ&libraries=places&loading=async&callback=initMap`;
    script.async = true;
    script.defer = true;

    window.initMap = function() {
      insertCustomElement();
    };

    document.head.appendChild(script);
  }();

  function insertCustomElement() {
    thisScript.insertAdjacentHTML('afterend', '<plunk-valuation>');
  };
