{"id":23,"date":"2025-11-12T18:04:12","date_gmt":"2025-11-12T18:04:12","guid":{"rendered":"https:\/\/propertytaxappealpros.com\/?page_id=23"},"modified":"2025-11-25T17:29:25","modified_gmt":"2025-11-25T17:29:25","slug":"home","status":"publish","type":"page","link":"https:\/\/propertytaxappealpros.com\/","title":{"rendered":"Home"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"23\" class=\"elementor elementor-23\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e66626a e-con-full e-flex e-con e-parent\" data-id=\"e66626a\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-4f2f505 elementor-widget elementor-widget-html\" data-id=\"4f2f505\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>McHenry County Property Tax Appeal Pros \u2013 Property Checker<\/title>\n    <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;600;700&display=swap\" rel=\"stylesheet\">\n    <style>\n        \/* CSS STYLES *\/\n        :root {\n            --green: #22c55e;\n            --blue: #1e40af;\n            --gray: #6b7280;\n            --light: #f9fafb;\n            --dark: #111827;\n            --orange: #f59e0b;\n        }\n        * { box-sizing: border-box; margin:0; padding:0; }\n        body { font-family: 'Inter', sans-serif; color: var(--dark); background: var(--light); line-height: 1.6; }\n        .container { max-width: 1100px; margin: auto; padding: 0 1rem; }\n        \n        .hero { \n            background: linear-gradient(to bottom, var(--green), var(--blue)); \n            color: white; \n            text-align: center; \n            padding: 5rem 1rem; \n        }\n        .badge { background: #fbbf24; color: #000; padding: .3rem .8rem; border-radius: 50px; font-weight: 600; font-size: .9rem; display: inline-block; margin-bottom: .5rem; }\n        h1 { font-size: 2.8rem; margin: 0 0 .5rem; }\n        .btn { background: var(--green); color: white; padding: 1rem 2rem; border-radius: 8px; font-weight: 600; text-decoration: none; display: inline-block; margin: 1rem; transition: transform .2s; }\n        .btn:hover { transform: translateY(-2px); }\n        .section { padding: 3rem 0; }\n        .townships { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; margin: 2rem 0; }\n        .township { \n            background: white; \n            border: 1px solid #e5e7eb; \n            padding: 1rem; \n            text-align: center; \n            border-radius: 8px; \n            box-shadow: 0 2px 5px rgba(0,0,0,.05); \n            font-weight: 500;\n            cursor: pointer;\n            transition: background 0.2s, transform 0.1s;\n        }\n        .township:hover {\n            transform: translateY(-2px);\n            box-shadow: 0 4px 8px rgba(0,0,0,.1);\n        }\n\n        \/* Color Coding for Township Boxes *\/\n        .township.open { background: #d1fae5; border-color: #34d399; }\n        .township.soon { background: #fef3c7; border-color: #fbbf24; }\n        .township.closed { background: #fcebeb; border-color: #fca5a5; } \n\n        .township-status { display: block; font-size: 0.8rem; font-weight: 400; color: var(--gray); margin-top: 0.2rem; }\n        .township.open .township-status { color: var(--dark); font-weight: 500; } \n        .township.soon .township-status { color: var(--orange); font-weight: 600; }\n        .township.closed .township-status { color: #b91c1c; font-weight: 600; }\n        \n        \/* Highlight countdown for urgency: Used for the status message and the boxes *\/\n        .countdown-days { \n            font-weight: 700; \n            color: #ef4444; \n            text-shadow: 0 0 1px rgba(255, 255, 255, 0.7); \n        }\n        \/* Style for countdown inside the township boxes *\/\n        .township.open .countdown-days-box {\n            font-weight: 700;\n            color: #ef4444; \n            display: block; \n            margin-top: 2px;\n        }\n\n\n        .form-box { background: white; padding: 2.5rem; border-radius: 12px; box-shadow: 0 10px 25px rgba(0,0,0,.1); max-width: 500px; margin: 0 auto; }\n        .form-box h2 { text-align: center; margin-top: 0; font-size: 1.75rem; }\n        \n        \/* Form Field Styles *\/\n        input, button { \n            width: 100%; \n            padding: 1.2rem;\n            margin: .5rem 0; \n            border: 1px solid #d1d5db; \n            border-radius: 8px; \n            font-size: 1rem; \n            line-height: 1.2;\n        }\n        \n        button { background: var(--green); color: white; font-weight: 600; border: none; cursor: pointer; transition: background .2s; }\n        button:hover { background: #16a34a; }\n        button:disabled { background: var(--gray); cursor: not-allowed; }\n\n        \/* --- CUSTOM SELECT STYLES (For alignment fix) --- *\/\n        .custom-select-wrapper {\n            position: relative;\n            width: 100%;\n            margin: .5rem 0; \n            z-index: 100;\n        }\n\n        .custom-select-selected {\n            \/* Mimics the input field styling *\/\n            width: 100%;\n            padding: 1.2rem 1.2rem;\n            border: 1px solid #d1d5db; \n            border-radius: 8px; \n            font-size: 1rem; \n            line-height: 1.2; \/* Ensures text centering *\/\n            background-color: white;\n            cursor: pointer;\n            user-select: none;\n            display: flex;\n            justify-content: space-between;\n            align-items: center; \/* Crucial for vertical centering *\/\n        }\n        .custom-select-selected.placeholder {\n            color: var(--gray); \/* Placeholder color *\/\n        }\n        .custom-select-selected:focus {\n            outline: none;\n            border-color: var(--blue);\n            box-shadow: 0 0 0 2px rgba(30, 64, 175, 0.2);\n        }\n        \n        \/* Disabled look after successful submission *\/\n        .custom-select-selected.disabled-look {\n            background-color: #f1f5f9;\n            color: #a1a1aa;\n            cursor: default;\n        }\n\n        .custom-select-selected::after {\n            \/* Custom down arrow *\/\n            content: '\u25bc';\n            font-size: 0.7rem;\n            color: var(--gray);\n            transition: transform 0.2s;\n        }\n        .custom-select-selected.open::after {\n            transform: rotate(180deg);\n        }\n\n        .options-list {\n            list-style: none;\n            padding: 0;\n            margin: 0;\n            border: 1px solid #d1d5db;\n            border-radius: 8px;\n            position: absolute;\n            width: 100%;\n            max-height: 250px;\n            overflow-y: auto;\n            background-color: white;\n            box-shadow: 0 4px 10px rgba(0,0,0,0.1);\n            display: none;\n        }\n        .options-list.open {\n            display: block;\n        }\n\n        .options-list li {\n            padding: 1rem 1.2rem;\n            cursor: pointer;\n            font-size: 1rem;\n            line-height: 1.2;\n        }\n        .options-list li:hover {\n            background-color: #f1f5f9;\n        }\n        .options-list li.selected {\n            background-color: var(--blue);\n            color: white;\n            font-weight: 600;\n        }\n        \/* --- END CUSTOM SELECT STYLES --- *\/\n\n\n        \/* Styles for the conditional messages *\/\n        .status-message { margin-bottom: 1rem; padding: 0.75rem; border-radius: 8px; text-align: center; font-weight: 600; display: none; }\n        .open-message { background: #d1fae5; color: #065f46; border: 1px solid #065f46; }\n        .soon-message { background: #fef3c7; color: #b45309; border: 1px solid #f59e0b; }\n        .closed-message { background: #fee2e2; color: #b91c1c; border: 1px solid #b91c1c; }\n        #loading-message { display: none; color: var(--blue); margin-top: 1rem; }\n        #success-message { display: none; color: var(--green); margin-top: 1rem; font-weight: 700; }\n\n        \/* Custom style for the final message *\/\n        .final-message { \n            text-align: center; \n            font-size: .95rem; \n            color: var(--dark); \n            margin-top: 1rem;\n            line-height: 1.4;\n            padding: 0 1rem;\n        }\n\n        footer { background: var(--dark); color: #ddd; text-align: center; padding: 2rem 1rem; font-size: .9rem; }\n        footer a { color: #aaa; text-decoration: none; }\n        footer a:hover { text-decoration: underline; }\n        @media (max-width: 640px) { h1 { font-size: 2.2rem; } .hero { padding: 3rem 1rem; } }\n    <\/style>\n<\/head>\n<body>\n\n    <section class=\"hero\">\n        <div class=\"container\">\n            <span class=\"badge\">PROPERTY TAX APPEAL PROS<\/span>\n            <h1>Start Your Property Tax Appeal Review \u2013 McHenry County<\/h1>\n            <p style=\"font-size:1.3rem; max-width:700px; margin:1.5rem auto;\">\n                <strong>Act now! Appeals are OPEN for multiple townships with deadlines this month!<\/strong> Use the checker below to <strong>start the review process<\/strong> now.\n            <\/p>\n            <a href=\"#checker\" class=\"btn\">Check Eligibility \u2013 Free<\/a>\n        <\/div>\n    <\/section>\n\n    <section class=\"section\">\n        <div class=\"container\">\n            <h2 style=\"text-align:center; font-size:1.75rem; margin-bottom:1rem;\">Check Your Township's Appeal Deadline<\/h2>\n            <p style=\"text-align:center; color:var(--gray); margin-bottom:2rem;\">\n                <strong>Click your township below<\/strong> to automatically update the form status.\n            <\/p>\n            <div class=\"townships\" id=\"township-boxes\">\n                <\/div>\n        <\/div>\n    <\/section>\n    \n    <section class=\"section\" style=\"background:#f1f5f9;\">\n        <div class=\"container\" style=\"text-align:center; max-width:700px;\">\n            <h2 style=\"font-size:1.75rem; margin-bottom:1rem;\">Why Submit Your Info Now?<\/h2>\n            <p style=\"color:var(--gray); margin-bottom:1.5rem;\">\n                <strong>For OPEN townships (Deadlines are imminent!):<\/strong> We <strong>assess your property<\/strong> immediately to determine if you are a strong <strong>candidate<\/strong> before the final closing date.\n            <\/p>\n            <p style=\"color:var(--gray); margin-bottom:1.5rem;\">\n                <strong>For OPENING SOON townships (Marengo, Riley):<\/strong> We prepare your <strong>review<\/strong> now so your property is ready to be assessed the moment the window opens, securing your spot.\n            <\/p>\n            <p style=\"color:var(--gray); margin-bottom:1.5rem;\">\n                <strong>For CLOSED townships:<\/strong> We save your property details to ensure you are <strong>first in line<\/strong> for the next appeal season (likely 2026).\n            <\/p>\n            <p style=\"font-style:italic; color:var(--green);\">\n                New to McHenry appeals? We're here to guide you \u2014 every step, no upfront fees.\n            <\/p>\n        <\/div>\n    <\/section>\n\n    <section id=\"checker\" class=\"section\">\n        <div class=\"container\">\n            <div class=\"form-box\">\n                <h2>Get Started in 60 Seconds<\/h2>\n                \n                <form id=\"appeal-form\"> \n                    \n                    <div class=\"custom-select-wrapper\">\n                        <div id=\"township-selected\" class=\"custom-select-selected placeholder\" tabindex=\"0\" role=\"combobox\" aria-expanded=\"false\" aria-controls=\"township-options-list\">\n                            Select Your Township\n                        <\/div>\n                        <ul id=\"township-options-list\" class=\"options-list\" role=\"listbox\" aria-label=\"Select Your Township\">\n                            <\/ul>\n                        <input type=\"hidden\" name=\"township\" id=\"township-hidden-input\" value=\"\" required>\n                    <\/div>\n\n                    <div id=\"status-message\" class=\"status-message\"><\/div>\n                    \n                    <input \n                        type=\"text\" \n                        name=\"parcel_id\" \n                        id=\"parcel-id-input\" \n                        placeholder=\"Your Parcel ID (e.g., 00-00-000-00)\" \n                        required\n                        maxlength=\"15\"\n                        oninput=\"formatParcelId(this);\"\n                    \/> \n                    \n                    <input type=\"text\" name=\"street_address\" id=\"street-address-input\" placeholder=\"Your Property Street Address\" required \/>\n                    \n                    <input type=\"text\" name=\"name\" id=\"name-input\" placeholder=\"Your Full Name (First and Last)\" required \/>\n                    \n                    <input \n                        type=\"tel\" \n                        name=\"phone\" \n                        id=\"phone-input\" \n                        placeholder=\"Your Phone Number (e.g., 815-555-1212)\" \n                        required \n                        oninput=\"formatPhoneNumber(this);\"\n                        maxlength=\"12\"\n                    \/>\n                    \n                    <input type=\"email\" name=\"email\" placeholder=\"Your Email for Next Steps\" required \/>\n                    \n                    <input type=\"hidden\" name=\"appeal_status\" id=\"appeal-status-hidden\" value=\"\">\n                    \n                    <button type=\"submit\" id=\"submit-button\" disabled>Please Select Your Township<\/button>\n                    \n                    <p id=\"loading-message\">Processing your request and checking eligibility...<\/p>\n                    <p id=\"success-message\">\ud83c\udf89 <strong>Submission Complete!<\/strong> We have successfully received your details. Please look below the form for the timeline of your free property assessment.<\/p>\n                    \n                <\/form>\n                \n                <p class=\"final-message\">\n                    <strong>Free Property Assessment.<\/strong> If we determine you have a strong case for property value reduction, we will respond within <strong>48 business hours.<\/strong> Our goal: a successful appeal and a <strong>reduced property tax bill.<\/strong>\n                <\/p>\n                \n            <\/div>\n        <\/div>\n    <\/section>\n\n    <footer>\n        <div class=\"container\">\n            <p>\u00a9 2025 Property Tax Appeal Pros | Serving McHenry County's 17 Townships<\/p>\n            <p>\n                <a href=\"\/privacy\">Privacy Policy<\/a> | \n                <a href=\"tel:815-555-0199\">815-555-0199<\/a>\n            <\/p>\n        <\/div>\n    <\/footer>\n\n    <script>\n        \/\/ *** IMPORTANT: REPLACE WITH YOUR GOOGLE APPS SCRIPT WEB APP URL ***\n        const WEB_APP_URL = 'https:\/\/script.google.com\/macros\/s\/AKfycbxElDcXR72c2WGJhaj0cvTQAOOcJe-z7zywmb6W_edD2Nll4H0bbSqES-CnN7w23N6v\/exec'; \n\n        \/\/ --- DYNAMIC LOGIC VARIABLES ---\n        \n        \/\/ ** FIX: Use the current date when the script runs (the user visits the page) **\n        const TODAY = new Date();\n        \/\/ Set the time to midnight (00:00:00) to ensure accurate day calculation (start of the day)\n        TODAY.setHours(0, 0, 0, 0); \n        \n        \/\/ Map of all township deadlines. Dates must be in YYYY-MM-DD format.\n        const TOWNSHIP_DEADLINES = {\n            'Algonquin': new Date('2025-10-23T23:59:59'),\n            'Alden': new Date('2025-10-10T23:59:59'),\n            'Burton': new Date('2025-11-20T23:59:59'),\n            'Chemung': new Date('2025-07-21T23:59:59'),\n            'Coral': new Date('2025-09-15T23:59:59'),\n            'Dorr': new Date('2025-08-08T23:59:59'),\n            'Dunham': new Date('2025-10-27T23:59:59'),\n            'Greenwood': new Date('2025-09-19T23:59:59'),\n            'Grafton': new Date('2025-09-02T23:59:59'),\n            'Hartland': new Date('2025-09-12T23:59:59'),\n            'Hebron': new Date('2025-12-01T23:59:59'),\n            'McHenry': new Date('2025-10-16T23:59:59'),\n            'Nunda': new Date('2025-11-21T23:59:59'),\n            'Richmond': new Date('2025-07-28T23:59:59'),\n            'Seneca': new Date('2025-11-15T23:59:59'), \n            \n            \/\/ UPDATED: Marengo is now open with a 12\/26\/2025 deadline\n            'Marengo': new Date('2025-12-26T23:59:59'), \n            'Riley': 'SOON', \/\/ Still opening soon as requested\n        };\n        \n        \/\/ DOM Elements\n        const appealForm = document.getElementById('appeal-form');\n        const townshipBoxes = document.getElementById('township-boxes');\n        const parcelIdInput = document.getElementById('parcel-id-input');\n        const nameInput = document.getElementById('name-input');\n        const phoneInput = document.getElementById('phone-input');\n        const statusMessage = document.getElementById('status-message');\n        const submitButton = document.getElementById('submit-button');\n        const hiddenStatus = document.getElementById('appeal-status-hidden');\n        const loadingMessage = document.getElementById('loading-message');\n        const successMessage = document.getElementById('success-message');\n\n        \/\/ CUSTOM DROPDOWN ELEMENTS\n        const customSelectSelected = document.getElementById('township-selected');\n        const optionsList = document.getElementById('township-options-list');\n        const townshipHiddenInput = document.getElementById('township-hidden-input');\n\n\n        \/\/ Helper function to format date for display (e.g., Nov 20)\n        function formatDate(date) {\n            return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n        }\n        \n        \/\/ Helper function to calculate days remaining\n        function getDaysRemaining(deadline) {\n            \/\/ Calculate difference in milliseconds\n            const diffTime = deadline.getTime() - TODAY.getTime();\n            \/\/ Convert to days (24 hours * 60 min * 60 sec * 1000 ms)\n            const diffDays = Math.ceil(diffTime \/ (1000 * 60 * 60 * 24)); \n            return diffDays;\n        }\n\n        \/\/ Helper function to get the status, CSS class, and display text\n        function getTownshipStatus(townshipName) {\n            const deadlineValue = TOWNSHIP_DEADLINES[townshipName];\n            let status = 'closed';\n            let statusText = 'Closed: Deadline Passed';\n            let daysRemaining = 0;\n\n            if (deadlineValue === 'SOON') {\n                status = 'soon';\n                statusText = 'OPENING SOON: Priority Review';\n            } else if (deadlineValue instanceof Date) {\n                daysRemaining = getDaysRemaining(deadlineValue);\n\n                if (daysRemaining >= 1) {\n                    status = 'open';\n                    \/\/ Updated the display text for the township boxes\n                    let daysText = `<span class=\"countdown-days-box\">${daysRemaining} DAY${daysRemaining > 1 ? 'S' : ''} LEFT<\/span>`;\n                    \n                    \/\/ Box Status Text (Date + Red Countdown)\n                    statusText = `Deadline ${formatDate(deadlineValue)} ${daysText}`;\n                } else {\n                    status = 'closed';\n                    statusText = `Closed: ${formatDate(deadlineValue)}`;\n                }\n            }\n            return { status, statusText, daysRemaining };\n        }\n        \n        \/\/ Function to dynamically build the township boxes and dropdown options\n        function renderTownships() {\n            townshipBoxes.innerHTML = '';\n            optionsList.innerHTML = ''; \/\/ Clear custom options list\n            \n            \/\/ Sort keys alphabetically for clean display\n            const sortedTownships = Object.keys(TOWNSHIP_DEADLINES).sort();\n\n            sortedTownships.forEach(township => {\n                const { status, statusText } = getTownshipStatus(township);\n                \n                \/\/ 1. Build Township Box\n                const boxDiv = document.createElement('div');\n                boxDiv.className = `township ${status}`;\n                boxDiv.setAttribute('data-township', township);\n                boxDiv.innerHTML = `${township} <span class=\"township-status\">${statusText}<\/span>`; \n                townshipBoxes.appendChild(boxDiv);\n\n                \/\/ 2. Build Custom Dropdown List Item\n                const listItem = document.createElement('li');\n                listItem.textContent = township;\n                listItem.setAttribute('data-value', township);\n                listItem.setAttribute('role', 'option');\n                \n                \/\/ Event listener for the custom list item\n                listItem.addEventListener('click', () => {\n                    selectTownship(township);\n                    toggleDropdown(false);\n                });\n                optionsList.appendChild(listItem);\n            });\n        }\n\n        \/\/ --- Custom Dropdown Logic ---\n        function toggleDropdown(force) {\n            const isOpen = optionsList.classList.contains('open');\n            if (force === true || (force !== false && !isOpen)) {\n                optionsList.classList.add('open');\n                customSelectSelected.classList.add('open');\n                customSelectSelected.setAttribute('aria-expanded', 'true');\n            } else {\n                optionsList.classList.remove('open');\n                customSelectSelected.classList.remove('open');\n                customSelectSelected.setAttribute('aria-expanded', 'false');\n            }\n        }\n\n        function selectTownship(township) {\n            \/\/ Update visual display\n            customSelectSelected.textContent = township;\n            customSelectSelected.classList.remove('placeholder');\n            \n            \/\/ Update hidden input for form submission\n            townshipHiddenInput.value = township;\n            \n            \/\/ Set 'selected' class on the list item\n            optionsList.querySelectorAll('li').forEach(li => {\n                li.classList.remove('selected');\n                if (li.getAttribute('data-value') === township) {\n                    li.classList.add('selected');\n                }\n            });\n\n            checkDeadline(township); \/\/ Check status based on selection\n        }\n\n        \/\/ Attach event listeners for the custom dropdown\n        customSelectSelected.addEventListener('click', () => {\n            toggleDropdown();\n        });\n\n        \/\/ Close dropdown when clicking outside\n        document.addEventListener('click', (e) => {\n            if (!e.target.closest('.custom-select-wrapper')) {\n                toggleDropdown(false);\n            }\n        });\n        \n        \/\/ Function to update status based on dropdown selection (now takes township as an argument)\n        function checkDeadline(selectedTownship = townshipHiddenInput.value) {\n            \n            if (!selectedTownship) {\n                statusMessage.style.display = 'none';\n                submitButton.disabled = true;\n                submitButton.textContent = 'Please Select Your Township';\n                hiddenStatus.value = '';\n                return;\n            }\n\n            const { status, daysRemaining } = getTownshipStatus(selectedTownship);\n\n            submitButton.disabled = false;\n            statusMessage.style.display = 'block';\n            statusMessage.className = 'status-message';\n\n            if (status === 'open') {\n                statusMessage.classList.add('open-message');\n                \n                let countdownDisplay = '';\n                const daysWord = `day${daysRemaining > 1 ? 's' : ''}`;\n                \n                if (daysRemaining <= 5) {\n                    \/\/ Special urgent message for 5 days or less\n                    countdownDisplay = `<strong><span class=\"countdown-days\">JUST ${daysRemaining} ${daysWord} LEFT!<\/span><\/strong>`;\n                } else {\n                    \/\/ Standard message, using the red class just for the number of days\n                    countdownDisplay = `<strong><span class=\"countdown-days\">${daysRemaining}<\/span> ${daysWord} left.<\/strong>`;\n                }\n\n                \/\/ Inject the countdown into the status message\n                statusMessage.innerHTML = `\u2705 <strong>2025 APPEAL OPEN!<\/strong> ${countdownDisplay} Submit your details for immediate <strong>review.<\/strong>`; \n                submitButton.textContent = 'Submit Details & Start My 2025 Review';\n                hiddenStatus.value = '2025_OPEN_IMMEDIATE_REVIEW';\n\n            } else if (status === 'soon') {\n                \/\/ SCENARIO 2: DEADLINE IS OPENING SOON \n                statusMessage.classList.add('soon-message');\n                \/\/ Using <strong> tags in the message string\n                statusMessage.innerHTML = '\u26a0\ufe0f <strong>OPENING SOON!<\/strong> Submit details now for <strong>priority 2025 review.<\/strong>'; \n                submitButton.textContent = 'Secure My Spot for 2025 Priority Review'; \n                hiddenStatus.value = '2025_OPENING_SOON_PRIORITY';\n            } else {\n                \/\/ SCENARIO 3: DEADLINE IS CLOSED \n                statusMessage.classList.add('closed-message');\n                \/\/ Using <strong> tags in the message string\n                statusMessage.innerHTML = '\ud83d\uded1 <strong>2025 Appeal Closed.<\/strong> Submit details to join the 2026 Priority Waitlist.'; \n                submitButton.textContent = 'Join 2026 Priority Waitlist';\n                hiddenStatus.value = '2026_WAITLIST';\n            }\n        }\n        \n        \/\/ Initialization function\n        document.addEventListener('DOMContentLoaded', () => {\n            renderTownships();\n            checkDeadline(''); \/\/ Set initial button\/message state to empty\n        });\n        \n        \/\/ --- Form Utility Functions ---\n\n        \/\/ Function to format Parcel ID visually (00-00-000-00 - 10 digits)\n        function formatParcelId(input) {\n            let cleanValue = input.value.replace(\/[^0-9]\/g, ''); \n            cleanValue = cleanValue.substring(0, 10);\n            \n            let formattedValue = '';\n            if (cleanValue.length > 0) {\n                formattedValue += cleanValue.substring(0, 2);\n            }\n            if (cleanValue.length > 2) {\n                formattedValue += '-' + cleanValue.substring(2, 4);\n            }\n            if (cleanValue.length > 4) {\n                formattedValue += '-' + cleanValue.substring(4, 7);\n            }\n            if (cleanValue.length > 7) {\n                formattedValue += '-' + cleanValue.substring(7, 10);\n            }\n            \n            input.value = formattedValue;\n        }\n\n        \/\/ Function to format Phone Number visually (XXX-XXX-XXXX - 10 digits)\n        function formatPhoneNumber(input) {\n            let cleanValue = input.value.replace(\/[^0-9]\/g, ''); \n            cleanValue = cleanValue.substring(0, 10);\n            \n            let formattedValue = '';\n            if (cleanValue.length > 0) {\n                formattedValue += cleanValue.substring(0, 3);\n            }\n            if (cleanValue.length > 3) {\n                formattedValue += '-' + cleanValue.substring(3, 6);\n            }\n            if (cleanValue.length > 6) {\n                formattedValue += '-' + cleanValue.substring(6, 10);\n            }\n            \n            input.value = formattedValue;\n        }\n        \n        \/\/ Function to extract the clean 10-digit number and perform final Parcel ID validation\n        function cleanAndValidateParcelId(inputElement) {\n            const parcelId = inputElement.value.replace(\/[^0-9]\/g, ''); \n            \n            if (parcelId.length !== 10) {\n                alert(`\u274c Error: Your Parcel ID must be exactly 10 digits (e.g., 03-31-400-00). Please correct the number you entered.`);\n                return false; \n            }\n            return parcelId; \n        }\n        \n        \/\/ Function to check for Full Name (requires at least one space)\n        function validateFullName(nameString) {\n            if (nameString.trim().includes(' ')) {\n                return true;\n            }\n            alert(`\u274c Error: Please enter your full name (First and Last Name).`);\n            return false;\n        }\n        \n        \/\/ Function to extract the clean 10-digit number and perform final Phone validation\n        function cleanAndValidatePhone(inputElement) {\n            const phone = inputElement.value.replace(\/[^0-9]\/g, ''); \n            \n            if (phone.length !== 10) {\n                alert(`\u274c Error: Your Phone Number must be exactly 10 digits. Please correct the number you entered.`);\n                return false; \n            }\n            return phone; \n        }\n\n\n        \/\/ Click handler for the township boxes\n        townshipBoxes.addEventListener('click', function(e) {\n            let targetDiv = e.target.closest('.township');\n            if (targetDiv && targetDiv.dataset.township) {\n                const townshipName = targetDiv.dataset.township;\n                \n                selectTownship(townshipName); \/\/ Use the new function to update the custom dropdown\n                document.getElementById('checker').scrollIntoView({ behavior: 'smooth' });\n            }\n        });\n\n        \/\/ Custom Fetch API submission handler \n        appealForm.addEventListener('submit', async function(e) {\n            e.preventDefault(); \n            \n            const form = e.target;\n            const formData = new FormData(form);\n            \n            \/\/ --- VALIDATION AND CLEANING ---\n            if (!formData.get('township')) {\n                alert('Please select your township.');\n                customSelectSelected.focus(); \n                return;\n            }\n\n            if (!validateFullName(formData.get('name'))) {\n                nameInput.focus();\n                return;\n            }\n            \n            const cleanedParcelId = cleanAndValidateParcelId(parcelIdInput);\n            if (cleanedParcelId === false) {\n                parcelIdInput.focus();\n                return;\n            }\n            formData.set('parcel_id', cleanedParcelId);\n\n            const cleanedPhone = cleanAndValidatePhone(phoneInput);\n            if (cleanedPhone === false) {\n                phoneInput.focus();\n                return;\n            }\n            formData.set('phone', cleanedPhone);\n\n            \/\/ Set loading state\n            submitButton.disabled = true;\n            submitButton.textContent = 'Submitting...'; \n            loadingMessage.style.display = 'block';\n            successMessage.style.display = 'none';\n\n        \/\/ =======================================================\n        \/\/ Fetch IP Address\n        \/\/ =======================================================\n        let ipAddress = 'Not Found';\n        try {\n            const ipResponse = await fetch('https:\/\/api.ipify.org?format=json');\n            \n            if (ipResponse.ok) {\n                const ipData = await ipResponse.json();\n                ipAddress = ipData.ip || 'Not Found';\n            } else {\n                ipAddress = 'IP Fetch Failed (HTTP Error)';\n                console.warn('Could not fetch IP address due to HTTP status:', ipResponse.status);\n            }\n        } catch (ipError) {\n            ipAddress = 'IP Fetch Failed (Network Error)';\n            console.warn('Could not fetch IP address due to network issue:', ipError);\n        }\n\n        \/\/ Add the IP address to the form data\n        formData.append('ip_address', ipAddress);\n        \/\/ =======================================================\n            \n            \/\/ Convert finalized form data (including IP) to URLSearchParams\n            const data = new URLSearchParams(formData);\n\n            try {\n                \/\/ Submit the data to the Google Apps Script Web App\n                const response = await fetch(WEB_APP_URL, { \n                    method: 'POST',\n                    body: data \n                });\n\n                if (response.ok) {\n                    \/\/ Success!\n                    loadingMessage.style.display = 'none';\n                    successMessage.style.display = 'block';\n                    \n                    \/\/ Disable all form inputs and clear values\n                    const formElements = form.querySelectorAll('input, button');\n                    formElements.forEach(element => {\n                        if (element.type !== 'hidden' && element.id !== 'submit-button') {\n                            element.disabled = true;\n                            element.value = ''; \n                        }\n                    });\n                    \n                    \/\/ Disable the custom dropdown appearance\n                    customSelectSelected.classList.add('disabled-look'); \n                    \n                    \/\/ Disable the submit button and set final text\n                    submitButton.disabled = true;\n                    submitButton.textContent = 'Submission Finalized';\n                    submitButton.style.backgroundColor = '#10b981'; \n\n                } else {\n                    \/\/ Handle non-OK response from the server (e.g., 400, 500)\n                    const errorText = await response.text();\n                    console.error('Server error response:', errorText);\n                    \n                    loadingMessage.style.display = 'none';\n                    alert('Submission failed due to a server error. Please try again or contact support.');\n\n                    \/\/ Re-enable button for user to try again\n                    submitButton.disabled = false;\n                    submitButton.textContent = 'Submit Details & Start My 2025 Review';\n                }\n\n            } catch (networkError) {\n                \/\/ Handle total network failure (e.g., disconnection, invalid URL)\n                console.error('Network Error:', networkError);\n                \n                loadingMessage.style.display = 'none';\n                alert('A network error occurred. Please check your connection and try again.');\n\n                \/\/ Re-enable button for user to try again\n                submitButton.disabled = false;\n                submitButton.textContent = 'Submit Details & Start My 2025 Review';\n            }\n        });\n    <\/script>\n<\/body>\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>McHenry County Property Tax Appeal Pros \u2013 Property Checker PROPERTY TAX APPEAL PROS Start Your Property Tax Appeal Review \u2013 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-23","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=\/wp\/v2\/pages\/23","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=23"}],"version-history":[{"count":129,"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=\/wp\/v2\/pages\/23\/revisions"}],"predecessor-version":[{"id":159,"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=\/wp\/v2\/pages\/23\/revisions\/159"}],"wp:attachment":[{"href":"https:\/\/propertytaxappealpros.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=23"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}