{"id":99486,"date":"2025-11-14T10:02:58","date_gmt":"2025-11-14T09:02:58","guid":{"rendered":"https:\/\/www.light-style.eu\/mon-compte\/votre-galerie-de-selection\/"},"modified":"2026-08-04T00:57:33","modified_gmt":"2026-08-03T22:57:33","slug":"votre-galerie-de-selection","status":"publish","type":"page","link":"https:\/\/www.light-style.eu\/fr\/mon-compte\/votre-galerie-de-selection\/","title":{"rendered":"Votre galerie !"},"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>Bienvenue dans votre galerie photo personnelle ! &#x2728;<\/strong><\/h3>\n\n<p class=\"has-text-align-center wp-block-paragraph\">Ravi de vous accueillir ! Nous avons rassembl\u00e9 pour vous les plus beaux moments de votre s\u00e9ance photo. <\/p>\n\n<p class=\"has-text-align-center wp-block-paragraph\">Prenez tout votre temps, installez-vous confortablement et s\u00e9lectionnez vos clich\u00e9s pr\u00e9f\u00e9r\u00e9s.<\/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 Les photos sont des \u0153uvres d\u2019art \u2013 on ne les appr\u00e9cie pas au format timbre-poste. Pour une profondeur d\u2019image et une brillance des couleurs optimales, nous recommandons une consultation sur tablette ou ordinateur. \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>Bon \u00e0 savoir :<\/strong><\/p>\n\n<ul class=\"wp-block-list\">\n<li><strong>Choisir ensemble :<\/strong> Vous pouvez facilement partager le lien de votre galerie avec votre famille ou vos amis afin de choisir vos favoris ensemble.<\/li>\n\n\n\n<li><strong>Sauvegarde automatique :<\/strong> Votre s\u00e9lection est directement enregistr\u00e9e en arri\u00e8re-plan \u2013 vous pouvez fermer la galerie \u00e0 tout moment et reprendre votre navigation plus tard.<\/li>\n\n\n\n<li><strong>Tout sous les yeux :<\/strong> Dans l\u2019aper\u00e7u, vous pouvez voir \u00e0 tout moment combien d\u2019images vous avez choisies et quelles options suppl\u00e9mentaires sont \u00e0 votre disposition.<\/li>\n<\/ul>\n\n<p class=\"has-text-align-center wp-block-paragraph\">D\u00e8s que vous avez marqu\u00e9 vos favoris, cliquez simplement en bas sur <strong>\u00ab V\u00e9rifier la s\u00e9lection &amp; envoyer \u00bb<\/strong> \u2013 nous nous occuperons ensuite de la retouche finale pour vous !<\/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>Les options suppl\u00e9mentaires facultatives, telles que la retouche (selon le type de photo), vous seront affich\u00e9es dans le processus de commande si elles sont pr\u00e9vues, et vous pourrez les y ajouter.<\/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>NOTE : La s\u00e9lection et la d\u00e9s\u00e9lection d&rsquo;une photo (le petit c\u0153ur) prend 1 \u00e0 2 secondes. Par s\u00e9curit\u00e9. Le petit c\u0153ur devient rouge lorsque le serveur a confirm\u00e9 votre s\u00e9lection. Ainsi, rien n&rsquo;est perdu.   <\/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                                        <p><button type=\"submit\" class=\"ls-btn\" style=\"width:100%;\">Galerie \u00f6ffnen<\/button><\/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;\">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                                <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: #c5a059; color: #fff; }\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            .ls-btn { background: #c5a059; color: #fff; border: none; padding: 12px; font-weight: bold; border-radius: 4px; cursor: pointer; }\n            .ls-btn:hover { background: #b08d4c; }\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            .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\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        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\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            document.querySelectorAll('.ls-fav-toggle-btn').forEach(btn => {\n                btn.addEventListener('click', function(e) {\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                    const favAction = isCurrentlyFav ? 'remove' : 'add';\n\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', favAction);\n\n                    fetch(ajaxUrl, { method: 'POST', body: fd })\n                    .then(r => r.json())\n                    .then(resp => {\n                        if (resp.success) {\n                            if (favAction === 'add') {\n                                btn.style.background = '#c5a059';\n                                btn.textContent = '\u2764\ufe0f';\n                                card.style.borderColor = '#c5a059';\n                                card.setAttribute('data-favorite', 'true');\n                            } else {\n                                btn.style.background = 'rgba(0,0,0,0.6)';\n                                btn.textContent = '\ud83e\udd0d';\n                                card.style.borderColor = '#ddd';\n                                card.setAttribute('data-favorite', 'false');\n                            }\n                            document.getElementById('ls-fav-selection-count').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                    });\n                });\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                    wandbildPanel.style.display = (wandbildPanel.style.display === 'none' || !wandbildPanel.style.display) ? 'block' : 'none';\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            const downloadZipBtn = document.getElementById('ls-download-zip-btn');\n            if (downloadZipBtn) {\n                downloadZipBtn.addEventListener('click', function() {\n                    downloadZipBtn.disabled = true;\n                    downloadZipBtn.textContent = '\u23f3 ZIP-Archiv wird erstellt...';\n                    const statusDiv = document.getElementById('ls-download-status');\n\n                    const fd = new FormData();\n                    fd.append('action', 'ls_download_favorites_zip');\n                    fd.append('nonce', lsNonce);\n\n                    fetch(ajaxUrl, { method: 'POST', body: fd })\n                    .then(r => r.json())\n                    .then(resp => {\n                        downloadZipBtn.disabled = false;\n                        downloadZipBtn.textContent = '\ud83d\udce5 Alle Favoriten als ZIP herunterladen';\n                        if (resp.success) {\n                            statusDiv.innerHTML = '<span style=\"color:#2e7d32;\">\u2714 Download startet...<\/span>';\n                            window.location.href = resp.data.download_url;\n                        } else {\n                            statusDiv.innerHTML = '<span style=\"color:#a00;\">Fehler: ' + (resp.data || 'Unbekannter Fehler') + '<\/span>';\n                        }\n                    });\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>Bienvenue dans votre galerie photo personnelle ! &#x2728; Ravi de vous accueillir ! Nous avons rassembl\u00e9 pour vous les plus beaux moments de votre s\u00e9ance photo. Prenez tout votre temps, installez-vous confortablement et s\u00e9lectionnez vos clich\u00e9s pr\u00e9f\u00e9r\u00e9s. \u00ab Les photos sont des \u0153uvres d\u2019art \u2013 on ne les appr\u00e9cie pas au format timbre-poste. Pour une&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":66682,"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-99486","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\/fr\/wp-json\/wp\/v2\/pages\/99486","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.light-style.eu\/fr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.light-style.eu\/fr\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.light-style.eu\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.light-style.eu\/fr\/wp-json\/wp\/v2\/comments?post=99486"}],"version-history":[{"count":0,"href":"https:\/\/www.light-style.eu\/fr\/wp-json\/wp\/v2\/pages\/99486\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.light-style.eu\/fr\/wp-json\/wp\/v2\/pages\/66682"}],"wp:attachment":[{"href":"https:\/\/www.light-style.eu\/fr\/wp-json\/wp\/v2\/media?parent=99486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}