{"id":99485,"date":"2025-11-14T10:02:58","date_gmt":"2025-11-14T09:02:58","guid":{"rendered":"https:\/\/www.light-style.eu\/%d0%bc%d0%be%d0%b9-%d1%81%d1%87%d0%b5%d1%82\/%d0%b2%d0%b0%d1%88%d0%b0-%d0%b3%d0%b0%d0%bb%d0%b5%d1%80%d0%b5%d1%8f-%d0%b4%d0%bb%d1%8f-%d0%b2%d1%8b%d0%b1%d0%be%d1%80%d0%b0\/"},"modified":"2026-08-28T17:51:28","modified_gmt":"2026-08-28T15:51:28","slug":"%d0%b2%d0%b0%d1%88%d0%b0-%d0%b3%d0%b0%d0%bb%d0%b5%d1%80%d0%b5%d1%8f-%d0%b4%d0%bb%d1%8f-%d0%b2%d1%8b%d0%b1%d0%be%d1%80%d0%b0","status":"publish","type":"page","link":"https:\/\/www.light-style.eu\/ru\/%d0%bc%d0%be%d0%b9-%d1%81%d1%87%d0%b5%d1%82\/%d0%b2%d0%b0%d1%88%d0%b0-%d0%b3%d0%b0%d0%bb%d0%b5%d1%80%d0%b5%d1%8f-%d0%b4%d0%bb%d1%8f-%d0%b2%d1%8b%d0%b1%d0%be%d1%80%d0%b0\/","title":{"rendered":"\u0412\u0430\u0448\u0430 \u0433\u0430\u043b\u0435\u0440\u0435\u044f!"},"content":{"rendered":"\n<h3 class=\"wp-block-heading has-text-align-center has-luminous-vivid-amber-color has-text-color has-link-color wp-elements-1\"><strong>\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 \u0412\u0430\u0448\u0443 \u043b\u0438\u0447\u043d\u0443\u044e \u0444\u043e\u0442\u043e\u0433\u0430\u043b\u0435\u0440\u0435\u044e! &#x2728;<\/strong><\/h3>\n\n<p class=\"has-text-align-center wp-block-paragraph\">\u0420\u0430\u0434\u044b, \u0447\u0442\u043e \u0412\u044b \u0437\u0434\u0435\u0441\u044c! \u041c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0434\u043b\u044f \u0412\u0430\u0441 \u0441\u0430\u043c\u044b\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u0412\u0430\u0448\u0435\u0439 \u0444\u043e\u0442\u043e\u0441\u0435\u0441\u0441\u0438\u0438. <\/p>\n\n<p class=\"has-text-align-center wp-block-paragraph\">\u041d\u0435 \u0442\u043e\u0440\u043e\u043f\u0438\u0442\u0435\u0441\u044c, \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u044c\u0442\u0435\u0441\u044c \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0412\u0430\u0448\u0438 \u0441\u0430\u043c\u044b\u0435 \u043b\u044e\u0431\u0438\u043c\u044b\u0435 \u0441\u043d\u0438\u043c\u043a\u0438.<\/p>\n\n<p class=\"has-text-align-center has-luminous-vivid-amber-color has-text-color has-link-color wp-elements-2 wp-block-paragraph\"><strong>\u00ab\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0430, \u0438\u0445 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0432 \u043c\u0438\u043d\u0438\u0430\u0442\u044e\u0440\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0414\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0439 \u0433\u043b\u0443\u0431\u0438\u043d\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u044f\u0440\u043a\u043e\u0441\u0442\u0438 \u0446\u0432\u0435\u0442\u043e\u0432 \u043c\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0441 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0430 \u0438\u043b\u0438 \u041f\u041a.\u00bb<\/strong><\/p>\n\n<p class=\"has-luminous-vivid-amber-color has-text-color has-link-color wp-elements-3 wp-block-paragraph\"><strong>\u041f\u043e\u043b\u0435\u0437\u043d\u043e \u0437\u043d\u0430\u0442\u044c:<\/strong><\/p>\n\n<ul class=\"wp-block-list\">\n<li><strong>\u0412\u044b\u0431\u0438\u0440\u0430\u0439\u0442\u0435 \u0432\u043c\u0435\u0441\u0442\u0435:<\/strong> \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u043d\u0430 \u0441\u0432\u043e\u044e \u0433\u0430\u043b\u0435\u0440\u0435\u044e \u0441 \u0441\u0435\u043c\u044c\u0435\u0439 \u0438\u043b\u0438 \u0434\u0440\u0443\u0437\u044c\u044f\u043c\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u0430\u0440\u043e\u043b\u044c, \u0447\u0442\u043e\u0431\u044b \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043c\u043e\u0433 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u0438\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0438\u043b\u0438 \u0437\u0430\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0438. <\/li>\n\n\n\n<li><strong>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435:<\/strong> \u0412\u0430\u0448 \u0432\u044b\u0431\u043e\u0440 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u2014 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0433\u0430\u043b\u0435\u0440\u0435\u044e \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u043f\u043e\u0437\u0436\u0435.<\/li>\n\n\n\n<li><strong>\u0412\u0441\u0435 \u043f\u043e\u0434 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c:<\/strong> \u0412 \u043e\u0431\u0437\u043e\u0440\u0435 \u0412\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u0438\u0434\u0438\u0442\u0435, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0412\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u0438 \u043a\u0430\u043a\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438 \u0412\u0430\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b.<\/li>\n<\/ul>\n\n<p class=\"has-text-align-center wp-block-paragraph\">\u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0412\u044b \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u0435 \u0441\u0432\u043e\u0438 \u0444\u0430\u0432\u043e\u0440\u0438\u0442\u044b, \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u0432\u043d\u0438\u0437\u0443 \u043d\u0430 <strong>\u00ab\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u00bb<\/strong> \u2014 \u043c\u044b \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u043c\u0441\u044f \u043e\u0431 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0434\u043b\u044f \u0412\u0430\u0441!<\/p>\n\n<p class=\"has-text-align-center has-luminous-vivid-amber-color has-text-color has-link-color wp-elements-4 wp-block-paragraph\"><strong>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u043b\u0443\u0433\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0435\u0442\u0443\u0448\u044c (\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0444\u043e\u0442\u043e\u0441\u044a\u0435\u043c\u043a\u0438), \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0412\u0430\u043c \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b, \u0438 \u0442\u0430\u043c \u0412\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0445 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c.<\/strong><\/p>\n\n<p class=\"has-text-align-center has-black-color has-cyan-bluish-gray-background-color has-text-color has-background has-link-color wp-elements-5 wp-block-paragraph\"><strong>\u041f\u0420\u0418\u041c\u0415\u0427\u0410\u041d\u0418\u0415: \u0412\u044b\u0431\u043e\u0440 \u0438 \u043e\u0442\u043c\u0435\u043d\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 (\u0441\u0435\u0440\u0434\u0435\u0447\u043a\u043e) \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 1\u20132 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u0414\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. \u0421\u0435\u0440\u0434\u0435\u0447\u043a\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043a\u0440\u0430\u0441\u043d\u044b\u043c, \u043a\u043e\u0433\u0434\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442 \u0412\u0430\u0448 \u0432\u044b\u0431\u043e\u0440. \u0422\u0430\u043a \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f.   <\/strong><\/p>\n\n<p class=\"wp-block-paragraph\">\u200bViel Freude beim St\u00f6bern und Ausw\u00e4hlen! &#x1f4f8;<\/p>\n            <div class=\"ls-login-wrapper\">\n                                                <form method=\"post\" class=\"ls-login-form\" id=\"ls-login-form\">\n                    <h3 style=\"margin-top:0; text-align:center; color:#fff;\">Kunden-Login<\/h3>\n                                        <input type=\"hidden\" name=\"ls_login\" value=\"1\">\n                    <p><label>Benutzername<\/label><input type=\"text\" name=\"ls_user\" required class=\"ls-input-field\"><\/p>\n                    <p><label>Passwort<\/label><input type=\"password\" name=\"ls_pass\" required class=\"ls-input-field\"><\/p>\n                                            <input type=\"hidden\" name=\"ls_recaptcha_token\" id=\"ls-recaptcha-token\" value=\"\">\n                                        <p><button type=\"submit\" class=\"ls-btn\" style=\"width:100%;\">Galerie \u00f6ffnen<\/button><\/p>\n                                            <p style=\"font-size:11px; color:#888; text-align:center; margin-bottom:0;\">Diese Seite wird durch reCAPTCHA gesch\u00fctzt. Es gelten die <a href=\"https:\/\/policies.google.com\/privacy\" target=\"_blank\" rel=\"noopener\" style=\"color:#c5a059;\">Datenschutzerkl\u00e4rung<\/a> und die <a href=\"https:\/\/policies.google.com\/terms\" target=\"_blank\" rel=\"noopener\" style=\"color:#c5a059;\">Nutzungsbedingungen<\/a> von Google.<\/p>\n                                    <\/form>\n                <p style=\"text-align:center; margin-top:10px;\">\n                    <a href=\"#\" id=\"ls-forgot-password-toggle\" style=\"color:#c5a059; font-size:13px; text-decoration:underline;\">Passwort vergessen?<\/a>\n                <\/p>\n                <form method=\"post\" id=\"ls-forgot-password-form\" style=\"display:none; margin-top:10px; border-top:1px solid #333; padding-top:15px;\">\n                    <p style=\"font-size:12px; color:#aaa;\">Bitte gib deinen Benutzernamen ein - wir informieren dann das Studio, das sich zeitnah bei dir meldet.<\/p>\n                    <p><label>Benutzername<\/label><input type=\"text\" name=\"ls_forgot_username\" required class=\"ls-input-field\"><\/p>\n                    <p><button type=\"submit\" name=\"ls_forgot_password\" class=\"ls-btn\" style=\"width:100%; background:#444; color:#fff; text-shadow:none; box-shadow:none; border-color:#333;\">Studio benachrichtigen<\/button><\/p>\n                <\/form>\n            <\/div>\n            <script>\n                (function() {\n                    var toggle = document.getElementById('ls-forgot-password-toggle');\n                    var form = document.getElementById('ls-forgot-password-form');\n                    if (toggle && form) {\n                        toggle.addEventListener('click', function(e) {\n                            e.preventDefault();\n                            form.style.display = (form.style.display === 'none' || !form.style.display) ? 'block' : 'none';\n                        });\n                    }\n                })();\n            <\/script>\n                            <script src=\"https:\/\/www.google.com\/recaptcha\/api.js?render=6Lf52XQtAAAAAM1zh8Dd6_Fe9QH_ikOg3vQBapll\"><\/script>\n                <script>\n                    (function() {\n                        var lsLoginForm = document.getElementById('ls-login-form');\n                        if (!lsLoginForm) return;\n\n                        \/\/ Absicherung: Falls Googles reCAPTCHA-Skript nicht l\u00e4dt oder blockiert\n                        \/\/ wird (z.B. durch einen Werbeblocker, eine Datenschutz-Erweiterung oder\n                        \/\/ eine Firewall), soll der Login NICHT komplett stumm h\u00e4ngen bleiben -\n                        \/\/ das Formular wird dann trotzdem ganz normal abgeschickt (ohne Token).\n                        \/\/ Der Server erkennt den fehlenden Token und protokolliert das sichtbar\n                        \/\/ f\u00fcr den Admin, statt den Kunden ohne jede R\u00fcckmeldung auszusperren.\n                        var lsRecaptchaSubmitted = false;\n                        function lsFallbackSubmit() {\n                            if (lsRecaptchaSubmitted) return;\n                            lsRecaptchaSubmitted = true;\n                            lsLoginForm.submit();\n                        }\n\n                        lsLoginForm.addEventListener('submit', function(e) {\n                            e.preventDefault();\n\n                            if (typeof grecaptcha === 'undefined' || !grecaptcha || typeof grecaptcha.ready !== 'function') {\n                                lsFallbackSubmit();\n                                return;\n                            }\n\n                            \/\/ Sicherheitsnetz: Falls grecaptcha.ready()\/execute() aus irgendeinem\n                            \/\/ Grund nie zur\u00fcckkehrt (z.B. durch Google selbst blockiert), nach\n                            \/\/ 6 Sekunden trotzdem absenden, statt endlos zu warten.\n                            var fallbackTimer = setTimeout(lsFallbackSubmit, 6000);\n\n                            try {\n                                grecaptcha.ready(function() {\n                                    grecaptcha.execute('6Lf52XQtAAAAAM1zh8Dd6_Fe9QH_ikOg3vQBapll', {action: 'login'}).then(function(token) {\n                                        clearTimeout(fallbackTimer);\n                                        var tokenField = document.getElementById('ls-recaptcha-token');\n                                        if (tokenField) tokenField.value = token;\n                                        lsFallbackSubmit();\n                                    }).catch(function() {\n                                        clearTimeout(fallbackTimer);\n                                        lsFallbackSubmit();\n                                    });\n                                });\n                            } catch (err) {\n                                clearTimeout(fallbackTimer);\n                                lsFallbackSubmit();\n                            }\n                        });\n                    })();\n                <\/script>\n                                <style>\n            .ls-gallery-container { font-family: sans-serif; color: #333; }\n            .ls-logout { color: #c5a059; text-decoration: none; font-weight: bold; }\n            .ls-logout:hover { text-decoration: underline; }\n            .ls-tab-btn { background: #f1f1f1; border: none; padding: 10px 18px; font-weight: bold; cursor: pointer; border-radius: 4px 4px 0 0; }\n            .ls-tab-btn.ls-tab-active { background: linear-gradient(180deg, #ecd08f 0%, #c5a059 45%, #a3803d 100%); color: #3a2c0f; text-shadow: 0 1px 0 rgba(255,255,255,0.3); }\n            .ls-login-wrapper { max-width: 400px; margin: 60px auto; background: #1a1a1a; padding: 30px; border-radius: 8px; border: 1px solid #333; color: #fff; }\n            .ls-input-field { width: 100%; padding: 10px; margin-top: 5px; background: #222; border: 1px solid #444; color: #fff; border-radius: 4px; box-sizing: border-box; }\n            \/* Metallischer Gold-Look: mehrstufiger Verlauf simuliert Lichtreflexion auf einer\n               polierten Oberfl\u00e4che, statt einer flachen Einheitsfarbe. *\/\n            .ls-btn {\n                background: linear-gradient(180deg, #f3d99a 0%, #dcb469 22%, #c5a059 45%, #a3803d 65%, #c5a059 85%, #e8c877 100%);\n                color: #3a2c0f;\n                border: 1px solid #8a6a2f;\n                padding: 12px;\n                font-weight: bold;\n                border-radius: 4px;\n                cursor: pointer;\n                text-shadow: 0 1px 0 rgba(255,255,255,0.35);\n                box-shadow: 0 2px 6px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.4);\n                transition: filter 0.15s ease, transform 0.15s ease;\n            }\n            .ls-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }\n            .ls-btn:active { filter: brightness(0.95); transform: translateY(0); }\n            \n            .ls-thumb-card.ls-active-thumb {\n                border: 3px solid #c5a059 !important;\n                box-shadow: 0 0 20px 5px rgba(197, 160, 89, 1.0), inset 0 0 10px rgba(197, 160, 89, 0.7) !important;\n                transform: scale(1.08);\n                z-index: 20;\n                background-color: #fffdf0 !important;\n            }\n            .ls-thumb-card.ls-active-thumb::after {\n                content: \"\u2713 Aktiv\";\n                position: absolute;\n                top: -9px;\n                left: 50%;\n                transform: translateX(-50%);\n                background: #c5a059;\n                color: #fff;\n                font-size: 9px;\n                font-weight: bold;\n                padding: 1px 6px;\n                border-radius: 3px;\n                z-index: 25;\n                box-shadow: 0 2px 5px rgba(0,0,0,0.4);\n                white-space: nowrap;\n            }\n\n            @keyframes ls-spin {\n                to { transform: rotate(360deg); }\n            }\n\n            \/* Miniaturbild-Leiste: Standard 2 Spalten bei schmaler Breite (Tablet\/kleinere\n               Fenster), auf breiten Bildschirmen mehr Platz und 3 Spalten - dort ist neben der\n               Gro\u00dfansicht ohnehin genug Raum ungenutzt. Breite\/Spaltenzahl liegen bewusst hier\n               (statt nur inline im PHP), damit die Media Query greifen kann. *\/\n            .ls-thumbs-sidebar {\n                width: 240px;\n                display: grid;\n                grid-template-columns: repeat(2, 1fr);\n                gap: 8px;\n            }\n            @media (min-width: 1400px) {\n                .ls-thumbs-sidebar {\n                    width: 340px;\n                    grid-template-columns: repeat(3, 1fr);\n                }\n            }\n\n            .ls-gallery-container img {\n                -webkit-user-drag: none;\n                user-select: none;\n                -webkit-user-select: none;\n                -moz-user-select: none;\n                -ms-user-select: none;\n            }\n            .ls-img-wrapper { position: relative; display: inline-block; }\n            .ls-img-shield { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 5; background: transparent; }\n\n            \/* Mobile Responsiveness: Sidebar + Gro\u00dfbild untereinander statt nebeneinander,\n               Miniaturen-Raster passt sich der Breite an, Kopfzeile\/Tabs brechen sauber um. *\/\n            @media (max-width: 782px) {\n                .ls-split-layout { flex-direction: column !important; gap: 15px !important; }\n                .ls-thumbs-sidebar { width: 100% !important; max-height: 55vh !important; grid-template-columns: repeat(4, 1fr) !important; }\n                .ls-main-viewer { width: 100%; box-sizing: border-box; }\n                .ls-header { flex-wrap: wrap; gap: 10px; }\n                .ls-tab-navigation { flex-wrap: wrap; }\n                .ls-tab-btn { flex-grow: 1; text-align: center; }\n            }\n            @media (max-width: 480px) {\n                .ls-thumbs-sidebar { grid-template-columns: repeat(3, 1fr) !important; max-height: 45vh !important; }\n                .ls-login-wrapper { margin: 20px auto !important; padding: 20px !important; max-width: 92% !important; }\n            }\n        <\/style>\n        <script>\n        const ajaxUrl = 'https:\/\/www.light-style.eu\/studiosite\/wp-admin\/admin-ajax.php';\n        const lsNonce = '';\n                \/\/ Vollst\u00e4ndige, sortierte Dateiliste (unabh\u00e4ngig von der Seitenaufteilung) - wird f\u00fcr\n        \/\/ Vor\/Zur\u00fcck-Navigation, Diashow und die Endnummer-Suche gebraucht, da diese \u00fcber die\n        \/\/ gesamte Galerie hinweg funktionieren sollen, nicht nur innerhalb der aktuell\n        \/\/ geladenen Seite der Miniaturbild-Leiste.\n        const lsAllFiles = [];\n        const lsIsViewOnly = false;\n        \/\/ Aktuelle Favoriten als Set (unabh\u00e4ngig davon, ob die passende Miniaturbild-Karte\n        \/\/ gerade im DOM geladen ist) - wird von der Diashow f\u00fcr den Herz-Button-Status genutzt\n        \/\/ und bei jedem Umschalten live mitgepflegt.\n        const lsFavoritedFiles = new Set([]);\n        let lsCurrentFileIndex = 0;\n        if (lsCurrentFileIndex < 0) lsCurrentFileIndex = 0;\n\n        \/\/ \"Gerade online\"-Puls f\u00fcrs Admin-Backend: solange diese Seite ge\u00f6ffnet ist, alle\n        \/\/ 60 Sekunden einen kleinen Zeitstempel-Ping senden (siehe handle_heartbeat()).\n        function lsSendHeartbeat() {\n            if (!lsNonce) return;\n            const fd = new FormData();\n            fd.append('action', 'ls_heartbeat');\n            fd.append('nonce', lsNonce);\n            fetch(ajaxUrl, { method: 'POST', body: fd }).catch(() => {});\n        }\n        if (lsNonce) {\n            lsSendHeartbeat();\n            setInterval(lsSendHeartbeat, 60000);\n        }\n\n        \/\/ --- Seitenaufteilung der Miniaturbild-Leiste (bei sehr gro\u00dfen Galerien) ---\n        let lsCurrentThumbsPage = 1;\n        let lsThumbsShowingAll = false;\n\n        function lsGeneratePendingThumbsInView() {\n            \/\/ Sucht alle aktuell sichtbaren Platzhalter (Vorschaubild fehlt noch) und l\u00e4sst sie\n            \/\/ im Hintergrund in kleinen H\u00e4ppchen erzeugen - f\u00fcllt sich nach und nach selbst auf,\n            \/\/ ohne dass der Kunde etwas daf\u00fcr tun muss oder die Seite blockiert wird.\n            const pending = Array.from(document.querySelectorAll('.ls-thumb-pending')).slice(0, 12);\n            if (pending.length === 0) return;\n\n            const files = pending.map(el => el.getAttribute('data-file'));\n            const fd = new FormData();\n            fd.append('action', 'ls_customer_generate_pending_thumbs');\n            fd.append('nonce', lsNonce);\n            files.forEach(f => fd.append('files[]', f));\n\n            fetch(ajaxUrl, { method: 'POST', body: fd })\n                .then(r => r.json())\n                .then(resp => {\n                    if (resp.success && resp.data.results) {\n                        Object.keys(resp.data.results).forEach(file => {\n                            const url = resp.data.results[file];\n                            document.querySelectorAll('.ls-thumb-pending[data-file=\"' + CSS.escape(file) + '\"]').forEach(placeholder => {\n                                const img = document.createElement('img');\n                                img.src = url;\n                                img.loading = 'lazy';\n                                img.alt = '';\n                                img.style.cssText = 'width:100%; height:70px; object-fit:contain; display:block; border-radius:2px; background:#f0f0f0;';\n                                placeholder.replaceWith(img);\n                            });\n                        });\n                    }\n                    \/\/ Weiter in kleinen H\u00e4ppchen, solange noch Platzhalter \u00fcbrig sind.\n                    if (document.querySelectorAll('.ls-thumb-pending').length > 0) {\n                        setTimeout(lsGeneratePendingThumbsInView, 400);\n                    }\n                })\n                .catch(() => {});\n        }\n        \/\/ Kurz nach dem Laden starten, statt sofort - l\u00e4sst der Seite Zeit, zuerst ganz normal\n        \/\/ aufzubauen.\n        setTimeout(lsGeneratePendingThumbsInView, 800);\n\n        function lsLoadThumbsPage(page, showAll, afterLoad) {\n            const sidebar = document.getElementById('ls-thumbs-sidebar');\n            const pageInfo = document.getElementById('ls-thumbs-page-info');\n            const prevBtn = document.getElementById('ls-thumbs-prev-btn');\n            const nextBtn = document.getElementById('ls-thumbs-next-btn');\n            const showAllBtn = document.getElementById('ls-thumbs-show-all-btn');\n            if (!sidebar) return;\n\n            if (pageInfo) pageInfo.textContent = showAll ? 'Lade alle Fotos...' : ('Lade Seite ' + page + '...');\n\n            const fd = new FormData();\n            fd.append('action', 'ls_get_gallery_photos_page');\n            fd.append('nonce', lsNonce);\n            fd.append('page', page);\n            if (showAll) fd.append('show_all', '1');\n\n            fetch(ajaxUrl, { method: 'POST', body: fd })\n                .then(r => r.json())\n                .then(resp => {\n                    if (!resp.success) {\n                        if (pageInfo) pageInfo.textContent = 'Fehler beim Laden.';\n                        if (typeof afterLoad === 'function') afterLoad(false);\n                        return;\n                    }\n                    const d = resp.data;\n                    sidebar.innerHTML = d.html;\n                    lsCurrentThumbsPage = d.current_page;\n                    lsThumbsShowingAll = d.show_all;\n\n                    if (pageInfo) {\n                        pageInfo.textContent = d.show_all\n                            ? ('Alle ' + d.total_files + ' Fotos angezeigt')\n                            : ('Seite ' + d.current_page + ' von ' + d.total_pages + ' (' + d.total_files + ' Fotos)');\n                    }\n                    if (prevBtn) prevBtn.disabled = d.show_all || d.current_page <= 1;\n                    if (nextBtn) {\n                        nextBtn.disabled = d.show_all || d.current_page >= d.total_pages;\n                        nextBtn.style.display = d.show_all ? 'none' : 'inline-block';\n                    }\n                    if (showAllBtn) {\n                        showAllBtn.textContent = d.show_all ? '\ud83d\udcd6 Zur\u00fcck zur Seitenansicht (50 pro Seite)' : ('\ud83d\udcd6 Alle ' + d.total_files + ' Fotos auf einer Seite anzeigen');\n                    }\n                    const jumpInputEl = document.getElementById('ls-thumbs-jump-input');\n                    if (jumpInputEl && !d.show_all) jumpInputEl.value = d.current_page;\n\n                    \/\/ Neu geladene Fotos landen ganz oben in der Liste - kein aktives Foto mehr\n                    \/\/ markiert, das ist auf einer neuen Seite ohnehin nicht mehr aussagekr\u00e4ftig.\n                    setTimeout(lsGeneratePendingThumbsInView, 300);\n\n                    if (typeof afterLoad === 'function') afterLoad(true);\n                })\n                .catch(() => {\n                    if (pageInfo) pageInfo.textContent = 'Netzwerkfehler beim Laden.';\n                    if (typeof afterLoad === 'function') afterLoad(false);\n                });\n        }\n\n        document.addEventListener('DOMContentLoaded', function() {\n            const prevBtn = document.getElementById('ls-thumbs-prev-btn');\n            const nextBtn = document.getElementById('ls-thumbs-next-btn');\n            const showAllBtn = document.getElementById('ls-thumbs-show-all-btn');\n            const jumpBtn = document.getElementById('ls-thumbs-jump-btn');\n            const jumpInput = document.getElementById('ls-thumbs-jump-input');\n\n            if (prevBtn) {\n                prevBtn.addEventListener('click', function() {\n                    if (lsCurrentThumbsPage > 1) lsLoadThumbsPage(lsCurrentThumbsPage - 1, false);\n                });\n            }\n            if (nextBtn) {\n                nextBtn.addEventListener('click', function() {\n                    lsLoadThumbsPage(lsCurrentThumbsPage + 1, false);\n                });\n            }\n            if (showAllBtn) {\n                showAllBtn.addEventListener('click', function() {\n                    if (lsThumbsShowingAll) {\n                        lsLoadThumbsPage(1, false);\n                    } else {\n                        lsLoadThumbsPage(1, true);\n                    }\n                });\n            }\n            if (jumpBtn && jumpInput) {\n                function lsDoJump() {\n                    const maxPage = parseInt(jumpInput.getAttribute('max'), 10) || 1;\n                    let target = parseInt(jumpInput.value, 10) || 1;\n                    target = Math.max(1, Math.min(target, maxPage));\n                    jumpInput.value = target;\n                    lsLoadThumbsPage(target, false);\n                }\n                jumpBtn.addEventListener('click', lsDoJump);\n                jumpInput.addEventListener('keydown', function(e) {\n                    if (e.key === 'Enter') { e.preventDefault(); lsDoJump(); }\n                });\n            }\n        });\n\n        function lsSwitchTab(tabName) {\n            document.querySelectorAll('.ls-tab-btn').forEach(btn => {\n                btn.classList.remove('ls-tab-active');\n                if (btn.getAttribute('data-tab') === tabName) {\n                    btn.classList.add('ls-tab-active');\n                }\n            });\n            const sectionAll = document.getElementById('ls-tab-content-all');\n            const sectionReorder = document.getElementById('ls-tab-content-reorder');\n            if (tabName === 'all') {\n                if (sectionAll) sectionAll.style.display = 'block';\n                if (sectionReorder) sectionReorder.style.display = 'none';\n            } else if (tabName === 'reorder') {\n                if (sectionAll) sectionAll.style.display = 'none';\n                if (sectionReorder) sectionReorder.style.display = 'block';\n            }\n        }\n\n        function lsHighlightThumb(filename) {\n            document.querySelectorAll('.ls-thumb-card').forEach(card => {\n                if (card.getAttribute('data-file') === filename) {\n                    card.classList.add('ls-active-thumb');\n                } else {\n                    card.classList.remove('ls-active-thumb');\n                }\n            });\n            const fnEl = document.getElementById('ls-active-image-filename');\n            if (fnEl) fnEl.textContent = filename;\n\n            \/\/ Zuschauer-Zugang: den Wandbild-Wunsch-Mail-Link auf das gerade angesehene Foto\n            \/\/ aktualisieren, damit der Dateiname immer zum tats\u00e4chlich angezeigten Bild passt.\n            const mailtoLink = document.getElementById('ls-viewer-mailto-link');\n            if (mailtoLink) {\n                const subjectPrefix = mailtoLink.getAttribute('data-subject-prefix') || 'Wandbild-Wunsch';\n                const body = 'Hallo,\\n\\nich habe folgendes Foto gesehen und w\u00fcrde es gerne als Wandbild\/Poster bestellen:\\n\\nDateiname: ' + filename + '\\nGew\u00fcnschtes Format: \\n\\nViele Gr\u00fc\u00dfe';\n                mailtoLink.href = 'mailto:order@light-style.eu?subject=' + encodeURIComponent(subjectPrefix) + '&body=' + encodeURIComponent(body);\n            }\n        }\n\n        function lsBuildPreviewUrl(filename) {\n            const galleryEl = document.querySelector('.ls-gallery-container');\n            const galleryId = galleryEl ? galleryEl.getAttribute('data-gallery') : '';\n            return ajaxUrl + '?action=ls_serve_photo&gallery=' + encodeURIComponent(galleryId) + '&size=preview&file=' + encodeURIComponent(filename);\n        }\n\n        \/\/ Zentrale Funktion zum Anzeigen eines Fotos im Gro\u00dfbild - von Klick auf eine\n        \/\/ Miniatur, den Vor\/Zur\u00fcck-Buttons, der Endnummer-Suche und der Diashow gemeinsam\n        \/\/ genutzt, damit sich das Verhalten \u00fcberall exakt gleich anf\u00fchlt.\n        function lsLoadPhotoByFilename(filename) {\n            const idx = lsAllFiles.indexOf(filename);\n            if (idx !== -1) lsCurrentFileIndex = idx;\n\n            const s = document.getElementById('ls-active-image-status');\n            if (s) { s.textContent = '\u23f3 Wird geladen...'; s.style.color = '#fff'; s.style.display = 'block'; }\n            const d = document.getElementById('ls-image-error-diagnosis');\n            if (d) d.style.display = 'none';\n            const activeImg = document.getElementById('ls-active-image');\n            if (activeImg) activeImg.src = lsBuildPreviewUrl(filename);\n            lsHighlightThumb(filename);\n        }\n\n        \/\/ Umschalter \"Nur Favoriten durchbl\u00e4ttern\" - wirkt sowohl auf die normale Vor\/Zur\u00fcck-\n        \/\/ Navigation als auch auf die Diashow. lsCurrentFileIndex bleibt dabei immer ein Index\n        \/\/ in lsAllFiles (der vollst\u00e4ndigen Liste); zur Navigation wird bei aktivem Filter\n        \/\/ stattdessen die gefilterte Liste herangezogen und danach zur\u00fcck auf den passenden\n        \/\/ Index in lsAllFiles gemappt.\n        let lsOnlyFavoritesMode = false;\n        function lsGetActiveFileList() {\n            return lsOnlyFavoritesMode ? lsAllFiles.filter(function(f) { return lsFavoritedFiles.has(f); }) : lsAllFiles;\n        }\n        function lsGetNextIndex(fromIndex, direction) {\n            const list = lsGetActiveFileList();\n            if (list.length === 0) return fromIndex;\n            const currentFilename = lsAllFiles[fromIndex];\n            let pos = list.indexOf(currentFilename);\n            pos = (pos === -1) ? 0 : (pos + direction);\n            if (pos < 0) pos = list.length - 1;\n            if (pos >= list.length) pos = 0;\n            return lsAllFiles.indexOf(list[pos]);\n        }\n\n        \/\/ Bl\u00e4ttert im Gro\u00dfbild zum vorherigen\/n\u00e4chsten Foto der GESAMTEN Galerie (nicht nur\n        \/\/ der aktuell in der Seitenleiste geladenen Seite).\n        function lsNavigatePhoto(direction) {\n            if (lsAllFiles.length === 0) return;\n            const idx = lsGetNextIndex(lsCurrentFileIndex, direction);\n            lsCurrentFileIndex = idx;\n            lsLoadPhotoByFilename(lsAllFiles[idx]);\n        }\n\n        \/\/ Endnummer-Suche: findet ein Foto, dessen Dateiname (vor der Dateiendung) mit der\n        \/\/ eingegebenen Zahl endet - z.B. \"139\" findet \"...-139.jpg\" oder \"IMG_0139.jpg\".\n        \/\/ Reicht die Endnummer, ganz ohne den kompletten Dateinamen tippen zu m\u00fcssen.\n        function lsSearchByNumber() {\n            const input = document.getElementById('ls-photo-search-input');\n            const statusEl = document.getElementById('ls-photo-search-status');\n            if (!input) return;\n            const query = input.value.trim().replace(\/^-+\/, '');\n            if (!query) return;\n\n            const match = lsAllFiles.find(function(fn) {\n                const nameOnly = fn.replace(\/\\.[^.]+$\/, '');\n                return nameOnly === query || nameOnly.endsWith('-' + query) || nameOnly.endsWith('_' + query) || nameOnly.endsWith(query);\n            });\n\n            if (!match) {\n                if (statusEl) { statusEl.textContent = 'Kein Foto mit dieser Nummer gefunden.'; statusEl.style.color = '#c0392b'; }\n                return;\n            }\n\n            if (statusEl) { statusEl.textContent = '\u2713 Gefunden: ' + match; statusEl.style.color = '#2e7d32'; }\n            lsLoadPhotoByFilename(match);\n\n            \/\/ Falls das gefundene Foto auf einer anderen Seite der Miniaturbild-Leiste liegt,\n            \/\/ automatisch dorthin wechseln (alle anzeigen), damit es auch dort sichtbar\/markiert ist.\n            const idx = lsAllFiles.indexOf(match);\n            const perPage = 50;\n            const targetPage = Math.floor(idx \/ perPage) + 1;\n            if (typeof lsLoadThumbsPage === 'function' && targetPage !== lsCurrentThumbsPage) {\n                lsLoadThumbsPage(targetPage, false);\n            }\n\n            document.getElementById('ls-active-image').scrollIntoView({ behavior: 'smooth', block: 'center' });\n        }\n\n        \/\/ Wird ausgel\u00f6st, wenn das Gro\u00dfbild nicht laden konnte. Stellt dieselbe Anfrage per\n        \/\/ fetch() nach und zeigt den tats\u00e4chlichen Server-Status samt Antworttext direkt auf\n        \/\/ der Seite an - so l\u00e4sst sich der genaue Fehler auch ganz ohne Entwicklertools (F12)\n        \/\/ ablesen, z.B. ob eine Firewall\/Sicherheitsregel mit eigener Fehlerseite antwortet.\n        function lsImageLoadError(imgSrc) {\n            const statusEl = document.getElementById('ls-active-image-status');\n            if (statusEl) {\n                statusEl.textContent = '\u26a0\ufe0f Bild konnte nicht geladen werden.';\n                statusEl.style.color = '#c0392b';\n            }\n\n            const diagEl = document.getElementById('ls-image-error-diagnosis');\n            if (!diagEl || !imgSrc) return;\n\n            diagEl.style.display = 'block';\n            diagEl.textContent = 'Pr\u00fcfe genaue Fehlerursache...';\n\n            fetch(imgSrc, { cache: 'no-store' })\n                .then(response => {\n                    return response.text().then(bodyText => {\n                        let info = 'HTTP-Status: ' + response.status + ' ' + response.statusText + '\\n';\n                        info += 'Content-Type der Antwort: ' + (response.headers.get('content-type') || '(unbekannt)') + '\\n';\n                        info += '\\n--- Antwort vom Server (erste 2500 Zeichen) ---\\n';\n                        info += bodyText.substring(0, 2500);\n                        diagEl.textContent = info;\n                    });\n                })\n                .catch(err => {\n                    diagEl.textContent = 'Die Anfrage konnte gar nicht erst gesendet werden (Netzwerkfehler): ' + err.message;\n                });\n        }\n\n        function lsOpenLightbox(imgSrc) {\n            const lbModal = document.getElementById('ls-lightbox-modal');\n            const lbImg = document.getElementById('ls-lightbox-large-img');\n            const lbStatus = document.getElementById('ls-lightbox-status');\n            if (lbModal && lbImg && imgSrc) {\n                if (lbStatus) {\n                    lbStatus.textContent = '\u23f3 Wird geladen...';\n                    lbStatus.style.color = '#c5a059';\n                    lbStatus.style.display = 'block';\n                }\n                lbImg.src = imgSrc;\n                lbModal.style.display = 'flex';\n            }\n        }\n\n        function getSelectedServicesData() {\n            const data = {};\n            document.querySelectorAll('.ls-service-checkbox:checked').forEach(cb => {\n                const title = cb.getAttribute('data-title');\n                const scope = cb.getAttribute('data-scope');\n                if (scope === 'per_image') {\n                    const favCards = document.querySelectorAll('.ls-thumb-card');\n                    const files = [];\n                    favCards.forEach(card => {\n                        if (card.getAttribute('data-ordered') !== '1' && card.getAttribute('data-favorite') === 'true') {\n                            files.push(card.getAttribute('data-file'));\n                        }\n                    });\n                    data[title] = { files: files };\n                } else {\n                    data[title] = { global: true };\n                }\n            });\n            return data;\n        }\n\n        document.addEventListener('DOMContentLoaded', function() {\n            document.addEventListener('contextmenu', function(e) {\n                if (e.target.tagName === 'IMG' || e.target.classList.contains('ls-img-shield')) {\n                    e.preventDefault();\n                }\n            });\n            document.addEventListener('dragstart', function(e) {\n                if (e.target.tagName === 'IMG') { e.preventDefault(); }\n            });\n\n            \/\/ Zentrale Funktion zum Setzen\/Entfernen eines Favoriten - funktioniert auch f\u00fcr\n            \/\/ Fotos, deren Miniaturbild-Karte gerade NICHT geladen ist (z.B. weil eine andere\n            \/\/ Seite der Seitenaufteilung aktiv ist, oder aus der Diashow heraus). Aktualisiert\n            \/\/ eine ggf. vorhandene Karte zus\u00e4tzlich optisch mit, falls sie im DOM ist.\n            function lsToggleFavoriteByFilename(file, makeFavorite, onDone) {\n                const fd = new FormData();\n                fd.append('action', 'ls_toggle_favorite');\n                fd.append('nonce', lsNonce);\n                fd.append('file', file);\n                fd.append('fav_action', makeFavorite ? 'add' : 'remove');\n\n                fetch(ajaxUrl, { method: 'POST', body: fd })\n                .then(r => r.json())\n                .then(resp => {\n                    if (resp.success) {\n                        if (makeFavorite) { lsFavoritedFiles.add(file); } else { lsFavoritedFiles.delete(file); }\n                        const card = document.querySelector('.ls-thumb-card[data-file=\"' + CSS.escape(file) + '\"]');\n                        if (card) {\n                            const btn = card.querySelector('.ls-fav-toggle-btn');\n                            if (makeFavorite) {\n                                if (btn) { btn.style.background = '#c5a059'; btn.textContent = '\u2764\ufe0f'; }\n                                card.style.borderColor = '#c5a059';\n                                card.setAttribute('data-favorite', 'true');\n                            } else {\n                                if (btn) { btn.style.background = 'rgba(0,0,0,0.6)'; btn.textContent = '\ud83e\udd0d'; }\n                                card.style.borderColor = '#ddd';\n                                card.setAttribute('data-favorite', 'false');\n                            }\n                        }\n                        const countEl = document.getElementById('ls-fav-selection-count');\n                        if (countEl) countEl.textContent = resp.data.count;\n                        const grandTotalEl = document.getElementById('ls-live-grand-total');\n                        if (grandTotalEl && resp.data.grand_total !== undefined) {\n                            grandTotalEl.textContent = new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(resp.data.grand_total) + ' \u20ac';\n                        }\n                    }\n                    if (typeof onDone === 'function') onDone(resp.success);\n                })\n                .catch(() => { if (typeof onDone === 'function') onDone(false); });\n            }\n\n            \/\/ Event-Delegation statt direkter Bindung an jeden einzelnen Button - so\n            \/\/ funktioniert der Favoriten-Button auch f\u00fcr Foto-Karten, die erst sp\u00e4ter per\n            \/\/ Seitenaufteilung (Paginierung) nachgeladen werden, ohne die Bindung erneut\n            \/\/ ausf\u00fchren zu m\u00fcssen.\n            document.addEventListener('click', function(e) {\n                const btn = e.target.closest('.ls-fav-toggle-btn');\n                if (!btn) return;\n                e.stopPropagation();\n                const file = btn.getAttribute('data-file');\n                const card = btn.closest('.ls-thumb-card');\n                const isCurrentlyFav = card.getAttribute('data-favorite') === 'true';\n                lsToggleFavoriteByFilename(file, !isCurrentlyFav);\n            });\n\n            const wandbildToggleBtn = document.getElementById('ls-wandbild-toggle-btn');\n            const wandbildPanel = document.getElementById('ls-wandbild-panel');\n            if (wandbildToggleBtn && wandbildPanel) {\n                wandbildToggleBtn.addEventListener('click', function() {\n                    const isOpening = (wandbildPanel.style.display === 'none' || !wandbildPanel.style.display);\n                    wandbildPanel.style.display = isOpening ? 'block' : 'none';\n                    if (isOpening) {\n                        \/\/ Automatisch zum gerade ge\u00f6ffneten Bereich scrollen - sonst geht er\n                        \/\/ leicht unter, da er weiter unten auf der Seite aufklappt.\n                        setTimeout(function() {\n                            wandbildPanel.scrollIntoView({ behavior: 'smooth', block: 'center' });\n                            \/\/ Kurzes Aufblitzen des Rahmens lenkt den Blick zus\u00e4tzlich dorthin.\n                            wandbildPanel.style.transition = 'box-shadow 0.4s ease';\n                            wandbildPanel.style.boxShadow = '0 0 0 3px rgba(197,160,89,0.6)';\n                            setTimeout(function() { wandbildPanel.style.boxShadow = ''; }, 900);\n                        }, 50);\n                    }\n                });\n            }\n\n            document.querySelectorAll('.ls-wandbild-select').forEach(function(sel) {\n                sel.addEventListener('change', function() {\n                    const file = sel.getAttribute('data-file');\n                    const row = sel.closest('.ls-wandbild-row');\n                    const statusEl = row ? row.querySelector('.ls-wandbild-row-status') : null;\n                    const hasSelection = (sel.value !== '');\n                    if (statusEl) { statusEl.textContent = '\u23f3 ...'; statusEl.style.color = '#888'; }\n\n                    const fd = new FormData();\n                    fd.append('action', 'ls_toggle_wandbild_selection');\n                    fd.append('nonce', lsNonce);\n                    fd.append('file', file);\n                    fd.append('option', sel.value);\n\n                    fetch(ajaxUrl, { method: 'POST', body: fd })\n                    .then(r => r.json())\n                    .then(resp => {\n                        if (resp.success) {\n                            if (statusEl) { statusEl.textContent = hasSelection ? '\u2713 Ausgew\u00e4hlt' : ''; statusEl.style.color = '#e8c877'; }\n                            if (row) {\n                                row.style.borderColor = hasSelection ? '#c5a059' : '#2a2a2a';\n                                row.style.background = hasSelection ? 'rgba(197,160,89,0.08)' : 'rgba(255,255,255,0.02)';\n                            }\n                            const grandTotalEl = document.getElementById('ls-live-grand-total');\n                            if (grandTotalEl && resp.data.grand_total !== undefined) {\n                                grandTotalEl.textContent = new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(resp.data.grand_total) + ' \u20ac';\n                            }\n                        } else {\n                            if (statusEl) { statusEl.textContent = '\u26a0 Fehler'; statusEl.style.color = '#a00'; }\n                        }\n                    })\n                    .catch(() => {\n                        if (statusEl) { statusEl.textContent = '\u26a0 Fehler'; statusEl.style.color = '#a00'; }\n                    });\n                });\n            });\n\n            function lsFormatEta(seconds) {\n                if (!isFinite(seconds) || seconds <= 0) return '';\n                if (seconds < 60) return Math.ceil(seconds) + ' Sek.';\n                return Math.ceil(seconds \/ 60) + ' Min.';\n            }\n\n            function lsSetupChunkedZipDownload(btn, statusDiv, ajaxAction) {\n                if (!btn || !statusDiv) return;\n                btn.addEventListener('click', function() {\n                    btn.disabled = true;\n                    const originalBtnText = btn.textContent;\n                    btn.textContent = '\u23f3 Wird vorbereitet...';\n                    const startTime = Date.now();\n\n                    function runZipChunk(offset) {\n                        const fd = new FormData();\n                        fd.append('action', ajaxAction);\n                        fd.append('nonce', lsNonce);\n                        fd.append('offset', offset);\n\n                        fetch(ajaxUrl, { method: 'POST', body: fd })\n                        .then(r => r.json())\n                        .then(resp => {\n                            if (!resp.success) {\n                                btn.disabled = false;\n                                btn.textContent = originalBtnText;\n                                statusDiv.innerHTML = '<span style=\"color:#a00;\">Fehler: ' + (resp.data || 'Unbekannter Fehler') + '<\/span>';\n                                return;\n                            }\n                            const d = resp.data;\n                            const pct = d.total > 0 ? Math.round((d.processed \/ d.total) * 100) : 100;\n                            const elapsedSec = (Date.now() - startTime) \/ 1000;\n                            const rate = elapsedSec > 0 ? (d.processed \/ elapsedSec) : 0;\n                            const remaining = Math.max(0, d.total - d.processed);\n                            const etaSec = rate > 0 ? (remaining \/ rate) : 0;\n                            const etaText = lsFormatEta(etaSec);\n\n                            statusDiv.innerHTML = '<span style=\"color:#ccc;\">\ud83d\udce6 ' + d.processed + ' von ' + d.total + ' Fotos gepackt (' + pct + '%)' + (etaText ? ' - noch ca. ' + etaText : '') + '...<\/span>';\n\n                            if (d.has_more) {\n                                runZipChunk(d.next_offset);\n                            } else {\n                                btn.disabled = false;\n                                btn.textContent = originalBtnText;\n                                statusDiv.innerHTML = '<span style=\"color:#2e7d32;\">\u2714 Fertig! Download startet...<\/span>';\n                                window.location.href = d.download_url;\n                            }\n                        })\n                        .catch(() => {\n                            btn.disabled = false;\n                            btn.textContent = originalBtnText;\n                            statusDiv.innerHTML = '<span style=\"color:#a00;\">Netzwerkfehler beim Packen des Archivs.<\/span>';\n                        });\n                    }\n\n                    runZipChunk(0);\n                });\n            }\n\n            \/\/ --- Endnummer-Suche ---\n            const onlyFavToggle = document.getElementById('ls-only-favorites-toggle');\n            if (onlyFavToggle) {\n                onlyFavToggle.addEventListener('change', function() {\n                    lsOnlyFavoritesMode = onlyFavToggle.checked;\n                });\n            }\n\n            \/\/ Eigener, von \"Nur Favoriten durchbl\u00e4ttern\" (Navigation\/Diashow) getrennter\n            \/\/ Schalter: blendet Nicht-Favoriten direkt im Thumbnail-Raster aus, wirkt sich NICHT\n            \/\/ auf Vor\/Zur\u00fcck-Navigation oder die Diashow aus. Nutzt das bereits vorhandene\n            \/\/ data-favorite-Attribut jeder Karte (siehe render_customer_thumb_card()).\n            function lsApplyFavoritesTileFilter(showOnlyFav) {\n                document.querySelectorAll('#ls-thumbs-sidebar .ls-thumb-card').forEach(function(card) {\n                    if (!showOnlyFav) {\n                        card.style.display = card.getAttribute('data-ordered') === '1' && !false ? 'none' : 'block';\n                        return;\n                    }\n                    card.style.display = card.getAttribute('data-favorite') === 'true' ? 'block' : 'none';\n                });\n            }\n\n            const thumbsOnlyFavToggle = document.getElementById('ls-thumbs-only-favorites-toggle');\n            const thumbsFavLoadingEl = document.getElementById('ls-thumbs-fav-loading');\n            if (thumbsOnlyFavToggle) {\n                thumbsOnlyFavToggle.addEventListener('change', function() {\n                    const showOnlyFav = thumbsOnlyFavToggle.checked;\n\n                    \/\/ Bei seitenweise aufgeteilten gro\u00dfen Galerien liegen nicht alle Favoriten\n                    \/\/ zwangsl\u00e4ufig auf der aktuell geladenen Seite - deshalb bei Aktivierung\n                    \/\/ zuerst alle Seiten nachladen (nutzt denselben Mechanismus wie der\n                    \/\/ \"Alle Fotos auf einer Seite anzeigen\"-Button), erst danach filtern. War\n                    \/\/ die Seite schon vollst\u00e4ndig geladen, entf\u00e4llt dieser Zwischenschritt.\n                    if (showOnlyFav && !lsThumbsShowingAll) {\n                        \/\/ Deutlich sichtbarer Lade-Hinweis, w\u00e4hrend im Hintergrund alle Seiten\n                        \/\/ nachgeladen werden - bei sehr gro\u00dfen Galerien (z.B. 1000+ Hochzeitsfotos)\n                        \/\/ kann das sp\u00fcrbar dauern, ohne diesen Hinweis k\u00f6nnte es wie ein H\u00e4nger wirken.\n                        if (thumbsFavLoadingEl) thumbsFavLoadingEl.style.display = 'inline-block';\n                        thumbsOnlyFavToggle.disabled = true;\n\n                        lsLoadThumbsPage(1, true, function(success) {\n                            if (thumbsFavLoadingEl) thumbsFavLoadingEl.style.display = 'none';\n                            thumbsOnlyFavToggle.disabled = false;\n                            if (success) {\n                                lsApplyFavoritesTileFilter(true);\n                            } else {\n                                thumbsOnlyFavToggle.checked = false;\n                            }\n                        });\n                        return;\n                    }\n\n                    lsApplyFavoritesTileFilter(showOnlyFav);\n                });\n            }\n\n            const searchBtn = document.getElementById('ls-photo-search-btn');\n            const searchInput = document.getElementById('ls-photo-search-input');\n            if (searchBtn) searchBtn.addEventListener('click', lsSearchByNumber);\n            if (searchInput) {\n                searchInput.addEventListener('keydown', function(e) {\n                    if (e.key === 'Enter') { e.preventDefault(); lsSearchByNumber(); }\n                });\n            }\n\n            \/\/ --- Diashow: gro\u00dfformatig, mit sanftem \u00dcberblenden (kein Springen zwischen\n            \/\/ Hoch-\/Querformat, da der Rahmen eine feste Gr\u00f6\u00dfe hat und nur das Bild darin per\n            \/\/ object-fit:contain skaliert wird) ---\n            (function() {\n                const modal = document.getElementById('ls-slideshow-modal');\n                const imgA = document.getElementById('ls-slideshow-img-a');\n                const imgB = document.getElementById('ls-slideshow-img-b');\n                const filenameEl = document.getElementById('ls-slideshow-filename');\n                const favBtn = document.getElementById('ls-slideshow-fav-btn');\n                const startBtn = document.getElementById('ls-slideshow-start-btn');\n                const prevBtn = document.getElementById('ls-slideshow-prev-btn');\n                const nextBtn = document.getElementById('ls-slideshow-next-btn');\n                const playPauseBtn = document.getElementById('ls-slideshow-playpause-btn');\n                const closeBtn = document.getElementById('ls-slideshow-close-btn');\n                if (!modal || !imgA || !imgB || !startBtn) return;\n\n                let activeImg = imgA;\n                let inactiveImg = imgB;\n                let slideIndex = 0;\n                let autoTimer = null;\n                let isPlaying = true;\n                const AUTO_ADVANCE_MS = 5000;\n\n                function updateFavButton() {\n                    if (!favBtn) return;\n                    const isFav = lsFavoritedFiles.has(lsAllFiles[slideIndex]);\n                    const iconEl = document.getElementById('ls-slideshow-fav-icon');\n                    if (iconEl) iconEl.textContent = isFav ? '\u2764\ufe0f' : '\ud83e\udd0d';\n                    favBtn.style.background = isFav ? 'rgba(197,160,89,0.25)' : 'rgba(255,255,255,0.08)';\n                    favBtn.style.borderColor = isFav ? '#c5a059' : '#555';\n                }\n\n                function showSlide(index) {\n                    if (lsAllFiles.length === 0) return;\n                    if (index < 0) index = lsAllFiles.length - 1;\n                    if (index >= lsAllFiles.length) index = 0;\n                    slideIndex = index;\n                    lsCurrentFileIndex = index;\n                    const filename = lsAllFiles[index];\n\n                    inactiveImg.onload = function() {\n                        activeImg.style.opacity = '0';\n                        inactiveImg.style.opacity = '1';\n                        const tmp = activeImg;\n                        activeImg = inactiveImg;\n                        inactiveImg = tmp;\n                    };\n                    inactiveImg.src = lsBuildPreviewUrl(filename);\n                    if (filenameEl) filenameEl.textContent = filename;\n                    updateFavButton();\n                    lsHighlightThumb(filename);\n                    const mainImg = document.getElementById('ls-active-image');\n                    if (mainImg) mainImg.src = lsBuildPreviewUrl(filename);\n                }\n\n                function startAutoAdvance() {\n                    stopAutoAdvance();\n                    autoTimer = setInterval(function() { showSlide(lsGetNextIndex(slideIndex, 1)); }, AUTO_ADVANCE_MS);\n                }\n                function stopAutoAdvance() {\n                    if (autoTimer) { clearInterval(autoTimer); autoTimer = null; }\n                }\n                function restartAutoAdvanceIfPlaying() {\n                    if (isPlaying) startAutoAdvance();\n                }\n\n                function openSlideshow() {\n                    modal.style.display = 'flex';\n                    document.body.style.overflow = 'hidden';\n                    isPlaying = true;\n                    if (playPauseBtn) playPauseBtn.textContent = '\u23f8 Pause';\n                    slideIndex = lsCurrentFileIndex;\n                    \/\/ Falls \"Nur Favoriten\" aktiv ist, aber das gerade angezeigte Foto kein\n                    \/\/ Favorit ist, gleich zum n\u00e4chsten passenden Foto springen.\n                    if (lsOnlyFavoritesMode && !lsFavoritedFiles.has(lsAllFiles[slideIndex])) {\n                        slideIndex = lsGetNextIndex(slideIndex, 1);\n                    }\n                    const filename = lsAllFiles[slideIndex];\n                    activeImg.style.opacity = '0';\n                    inactiveImg.style.opacity = '0';\n                    activeImg.onload = function() { activeImg.style.opacity = '1'; };\n                    activeImg.src = lsBuildPreviewUrl(filename);\n                    if (filenameEl) filenameEl.textContent = filename;\n                    updateFavButton();\n                    startAutoAdvance();\n                }\n\n                function closeSlideshow() {\n                    modal.style.display = 'none';\n                    document.body.style.overflow = '';\n                    stopAutoAdvance();\n                }\n\n                startBtn.addEventListener('click', openSlideshow);\n                if (closeBtn) closeBtn.addEventListener('click', closeSlideshow);\n                if (prevBtn) prevBtn.addEventListener('click', function() { stopAutoAdvance(); showSlide(lsGetNextIndex(slideIndex, -1)); restartAutoAdvanceIfPlaying(); });\n                if (nextBtn) nextBtn.addEventListener('click', function() { stopAutoAdvance(); showSlide(lsGetNextIndex(slideIndex, 1)); restartAutoAdvanceIfPlaying(); });\n                if (playPauseBtn) {\n                    playPauseBtn.addEventListener('click', function() {\n                        isPlaying = !isPlaying;\n                        playPauseBtn.textContent = isPlaying ? '\u23f8 Pause' : '\u25b6 Weiter';\n                        if (isPlaying) startAutoAdvance(); else stopAutoAdvance();\n                    });\n                }\n                if (favBtn) {\n                    favBtn.addEventListener('click', function() {\n                        const filename = lsAllFiles[slideIndex];\n                        const makeFav = !lsFavoritedFiles.has(filename);\n                        lsToggleFavoriteByFilename(filename, makeFav, function() { updateFavButton(); });\n                    });\n                }\n\n                document.addEventListener('keydown', function(e) {\n                    if (modal.style.display !== 'flex') return;\n                    if (e.key === 'Escape') closeSlideshow();\n                    if (e.key === 'ArrowLeft') { stopAutoAdvance(); showSlide(lsGetNextIndex(slideIndex, -1)); restartAutoAdvanceIfPlaying(); }\n                    if (e.key === 'ArrowRight') { stopAutoAdvance(); showSlide(lsGetNextIndex(slideIndex, 1)); restartAutoAdvanceIfPlaying(); }\n                });\n            })();\n\n            lsSetupChunkedZipDownload(document.getElementById('ls-download-zip-btn'), document.getElementById('ls-download-status'), 'ls_prepare_download_zip_chunk');\n            lsSetupChunkedZipDownload(document.getElementById('ls-download-favorites-zip-btn'), document.getElementById('ls-download-favorites-status'), 'ls_prepare_favorites_zip_chunk');\n\n            \/\/ Zuschauer-Zugang: das gerade aktive\/angeklickte Foto einzeln herunterladen (nicht\n            \/\/ per AJAX, sondern ein echter Datei-Download \u00fcber den serverseitigen Endpunkt).\n            const downloadSingleBtn = document.getElementById('ls-download-single-photo-btn');\n            if (downloadSingleBtn) {\n                downloadSingleBtn.addEventListener('click', function() {\n                    const filenameEl = document.getElementById('ls-active-image-filename');\n                    const file = filenameEl ? filenameEl.textContent.trim() : '';\n                    const statusEl = document.getElementById('ls-download-single-status');\n                    if (!file) {\n                        if (statusEl) statusEl.textContent = 'Kein Foto ausgew\u00e4hlt.';\n                        return;\n                    }\n                    const galleryEl = document.querySelector('.ls-gallery-container');\n                    const galleryId = galleryEl ? galleryEl.getAttribute('data-gallery') : '';\n                    const url = ajaxUrl + '?action=ls_download_single_photo&gallery=' + encodeURIComponent(galleryId) + '&file=' + encodeURIComponent(file);\n                    if (statusEl) statusEl.textContent = '\u2714 Download gestartet...';\n                    window.location.href = url;\n                });\n            }\n\n            const submitFirstBtn = document.getElementById('ls-submit-first-order-btn');\n            const summaryModal = document.getElementById('ls-checkout-summary-modal');\n            const confirmOrderBtn = document.getElementById('ls-confirm-order-btn');\n            const submitReorderBtn = document.getElementById('ls-submit-reorder-btn');\n            const fileDropdown = document.getElementById('ls-checkout-file-dropdown');\n            const thumbPreview = document.getElementById('ls-checkout-thumb-preview');\n            const shippingCheckbox = document.getElementById('ls-shipping-checkbox');\n            const agbCheckbox = document.getElementById('ls-agb-checkbox');\n\n            if (fileDropdown && thumbPreview) {\n                fileDropdown.addEventListener('change', function() {\n                    const baseUrl = fileDropdown.dataset.baseUrl || '';\n                    if (fileDropdown.value) {\n                        thumbPreview.src = baseUrl + encodeURIComponent(fileDropdown.value);\n                    }\n                });\n            }\n\n            function fetchAndUpdateCheckoutSummary() {\n                const shippingChecked = shippingCheckbox?.checked || false;\n                const servicesData = getSelectedServicesData();\n\n                const fd = new FormData();\n                fd.append('action', 'ls_calculate_checkout_summary');\n                fd.append('nonce', lsNonce);\n                fd.append('shipping_selected', shippingChecked ? '1' : '0');\n                fd.append('services_data_json', JSON.stringify(servicesData));\n\n                return fetch(ajaxUrl, { method: 'POST', body: fd })\n                .then(r => r.json())\n                .then(resp => {\n                    if (resp.success) {\n                        const data = resp.data;\n                        const tbody = document.getElementById('ls-summary-tbody');\n                        tbody.innerHTML = '';\n\n                        if (fileDropdown) {\n                            fileDropdown.innerHTML = '';\n                            fileDropdown.dataset.baseUrl = data.upload_base_url;\n                            if (data.selected_files && data.selected_files.length > 0) {\n                                data.selected_files.forEach((file, idx) => {\n                                    const opt = document.createElement('option');\n                                    opt.value = file;\n                                    opt.textContent = (idx + 1) + '. ' + file;\n                                    fileDropdown.appendChild(opt);\n                                });\n                                if (thumbPreview) {\n                                    thumbPreview.src = data.upload_base_url + encodeURIComponent(data.selected_files[0]);\n                                }\n                            } else {\n                                const opt = document.createElement('option');\n                                opt.textContent = 'Keine Fotos ausgew\u00e4hlt';\n                                fileDropdown.appendChild(opt);\n                                if (thumbPreview) thumbPreview.src = '';\n                            }\n                        }\n\n                        data.items.forEach(item => {\n                            const tr = document.createElement('tr');\n                            tr.style.borderBottom = '1px solid #333';\n                            tr.innerHTML = `\n                                <td style=\"padding:6px;\">${item.title}<\/td>\n                                <td style=\"padding:6px; text-align:center;\">${item.qty}<\/td>\n                                <td style=\"padding:6px; text-align:right;\">${new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(item.unit_price)} \u20ac<\/td>\n                                <td style=\"padding:6px; text-align:right;\">${new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(item.total)} \u20ac<\/td>\n                            `;\n                            tbody.appendChild(tr);\n                        });\n\n                        const totalsBox = document.getElementById('ls-summary-totals-box');\n                        const vatText = data.is_business ? `zzgl. ${data.vat_rate}% MwSt.` : `inkl. MwSt. (${data.vat_rate}%)`;\n                        totalsBox.innerHTML = `\n                            Netto-Betrag: <strong>${new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(data.netto_total)} \u20ac<\/strong><br>\n                            ${vatText}: <strong>${new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(data.vat_amount)} \u20ac<\/strong><br>\n                            Gesamtbetrag (Brutto): <strong>${new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(data.grand_total)} \u20ac<\/strong>\n                        `;\n                    }\n                });\n            }\n\n            if (submitFirstBtn && summaryModal) {\n                submitFirstBtn.addEventListener('click', function() {\n                    const count = parseInt(document.getElementById('ls-fav-selection-count').textContent || '0');\n                    if (count <= 0) {\n                        alert('Du hast noch keine Favoriten (\u2764\ufe0f) ausgew\u00e4hlt!');\n                        return;\n                    }\n\n                    submitFirstBtn.disabled = true;\n                    const originalText = submitFirstBtn.textContent;\n                    submitFirstBtn.textContent = '\u23f3 Wird berechnet...';\n\n                    fetchAndUpdateCheckoutSummary().then(() => {\n                        submitFirstBtn.disabled = false;\n                        submitFirstBtn.textContent = originalText;\n                        summaryModal.style.display = 'flex';\n                    });\n                });\n            }\n\n            if (shippingCheckbox) {\n                shippingCheckbox.addEventListener('change', fetchAndUpdateCheckoutSummary);\n            }\n            document.querySelectorAll('.ls-service-checkbox').forEach(cb => {\n                cb.addEventListener('change', fetchAndUpdateCheckoutSummary);\n            });\n\n            if (confirmOrderBtn) {\n                confirmOrderBtn.addEventListener('click', function() {\n                    const agbChecked = agbCheckbox?.checked || false;\n                    const statusDiv = document.getElementById('ls-order-submit-status');\n\n                    if (!agbChecked) {\n                        statusDiv.innerHTML = '<span style=\"color:#a00;\">Bitte akzeptiere die AGB.<\/span>';\n                        return;\n                    }\n\n                    confirmOrderBtn.disabled = true;\n                    confirmOrderBtn.textContent = '\u23f3 Wird \u00fcbermittelt...';\n\n                    const shippingChecked = shippingCheckbox?.checked || false;\n                    const servicesData = getSelectedServicesData();\n                    const selectedRating = document.querySelector('input[name=\"ls_customer_rating\"]:checked')?.value || '';\n                    const feedbackText = document.getElementById('ls-customer-feedback')?.value || '';\n\n                    const fd = new FormData();\n                    fd.append('action', 'ls_submit_order');\n                    fd.append('nonce', lsNonce);\n                    fd.append('agb_accepted', '1');\n                    fd.append('shipping_selected', shippingChecked ? '1' : '0');\n                    fd.append('services_data_json', JSON.stringify(servicesData));\n                    fd.append('rating', selectedRating);\n                    fd.append('feedback', feedbackText);\n\n                    fetch(ajaxUrl, { method: 'POST', body: fd })\n                    .then(r => r.json())\n                    .then(resp => {\n                        confirmOrderBtn.disabled = false;\n                        confirmOrderBtn.textContent = 'Jetzt verbindlich bestellen';\n                        if (resp.success) {\n                            statusDiv.innerHTML = '<span style=\"color:#2e7d32;\">\u2714 ' + resp.data + '<\/span>';\n                            setTimeout(() => { location.reload(); }, 2000);\n                        } else {\n                            statusDiv.innerHTML = '<span style=\"color:#a00;\">Fehler: ' + (resp.data || 'Unbekannter Fehler') + '<\/span>';\n                        }\n                    });\n                });\n            }\n\n            \/\/ ---- Nachbestell-Warenkorb (Checkout \u00e4hnlich der Erstbestellung, ohne Smileys) ----\n            const reorderCart = [];\n            const addReorderItemBtn = document.getElementById('ls-add-reorder-item-btn');\n            const reorderCartWrapper = document.getElementById('ls-reorder-cart-wrapper');\n            const reorderCartTbody = document.getElementById('ls-reorder-cart-tbody');\n            const reorderCartSubtotalEl = document.getElementById('ls-reorder-cart-subtotal');\n            const reorderSummaryModal = document.getElementById('ls-reorder-summary-modal');\n            const reorderShippingCheckbox = document.getElementById('ls-reorder-shipping-checkbox');\n            const reorderAgbCheckbox = document.getElementById('ls-reorder-agb-checkbox');\n            const confirmReorderBtn = document.getElementById('ls-confirm-reorder-btn');\n            const reorderFileSelect = document.getElementById('ls-reorder-file-select');\n            const reorderFileThumb = document.getElementById('ls-reorder-file-thumb');\n\n            if (reorderFileSelect && reorderFileThumb) {\n                reorderFileSelect.addEventListener('change', function() {\n                    const baseUrl = reorderFileSelect.dataset.baseUrl || '';\n                    if (reorderFileSelect.value) {\n                        reorderFileThumb.src = baseUrl + encodeURIComponent(reorderFileSelect.value);\n                    }\n                });\n            }\n\n            function formatEuro(val) {\n                return new Intl.NumberFormat('de-DE', {minimumFractionDigits:2, maximumFractionDigits:2}).format(val) + ' \u20ac';\n            }\n\n            function renderReorderCart() {\n                if (!reorderCartTbody) return;\n                reorderCartTbody.innerHTML = '';\n                let subtotal = 0;\n\n                reorderCart.forEach((item, idx) => {\n                    const lineTotal = item.price * item.qty;\n                    subtotal += lineTotal;\n                    const tr = document.createElement('tr');\n                    tr.style.borderBottom = '1px solid #333';\n                    tr.innerHTML = `\n                        <td style=\"padding:6px;\">${item.file}<\/td>\n                        <td style=\"padding:6px;\">${item.option}<\/td>\n                        <td style=\"padding:6px; text-align:center;\">${item.qty}<\/td>\n                        <td style=\"padding:6px; text-align:right;\">${formatEuro(lineTotal)}<\/td>\n                        <td style=\"padding:6px; text-align:right;\"><button type=\"button\" class=\"ls-reorder-remove-item\" data-idx=\"${idx}\" style=\"background:#444; color:#fff; border:none; border-radius:4px; padding:4px 8px; cursor:pointer;\">Entfernen<\/button><\/td>\n                    `;\n                    reorderCartTbody.appendChild(tr);\n                });\n\n                if (reorderCartSubtotalEl) reorderCartSubtotalEl.textContent = formatEuro(subtotal);\n                if (reorderCartWrapper) reorderCartWrapper.style.display = reorderCart.length > 0 ? 'block' : 'none';\n            }\n\n            if (addReorderItemBtn) {\n                addReorderItemBtn.addEventListener('click', function() {\n                    const fileSelect = document.getElementById('ls-reorder-file-select');\n                    const itemSelect = document.getElementById('ls-reorder-item-select');\n                    const qtyInput = document.getElementById('ls-reorder-qty');\n                    if (!fileSelect || !itemSelect || !qtyInput) return;\n\n                    const selectedFile = fileSelect.value;\n                    const selectedOption = itemSelect.value;\n                    const selectedPrice = parseFloat(itemSelect.options[itemSelect.selectedIndex].getAttribute('data-price')) || 0;\n                    const qty = parseInt(qtyInput.value, 10) || 1;\n\n                    reorderCart.push({ file: selectedFile, option: selectedOption, price: selectedPrice, qty: qty });\n                    renderReorderCart();\n                    qtyInput.value = '1';\n                });\n            }\n\n            if (reorderCartTbody) {\n                reorderCartTbody.addEventListener('click', function(e) {\n                    const btn = e.target.closest('.ls-reorder-remove-item');\n                    if (!btn) return;\n                    const idx = parseInt(btn.getAttribute('data-idx'));\n                    reorderCart.splice(idx, 1);\n                    renderReorderCart();\n                });\n            }\n\n            function fetchAndUpdateReorderSummary() {\n                const shippingChecked = reorderShippingCheckbox?.checked || false;\n\n                const fd = new FormData();\n                fd.append('action', 'ls_calculate_reorder_summary');\n                fd.append('nonce', lsNonce);\n                fd.append('shipping_selected', shippingChecked ? '1' : '0');\n                fd.append('cart_items_json', JSON.stringify(reorderCart));\n\n                return fetch(ajaxUrl, { method: 'POST', body: fd })\n                .then(r => r.json())\n                .then(resp => {\n                    if (resp.success) {\n                        const data = resp.data;\n                        const tbody = document.getElementById('ls-reorder-summary-tbody');\n                        tbody.innerHTML = '';\n\n                        data.items.forEach(item => {\n                            const tr = document.createElement('tr');\n                            tr.style.borderBottom = '1px solid #333';\n                            tr.innerHTML = `\n                                <td style=\"padding:6px;\">${item.title}<\/td>\n                                <td style=\"padding:6px; text-align:center;\">${item.qty}<\/td>\n                                <td style=\"padding:6px; text-align:right;\">${formatEuro(item.unit_price)}<\/td>\n                                <td style=\"padding:6px; text-align:right;\">${formatEuro(item.total)}<\/td>\n                            `;\n                            tbody.appendChild(tr);\n                        });\n\n                        const totalsBox = document.getElementById('ls-reorder-summary-totals-box');\n                        const vatText = data.is_business ? `zzgl. ${data.vat_rate}% MwSt.` : `inkl. MwSt. (${data.vat_rate}%)`;\n                        totalsBox.innerHTML = `\n                            Netto-Betrag: <strong>${formatEuro(data.netto_total)}<\/strong><br>\n                            ${vatText}: <strong>${formatEuro(data.vat_amount)}<\/strong><br>\n                            Gesamtbetrag (Brutto): <strong>${formatEuro(data.grand_total)}<\/strong>\n                        `;\n                    }\n                });\n            }\n\n            if (submitReorderBtn && reorderSummaryModal) {\n                submitReorderBtn.addEventListener('click', function() {\n                    if (reorderCart.length === 0) {\n                        alert('Bitte f\u00fcge zuerst mindestens eine Position zu deinem Warenkorb hinzu.');\n                        return;\n                    }\n\n                    submitReorderBtn.disabled = true;\n                    const originalText = submitReorderBtn.textContent;\n                    submitReorderBtn.textContent = 'Wird berechnet...';\n\n                    fetchAndUpdateReorderSummary().then(() => {\n                        submitReorderBtn.disabled = false;\n                        submitReorderBtn.textContent = originalText;\n                        reorderSummaryModal.style.display = 'flex';\n                    });\n                });\n            }\n\n            if (reorderShippingCheckbox) {\n                reorderShippingCheckbox.addEventListener('change', fetchAndUpdateReorderSummary);\n            }\n\n            if (confirmReorderBtn) {\n                confirmReorderBtn.addEventListener('click', function() {\n                    const agbChecked = reorderAgbCheckbox?.checked || false;\n                    const statusDiv = document.getElementById('ls-reorder-order-submit-status');\n\n                    if (!agbChecked) {\n                        statusDiv.innerHTML = '<span style=\"color:#a00;\">Bitte akzeptiere die AGB.<\/span>';\n                        return;\n                    }\n\n                    confirmReorderBtn.disabled = true;\n                    confirmReorderBtn.textContent = 'Wird \u00fcbermittelt...';\n\n                    const shippingChecked = reorderShippingCheckbox?.checked || false;\n\n                    const fd = new FormData();\n                    fd.append('action', 'ls_submit_reorder');\n                    fd.append('nonce', lsNonce);\n                    fd.append('agb_accepted', '1');\n                    fd.append('shipping_selected', shippingChecked ? '1' : '0');\n                    reorderCart.forEach((item, idx) => {\n                        fd.append('items[' + idx + '][file]', item.file);\n                        fd.append('items[' + idx + '][option]', item.option);\n                        fd.append('items[' + idx + '][price]', item.price);\n                        fd.append('items[' + idx + '][qty]', item.qty);\n                    });\n\n                    fetch(ajaxUrl, { method: 'POST', body: fd })\n                    .then(r => r.json())\n                    .then(resp => {\n                        confirmReorderBtn.disabled = false;\n                        confirmReorderBtn.textContent = 'Jetzt verbindlich nachbestellen';\n                        if (resp.success) {\n                            statusDiv.innerHTML = '<span style=\"color:#2e7d32;\">' + resp.data + '<\/span>';\n                            setTimeout(() => { location.reload(); }, 2000);\n                        } else {\n                            statusDiv.innerHTML = '<span style=\"color:#a00;\">Fehler: ' + (resp.data || 'Unbekannter Fehler') + '<\/span>';\n                        }\n                    });\n                });\n            }\n        });\n        <\/script>\n        \n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 \u0412\u0430\u0448\u0443 \u043b\u0438\u0447\u043d\u0443\u044e \u0444\u043e\u0442\u043e\u0433\u0430\u043b\u0435\u0440\u0435\u044e! &#x2728; \u0420\u0430\u0434\u044b, \u0447\u0442\u043e \u0412\u044b \u0437\u0434\u0435\u0441\u044c! \u041c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0434\u043b\u044f \u0412\u0430\u0441 \u0441\u0430\u043c\u044b\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u0412\u0430\u0448\u0435\u0439 \u0444\u043e\u0442\u043e\u0441\u0435\u0441\u0441\u0438\u0438. \u041d\u0435 \u0442\u043e\u0440\u043e\u043f\u0438\u0442\u0435\u0441\u044c, \u0440\u0430\u0441\u0441\u043b\u0430\u0431\u044c\u0442\u0435\u0441\u044c \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0412\u0430\u0448\u0438 \u0441\u0430\u043c\u044b\u0435 \u043b\u044e\u0431\u0438\u043c\u044b\u0435 \u0441\u043d\u0438\u043c\u043a\u0438. \u00ab\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0430, \u0438\u0445 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0432 \u043c\u0438\u043d\u0438\u0430\u0442\u044e\u0440\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0414\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0439 \u0433\u043b\u0443\u0431\u0438\u043d\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u044f\u0440\u043a\u043e\u0441\u0442\u0438 \u0446\u0432\u0435\u0442\u043e\u0432 \u043c\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0441 \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u0430 \u0438\u043b\u0438 \u041f\u041a.\u00bb&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":25208,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_seo_schema_type":"","ngg_post_thumbnail":0,"footnotes":""},"class_list":["post-99485","page","type-page","status-publish","hentry","entry","no-media"],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/pages\/99485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/comments?post=99485"}],"version-history":[{"count":0,"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/pages\/99485\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/pages\/25208"}],"wp:attachment":[{"href":"https:\/\/www.light-style.eu\/ru\/wp-json\/wp\/v2\/media?parent=99485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}