{
  "version": 3,
  "sources": ["../alpine-components/photo-modals.js", "../alpine-components/batch.js", "../alpine-components/photo-upload.js", "../alpine-components/onboarding.js", "../alpine-components/property-create.js", "../alpine-components/address.js", "../alpine-components/listing-form.js", "../public-upload.js"],
  "sourcesContent": ["document.addEventListener('alpine:init', () => {\n\n    Alpine.data('photoModals', () => ({\n        comparisonOpen: false,\n        feedbackOpen: false,\n        revisionOpen: false,\n        deleteOpen: false,\n        qaExplainOpen: false,\n        metadataOpen: false,\n        upscaleConfirmOpen: false,\n        deleting: false,\n        revisionSrc: '',\n        revisionUrls: {},\n        menuOpen: false,\n\n        init() {\n            const json = this.$el.dataset.revisionUrls;\n            if (json) {\n                try { this.revisionUrls = JSON.parse(json); } catch (e) { this.revisionUrls = {}; }\n            }\n\n            document.addEventListener('feedback:reload', () => {\n                this._feedbackNeedsReload = true;\n            });\n        },\n\n        openComparison()  { this.comparisonOpen = true;  this.lockScroll(); },\n        closeComparison() { this.comparisonOpen = false; this.unlockScroll(); },\n        openFeedback()    { this.feedbackOpen = true;    this.lockScroll(); },\n        closeFeedback()   { if (this._feedbackNeedsReload) { window.location.reload(); return; } this.feedbackOpen = false; this.unlockScroll(); },\n        showRevision(id)  { this.revisionSrc = this.revisionUrls[id] || ''; this.revisionOpen = true; this.lockScroll(); },\n        closeRevision()   { this.revisionOpen = false;   this.unlockScroll(); },\n        openDelete()      { this.deleteOpen = true;      this.lockScroll(); },\n        closeDelete()     { this.deleteOpen = false;     this.unlockScroll(); },\n        openQaExplain()   { this.qaExplainOpen = true;   this.lockScroll(); },\n        closeQaExplain()  { this.qaExplainOpen = false;  this.unlockScroll(); },\n        openMetadata()        { this.metadataOpen = true;        this.lockScroll(); },\n        closeMetadata()       { this.metadataOpen = false;       this.unlockScroll(); },\n        openUpscaleConfirm()  { this.upscaleConfirmOpen = true;  this.lockScroll(); },\n        closeUpscaleConfirm() { this.upscaleConfirmOpen = false; this.unlockScroll(); },\n\n        get anyOpen() { return this.comparisonOpen || this.feedbackOpen || this.revisionOpen || this.deleteOpen || this.qaExplainOpen || this.metadataOpen || this.upscaleConfirmOpen; },\n        lockScroll()   { window._scrollLock.lock(); },\n        unlockScroll() { if (!this.anyOpen) window._scrollLock.unlock(); },\n    }));\n\n    Alpine.data('editForm', () => ({\n        activeTab: 'outdoor',\n        submitting: false,\n        duplicateWarningBypassed: false,\n        floorplanWarningBypassed: false,\n        floorplanWarningPending: false,\n        previousPresets: [],\n        outdoor: { optimize: true, sunshine: true, declutter: true },\n        indoor: { optimize: true, declutter: true, details: true, staging: true },\n        replaceFurniture: false,\n        lockCameraAngle: true,\n        resolution4k: false,\n        roomType: '',\n        furnitureStyle: '',\n        intensity: 'normal',\n        additionalGuidance: '',\n        roomOpen: false,\n        styleOpen: false,\n        roomOptions: [\n            {v:'',l:'Auto'}, {v:'living_room',l:'Wohnzimmer'},\n            {v:'bedroom',l:'Schlafzimmer'}, {v:'kitchen',l:'K\u00FCche'},\n            {v:'bathroom',l:'Badezimmer'}, {v:'kids_room',l:'Kinderzimmer'},\n            {v:'dining_room',l:'Esszimmer'}, {v:'hallway',l:'Flur'},\n            {v:'office',l:'B\u00FCro'}, {v:'garage',l:'Garage'},\n            {v:'basement',l:'Keller'},\n        ],\n        styleOptions: [\n            {v:'',l:'Auto'}, {v:'modern',l:'Modern'},\n            {v:'skandinavisch',l:'Skandinavisch'}, {v:'klassisch',l:'Klassisch'},\n            {v:'landhausstil',l:'Landhausstil'}, {v:'industriell',l:'Industriell'},\n        ],\n\n        init() {\n            this.floorplanWarningPending = this.$el.dataset.floorplanWarningPending === 'true';\n            // Apply saved preset preferences\n            const prefsJson = this.$el.dataset.presetPrefs;\n            if (prefsJson) {\n                try {\n                    const prefs = JSON.parse(prefsJson);\n                    if (prefs.outdoor) {\n                        this.outdoor.optimize = prefs.outdoor.includes('optimize');\n                        this.outdoor.sunshine = prefs.outdoor.includes('sunshine');\n                        this.outdoor.declutter = prefs.outdoor.includes('declutter');\n                    }\n                    if (prefs.indoor) {\n                        this.indoor.optimize = prefs.indoor.includes('optimize_indoor');\n                        this.indoor.declutter = prefs.indoor.includes('declutter_indoor');\n                        this.indoor.details = prefs.indoor.includes('details');\n                        this.indoor.staging = prefs.indoor.includes('staging');\n                    }\n                    if (typeof prefs.replace_furniture === 'boolean')\n                        this.replaceFurniture = prefs.replace_furniture;\n                    if (typeof prefs.lock_camera_angle === 'boolean')\n                        this.lockCameraAngle = prefs.lock_camera_angle;\n                    if (prefs.intensity === 'subtle')\n                        this.intensity = 'subtle';\n                    if (prefs.resolution === '4K')\n                        this.resolution4k = true;\n                    if (prefs.furniture_style)\n                        this.furnitureStyle = prefs.furniture_style;\n                    if (prefs.aspect_ratio) {\n                        const sel = this.$el.querySelector('#aspect-ratio');\n                        if (sel) sel.value = prefs.aspect_ratio;\n                    }\n                } catch (e) {}\n            }\n\n            // Parse previous presets for duplicate detection\n            try {\n                this.previousPresets = JSON.parse(this.$el.dataset.previousPresets || '[]');\n            } catch (e) { this.previousPresets = []; }\n\n            this.activeTab = this.$el.dataset.initialTab || 'outdoor';\n            this.isFloorplan = this.activeTab === 'floorplan';\n            this.roomType = this.$el.dataset.roomType || '';\n\n            // Construction subtype override (photo-specific > account preference)\n            const subtype = this.$el.dataset.sceneSubtype || '';\n            if (this.activeTab === 'indoor' && subtype === 'construction') {\n                this.indoor.declutter = false;\n                this.indoor.staging = false;\n                this.indoor.details = false;\n            }\n        },\n\n        switchTab(tab) {\n            this.activeTab = tab;\n            if (tab !== 'indoor') {\n                this.indoor.staging = false;\n                this.replaceFurniture = false;\n                this.roomType = '';\n                this.furnitureStyle = '';\n            }\n        },\n\n        get showStagingOptions() {\n            return this.activeTab === 'indoor' && this.indoor.staging;\n        },\n\n        getSelectedPresets() {\n            if (this.activeTab === 'outdoor') {\n                return Object.entries(this.outdoor).filter(([, v]) => v).map(([k]) => k);\n            }\n            if (this.activeTab === 'indoor') {\n                var presets = [];\n                if (this.indoor.optimize) presets.push('optimize_indoor');\n                if (this.indoor.declutter) presets.push('declutter_indoor');\n                if (this.indoor.details) presets.push('details');\n                if (this.indoor.staging) presets.push(this.replaceFurniture ? 'staging_replace' : 'staging');\n                return presets;\n            }\n            if (this.activeTab === 'floorplan') {\n                // Floorplan presets from hidden inputs \u2014 always one preset\n                var input = this.$el.querySelector('input[name=\"presets\"][value^=\"floorplan\"]');\n                return input ? [input.value] : [];\n            }\n            return [];\n        },\n\n        isDuplicatePresets() {\n            if (!this.previousPresets.length) return false;\n            if (this.additionalGuidance.trim()) return false;\n            var selected = this.getSelectedPresets();\n            if (!selected.length) return false;\n            return selected.every(function(p) { return this.previousPresets.indexOf(p) !== -1; }.bind(this));\n        },\n\n        // Pre-submit gates. handleConfirm walks this list and opens the\n        // first gate whose `needs()` returns true. Confirming a gate sets\n        // its `bypassed` flag and calls _resumeSubmit(), which re-walks the\n        // gates synchronously and either opens the next pending gate or\n        // fires the captured HTMX issueRequest.\n        gates() {\n            const self = this;\n            return [\n                {\n                    needs() {\n                        return self.activeTab === 'floorplan'\n                            && self.floorplanWarningPending\n                            && !self.floorplanWarningBypassed;\n                    },\n                    open() { Alpine.store('modal').show('floorplan-warning'); },\n                },\n                {\n                    needs() {\n                        return self.activeTab !== 'custom'\n                            && !self.duplicateWarningBypassed\n                            && self.isDuplicatePresets();\n                    },\n                    open() { Alpine.store('modal').show('duplicate-warning'); },\n                },\n            ];\n        },\n\n        handleConfirm(event) {\n            for (const gate of this.gates()) {\n                if (gate.needs()) {\n                    event.preventDefault();\n                    this._issueRequest = event.detail.issueRequest;\n                    gate.open();\n                    return;\n                }\n            }\n        },\n\n        _resumeSubmit() {\n            // A bypassed gate may have unblocked the next one \u2014 walk the\n            // chain again before submitting. event.detail.issueRequest is\n            // the htmx:confirm completion callback and does NOT re-emit\n            // htmx:confirm, so the chain has to advance itself here.\n            for (const gate of this.gates()) {\n                if (gate.needs()) {\n                    gate.open();\n                    return;\n                }\n            }\n            this.submitting = true;\n            if (this._issueRequest) this._issueRequest();\n        },\n\n        confirmFloorplanWarning() {\n            Alpine.store('modal').close();\n            this.floorplanWarningBypassed = true;\n            this._resumeSubmit();\n        },\n\n        confirmSubmit() {\n            Alpine.store('modal').close();\n            this.duplicateWarningBypassed = true;\n            this._resumeSubmit();\n        },\n    }));\n\n});\n", "document.addEventListener('alpine:init', () => {\n\n    Alpine.data('batchOutdoorPresets', () => ({\n        outdoor: { optimize: true, sunshine: true, declutter: true },\n        init() {\n            const prefs = JSON.parse(this.$el.dataset.presetPrefs || '{}');\n            if (prefs.outdoor) {\n                this.outdoor.optimize = prefs.outdoor.includes('optimize');\n                this.outdoor.sunshine = prefs.outdoor.includes('sunshine');\n                this.outdoor.declutter = prefs.outdoor.includes('declutter');\n            }\n        },\n    }));\n\n    Alpine.data('batchIndoorPresets', () => ({\n        indoor: { optimize_indoor: true, declutter_indoor: true, details: true, staging: true },\n        replaceFurniture: false,\n        furnitureStyle: '',\n        styleOpen: false,\n        styleOptions: [\n            {v:'',l:'Auto'}, {v:'modern',l:'Modern'},\n            {v:'skandinavisch',l:'Skandinavisch'}, {v:'klassisch',l:'Klassisch'},\n            {v:'landhausstil',l:'Landhausstil'}, {v:'industriell',l:'Industriell'},\n        ],\n        init() {\n            const prefs = JSON.parse(this.$el.dataset.presetPrefs || '{}');\n            if (prefs.indoor) {\n                this.indoor.optimize_indoor = prefs.indoor.includes('optimize_indoor');\n                this.indoor.declutter_indoor = prefs.indoor.includes('declutter_indoor');\n                this.indoor.details = prefs.indoor.includes('details');\n                this.indoor.staging = prefs.indoor.includes('staging');\n            }\n            if (typeof prefs.replace_furniture === 'boolean')\n                this.replaceFurniture = prefs.replace_furniture;\n            if (prefs.furniture_style)\n                this.furnitureStyle = prefs.furniture_style;\n        },\n    }));\n\n    Alpine.data('batchSelect', () => ({\n        selectedPhotos: {},\n        modalOpen: false,\n        loading: false,\n        deleting: false,\n\n        get count() { return Object.keys(this.selectedPhotos).length; },\n        get hasSelection() { return this.count > 0; },\n        get countLabel() {\n            return this.count === 1 ? '1 Foto ausgew\u00E4hlt' : this.count + ' Fotos ausgew\u00E4hlt';\n        },\n\n        togglePhoto(id, checked) {\n            if (checked) this.selectedPhotos[id] = true;\n            else delete this.selectedPhotos[id];\n        },\n\n        isSelectableCheckbox(checkbox) {\n            return !checkbox.disabled && checkbox.offsetParent !== null;\n        },\n\n        getSectionCheckboxes(sectionKey) {\n            const selector = '.batch-select-checkbox[data-photo-section=\"' + sectionKey + '\"]';\n            return Array.from(this.$root.querySelectorAll(selector))\n                .filter(cb => this.isSelectableCheckbox(cb));\n        },\n\n        isSectionFullySelected(sectionKey) {\n            const checkboxes = this.getSectionCheckboxes(sectionKey);\n            return checkboxes.length > 0 && checkboxes.every(cb => this.isSelected(cb.dataset.photoId));\n        },\n\n        isSectionPartiallySelected(sectionKey) {\n            const checkboxes = this.getSectionCheckboxes(sectionKey);\n            if (!checkboxes.length) return false;\n            const selectedCount = checkboxes.filter(cb => this.isSelected(cb.dataset.photoId)).length;\n            return selectedCount > 0 && selectedCount < checkboxes.length;\n        },\n\n        toggleSection(sectionKey, checked) {\n            this.getSectionCheckboxes(sectionKey).forEach(cb => {\n                cb.checked = checked;\n                this.togglePhoto(cb.dataset.photoId, checked);\n            });\n        },\n\n        isSelected(id) { return !!this.selectedPhotos[id]; },\n\n        clearSelection() {\n            this.selectedPhotos = {};\n            this.$root.querySelectorAll('.batch-select-checkbox').forEach(cb => { cb.checked = false; });\n        },\n\n        openModal() {\n            if (!this.hasSelection || this.loading) return;\n            this.loading = true;\n            this.modalOpen = true;\n            const params = Object.keys(this.selectedPhotos).map(id => 'photos=' + encodeURIComponent(id)).join('&');\n            htmx.ajax('GET', this.$root.dataset.modalUrl + '?' + params, { target: '#batch-modal-content', swap: 'innerHTML' })\n                .finally(() => { this.loading = false; });\n        },\n\n        openUpscaleModal() {\n            if (!this.hasSelection || this.loading) return;\n            this.loading = true;\n            this.modalOpen = true;\n            const params = Object.keys(this.selectedPhotos).map(id => 'photos=' + encodeURIComponent(id)).join('&');\n            htmx.ajax('GET', this.$root.dataset.upscaleUrl + '?' + params, { target: '#batch-modal-content', swap: 'innerHTML' })\n                .finally(() => { this.loading = false; });\n        },\n\n        closeModal() { this.modalOpen = false; },\n        closeAndRefresh() { this.modalOpen = false; this.clearSelection(); htmx.trigger('#photo-grid', 'refresh'); },\n\n        openDeleteModal() {\n            if (!this.hasSelection || this.deleting) return;\n            Alpine.store('modal')?.show('batch-photo-delete');\n        },\n\n        closeDeleteModal() {\n            if (this.deleting) return;\n            Alpine.store('modal')?.close();\n        },\n\n        submitDelete() {\n            if (!this.hasSelection || this.deleting) return;\n            this.deleting = true;\n            const url = this.$root.dataset.deleteUrl;\n            const csrf = this.$root.dataset.csrf;\n            const formData = new FormData();\n            Object.keys(this.selectedPhotos).forEach(id => formData.append('photo_ids', id));\n            fetch(url, {\n                method: 'POST',\n                body: formData,\n                headers: { 'X-CSRFToken': csrf, 'X-Requested-With': 'XMLHttpRequest' },\n            })\n                .then(r => { if (!r.ok) throw new Error('Delete failed (' + r.status + ')'); })\n                .then(() => {\n                    Alpine.store('modal')?.close();\n                    this.clearSelection();\n                    htmx.trigger('#photo-grid', 'refresh');\n                })\n                .catch(err => {\n                    console.error(err);\n                    window.alert('L\u00F6schen fehlgeschlagen. Bitte erneut versuchen.');\n                })\n                .finally(() => { this.deleting = false; });\n        },\n\n        init() {\n            // Listen for batch clear events from HTMX-swapped partials\n            document.addEventListener('batch:clear', () => this.clearSelection());\n\n            // Re-check boxes after HTMX swaps photo cards\n            this.$root.addEventListener('htmx:afterSwap', () => {\n                this.$root.querySelectorAll('.batch-select-checkbox').forEach(cb => {\n                    cb.checked = this.isSelected(cb.dataset.photoId);\n                });\n                // Force Alpine to recompute section header tri-state bindings.\n                this.selectedPhotos = { ...this.selectedPhotos };\n            });\n        },\n    }));\n\n});\n", "document.addEventListener('alpine:init', () => {\n\n    Alpine.data('photoUpload', () => ({\n        isOpen: false,\n        dragging: false,\n        hasUploads: false,\n        pendingUploads: 0,\n        // URL import state\n        activeTab: 'device',\n        importUrl: '',\n        scraping: false,\n        importing: false,\n        scrapedImages: [],\n        scrapedMetadata: {},\n\n        open() {\n            this.isOpen = true;\n            this.lockScroll();\n        },\n\n        close() {\n            if (this.pendingUploads > 0 || this.importing) return;\n            this.isOpen = false;\n            this.unlockScroll();\n            this.resetUrlImport();\n            if (this.hasUploads) htmx.trigger('#photo-grid', 'refresh');\n        },\n\n        lockScroll()   { window._scrollLock.lock(); },\n        unlockScroll() { window._scrollLock.unlock(); },\n\n        openFilePicker() { this.$refs.fileInput?.click(); },\n\n        onFileSelect(e) {\n            this.handleFiles(e.target.files);\n            e.target.value = '';\n        },\n\n        onDrop(e) {\n            this.dragging = false;\n            this.handleFiles(e.dataTransfer.files);\n        },\n\n        handleFiles(files) {\n            Array.from(files).forEach(file => {\n                if (!this.isValidFile(file)) return;\n                this.uploadFile(file);\n            });\n        },\n\n        isValidFile(file) {\n            const validTypes = ['image/jpeg', 'image/png', 'image/webp'];\n            const maxSize = 20 * 1024 * 1024;\n            return validTypes.includes(file.type) && file.size <= maxSize;\n        },\n\n        uploadFile(file) {\n            this.hasUploads = true;\n            this.pendingUploads++;\n\n            const tempId = 'temp-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);\n            const previewUrl = URL.createObjectURL(file);\n            const uploadUrl = this.$root.dataset.uploadUrl;\n            const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n            // Capture the ref now: `this.$refs` throws (_x_refs) once an hx-boost\n            // navigation tears the component down mid-upload.\n            const uploadRows = this.$refs.uploadRows;\n\n            const placeholderHtml = '<div id=\"' + tempId + '\" class=\"flex items-center gap-4 p-3 bg-soft rounded-lg border border-border\">' +\n                '<div class=\"w-16 h-12 bg-muted rounded overflow-hidden flex-shrink-0\">' +\n                '<img src=\"' + previewUrl + '\" class=\"w-full h-full object-cover\">' +\n                '</div>' +\n                '<div class=\"flex-1 min-w-0\">' +\n                '<p class=\"font-medium text-foreground truncate text-sm\">' + this.escapeHtml(file.name) + '</p>' +\n                '<div class=\"flex items-center gap-1.5 text-sm text-muted-foreground mt-0.5\">' +\n                '<svg class=\"w-4 h-4 animate-spin\" fill=\"none\" viewBox=\"0 0 24 24\">' +\n                '<circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>' +\n                '<path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path>' +\n                '</svg>' +\n                '<span>Wird hochgeladen...</span>' +\n                '</div></div></div>';\n            if (uploadRows) uploadRows.insertAdjacentHTML('beforeend', placeholderHtml);\n\n            const doUpload = () => {\n                const formData = new FormData();\n                formData.append('photo', file);\n                return fetch(uploadUrl, {\n                    method: 'POST',\n                    headers: { 'X-CSRFToken': csrfToken },\n                    body: formData\n                }).then(response => {\n                    if (!response.ok) return response.json().then(data => { throw new Error(data.error || 'Upload fehlgeschlagen'); });\n                    return response.json();\n                });\n            };\n\n            const showError = (msg) => {\n                const placeholder = document.getElementById(tempId);\n                if (placeholder) {\n                    const retryId = tempId + '-retry';\n                    placeholder.outerHTML = '<div id=\"' + tempId + '\" class=\"flex items-center gap-4 p-3 bg-red-50 rounded-lg border border-red-200\">' +\n                        '<div class=\"w-16 h-12 bg-red-100 rounded flex items-center justify-center flex-shrink-0\">' +\n                        '<svg class=\"w-5 h-5 text-red-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">' +\n                        '<path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>' +\n                        '</svg></div>' +\n                        '<div class=\"flex-1 min-w-0\">' +\n                        '<p class=\"font-medium text-red-800 truncate text-sm\">' + this.escapeHtml(file.name) + '</p>' +\n                        '<p class=\"text-sm text-red-600\">' + this.escapeHtml(msg) + '</p>' +\n                        '</div>' +\n                        '<button id=\"' + retryId + '\" class=\"px-3 py-1 text-xs font-medium text-red-700 bg-red-100 hover:bg-red-200 rounded transition-colors cursor-pointer flex-shrink-0\">Nochmal</button>' +\n                        '</div>';\n                    const retryBtn = document.getElementById(retryId);\n                    if (retryBtn) retryBtn.addEventListener('click', () => {\n                        const row = document.getElementById(tempId);\n                        if (row) row.outerHTML = placeholderHtml;\n                        this.pendingUploads++;\n                        doUpload().then(onSuccess).catch(e => showError(friendlyMsg(e))).finally(onDone);\n                    });\n                }\n            };\n\n            const friendlyMsg = (error) => {\n                if (error instanceof TypeError) return 'Upload fehlgeschlagen \u2014 bitte erneut versuchen';\n                return error.message || 'Upload fehlgeschlagen';\n            };\n\n            const onSuccess = (data) => {\n                const placeholder = document.getElementById(tempId);\n                if (placeholder && data.row_html) {\n                    placeholder.outerHTML = data.row_html;\n                    if (uploadRows) htmx.process(uploadRows);\n                }\n            };\n\n            const onDone = () => {\n                URL.revokeObjectURL(previewUrl);\n                this.pendingUploads--;\n            };\n\n            doUpload()\n            .then(onSuccess)\n            .catch(error => {\n                // Auto-retry once for transient errors (e.g. iOS Safari after photo picker)\n                if (error instanceof TypeError) {\n                    return new Promise(r => setTimeout(r, 500))\n                        .then(doUpload)\n                        .then(onSuccess)\n                        .catch(e => showError(friendlyMsg(e)));\n                }\n                showError(friendlyMsg(error));\n            })\n            .finally(onDone);\n        },\n\n        // --- URL Import ---\n\n        async startScrape() {\n            const url = this.importUrl.trim();\n            if (!url) return;\n\n            this.scraping = true;\n            this.scrapedImages = [];\n            // Capture the ref now, before any await \u2014 `this.$refs` throws (_x_refs)\n            // if an hx-boost navigation tears the component down mid-scrape.\n            const scrapeResults = this.$refs.scrapeResults;\n            if (scrapeResults) scrapeResults.innerHTML = '';\n\n            const scrapeUrl = this.$root.dataset.scrapeUrl;\n            const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n\n            try {\n                const formData = new FormData();\n                formData.append('url', url);\n\n                const res = await fetch(scrapeUrl, {\n                    method: 'POST',\n                    headers: { 'X-CSRFToken': csrfToken },\n                    body: formData,\n                });\n\n                const html = await res.text();\n                if (scrapeResults) {\n                    scrapeResults.innerHTML = html;\n\n                    // Read image URLs and metadata from embedded JSON\n                    const dataEl = scrapeResults.querySelector('#scraped-image-data');\n                    if (dataEl) {\n                        try { this.scrapedImages = JSON.parse(dataEl.textContent); } catch(e) {}\n                    }\n                    const metaEl = scrapeResults.querySelector('#scraped-metadata');\n                    if (metaEl) {\n                        try { this.scrapedMetadata = JSON.parse(metaEl.textContent); } catch(e) {}\n                    }\n                }\n            } catch (e) {\n                if (scrapeResults) scrapeResults.innerHTML = '<p class=\"text-sm text-alert-error-foreground text-center py-4\">Verbindungsfehler. Bitte erneut versuchen.</p>';\n            } finally {\n                this.scraping = false;\n            }\n        },\n\n        resetUrlImport() {\n            this.scrapedImages = [];\n            this.scrapedMetadata = {};\n            this.importUrl = '';\n            this.scraping = false;\n            this.importing = false;\n            if (this.$refs.scrapeResults) this.$refs.scrapeResults.innerHTML = '';\n        },\n\n        async importSelectedUrls(selectedIndexes) {\n            if (this.importing) return;\n            const urls = selectedIndexes.map(i => this.scrapedImages[i]).filter(Boolean);\n            if (!urls.length) return;\n\n            this.importing = true;\n            this.hasUploads = true;\n            this.activeTab = 'device'; // Switch to show upload rows\n            // Capture refs now, before any await \u2014 `this.$refs` throws (_x_refs)\n            // if an hx-boost navigation tears the component down mid-import.\n            const scrapeResults = this.$refs.scrapeResults;\n            const uploadRows = this.$refs.uploadRows;\n            if (scrapeResults) scrapeResults.innerHTML = '';\n            this.scrapedImages = [];\n\n            const importUrl = this.$root.dataset.importUrl;\n            const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n\n            // Show pending placeholders\n            const tempIds = urls.map((_, i) => {\n                const tempId = 'import-' + Date.now() + '-' + i;\n                const html = '<div id=\"' + tempId + '\" class=\"flex items-center gap-4 p-3 bg-soft rounded-lg border border-border\">' +\n                    '<div class=\"w-16 h-12 bg-muted rounded flex items-center justify-center flex-shrink-0\">' +\n                    '<svg class=\"w-5 h-5 text-muted-foreground\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909M3.75 21h16.5\"/></svg>' +\n                    '</div>' +\n                    '<div class=\"flex-1 min-w-0\">' +\n                    '<p class=\"font-medium text-foreground text-sm\">Foto ' + (i + 1) + ' von ' + urls.length + '</p>' +\n                    '<div class=\"flex items-center gap-1.5 text-sm text-muted-foreground mt-0.5\">' +\n                    '<svg class=\"w-4 h-4 animate-spin\" fill=\"none\" viewBox=\"0 0 24 24\">' +\n                    '<circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>' +\n                    '<path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path>' +\n                    '</svg><span>Wird importiert...</span></div></div></div>';\n                if (uploadRows) uploadRows.insertAdjacentHTML('beforeend', html);\n                return tempId;\n            });\n\n            this.pendingUploads += urls.length;\n\n            try {\n                const res = await fetch(importUrl, {\n                    method: 'POST',\n                    headers: {\n                        'X-CSRFToken': csrfToken,\n                        'Content-Type': 'application/json',\n                    },\n                    body: JSON.stringify({ urls, metadata: this.scrapedMetadata }),\n                });\n\n                const data = await res.json();\n\n                // Replace placeholders with actual upload rows\n                (data.results || []).forEach((result, i) => {\n                    const placeholder = document.getElementById(tempIds[i]);\n                    if (placeholder && result.row_html) {\n                        placeholder.outerHTML = result.row_html;\n                    }\n                });\n\n                // Mark remaining placeholders as failed\n                const successCount = (data.results || []).length;\n                for (let i = successCount; i < tempIds.length; i++) {\n                    const placeholder = document.getElementById(tempIds[i]);\n                    if (placeholder) {\n                        placeholder.outerHTML = '<div class=\"flex items-center gap-4 p-3 bg-alert-error rounded-lg border border-alert-error-border\">' +\n                            '<div class=\"w-16 h-12 bg-alert-error rounded flex items-center justify-center flex-shrink-0\">' +\n                            '<svg class=\"w-5 h-5 text-alert-error-foreground\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">' +\n                            '<path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/></svg></div>' +\n                            '<div class=\"flex-1 min-w-0\"><p class=\"font-medium text-alert-error-foreground text-sm\">Import fehlgeschlagen</p></div></div>';\n                    }\n                }\n\n                if (uploadRows) htmx.process(uploadRows);\n            } catch (e) {\n                // Network error \u2014 mark all as failed\n                tempIds.forEach(id => {\n                    const el = document.getElementById(id);\n                    if (el) el.querySelector('span').textContent = 'Import fehlgeschlagen';\n                });\n            } finally {\n                this.pendingUploads -= urls.length;\n                this.importing = false;\n            }\n        },\n\n        escapeHtml(text) {\n            const div = document.createElement('div');\n            div.textContent = text;\n            return div.innerHTML;\n        },\n    }));\n\n});\n", "document.addEventListener('alpine:init', () => {\n\n    Alpine.data('onboarding', () => ({\n        open: true,\n        dragging: false,\n        uploading: false,\n        processing: false,\n        uploadStarted: false,\n        error: '',\n        errorInContent: false,\n        importUrl: '',\n        scraping: false,\n\n        close() {\n            this.open = false;\n            if (this.uploadStarted) window.location.reload();\n        },\n\n        openFilePicker() { this.$refs.fileInput?.click(); },\n\n        onFileSelect(e) {\n            if (e.target.files.length > 0) this.handleFile(e.target.files[0]);\n        },\n\n        onDrop(e) {\n            this.dragging = false;\n            if (e.dataTransfer.files.length > 0) this.handleFile(e.dataTransfer.files[0]);\n        },\n\n        handleFile(file) {\n            const validTypes = ['image/jpeg', 'image/png', 'image/webp'];\n            if (!validTypes.includes(file.type)) {\n                this.error = 'Bitte w\u00E4hlen Sie ein JPG, PNG oder WebP Bild.';\n                return;\n            }\n            if (file.size > 20 * 1024 * 1024) {\n                this.error = 'Die Datei ist zu gro\u00DF (max. 20 MB).';\n                return;\n            }\n            this.error = '';\n            this.uploadFile(file);\n        },\n\n        uploadFile(file) {\n            this.uploading = true;\n            const uploadUrl = this.$root.dataset.uploadUrl;\n            const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n            const formData = new FormData();\n            formData.append('photo', file);\n\n            fetch(uploadUrl, {\n                method: 'POST',\n                headers: { 'X-CSRFToken': csrfToken },\n                body: formData\n            })\n            .then(response => {\n                if (!response.ok) return response.json().then(data => { throw new Error(data.error || 'Upload fehlgeschlagen'); });\n                return response.json();\n            })\n            .then(data => {\n                if (data.success) {\n                    this.uploadStarted = true;\n                    this.processing = true;\n                    this.$nextTick(() => {\n                        const el = document.getElementById('onboarding-content');\n                        if (el) {\n                            el.innerHTML = data.html;\n                            if (typeof htmx !== 'undefined') htmx.process(el);\n                        }\n                    });\n                } else {\n                    this.showContentError(data.error || 'Upload fehlgeschlagen');\n                }\n            })\n            .catch(() => {\n                this.showContentError('Verbindungsfehler. Bitte versuchen Sie es erneut.');\n            });\n        },\n\n        async startUrlImport() {\n            const url = this.importUrl.trim();\n            if (!url) return;\n\n            this.error = '';\n            this.scraping = true;\n\n            const importUrl = this.$root.dataset.urlImportUrl;\n            const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n\n            const formData = new FormData();\n            formData.append('url', url);\n\n            try {\n                const response = await fetch(importUrl, {\n                    method: 'POST',\n                    headers: { 'X-CSRFToken': csrfToken },\n                    body: formData,\n                });\n\n                const data = await response.json();\n\n                if (data.success) {\n                    this.uploadStarted = true;\n                    this.processing = true;\n                    this.scraping = false;\n                    this.$nextTick(() => {\n                        const el = document.getElementById('onboarding-content');\n                        if (el) {\n                            el.innerHTML = data.html;\n                            if (typeof htmx !== 'undefined') htmx.process(el);\n                        }\n                    });\n                } else {\n                    this.scraping = false;\n                    if (data.limit_reached) {\n                        this.showContentError(data.error);\n                    } else {\n                        this.error = data.error || 'Import fehlgeschlagen';\n                    }\n                }\n            } catch (e) {\n                this.scraping = false;\n                this.error = 'Verbindungsfehler. Bitte versuchen Sie es erneut.';\n            }\n        },\n\n        showContentError(message) {\n            this.uploading = false;\n            this.scraping = false;\n            this.errorInContent = true;\n            this.error = message;\n        },\n\n        reset() { window.location.reload(); },\n    }));\n\n});\n", "document.addEventListener('alpine:init', () => {\n\n    Alpine.data('propertyCreate', () => ({\n        step: 'choice',  // choice | manual | url | scraping | results | importing\n        importUrl: '',\n        scraping: false,\n        importing: false,\n        scrapedImages: [],\n        scrapedMetadata: {},\n        propertyName: '',\n        importError: '',\n\n        get isOpen() { return !!Alpine.store('modal')?.is('property-create'); },\n\n        openModal() {\n            Alpine.store('modal')?.show('property-create');\n        },\n\n        closeModal() {\n            if (this.importing) return;\n            Alpine.store('modal')?.close();\n            this.reset();\n        },\n\n        reset() {\n            this.step = 'choice';\n            this.importUrl = '';\n            this.scraping = false;\n            this.importing = false;\n            this.scrapedImages = [];\n            this.scrapedMetadata = {};\n            this.propertyName = '';\n            this.importError = '';\n            if (this.$refs.scrapeResults) this.$refs.scrapeResults.innerHTML = '';\n        },\n\n        goManual() { this.step = 'manual'; },\n\n        goUrl() { this.step = 'url'; },\n\n        goBack() {\n            if (this.step === 'results') {\n                this.step = 'url';\n                this.scrapedImages = [];\n                this.scrapedMetadata = {};\n                this.propertyName = '';\n                this.importError = '';\n                if (this.$refs.scrapeResults) this.$refs.scrapeResults.innerHTML = '';\n            } else {\n                this.step = 'choice';\n            }\n        },\n\n        async startScrape() {\n            const url = this.importUrl.trim();\n            if (!url) return;\n\n            this.step = 'scraping';\n            this.scrapedImages = [];\n            this.importError = '';\n            // Capture the ref now, before any await. After an hx-boost navigation\n            // the component is torn down and `this.$refs` itself throws (_x_refs).\n            const scrapeResults = this.$refs.scrapeResults;\n            if (scrapeResults) scrapeResults.innerHTML = '';\n\n            const scrapeUrl = this.$root.dataset.scrapeUrl;\n            const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n\n            try {\n                const formData = new FormData();\n                formData.append('url', url);\n\n                const res = await fetch(scrapeUrl, {\n                    method: 'POST',\n                    headers: { 'X-CSRFToken': csrfToken },\n                    body: formData,\n                });\n\n                const html = await res.text();\n                if (scrapeResults) {\n                    scrapeResults.innerHTML = html;\n\n                    // Read image URLs from embedded JSON\n                    const dataEl = scrapeResults.querySelector('#scraped-image-data');\n                    if (dataEl) {\n                        try { this.scrapedImages = JSON.parse(dataEl.textContent); } catch(e) {}\n                    }\n\n                    // Read metadata\n                    const metaEl = scrapeResults.querySelector('#scraped-metadata');\n                    if (metaEl) {\n                        try { this.scrapedMetadata = JSON.parse(metaEl.textContent); } catch(e) {}\n                    }\n                }\n\n                // Prefill property name from metadata\n                if (this.scrapedMetadata.name) {\n                    this.propertyName = this.scrapedMetadata.name;\n                }\n\n                this.step = 'results';\n            } catch (e) {\n                if (scrapeResults) {\n                    scrapeResults.innerHTML = '<p class=\"text-sm text-alert-error-foreground text-center py-4\">Verbindungsfehler. Bitte erneut versuchen.</p>';\n                }\n                this.step = 'results';\n            }\n        },\n\n        resetScrape() {\n            this.scrapedImages = [];\n            this.scrapedMetadata = {};\n            this.propertyName = '';\n            this.importUrl = '';\n            this.importError = '';\n            if (this.$refs.scrapeResults) this.$refs.scrapeResults.innerHTML = '';\n            this.step = 'url';\n        },\n\n        async createWithImport(selectedIndexes) {\n            if (this.importing) return;\n\n            const name = this.propertyName.trim();\n            if (!name) {\n                this.importError = 'Name ist erforderlich';\n                return;\n            }\n\n            const urls = selectedIndexes.map(i => this.scrapedImages[i]).filter(Boolean);\n            if (!urls.length) return;\n\n            this.importError = '';\n            this.step = 'importing';\n            this.importing = true;\n\n            const createUrl = this.$root.dataset.createUrl;\n            const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n\n            try {\n                const res = await fetch(createUrl, {\n                    method: 'POST',\n                    headers: {\n                        'X-CSRFToken': csrfToken,\n                        'Content-Type': 'application/json',\n                    },\n                    body: JSON.stringify({ name, urls, metadata: this.scrapedMetadata }),\n                });\n\n                const data = await res.json();\n\n                if (!res.ok) {\n                    this.importError = data.error || 'Import fehlgeschlagen';\n                    this.step = 'results';\n                    this.importing = false;\n                    return;\n                }\n\n                // Redirect to new property\n                if (data.redirect_url) {\n                    window.location.href = data.redirect_url;\n                    return;\n                }\n            } catch (e) {\n                this.importError = 'Verbindungsfehler. Bitte erneut versuchen.';\n                this.step = 'results';\n            } finally {\n                this.importing = false;\n            }\n        },\n    }));\n\n});\n", "document.addEventListener('alpine:init', () => {\n\n    // Reusable address autocomplete via Google Places Autocomplete Data API\n    // Uses our own input + dropdown \u2014 no Google widget, no full-screen overlay on mobile\n    Alpine.data('addressAutocomplete', (initialStreet = '', initialPostalCode = '', initialCity = '', apiKey = '') => ({\n        street: initialStreet,\n        postalCode: initialPostalCode,\n        city: initialCity,\n        query: '',\n        suggestions: [],\n        showDropdown: false,\n        _debounceTimer: null,\n        _sessionToken: null,\n        _places: null,\n        _ready: false,\n        _els: null,\n\n        init() {\n            this.query = [this.street, this.postalCode, this.city].filter(Boolean).join(', ');\n            // Cache DOM refs now \u2014 they won't work after await in async methods\n            this._els = {\n                street: this.$refs.hiddenStreet,\n                postalCode: this.$refs.hiddenPostalCode,\n                city: this.$refs.hiddenCity,\n                root: this.$el,\n            };\n            if (apiKey) this._loadApi(apiKey);\n        },\n\n        async _loadApi(key) {\n            try {\n                // Dynamically load Google Maps API if not yet present.\n                // Done here instead of a <script> tag so it works with hx-boost navigation.\n                if (!window.google?.maps?.importLibrary) {\n                    await this._injectScript(key);\n                }\n                // Use the module reference from importLibrary directly to avoid\n                // instanceof mismatches when the API is loaded dynamically.\n                this._places = await google.maps.importLibrary('places');\n                this._sessionToken = new this._places.AutocompleteSessionToken();\n                this._ready = true;\n            } catch (e) {\n                console.error('Google Places API failed to load:', e);\n            }\n        },\n\n        _injectScript(key) {\n            // Deduplicate: reuse existing loading promise if another instance started it\n            if (window._gmapsLoading) return window._gmapsLoading;\n            window._gmapsLoading = new Promise((resolve, reject) => {\n                const cb = '__gmapsReady';\n                window[cb] = () => { delete window[cb]; resolve(); };\n                const s = document.createElement('script');\n                s.src = 'https://maps.googleapis.com/maps/api/js?key=' + key + '&loading=async&callback=' + cb;\n                s.async = true;\n                s.onerror = () => { window._gmapsLoading = null; reject(new Error('Google Maps script failed')); };\n                document.head.appendChild(s);\n            });\n            return window._gmapsLoading;\n        },\n\n        onInput() {\n            const q = this.query.trim();\n            if (q.length < 3 || !this._ready) {\n                this.suggestions = [];\n                this.showDropdown = false;\n                return;\n            }\n            clearTimeout(this._debounceTimer);\n            this._debounceTimer = setTimeout(() => this._fetchSuggestions(q), 250);\n        },\n\n        async _fetchSuggestions(input) {\n            try {\n                const { suggestions } = await this._places.AutocompleteSuggestion.fetchAutocompleteSuggestions({\n                    input,\n                    sessionToken: this._sessionToken,\n                    region: 'de',\n                    includedPrimaryTypes: ['street_address', 'route', 'premise', 'subpremise'],\n                    language: 'de',\n                });\n                this.suggestions = suggestions.map(s => ({\n                    text: s.placePrediction.text.text,\n                    mainText: s.placePrediction.mainText?.text || s.placePrediction.text.text,\n                    secondaryText: s.placePrediction.secondaryText?.text || '',\n                    place: s.placePrediction.toPlace(),\n                }));\n                this.showDropdown = this.suggestions.length > 0;\n            } catch (e) {\n                console.error('Address autocomplete error:', e);\n                this.suggestions = [];\n                this.showDropdown = false;\n            }\n        },\n\n        async selectSuggestion(suggestion) {\n            this.query = suggestion.text;\n            this.showDropdown = false;\n            this.suggestions = [];\n\n            try {\n                const place = suggestion.place;\n                await place.fetchFields({ fields: ['addressComponents'] });\n                if (place.addressComponents) {\n                    this._parsePlaceComponents(place.addressComponents);\n                } else {\n                    this.street = suggestion.mainText;\n                    this._syncAndNotify();\n                }\n            } catch (e) {\n                this.street = suggestion.mainText;\n                this._syncAndNotify();\n            }\n\n            this._sessionToken = new this._places.AutocompleteSessionToken();\n        },\n\n        onBlur() {\n            setTimeout(() => { this.showDropdown = false; }, 200);\n        },\n\n        _parsePlaceComponents(components) {\n            let route = '';\n            let streetNumber = '';\n            this.postalCode = '';\n            this.city = '';\n\n            for (const component of components) {\n                const type = component.types[0];\n                if (type === 'route') route = component.longText;\n                else if (type === 'street_number') streetNumber = component.longText;\n                else if (type === 'postal_code') this.postalCode = component.longText;\n                else if (type === 'locality') this.city = component.longText;\n                else if (type === 'sublocality_level_1' && !this.city) this.city = component.longText;\n            }\n\n            this.street = streetNumber ? `${route} ${streetNumber}` : route;\n            this.query = [this.street, this.postalCode, this.city].filter(Boolean).join(', ');\n            this._syncAndNotify();\n        },\n\n        _syncAndNotify() {\n            if (this._els.street) this._els.street.value = this.street;\n            if (this._els.postalCode) this._els.postalCode.value = this.postalCode;\n            if (this._els.city) this._els.city.value = this.city;\n\n            // Root may be detached if an hx-boost navigation tore the component\n            // down while a Places callback was in flight \u2014 guard the dispatch.\n            if (this._els.root && this._els.root.isConnected) {\n                this._els.root.dispatchEvent(new CustomEvent('address-changed', { bubbles: true }));\n            }\n        },\n    }));\n\n});\n", "document.addEventListener('alpine:init', () => {\n\n    Alpine.data('listingForm', function() {\n        return {\n            listingType: '',\n            propertyType: '',\n            hasParking: false,\n            hasProvision: false,\n            energyValue: '',\n            energySources: [],\n            energySourceLabels: {},\n            counts: {},\n            saleFields: ['property_type', 'condition', 'construction_year', 'street', 'living_area', 'rooms', 'price', 'buyer_commission', 'energy_cert_type', 'energy_value', 'energy_source', 'heating_type'],\n            rentalFields: ['property_type', 'condition', 'construction_year', 'street', 'living_area', 'rooms', 'cold_rent', 'utilities', 'deposit', 'energy_cert_type', 'energy_value', 'energy_source', 'heating_type'],\n            sections: {\n                basisdaten: ['property_type', 'condition', 'construction_year'],\n                adresse: ['street'],\n                flaechen: ['living_area', 'rooms'],\n                finanzen_sale: ['price', 'buyer_commission'],\n                finanzen_rental: ['cold_rent', 'utilities', 'deposit'],\n                energie: ['energy_cert_type', 'energy_value', 'energy_source', 'heating_type']\n            },\n            _saveTimer: null,\n            saveStatus: '',\n            _saveUrl: '',\n\n            init() {\n                const d = this.$el.dataset;\n                this.listingType = d.listingType || 'sale';\n                this.propertyType = d.propertyType || '';\n                this.hasParking = d.hasParking === 'true';\n                this.hasProvision = d.hasProvision === 'true';\n                this.energyValue = d.energyValue || '';\n                this._saveUrl = d.saveUrl || '';\n\n                try { this.energySources = JSON.parse(d.energySources || '[]'); } catch(e) { this.energySources = []; }\n                try { this.energySourceLabels = JSON.parse(d.energySourceLabels || '{}'); } catch(e) { this.energySourceLabels = {}; }\n\n                this.$nextTick(() => this.updateAll());\n            },\n\n            updateAll() {\n                for (const [key, fields] of Object.entries(this.sections)) {\n                    if (key === 'finanzen_sale' || key === 'finanzen_rental') continue;\n                    this.counts[key] = this._count(fields);\n                }\n                const finKey = this.listingType === 'sale' ? 'finanzen_sale' : 'finanzen_rental';\n                this.counts.finanzen = this._count(this.sections[finKey]);\n            },\n\n            _count(fields) {\n                let filled = 0;\n                for (const f of fields) {\n                    if (f === 'energy_source') { if (this.energySources.length > 0) filled++; continue; }\n                    const el = this.$el.querySelector('[name=\"' + f + '\"]');\n                    if (el && el.value && el.value.trim() !== '') filled++;\n                }\n                return { filled, total: fields.length };\n            },\n\n            filled(s) { return this.counts[s]?.filled || 0; },\n            total(s) { return this.counts[s]?.total || 0; },\n            pct(s) { const t = this.total(s); return t > 0 ? Math.round(this.filled(s) / t * 100) : 0; },\n            colorClass(s) { const p = this.pct(s); return p === 100 ? 'text-emerald-600' : p > 0 ? 'text-amber-600' : 'text-muted-foreground'; },\n            strokeClass(s) { const p = this.pct(s); return p === 100 ? 'stroke-emerald-500' : p > 0 ? 'stroke-amber-500' : 'stroke-muted-foreground/30'; },\n\n            computedWarmRent() {\n                const cold = parseFloat((this.$el.querySelector('[name=\"cold_rent\"]')?.value || '').replace(/\\./g, '').replace(',', '.'));\n                const util = parseFloat((this.$el.querySelector('[name=\"utilities\"]')?.value || '').replace(/\\./g, '').replace(',', '.'));\n                if (!isNaN(cold) && !isNaN(util)) return (cold + util).toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 2});\n                if (!isNaN(cold)) return cold.toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 2});\n                return '';\n            },\n\n            computedEnergyClass() {\n                const raw = (this.energyValue || '').replace(/\\./g, '').replace(',', '.');\n                const val = parseFloat(raw);\n                if (isNaN(val)) return '';\n                if (val <= 30) return 'A+';\n                if (val <= 50) return 'A';\n                if (val <= 75) return 'B';\n                if (val <= 100) return 'C';\n                if (val <= 130) return 'D';\n                if (val <= 160) return 'E';\n                if (val <= 200) return 'F';\n                if (val <= 250) return 'G';\n                return 'H';\n            },\n\n            autoSave() {\n                clearTimeout(this._saveTimer);\n                this._saveTimer = setTimeout(() => this._doSave(), 1500);\n            },\n\n            async _doSave() {\n                this.saveStatus = 'saving';\n                try {\n                    const formData = new FormData(this.$el);\n                    const res = await fetch(this._saveUrl, {\n                        method: 'POST',\n                        headers: {\n                            'X-Auto-Save': '1',\n                            'X-CSRFToken': formData.get('csrfmiddlewaretoken'),\n                        },\n                        body: formData,\n                    });\n                    const data = await res.json();\n                    this.saveStatus = data.ok ? 'saved' : '';\n                } catch {\n                    this.saveStatus = '';\n                }\n                if (this.saveStatus === 'saved') {\n                    setTimeout(() => { if (this.saveStatus === 'saved') this.saveStatus = ''; }, 2000);\n                }\n            }\n        };\n    });\n\n});\n", "/**\n * Shared Alpine.js component for public upload forms.\n * Used by: free tool, foto check, landing pages.\n *\n * Config via data attributes on the x-data element:\n *   data-upload-url    \u2014 POST endpoint for the upload\n *   data-prefill-email \u2014 optional pre-filled email\n *   data-require-consent \u2014 if present, consent checkbox is required\n */\ndocument.addEventListener('alpine:init', () => {\n    Alpine.data('publicUpload', function() {\n        return {\n            step: 1,\n            dragOver: false,\n            file: null,\n            fileName: '',\n            fileSize: '',\n            previewUrl: '',\n            email: '',\n            consent: false,\n            error: '',\n            submitting: false,\n\n            init() {\n                this.email = this.$root.dataset.prefillEmail || '';\n            },\n\n            handleFileSelect(event) {\n                const file = event.target.files[0];\n                if (file) this.selectFile(file);\n            },\n\n            handleDrop(event) {\n                this.dragOver = false;\n                const file = event.dataTransfer.files[0];\n                if (file) this.selectFile(file);\n            },\n\n            selectFile(file) {\n                const validTypes = ['image/jpeg', 'image/png', 'image/webp'];\n                if (!validTypes.includes(file.type)) {\n                    this.error = 'Ung\u00FCltiges Dateiformat. Bitte verwenden Sie JPG, PNG oder WebP.';\n                    return;\n                }\n                if (file.size > 20 * 1024 * 1024) {\n                    this.error = 'Datei zu gro\u00DF (max. 20 MB).';\n                    return;\n                }\n\n                this.file = file;\n                this.fileName = file.name;\n                this.fileSize = (file.size / (1024 * 1024)).toFixed(1) + ' MB';\n                this.previewUrl = URL.createObjectURL(file);\n                this.error = '';\n                this.step = 2;\n            },\n\n            reset() {\n                if (this.previewUrl) URL.revokeObjectURL(this.previewUrl);\n                this.step = 1;\n                this.file = null;\n                this.fileName = '';\n                this.fileSize = '';\n                this.previewUrl = '';\n                this.error = '';\n                this.consent = false;\n                const fileInput = this.$root.querySelector('input[type=file]');\n                if (fileInput) fileInput.value = '';\n            },\n\n            async submit() {\n                if (this.$root.dataset.requireConsent !== undefined && !this.consent) {\n                    this.error = 'Bitte stimmen Sie der \u00F6ffentlichen Anzeige zu.';\n                    return;\n                }\n\n                this.error = '';\n                this.submitting = true;\n\n                const formData = new FormData();\n                formData.append('image', this.file);\n                formData.append('email', this.email);\n\n                if (this.consent) {\n                    formData.append('consent_public', 'on');\n                }\n\n                // Turnstile token\n                const turnstileInput = this.$root.querySelector('[name=\"cf-turnstile-response\"]');\n                if (turnstileInput) {\n                    formData.append('cf-turnstile-response', turnstileInput.value);\n                }\n\n                const csrfToken = document.querySelector('meta[name=\"csrf-token\"]').content;\n                const uploadUrl = this.$root.dataset.uploadUrl;\n\n                try {\n                    const response = await fetch(uploadUrl, {\n                        method: 'POST',\n                        headers: { 'X-CSRFToken': csrfToken },\n                        body: formData,\n                    });\n\n                    const data = await response.json();\n\n                    if (!response.ok) {\n                        this.error = data.error || 'Ein Fehler ist aufgetreten.';\n                        const widget = this.$root.querySelector('.cf-turnstile');\n                        if (widget && typeof turnstile !== 'undefined') {\n                            turnstile.reset(widget);\n                        }\n                        this.submitting = false;\n                        return;\n                    }\n\n                    window.location.href = data.redirect_url;\n                } catch (e) {\n                    this.error = 'Verbindungsfehler. Bitte versuchen Sie es erneut.';\n                    this.submitting = false;\n                }\n            }\n        };\n    });\n});\n"],
  "mappings": "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",
  "names": ["json", "id", "prefsJson", "prefs", "sel", "subtype", "tab", "v", "k", "presets", "input", "selected", "p", "self", "event", "gate", "prefs", "id", "checked", "checkbox", "sectionKey", "selector", "cb", "checkboxes", "selectedCount", "params", "_a", "url", "csrf", "formData", "err", "_a", "files", "file", "tempId", "previewUrl", "uploadUrl", "csrfToken", "uploadRows", "placeholderHtml", "doUpload", "formData", "response", "data", "showError", "msg", "placeholder", "retryId", "retryBtn", "row", "onSuccess", "e", "friendlyMsg", "onDone", "error", "r", "url", "scrapeResults", "scrapeUrl", "html", "dataEl", "metaEl", "selectedIndexes", "urls", "i", "importUrl", "tempIds", "_", "result", "successCount", "id", "el", "text", "div", "_a", "file", "uploadUrl", "csrfToken", "formData", "response", "data", "el", "url", "importUrl", "message", "_a", "url", "scrapeResults", "scrapeUrl", "csrfToken", "formData", "html", "dataEl", "metaEl", "selectedIndexes", "name", "urls", "createUrl", "res", "data", "initialStreet", "initialPostalCode", "initialCity", "apiKey", "key", "_a", "_b", "e", "resolve", "reject", "cb", "s", "q", "input", "suggestions", "suggestion", "place", "components", "route", "streetNumber", "component", "type", "d", "key", "fields", "finKey", "filled", "f", "el", "s", "_a", "p", "_b", "cold", "util", "raw", "val", "formData", "data", "event", "file", "fileInput", "formData", "turnstileInput", "csrfToken", "uploadUrl", "response", "data", "widget"]
}
