{"id":2109,"date":"2025-06-18T12:28:53","date_gmt":"2025-06-18T16:28:53","guid":{"rendered":"https:\/\/farmtab.com\/growingdirtfarm\/?page_id=2109"},"modified":"2026-03-25T13:20:11","modified_gmt":"2026-03-25T17:20:11","slug":"csa","status":"publish","type":"page","link":"https:\/\/farmtab.com\/growingdirtfarm\/csa\/","title":{"rendered":"Community Supported Agriculture Order Form"},"content":{"rendered":"\n<div id=\"csa-container-message\" class=\"csa-order-form-container\">\n        <!-- \u2500\u2500 Step Progress Bar \u2500\u2500 -->\n    <div class=\"csa-steps\" id=\"csa-steps\">\n        <div class=\"csa-step active\" data-step=\"1\">\n            <div class=\"step-circle\">1<\/div>\n            <span class=\"step-label\">Location &amp; Pickup<\/span>\n        <\/div>\n        <div class=\"step-connector\"><\/div>\n        <div class=\"csa-step\" data-step=\"2\">\n            <div class=\"step-circle\">2<\/div>\n            <span class=\"step-label\">Choose Products<\/span>\n        <\/div>\n        <div class=\"step-connector\"><\/div>\n        <div class=\"csa-step\" data-step=\"3\">\n            <div class=\"step-circle\">3<\/div>\n            <span class=\"step-label\">Review &amp; Pay<\/span>\n        <\/div>\n    <\/div>\n\n    <form id=\"csa-order-form\">\n\n        <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n             SECTION 1 \u2014 Location & Pickup\n             \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n        <div class=\"csa-section active\" id=\"csa-section-1\">\n            <div class=\"csa-section-header\">\n                <span class=\"section-badge\">1<\/span>\n                <div>\n                    <h2>Select Your Location &amp; Pickup Day<\/h2>\n                    <p class=\"section-subtitle\">Find a CSA pickup location near you and choose your preferred day.<\/p>\n                <\/div>\n            <\/div>\n\n            <div id=\"map-container\">\n                <input id=\"user-address\" type=\"text\" placeholder=\"Enter your address to find nearby pickup locations\u2026\">\n                <div id=\"map\"><\/div>\n            <\/div>\n\n            <select id=\"csa-location-selector\" name=\"csa_location\">\n                <option value=\"\">\u2014 Select a pickup location \u2014<\/option>\n                                    <option value=\"1\"\n                            data-places=\"51 Lenape Ln, Great Meadows, NJ 07838, USA\"\n                            data-pickup-days='[&quot;Saturday&quot;]'\n                            data-pickup-times='{&quot;Saturday&quot;:{&quot;start&quot;:&quot;09:00&quot;,&quot;end&quot;:&quot;12:00&quot;}}'\n                            data-delivery='[{&quot;title&quot;:&quot;Free Local Pickup&quot;,&quot;description&quot;:&quot;Customer picks up their shares at this location.&quot;,&quot;price&quot;:&quot;0.00&quot;},{&quot;title&quot;:&quot;DoorDash Delivery&quot;,&quot;description&quot;:&quot;Starts at $7.00 plus tip per delivery.&quot;,&quot;price&quot;:&quot;7.00&quot;}]'>\n                        Farm pickup-Allamuchy                    <\/option>\n                                    <option value=\"2\"\n                            data-places=\"Bald Eagle Rd N, Allamuchy Township, NJ 07840, USA\"\n                            data-pickup-days='[&quot;Friday&quot;]'\n                            data-pickup-times='{&quot;Friday&quot;:{&quot;start&quot;:&quot;09:30&quot;,&quot;end&quot;:&quot;11:00&quot;}}'\n                            data-delivery='[{&quot;title&quot;:&quot;DoorDash Delivery&quot;,&quot;description&quot;:&quot;Starts at $7.00 plus tip per delivery.&quot;,&quot;price&quot;:&quot;7.00&quot;},{&quot;title&quot;:&quot;PV resident only)&quot;,&quot;description&quot;:&quot;Delivery within the gated community, Panther Valley&quot;,&quot;price&quot;:3}]'>\n                        Panther Valley Resident (only within gated community)                    <\/option>\n                                    <option value=\"3\"\n                            data-places=\"Main St, Boonton, NJ 07005, USA\"\n                            data-pickup-days='[&quot;Thursday&quot;]'\n                            data-pickup-times='{&quot;Thursday&quot;:{&quot;start&quot;:&quot;10:00&quot;,&quot;end&quot;:&quot;13:00&quot;}}'\n                            data-delivery='[{&quot;title&quot;:&quot;Boonton area&quot;,&quot;description&quot;:&quot;delivery for the general Boonton NJ area&quot;,&quot;price&quot;:7}]'>\n                        Boonton area                    <\/option>\n                                    <option value=\"4\"\n                            data-places=\"Paramus, NJ 07652, USA\"\n                            data-pickup-days='[&quot;Thursday&quot;]'\n                            data-pickup-times='{&quot;Thursday&quot;:{&quot;start&quot;:&quot;11:00&quot;,&quot;end&quot;:&quot;14:00&quot;}}'\n                            data-delivery='[{&quot;title&quot;:&quot;Paramus delivery&quot;,&quot;description&quot;:&quot;(Paramus, Ridgewood, River edge\\\/Oradell, to GArfield also&quot;,&quot;price&quot;:10}]'>\n                        Paramus NJ area                    <\/option>\n                            <\/select>\n\n            <div id=\"location-details\"><\/div>\n\n            <div class=\"section-footer\">\n                <button type=\"button\" class=\"btn-next\" id=\"next-to-step-2\">\n                    Continue to Products \u2192\n                <\/button>\n            <\/div>\n        <\/div>\n\n        <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n             SECTION 2 \u2014 Products & Add-Ons\n             \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n        <div class=\"csa-section\" id=\"csa-section-2\">\n            <div class=\"csa-section-header\">\n                <span class=\"section-badge\">2<\/span>\n                <div>\n                    <h2>Select Your CSA Products<\/h2>\n                    <p class=\"section-subtitle\">Choose a CSA share and any add-ons you'd like.<\/p>\n                <\/div>\n            <\/div>\n\n            <h3 class=\"product-group-label\">CSA Shares<\/h3>\n            <div class=\"csa-products\">\n                                    <div class=\"csa-product\"\n                         data-id=\"1\"\n                         data-price=\"200.00\">\n\n                                                    <img decoding=\"async\" src=\"https:\/\/farmtab.com\/growingdirtfarm\/wp-content\/uploads\/sites\/71\/2026\/03\/original-13.jpeg\" alt=\"Pastured Egg (4 doz) subscription\">\n                        \n                        <h3>Pastured Egg (4 doz) subscription<\/h3>\n                        <p class=\"product-price\">$200.00<\/p>\n                        <p class=\"price-per-share\">$25.00 per share<\/p>\n                        <span class=\"renewal-freq\">monthly<\/span>\n\n                        <button type=\"button\" class=\"product-details-toggle\" aria-expanded=\"false\">Show details \u25be<\/button>\n                        <div class=\"product-meta\"\n                             data-total-shares=\"8\"\n                             data-renewal-freq=\"monthly\"\n                             data-start-date=\"2026-05-01\">\n                            <p>Get 4 dozen pasture raised eggs once a month.\r\n\r\nNote-  each CSA week you will get a reminder before which allows you to select whatever pickup or delivery options there may be, including Door dash where available.<\/p>\n                            <p><strong>Total Shares:<\/strong> 8<\/p>\n                            <p><strong>Start Date:<\/strong> Friday, May 1, 2026<\/p>\n                        <\/div>\n\n                        <div class=\"product-actions\">\n                            <button type=\"button\" class=\"add-to-order-btn button\">Add to Order<\/button>\n                            <div class=\"quantity-container\">\n                                <label>Qty:<\/label>\n                                <input type=\"number\" class=\"product-quantity\" min=\"1\" value=\"1\">\n                            <\/div>\n                        <\/div>\n\n                        <input type=\"hidden\" class=\"selected-product-id\" value=\"\">\n                    <\/div>\n                                    <div class=\"csa-product\"\n                         data-id=\"2\"\n                         data-price=\"224.00\">\n\n                                                    <img decoding=\"async\" src=\"https:\/\/farmtab.com\/growingdirtfarm\/wp-content\/uploads\/sites\/71\/2026\/03\/original-13.jpeg\" alt=\"Pastured Egg (2 doz)subscription\">\n                        \n                        <h3>Pastured Egg (2 doz)subscription<\/h3>\n                        <p class=\"product-price\">$224.00<\/p>\n                        <p class=\"price-per-share\">$14.00 per share<\/p>\n                        <span class=\"renewal-freq\">biweekly<\/span>\n\n                        <button type=\"button\" class=\"product-details-toggle\" aria-expanded=\"false\">Show details \u25be<\/button>\n                        <div class=\"product-meta\"\n                             data-total-shares=\"16\"\n                             data-renewal-freq=\"biweekly\"\n                             data-start-date=\"2026-05-01\">\n                            <p>2 dozen pastured eggs twice a month<\/p>\n                            <p><strong>Total Shares:<\/strong> 16<\/p>\n                            <p><strong>Start Date:<\/strong> Friday, May 1, 2026<\/p>\n                        <\/div>\n\n                        <div class=\"product-actions\">\n                            <button type=\"button\" class=\"add-to-order-btn button\">Add to Order<\/button>\n                            <div class=\"quantity-container\">\n                                <label>Qty:<\/label>\n                                <input type=\"number\" class=\"product-quantity\" min=\"1\" value=\"1\">\n                            <\/div>\n                        <\/div>\n\n                        <input type=\"hidden\" class=\"selected-product-id\" value=\"\">\n                    <\/div>\n                            <\/div>\n\n            <h3 class=\"product-group-label\">Add-Ons<\/h3>\n            <div class=\"csa-products\">\n                                                            <div class=\"csa-product\"\n                             data-id=\"3\"\n                             data-price=\"110.00\">\n\n                                                            <img decoding=\"async\" src=\"https:\/\/farmtab.com\/growingdirtfarm\/wp-content\/uploads\/sites\/71\/2026\/03\/original-16.jpeg\" alt=\"Select a Sausage add-on\">\n                            \n                            <h3>Select a Sausage add-on<\/h3>\n                            <p class=\"product-price\">$110.00<\/p>\n                            <p class=\"price-per-share\">$13.75 per share<\/p>\n                            <span class=\"renewal-freq\">monthly<\/span>\n\n                            <button type=\"button\" class=\"product-details-toggle\" aria-expanded=\"false\">Show details \u25be<\/button>\n                            <div class=\"product-meta\"\n                                 data-total-shares=\"8\"\n                                 data-renewal-freq=\"monthly\"\n                                 data-start-date=\"2026-05-01\">\n                                <p>add on a selection of our pasture raised pork, nitrate free sausage once a month to go along with your other CSA deliveries.\r\n\r\nYou will be able to select one style from a choice of 4 each month.\r\n\r\nNote-  you can also shop items ala carte if you wish without subscribing.<\/p>\n                                <p><strong>Total Shares:<\/strong> 8<\/p>\n                                <p><strong>Start Date:<\/strong> Friday, May 1, 2026<\/p>\n                            <\/div>\n\n                            <div class=\"product-actions\">\n                                <button type=\"button\" class=\"add-to-order-btn button\">Add to Order<\/button>\n                                <div class=\"quantity-container\">\n                                    <label>Qty:<\/label>\n                                    <input type=\"number\" class=\"product-quantity\" min=\"1\" value=\"1\">\n                                <\/div>\n                            <\/div>\n\n                            <input type=\"hidden\" class=\"selected-product-id\" value=\"\">\n                        <\/div>\n                                                <\/div>\n\n            <div id=\"delivery-options\"><\/div>\n\n            <div class=\"section-footer two-col\">\n                <button type=\"button\" class=\"btn-back\" id=\"back-to-step-1\">\u2190 Back<\/button>\n                <button type=\"button\" class=\"btn-next\" id=\"next-to-step-3\">\n                    Continue to Review &amp; Pay \u2192\n                <\/button>\n            <\/div>\n        <\/div>\n\n        <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n             SECTION 3 \u2014 Review & Pay\n             \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n        <div class=\"csa-section\" id=\"csa-section-3\">\n            <div class=\"csa-section-header\">\n                <span class=\"section-badge\">3<\/span>\n                <div>\n                    <h2>Review &amp; Pay<\/h2>\n                    <p class=\"section-subtitle\">Confirm your order details and complete your payment.<\/p>\n                <\/div>\n            <\/div>\n\n            <!-- Order Summary -->\n            <div id=\"order-total\">Total: $0.00<\/div>\n\n            <div id=\"payment-options\">\n                <h3>Payment Options<\/h3>\n                <select id=\"payment-method\" name=\"payment_method\" required>\n                    <option value=\"\" disabled selected>\u2014 Select a payment plan \u2014<\/option>\n                    <option value=\"full\">Pay in Full<\/option>\n                                        <option value=\"monthly\">Pay in 3 Monthly Installments<\/option>\n                                        <option value=\"weekly\">Pay in 10 Weekly Installments<\/option>\n                                    <\/select>\n            <\/div>\n\n            <div id=\"installment-breakdown\"><\/div>\n            <div id=\"cart-totals\"><\/div>\n\n            <!-- Billing Details -->\n            <h3 class=\"billing-heading\">Billing Details<\/h3>\n            <p class=\"billing-subtext\">Please enter your billing information below.<\/p>\n            <div class=\"billing-fields\">\n                <div>\n                    <label for=\"billing_first_name\">First Name<\/label>\n                    <input type=\"text\" id=\"billing_first_name\" name=\"billing_first_name\" placeholder=\"Jane\" required>\n                <\/div>\n                <div>\n                    <label for=\"billing_last_name\">Last Name<\/label>\n                    <input type=\"text\" id=\"billing_last_name\" name=\"billing_last_name\" placeholder=\"Smith\" required>\n                <\/div>\n                <div>\n                    <label for=\"billing_phone\">Phone Number<\/label>\n                    <input type=\"tel\" id=\"billing_phone\" name=\"billing_phone\" placeholder=\"(555) 000-0000\" required>\n                <\/div>\n                <div class=\"full-width\">\n                    <label for=\"billing_street\">Street Address<\/label>\n                    <input type=\"text\" id=\"billing_street\" name=\"billing_street\" placeholder=\"123 Main St\" required>\n                <\/div>\n                <div>\n                    <label for=\"billing_city\">City<\/label>\n                    <input type=\"text\" id=\"billing_city\" name=\"billing_city\" placeholder=\"Springfield\" required>\n                <\/div>\n                <div>\n                    <label for=\"billing_state\">State<\/label>\n                    <input type=\"text\" id=\"billing_state\" name=\"billing_state\" placeholder=\"NJ\" required>\n                <\/div>\n                <div>\n                    <label for=\"billing_zip\">ZIP Code<\/label>\n                    <input type=\"text\" id=\"billing_zip\" name=\"billing_zip\" placeholder=\"08540\" required>\n                <\/div>\n            <\/div>\n\n            <!-- Payment -->\n            <div id=\"stripe-payment-section\">\n                <h3>Payment Information<\/h3>\n                <div id=\"card-element\"><\/div>\n                <div id=\"card-errors\"><\/div>\n                <button type=\"submit\" id=\"submit-button\" class=\"button button-primary\">Submit and Pay<\/button>\n            <\/div>\n\n            <!-- Message for logged-out users \u2014 triggers the login\/register modal -->\n            <div id=\"login-required-message\">\n                <h3>Please log in or register to continue<\/h3>\n                <p>You must be logged in to submit this form and complete your payment.<\/p>\n                <button type=\"button\" id=\"csa-open-login-modal\" class=\"button button-primary\">Log In<\/button>\n                <button type=\"button\" id=\"csa-open-register-modal\" class=\"button button-secondary\">Create Account<\/button>\n            <\/div>\n\n            <!-- Login \/ Register Modal -->\n            <div id=\"csa-auth-modal\" style=\"display:none;position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,0.55);overflow-y:auto;\" role=\"dialog\" aria-modal=\"true\">\n                <div style=\"background:#fff;border-radius:10px;max-width:420px;width:calc(100% - 32px);margin:60px auto;padding:28px;position:relative;box-shadow:0 8px 32px rgba(0,0,0,0.2);\">\n                    <button id=\"csa-auth-modal-close\" type=\"button\" aria-label=\"Close\" style=\"position:absolute;top:12px;right:14px;background:none;border:none;font-size:24px;cursor:pointer;color:#555;line-height:1;\">&times;<\/button>\n\n                    <!-- Tab switcher -->\n                    <div style=\"display:flex;gap:0;margin-bottom:20px;border-bottom:2px solid #eee;\">\n                        <button type=\"button\" class=\"csa-auth-tab active\" data-tab=\"login\" style=\"flex:1;padding:10px;border:none;background:none;font-size:15px;font-weight:600;cursor:pointer;border-bottom:2px solid #333;margin-bottom:-2px;\">Log In<\/button>\n                        <button type=\"button\" class=\"csa-auth-tab\" data-tab=\"register\" style=\"flex:1;padding:10px;border:none;background:none;font-size:15px;font-weight:400;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;\">Create Account<\/button>\n                    <\/div>\n\n                    <!-- Login form -->\n                    <div id=\"csa-tab-login\">\n                        <p id=\"csa-login-msg\" style=\"display:none;color:red;margin-bottom:10px;\"><\/p>\n                        <label style=\"display:block;margin-bottom:10px;\">Username or Email\n                            <input type=\"text\" id=\"csa-login-user\" autocomplete=\"username\" style=\"display:block;width:100%;margin-top:4px;padding:8px;border:1px solid #ccc;border-radius:4px;\">\n                        <\/label>\n                        <label style=\"display:block;margin-bottom:14px;\">Password\n                            <input type=\"password\" id=\"csa-login-pass\" autocomplete=\"current-password\" style=\"display:block;width:100%;margin-top:4px;padding:8px;border:1px solid #ccc;border-radius:4px;\">\n                        <\/label>\n                        <button type=\"button\" id=\"csa-login-btn\" style=\"width:100%;padding:11px;background:#333;color:#fff;border:none;border-radius:5px;font-size:15px;cursor:pointer;\">Log In<\/button>\n                        <p style=\"text-align:center;margin-top:12px;font-size:13px;\">\n                            <a href=\"https:\/\/farmtab.com\/growingdirtfarm\/my-account\/lost-password\/\" target=\"_blank\">Forgot password?<\/a>\n                        <\/p>\n                    <\/div>\n\n                    <!-- Register form -->\n                    <div id=\"csa-tab-register\" style=\"display:none;\">\n                        <p id=\"csa-register-msg\" style=\"display:none;color:red;margin-bottom:10px;\"><\/p>\n                        <label style=\"display:block;margin-bottom:10px;\">First Name\n                            <input type=\"text\" id=\"csa-reg-first\" autocomplete=\"given-name\" style=\"display:block;width:100%;margin-top:4px;padding:8px;border:1px solid #ccc;border-radius:4px;\">\n                        <\/label>\n                        <label style=\"display:block;margin-bottom:10px;\">Last Name\n                            <input type=\"text\" id=\"csa-reg-last\" autocomplete=\"family-name\" style=\"display:block;width:100%;margin-top:4px;padding:8px;border:1px solid #ccc;border-radius:4px;\">\n                        <\/label>\n                        <label style=\"display:block;margin-bottom:10px;\">Email Address\n                            <input type=\"email\" id=\"csa-reg-email\" autocomplete=\"email\" style=\"display:block;width:100%;margin-top:4px;padding:8px;border:1px solid #ccc;border-radius:4px;\">\n                        <\/label>\n                        <label style=\"display:block;margin-bottom:14px;\">Password\n                            <input type=\"password\" id=\"csa-reg-pass\" autocomplete=\"new-password\" style=\"display:block;width:100%;margin-top:4px;padding:8px;border:1px solid #ccc;border-radius:4px;\">\n                        <\/label>\n                        <button type=\"button\" id=\"csa-register-btn\" style=\"width:100%;padding:11px;background:#333;color:#fff;border:none;border-radius:5px;font-size:15px;cursor:pointer;\">Create Account<\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <div class=\"section-footer two-col\">\n                <button type=\"button\" class=\"btn-back\" id=\"back-to-step-2\">\u2190 Back to Products<\/button>\n            <\/div>\n        <\/div>\n\n    <\/form>\n\n    <script>\n    \/\/ Product details toggle\n    document.addEventListener('DOMContentLoaded', function () {\n        document.querySelectorAll('.product-details-toggle').forEach(function (btn) {\n            btn.addEventListener('click', function () {\n                var meta = btn.nextElementSibling;\n                var open = meta.classList.toggle('open');\n                btn.setAttribute('aria-expanded', open);\n                btn.textContent = open ? 'Hide details \u25b4' : 'Show details \u25be';\n            });\n        });\n    });\n    <\/script>\n\n    <script>\n    \/\/ \u2500\u2500 Stepper Navigation \u2500\u2500\n    document.addEventListener('DOMContentLoaded', function () {\n        var currentStep = 1;\n\n        function goToStep(n) {\n            document.querySelectorAll('.csa-section').forEach(function(s) {\n                s.classList.remove('active');\n            });\n            var target = document.getElementById('csa-section-' + n);\n            if (target) target.classList.add('active');\n\n            document.querySelectorAll('.csa-step').forEach(function(s) {\n                var num = parseInt(s.getAttribute('data-step'));\n                s.classList.remove('active', 'completed');\n                if (num === n) s.classList.add('active');\n                if (num < n)  s.classList.add('completed');\n            });\n\n            document.querySelectorAll('.step-connector').forEach(function(c, i) {\n                c.classList.toggle('filled', i < n - 1);\n            });\n\n            currentStep = n;\n\n            var stepsEl = document.getElementById('csa-steps');\n            if (stepsEl) stepsEl.scrollIntoView({ behavior: 'smooth', block: 'start' });\n        }\n\n        var next1 = document.getElementById('next-to-step-2');\n        if (next1) next1.addEventListener('click', function() {\n            var loc = document.getElementById('csa-location-selector');\n            if (!loc || !loc.value) {\n                loc.focus();\n                loc.style.borderColor = '#dc2626';\n                setTimeout(function(){ loc.style.borderColor = ''; }, 2000);\n                return;\n            }\n            var pickupChecked = document.querySelector('input[name=\"selected_pickup_day\"]:checked');\n            if (!pickupChecked) {\n                var details = document.getElementById('location-details');\n                if (details) {\n                    details.style.outline = '2px solid #dc2626';\n                    details.style.borderRadius = '8px';\n                    setTimeout(function(){ details.style.outline = ''; }, 2000);\n                }\n                return;\n            }\n            goToStep(2);\n        });\n\n        var next2 = document.getElementById('next-to-step-3');\n        if (next2) next2.addEventListener('click', function() {\n            var anySelected = document.querySelector('.csa-product .selected-product-id[value]:not([value=\"\"])');\n            if (!anySelected) {\n                var grid = document.querySelector('.csa-products');\n                if (grid) {\n                    grid.style.outline = '2px solid #dc2626';\n                    grid.style.borderRadius = '10px';\n                    setTimeout(function(){ grid.style.outline = ''; }, 2000);\n                }\n                return;\n            }\n            goToStep(3);\n        });\n\n        var back1 = document.getElementById('back-to-step-1');\n        if (back1) back1.addEventListener('click', function(){ goToStep(1); });\n\n        var back2 = document.getElementById('back-to-step-2');\n        if (back2) back2.addEventListener('click', function(){ goToStep(2); });\n    });\n    <\/script>\n\n<script>\ndocument.addEventListener('DOMContentLoaded', function () {\n\n    function formatTime24to12(timeStr) {\n        if (!timeStr) return '';\n        const [hour, minute] = timeStr.split(':');\n        const date = new Date();\n        date.setHours(hour);\n        date.setMinutes(minute || 0);\n        return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });\n    }\n\n    \/\/ \u2500\u2500 Use the platform publishable key (shared with WooCommerce Stripe Connect Gateway) \u2500\u2500\n    const stripeKey  = \"pk_live_51MrtHzFHwmClpvVk2FVSJWoTNSSK2WjZREbSBDdefLM47b91kgCJzxLLCgxeoomwmj3erRT7pMZNViDDFrVCdvBZ000vRh38Kn\";\n    const serviceFee = 7.99;\n    const ajaxUrl    = \"https:\/\/farmtab.com\/growingdirtfarm\/wp-admin\/admin-ajax.php\";\n    const isLoggedIn      = false;\n    const csaMonthlyCount = 3;\n    const csaWeeklyCount  = 10;\n\n    document.getElementById(\"stripe-payment-section\").style.display  = isLoggedIn ? \"block\" : \"none\";\n    document.getElementById(\"login-required-message\").style.display = isLoggedIn ? \"none\"  : \"block\";\n\n    if (!stripeKey) {\n        console.error(\"Error: Stripe publishable key is missing.\");\n        alert(\"Stripe is not configured properly. Please check your settings.\");\n        return;\n    }\n\n    const stripe     = Stripe(stripeKey);\n    const elements   = stripe.elements();\n    const cardElement = elements.create(\"card\");\n    cardElement.mount(\"#card-element\");\n\n    const form                 = document.getElementById('csa-order-form');\n    const locationSelector     = document.getElementById('csa-location-selector');\n    const locationDetails      = document.getElementById('location-details');\n    const deliveryOptions      = document.getElementById('delivery-options');\n    const totalDisplay         = document.getElementById('order-total');\n    const paymentSelect        = document.getElementById('payment-method');\n    const installmentBreakdown = document.getElementById('installment-breakdown');\n    const cartTotalsContainer  = document.getElementById('cart-totals');\n    const submitButton         = form.querySelector('button[type=\"submit\"]');\n\n    let clientSecret  = null;\n    let dueNowAmount  = 0;\n    let fullAmount    = 0;\n    let monthlyAmount = 0;\n    let weeklyAmount  = 0;\n\n    \/\/ \u2500\u2500 Location selector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    if (locationSelector) {\n        locationSelector.addEventListener(\"change\", function () {\n            const selected       = this.options[this.selectedIndex];\n            const address        = selected.getAttribute(\"data-places\") || \"\";\n            const pickupDays     = JSON.parse(selected.getAttribute(\"data-pickup-days\") || \"[]\");\n            const pickupTimes    = JSON.parse(selected.getAttribute(\"data-pickup-times\") || \"{}\");\n            const deliveryOpts   = JSON.parse(selected.getAttribute(\"data-delivery\") || \"[]\");\n\n            let customDeliveryFee   = 0;\n            let customDeliveryTitle = \"\";\n\n            let pickupHtml = `<p><strong>Address:<\/strong> ${address}<\/p><p><strong>Select a Pickup Day:<\/strong><\/p>`;\n            if (pickupDays.length > 0) {\n                pickupHtml += \"<div>\";\n                pickupDays.forEach(day => {\n                    const time      = pickupTimes[day] || {};\n                    const startTime = formatTime24to12(time.start);\n                    const endTime   = formatTime24to12(time.end);\n                    const timeStr   = (startTime || endTime)\n                        ? `${startTime}${startTime && endTime ? ' - ' : ''}${endTime}` : '';\n                    pickupHtml += `\n                        <label>\n                            <input type=\"radio\" name=\"selected_pickup_day\" value=\"${day}\" required>\n                            ${day} ${timeStr ? `(${timeStr})` : ''}\n                        <\/label><br>`;\n                });\n                pickupHtml += \"<\/div>\";\n            }\n            locationDetails.innerHTML = pickupHtml;\n\n            let deliveryHtml = \"<h3>Available Delivery Options<\/h3><ul>\";\n            deliveryOpts.forEach(option => {\n                if (typeof option === \"object\" && option.title && option.price && option.description) {\n                    deliveryHtml += `<li><strong>${option.title}<\/strong>: ${option.description} ($${parseFloat(option.price).toFixed(2)})<\/li>`;\n                    if (option.title !== \"Free Local Pickup\" && option.title !== \"DoorDash Delivery\") {\n                        customDeliveryFee   = parseFloat(option.price);\n                        customDeliveryTitle = option.title;\n                    }\n                }\n            });\n            deliveryHtml += \"<\/ul>\";\n\n            const deliveryOptionsContainer = document.getElementById(\"delivery-options\");\n            if (deliveryOptionsContainer) {\n                deliveryOptionsContainer.innerHTML = deliveryHtml;\n            }\n\n            window.selectedDeliveryFee   = customDeliveryFee;\n            window.selectedDeliveryTitle = customDeliveryTitle;\n            updateTotal();\n        });\n    }\n\n    \/\/ \u2500\u2500 Add \/ remove products \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    form.addEventListener('click', function (event) {\n        if (event.target.classList.contains('add-to-order-btn')) {\n            const product         = event.target.closest('.csa-product');\n            const hiddenInput     = product.querySelector('.selected-product-id');\n            const quantityContainer = product.querySelector('.quantity-container');\n\n            if (!hiddenInput.value) {\n                event.target.textContent = 'Added \u2713';\n                event.target.classList.add('added');\n                hiddenInput.value = product.dataset.id;\n                product.classList.add('selected');\n                quantityContainer.classList.add('visible');\n            } else {\n                event.target.textContent = 'Add to Order';\n                event.target.classList.remove('added');\n                hiddenInput.value = '';\n                product.classList.remove('selected');\n                quantityContainer.classList.remove('visible');\n            }\n            updateTotal();\n        }\n    });\n\n    form.addEventListener('change', function (event) {\n        if (event.target.classList.contains('product-quantity')) {\n            updateTotal();\n        }\n    });\n\n    \/\/ \u2500\u2500 Pro-rate helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    \/\/ Returns the dollar amount to deduct from a product line when the customer\n    \/\/ is ordering after the product's start date.\n    \/\/\n    \/\/ Logic:\n    \/\/   \u2022 per-share cost = price \/ total_shares\n    \/\/   \u2022 elapsed shares = number of share periods that have *fully* passed since\n    \/\/     start_date as of today (each period = renewal interval in days)\n    \/\/   \u2022 discount = elapsed_shares \u00d7 per_share_cost \u00d7 qty\n    \/\/   \u2022 capped at the line total (can never create a negative product cost)\n    \/\/   \u2022 only applies when payment plan = \"full\" (installment customers pay\n    \/\/     the full split amount \u2014 the subscription handles timing automatically)\n    \/\/\n    \/\/ renewal_frequency values (from the DB): weekly, biweekly, monthly\n    function calcProration(price, totalShares, renewalFreq, startDateStr, qty) {\n        if (!startDateStr || !totalShares || totalShares <= 0) return 0;\n\n        const today     = new Date();\n        today.setHours(0, 0, 0, 0);\n        \/\/ Parse YYYY-MM-DD start date without UTC shift\n        const parts     = startDateStr.split('-');\n        const startDate = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));\n        startDate.setHours(0, 0, 0, 0);\n\n        if (today <= startDate) return 0; \/\/ hasn't started yet \u2014 no proration\n\n        const msPerDay     = 1000 * 60 * 60 * 24;\n        const daysSinceStart = Math.floor((today - startDate) \/ msPerDay);\n\n        \/\/ Share interval in days\n        const freq = (renewalFreq || '').toLowerCase().trim();\n        let intervalDays;\n        if      (freq === 'weekly')    intervalDays = 7;\n        else if (freq === 'biweekly')  intervalDays = 14;\n        else if (freq === 'monthly')   intervalDays = 30;\n        else return 0; \/\/ unknown frequency \u2014 skip proration to be safe\n\n        \/\/ Fully elapsed share periods (floor \u2014 don't count the current active period)\n        const elapsedShares = Math.min(\n            Math.floor(daysSinceStart \/ intervalDays),\n            totalShares - 1  \/\/ never deduct the last share (customer still receives value)\n        );\n\n        if (elapsedShares <= 0) return 0;\n\n        const perShareCost = price \/ totalShares;\n        const discount     = elapsedShares * perShareCost * qty;\n\n        \/\/ Cap at the full line total so we never go negative\n        return Math.min(discount, price * qty);\n    }\n\n    \/\/ \u2500\u2500 Update cart total and request a fresh PaymentIntent \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    async function updateTotal() {\n        let productSubtotal = 0;  \/\/ raw product cost before proration\n        let totalProration  = 0;  \/\/ total discount from elapsed shares\n        let cartHTML = '<h3>Cart Totals<\/h3><table style=\"width:100%; border-collapse: collapse;\">';\n        cartHTML    += '<tr><th style=\"text-align:left;\">Product<\/th><th>Qty<\/th><th>Price<\/th><th>Total<\/th><\/tr>';\n\n        const selectedPlanForProrate = paymentSelect?.value || 'full';\n\n        document.querySelectorAll(\".csa-product\").forEach(product => {\n            const selectedId = product.querySelector(\".selected-product-id\")?.value;\n            if (selectedId) {\n                const name        = product.querySelector(\"h3\").textContent.split(\" - \")[0];\n                const price       = parseFloat(product.dataset.price);\n                const qty         = parseInt(product.querySelector(\".product-quantity\")?.value) || 1;\n                const lineTotal   = price * qty;\n                productSubtotal  += lineTotal;\n\n                \/\/ Read product metadata for proration\n                const meta        = product.querySelector('.product-meta');\n                const totalShares = parseInt(meta?.dataset.totalShares) || 0;\n                const renewalFreq = meta?.dataset.renewalFreq || '';\n                const startDate   = meta?.dataset.startDate   || '';\n\n                \/\/ Proration only on Pay in Full \u2014 installment plans divide the\n                \/\/ full cost across the subscription schedule automatically.\n                let lineProration = 0;\n                if (selectedPlanForProrate === 'full') {\n                    lineProration = calcProration(price, totalShares, renewalFreq, startDate, qty);\n                    totalProration += lineProration;\n                }\n\n                const discountedLine = lineTotal - lineProration;\n\n                cartHTML += `\n                    <tr>\n                        <td>${name}${lineProration > 0 ? ' <em style=\"color:#888;font-size:0.85em;\">(prorated)<\/em>' : ''}<\/td>\n                        <td style=\"text-align:center;\">${qty}<\/td>\n                        <td style=\"text-align:right;\">$${price.toFixed(2)}<\/td>\n                        <td style=\"text-align:right;\">${lineProration > 0\n                            ? `<span style=\"text-decoration:line-through;color:#999;\">$${lineTotal.toFixed(2)}<\/span> $${discountedLine.toFixed(2)}`\n                            : `$${lineTotal.toFixed(2)}`\n                        }<\/td>\n                    <\/tr>`;\n            }\n        });\n\n        cartHTML += \"<\/table>\";\n        cartHTML += `<p><strong>Subtotal:<\/strong> $${productSubtotal.toFixed(2)}<\/p>`;\n\n        \/\/ Show proration line if any discount applies\n        if (totalProration > 0) {\n            cartHTML += `<p style=\"color:#2a7d4f;\">\n                <strong>Prorated Discount:<\/strong>\n                &minus;$${totalProration.toFixed(2)}\n                <span class=\"proration-discount-value\" data-amount=\"${totalProration.toFixed(2)}\" style=\"display:none;\"><\/span>\n                <span style=\"font-size:0.85em;color:#666;display:block;margin-top:2px;\">\n                    Shares that have already passed since the product start date have been\n                    deducted from your product total. Your service fee and delivery fee are not affected.\n                <\/span>\n            <\/p>`;\n        }\n\n        \/\/ Start building the running total from the prorated product cost\n        let total = productSubtotal - totalProration;\n\n        if (serviceFee > 0) {\n            total    += serviceFee;\n            cartHTML += `<p><strong>Service Fee:<\/strong> $${serviceFee.toFixed(2)}<\/p>`;\n        }\n\n        if (window.selectedDeliveryFee && window.selectedDeliveryFee > 0) {\n            total    += window.selectedDeliveryFee;\n            cartHTML += `<p><strong>Delivery Fee (${window.selectedDeliveryTitle}):<\/strong> $${window.selectedDeliveryFee.toFixed(2)}<\/p>`;\n        }\n\n        fullAmount    = total;\n        monthlyAmount = total \/ csaMonthlyCount;\n        weeklyAmount  = total \/ csaWeeklyCount;\n\n        dueNowAmount = calculateDueNow(total);\n\n        \/\/ Per-installment service fee sent to server so application_fee_amount\n        \/\/ is the correct fraction per charge, not the full option value.\n        const plan = paymentSelect?.value || 'full';\n        if      (plan === 'monthly') window.csaServiceFeeInstallment = serviceFee \/ csaMonthlyCount;\n        else if (plan === 'weekly')  window.csaServiceFeeInstallment = serviceFee \/ csaWeeklyCount;\n        else                         window.csaServiceFeeInstallment = serviceFee;\n\n        totalDisplay.textContent = `Total: $${total.toFixed(2)}`;\n        cartHTML += `<p><strong>Amount Due Today:<\/strong> $${dueNowAmount.toFixed(2)}<\/p>`;\n        cartHTML += getInstallmentScheduleHTML(total);\n\n        const cartTotalsEl = document.getElementById(\"cart-totals\");\n        if (cartTotalsEl) cartTotalsEl.innerHTML = cartHTML;\n\n        if (installmentBreakdown) {\n            installmentBreakdown.innerHTML = getInstallmentScheduleHTML(total);\n        }\n\n        if (submitButton) {\n            submitButton.textContent = `Pay now ($${dueNowAmount.toFixed(2)})`;\n        }\n\n        await fetchPaymentIntent();\n    }\n\n    function calculateDueNow(total) {\n        const method = paymentSelect?.value || 'full';\n        if (method === 'monthly') return total \/ csaMonthlyCount;\n        if (method === 'weekly')  return total \/ csaWeeklyCount;\n        return total;\n    }\n\n    function getInstallmentScheduleHTML(total) {\n        const method = paymentSelect?.value || 'full';\n        const today  = new Date();\n        let html     = '';\n\n        if (method === 'monthly') {\n            const installment = total \/ csaMonthlyCount;\n            const dueDates = Array.from({ length: csaMonthlyCount }, (_, i) => {\n                const d = new Date(today);\n                d.setDate(d.getDate() + (i * 30));\n                return d.toLocaleDateString();\n            });\n            html = `\n                <p><strong>Installment Plan:<\/strong> ${csaMonthlyCount} monthly payments of $${installment.toFixed(2)}<\/p>\n                <ul>${dueDates.map(date => `<li>${date}: $${installment.toFixed(2)}<\/li>`).join('')}<\/ul>`;\n        } else if (method === 'weekly') {\n            const installment = total \/ csaWeeklyCount;\n            html = `<p><strong>Installment Plan:<\/strong> ${csaWeeklyCount} weekly payments of $${installment.toFixed(2)}<\/p><ul>`;\n            for (let i = 0; i < csaWeeklyCount; i++) {\n                const due = new Date(today);\n                due.setDate(today.getDate() + (i * 7));\n                html += `<li>${due.toLocaleDateString()}: $${installment.toFixed(2)}<\/li>`;\n            }\n            html += '<\/ul>';\n        } else {\n            html = `<p><strong>Full Payment:<\/strong> $${total.toFixed(2)} due today.<\/p>`;\n        }\n        return html;\n    }\n\n    if (paymentSelect) {\n        paymentSelect.addEventListener('change', async function () {\n            const selectedPlan = this.value;\n            switch (selectedPlan) {\n                case 'full':    dueNowAmount = fullAmount;                          break;\n                case 'monthly': dueNowAmount = fullAmount \/ csaMonthlyCount;        break;\n                case 'weekly':  dueNowAmount = fullAmount \/ csaWeeklyCount;         break;\n                default: return;\n            }\n            \/\/ Keep per-installment fee in sync with the chosen plan\n            if      (selectedPlan === 'monthly') window.csaServiceFeeInstallment = serviceFee \/ csaMonthlyCount;\n            else if (selectedPlan === 'weekly')  window.csaServiceFeeInstallment = serviceFee \/ csaWeeklyCount;\n            else                                  window.csaServiceFeeInstallment = serviceFee;\n            await updateTotal();\n        });\n    }\n\n    \/\/ \u2500\u2500 Fetch a Stripe Connect split PaymentIntent from the server \u2500\u2500\u2500\u2500\u2500\n    \/\/ The AJAX handler (csa_create_payment_intent in csa-plugin.php) now\n    \/\/ creates the intent with:\n    \/\/   - platform key            \u2192 charges go through the platform account\n    \/\/   - application_fee_amount  \u2192 service fee stays on the platform\n    \/\/   - transfer_data           \u2192 product cost forwarded to the farmer's\n    \/\/                               Stripe Connect account\n    async function fetchPaymentIntent() {\n        console.log(\"Requesting new CSA split PaymentIntent...\");\n        clientSecret = null;\n\n        \/\/ Send both the total amount and the delivery fee so the server can\n        \/\/ compute the correct application_fee_amount (service fee only;\n        \/\/ delivery fee goes to the platform, not the farmer).\n        const deliveryFeeForServer = window.selectedDeliveryFee\n            ? parseFloat(window.selectedDeliveryFee)\n            : 0;\n\n        const response = await fetch(ajaxUrl, {\n            method: \"POST\",\n            headers: { \"Content-Type\": \"application\/x-www-form-urlencoded\" },\n            body: new URLSearchParams({\n                action:                  \"csa_create_payment_intent\",\n                amount:                  dueNowAmount,\n                delivery_fee:            deliveryFeeForServer,\n                service_fee_installment: window.csaServiceFeeInstallment ?? serviceFee,\n                payment_plan:            paymentSelect?.value || 'full'\n            })\n        });\n\n        const rawText = await response.text();\n        try {\n            const data = JSON.parse(rawText);\n            if (data.success && data.data && data.data.clientSecret) {\n                clientSecret = data.data.clientSecret;\n                console.log(\"CSA split PaymentIntent ready.\");\n            } else {\n                throw new Error(\"PaymentIntent creation failed.\");\n            }\n        } catch (err) {\n            console.error(\"PaymentIntent error:\", err, rawText);\n            alert(\"Error initializing payment. Please refresh and try again.\");\n        }\n    }\n\n    \/\/ \u2500\u2500 Form submission \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    form.addEventListener('submit', async function (e) {\n        e.preventDefault();\n        const submitBtn = document.getElementById(\"submit-button\");\n        submitBtn.disabled    = true;\n        submitBtn.textContent = \"Processing...\";\n\n        if (!clientSecret) {\n            await fetchPaymentIntent();\n        }\n\n        if (!clientSecret) {\n            alert(\"Payment not initialized. Please try again.\");\n            submitBtn.disabled    = false;\n            submitBtn.textContent = \"Submit and Pay\";\n            return;\n        }\n\n        try {\n            const { error, paymentIntent } = await stripe.confirmCardPayment(clientSecret, {\n                payment_method: { card: cardElement }\n            });\n\n            if (error) {\n                document.getElementById(\"card-errors\").textContent = error.message;\n                submitBtn.disabled    = false;\n                submitBtn.textContent = \"Submit and Pay\";\n                return;\n            }\n\n            if (!paymentIntent || paymentIntent.status !== \"succeeded\") {\n                alert(\"Payment processing failed.\");\n                submitBtn.disabled    = false;\n                submitBtn.textContent = \"Submit and Pay\";\n                return;\n            }\n\n            \/\/ \u2500\u2500 Save card for subscription recurring payments \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n            \/\/ For installment plans, run a SetupIntent so the card is saved and\n            \/\/ WooCommerce Subscriptions can charge it for future instalments.\n            let savedPaymentMethodId = paymentIntent.payment_method || null;\n\n            const selectedPlan = paymentSelect?.value || 'full';\n            if (selectedPlan === 'monthly' || selectedPlan === 'weekly') {\n                try {\n                    submitBtn.textContent = \"Saving payment method\u2026\";\n                    const siRes  = await fetch(ajaxUrl, {\n                        method: 'POST',\n                        headers: { 'Content-Type': 'application\/x-www-form-urlencoded' },\n                        body: new URLSearchParams({ action: 'csa_create_setup_intent' })\n                    });\n                    const siData = await siRes.json();\n\n                    if (siData.success && siData.data?.clientSecret) {\n                        const { setupIntent, error: siError } = await stripe.confirmCardSetup(\n                            siData.data.clientSecret,\n                            { payment_method: { card: cardElement } }\n                        );\n                        if (siError) {\n                            console.warn('Card save warning (non-fatal):', siError.message);\n                        } else if (setupIntent?.payment_method) {\n                            savedPaymentMethodId = setupIntent.payment_method;\n                            console.log('Card saved for subscription:', savedPaymentMethodId);\n                        }\n                    }\n                } catch (siErr) {\n                    console.warn('SetupIntent error (non-fatal):', siErr);\n                }\n                submitBtn.textContent = \"Finalising order\u2026\";\n            }\n\n            const formData = new FormData(form);\n\n            const totalText  = document.getElementById(\"order-total\")?.textContent || \"Total: $0.00\";\n            const totalMatch = totalText.match(\/\\$([\\d.]+)\/);\n            const totalAmount = totalMatch ? parseFloat(totalMatch[1]) : 0;\n\n            if (window.selectedDeliveryFee > 0) {\n                formData.append(\"custom_delivery_fee\",    window.selectedDeliveryFee.toFixed(2));\n                formData.append(\"custom_delivery_option\", window.selectedDeliveryTitle);\n            }\n\n            formData.append(\"billing_first_name\", document.getElementById(\"billing_first_name\").value);\n            formData.append(\"billing_last_name\",  document.getElementById(\"billing_last_name\").value);\n            formData.append(\"billing_phone\",      document.getElementById(\"billing_phone\").value);\n            formData.append(\"billing_street\",     document.getElementById(\"billing_street\").value);\n            formData.append(\"billing_city\",       document.getElementById(\"billing_city\").value);\n            formData.append(\"billing_state\",      document.getElementById(\"billing_state\").value);\n            formData.append(\"billing_zip\",        document.getElementById(\"billing_zip\").value);\n            formData.append(\"action\",             \"csa_handle_form_submission\");\n            formData.append(\"payment_intent_id\",  paymentIntent.id);\n            formData.append(\"total_amount\",       totalAmount.toFixed(2));\n            \/\/ Send the prorated discount so the server can record it on the order\n            const proratedDiscount = parseFloat(\n                document.querySelector('#cart-totals .proration-discount-value')?.dataset.amount || '0'\n            );\n            if (proratedDiscount > 0) {\n                formData.append(\"proration_discount\", proratedDiscount.toFixed(2));\n            }\n            if (savedPaymentMethodId) {\n                formData.append(\"saved_payment_method_id\", savedPaymentMethodId);\n            }\n\n            const selectedPickupDay = document.querySelector('input[name=\"selected_pickup_day\"]:checked');\n            formData.append(\"pickup_day\", selectedPickupDay ? selectedPickupDay.value : \"Not Selected\");\n\n            if (paymentSelect && paymentSelect.value) {\n                formData.append(\"payment_plan\", paymentSelect.value);\n            } else {\n                alert(\"Please choose a payment plan.\");\n                submitBtn.disabled    = false;\n                submitBtn.textContent = \"Submit and Pay\";\n                return;\n            }\n\n            document.querySelectorAll('.csa-product').forEach(product => {\n                const id  = product.querySelector('.selected-product-id')?.value;\n                const qty = product.querySelector('.product-quantity')?.value;\n\n                if (id) {\n                    formData.append(\"products[]\",  id);\n                    formData.append(\"quantities[]\", qty);\n\n                    \/\/ Read product metadata from data-* attributes set directly by PHP.\n                    \/\/ The old nth-of-type selectors broke because renewal_frequency is\n                    \/\/ rendered as a <span>, not a <p>, causing \"undefined\" to be stored.\n                    const meta        = product.querySelector('.product-meta');\n                    const name        = product.querySelector('h3')?.textContent.split(\" - $\")[0].trim();\n                    const totalShares = meta?.dataset.totalShares || '';\n                    const renewalFreq = meta?.dataset.renewalFreq  || '';\n                    const startDate   = meta?.dataset.startDate    || '';\n\n                    formData.append(\"product_names[]\",               name);\n                    formData.append(\"product_total_shares[]\",        totalShares);\n                    formData.append(\"product_renewal_frequencies[]\", renewalFreq);\n                    formData.append(\"product_start_dates[]\",         startDate);\n                }\n            });\n\n            const submitResponse = await fetch(ajaxUrl, {\n                method: \"POST\",\n                body:   formData\n            });\n\n            const result = await submitResponse.json();\n\n            if (result.success) {\n                alert(\"Order placed successfully!\");\n                const pathSegments = window.location.pathname.split('\/');\n                const subsitePath  = pathSegments.length > 1 ? '\/' + pathSegments[1] : '';\n                const subsiteUrl   = window.location.origin + subsitePath;\n                const redirectUrl  = subsiteUrl + \"\/my-account\/csa-orders\";\n                window.location.href = result.redirect_url || redirectUrl;\n            } else {\n                alert(\"Order failed: \" + result.data);\n                submitBtn.disabled    = false;\n                submitBtn.textContent = \"Submit and Pay\";\n            }\n\n        } catch (error) {\n            console.error(\"Error during payment confirmation:\", error);\n            alert(\"An unexpected error occurred. Please try again later.\");\n            submitBtn.disabled    = false;\n            submitBtn.textContent = \"Submit and Pay\";\n        }\n    });\n\n    \/\/ Initialise totals on load\n    updateTotal();\n});\n\n    \/\/ \u2500\u2500 Auth Modal JS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    (function() {\n        const modal      = document.getElementById('csa-auth-modal');\n        const closeBtn   = document.getElementById('csa-auth-modal-close');\n        const tabs       = document.querySelectorAll('.csa-auth-tab');\n        const loginTab   = document.getElementById('csa-tab-login');\n        const regTab     = document.getElementById('csa-tab-register');\n        const authAjax   = \"https:\\\/\\\/farmtab.com\\\/growingdirtfarm\\\/wp-admin\\\/admin-ajax.php\";\n        const csaNonce   = \"348f391f35\";\n\n        function openModal(tab) {\n            if (!modal) return;\n            modal.style.display = 'block';\n            document.body.style.overflow = 'hidden';\n            switchTab(tab || 'login');\n        }\n        function closeModal() {\n            if (!modal) return;\n            modal.style.display = 'none';\n            document.body.style.overflow = '';\n        }\n        function switchTab(name) {\n            tabs.forEach(t => {\n                const active = t.dataset.tab === name;\n                t.style.fontWeight   = active ? '600' : '400';\n                t.style.borderBottom = active ? '2px solid #333' : '2px solid transparent';\n            });\n            if (loginTab) loginTab.style.display = (name === 'login')    ? 'block' : 'none';\n            if (regTab)   regTab.style.display   = (name === 'register') ? 'block' : 'none';\n        }\n\n        document.getElementById('csa-open-login-modal')?.addEventListener('click',    () => openModal('login'));\n        document.getElementById('csa-open-register-modal')?.addEventListener('click', () => openModal('register'));\n        closeBtn?.addEventListener('click', closeModal);\n        modal?.addEventListener('click', e => { if (e.target === modal) closeModal(); });\n        document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); });\n        tabs.forEach(t => t.addEventListener('click', () => switchTab(t.dataset.tab)));\n\n        document.getElementById('csa-login-pass')?.addEventListener('keydown', e => {\n            if (e.key === 'Enter') document.getElementById('csa-login-btn')?.click();\n        });\n\n        document.getElementById('csa-login-btn')?.addEventListener('click', async function() {\n            const btn  = this;\n            const msg  = document.getElementById('csa-login-msg');\n            const user = document.getElementById('csa-login-user').value.trim();\n            const pass = document.getElementById('csa-login-pass').value;\n            msg.style.display = 'none';\n            if (!user || !pass) { msg.textContent='Please enter your username and password.'; msg.style.color='red'; msg.style.display='block'; return; }\n            btn.disabled=true; btn.textContent='Logging in\u2026';\n            const fd = new FormData();\n            fd.append('action','csa_ajax_login'); fd.append('nonce',csaNonce);\n            fd.append('log',user); fd.append('pwd',pass);\n            try {\n                const res  = await fetch(authAjax,{method:'POST',body:fd});\n                const data = await res.json();\n                if (data.success) {\n                    msg.style.color='green'; msg.textContent='Logged in! Reloading\u2026'; msg.style.display='block';\n                    setTimeout(()=>location.reload(),800);\n                } else {\n                    msg.style.color='red'; msg.textContent=data.data||'Login failed. Please try again.'; msg.style.display='block';\n                    btn.disabled=false; btn.textContent='Log In';\n                }\n            } catch(e) {\n                msg.style.color='red'; msg.textContent='An error occurred. Please try again.'; msg.style.display='block';\n                btn.disabled=false; btn.textContent='Log In';\n            }\n        });\n\n        document.getElementById('csa-register-btn')?.addEventListener('click', async function() {\n            const btn   = this;\n            const msg   = document.getElementById('csa-register-msg');\n            const first = document.getElementById('csa-reg-first').value.trim();\n            const last  = document.getElementById('csa-reg-last').value.trim();\n            const email = document.getElementById('csa-reg-email').value.trim();\n            const pass  = document.getElementById('csa-reg-pass').value;\n            msg.style.display='none';\n            if (!email||!pass) { msg.textContent='Email and password are required.'; msg.style.color='red'; msg.style.display='block'; return; }\n            btn.disabled=true; btn.textContent='Creating account\u2026';\n            const fd = new FormData();\n            fd.append('action','csa_ajax_register'); fd.append('nonce',csaNonce);\n            fd.append('first_name',first); fd.append('last_name',last);\n            fd.append('email',email); fd.append('password',pass);\n            try {\n                const res  = await fetch(authAjax,{method:'POST',body:fd});\n                const data = await res.json();\n                if (data.success) {\n                    msg.style.color='green'; msg.textContent='Account created! Logging you in\u2026'; msg.style.display='block';\n                    setTimeout(()=>location.reload(),1000);\n                } else {\n                    msg.style.color='red'; msg.textContent=data.data||'Registration failed. Please try again.'; msg.style.display='block';\n                    btn.disabled=false; btn.textContent='Create Account';\n                }\n            } catch(e) {\n                msg.style.color='red'; msg.textContent='An error occurred. Please try again.'; msg.style.display='block';\n                btn.disabled=false; btn.textContent='Create Account';\n            }\n        });\n    })();\n<\/script>\n<script src=\"https:\/\/maps.googleapis.com\/maps\/api\/js?key=AIzaSyCTt6H3axL0IZ7QpLfJTCVMrEMGCkUt_WI&libraries=places,geometry\" async defer><\/script>\n\n<script>\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n    let map;\n    let markers = [];\n    let userLocation = null;\n    let geocoder;\n\n    function initMap() {\n        geocoder = new google.maps.Geocoder();\n        \/\/ Ensure the map container is fully sized before initialization to\n        \/\/ prevent the controls (fullscreen, pegman, camera) from rendering\n        \/\/ off-center. position:relative is required for Google Maps internals.\n        const mapEl = document.getElementById('map');\n        if (mapEl) {\n            mapEl.style.position = 'relative';\n            mapEl.style.width    = '100%';\n            if (!mapEl.style.height) mapEl.style.height = '400px';\n            mapEl.style.overflow = 'hidden';\n        }\n        map = new google.maps.Map(document.getElementById(\"map\"), {\n            center: { lat: 40.7128, lng: -74.006 },\n            zoom: 8,\n        });\n        \/\/ Trigger a resize after the container settles so all map controls\n        \/\/ (fullscreen button, pegman, camera) render in their correct positions.\n        setTimeout(() => {\n            google.maps.event.trigger(map, 'resize');\n            map.setCenter({ lat: 40.7128, lng: -74.006 });\n        }, 150);\n\n        const addressInput  = document.getElementById(\"user-address\");\n        const autocomplete  = new google.maps.places.Autocomplete(addressInput);\n        autocomplete.addListener(\"place_changed\", () => {\n            const place = autocomplete.getPlace();\n            if (!place.geometry) return;\n            userLocation = place.geometry.location;\n            map.setCenter(userLocation);\n            addUserMarker(userLocation);\n            updateDistances();\n        });\n\n        plotLocationMarkers();\n    }\n\n    function addUserMarker(position) {\n        new google.maps.Marker({\n            map,\n            position,\n            icon: { url: \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/blue-dot.png\" }\n        });\n    }\n\n    function plotLocationMarkers() {\n        const selector = document.getElementById(\"csa-location-selector\");\n        markers = [];\n\n        for (let option of selector.options) {\n            const address = option.getAttribute(\"data-places\");\n            if (!address) continue;\n\n            geocoder.geocode({ address }, (results, status) => {\n                if (status === \"OK\") {\n                    const location = results[0].geometry.location;\n                    const title    = option.textContent;\n\n                    const marker = new google.maps.Marker({ map, position: location, title });\n                    const infoWindow = new google.maps.InfoWindow({\n                        content: `<div class=\"map-label\">${title}<\/div>`\n                    });\n                    marker.addListener(\"click\", () => infoWindow.open(map, marker));\n                    markers.push(marker);\n                }\n            });\n        }\n    }\n\n    function updateDistances() {\n        if (!userLocation || markers.length === 0) return;\n        markers.forEach(marker => {\n            const distanceInMeters = google.maps.geometry.spherical.computeDistanceBetween(\n                userLocation, marker.getPosition()\n            );\n            const miles      = (distanceInMeters \/ 1609.34).toFixed(1);\n            const title      = marker.getTitle();\n            const infoWindow = new google.maps.InfoWindow({\n                content: `<div class=\"map-label\">${title} (${miles} mi)<\/div>`\n            });\n            infoWindow.open(map, marker);\n        });\n    }\n\n    window.addEventListener(\"load\", initMap);\n});\n<\/script>\n\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"standard-page.php","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-2109","page","type-page","status-publish","hentry"],"acf":{"enter_farm_name":"","enter_email":"","enter_website_url":"","enter_phone_number":"","enter_description":"","enter_featured_image":false,"enter_profile_image":false,"farmers_markets":["Not attending any markets"],"farmers_markets_hours":[],"farmers_markets_dates":[],"address_street":"Street","city":"City","state":"Alabama","zip_code":"Zip Code","monday_is_open":"","tuesday_is_open":"","wednesday_is_open":"","thursday_is_open":"","friday_is_open":"","saturday_is_open":"","sunday_is_open":"","monday_is_closed":"","tuesday_is_closed":"","wednesday_is_closed":"","thursday_is_closed":"","friday_is_closed":"","saturday_is_closed":"","sunday_is_closed":""},"ams_acf":[{"key":"enter_farm_name","value":""},{"key":"enter_email","value":""},{"key":"enter_website_url","value":""},{"key":"enter_phone_number","value":""},{"key":"enter_description","value":""},{"key":"enter_featured_image","value":false},{"key":"enter_profile_image","value":false},{"key":"farmers_markets","value":["Not attending any markets"]},{"key":"farmers_markets_hours","value":[]},{"key":"farmers_markets_dates","value":[]},{"key":"address_street","value":"Street"},{"key":"city","value":"City"},{"key":"state","value":"Alabama"},{"key":"zip_code","value":"Zip Code"},{"key":"monday_is_open","value":""},{"key":"tuesday_is_open","value":""},{"key":"wednesday_is_open","value":""},{"key":"thursday_is_open","value":""},{"key":"friday_is_open","value":""},{"key":"saturday_is_open","value":""},{"key":"sunday_is_open","value":""},{"key":"monday_is_closed","value":""},{"key":"tuesday_is_closed","value":""},{"key":"wednesday_is_closed","value":""},{"key":"thursday_is_closed","value":""},{"key":"friday_is_closed","value":""},{"key":"saturday_is_closed","value":""},{"key":"sunday_is_closed","value":""}],"_links":{"self":[{"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/pages\/2109","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/comments?post=2109"}],"version-history":[{"count":3,"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/pages\/2109\/revisions"}],"predecessor-version":[{"id":2305,"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/pages\/2109\/revisions\/2305"}],"wp:attachment":[{"href":"https:\/\/farmtab.com\/growingdirtfarm\/wp-json\/wp\/v2\/media?parent=2109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}