/**
 * KundenKarte Module JavaScript
 * Copyright (C) 2026 Alles Watt lauft
 */

(function() {
    'use strict';

    // Namespace
    window.KundenKarte = window.KundenKarte || {};

    // ===========================================
    // Global Dialog Functions (replacing browser dialogs)
    // ===========================================

    // Escape HTML helper
    function escapeHtml(text) {
        if (!text) return '';
        var div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    // Global alert dialog
    KundenKarte.showAlert = function(title, message, onClose) {
        $('#kundenkarte-alert-dialog').remove();

        var html = '<div id="kundenkarte-alert-dialog" class="kundenkarte-modal">';
        html += '<div class="kundenkarte-modal-content" style="max-width:400px;">';
        html += '<div class="kundenkarte-modal-header"><h3>' + escapeHtml(title) + '</h3>';
        html += '<span class="kundenkarte-modal-close">&times;</span></div>';
        html += '<div class="kundenkarte-modal-body" style="padding:20px;">';
        html += '<p style="margin:0;font-size:14px;">' + escapeHtml(message) + '</p>';
        html += '</div>';
        html += '<div class="kundenkarte-modal-footer" style="display:flex;justify-content:flex-end;">';
        html += '<button type="button" class="button" id="alert-ok"><i class="fa fa-check"></i> OK</button>';
        html += '</div>';
        html += '</div></div>';

        $('body').append(html);
        $('#kundenkarte-alert-dialog').addClass('visible');
        $('#alert-ok').focus();

        var closeDialog = function() {
            $('#kundenkarte-alert-dialog').remove();
            $(document).off('keydown.alertDialog');
            if (typeof onClose === 'function') onClose();
        };

        $('#alert-ok, #kundenkarte-alert-dialog .kundenkarte-modal-close').on('click', closeDialog);
        $(document).on('keydown.alertDialog', function(e) {
            if (e.key === 'Escape' || e.key === 'Enter') closeDialog();
        });
    };

    // Global confirm dialog
    KundenKarte.showConfirm = function(title, message, onConfirm, onCancel) {
        $('#kundenkarte-confirm-dialog').remove();

        var html = '<div id="kundenkarte-confirm-dialog" class="kundenkarte-modal">';
        html += '<div class="kundenkarte-modal-content" style="max-width:400px;">';
        html += '<div class="kundenkarte-modal-header"><h3>' + escapeHtml(title) + '</h3>';
        html += '<span class="kundenkarte-modal-close">&times;</span></div>';
        html += '<div class="kundenkarte-modal-body" style="padding:20px;">';
        html += '<p style="margin:0;font-size:14px;">' + escapeHtml(message) + '</p>';
        html += '</div>';
        html += '<div class="kundenkarte-modal-footer" style="display:flex;gap:10px;justify-content:flex-end;">';
        html += '<button type="button" class="button" id="confirm-yes" style="background:#c0392b;color:#fff;"><i class="fa fa-check"></i> Ja</button>';
        html += '<button type="button" class="button" id="confirm-no"><i class="fa fa-times"></i> Nein</button>';
        html += '</div>';
        html += '</div></div>';

        $('body').append(html);
        $('#kundenkarte-confirm-dialog').addClass('visible');
        $('#confirm-yes').focus();

        $('#confirm-yes').on('click', function() {
            $('#kundenkarte-confirm-dialog').remove();
            $(document).off('keydown.confirmDialog');
            if (typeof onConfirm === 'function') onConfirm();
        });

        $('#confirm-no, #kundenkarte-confirm-dialog .kundenkarte-modal-close').on('click', function() {
            $('#kundenkarte-confirm-dialog').remove();
            $(document).off('keydown.confirmDialog');
            if (typeof onCancel === 'function') onCancel();
        });

        $(document).on('keydown.confirmDialog', function(e) {
            if (e.key === 'Escape') {
                $('#kundenkarte-confirm-dialog').remove();
                $(document).off('keydown.confirmDialog');
                if (typeof onCancel === 'function') onCancel();
            } else if (e.key === 'Enter') {
                $('#kundenkarte-confirm-dialog').remove();
                $(document).off('keydown.confirmDialog');
                if (typeof onConfirm === 'function') onConfirm();
            }
        });
    };

    // Global error display with details
    KundenKarte.showError = function(title, message, details) {
        $('#kundenkarte-error-dialog').remove();

        var html = '<div id="kundenkarte-error-dialog" class="kundenkarte-modal">';
        html += '<div class="kundenkarte-modal-content" style="max-width:450px;">';
        html += '<div class="kundenkarte-modal-header" style="background:#c0392b;"><h3 style="color:#fff;"><i class="fa fa-exclamation-triangle"></i> ' + escapeHtml(title || 'Fehler') + '</h3>';
        html += '<span class="kundenkarte-modal-close" style="color:#fff;">&times;</span></div>';
        html += '<div class="kundenkarte-modal-body" style="padding:20px;">';
        html += '<p style="margin:0 0 10px 0;font-size:14px;">' + escapeHtml(message || 'Ein unbekannter Fehler ist aufgetreten.') + '</p>';
        if (details) {
            html += '<details style="margin-top:10px;"><summary style="cursor:pointer;color:#888;font-size:12px;">Technische Details</summary>';
            html += '<pre style="background:#f5f5f5;padding:10px;margin-top:5px;font-size:11px;overflow:auto;max-height:150px;border-radius:4px;">' + escapeHtml(details) + '</pre>';
            html += '</details>';
        }
        html += '</div>';
        html += '<div class="kundenkarte-modal-footer" style="display:flex;justify-content:flex-end;">';
        html += '<button type="button" class="button" id="error-ok"><i class="fa fa-check"></i> OK</button>';
        html += '</div>';
        html += '</div></div>';

        $('body').append(html);
        $('#kundenkarte-error-dialog').addClass('visible');
        $('#error-ok').focus();

        var closeDialog = function() {
            $('#kundenkarte-error-dialog').remove();
            $(document).off('keydown.errorDialog');
        };

        $('#error-ok, #kundenkarte-error-dialog .kundenkarte-modal-close').on('click', closeDialog);
        $(document).on('keydown.errorDialog', function(e) {
            if (e.key === 'Escape' || e.key === 'Enter') closeDialog();
        });
    };

    // Global success/info notification (non-blocking)
    KundenKarte.showNotification = function(message, type) {
        type = type || 'success';
        var bgColor = type === 'success' ? '#27ae60' : (type === 'warning' ? '#f39c12' : (type === 'error' ? '#e74c3c' : '#3498db'));
        var icon = type === 'success' ? 'fa-check' : (type === 'warning' ? 'fa-exclamation' : (type === 'error' ? 'fa-times' : 'fa-info'));

        var $note = $('<div class="kundenkarte-notification" style="position:fixed;top:20px;right:20px;background:' + bgColor + ';color:#fff;padding:12px 20px;border-radius:6px;z-index:100003;box-shadow:0 4px 12px rgba(0,0,0,0.3);max-width:400px;"><i class="fa ' + icon + '" style="margin-right:8px;"></i>' + escapeHtml(message) + '</div>');
        $('body').append($note);

        setTimeout(function() {
            $note.fadeOut(300, function() { $(this).remove(); });
        }, 3000);
    };

    // Get base URL for AJAX calls
    var baseUrl = (typeof DOL_URL_ROOT !== 'undefined') ? DOL_URL_ROOT : '';
    if (!baseUrl) {
        // Try to detect from script src
        var scripts = document.getElementsByTagName('script');
        for (var i = 0; i < scripts.length; i++) {
            var src = scripts[i].src;
            if (src && src.indexOf('/kundenkarte/js/kundenkarte.js') > -1) {
                baseUrl = src.replace('/custom/kundenkarte/js/kundenkarte.js', '').replace(/\?.*$/, '');
                break;
            }
        }
    }

    /**
     * Tree Component
     */
    KundenKarte.Tree = {
        tooltipTimeout: null,
        hideTimeout: null,
        currentTooltip: null,
        currentItem: null,
        draggedNode: null,
        isDragging: false,
        dropTarget: null,

        init: function() {
            this.bindEvents();
            this.initDragDrop();
            this.initCompactMode();
        },

        bindEvents: function() {
            var self = this;

            // Toggle tree nodes - MUST use stopImmediatePropagation for delegated handlers on same element
            $(document).on('click', '.kundenkarte-tree-toggle', function(e) {
                e.preventDefault();
                e.stopPropagation();
                e.stopImmediatePropagation();

                var $toggle = $(this);
                var $node = $toggle.closest('.kundenkarte-tree-node');
                var $children = $node.children('.kundenkarte-tree-children');

                $toggle.toggleClass('collapsed');
                $children.toggleClass('collapsed');
            });

            // Expand all nodes
            $(document).on('click', '#btn-expand-all', function(e) {
                e.preventDefault();
                self.expandAll();
            });

            // Collapse all nodes
            $(document).on('click', '#btn-collapse-all', function(e) {
                e.preventDefault();
                self.collapseAll();
            });

            // Compact mode toggle
            $(document).on('click', '#btn-compact-mode', function(e) {
                e.preventDefault();
                self.toggleCompactMode();
            });

            // In compact mode, click on item to expand/show details
            $(document).on('click', '.kundenkarte-tree.compact-mode .kundenkarte-tree-item', function(e) {
                // Don't trigger on action buttons or toggle
                if ($(e.target).closest('.kundenkarte-tree-actions, .kundenkarte-tree-toggle, .kundenkarte-tree-files').length) {
                    return;
                }
                $(this).toggleClass('expanded');
            });

            // Hover tooltip on ICON only - show after delay
            $(document).on('mouseenter', '.kundenkarte-tooltip-trigger', function(e) {
                var $trigger = $(this);
                var anlageId = $trigger.data('anlage-id');

                if (!anlageId) return;

                // Cancel any pending hide
                clearTimeout(self.hideTimeout);
                self.hideTimeout = null;

                self.currentItem = $trigger;

                self.tooltipTimeout = setTimeout(function() {
                    self.showTooltip($trigger, anlageId);
                }, 300);
            });

            // Hide tooltip when leaving icon
            $(document).on('mouseleave', '.kundenkarte-tooltip-trigger', function() {
                clearTimeout(self.tooltipTimeout);
                self.tooltipTimeout = null;
                self.currentItem = null;

                // Hide after short delay (allows moving to tooltip)
                self.hideTimeout = setTimeout(function() {
                    self.hideTooltip();
                }, 100);
            });

            // Images tooltip on hover
            $(document).on('mouseenter', '.kundenkarte-images-trigger', function(e) {
                var $trigger = $(this);
                var anlageId = $trigger.data('anlage-id');

                if (!anlageId) return;

                clearTimeout(self.hideTimeout);
                self.hideTimeout = null;

                self.tooltipTimeout = setTimeout(function() {
                    self.showImagesPopup($trigger, anlageId);
                }, 300);
            });

            $(document).on('mouseleave', '.kundenkarte-images-trigger', function() {
                clearTimeout(self.tooltipTimeout);
                self.tooltipTimeout = null;

                self.hideTimeout = setTimeout(function() {
                    self.hideTooltip();
                }, 100);
            });

            // Documents tooltip on hover
            $(document).on('mouseenter', '.kundenkarte-docs-trigger', function(e) {
                var $trigger = $(this);
                var anlageId = $trigger.data('anlage-id');

                if (!anlageId) return;

                clearTimeout(self.hideTimeout);
                self.hideTimeout = null;

                self.tooltipTimeout = setTimeout(function() {
                    self.showDocsPopup($trigger, anlageId);
                }, 300);
            });

            $(document).on('mouseleave', '.kundenkarte-docs-trigger', function() {
                clearTimeout(self.tooltipTimeout);
                self.tooltipTimeout = null;

                self.hideTimeout = setTimeout(function() {
                    self.hideTooltip();
                }, 100);
            });

            // File badge tooltip on hover (combined images + documents)
            $(document).on('mouseenter', '.kundenkarte-tree-file-badge', function(e) {
                var $trigger = $(this);
                var anlageId = $trigger.data('anlage-id');

                if (!anlageId) return;

                clearTimeout(self.hideTimeout);
                self.hideTimeout = null;

                self.tooltipTimeout = setTimeout(function() {
                    self.showFilePreview($trigger, anlageId);
                }, 300);
            });

            $(document).on('mouseleave', '.kundenkarte-tree-file-badge', function() {
                clearTimeout(self.tooltipTimeout);
                self.tooltipTimeout = null;

                self.hideTimeout = setTimeout(function() {
                    self.hideTooltip();
                }, 100);
            });

            // Keep tooltip visible when hovering over it
            $(document).on('mouseenter', '#kundenkarte-tooltip', function() {
                clearTimeout(self.hideTimeout);
                self.hideTimeout = null;
            });

            // Hide when leaving tooltip
            $(document).on('mouseleave', '#kundenkarte-tooltip', function() {
                self.hideTooltip();
            });

            // Select item
            $(document).on('click', '.kundenkarte-tree-item', function(e) {
                if ($(e.target).closest('.kundenkarte-tree-toggle, .kundenkarte-tree-actions, .kundenkarte-tree-files').length) {
                    return;
                }

                $('.kundenkarte-tree-item').removeClass('selected');
                $(this).addClass('selected');

                var anlageId = $(this).data('anlage-id');
                if (anlageId) {
                    $(document).trigger('kundenkarte:element:selected', [anlageId]);
                }
            });
        },

        showTooltip: function($item, anlageId) {
            var self = this;

            // Get tooltip data from data attribute (faster than AJAX)
            var tooltipDataStr = $item.attr('data-tooltip');
            if (!tooltipDataStr) {
                console.log('No tooltip data for anlage', anlageId);
                return;
            }

            var data;
            try {
                data = JSON.parse(tooltipDataStr);
            } catch(e) {
                console.error('Failed to parse tooltip JSON:', e, tooltipDataStr);
                return;
            }

            var html = self.buildTooltipHtml(data);
            var $tooltip = $('#kundenkarte-tooltip');

            if (!$tooltip.length) {
                $tooltip = $('<div id="kundenkarte-tooltip" class="kundenkarte-tooltip"></div>');
                $('body').append($tooltip);
            }

            $tooltip.html(html);

            // Position tooltip
            var offset = $item.offset();
            var itemWidth = $item.outerWidth();
            var windowWidth = $(window).width();
            var scrollTop = $(window).scrollTop();

            // First show to calculate width
            $tooltip.css({ visibility: 'hidden', display: 'block' });
            var tooltipWidth = $tooltip.outerWidth();
            var tooltipHeight = $tooltip.outerHeight();
            $tooltip.css({ visibility: '', display: '' });

            var left = offset.left + itemWidth + 10;
            if (left + tooltipWidth > windowWidth - 20) {
                left = offset.left - tooltipWidth - 10;
            }
            if (left < 10) {
                left = 10;
            }

            var top = offset.top;
            // Prevent tooltip from going below viewport
            if (top + tooltipHeight > scrollTop + $(window).height() - 20) {
                top = scrollTop + $(window).height() - tooltipHeight - 20;
            }

            $tooltip.css({
                top: top,
                left: left
            }).addClass('visible').show();

            self.currentTooltip = $tooltip;
        },

        hideTooltip: function() {
            clearTimeout(this.hideTimeout);
            this.hideTimeout = null;
            var $tooltip = $('#kundenkarte-tooltip');
            if ($tooltip.length) {
                $tooltip.removeClass('visible').hide();
            }
            this.currentTooltip = null;
        },

        showImagesPopup: function($trigger, anlageId) {
            var self = this;

            // Load images via AJAX - use absolute path
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/anlage_images.php',
                data: { anlage_id: anlageId },
                dataType: 'json',
                success: function(response) {
                    if (!response.images || response.images.length === 0) {
                        return;
                    }

                    var html = '<div class="kundenkarte-images-popup">';
                    html += '<div class="kundenkarte-images-grid">';
                    for (var i = 0; i < response.images.length; i++) {
                        var img = response.images[i];
                        html += '<a href="' + img.url + '" target="_blank" class="kundenkarte-images-thumb">';
                        html += '<img src="' + img.thumb + '" alt="' + self.escapeHtml(img.name) + '">';
                        html += '</a>';
                    }
                    html += '</div>';
                    html += '</div>';

                    var $tooltip = $('#kundenkarte-tooltip');
                    if (!$tooltip.length) {
                        $tooltip = $('<div id="kundenkarte-tooltip" class="kundenkarte-tooltip"></div>');
                        $('body').append($tooltip);
                    }

                    $tooltip.html(html);

                    // Position tooltip
                    var offset = $trigger.offset();
                    var windowWidth = $(window).width();
                    var scrollTop = $(window).scrollTop();

                    $tooltip.css({ visibility: 'hidden', display: 'block' });
                    var tooltipWidth = $tooltip.outerWidth();
                    var tooltipHeight = $tooltip.outerHeight();
                    $tooltip.css({ visibility: '', display: '' });

                    var left = offset.left + $trigger.outerWidth() + 10;
                    if (left + tooltipWidth > windowWidth - 20) {
                        left = offset.left - tooltipWidth - 10;
                    }
                    if (left < 10) left = 10;

                    var top = offset.top;
                    if (top + tooltipHeight > scrollTop + $(window).height() - 20) {
                        top = scrollTop + $(window).height() - tooltipHeight - 20;
                    }

                    $tooltip.css({ top: top, left: left }).addClass('visible').show();
                    self.currentTooltip = $tooltip;
                }
            });
        },

        showDocsPopup: function($trigger, anlageId) {
            var self = this;

            // Load documents via AJAX
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/anlage_docs.php',
                data: { anlage_id: anlageId },
                dataType: 'json',
                success: function(response) {
                    if (!response.docs || response.docs.length === 0) {
                        return;
                    }

                    // Visual document cards with icons
                    var html = '<div class="kundenkarte-docs-popup">';
                    html += '<div class="kundenkarte-docs-grid">';
                    for (var i = 0; i < response.docs.length; i++) {
                        var doc = response.docs[i];
                        var iconClass = doc.type === 'pdf' ? 'fa-file-pdf-o' : 'fa-file-text-o';
                        var iconColor = doc.type === 'pdf' ? '#e74c3c' : '#f39c12';
                        html += '<a href="' + doc.url + '" target="_blank" class="kundenkarte-docs-card">';
                        html += '<div class="kundenkarte-docs-card-icon" style="color:' + iconColor + '">';
                        html += '<i class="fa ' + iconClass + '"></i>';
                        html += '</div>';
                        html += '<div class="kundenkarte-docs-card-name">' + self.escapeHtml(doc.name) + '</div>';
                        html += '</a>';
                    }
                    html += '</div>';
                    html += '</div>';

                    var $tooltip = $('#kundenkarte-tooltip');
                    if (!$tooltip.length) {
                        $tooltip = $('<div id="kundenkarte-tooltip" class="kundenkarte-tooltip"></div>');
                        $('body').append($tooltip);
                    }

                    $tooltip.html(html);

                    // Position tooltip
                    var offset = $trigger.offset();
                    var windowWidth = $(window).width();
                    var scrollTop = $(window).scrollTop();

                    $tooltip.css({ visibility: 'hidden', display: 'block' });
                    var tooltipWidth = $tooltip.outerWidth();
                    var tooltipHeight = $tooltip.outerHeight();
                    $tooltip.css({ visibility: '', display: '' });

                    var left = offset.left + $trigger.outerWidth() + 10;
                    if (left + tooltipWidth > windowWidth - 20) {
                        left = offset.left - tooltipWidth - 10;
                    }
                    if (left < 10) left = 10;

                    var top = offset.top;
                    if (top + tooltipHeight > scrollTop + $(window).height() - 20) {
                        top = scrollTop + $(window).height() - tooltipHeight - 20;
                    }

                    $tooltip.css({ top: top, left: left }).addClass('visible').show();
                    self.currentTooltip = $tooltip;
                }
            });
        },

        showFilePreview: function($trigger, anlageId) {
            var self = this;

            // Load all files via AJAX
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/file_preview.php',
                data: { anlage_id: anlageId },
                dataType: 'json',
                success: function(response) {
                    if ((!response.images || response.images.length === 0) &&
                        (!response.documents || response.documents.length === 0)) {
                        return;
                    }

                    var html = '<div class="kundenkarte-file-preview">';

                    // Images section with thumbnails
                    if (response.images && response.images.length > 0) {
                        html += '<div class="kundenkarte-file-preview-section">';
                        html += '<div class="kundenkarte-file-preview-title"><i class="fa fa-image"></i> Bilder (' + response.images.length + ')</div>';
                        html += '<div class="kundenkarte-file-preview-thumbs">';
                        for (var i = 0; i < response.images.length && i < 6; i++) {
                            var img = response.images[i];
                            var pinnedClass = img.is_pinned ? ' is-pinned' : '';
                            var coverClass = img.is_cover ? ' is-cover' : '';
                            html += '<a href="' + img.url + '" target="_blank" class="kundenkarte-file-preview-thumb' + pinnedClass + coverClass + '">';
                            html += '<img src="' + img.thumb_url + '" alt="' + self.escapeHtml(img.name) + '">';
                            if (img.is_pinned) {
                                html += '<span class="kundenkarte-file-preview-pin"><i class="fa fa-thumb-tack"></i></span>';
                            }
                            html += '</a>';
                        }
                        if (response.images.length > 6) {
                            html += '<span class="kundenkarte-file-preview-more">+' + (response.images.length - 6) + '</span>';
                        }
                        html += '</div>';
                        html += '</div>';
                    }

                    // Documents section with icons
                    if (response.documents && response.documents.length > 0) {
                        html += '<div class="kundenkarte-file-preview-section">';
                        html += '<div class="kundenkarte-file-preview-title"><i class="fa fa-file-text-o"></i> Dokumente (' + response.documents.length + ')</div>';
                        html += '<div class="kundenkarte-file-preview-docs">';
                        for (var j = 0; j < response.documents.length && j < 5; j++) {
                            var doc = response.documents[j];
                            var docPinnedClass = doc.is_pinned ? ' is-pinned' : '';
                            html += '<a href="' + doc.url + '" target="_blank" class="kundenkarte-file-preview-doc' + docPinnedClass + '">';
                            html += '<i class="fa ' + doc.icon + '" style="color:' + doc.color + '"></i>';
                            html += '<span class="kundenkarte-file-preview-doc-name">' + self.escapeHtml(doc.name) + '</span>';
                            if (doc.is_pinned) {
                                html += '<i class="fa fa-thumb-tack kundenkarte-file-preview-doc-pin"></i>';
                            }
                            html += '</a>';
                        }
                        if (response.documents.length > 5) {
                            html += '<div class="kundenkarte-file-preview-more-docs">+' + (response.documents.length - 5) + ' weitere</div>';
                        }
                        html += '</div>';
                        html += '</div>';
                    }

                    html += '</div>';

                    var $tooltip = $('#kundenkarte-tooltip');
                    if (!$tooltip.length) {
                        $tooltip = $('<div id="kundenkarte-tooltip" class="kundenkarte-tooltip"></div>');
                        $('body').append($tooltip);
                    }

                    $tooltip.html(html);

                    // Position tooltip
                    var offset = $trigger.offset();
                    var windowWidth = $(window).width();
                    var scrollTop = $(window).scrollTop();

                    $tooltip.css({ visibility: 'hidden', display: 'block' });
                    var tooltipWidth = $tooltip.outerWidth();
                    var tooltipHeight = $tooltip.outerHeight();
                    $tooltip.css({ visibility: '', display: '' });

                    var left = offset.left + $trigger.outerWidth() + 10;
                    if (left + tooltipWidth > windowWidth - 20) {
                        left = offset.left - tooltipWidth - 10;
                    }
                    if (left < 10) left = 10;

                    var top = offset.top;
                    if (top + tooltipHeight > scrollTop + $(window).height() - 20) {
                        top = scrollTop + $(window).height() - tooltipHeight - 20;
                    }

                    $tooltip.css({ top: top, left: left }).addClass('visible').show();
                    self.currentTooltip = $tooltip;
                }
            });
        },

        buildTooltipHtml: function(data) {
            var html = '<div class="kundenkarte-tooltip-header">';
            html += '<span class="kundenkarte-tooltip-icon"><i class="fa ' + (data.picto || 'fa-cube') + '"></i></span>';
            html += '<div>';
            html += '<div class="kundenkarte-tooltip-title">' + this.escapeHtml(data.label || '') + '</div>';
            html += '<div class="kundenkarte-tooltip-type">' + this.escapeHtml(data.type || data.type_label || '') + '</div>';
            html += '</div></div>';

            html += '<div class="kundenkarte-tooltip-fields">';

            // Dynamic fields only (from PHP data-tooltip attribute)
            if (data.fields) {
                for (var key in data.fields) {
                    if (data.fields.hasOwnProperty(key)) {
                        var field = data.fields[key];
                        // Handle header fields as section titles (must span both grid columns)
                        if (field.type === 'header') {
                            html += '<span class="kundenkarte-tooltip-field-header" style="grid-column:1/-1;display:block;width:100%;font-weight:bold;margin-top:8px;padding-top:8px;border-top:1px solid #ddd;">' + this.escapeHtml(field.label) + '</span>';
                        } else if (field.value) {
                            html += '<span class="kundenkarte-tooltip-field-label">' + this.escapeHtml(field.label) + ':</span>';
                            html += '<span class="kundenkarte-tooltip-field-value">' + this.escapeHtml(field.value) + '</span>';
                        }
                    }
                }
            }

            html += '</div>';

            // Notes (note_html is already sanitized and formatted with <br> by PHP)
            if (data.note_html) {
                html += '<div class="kundenkarte-tooltip-note" style="margin-top:10px;padding-top:10px;border-top:1px solid #eee;font-size:0.9em;color:#666;">';
                html += '<i class="fa fa-sticky-note"></i><br>' + data.note_html;
                html += '</div>';
            }

            // Images (from AJAX)
            if (data.images && data.images.length > 0) {
                html += '<div class="kundenkarte-tooltip-images">';
                for (var i = 0; i < Math.min(data.images.length, 4); i++) {
                    html += '<img src="' + data.images[i].thumb_url + '" class="kundenkarte-tooltip-thumb" alt="">';
                }
                html += '</div>';
            }

            return html;
        },

        escapeHtml: function(text) {
            if (!text) return '';
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        },

        escapeHtmlPreservingBreaks: function(text) {
            if (!text) return '';
            // Convert <br> to newlines first (for old data with <br> tags)
            text = text.replace(/<br\s*\/?>/gi, '\n');
            return this.escapeHtml(text);
        },

        refresh: function(socId, systemId) {
            var $container = $('.kundenkarte-tree[data-system="' + systemId + '"]');
            if (!$container.length) return;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/anlage_tree.php',
                data: { socid: socId, system: systemId },
                success: function(html) {
                    $container.html(html);
                }
            });
        },

        // Drag & Drop Sortierung initialisieren
        initDragDrop: function() {
            var self = this;
            this.draggedNode = null;

            $(document).on('mousedown', '.kundenkarte-tree-item', function(e) {
                // Nicht bei Klick auf Links, Buttons oder Toggle
                if ($(e.target).closest('a, button, .kundenkarte-tree-toggle').length) return;

                var $item = $(this);
                var $node = $item.closest('.kundenkarte-tree-node');

                // Nur wenn Schreibberechtigung (Actions vorhanden)
                if (!$item.find('.kundenkarte-tree-actions').length) return;

                self.draggedNode = $node;
                self.dragStartY = e.pageY;
                self.isDragging = false;

                $(document).on('mousemove.treeDrag', function(e) {
                    // Erst ab 5px Bewegung als Drag werten
                    if (!self.isDragging && Math.abs(e.pageY - self.dragStartY) > 5) {
                        self.isDragging = true;
                        self.draggedNode.addClass('kundenkarte-dragging');
                        $('body').addClass('kundenkarte-drag-active');
                    }

                    if (self.isDragging) {
                        self.handleDragOver(e);
                    }
                });

                $(document).on('mouseup.treeDrag', function(e) {
                    $(document).off('mousemove.treeDrag mouseup.treeDrag');

                    if (self.isDragging) {
                        self.handleDrop();
                    }

                    self.draggedNode.removeClass('kundenkarte-dragging');
                    $('body').removeClass('kundenkarte-drag-active');
                    $('.kundenkarte-drag-above, .kundenkarte-drag-below').removeClass('kundenkarte-drag-above kundenkarte-drag-below');
                    self.draggedNode = null;
                    self.isDragging = false;
                    self.dropTarget = null;
                });
            });
        },

        handleDragOver: function(e) {
            var self = this;
            // Alle Markierungen entfernen
            $('.kundenkarte-drag-above, .kundenkarte-drag-below').removeClass('kundenkarte-drag-above kundenkarte-drag-below');

            // Element unter dem Mauszeiger finden
            var $target = $(e.target).closest('.kundenkarte-tree-node');
            if (!$target.length || $target.is(self.draggedNode)) return;

            // Nur Geschwister erlauben (gleicher Parent-Container)
            var $dragParent = self.draggedNode.parent();
            var $targetParent = $target.parent();
            if (!$dragParent.is($targetParent)) return;

            // Position bestimmen: obere oder untere Hälfte des Ziels
            var targetRect = $target.children('.kundenkarte-tree-item')[0].getBoundingClientRect();
            var midY = targetRect.top + targetRect.height / 2;

            if (e.clientY < midY) {
                $target.addClass('kundenkarte-drag-above');
                self.dropTarget = { node: $target, position: 'before' };
            } else {
                $target.addClass('kundenkarte-drag-below');
                self.dropTarget = { node: $target, position: 'after' };
            }
        },

        handleDrop: function() {
            var self = this;
            if (!self.dropTarget) return;

            var $target = self.dropTarget.node;
            var position = self.dropTarget.position;

            // DOM-Reihenfolge aktualisieren
            if (position === 'before') {
                self.draggedNode.insertBefore($target);
            } else {
                self.draggedNode.insertAfter($target);
            }

            // Neue Reihenfolge der Geschwister sammeln
            var $parent = self.draggedNode.parent();
            var ids = [];
            $parent.children('.kundenkarte-tree-node').each(function() {
                var id = $(this).children('.kundenkarte-tree-item').data('anlage-id');
                if (id) ids.push(id);
            });

            // Per AJAX speichern
            var baseUrl = $('meta[name="dolibarr-baseurl"]').attr('content') || '';
            $.ajax({
                type: 'POST',
                url: baseUrl + '/custom/kundenkarte/ajax/anlage.php',
                data: {
                    action: 'reorder',
                    token: $('input[name="token"]').val() || '',
                    'ids[]': ids
                },
                dataType: 'json'
            });
        },

        expandAll: function() {
            $('.kundenkarte-tree-toggle').removeClass('collapsed');
            $('.kundenkarte-tree-children').removeClass('collapsed');
        },

        collapseAll: function() {
            $('.kundenkarte-tree-toggle').addClass('collapsed');
            $('.kundenkarte-tree-children').addClass('collapsed');
        },

        toggleCompactMode: function() {
            var $tree = $('.kundenkarte-tree');
            var $btn = $('#btn-compact-mode');

            $tree.toggleClass('compact-mode');
            $btn.toggleClass('active');

            if ($tree.hasClass('compact-mode')) {
                $btn.find('span').text('Normal');
                $btn.find('i').removeClass('fa-compress').addClass('fa-expand');
                // Remove any expanded items
                $('.kundenkarte-tree-item.expanded').removeClass('expanded');
                // Store preference
                localStorage.setItem('kundenkarte_compact_mode', '1');
            } else {
                $btn.find('span').text('Kompakt');
                $btn.find('i').removeClass('fa-expand').addClass('fa-compress');
                localStorage.removeItem('kundenkarte_compact_mode');
            }
        },

        initCompactMode: function() {
            // Check localStorage for saved preference
            if (localStorage.getItem('kundenkarte_compact_mode') === '1') {
                this.toggleCompactMode();
            }

            // Auto-enable on mobile
            if (window.innerWidth <= 768 && !localStorage.getItem('kundenkarte_compact_mode_manual')) {
                if (!$('.kundenkarte-tree').hasClass('compact-mode')) {
                    this.toggleCompactMode();
                }
            }
        }
    };

    /**
     * Favorite Products Component
     */
    KundenKarte.Favorites = {
        init: function() {
            this.bindEvents();
        },

        bindEvents: function() {
            // Select all checkbox
            $(document).on('change', '#kundenkarte-select-all', function() {
                var checked = $(this).prop('checked');
                $('.kundenkarte-favorites-table input[type="checkbox"][name="selected_products[]"]').prop('checked', checked);
                KundenKarte.Favorites.updateGenerateButton();
            });

            // Individual checkbox
            $(document).on('change', '.kundenkarte-favorites-table input[type="checkbox"][name="selected_products[]"]', function() {
                KundenKarte.Favorites.updateGenerateButton();
            });

            // Save button click
            $(document).on('click', '.kundenkarte-qty-save', function(e) {
                e.preventDefault();
                var $btn = $(this);
                var favId = $btn.data('fav-id');
                var $input = $('input.kundenkarte-favorites-qty[data-fav-id="' + favId + '"]');
                var qtyStr = $input.val().replace(',', '.');
                var qty = parseFloat(qtyStr);

                if (!isNaN(qty) && qty > 0) {
                    // Limit to 2 decimal places
                    qty = Math.round(qty * 100) / 100;

                    // Format nicely
                    var display = (qty % 1 === 0) ? qty.toString() : qty.toFixed(2).replace(/\.?0+$/, '');
                    $input.val(display);

                    // Visual feedback
                    $btn.prop('disabled', true);
                    $btn.find('i').removeClass('fa-save').addClass('fa-spinner fa-spin');

                    $.ajax({
                        url: baseUrl + '/custom/kundenkarte/ajax/favorite_update.php',
                        method: 'POST',
                        data: { id: favId, qty: qty, token: $('input[name="token"]').val() },
                        success: function() {
                            $btn.find('i').removeClass('fa-spinner fa-spin').addClass('fa-check').css('color', '#0a0');
                            setTimeout(function() {
                                $btn.find('i').removeClass('fa-check').addClass('fa-save').css('color', '');
                                $btn.prop('disabled', false);
                            }, 1500);
                        },
                        error: function() {
                            $btn.find('i').removeClass('fa-spinner fa-spin').addClass('fa-exclamation-triangle').css('color', '#c00');
                            setTimeout(function() {
                                $btn.find('i').removeClass('fa-exclamation-triangle').addClass('fa-save').css('color', '');
                                $btn.prop('disabled', false);
                            }, 2000);
                        }
                    });
                }
            });
        },

        updateGenerateButton: function() {
            var count = $('.kundenkarte-favorites-table input[type="checkbox"][name="selected_products[]"]:checked').length;
            var $btn = $('#btn-generate-order');

            if (count > 0) {
                $btn.prop('disabled', false).text($btn.data('text').replace('%d', count));
            } else {
                $btn.prop('disabled', true).text($btn.data('text-none'));
            }
        }
    };

    /**
     * System Tabs Component
     */
    KundenKarte.SystemTabs = {
        init: function() {
            this.bindEvents();
        },

        bindEvents: function() {
            $(document).on('click', '.kundenkarte-system-tab:not(.active):not(.kundenkarte-system-tab-add)', function() {
                var systemId = $(this).data('system');
                KundenKarte.SystemTabs.switchTo(systemId);
            });
        },

        switchTo: function(systemId) {
            $('.kundenkarte-system-tab').removeClass('active');
            $('.kundenkarte-system-tab[data-system="' + systemId + '"]').addClass('active');

            $('.kundenkarte-system-content').hide();
            $('.kundenkarte-system-content[data-system="' + systemId + '"]').show();

            // Update URL without reload
            var url = new URL(window.location.href);
            url.searchParams.set('system', systemId);
            window.history.replaceState({}, '', url);
        }
    };

    /**
     * Icon Picker Component with Custom Icon Upload
     */
    KundenKarte.IconPicker = {
        // Common FontAwesome icons for installations/technical use
        icons: [
            // Electrical
            'fa-bolt', 'fa-plug', 'fa-power-off', 'fa-charging-station', 'fa-battery-full', 'fa-battery-half',
            'fa-car-battery', 'fa-solar-panel', 'fa-sun', 'fa-lightbulb', 'fa-toggle-on', 'fa-toggle-off',
            // Network/Internet
            'fa-wifi', 'fa-network-wired', 'fa-server', 'fa-database', 'fa-hdd', 'fa-ethernet',
            'fa-broadcast-tower', 'fa-satellite-dish', 'fa-satellite', 'fa-signal', 'fa-rss',
            // TV/Media
            'fa-tv', 'fa-play-circle', 'fa-video', 'fa-film', 'fa-podcast', 'fa-music',
            // Temperature/Climate
            'fa-thermometer-half', 'fa-temperature-high', 'fa-temperature-low', 'fa-fire', 'fa-fire-alt',
            'fa-snowflake', 'fa-wind', 'fa-fan', 'fa-air-freshener',
            // Building/Structure
            'fa-home', 'fa-building', 'fa-warehouse', 'fa-door-open', 'fa-door-closed', 'fa-archway',
            // Devices/Hardware
            'fa-microchip', 'fa-memory', 'fa-sim-card', 'fa-sd-card', 'fa-usb', 'fa-desktop', 'fa-laptop',
            'fa-mobile-alt', 'fa-tablet-alt', 'fa-keyboard', 'fa-print', 'fa-fax',
            // Security
            'fa-shield-alt', 'fa-lock', 'fa-unlock', 'fa-key', 'fa-fingerprint', 'fa-eye', 'fa-video',
            'fa-bell', 'fa-exclamation-triangle', 'fa-user-shield',
            // Objects
            'fa-cube', 'fa-cubes', 'fa-box', 'fa-boxes', 'fa-archive', 'fa-toolbox', 'fa-tools', 'fa-wrench',
            'fa-cog', 'fa-cogs', 'fa-sliders-h',
            // Layout
            'fa-th', 'fa-th-large', 'fa-th-list', 'fa-grip-horizontal', 'fa-grip-vertical', 'fa-bars',
            'fa-stream', 'fa-layer-group', 'fa-project-diagram', 'fa-share-alt', 'fa-sitemap',
            // Arrows/Direction
            'fa-exchange-alt', 'fa-arrows-alt', 'fa-expand', 'fa-compress', 'fa-random',
            // Misc
            'fa-tachometer-alt', 'fa-chart-line', 'fa-chart-bar', 'fa-chart-pie', 'fa-chart-area',
            'fa-clock', 'fa-calendar', 'fa-tag', 'fa-tags', 'fa-bookmark', 'fa-star', 'fa-heart',
            'fa-check', 'fa-times', 'fa-plus', 'fa-minus', 'fa-info-circle', 'fa-question-circle',
            'fa-dot-circle', 'fa-circle', 'fa-square', 'fa-adjust'
        ],

        customIcons: [],
        currentInput: null,
        currentTab: 'fontawesome',

        init: function() {
            this.createModal();
            this.bindEvents();
        },

        createModal: function() {
            if ($('#kundenkarte-icon-picker-modal').length) return;

            var self = this;
            var html = '<div id="kundenkarte-icon-picker-modal" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:700px;">';
            html += '<div class="kundenkarte-modal-header">';
            html += '<h3>Icon auswählen</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-body">';

            // Tabs
            html += '<div class="kundenkarte-icon-tabs" style="display:flex;gap:5px;margin-bottom:15px;border-bottom:2px solid #e0e0e0;padding-bottom:10px;">';
            html += '<button type="button" class="button kundenkarte-icon-tab active" data-tab="fontawesome"><i class="fa fa-font-awesome"></i> Font Awesome</button>';
            html += '<button type="button" class="button kundenkarte-icon-tab" data-tab="custom"><i class="fa fa-upload"></i> Eigene Icons</button>';
            html += '</div>';

            // Font Awesome Tab Content
            html += '<div class="kundenkarte-icon-tab-content" data-tab="fontawesome">';
            html += '<input type="text" id="kundenkarte-icon-search" class="flat" placeholder="Suchen..." style="width:100%;margin-bottom:10px;">';
            html += '<div class="kundenkarte-icon-grid" id="kundenkarte-fa-icons">';
            for (var i = 0; i < this.icons.length; i++) {
                html += '<div class="kundenkarte-icon-item" data-icon="' + this.icons[i] + '" data-type="fa" title="' + this.icons[i] + '">';
                html += '<i class="fa ' + this.icons[i] + '"></i>';
                html += '</div>';
            }
            html += '</div>';
            html += '</div>';

            // Custom Icons Tab Content
            html += '<div class="kundenkarte-icon-tab-content" data-tab="custom" style="display:none;">';
            // Upload area
            html += '<div class="kundenkarte-icon-upload-area" style="border:2px dashed #ccc;border-radius:8px;padding:20px;text-align:center;margin-bottom:15px;background:#f9f9f9;">';
            html += '<i class="fa fa-cloud-upload" style="font-size:32px;color:#888;margin-bottom:10px;display:block;"></i>';
            html += '<p style="margin:0 0 10px 0;">Icon hochladen (PNG, JPG, SVG, max 500KB)</p>';
            html += '<input type="file" id="kundenkarte-icon-upload" accept=".png,.jpg,.jpeg,.gif,.svg,.webp" style="display:none;">';
            html += '<button type="button" class="button" id="kundenkarte-icon-upload-btn"><i class="fa fa-plus"></i> Datei auswählen</button>';
            html += '</div>';
            // Custom icons grid
            html += '<div class="kundenkarte-icon-grid" id="kundenkarte-custom-icons">';
            html += '<p class="opacitymedium" style="grid-column:1/-1;text-align:center;">Lade eigene Icons...</p>';
            html += '</div>';
            html += '</div>';

            html += '</div>';
            html += '</div>';
            html += '</div>';

            $('body').append(html);
        },

        bindEvents: function() {
            var self = this;

            // Open picker
            $(document).on('click', '.kundenkarte-icon-picker-btn', function(e) {
                e.preventDefault();
                var inputName = $(this).data('input');
                self.currentInput = $('input[name="' + inputName + '"]');
                self.open();
            });

            // Close modal
            $(document).on('click', '.kundenkarte-modal-close, #kundenkarte-icon-picker-modal', function(e) {
                if (e.target === this || $(e.target).hasClass('kundenkarte-modal-close')) {
                    self.close();
                }
            });

            // Tab switching
            $(document).on('click', '.kundenkarte-icon-tab', function() {
                var tab = $(this).data('tab');
                self.switchTab(tab);
            });

            // Select FA icon
            $(document).on('click', '.kundenkarte-icon-item[data-type="fa"]', function() {
                var icon = $(this).data('icon');
                self.selectIcon(icon, 'fa');
            });

            // Select custom icon
            $(document).on('click', '.kundenkarte-icon-item[data-type="custom"]', function() {
                var iconUrl = $(this).data('icon');
                self.selectIcon(iconUrl, 'custom');
            });

            // Search filter (FA only)
            $(document).on('input', '#kundenkarte-icon-search', function() {
                var search = $(this).val().toLowerCase();
                $('#kundenkarte-fa-icons .kundenkarte-icon-item').each(function() {
                    var icon = $(this).data('icon').toLowerCase();
                    $(this).toggle(icon.indexOf(search) > -1);
                });
            });

            // Upload button click
            $(document).on('click', '#kundenkarte-icon-upload-btn', function() {
                $('#kundenkarte-icon-upload').click();
            });

            // File selected
            $(document).on('change', '#kundenkarte-icon-upload', function() {
                var file = this.files[0];
                if (file) {
                    self.uploadIcon(file);
                }
            });

            // Delete custom icon
            $(document).on('click', '.kundenkarte-icon-delete', function(e) {
                e.stopPropagation();
                var filename = $(this).data('filename');
                self.showDeleteConfirm(filename);
            });

            // ESC key to close
            $(document).on('keydown', function(e) {
                if (e.key === 'Escape') {
                    self.close();
                }
            });
        },

        switchTab: function(tab) {
            this.currentTab = tab;
            $('.kundenkarte-icon-tab').removeClass('active');
            $('.kundenkarte-icon-tab[data-tab="' + tab + '"]').addClass('active');
            $('.kundenkarte-icon-tab-content').hide();
            $('.kundenkarte-icon-tab-content[data-tab="' + tab + '"]').show();

            if (tab === 'custom') {
                this.loadCustomIcons();
            }
        },

        loadCustomIcons: function() {
            var self = this;
            var $grid = $('#kundenkarte-custom-icons');

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/icon_upload.php',
                data: { action: 'list' },
                dataType: 'json',
                success: function(response) {
                    $grid.empty();

                    if (response.icons && response.icons.length > 0) {
                        self.customIcons = response.icons;
                        for (var i = 0; i < response.icons.length; i++) {
                            var icon = response.icons[i];
                            var html = '<div class="kundenkarte-icon-item kundenkarte-custom-icon-item" data-icon="' + icon.url + '" data-type="custom" title="' + icon.name + '" style="position:relative;">';
                            html += '<img src="' + icon.url + '" alt="' + icon.name + '" style="max-width:32px;max-height:32px;">';
                            html += '<span class="kundenkarte-icon-delete" data-filename="' + icon.filename + '" title="Löschen" style="position:absolute;top:-5px;right:-5px;background:#c00;color:#fff;border-radius:50%;width:16px;height:16px;font-size:10px;line-height:16px;text-align:center;cursor:pointer;display:none;">&times;</span>';
                            html += '</div>';
                            $grid.append(html);
                        }
                    } else {
                        $grid.html('<p class="opacitymedium" style="grid-column:1/-1;text-align:center;">Noch keine eigenen Icons hochgeladen.</p>');
                    }
                },
                error: function() {
                    $grid.html('<p class="warning" style="grid-column:1/-1;text-align:center;">Fehler beim Laden der Icons.</p>');
                }
            });
        },

        uploadIcon: function(file) {
            var self = this;
            var formData = new FormData();
            formData.append('action', 'upload');
            formData.append('icon', file);

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/icon_upload.php',
                method: 'POST',
                data: formData,
                processData: false,
                contentType: false,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.loadCustomIcons();
                        // Auto-select uploaded icon
                        setTimeout(function() {
                            self.selectIcon(response.icon.url, 'custom');
                        }, 500);
                    } else {
                        KundenKarte.showAlert('Fehler', response.error || 'Unbekannter Fehler');
                    }
                },
                error: function(xhr) {
                    var msg = 'Upload fehlgeschlagen';
                    try {
                        var resp = JSON.parse(xhr.responseText);
                        msg = resp.error || msg;
                    } catch(e) {}
                    KundenKarte.showAlert('Fehler', msg);
                }
            });

            // Reset input
            $('#kundenkarte-icon-upload').val('');
        },

        deleteIcon: function(filename) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/icon_upload.php',
                method: 'POST',
                data: { action: 'delete', filename: filename },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.loadCustomIcons();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error || 'Löschen fehlgeschlagen');
                    }
                }
            });
        },

        showDeleteConfirm: function(filename) {
            var self = this;

            // Remove any existing confirm dialog
            $('#kundenkarte-delete-confirm').remove();

            // Create Dolibarr-style confirmation dialog
            var html = '<div id="kundenkarte-delete-confirm" class="kundenkarte-confirm-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:10001;display:flex;align-items:center;justify-content:center;">';
            html += '<div class="kundenkarte-confirm-box" style="background:#fff;border-radius:6px;box-shadow:0 4px 20px rgba(0,0,0,0.3);max-width:400px;width:90%;">';

            // Header (Dolibarr style)
            html += '<div class="kundenkarte-confirm-header" style="background:linear-gradient(to bottom,#f8f8f8,#e8e8e8);border-bottom:1px solid #ccc;padding:12px 15px;border-radius:6px 6px 0 0;">';
            html += '<span style="font-weight:bold;font-size:14px;"><i class="fa fa-exclamation-triangle" style="color:#f0ad4e;margin-right:8px;"></i>Bestätigung</span>';
            html += '</div>';

            // Body
            html += '<div class="kundenkarte-confirm-body" style="padding:20px;text-align:center;">';
            html += '<p style="margin:0 0 5px 0;font-size:14px;">Möchten Sie dieses Icon wirklich löschen?</p>';
            html += '<p style="margin:0;color:#666;font-size:12px;"><code>' + this.escapeHtml(filename) + '</code></p>';
            html += '</div>';

            // Footer with buttons (Dolibarr style)
            html += '<div class="kundenkarte-confirm-footer" style="background:#f5f5f5;border-top:1px solid #ddd;padding:12px 15px;text-align:center;border-radius:0 0 6px 6px;">';
            html += '<button type="button" class="button" id="kundenkarte-confirm-yes" style="background:#c9302c;color:#fff;border:1px solid #ac2925;padding:6px 20px;margin-right:10px;cursor:pointer;"><i class="fa fa-check"></i> Ja, löschen</button>';
            html += '<button type="button" class="button" id="kundenkarte-confirm-no" style="padding:6px 20px;cursor:pointer;"><i class="fa fa-times"></i> Abbrechen</button>';
            html += '</div>';

            html += '</div>';
            html += '</div>';

            $('body').append(html);

            // Bind events
            $('#kundenkarte-confirm-yes').on('click', function() {
                $('#kundenkarte-delete-confirm').remove();
                self.deleteIcon(filename);
            });

            $('#kundenkarte-confirm-no, #kundenkarte-delete-confirm').on('click', function(e) {
                if (e.target === this) {
                    $('#kundenkarte-delete-confirm').remove();
                }
            });

            // ESC to close
            $(document).one('keydown.confirmDialog', function(e) {
                if (e.key === 'Escape') {
                    $('#kundenkarte-delete-confirm').remove();
                }
            });
        },

        escapeHtml: function(text) {
            if (!text) return '';
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        },

        selectIcon: function(icon, type) {
            if (this.currentInput) {
                // For custom icons, store the URL with a prefix to distinguish
                var value = (type === 'custom') ? 'img:' + icon : icon;
                this.currentInput.val(value);

                // Update preview
                var $wrapper = this.currentInput.closest('.kundenkarte-icon-picker-wrapper');
                var $preview = $wrapper.find('.kundenkarte-icon-preview');
                if ($preview.length) {
                    if (type === 'custom') {
                        $preview.html('<img src="' + icon + '" style="max-width:20px;max-height:20px;">');
                    } else {
                        $preview.html('<i class="fa ' + icon + '"></i>');
                    }
                }
            }
            this.close();
        },

        open: function() {
            $('#kundenkarte-icon-search').val('');
            $('#kundenkarte-fa-icons .kundenkarte-icon-item').show();
            this.switchTab('fontawesome');
            $('#kundenkarte-icon-picker-modal').addClass('visible');
        },

        close: function() {
            $('#kundenkarte-icon-picker-modal').removeClass('visible');
            this.currentInput = null;
        }
    };

    /**
     * Dynamic Fields Component
     * Loads and renders type-specific fields when creating/editing anlagen
     */
    KundenKarte.DynamicFields = {
        init: function() {
            var self = this;
            var $typeSelect = $('select[name="fk_anlage_type"]');
            var $container = $('#dynamic_fields');

            if (!$typeSelect.length || !$container.length) return;

            // Load fields when type changes
            $typeSelect.on('change', function() {
                self.loadFields($(this).val());
            });

            // Load initial fields if type is already selected
            if ($typeSelect.val()) {
                self.loadFields($typeSelect.val());
            }
        },

        loadFields: function(typeId) {
            var self = this;
            var $container = $('#dynamic_fields');
            if (!typeId) {
                $container.html('');
                return;
            }

            // Store current type ID for autocomplete
            this.currentTypeId = typeId;

            // Get anlage_id if editing or copying
            var anlageId = $('input[name="anlage_id"]').val() || $('input[name="copy_from"]').val() || 0;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/type_fields.php',
                data: { type_id: typeId, anlage_id: anlageId },
                dataType: 'json',
                success: function(data) {
                    if (data.fields && data.fields.length > 0) {
                        var html = '';

                        data.fields.forEach(function(field) {
                            if (field.type === 'header') {
                                // Header row spans both columns with styling
                                html += '<tr class="liste_titre dynamic-field-row"><th colspan="2" style="background:#f0f0f0;padding:8px;">' + KundenKarte.DynamicFields.escapeHtml(field.label) + '</th></tr>';
                            } else {
                                html += '<tr class="dynamic-field-row"><td class="titlefield">' + KundenKarte.DynamicFields.escapeHtml(field.label);
                                if (field.required) html += ' <span class="fieldrequired">*</span>';
                                html += '</td><td>';
                                html += KundenKarte.DynamicFields.renderField(field);
                                html += '</td></tr>';
                            }
                        });

                        $container.html(html);
                    } else {
                        $container.html('');
                    }
                }
            });
        },

        currentTypeId: 0,

        renderField: function(field) {
            var name = 'field_' + field.code;
            var value = field.value || '';
            var required = field.required ? ' required' : '';
            var autocompleteClass = field.autocomplete ? ' kk-autocomplete' : '';
            var autocompleteAttrs = field.autocomplete ? ' data-field-code="' + field.code + '" data-type-id="' + this.currentTypeId + '"' : '';

            switch (field.type) {
                case 'text':
                    return '<input type="text" name="' + name + '" class="flat minwidth300' + autocompleteClass + '" value="' + this.escapeHtml(value) + '"' + autocompleteAttrs + required + ' autocomplete="off">';

                case 'textarea':
                    return '<textarea name="' + name + '" class="flat minwidth300' + autocompleteClass + '" rows="3"' + autocompleteAttrs + required + ' autocomplete="off">' + this.escapeHtml(value) + '</textarea>';

                case 'number':
                    var attrs = '';
                    if (field.options) {
                        var opts = field.options.split('|');
                        opts.forEach(function(opt) {
                            var parts = opt.split(':');
                            if (parts.length === 2) {
                                attrs += ' ' + parts[0] + '="' + parts[1] + '"';
                            }
                        });
                    }
                    return '<input type="number" name="' + name + '" class="flat" value="' + this.escapeHtml(value) + '"' + attrs + required + '>';

                case 'select':
                    var html = '<select name="' + name + '" class="flat minwidth200"' + required + '>';
                    html += '<option value="">-- Auswählen --</option>';
                    if (field.options) {
                        var options = field.options.split('|');
                        options.forEach(function(opt) {
                            var selected = (opt === value) ? ' selected' : '';
                            html += '<option value="' + KundenKarte.DynamicFields.escapeHtml(opt) + '"' + selected + '>' + KundenKarte.DynamicFields.escapeHtml(opt) + '</option>';
                        });
                    }
                    html += '</select>';
                    return html;

                case 'date':
                    var inputId = 'date_' + name.replace(/[^a-zA-Z0-9]/g, '_');
                    return '<input type="date" name="' + name + '" id="' + inputId + '" class="flat" value="' + this.escapeHtml(value) + '"' + required + '>' +
                           '<button type="button" class="button buttongen" style="margin-left:4px;padding:2px 6px;font-size:11px;" onclick="document.getElementById(\'' + inputId + '\').value = new Date().toISOString().split(\'T\')[0];" title="Heute">Heute</button>';

                case 'checkbox':
                    var checked = (value === '1' || value === 'true' || value === 'yes') ? ' checked' : '';
                    return '<input type="checkbox" name="' + name + '" value="1"' + checked + '>';

                default:
                    return '<input type="text" name="' + name + '" class="flat minwidth300" value="' + this.escapeHtml(value) + '"' + required + '>';
            }
        },

        escapeHtml: function(text) {
            if (!text) return '';
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }
    };

    /**
     * Equipment Component
     * Manages Hutschienen (DIN rail) components with SVG visualization
     */
    KundenKarte.Equipment = {
        TE_WIDTH: 50, // Width of one TE in pixels (wider for more space)
        BLOCK_HEIGHT: 110, // Height of equipment block in pixels
        currentCarrierId: null,
        currentAnlageId: null,
        currentSystemId: null,
        draggedEquipment: null,
        isSaving: false, // Prevent double-clicks

        init: function(anlageId, systemId) {
            if (!anlageId) return;
            this.currentAnlageId = anlageId;
            this.currentSystemId = systemId || 0;
            this.bindEvents();
        },

        bindEvents: function() {
            var self = this;

            // Add panel button
            $(document).on('click', '.kundenkarte-add-panel', function(e) {
                e.preventDefault();
                var anlageId = $(this).data('anlage-id');
                self.showPanelDialog(anlageId);
            });

            // Edit panel
            $(document).on('click', '.kundenkarte-panel-edit', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var panelId = $(this).closest('.kundenkarte-panel').data('panel-id');
                self.showPanelDialog(self.currentAnlageId, panelId);
            });

            // Delete panel
            $(document).on('click', '.kundenkarte-panel-delete', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var panelId = $(this).closest('.kundenkarte-panel').data('panel-id');
                self.deletePanel(panelId);
            });

            // Quick-duplicate panel (+ button next to last panel)
            $(document).on('click', '.kundenkarte-panel-quickadd', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var panelId = $(this).data('panel-id');
                self.duplicatePanel(panelId);
            });

            // Quick-duplicate carrier (+ button below last carrier)
            $(document).on('click', '.kundenkarte-carrier-quickadd', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var carrierId = $(this).data('carrier-id');
                self.duplicateCarrier(carrierId);
            });

            // Add carrier button
            $(document).on('click', '.kundenkarte-add-carrier', function(e) {
                e.preventDefault();
                var anlageId = $(this).data('anlage-id');
                var panelId = $(this).data('panel-id') || 0;
                self.showCarrierDialog(anlageId, null, panelId);
            });

            // Edit carrier
            $(document).on('click', '.kundenkarte-carrier-edit', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var carrierId = $(this).closest('.kundenkarte-carrier').data('carrier-id');
                self.showCarrierDialog(self.currentAnlageId, carrierId);
            });

            // Delete carrier
            $(document).on('click', '.kundenkarte-carrier-delete', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var carrierId = $(this).closest('.kundenkarte-carrier').data('carrier-id');
                self.deleteCarrier(carrierId);
            });

            // Add equipment (click on empty slot or + button)
            $(document).on('click', '.kundenkarte-carrier-add-equipment, .kundenkarte-slot-empty', function(e) {
                e.preventDefault();
                var $carrier = $(this).closest('.kundenkarte-carrier');
                var carrierId = $carrier.data('carrier-id');
                var position = $(this).data('position') || null;
                self.showEquipmentDialog(carrierId, null, position);
            });

            // Edit equipment (click on block)
            $(document).on('click', '.kundenkarte-equipment-block', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var equipmentId = $(this).data('equipment-id');
                self.showEquipmentDialog(null, equipmentId);
            });

            // Quick-add slot (duplicate last equipment into next free position)
            $(document).on('click', '.kundenkarte-slot-quickadd', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var equipmentId = $(this).data('equipment-id');
                self.duplicateEquipment(equipmentId);
            });

            // Delete equipment
            $(document).on('click', '.kundenkarte-equipment-delete', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var equipmentId = $(this).closest('.kundenkarte-equipment-block').data('equipment-id');
                self.deleteEquipment(equipmentId);
            });

            // Add output connection
            $(document).on('click', '.kundenkarte-add-output-btn', function(e) {
                e.preventDefault();
                var carrierId = $(this).data('carrier-id');
                self.showOutputDialog(carrierId);
            });

            // Add rail connection
            $(document).on('click', '.kundenkarte-add-rail-btn', function(e) {
                e.preventDefault();
                var carrierId = $(this).data('carrier-id');
                self.showRailDialog(carrierId);
            });

            // Click on rail to edit
            $(document).on('click', '.kundenkarte-rail', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var connectionId = $(this).data('connection-id');
                // Find carrier ID from connections container or carrier element
                var carrierId = $(this).closest('.kundenkarte-connections-container').data('carrier-id') ||
                               $(this).closest('.kundenkarte-carrier').data('carrier-id');
                self.showEditRailDialog(connectionId, carrierId);
            });

            // Click on output to edit
            $(document).on('click', '.kundenkarte-output', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var connectionId = $(this).data('connection-id');
                // Find carrier ID from connections container or carrier element
                var carrierId = $(this).closest('.kundenkarte-connections-container').data('carrier-id') ||
                               $(this).closest('.kundenkarte-carrier').data('carrier-id');
                self.showEditOutputDialog(connectionId, carrierId);
            });

            // Click on connection to delete (generic connections)
            $(document).on('click', '.kundenkarte-connection', function(e) {
                e.preventDefault();
                var connectionId = $(this).data('connection-id');
                self.deleteConnection(connectionId);
            });

            // Drag & Drop events
            $(document).on('dragstart', '.kundenkarte-equipment-block', function(e) {
                self.draggedEquipment = $(this);
                $(this).addClass('dragging');
                e.originalEvent.dataTransfer.effectAllowed = 'move';
                e.originalEvent.dataTransfer.setData('text/plain', $(this).data('equipment-id'));
            });

            $(document).on('dragend', '.kundenkarte-equipment-block', function() {
                $(this).removeClass('dragging');
                self.draggedEquipment = null;
                $('.kundenkarte-slot-drop-target').removeClass('kundenkarte-slot-drop-target');
            });

            $(document).on('dragover', '.kundenkarte-slot-empty, .kundenkarte-carrier-slots', function(e) {
                e.preventDefault();
                e.originalEvent.dataTransfer.dropEffect = 'move';
            });

            $(document).on('dragenter', '.kundenkarte-slot-empty', function(e) {
                e.preventDefault();
                $(this).addClass('kundenkarte-slot-drop-target');
            });

            $(document).on('dragleave', '.kundenkarte-slot-empty', function() {
                $(this).removeClass('kundenkarte-slot-drop-target');
            });

            $(document).on('drop', '.kundenkarte-slot-empty', function(e) {
                e.preventDefault();
                $(this).removeClass('kundenkarte-slot-drop-target');

                if (self.draggedEquipment) {
                    var equipmentId = self.draggedEquipment.data('equipment-id');
                    var newPosition = $(this).data('position');
                    self.moveEquipment(equipmentId, newPosition);
                }
            });

            // Equipment type change in dialog
            $(document).on('change', '#equipment_type_id', function() {
                self.loadEquipmentTypeFields($(this).val());
            });

            // Hover tooltip for equipment
            $(document).on('mouseenter', '.kundenkarte-equipment-block', function() {
                var $block = $(this);
                var tooltipData = $block.attr('data-tooltip');
                if (tooltipData) {
                    self.showEquipmentTooltip($block, JSON.parse(tooltipData));
                }
            });

            $(document).on('mouseleave', '.kundenkarte-equipment-block', function() {
                self.hideEquipmentTooltip();
            });
        },

        loadCarriers: function(anlageId) {
            var self = this;
            var $container = $('.kundenkarte-equipment-container[data-anlage-id="' + anlageId + '"]');

            if (!$container.length) return;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                data: { action: 'list', anlage_id: anlageId },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.renderCarriers($container, response.carriers);
                    }
                }
            });
        },

        renderCarriers: function($container, carriers) {
            var self = this;
            var html = '';

            if (carriers.length === 0) {
                html = '<div class="opacitymedium" style="padding:10px;">Keine Hutschienen vorhanden. Klicken Sie auf "Hutschiene hinzufügen".</div>';
            } else {
                carriers.forEach(function(carrier) {
                    html += self.renderCarrier(carrier);
                });
            }

            $container.find('.kundenkarte-carriers-list').html(html);
        },

        renderCarrier: function(carrier) {
            var self = this;
            var totalWidth = carrier.total_te * this.TE_WIDTH;

            var html = '<div class="kundenkarte-carrier" data-carrier-id="' + carrier.id + '">';

            // Header
            html += '<div class="kundenkarte-carrier-header">';
            html += '<span class="kundenkarte-carrier-label">' + this.escapeHtml(carrier.label || 'Hutschiene') + '</span>';
            html += '<span class="kundenkarte-carrier-info">' + carrier.used_te + '/' + carrier.total_te + ' TE belegt</span>';
            html += '<span class="kundenkarte-carrier-actions">';
            html += '<a href="#" class="kundenkarte-carrier-add-equipment" title="Equipment hinzufügen"><i class="fa fa-plus"></i></a>';
            html += '<a href="#" class="kundenkarte-carrier-edit" title="Bearbeiten"><i class="fa fa-edit"></i></a>';
            html += '<a href="#" class="kundenkarte-carrier-delete" title="Löschen"><i class="fa fa-trash"></i></a>';
            html += '</span>';
            html += '</div>';

            // SVG Rail
            html += '<div class="kundenkarte-carrier-svg-container" style="width:' + totalWidth + 'px;">';
            html += '<svg class="kundenkarte-carrier-svg" width="' + totalWidth + '" height="' + this.BLOCK_HEIGHT + '" viewBox="0 0 ' + totalWidth + ' ' + this.BLOCK_HEIGHT + '">';

            // Background grid (TE markers)
            for (var i = 0; i <= carrier.total_te; i++) {
                var x = i * this.TE_WIDTH;
                html += '<line x1="' + x + '" y1="0" x2="' + x + '" y2="' + this.BLOCK_HEIGHT + '" stroke="#ddd" stroke-width="0.5"/>';
            }

            // Render equipment blocks
            if (carrier.equipment) {
                carrier.equipment.forEach(function(eq) {
                    html += self.renderEquipmentBlock(eq);
                });
            }

            html += '</svg>';

            // Clickable slots overlay (for adding equipment)
            html += '<div class="kundenkarte-carrier-slots">';
            var occupiedSlots = this.getOccupiedSlots(carrier.equipment);
            for (var pos = 1; pos <= carrier.total_te; pos++) {
                if (!occupiedSlots[pos]) {
                    var slotLeft = (pos - 1) * this.TE_WIDTH;
                    html += '<div class="kundenkarte-slot-empty" data-position="' + pos + '" style="left:' + slotLeft + 'px;width:' + this.TE_WIDTH + 'px;"></div>';
                }
            }
            html += '</div>';

            html += '</div>'; // svg-container
            html += '</div>'; // carrier

            return html;
        },

        renderEquipmentBlock: function(equipment) {
            var x = (equipment.position_te - 1) * this.TE_WIDTH;
            var width = equipment.width_te * this.TE_WIDTH;
            var color = equipment.block_color || equipment.type_color || '#3498db';
            var label = equipment.block_label || equipment.type_label_short || '';

            // Build tooltip data
            var tooltipData = {
                label: equipment.label,
                type: equipment.type_label,
                fields: equipment.field_values || {}
            };

            var html = '<g class="kundenkarte-equipment-block" data-equipment-id="' + equipment.id + '" ';
            html += 'data-tooltip=\'' + JSON.stringify(tooltipData).replace(/'/g, "&#39;") + '\' ';
            html += 'draggable="true" style="cursor:pointer;">';

            // Block rectangle with rounded corners
            html += '<rect x="' + (x + 1) + '" y="2" width="' + (width - 2) + '" height="' + (this.BLOCK_HEIGHT - 4) + '" ';
            html += 'rx="3" ry="3" fill="' + color + '" stroke="#333" stroke-width="1"/>';

            // Label text (centered)
            var fontSize = width < 40 ? 11 : 14;
            html += '<text x="' + (x + width/2) + '" y="' + (this.BLOCK_HEIGHT/2) + '" ';
            html += 'text-anchor="middle" dominant-baseline="middle" ';
            html += 'fill="#fff" font-size="' + fontSize + 'px" font-weight="bold">';
            html += this.escapeHtml(label);
            html += '</text>';

            // Duplicate button (+) at the right edge
            html += '</g>';

            return html;
        },

        getOccupiedSlots: function(equipment) {
            var slots = {};
            if (equipment) {
                equipment.forEach(function(eq) {
                    for (var i = 0; i < eq.width_te; i++) {
                        slots[eq.position_te + i] = true;
                    }
                });
            }
            return slots;
        },

        // Panel dialog functions
        showPanelDialog: function(anlageId, panelId) {
            var self = this;

            if ($('#kundenkarte-panel-dialog').length) return;

            var isEdit = !!panelId;
            var title = isEdit ? 'Feld bearbeiten' : 'Feld hinzufügen';

            var panelData = { label: '' };

            var showDialog = function(data) {
                var html = '<div id="kundenkarte-panel-dialog" class="kundenkarte-modal">';
                html += '<div class="kundenkarte-modal-content" style="max-width:400px;">';
                html += '<div class="kundenkarte-modal-header"><h3>' + title + '</h3>';
                html += '<span class="kundenkarte-modal-close">&times;</span></div>';
                html += '<div class="kundenkarte-modal-body">';
                html += '<table class="noborder" style="width:100%;">';
                html += '<tr><td class="titlefield">Bezeichnung</td>';
                html += '<td><input type="text" name="panel_label" class="flat minwidth200" placeholder="z.B. Feld 1" value="' + self.escapeHtml(data.label) + '"></td></tr>';
                html += '</table>';
                html += '</div>';
                html += '<div class="kundenkarte-modal-footer">';
                html += '<button type="button" class="button" id="panel-save"><i class="fa fa-save"></i> Speichern</button> ';
                html += '<button type="button" class="button" id="panel-cancel">Abbrechen</button>';
                html += '</div>';
                html += '</div></div>';

                $('body').append(html);
                $('#kundenkarte-panel-dialog').addClass('visible');

                $('#panel-save').on('click', function() {
                    var label = $('input[name="panel_label"]').val();
                    self.savePanel(anlageId, panelId, label);
                });

                $('#panel-cancel, .kundenkarte-modal-close').on('click', function() {
                    $('#kundenkarte-panel-dialog').remove();
                });

                $(document).on('keydown.panelDialog', function(e) {
                    if (e.key === 'Escape') {
                        $('#kundenkarte-panel-dialog').remove();
                        $(document).off('keydown.panelDialog');
                    }
                });
            };

            if (isEdit) {
                var $panel = $('.kundenkarte-panel[data-panel-id="' + panelId + '"]');
                panelData.label = $panel.find('.kundenkarte-panel-label').text();
                showDialog(panelData);
            } else {
                showDialog(panelData);
            }
        },

        savePanel: function(anlageId, panelId, label) {
            var self = this;

            if (self.isSaving) return;
            self.isSaving = true;
            $('#panel-save').prop('disabled', true);

            var action = panelId ? 'update' : 'create';

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                method: 'POST',
                data: {
                    action: action,
                    anlage_id: anlageId,
                    panel_id: panelId,
                    label: label,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    self.isSaving = false;
                    if (response.success) {
                        $('#kundenkarte-panel-dialog').remove();
                        location.reload();
                    } else {
                        $('#panel-save').prop('disabled', false);
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    self.isSaving = false;
                    $('#panel-save').prop('disabled', false);
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        deletePanel: function(panelId) {
            var self = this;
            self.showConfirmDialog('Feld löschen', 'Möchten Sie dieses Feld wirklich löschen? Alle Hutschienen und Equipment werden ebenfalls gelöscht.', function() {
                $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                    method: 'POST',
                    data: {
                        action: 'delete',
                        panel_id: panelId,
                        token: $('input[name="token"]').val()
                    },
                    dataType: 'json',
                    success: function(response) {
                        if (response.success) {
                            location.reload();
                        } else {
                            self.showAlertDialog('Fehler', response.error);
                        }
                    },
                    error: function() {
                        self.showAlertDialog('Fehler', 'Netzwerkfehler');
                    }
                });
            });
        },

        duplicatePanel: function(panelId) {
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                method: 'POST',
                data: {
                    action: 'duplicate',
                    panel_id: panelId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        duplicateCarrier: function(carrierId) {
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                method: 'POST',
                data: {
                    action: 'duplicate',
                    carrier_id: carrierId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        showCarrierDialog: function(anlageId, carrierId, panelId) {
            var self = this;

            // Prevent opening multiple dialogs
            if ($('#kundenkarte-carrier-dialog').length) return;

            var isEdit = !!carrierId;
            var title = isEdit ? 'Hutschiene bearbeiten' : 'Hutschiene hinzufügen';
            panelId = panelId || 0;

            // Load carrier data if editing
            var carrierData = { label: '', total_te: 12, fk_panel: panelId };

            var showDialog = function(data, panels) {
                var html = '<div id="kundenkarte-carrier-dialog" class="kundenkarte-modal">';
                html += '<div class="kundenkarte-modal-content" style="max-width:400px;">';
                html += '<div class="kundenkarte-modal-header"><h3>' + title + '</h3>';
                html += '<span class="kundenkarte-modal-close">&times;</span></div>';
                html += '<div class="kundenkarte-modal-body">';
                html += '<input type="hidden" name="carrier_id" value="' + (carrierId || '') + '">';
                html += '<table class="noborder" style="width:100%;">';
                html += '<tr><td class="titlefield">Bezeichnung</td>';
                html += '<td><input type="text" name="carrier_label" class="flat minwidth200" value="' + self.escapeHtml(data.label) + '"></td></tr>';
                html += '<tr><td>Kapazität (TE)</td>';
                html += '<td><input type="number" name="carrier_total_te" class="flat" min="1" max="72" value="' + data.total_te + '"></td></tr>';

                // Panel dropdown (only show if panels exist)
                if (panels && panels.length > 0) {
                    html += '<tr><td>Feld</td>';
                    html += '<td><select name="carrier_panel_id" class="flat minwidth200">';
                    html += '<option value="0">-- Kein Feld (direkt) --</option>';
                    panels.forEach(function(p) {
                        var selected = (data.fk_panel == p.id) ? ' selected' : '';
                        html += '<option value="' + p.id + '"' + selected + '>' + self.escapeHtml(p.label) + '</option>';
                    });
                    html += '</select></td></tr>';
                }

                html += '</table>';
                html += '</div>';
                html += '<div class="kundenkarte-modal-footer">';
                html += '<button type="button" class="button" id="carrier-save"><i class="fa fa-save"></i> Speichern</button> ';
                html += '<button type="button" class="button" id="carrier-cancel">Abbrechen</button>';
                html += '</div>';
                html += '</div></div>';

                $('body').append(html);
                $('#kundenkarte-carrier-dialog').addClass('visible');

                // Save button
                $('#carrier-save').on('click', function() {
                    var label = $('input[name="carrier_label"]').val();
                    var totalTe = parseInt($('input[name="carrier_total_te"]').val()) || 12;
                    var selectedPanelId = $('select[name="carrier_panel_id"]').val() || 0;

                    self.saveCarrier(anlageId, carrierId, label, totalTe, selectedPanelId);
                });

                // Close
                $('#carrier-cancel, .kundenkarte-modal-close').on('click', function() {
                    $('#kundenkarte-carrier-dialog').remove();
                });

                $(document).on('keydown.carrierDialog', function(e) {
                    if (e.key === 'Escape') {
                        $('#kundenkarte-carrier-dialog').remove();
                        $(document).off('keydown.carrierDialog');
                    }
                });
            };

            // Load panels for the anlage
            var loadPanelsAndShow = function() {
                $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                    data: { action: 'list', anlage_id: self.currentAnlageId },
                    dataType: 'json',
                    success: function(response) {
                        var panels = response.success ? response.panels : [];
                        showDialog(carrierData, panels);
                    },
                    error: function() {
                        showDialog(carrierData, []);
                    }
                });
            };

            if (isEdit) {
                // Fetch existing carrier data via AJAX
                $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                    data: { action: 'get', carrier_id: carrierId },
                    dataType: 'json',
                    success: function(response) {
                        if (response.success && response.carrier) {
                            carrierData.label = response.carrier.label;
                            carrierData.total_te = response.carrier.total_te;
                            carrierData.fk_panel = response.carrier.fk_panel || 0;
                        }
                        loadPanelsAndShow();
                    },
                    error: function() {
                        // Fallback to DOM data
                        var $carrier = $('.kundenkarte-carrier[data-carrier-id="' + carrierId + '"]');
                        carrierData.label = $carrier.find('.kundenkarte-carrier-label').text();
                        var infoText = $carrier.find('.kundenkarte-carrier-info').text();
                        var match = infoText.match(/\/(\d+)/);
                        if (match) carrierData.total_te = parseInt(match[1]);
                        loadPanelsAndShow();
                    }
                });
            } else {
                carrierData.fk_panel = panelId;
                loadPanelsAndShow();
            }
        },

        saveCarrier: function(anlageId, carrierId, label, totalTe, panelId) {
            var self = this;

            // Prevent double-click
            if (self.isSaving) return;
            self.isSaving = true;
            $('#carrier-save').prop('disabled', true);

            var action = carrierId ? 'update' : 'create';

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                method: 'POST',
                data: {
                    action: action,
                    anlage_id: anlageId,
                    carrier_id: carrierId,
                    panel_id: panelId || 0,
                    label: label,
                    total_te: totalTe,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    self.isSaving = false;
                    if (response.success) {
                        $('#kundenkarte-carrier-dialog').remove();
                        // Reload page to get fresh PHP-rendered carriers
                        location.reload();
                    } else {
                        $('#carrier-save').prop('disabled', false);
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    self.isSaving = false;
                    $('#carrier-save').prop('disabled', false);
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        deleteCarrier: function(carrierId) {
            var self = this;

            self.showConfirmDialog('Hutschiene löschen', 'Möchten Sie diese Hutschiene wirklich löschen? Alle Equipment darauf wird ebenfalls gelöscht.', function() {
                $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                    method: 'POST',
                    data: {
                        action: 'delete',
                        carrier_id: carrierId,
                        token: $('input[name="token"]').val()
                    },
                    dataType: 'json',
                    success: function(response) {
                        if (response.success) {
                            location.reload();
                        } else {
                            self.showAlertDialog('Fehler', response.error);
                        }
                    }
                });
            });
        },

        showEquipmentDialog: function(carrierId, equipmentId, position) {
            var self = this;

            // Prevent opening multiple dialogs
            if ($('#kundenkarte-equipment-dialog').length) return;

            var isEdit = !!equipmentId;
            var title = isEdit ? 'Equipment bearbeiten' : 'Equipment hinzufügen';

            // First, load equipment types
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_type_fields.php',
                data: { type_id: 0 }, // Get types list
                dataType: 'json',
                success: function() {
                    self.renderEquipmentDialog(carrierId, equipmentId, position, title, isEdit);
                }
            });
        },

        renderEquipmentDialog: function(carrierId, equipmentId, position, title, isEdit) {
            var self = this;

            var html = '<div id="kundenkarte-equipment-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:500px;">';
            html += '<div class="kundenkarte-modal-header"><h3>' + title + '</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';
            html += '<input type="hidden" name="equipment_carrier_id" value="' + (carrierId || '') + '">';
            html += '<input type="hidden" name="equipment_id" value="' + (equipmentId || '') + '">';
            html += '<input type="hidden" name="equipment_position" value="' + (position || '') + '">';
            html += '<table class="noborder" style="width:100%;">';
            html += '<tr><td class="titlefield">Typ <span class="fieldrequired">*</span></td>';
            html += '<td><select name="equipment_type_id" id="equipment_type_id" class="flat minwidth200">';
            html += '<option value="">-- Typ wählen --</option>';
            html += '</select></td></tr>';
            html += '<tr><td>Bezeichnung</td>';
            html += '<td><input type="text" name="equipment_label" class="flat minwidth200"></td></tr>';
            html += '<tbody id="equipment-dynamic-fields"></tbody>';
            html += '<tr class="protection-fields"><td colspan="2" style="padding-top:15px;border-top:1px solid #444;">';
            html += '<strong><i class="fa fa-shield"></i> FI/RCD-Zuordnung</strong></td></tr>';
            html += '<tr class="protection-fields"><td>Schutzeinrichtung</td>';
            html += '<td><select name="equipment_fk_protection" id="equipment_fk_protection" class="flat minwidth200">';
            html += '<option value="">-- Keine --</option>';
            html += '</select></td></tr>';
            html += '<tr class="protection-fields"><td>Schutzbezeichnung</td>';
            html += '<td><input type="text" name="equipment_protection_label" class="flat minwidth200" placeholder="z.B. FI 40A/30mA"></td></tr>';
            html += '</table>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="equipment-save"><i class="fa fa-save"></i> Speichern</button> ';
            if (isEdit) {
                html += '<button type="button" class="button" id="equipment-delete" style="background:#c0392b;color:#fff;"><i class="fa fa-trash"></i> Löschen</button> ';
            }
            html += '<button type="button" class="button" id="equipment-cancel">Abbrechen</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-equipment-dialog').addClass('visible');

            // Load equipment types into select
            self.loadEquipmentTypes(equipmentId);

            // Save button
            $('#equipment-save').on('click', function() {
                self.saveEquipment();
            });

            // Delete button
            $('#equipment-delete').on('click', function() {
                $('#kundenkarte-equipment-dialog').remove();
                self.showConfirmDialog('Equipment löschen', 'Möchten Sie dieses Equipment wirklich löschen?', function() {
                    self.deleteEquipment(equipmentId);
                });
            });

            // Close
            $('#equipment-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-equipment-dialog').remove();
            });

            $(document).on('keydown.equipmentDialog', function(e) {
                if (e.key === 'Escape') {
                    $('#kundenkarte-equipment-dialog').remove();
                    $(document).off('keydown.equipmentDialog');
                }
            });
        },

        loadEquipmentTypes: function(equipmentId) {
            var self = this;

            // Get equipment types from admin config (stored in page data or via AJAX)
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                data: { action: 'get_types', system_id: self.currentSystemId },
                dataType: 'json',
                success: function(response) {
                    if (response.types) {
                        var $select = $('#equipment_type_id');
                        // Clear existing options except first placeholder
                        $select.find('option:not(:first)').remove();
                        response.types.forEach(function(type) {
                            $select.append('<option value="' + type.id + '">' + self.escapeHtml(type.label) + '</option>');
                        });

                        // Load protection devices
                        self.loadProtectionDevices();

                        // If editing, load equipment data
                        if (equipmentId) {
                            self.loadEquipmentData(equipmentId);
                        }
                    }
                }
            });
        },

        loadProtectionDevices: function() {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                data: { action: 'get_protection_devices', anlage_id: self.currentAnlageId },
                dataType: 'json',
                success: function(response) {
                    if (response.success && response.devices) {
                        var $select = $('#equipment_fk_protection');
                        $select.find('option:not(:first)').remove();
                        response.devices.forEach(function(device) {
                            $select.append('<option value="' + device.id + '">' + self.escapeHtml(device.display_label) + '</option>');
                        });
                    }
                }
            });
        },

        loadEquipmentData: function(equipmentId) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                data: { action: 'get', equipment_id: equipmentId },
                dataType: 'json',
                success: function(response) {
                    if (response.equipment) {
                        var eq = response.equipment;
                        $('input[name="equipment_carrier_id"]').val(eq.fk_carrier);
                        $('input[name="equipment_label"]').val(eq.label);
                        $('input[name="equipment_position"]').val(eq.position_te);
                        $('#equipment_type_id').val(eq.type_id).trigger('change');
                        // Protection fields
                        if (eq.fk_protection) {
                            $('#equipment_fk_protection').val(eq.fk_protection);
                        }
                        if (eq.protection_label) {
                            $('input[name="equipment_protection_label"]').val(eq.protection_label);
                        }
                    }
                }
            });
        },

        loadEquipmentTypeFields: function(typeId) {
            var self = this;
            var $container = $('#equipment-dynamic-fields');
            var equipmentId = $('input[name="equipment_id"]').val();

            if (!typeId) {
                $container.html('');
                return;
            }

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_type_fields.php',
                data: { type_id: typeId, equipment_id: equipmentId },
                dataType: 'json',
                success: function(response) {
                    if (response.success && response.fields) {
                        var html = '';
                        response.fields.forEach(function(field) {
                            html += '<tr><td>' + self.escapeHtml(field.label);
                            if (field.required) html += ' <span class="fieldrequired">*</span>';
                            html += '</td><td>';
                            html += self.renderEquipmentField(field);
                            html += '</td></tr>';
                        });
                        $container.html(html);
                    } else {
                        $container.html('');
                    }
                }
            });
        },

        renderEquipmentField: function(field) {
            var name = 'eq_field_' + field.code;
            var value = field.value || '';
            var required = field.required ? ' required' : '';

            switch (field.type) {
                case 'select':
                    var html = '<select name="' + name + '" class="flat"' + required + '>';
                    html += '<option value="">--</option>';
                    if (field.options) {
                        field.options.split('|').forEach(function(opt) {
                            var selected = (opt === value) ? ' selected' : '';
                            html += '<option value="' + KundenKarte.Equipment.escapeHtml(opt) + '"' + selected + '>' + KundenKarte.Equipment.escapeHtml(opt) + '</option>';
                        });
                    }
                    html += '</select>';
                    return html;

                case 'number':
                    return '<input type="number" name="' + name + '" class="flat" value="' + this.escapeHtml(value) + '"' + required + '>';

                default:
                    return '<input type="text" name="' + name + '" class="flat minwidth200" value="' + this.escapeHtml(value) + '"' + required + '>';
            }
        },

        saveEquipment: function() {
            var self = this;

            // Prevent double-click
            if (self.isSaving) return;

            var carrierId = $('input[name="equipment_carrier_id"]').val();
            var equipmentId = $('input[name="equipment_id"]').val();
            var typeId = $('#equipment_type_id').val();
            var position = $('input[name="equipment_position"]').val();
            var label = $('input[name="equipment_label"]').val();
            var fkProtection = $('#equipment_fk_protection').val();
            var protectionLabel = $('input[name="equipment_protection_label"]').val();

            if (!typeId) {
                KundenKarte.showAlert('Hinweis', 'Bitte wählen Sie einen Typ.');
                return;
            }

            self.isSaving = true;
            $('#equipment-save').prop('disabled', true);

            // Collect field values
            var fieldValues = {};
            $('#equipment-dynamic-fields input, #equipment-dynamic-fields select').each(function() {
                var name = $(this).attr('name');
                if (name && name.startsWith('eq_field_')) {
                    var code = name.replace('eq_field_', '');
                    fieldValues[code] = $(this).val();
                }
            });

            var action = equipmentId ? 'update' : 'create';

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: action,
                    carrier_id: carrierId,
                    equipment_id: equipmentId,
                    type_id: typeId,
                    label: label,
                    position_te: position,
                    fk_protection: fkProtection,
                    protection_label: protectionLabel,
                    field_values: JSON.stringify(fieldValues),
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    self.isSaving = false;
                    if (response.success) {
                        $('#kundenkarte-equipment-dialog').remove();
                        // Reload page to get fresh data
                        location.reload();
                    } else {
                        $('#equipment-save').prop('disabled', false);
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    self.isSaving = false;
                    $('#equipment-save').prop('disabled', false);
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        duplicateEquipment: function(equipmentId) {
            var self = this;

            if (self.isSaving) return;
            self.isSaving = true;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'duplicate',
                    equipment_id: equipmentId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    self.isSaving = false;
                    if (response.success) {
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    self.isSaving = false;
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        deleteEquipment: function(equipmentId) {
            var self = this;

            // No confirm here - handled by caller
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'delete',
                    equipment_id: equipmentId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        location.reload();
                    } else {
                        self.showAlertDialog('Fehler', response.error);
                    }
                }
            });
        },

        moveEquipment: function(equipmentId, newPosition) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'move',
                    equipment_id: equipmentId,
                    position_te: newPosition,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                }
            });
        },

        showEquipmentTooltip: function($block, data) {
            var self = this;

            var html = '<div class="kundenkarte-equipment-tooltip-header">';
            html += '<strong>' + this.escapeHtml(data.type || '') + '</strong>';
            if (data.label) {
                html += '<br><span style="color:#666;">' + this.escapeHtml(data.label) + '</span>';
            }
            html += '</div>';

            if (data.fields && Object.keys(data.fields).length > 0) {
                html += '<div class="kundenkarte-equipment-tooltip-fields">';
                for (var key in data.fields) {
                    if (data.fields[key]) {
                        html += '<div><span class="field-label">' + this.escapeHtml(key) + ':</span> ';
                        html += '<span class="field-value">' + this.escapeHtml(data.fields[key]) + '</span></div>';
                    }
                }
                html += '</div>';
            }

            var $tooltip = $('#kundenkarte-equipment-tooltip');
            if (!$tooltip.length) {
                $tooltip = $('<div id="kundenkarte-equipment-tooltip" class="kundenkarte-equipment-tooltip"></div>');
                $('body').append($tooltip);
            }

            $tooltip.html(html);

            // Position near the block
            var offset = $block.offset ? $block.offset() : $(this).offset();
            var rect = $block[0].getBoundingClientRect ? $block[0].getBoundingClientRect() : { right: 0, top: 0 };

            $tooltip.css({
                top: rect.top + window.scrollY + 10,
                left: rect.right + window.scrollX + 10
            }).addClass('visible');
        },

        hideEquipmentTooltip: function() {
            $('#kundenkarte-equipment-tooltip').removeClass('visible');
        },

        // ==========================================
        // CONNECTION METHODS (Stromverbindungen)
        // ==========================================

        showOutputDialog: function(carrierId) {
            var self = this;

            if ($('#kundenkarte-output-dialog').length) return;

            // Get equipment on this carrier for dropdown
            var $carrier = $('.kundenkarte-carrier[data-carrier-id="' + carrierId + '"]');
            var equipmentOptions = [];

            $carrier.find('.kundenkarte-equipment-block').each(function() {
                var $block = $(this);
                var tooltipData = $block.data('tooltip');
                var id = $block.data('equipment-id');
                var label = tooltipData ? (tooltipData.label || tooltipData.type || 'Equipment ' + id) : 'Equipment ' + id;
                equipmentOptions.push({ id: id, label: label });
            });

            var html = '<div id="kundenkarte-output-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:500px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Abgang hinzufügen</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';
            html += '<div class="kundenkarte-connection-form">';

            // Equipment selection
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Von Equipment</label>';
            html += '<select name="output_equipment_id" id="output_equipment_id" class="flat">';
            equipmentOptions.forEach(function(eq) {
                html += '<option value="' + eq.id + '">' + self.escapeHtml(eq.label) + '</option>';
            });
            html += '</select>';
            html += '</div>';
            html += '</div>';

            // Phase selection
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Phasen</label>';
            html += '<div class="kundenkarte-phase-buttons">';
            html += '<button type="button" class="kundenkarte-phase-btn phase-L1" data-phase="L1">L1</button>';
            html += '<button type="button" class="kundenkarte-phase-btn phase-N" data-phase="N">N</button>';
            html += '<button type="button" class="kundenkarte-phase-btn active" data-phase="L1N">L1+N</button>';
            html += '<button type="button" class="kundenkarte-phase-btn" data-phase="L1L2L3">3P</button>';
            html += '<button type="button" class="kundenkarte-phase-btn" data-phase="L1L2L3N">3P+N</button>';
            html += '<button type="button" class="kundenkarte-phase-btn" data-phase="L1L2L3NPE">3P+N+PE</button>';
            html += '</div>';
            html += '<input type="hidden" name="output_connection_type" value="L1N">';
            html += '</div>';
            html += '</div>';

            // Consumer label
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Verbraucher</label>';
            html += '<input type="text" name="output_consumer_label" placeholder="z.B. Küche Steckdosen">';
            html += '</div>';
            html += '</div>';

            // Cable info
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Kabeltyp</label>';
            html += '<select name="output_cable_type">';
            html += '<option value="">--</option>';
            html += '<option value="NYM-J">NYM-J</option>';
            html += '<option value="NYY-J">NYY-J</option>';
            html += '<option value="H07V-K">H07V-K</option>';
            html += '<option value="H07V-U">H07V-U</option>';
            html += '<option value="H05VV-F">H05VV-F</option>';
            html += '</select>';
            html += '</div>';
            html += '<div class="form-group">';
            html += '<label>Querschnitt</label>';
            html += '<select name="output_cable_section">';
            html += '<option value="">--</option>';
            html += '<option value="3x1.5">3x1.5</option>';
            html += '<option value="3x2.5">3x2.5</option>';
            html += '<option value="5x1.5">5x1.5</option>';
            html += '<option value="5x2.5">5x2.5</option>';
            html += '<option value="5x4">5x4</option>';
            html += '<option value="5x6">5x6</option>';
            html += '<option value="5x10">5x10</option>';
            html += '</select>';
            html += '</div>';
            html += '</div>';

            html += '</div>'; // form
            html += '</div>'; // body
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="output-save"><i class="fa fa-save"></i> Speichern</button> ';
            html += '<button type="button" class="button" id="output-cancel">Abbrechen</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-output-dialog').addClass('visible');

            // Phase button handlers
            $('#kundenkarte-output-dialog .kundenkarte-phase-btn').on('click', function() {
                $('#kundenkarte-output-dialog .kundenkarte-phase-btn').removeClass('active');
                $(this).addClass('active');
                $('input[name="output_connection_type"]').val($(this).data('phase'));
            });

            // Save
            $('#output-save').on('click', function() {
                self.saveOutput(carrierId);
            });

            // Close
            $('#output-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-output-dialog').remove();
            });
        },

        saveOutput: function(carrierId) {
            var self = this;

            var data = {
                action: 'create_output',
                carrier_id: carrierId,
                equipment_id: $('select[name="output_equipment_id"]').val(),
                connection_type: $('input[name="output_connection_type"]').val(),
                output_label: $('input[name="output_consumer_label"]').val(),
                medium_type: $('select[name="output_cable_type"]').val(),
                medium_spec: $('select[name="output_cable_section"]').val(),
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-output-dialog').remove();
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        showRailDialog: function(carrierId) {
            var self = this;

            if ($('#kundenkarte-rail-dialog').length) return;

            // Get carrier info
            var $carrier = $('.kundenkarte-carrier[data-carrier-id="' + carrierId + '"]');
            var totalTE = 12;
            var infoText = $carrier.find('.kundenkarte-carrier-info').text();
            var match = infoText.match(/\/(\d+)/);
            if (match) totalTE = parseInt(match[1]);

            var html = '<div id="kundenkarte-rail-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:450px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Sammelschiene hinzufügen</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';
            html += '<div class="kundenkarte-connection-form">';

            // Quick presets row
            html += '<div class="form-row" style="margin-bottom:10px;">';
            html += '<label style="width:100%;margin-bottom:5px;">Schnellauswahl:</label>';
            html += '<div style="display:flex;flex-wrap:wrap;gap:5px;">';
            // Electrical presets
            html += '<button type="button" class="rail-preset-btn" data-type="L1" data-color="#8B4513" style="padding:3px 8px;font-size:11px;">L1</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="L1N" data-color="#3498db" style="padding:3px 8px;font-size:11px;">L1N</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="3P" data-color="#2c3e50" style="padding:3px 8px;font-size:11px;">3P</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="3P+N" data-color="#2c3e50" style="padding:3px 8px;font-size:11px;">3P+N</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="N" data-color="#0066cc" style="padding:3px 8px;font-size:11px;">N</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="PE" data-color="#27ae60" style="padding:3px 8px;font-size:11px;">PE</button>';
            html += '|';
            // Network presets
            html += '<button type="button" class="rail-preset-btn" data-type="CAT6" data-color="#9b59b6" style="padding:3px 8px;font-size:11px;">CAT6</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="LWL" data-color="#f39c12" style="padding:3px 8px;font-size:11px;">LWL</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="Koax" data-color="#e74c3c" style="padding:3px 8px;font-size:11px;">Koax</button>';
            html += '</div>';
            html += '</div>';

            // Connection type (free text)
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Bezeichnung</label>';
            html += '<input type="text" name="rail_connection_type" value="" placeholder="z.B. L1N, CAT6, BUS, Klingel">';
            html += '</div>';
            html += '<div class="form-group">';
            html += '<label>Farbe</label>';
            html += '<input type="color" name="rail_color" value="#3498db">';
            html += '</div>';
            html += '</div>';

            // Position (above/below)
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Position</label>';
            html += '<select name="rail_position">';
            html += '<option value="below">Unterhalb (Standard)</option>';
            html += '<option value="above">Oberhalb</option>';
            html += '</select>';
            html += '</div>';
            html += '</div>';

            // TE range
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Von TE</label>';
            html += '<input type="number" name="rail_start_te" value="1" min="1" max="' + totalTE + '">';
            html += '</div>';
            html += '<div class="form-group">';
            html += '<label>Bis TE</label>';
            html += '<input type="number" name="rail_end_te" value="' + totalTE + '" min="1" max="' + totalTE + '">';
            html += '</div>';
            html += '</div>';

            // Multi-phase rail options
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Sammelschiene</label>';
            html += '<select name="rail_phases">';
            html += '<option value="">Einfache Linie</option>';
            html += '<option value="L1">L1 (einphasig)</option>';
            html += '<option value="L1N">L1+N (einphasig)</option>';
            html += '<option value="3P">3P (L1/L2/L3)</option>';
            html += '<option value="3P+N">3P+N (L1/L2/L3/N)</option>';
            html += '</select>';
            html += '</div>';
            html += '</div>';

            // Excluded positions (for FI switches etc.)
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;">';
            html += '<label>Ausgenommene TE (z.B. für FI)</label>';
            html += '<input type="text" name="rail_excluded_te" value="" placeholder="z.B. 3,4,7 (kommagetrennt)">';
            html += '<small style="color:#666;font-size:11px;">An diesen Positionen wird die Schiene unterbrochen</small>';
            html += '</div>';
            html += '</div>';

            html += '</div>'; // form
            html += '</div>'; // body
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="rail-save"><i class="fa fa-save"></i> Speichern</button> ';
            html += '<button type="button" class="button" id="rail-cancel">Abbrechen</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-rail-dialog').addClass('visible');

            // Preset button handlers
            $('#kundenkarte-rail-dialog .rail-preset-btn').on('click', function() {
                var type = $(this).data('type');
                $('input[name="rail_connection_type"]').val(type);
                $('input[name="rail_color"]').val($(this).data('color'));

                // Auto-set rail_phases for electrical presets
                var phasesSelect = $('select[name="rail_phases"]');
                if (type === 'L1') phasesSelect.val('L1');
                else if (type === 'L1N') phasesSelect.val('L1N');
                else if (type === '3P') phasesSelect.val('3P');
                else if (type === '3P+N') phasesSelect.val('3P+N');
                else phasesSelect.val(''); // Simple line for N, PE, network cables
            });

            // Save
            $('#rail-save').on('click', function() {
                self.saveRail(carrierId);
            });

            // Close
            $('#rail-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-rail-dialog').remove();
            });
        },

        saveRail: function(carrierId) {
            var self = this;

            // position_y: -1 = above equipment, 0+ = below equipment
            var positionY = $('select[name="rail_position"]').val() === 'above' ? -1 : 0;

            var data = {
                action: 'create_rail',
                carrier_id: carrierId,
                connection_type: $('input[name="rail_connection_type"]').val(),
                color: $('input[name="rail_color"]').val(),
                rail_start_te: $('input[name="rail_start_te"]').val(),
                rail_end_te: $('input[name="rail_end_te"]').val(),
                rail_phases: $('select[name="rail_phases"]').val(),
                excluded_te: $('input[name="rail_excluded_te"]').val(),
                position_y: positionY,
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-rail-dialog').remove();
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        showEditRailDialog: function(connectionId, carrierId) {
            var self = this;

            if ($('#kundenkarte-rail-dialog').length) return;

            // Load connection data first
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                data: { action: 'get', connection_id: connectionId },
                dataType: 'json',
                success: function(response) {
                    if (response.success && response.connection) {
                        self.renderEditRailDialog(connectionId, carrierId, response.connection);
                    } else {
                        KundenKarte.showAlert('Fehler', 'Verbindung nicht gefunden');
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        renderEditRailDialog: function(connectionId, carrierId, conn) {
            var self = this;

            // Get carrier info
            var $carrier = $('.kundenkarte-carrier[data-carrier-id="' + carrierId + '"]');
            var totalTE = 12;
            var infoText = $carrier.find('.kundenkarte-carrier-info').text();
            var match = infoText.match(/\/(\d+)/);
            if (match) totalTE = parseInt(match[1]);

            var isAbove = conn.position_y < 0;

            var html = '<div id="kundenkarte-rail-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:450px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Sammelschiene bearbeiten</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';
            html += '<input type="hidden" name="rail_connection_id" value="' + connectionId + '">';
            html += '<div class="kundenkarte-connection-form">';

            // Quick presets row
            html += '<div class="form-row" style="margin-bottom:10px;">';
            html += '<label style="width:100%;margin-bottom:5px;">Schnellauswahl:</label>';
            html += '<div style="display:flex;flex-wrap:wrap;gap:5px;">';
            html += '<button type="button" class="rail-preset-btn" data-type="L1" data-color="#8B4513" style="padding:3px 8px;font-size:11px;">L1</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="L1N" data-color="#3498db" style="padding:3px 8px;font-size:11px;">L1N</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="3P" data-color="#2c3e50" style="padding:3px 8px;font-size:11px;">3P</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="3P+N" data-color="#2c3e50" style="padding:3px 8px;font-size:11px;">3P+N</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="N" data-color="#0066cc" style="padding:3px 8px;font-size:11px;">N</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="PE" data-color="#27ae60" style="padding:3px 8px;font-size:11px;">PE</button>';
            html += '|';
            html += '<button type="button" class="rail-preset-btn" data-type="CAT6" data-color="#9b59b6" style="padding:3px 8px;font-size:11px;">CAT6</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="LWL" data-color="#f39c12" style="padding:3px 8px;font-size:11px;">LWL</button>';
            html += '<button type="button" class="rail-preset-btn" data-type="Koax" data-color="#e74c3c" style="padding:3px 8px;font-size:11px;">Koax</button>';
            html += '</div>';
            html += '</div>';

            // Connection type (free text)
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Bezeichnung</label>';
            html += '<input type="text" name="rail_connection_type" value="' + self.escapeHtml(conn.connection_type || '') + '" placeholder="z.B. L1N, CAT6, BUS, Klingel">';
            html += '</div>';
            html += '<div class="form-group">';
            html += '<label>Farbe</label>';
            html += '<input type="color" name="rail_color" value="' + (conn.color || '#3498db') + '">';
            html += '</div>';
            html += '</div>';

            // Position (above/below)
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Position</label>';
            html += '<select name="rail_position">';
            html += '<option value="below"' + (!isAbove ? ' selected' : '') + '>Unterhalb</option>';
            html += '<option value="above"' + (isAbove ? ' selected' : '') + '>Oberhalb</option>';
            html += '</select>';
            html += '</div>';
            html += '</div>';

            // TE range
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Von TE</label>';
            html += '<input type="number" name="rail_start_te" value="' + (conn.rail_start_te || 1) + '" min="1" max="' + totalTE + '">';
            html += '</div>';
            html += '<div class="form-group">';
            html += '<label>Bis TE</label>';
            html += '<input type="number" name="rail_end_te" value="' + (conn.rail_end_te || totalTE) + '" min="1" max="' + totalTE + '">';
            html += '</div>';
            html += '</div>';

            // Multi-phase rail options
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Sammelschiene</label>';
            html += '<select name="rail_phases">';
            html += '<option value=""' + (!conn.rail_phases ? ' selected' : '') + '>Einfache Linie</option>';
            html += '<option value="L1"' + (conn.rail_phases === 'L1' ? ' selected' : '') + '>L1 (einphasig)</option>';
            html += '<option value="L1N"' + (conn.rail_phases === 'L1N' ? ' selected' : '') + '>L1+N (einphasig)</option>';
            html += '<option value="3P"' + (conn.rail_phases === '3P' ? ' selected' : '') + '>3P (L1/L2/L3)</option>';
            html += '<option value="3P+N"' + (conn.rail_phases === '3P+N' ? ' selected' : '') + '>3P+N (L1/L2/L3/N)</option>';
            html += '</select>';
            html += '</div>';
            html += '</div>';

            // Excluded positions (for FI switches etc.)
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;">';
            html += '<label>Ausgenommene TE (z.B. für FI)</label>';
            html += '<input type="text" name="rail_excluded_te" value="' + self.escapeHtml(conn.excluded_te || '') + '" placeholder="z.B. 3,4,7 (kommagetrennt)">';
            html += '<small style="color:#666;font-size:11px;">An diesen Positionen wird die Schiene unterbrochen</small>';
            html += '</div>';
            html += '</div>';

            html += '</div>'; // form
            html += '</div>'; // body
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="rail-save"><i class="fa fa-save"></i> Speichern</button> ';
            html += '<button type="button" class="button" id="rail-delete" style="background:#c0392b;color:#fff;"><i class="fa fa-trash"></i> Löschen</button> ';
            html += '<button type="button" class="button" id="rail-cancel">Abbrechen</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-rail-dialog').addClass('visible');

            // Preset button handlers
            $('#kundenkarte-rail-dialog .rail-preset-btn').on('click', function() {
                var type = $(this).data('type');
                $('input[name="rail_connection_type"]').val(type);
                $('input[name="rail_color"]').val($(this).data('color'));

                // Auto-set rail_phases for electrical presets
                var phasesSelect = $('select[name="rail_phases"]');
                if (type === 'L1') phasesSelect.val('L1');
                else if (type === 'L1N') phasesSelect.val('L1N');
                else if (type === '3P') phasesSelect.val('3P');
                else if (type === '3P+N') phasesSelect.val('3P+N');
                else phasesSelect.val(''); // Simple line for N, PE, network cables
            });

            // Save
            $('#rail-save').on('click', function() {
                self.updateRail(connectionId, carrierId);
            });

            // Delete
            $('#rail-delete').on('click', function() {
                $('#kundenkarte-rail-dialog').remove();
                self.showConfirmDialog('Sammelschiene löschen', 'Möchten Sie diese Sammelschiene wirklich löschen?', function() {
                    self.doDeleteConnection(connectionId);
                });
            });

            // Close
            $('#rail-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-rail-dialog').remove();
            });
        },

        updateRail: function(connectionId, carrierId) {
            var self = this;

            var positionY = $('select[name="rail_position"]').val() === 'above' ? -1 : 0;

            var data = {
                action: 'update',
                connection_id: connectionId,
                carrier_id: carrierId,
                connection_type: $('input[name="rail_connection_type"]').val(),
                color: $('input[name="rail_color"]').val(),
                rail_start_te: $('input[name="rail_start_te"]').val(),
                rail_end_te: $('input[name="rail_end_te"]').val(),
                rail_phases: $('select[name="rail_phases"]').val(),
                excluded_te: $('input[name="rail_excluded_te"]').val(),
                position_y: positionY,
                is_rail: 1,
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-rail-dialog').remove();
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        showEditOutputDialog: function(connectionId, carrierId) {
            var self = this;

            if ($('#kundenkarte-output-dialog').length) return;

            // Load connection data first
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                data: { action: 'get', connection_id: connectionId },
                dataType: 'json',
                success: function(response) {
                    if (response.success && response.connection) {
                        self.renderEditOutputDialog(connectionId, carrierId, response.connection);
                    } else {
                        KundenKarte.showAlert('Fehler', 'Verbindung nicht gefunden');
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        renderEditOutputDialog: function(connectionId, carrierId, conn) {
            var self = this;

            var html = '<div id="kundenkarte-output-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:450px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Abgang bearbeiten</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';
            html += '<input type="hidden" name="output_connection_id" value="' + connectionId + '">';
            html += '<input type="hidden" name="output_fk_source" value="' + (conn.fk_source || '') + '">';
            html += '<div class="kundenkarte-connection-form">';

            // Quick presets
            html += '<div class="form-row" style="margin-bottom:10px;">';
            html += '<label style="width:100%;margin-bottom:5px;">Schnellauswahl Typ:</label>';
            html += '<div style="display:flex;flex-wrap:wrap;gap:5px;">';
            html += '<button type="button" class="output-preset-btn" data-type="L1N" data-color="#3498db" style="padding:3px 8px;font-size:11px;">L1N</button>';
            html += '<button type="button" class="output-preset-btn" data-type="3P" data-color="#2c3e50" style="padding:3px 8px;font-size:11px;">3P</button>';
            html += '<button type="button" class="output-preset-btn" data-type="3P+N" data-color="#2c3e50" style="padding:3px 8px;font-size:11px;">3P+N</button>';
            html += '|';
            html += '<button type="button" class="output-preset-btn" data-type="CAT6" data-color="#9b59b6" style="padding:3px 8px;font-size:11px;">CAT6</button>';
            html += '<button type="button" class="output-preset-btn" data-type="LWL" data-color="#f39c12" style="padding:3px 8px;font-size:11px;">LWL</button>';
            html += '</div>';
            html += '</div>';

            // Output label (consumer)
            html += '<div class="form-row">';
            html += '<div class="form-group" style="flex:2;">';
            html += '<label>Ziel/Verbraucher</label>';
            html += '<input type="text" name="output_label" value="' + self.escapeHtml(conn.output_label || '') + '" placeholder="z.B. Küche Steckdosen, Bad Licht">';
            html += '</div>';
            html += '</div>';

            // Connection type and color
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Typ</label>';
            html += '<input type="text" name="output_connection_type" value="' + self.escapeHtml(conn.connection_type || '') + '" placeholder="z.B. L1N">';
            html += '</div>';
            html += '<div class="form-group">';
            html += '<label>Farbe</label>';
            html += '<input type="color" name="output_color" value="' + (conn.color || '#3498db') + '">';
            html += '</div>';
            html += '</div>';

            // Medium info
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Kabeltyp</label>';
            html += '<input type="text" name="output_medium_type" value="' + self.escapeHtml(conn.medium_type || '') + '" placeholder="z.B. NYM-J">';
            html += '</div>';
            html += '<div class="form-group">';
            html += '<label>Querschnitt</label>';
            html += '<input type="text" name="output_medium_spec" value="' + self.escapeHtml(conn.medium_spec || '') + '" placeholder="z.B. 3x1.5">';
            html += '</div>';
            html += '</div>';

            // Length
            html += '<div class="form-row">';
            html += '<div class="form-group">';
            html += '<label>Länge</label>';
            html += '<input type="text" name="output_medium_length" value="' + self.escapeHtml(conn.medium_length || '') + '" placeholder="z.B. ca. 15m">';
            html += '</div>';
            html += '</div>';

            html += '</div>'; // form
            html += '</div>'; // body
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="output-save"><i class="fa fa-save"></i> Speichern</button> ';
            html += '<button type="button" class="button" id="output-delete" style="background:#c0392b;color:#fff;"><i class="fa fa-trash"></i> Löschen</button> ';
            html += '<button type="button" class="button" id="output-cancel">Abbrechen</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-output-dialog').addClass('visible');

            // Preset button handlers
            $('#kundenkarte-output-dialog .output-preset-btn').on('click', function() {
                $('input[name="output_connection_type"]').val($(this).data('type'));
                $('input[name="output_color"]').val($(this).data('color'));
            });

            // Save
            $('#output-save').on('click', function() {
                self.updateOutput(connectionId, carrierId);
            });

            // Delete
            $('#output-delete').on('click', function() {
                $('#kundenkarte-output-dialog').remove();
                self.showConfirmDialog('Abgang löschen', 'Möchten Sie diesen Abgang wirklich löschen?', function() {
                    self.doDeleteConnection(connectionId);
                });
            });

            // Close
            $('#output-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-output-dialog').remove();
            });
        },

        updateOutput: function(connectionId, carrierId) {
            var self = this;

            var data = {
                action: 'update',
                connection_id: connectionId,
                carrier_id: carrierId,
                fk_source: $('input[name="output_fk_source"]').val(),
                source_terminal: 'output',
                connection_type: $('input[name="output_connection_type"]').val(),
                color: $('input[name="output_color"]').val(),
                output_label: $('input[name="output_label"]').val(),
                medium_type: $('input[name="output_medium_type"]').val(),
                medium_spec: $('input[name="output_medium_spec"]').val(),
                medium_length: $('input[name="output_medium_length"]').val(),
                is_rail: 0,
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-output-dialog').remove();
                        location.reload();
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        deleteConnection: function(connectionId) {
            var self = this;

            self.showConfirmDialog('Verbindung löschen', 'Möchten Sie diese Verbindung wirklich löschen?', function() {
                self.doDeleteConnection(connectionId);
            });
        },

        // Internal function to delete connection without confirmation
        doDeleteConnection: function(connectionId) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'delete',
                    connection_id: connectionId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        location.reload();
                    } else {
                        self.showAlertDialog('Fehler', response.error);
                    }
                }
            });
        },

        // Custom confirm dialog (replaces browser confirm())
        showConfirmDialog: function(title, message, onConfirm, onCancel) {
            var self = this;

            // Remove any existing confirm dialog
            $('#kundenkarte-confirm-dialog').remove();

            var html = '<div id="kundenkarte-confirm-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:400px;">';
            html += '<div class="kundenkarte-modal-header"><h3>' + self.escapeHtml(title) + '</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body" style="padding:20px;">';
            html += '<p style="margin:0;font-size:14px;">' + self.escapeHtml(message) + '</p>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer" style="display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button type="button" class="button" id="confirm-yes" style="background:#c0392b;color:#fff;"><i class="fa fa-check"></i> Ja</button>';
            html += '<button type="button" class="button" id="confirm-no"><i class="fa fa-times"></i> Nein</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-confirm-dialog').addClass('visible');

            // Focus yes button
            $('#confirm-yes').focus();

            // Yes button
            $('#confirm-yes').on('click', function() {
                $('#kundenkarte-confirm-dialog').remove();
                if (typeof onConfirm === 'function') {
                    onConfirm();
                }
            });

            // No button and close
            $('#confirm-no, #kundenkarte-confirm-dialog .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-confirm-dialog').remove();
                if (typeof onCancel === 'function') {
                    onCancel();
                }
            });

            // ESC key
            $(document).one('keydown.confirmDialog', function(e) {
                if (e.key === 'Escape') {
                    $('#kundenkarte-confirm-dialog').remove();
                    if (typeof onCancel === 'function') {
                        onCancel();
                    }
                } else if (e.key === 'Enter') {
                    $('#kundenkarte-confirm-dialog').remove();
                    if (typeof onConfirm === 'function') {
                        onConfirm();
                    }
                }
            });
        },

        // Custom alert dialog (replaces browser alert())
        showAlertDialog: function(title, message, onClose) {
            var self = this;

            // Remove any existing alert dialog
            $('#kundenkarte-alert-dialog').remove();

            var html = '<div id="kundenkarte-alert-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:400px;">';
            html += '<div class="kundenkarte-modal-header"><h3>' + self.escapeHtml(title) + '</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body" style="padding:20px;">';
            html += '<p style="margin:0;font-size:14px;">' + self.escapeHtml(message) + '</p>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer" style="display:flex;justify-content:flex-end;">';
            html += '<button type="button" class="button" id="alert-ok"><i class="fa fa-check"></i> OK</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-alert-dialog').addClass('visible');

            $('#alert-ok').focus();

            var closeDialog = function() {
                $('#kundenkarte-alert-dialog').remove();
                $(document).off('keydown.alertDialog');
                if (typeof onClose === 'function') {
                    onClose();
                }
            };

            $('#alert-ok, #kundenkarte-alert-dialog .kundenkarte-modal-close').on('click', closeDialog);

            $(document).on('keydown.alertDialog', function(e) {
                if (e.key === 'Escape' || e.key === 'Enter') {
                    closeDialog();
                }
            });
        },

        escapeHtml: function(text) {
            if (!text) return '';
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        },

        // BOM (Bill of Materials) / Stückliste Dialog
        showBOMDialog: function() {
            var self = this;
            var anlageId = this.anlageId;

            // Show loading
            var html = '<div id="kundenkarte-bom-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:900px;max-height:80vh;">';
            html += '<div class="kundenkarte-modal-header" style="background:#9b59b6;">';
            html += '<h3 style="color:#fff;"><i class="fa fa-list-alt"></i> Stückliste (BOM)</h3>';
            html += '<span class="kundenkarte-modal-close" style="color:#fff;">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body" style="padding:20px;overflow:auto;max-height:calc(80vh - 130px);">';
            html += '<div class="bom-loading" style="text-align:center;padding:40px;"><i class="fa fa-spinner fa-spin fa-2x"></i><br>Lade Stückliste...</div>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer" style="display:flex;justify-content:space-between;">';
            html += '<span class="bom-totals" style="color:#888;"></span>';
            html += '<button type="button" class="button" id="bom-close"><i class="fa fa-times"></i> Schließen</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-bom-dialog').addClass('visible');

            // Close handler
            $('#bom-close, #kundenkarte-bom-dialog .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-bom-dialog').remove();
            });

            $(document).on('keydown.bomDialog', function(e) {
                if (e.key === 'Escape') {
                    $('#kundenkarte-bom-dialog').remove();
                    $(document).off('keydown.bomDialog');
                }
            });

            // Load BOM data
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/bom_generator.php',
                data: { action: 'generate', anlage_id: anlageId },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.renderBOMContent(response);
                    } else {
                        $('.bom-loading').html('<div style="color:#e74c3c;"><i class="fa fa-exclamation-triangle"></i> ' + (response.error || 'Fehler beim Laden') + '</div>');
                    }
                },
                error: function() {
                    $('.bom-loading').html('<div style="color:#e74c3c;"><i class="fa fa-exclamation-triangle"></i> AJAX Fehler</div>');
                }
            });
        },

        renderBOMContent: function(data) {
            var self = this;
            var $body = $('#kundenkarte-bom-dialog .kundenkarte-modal-body');

            if (!data.summary || data.summary.length === 0) {
                $body.html('<div style="text-align:center;padding:40px;color:#888;"><i class="fa fa-info-circle fa-2x"></i><br><br>Keine Materialien im Schaltplan gefunden.<br>Fügen Sie Equipment hinzu oder verknüpfen Sie Produkte.</div>');
                return;
            }

            var html = '';

            // Summary table (grouped by product)
            html += '<h4 style="margin:0 0 15px 0;color:#9b59b6;"><i class="fa fa-cubes"></i> Zusammenfassung nach Produkt</h4>';
            html += '<table class="noborder centpercent" style="font-size:13px;">';
            html += '<tr class="liste_titre">';
            html += '<th>Referenz</th>';
            html += '<th>Bezeichnung</th>';
            html += '<th class="right">Menge</th>';
            html += '<th class="right">Einzelpreis</th>';
            html += '<th class="right">Gesamt</th>';
            html += '</tr>';

            var totalWithPrice = 0;
            var totalQuantity = 0;

            data.summary.forEach(function(item, index) {
                var rowClass = index % 2 === 0 ? 'oddeven' : 'oddeven';
                var hasProduct = item.product_id ? true : false;
                var priceCell = hasProduct && item.price ? self.formatPrice(item.price) + ' €' : '-';
                var totalCell = hasProduct && item.total ? self.formatPrice(item.total) + ' €' : '-';

                html += '<tr class="' + rowClass + '">';
                html += '<td>' + self.escapeHtml(item.product_ref || '-') + '</td>';
                html += '<td>' + self.escapeHtml(item.product_label || '-');
                if (!hasProduct) {
                    html += ' <span style="color:#e74c3c;font-size:11px;">(kein Produkt verknüpft)</span>';
                }
                html += '</td>';
                html += '<td class="right"><strong>' + item.quantity + '</strong></td>';
                html += '<td class="right">' + priceCell + '</td>';
                html += '<td class="right">' + totalCell + '</td>';
                html += '</tr>';

                totalQuantity += item.quantity;
                if (hasProduct && item.total) {
                    totalWithPrice += item.total;
                }
            });

            // Totals row
            html += '<tr style="background:#f5f5f5;font-weight:bold;">';
            html += '<td colspan="2">Summe</td>';
            html += '<td class="right">' + totalQuantity + ' Stück</td>';
            html += '<td></td>';
            html += '<td class="right">' + self.formatPrice(totalWithPrice) + ' €</td>';
            html += '</tr>';

            html += '</table>';

            // Detailed list (collapsible)
            if (data.items && data.items.length > 0) {
                html += '<details style="margin-top:20px;">';
                html += '<summary style="cursor:pointer;color:#3498db;font-weight:bold;"><i class="fa fa-list"></i> Detailliste (' + data.items.length + ' Einträge)</summary>';
                html += '<table class="noborder centpercent" style="font-size:12px;margin-top:10px;">';
                html += '<tr class="liste_titre">';
                html += '<th>Equipment</th>';
                html += '<th>Typ</th>';
                html += '<th>Feld/Hutschiene</th>';
                html += '<th>Breite</th>';
                html += '<th>Produkt</th>';
                html += '</tr>';

                data.items.forEach(function(item, index) {
                    var rowClass = index % 2 === 0 ? 'oddeven' : 'oddeven';
                    html += '<tr class="' + rowClass + '">';
                    html += '<td>' + self.escapeHtml(item.equipment_label || '-') + '</td>';
                    html += '<td><span style="color:#888;">' + self.escapeHtml(item.type_ref || '') + '</span> ' + self.escapeHtml(item.type_label || '-') + '</td>';
                    html += '<td>' + self.escapeHtml(item.panel_label || '-') + ' / ' + self.escapeHtml(item.carrier_label || '-') + '</td>';
                    html += '<td class="center">' + (item.width_te || 1) + ' TE</td>';
                    html += '<td>' + (item.product_ref ? self.escapeHtml(item.product_ref) : '<em style="color:#888;">-</em>') + '</td>';
                    html += '</tr>';
                });

                html += '</table>';
                html += '</details>';
            }

            // Export buttons
            html += '<div style="margin-top:20px;display:flex;gap:10px;">';
            html += '<button type="button" class="button bom-copy-clipboard"><i class="fa fa-clipboard"></i> In Zwischenablage kopieren</button>';
            html += '</div>';

            $body.html(html);

            // Update totals in footer
            $('.bom-totals').html('<strong>' + totalQuantity + '</strong> Artikel | <strong>' + self.formatPrice(totalWithPrice) + ' €</strong> (geschätzt)');

            // Copy to clipboard
            $body.find('.bom-copy-clipboard').on('click', function() {
                var text = 'Stückliste\n\n';
                text += 'Referenz\tBezeichnung\tMenge\tEinzelpreis\tGesamt\n';
                data.summary.forEach(function(item) {
                    text += (item.product_ref || '-') + '\t';
                    text += (item.product_label || '-') + '\t';
                    text += item.quantity + '\t';
                    text += (item.price ? self.formatPrice(item.price) + ' €' : '-') + '\t';
                    text += (item.total ? self.formatPrice(item.total) + ' €' : '-') + '\n';
                });
                text += '\nSumme:\t\t' + totalQuantity + ' Stück\t\t' + self.formatPrice(totalWithPrice) + ' €';

                navigator.clipboard.writeText(text).then(function() {
                    KundenKarte.showNotification('In Zwischenablage kopiert', 'success');
                }).catch(function() {
                    KundenKarte.showError('Fehler', 'Kopieren nicht möglich');
                });
            });
        },

        formatPrice: function(price) {
            if (!price) return '0,00';
            return parseFloat(price).toFixed(2).replace('.', ',');
        },

        // Audit Log Dialog
        showAuditLogDialog: function() {
            var self = this;
            var anlageId = this.anlageId;

            var html = '<div id="kundenkarte-audit-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:800px;max-height:80vh;">';
            html += '<div class="kundenkarte-modal-header" style="background:#34495e;">';
            html += '<h3 style="color:#fff;"><i class="fa fa-history"></i> Änderungsprotokoll</h3>';
            html += '<span class="kundenkarte-modal-close" style="color:#fff;">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body" style="padding:20px;overflow:auto;max-height:calc(80vh - 130px);">';
            html += '<div class="audit-loading" style="text-align:center;padding:40px;"><i class="fa fa-spinner fa-spin fa-2x"></i><br>Lade Protokoll...</div>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="audit-close"><i class="fa fa-times"></i> Schließen</button>';
            html += '</div>';
            html += '</div></div>';

            $('body').append(html);
            $('#kundenkarte-audit-dialog').addClass('visible');

            // Close handler
            $('#audit-close, #kundenkarte-audit-dialog .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-audit-dialog').remove();
            });

            $(document).on('keydown.auditDialog', function(e) {
                if (e.key === 'Escape') {
                    $('#kundenkarte-audit-dialog').remove();
                    $(document).off('keydown.auditDialog');
                }
            });

            // Load audit data
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/audit_log.php',
                data: { action: 'fetch_anlage', anlage_id: anlageId, limit: 100 },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.renderAuditContent(response.logs);
                    } else {
                        $('.audit-loading').html('<div style="color:#e74c3c;"><i class="fa fa-exclamation-triangle"></i> ' + (response.error || 'Fehler beim Laden') + '</div>');
                    }
                },
                error: function() {
                    $('.audit-loading').html('<div style="color:#e74c3c;"><i class="fa fa-exclamation-triangle"></i> AJAX Fehler</div>');
                }
            });
        },

        renderAuditContent: function(logs) {
            var self = this;
            var $body = $('#kundenkarte-audit-dialog .kundenkarte-modal-body');

            if (!logs || logs.length === 0) {
                $body.html('<div style="text-align:center;padding:40px;color:#888;"><i class="fa fa-info-circle fa-2x"></i><br><br>Keine Änderungen protokolliert.</div>');
                return;
            }

            var html = '<div class="audit-timeline">';

            logs.forEach(function(log) {
                html += '<div class="audit-entry" style="display:flex;gap:15px;padding:10px 0;border-bottom:1px solid #eee;">';
                html += '<div class="audit-icon" style="flex:0 0 40px;text-align:center;">';
                html += '<i class="fa ' + log.action_icon + '" style="font-size:20px;color:' + log.action_color + ';"></i>';
                html += '</div>';
                html += '<div class="audit-content" style="flex:1;">';
                html += '<div class="audit-header" style="display:flex;justify-content:space-between;margin-bottom:5px;">';
                html += '<strong style="color:' + log.action_color + ';">' + self.escapeHtml(log.action_label) + '</strong>';
                html += '<span style="color:#888;font-size:12px;">' + self.escapeHtml(log.date_action) + '</span>';
                html += '</div>';
                html += '<div style="color:#666;">';
                html += '<span style="background:#f5f5f5;padding:2px 6px;border-radius:3px;font-size:11px;">' + self.escapeHtml(log.object_type_label) + '</span> ';
                html += self.escapeHtml(log.object_ref || 'ID ' + log.object_id);
                html += '</div>';

                if (log.field_changed) {
                    html += '<div style="margin-top:5px;font-size:12px;color:#888;">';
                    html += 'Feld: ' + self.escapeHtml(log.field_changed);
                    if (log.old_value || log.new_value) {
                        html += ' (<em>' + self.escapeHtml(log.old_value || '-') + '</em> → <em>' + self.escapeHtml(log.new_value || '-') + '</em>)';
                    }
                    html += '</div>';
                }

                if (log.note) {
                    html += '<div style="margin-top:5px;font-size:12px;font-style:italic;color:#666;">' + self.escapeHtml(log.note) + '</div>';
                }

                html += '<div style="margin-top:5px;font-size:11px;color:#aaa;">';
                html += '<i class="fa fa-user"></i> ' + self.escapeHtml(log.user_name || log.user_login);
                html += '</div>';
                html += '</div></div>';
            });

            html += '</div>';

            $body.html(html);
        }
    };

    /**
     * Connection Editor Component
     * Interactive SVG-based connection editor with orthogonal routing
     * Supports busbars, multi-phase connections, and drag-drop
     */
    KundenKarte.ConnectionEditor = {
        TE_WIDTH: 50,
        BLOCK_HEIGHT: 110,
        BUSBAR_HEIGHT: 25,
        BUSBAR_SPACING: 8,
        CONNECTION_AREA_HEIGHT: 120,
        ENDPOINT_RADIUS: 6,

        // Phase colors (German electrical standard)
        PHASE_COLORS: {
            'L1': '#8B4513',    // Brown
            'L2': '#000000',    // Black
            'L3': '#808080',    // Gray
            'N': '#0066cc',     // Blue
            'PE': '#27ae60',    // Green-Yellow
            'L1N': '#3498db',   // Combined
            '3P': '#2c3e50',    // 3-phase
            '3P+N': '#34495e'   // 3-phase + neutral
        },

        // State
        isExpanded: false,
        currentCarrierId: null,
        currentAnlageId: null,
        connections: [],
        busbars: [],
        equipment: [],
        dragState: null,
        selectedConnection: null,

        init: function(anlageId) {
            console.log('ConnectionEditor.init called with anlageId:', anlageId);
            if (!anlageId) {
                console.log('ConnectionEditor: No anlageId, aborting');
                return;
            }
            this.currentAnlageId = anlageId;

            // Restore expanded state from localStorage
            var savedState = localStorage.getItem('kundenkarte_connection_editor_expanded');
            this.isExpanded = savedState === 'true';
            console.log('ConnectionEditor: isExpanded =', this.isExpanded);

            this.bindEvents();
            console.log('ConnectionEditor: Events bound');

            this.renderAllEditors();
            console.log('ConnectionEditor: Editors rendered');
        },

        bindEvents: function() {
            var self = this;

            // Toggle editor visibility
            $(document).on('click', '.kundenkarte-connection-editor-toggle', function(e) {
                e.preventDefault();
                var $editor = $(this).closest('.kundenkarte-carrier').find('.kundenkarte-connection-editor');
                var carrierId = $(this).closest('.kundenkarte-carrier').data('carrier-id');

                $editor.toggleClass('expanded');
                $(this).find('i').toggleClass('fa-chevron-down fa-chevron-up');

                // Save state
                self.isExpanded = $editor.hasClass('expanded');
                localStorage.setItem('kundenkarte_connection_editor_expanded', self.isExpanded);

                if (self.isExpanded) {
                    self.loadAndRenderEditor(carrierId);
                }
            });

            // Add busbar button
            $(document).on('click', '.kundenkarte-add-busbar-btn', function(e) {
                e.preventDefault();
                var carrierId = $(this).data('carrier-id');
                self.showBusbarDialog(carrierId);
            });

            // Add connection button
            $(document).on('click', '.kundenkarte-add-conn-btn', function(e) {
                e.preventDefault();
                var carrierId = $(this).data('carrier-id');
                self.showConnectionDialog(carrierId);
            });

            // SVG mouse events for drag-drop connections
            $(document).on('mousedown', '.kundenkarte-endpoint', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $endpoint = $(this);
                var carrierId = $endpoint.closest('.kundenkarte-connection-editor').data('carrier-id');

                self.startDragConnection(e, $endpoint, carrierId);
            });

            $(document).on('mousemove', function(e) {
                if (self.dragState) {
                    self.updateDragConnection(e);
                }
            });

            $(document).on('mouseup', function(e) {
                if (self.dragState) {
                    self.endDragConnection(e);
                }
            });

            // Click on busbar to edit
            $(document).on('click', '.kundenkarte-busbar-element', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var connectionId = $(this).data('connection-id');
                var carrierId = $(this).closest('.kundenkarte-connection-editor').data('carrier-id');
                self.showEditBusbarDialog(connectionId, carrierId);
            });

            // Click on connection line to edit/delete
            $(document).on('click', '.kundenkarte-connection-path', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var connectionId = $(this).data('connection-id');
                var carrierId = $(this).closest('.kundenkarte-connection-editor').data('carrier-id');
                self.showEditConnectionDialog(connectionId, carrierId);
            });

            // Hover effects
            $(document).on('mouseenter', '.kundenkarte-endpoint', function() {
                $(this).addClass('hover');
            });
            $(document).on('mouseleave', '.kundenkarte-endpoint', function() {
                $(this).removeClass('hover');
            });
        },

        renderAllEditors: function() {
            var self = this;
            $('.kundenkarte-carrier').each(function() {
                var carrierId = $(this).data('carrier-id');
                var $editor = $(this).find('.kundenkarte-connection-editor');

                // Editor is already rendered via PHP, just need to initialize state
                if ($editor.length) {
                    if (self.isExpanded) {
                        $editor.addClass('expanded');
                        $(this).find('.kundenkarte-connection-editor-toggle i').removeClass('fa-chevron-down').addClass('fa-chevron-up');
                        self.loadAndRenderEditor(carrierId);
                    }
                }
            });
        },

        loadAndRenderEditor: function(carrierId) {
            var self = this;

            // Load equipment for this carrier
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                data: { action: 'list', carrier_id: carrierId },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.equipment = response.equipment || [];

                        // Load connections
                        $.ajax({
                            url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                            data: { action: 'list', carrier_id: carrierId },
                            dataType: 'json',
                            success: function(connResponse) {
                                if (connResponse.success) {
                                    self.connections = connResponse.connections || [];
                                    self.busbars = self.connections.filter(function(c) { return c.is_rail == 1; });
                                    self.renderEditor(carrierId);
                                }
                            }
                        });
                    }
                }
            });
        },

        renderEditor: function(carrierId) {
            var self = this;
            var $editor = $('.kundenkarte-connection-editor[data-carrier-id="' + carrierId + '"]');
            var $svg = $editor.find('.kundenkarte-connection-svg');
            var totalTE = parseInt($editor.data('total-te')) || 12;
            var totalWidth = totalTE * this.TE_WIDTH;

            // Reset busbar positions
            this.busbarPositions = {};

            var svgContent = '';

            // Defs for markers and gradients
            svgContent += '<defs>';
            svgContent += '<marker id="arrowhead-' + carrierId + '" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">';
            svgContent += '<polygon points="0 0, 10 3.5, 0 7" fill="#888"/>';
            svgContent += '</marker>';

            // Phase gradients
            Object.keys(this.PHASE_COLORS).forEach(function(phase) {
                svgContent += '<linearGradient id="grad-' + phase + '-' + carrierId + '" x1="0%" y1="0%" x2="0%" y2="100%">';
                svgContent += '<stop offset="0%" style="stop-color:' + self.PHASE_COLORS[phase] + ';stop-opacity:1" />';
                svgContent += '<stop offset="100%" style="stop-color:' + self.darkenColor(self.PHASE_COLORS[phase], 20) + ';stop-opacity:1" />';
                svgContent += '</linearGradient>';
            });
            svgContent += '</defs>';

            // If no busbars exist, show a demo
            if (this.busbars.length === 0 && this.equipment.length > 0) {
                svgContent += this.renderDemoView(carrierId, totalTE, totalWidth);
                $svg.html(svgContent);
                $svg.attr('height', 200);
                return;
            }

            // Background grid
            for (var i = 0; i <= totalTE; i++) {
                var x = i * this.TE_WIDTH;
                svgContent += '<line x1="' + x + '" y1="0" x2="' + x + '" y2="' + this.CONNECTION_AREA_HEIGHT + '" stroke="#333" stroke-width="0.5" stroke-dasharray="2,2"/>';
            }

            // Render busbars
            var busbarY = 15;
            var busbarsByPosition = {};

            this.busbars.forEach(function(busbar, index) {
                var posKey = busbar.position_y < 0 ? 'above' : busbar.position_y;
                if (!busbarsByPosition[posKey]) busbarsByPosition[posKey] = [];
                busbarsByPosition[posKey].push(busbar);
            });

            Object.keys(busbarsByPosition).forEach(function(posKey) {
                busbarsByPosition[posKey].forEach(function(busbar, idx) {
                    svgContent += self.renderBusbar(busbar, carrierId, busbarY + (idx * (self.BUSBAR_HEIGHT + self.BUSBAR_SPACING)));
                });
                busbarY += busbarsByPosition[posKey].length * (self.BUSBAR_HEIGHT + self.BUSBAR_SPACING);
            });

            // Render equipment endpoints
            var equipmentY = busbarY + 20;

            // Store equipment positions for connection routing
            this.equipmentPositions = {};
            this.equipment.forEach(function(eq) {
                var width = eq.width_te * self.TE_WIDTH;
                var centerX = (eq.position_te - 1) * self.TE_WIDTH + width / 2;
                self.equipmentPositions[eq.id] = {
                    x: centerX,
                    left: (eq.position_te - 1) * self.TE_WIDTH,
                    right: eq.position_te * self.TE_WIDTH + (eq.width_te - 1) * self.TE_WIDTH,
                    inputY: equipmentY - 15,
                    outputY: equipmentY + 15,
                    centerY: equipmentY
                };
            });

            // Render non-busbar connections FIRST (behind equipment)
            // But route them around blocks, not through them
            var regularConnections = this.connections.filter(function(c) { return c.is_rail != 1; });

            // Connection layer - rendered below equipment layer
            svgContent += '<g class="kundenkarte-connections-layer">';
            regularConnections.forEach(function(conn, index) {
                svgContent += self.renderOrthogonalConnection(conn, carrierId, equipmentY, index);
            });
            svgContent += '</g>';

            // Equipment layer - rendered on top
            svgContent += '<g class="kundenkarte-equipment-layer">';
            this.equipment.forEach(function(eq) {
                svgContent += self.renderEquipmentEndpoints(eq, equipmentY, carrierId);
            });
            svgContent += '</g>';

            // Render drag preview line (hidden by default) - on top of everything
            svgContent += '<path id="drag-preview-' + carrierId + '" class="kundenkarte-drag-preview" d="" fill="none" stroke="#3498db" stroke-width="2" stroke-dasharray="5,5" style="display:none;"/>';

            $svg.html(svgContent);
            $svg.attr('height', equipmentY + 60);
        },

        renderBusbar: function(busbar, carrierId, y) {
            var self = this;
            var startX = (busbar.rail_start_te - 1) * this.TE_WIDTH + 5;
            var endX = busbar.rail_end_te * this.TE_WIDTH - 5;
            var color = busbar.color || this.PHASE_COLORS[busbar.connection_type] || '#3498db';
            var phases = busbar.rail_phases || '';
            var excludedTE = (busbar.excluded_te || '').split(',').map(function(t) { return parseInt(t.trim()); }).filter(function(t) { return !isNaN(t); });

            var html = '<g class="kundenkarte-busbar-element" data-connection-id="' + busbar.id + '">';

            // Determine phase list
            var phaseList = [];
            if (phases === '3P+N') {
                phaseList = ['L1', 'L2', 'L3', 'N'];
            } else if (phases === '3P') {
                phaseList = ['L1', 'L2', 'L3'];
            } else if (phases === 'L1N') {
                phaseList = ['L1', 'N'];
            } else if (phases === 'L1') {
                phaseList = ['L1'];
            } else {
                phaseList = [busbar.connection_type || 'L1'];
            }

            var phaseHeight = phaseList.length > 1 ? 6 : (this.BUSBAR_HEIGHT - 8);
            var phaseSpacing = phaseList.length > 1 ? 2 : 0;
            var totalPhaseHeight = phaseList.length * phaseHeight + (phaseList.length - 1) * phaseSpacing;
            var phaseStartY = y + (this.BUSBAR_HEIGHT - totalPhaseHeight) / 2;

            // Draw each phase line
            phaseList.forEach(function(phase, idx) {
                var phaseY = phaseStartY + idx * (phaseHeight + phaseSpacing);
                var phaseColor = self.PHASE_COLORS[phase] || color;

                // Draw the phase line with gaps for excluded TE
                html += self.renderBusbarLine(startX, endX, phaseY, phaseHeight, phaseColor, excludedTE, carrierId, busbar.id, phase);

                // Phase label on the left
                html += '<text x="' + (startX - 3) + '" y="' + (phaseY + phaseHeight/2 + 3) + '" ';
                html += 'text-anchor="end" fill="' + phaseColor + '" font-size="9" font-weight="bold">';
                html += phase;
                html += '</text>';
            });

            // Connection endpoints for EACH phase at EACH TE position
            for (var te = busbar.rail_start_te; te <= busbar.rail_end_te; te++) {
                if (excludedTE.indexOf(te) === -1) {
                    var epX = (te - 0.5) * this.TE_WIDTH;

                    phaseList.forEach(function(phase, idx) {
                        var epY = phaseStartY + idx * (phaseHeight + phaseSpacing) + phaseHeight;
                        var phaseColor = self.PHASE_COLORS[phase] || color;

                        html += '<circle class="kundenkarte-endpoint kundenkarte-busbar-endpoint kundenkarte-phase-endpoint" ';
                        html += 'data-type="busbar-phase" data-connection-id="' + busbar.id + '" data-te="' + te + '" data-phase="' + phase + '" ';
                        html += 'cx="' + epX + '" cy="' + epY + '" r="4" ';
                        html += 'fill="' + phaseColor + '" stroke="#fff" stroke-width="1"/>';
                    });
                }
            }

            // Busbar type label (bottom right)
            html += '<text x="' + (endX - 5) + '" y="' + (y + this.BUSBAR_HEIGHT - 2) + '" ';
            html += 'text-anchor="end" fill="#888" font-size="8">';
            html += this.escapeHtml(busbar.connection_type || '');
            html += '</text>';

            html += '</g>';

            // Store busbar phase positions for connection routing
            if (!this.busbarPositions) this.busbarPositions = {};
            this.busbarPositions[busbar.id] = {
                phases: phaseList,
                startTE: busbar.rail_start_te,
                endTE: busbar.rail_end_te,
                y: y,
                phaseStartY: phaseStartY,
                phaseHeight: phaseHeight,
                phaseSpacing: phaseSpacing
            };

            return html;
        },

        renderBusbarLine: function(startX, endX, y, height, color, excludedTE, carrierId, busbarId, phase) {
            var html = '';
            var segments = [];
            var currentStart = startX;
            var teWidth = this.TE_WIDTH;

            // Calculate segments with gaps
            for (var te = Math.ceil(startX / teWidth) + 1; te <= Math.floor(endX / teWidth); te++) {
                if (excludedTE.indexOf(te) !== -1) {
                    if (currentStart < (te - 1) * teWidth + teWidth/2) {
                        segments.push({ start: currentStart, end: (te - 1) * teWidth + teWidth/4 });
                    }
                    currentStart = (te - 1) * teWidth + teWidth * 0.75;
                }
            }
            segments.push({ start: currentStart, end: endX });

            segments.forEach(function(seg) {
                html += '<rect x="' + seg.start + '" y="' + y + '" width="' + (seg.end - seg.start) + '" height="' + height + '" ';
                html += 'fill="' + color + '" rx="1" ry="1" class="kundenkarte-busbar-line" data-phase="' + (phase || '') + '"/>';
            });

            return html;
        },

        renderEquipmentEndpoints: function(eq, baseY, carrierId) {
            var x = (eq.position_te - 0.5) * this.TE_WIDTH;
            var width = eq.width_te * this.TE_WIDTH;
            var centerX = (eq.position_te - 1) * this.TE_WIDTH + width / 2;
            var color = eq.block_color || eq.type_color || '#3498db';

            var html = '<g class="kundenkarte-equipment-endpoints" data-equipment-id="' + eq.id + '">';

            // Equipment representation
            html += '<rect x="' + ((eq.position_te - 1) * this.TE_WIDTH + 2) + '" y="' + (baseY - 8) + '" ';
            html += 'width="' + (width - 4) + '" height="16" rx="3" ry="3" fill="' + color + '" stroke="#333" stroke-width="1"/>';

            // Label
            html += '<text x="' + centerX + '" y="' + (baseY + 4) + '" text-anchor="middle" fill="#fff" font-size="9" font-weight="bold">';
            html += this.escapeHtml(eq.type_label_short || eq.label || '');
            html += '</text>';

            // Input endpoint (top)
            html += '<circle class="kundenkarte-endpoint kundenkarte-equipment-input" ';
            html += 'data-type="equipment-input" data-equipment-id="' + eq.id + '" ';
            html += 'cx="' + centerX + '" cy="' + (baseY - 15) + '" r="' + this.ENDPOINT_RADIUS + '" ';
            html += 'fill="#fff" stroke="' + color + '" stroke-width="2"/>';

            // Output endpoint (bottom)
            html += '<circle class="kundenkarte-endpoint kundenkarte-equipment-output" ';
            html += 'data-type="equipment-output" data-equipment-id="' + eq.id + '" ';
            html += 'cx="' + centerX + '" cy="' + (baseY + 15) + '" r="' + this.ENDPOINT_RADIUS + '" ';
            html += 'fill="#fff" stroke="' + color + '" stroke-width="2"/>';

            html += '</g>';
            return html;
        },

        renderOrthogonalConnection: function(conn, carrierId, equipmentY, connectionIndex) {
            var color = conn.color || this.PHASE_COLORS[conn.connection_type] || '#888888';
            var sourcePos = this.equipmentPositions[conn.fk_source];
            var targetPos = this.equipmentPositions[conn.fk_target];

            if (!sourcePos || !targetPos) return '';

            var sourceX = sourcePos.x;
            var targetX = targetPos.x;
            var sourceY = conn.source_terminal === 'input' ? sourcePos.inputY : sourcePos.outputY;
            var targetY = conn.target_terminal === 'input' ? targetPos.inputY : targetPos.outputY;

            // Create orthogonal path that routes AROUND blocks, not through them
            var path = this.createOrthogonalPath(sourceX, sourceY, targetX, targetY, connectionIndex, equipmentY);

            var html = '<g class="kundenkarte-connection-group" data-connection-id="' + conn.id + '">';

            // Connection line with shadow for visibility
            html += '<path class="kundenkarte-connection-path-shadow" ';
            html += 'd="' + path + '" fill="none" stroke="rgba(0,0,0,0.3)" stroke-width="5" ';
            html += 'stroke-linecap="round" stroke-linejoin="round"/>';

            // Main connection line
            html += '<path class="kundenkarte-connection-path" data-connection-id="' + conn.id + '" ';
            html += 'd="' + path + '" fill="none" stroke="' + color + '" stroke-width="2.5" ';
            html += 'stroke-linecap="round" stroke-linejoin="round"/>';

            // Label if exists - positioned along the routing path
            if (conn.output_label) {
                var labelY = equipmentY + 35 + (connectionIndex * 12);
                var labelX = (sourceX + targetX) / 2;
                html += '<rect x="' + (labelX - 25) + '" y="' + (labelY - 8) + '" width="50" height="12" rx="2" fill="#1e1e1e" opacity="0.9"/>';
                html += '<text x="' + labelX + '" y="' + (labelY + 2) + '" text-anchor="middle" fill="#ccc" font-size="9">';
                html += this.escapeHtml(conn.output_label);
                html += '</text>';
            }

            html += '</g>';
            return html;
        },

        createOrthogonalPath: function(x1, y1, x2, y2, connectionIndex, equipmentY) {
            // Offset for multiple connections to avoid overlap
            var routeOffset = (connectionIndex || 0) * 8;

            // Route connections BELOW the equipment blocks to keep them visible
            var routeY = equipmentY + 30 + routeOffset;

            // If source and target are the same terminal type, route around
            var bothOutputs = y1 > equipmentY && y2 > equipmentY;
            var bothInputs = y1 < equipmentY && y2 < equipmentY;

            if (Math.abs(x1 - x2) < 10) {
                // Vertically aligned - straight line
                return 'M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2;
            }

            if (bothOutputs) {
                // Both from output - route below
                return 'M ' + x1 + ' ' + y1 +
                       ' L ' + x1 + ' ' + routeY +
                       ' L ' + x2 + ' ' + routeY +
                       ' L ' + x2 + ' ' + y2;
            }

            if (bothInputs) {
                // Both from input - route above
                var routeYAbove = equipmentY - 30 - routeOffset;
                return 'M ' + x1 + ' ' + y1 +
                       ' L ' + x1 + ' ' + routeYAbove +
                       ' L ' + x2 + ' ' + routeYAbove +
                       ' L ' + x2 + ' ' + y2;
            }

            // Mixed terminals (output to input or vice versa)
            // Route to the side and then up/down
            if (y1 > y2) {
                // Going up (output to input)
                return 'M ' + x1 + ' ' + y1 +
                       ' L ' + x1 + ' ' + routeY +
                       ' L ' + x2 + ' ' + routeY +
                       ' L ' + x2 + ' ' + y2;
            } else {
                // Going down (input to output)
                var routeYAbove2 = equipmentY - 30 - routeOffset;
                return 'M ' + x1 + ' ' + y1 +
                       ' L ' + x1 + ' ' + routeYAbove2 +
                       ' L ' + x2 + ' ' + routeYAbove2 +
                       ' L ' + x2 + ' ' + y2;
            }
        },

        // Drag and drop connection creation
        startDragConnection: function(e, $endpoint, carrierId) {
            var $svg = $endpoint.closest('svg');
            var offset = $svg.offset();
            var svgPoint = this.getSVGPoint($svg[0], e.clientX, e.clientY);

            this.dragState = {
                carrierId: carrierId,
                startEndpoint: $endpoint,
                startX: parseFloat($endpoint.attr('cx')),
                startY: parseFloat($endpoint.attr('cy')),
                startType: $endpoint.data('type'),
                startId: $endpoint.data('equipment-id') || $endpoint.data('connection-id'),
                currentX: svgPoint.x,
                currentY: svgPoint.y
            };

            $endpoint.addClass('dragging');
            $('#drag-preview-' + carrierId).show();
        },

        updateDragConnection: function(e) {
            if (!this.dragState) return;

            var $svg = $('#drag-preview-' + this.dragState.carrierId).closest('svg');
            var svgPoint = this.getSVGPoint($svg[0], e.clientX, e.clientY);

            this.dragState.currentX = svgPoint.x;
            this.dragState.currentY = svgPoint.y;

            var path = this.createOrthogonalPath(
                this.dragState.startX,
                this.dragState.startY,
                this.dragState.currentX,
                this.dragState.currentY
            );

            $('#drag-preview-' + this.dragState.carrierId).attr('d', path);
        },

        endDragConnection: function(e) {
            if (!this.dragState) return;

            var $targetEndpoint = $(e.target).closest('.kundenkarte-endpoint');

            if ($targetEndpoint.length && !$targetEndpoint.is(this.dragState.startEndpoint)) {
                // Valid drop target
                this.createConnection(
                    this.dragState.carrierId,
                    this.dragState.startType,
                    this.dragState.startId,
                    $targetEndpoint.data('type'),
                    $targetEndpoint.data('equipment-id') || $targetEndpoint.data('connection-id'),
                    $targetEndpoint.data('te')
                );
            }

            // Cleanup
            this.dragState.startEndpoint.removeClass('dragging');
            $('#drag-preview-' + this.dragState.carrierId).hide().attr('d', '');
            this.dragState = null;
        },

        getSVGPoint: function(svg, clientX, clientY) {
            var pt = svg.createSVGPoint();
            pt.x = clientX;
            pt.y = clientY;
            var svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
            return { x: svgP.x, y: svgP.y };
        },

        createConnection: function(carrierId, sourceType, sourceId, targetType, targetId, targetTE) {
            var self = this;

            var data = {
                action: 'create',
                carrier_id: carrierId,
                token: $('input[name="token"]').val()
            };

            // Determine source and target based on types
            if (sourceType.indexOf('equipment') !== -1) {
                data.fk_source = sourceId;
                data.source_terminal = sourceType === 'equipment-input' ? 'input' : 'output';
            } else if (sourceType === 'busbar') {
                data.fk_source = null;
                data.source_terminal = 'busbar-' + sourceId;
            }

            if (targetType.indexOf('equipment') !== -1) {
                data.fk_target = targetId;
                data.target_terminal = targetType === 'equipment-input' ? 'input' : 'output';
            } else if (targetType === 'busbar') {
                data.fk_target = null;
                data.target_terminal = 'busbar-' + targetId + '-te' + targetTE;
            }

            data.connection_type = 'L1N';
            data.color = this.PHASE_COLORS['L1N'];

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.loadAndRenderEditor(carrierId);
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        // Dialogs
        showBusbarDialog: function(carrierId) {
            var self = this;

            if ($('#kundenkarte-busbar-dialog').length) return;

            var $editor = $('.kundenkarte-connection-editor[data-carrier-id="' + carrierId + '"]');
            var totalTE = parseInt($editor.data('total-te')) || 12;

            var html = '<div id="kundenkarte-busbar-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:500px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Sammelschiene hinzufügen</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';

            html += '<div class="kundenkarte-connection-form">';

            // Quick presets
            html += '<div class="form-row" style="margin-bottom:15px;">';
            html += '<label style="width:100%;margin-bottom:8px;font-weight:bold;">Schnellauswahl:</label>';
            html += '<div style="display:flex;flex-wrap:wrap;gap:8px;">';

            var presets = [
                { type: 'L1', color: '#8B4513', phases: 'L1' },
                { type: 'L1N', color: '#3498db', phases: 'L1N' },
                { type: '3P', color: '#2c3e50', phases: '3P' },
                { type: '3P+N', color: '#34495e', phases: '3P+N' },
                { type: 'N', color: '#0066cc', phases: '' },
                { type: 'PE', color: '#27ae60', phases: '' }
            ];

            presets.forEach(function(p) {
                html += '<button type="button" class="busbar-preset-btn" data-type="' + p.type + '" data-color="' + p.color + '" data-phases="' + p.phases + '" ';
                html += 'style="padding:8px 16px;background:' + p.color + ';color:#fff;border:none;border-radius:4px;cursor:pointer;font-weight:bold;">';
                html += p.type + '</button>';
            });

            html += '</div></div>';

            // Type and color
            html += '<div class="form-row">';
            html += '<div class="form-group"><label>Bezeichnung</label>';
            html += '<input type="text" name="busbar_type" value="L1N" placeholder="z.B. L1N, 3P, PE"></div>';
            html += '<div class="form-group"><label>Farbe</label>';
            html += '<input type="color" name="busbar_color" value="#3498db"></div>';
            html += '</div>';

            // Range
            html += '<div class="form-row">';
            html += '<div class="form-group"><label>Von TE</label>';
            html += '<input type="number" name="busbar_start" value="1" min="1" max="' + totalTE + '"></div>';
            html += '<div class="form-group"><label>Bis TE</label>';
            html += '<input type="number" name="busbar_end" value="' + totalTE + '" min="1" max="' + totalTE + '"></div>';
            html += '</div>';

            // Phases
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Phasendarstellung</label>';
            html += '<select name="busbar_phases">';
            html += '<option value="">Einfache Linie</option>';
            html += '<option value="L1N">L1+N (2 Linien)</option>';
            html += '<option value="3P">3P (L1/L2/L3)</option>';
            html += '<option value="3P+N">3P+N (L1/L2/L3/N)</option>';
            html += '</select></div>';
            html += '</div>';

            // Excluded
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Ausgenommene TE (kommagetrennt)</label>';
            html += '<input type="text" name="busbar_excluded" placeholder="z.B. 3,4 für FI-Lücke"></div>';
            html += '</div>';

            html += '</div>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="busbar-save"><i class="fa fa-save"></i> Erstellen</button> ';
            html += '<button type="button" class="button" id="busbar-cancel">Abbrechen</button>';
            html += '</div></div></div>';

            $('body').append(html);
            $('#kundenkarte-busbar-dialog').addClass('visible');

            // Preset handlers
            $('.busbar-preset-btn').on('click', function() {
                $('input[name="busbar_type"]').val($(this).data('type'));
                $('input[name="busbar_color"]').val($(this).data('color'));
                $('select[name="busbar_phases"]').val($(this).data('phases'));
            });

            // Save
            $('#busbar-save').on('click', function() {
                self.saveBusbar(carrierId);
            });

            // Close
            $('#busbar-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-busbar-dialog').remove();
            });
        },

        saveBusbar: function(carrierId) {
            var self = this;

            var data = {
                action: 'create_rail',
                carrier_id: carrierId,
                connection_type: $('input[name="busbar_type"]').val(),
                color: $('input[name="busbar_color"]').val(),
                rail_start_te: $('input[name="busbar_start"]').val(),
                rail_end_te: $('input[name="busbar_end"]').val(),
                rail_phases: $('select[name="busbar_phases"]').val(),
                excluded_te: $('input[name="busbar_excluded"]').val(),
                position_y: 0,
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-busbar-dialog').remove();
                        self.loadAndRenderEditor(carrierId);
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                },
                error: function() {
                    KundenKarte.showAlert('Fehler', 'Netzwerkfehler');
                }
            });
        },

        showEditBusbarDialog: function(connectionId, carrierId) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                data: { action: 'get', connection_id: connectionId },
                dataType: 'json',
                success: function(response) {
                    if (response.success && response.connection) {
                        self.renderEditBusbarDialog(connectionId, carrierId, response.connection);
                    }
                }
            });
        },

        renderEditBusbarDialog: function(connectionId, carrierId, conn) {
            var self = this;
            var $editor = $('.kundenkarte-connection-editor[data-carrier-id="' + carrierId + '"]');
            var totalTE = parseInt($editor.data('total-te')) || 12;

            var html = '<div id="kundenkarte-busbar-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:500px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Sammelschiene bearbeiten</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';

            html += '<div class="kundenkarte-connection-form">';
            html += '<input type="hidden" name="busbar_id" value="' + connectionId + '">';

            // Type and color
            html += '<div class="form-row">';
            html += '<div class="form-group"><label>Bezeichnung</label>';
            html += '<input type="text" name="busbar_type" value="' + this.escapeHtml(conn.connection_type || '') + '"></div>';
            html += '<div class="form-group"><label>Farbe</label>';
            html += '<input type="color" name="busbar_color" value="' + (conn.color || '#3498db') + '"></div>';
            html += '</div>';

            // Range
            html += '<div class="form-row">';
            html += '<div class="form-group"><label>Von TE</label>';
            html += '<input type="number" name="busbar_start" value="' + (conn.rail_start_te || 1) + '" min="1" max="' + totalTE + '"></div>';
            html += '<div class="form-group"><label>Bis TE</label>';
            html += '<input type="number" name="busbar_end" value="' + (conn.rail_end_te || totalTE) + '" min="1" max="' + totalTE + '"></div>';
            html += '</div>';

            // Phases
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Phasendarstellung</label>';
            html += '<select name="busbar_phases">';
            html += '<option value=""' + (!conn.rail_phases ? ' selected' : '') + '>Einfache Linie</option>';
            html += '<option value="L1N"' + (conn.rail_phases === 'L1N' ? ' selected' : '') + '>L1+N</option>';
            html += '<option value="3P"' + (conn.rail_phases === '3P' ? ' selected' : '') + '>3P</option>';
            html += '<option value="3P+N"' + (conn.rail_phases === '3P+N' ? ' selected' : '') + '>3P+N</option>';
            html += '</select></div>';
            html += '</div>';

            // Excluded
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Ausgenommene TE</label>';
            html += '<input type="text" name="busbar_excluded" value="' + this.escapeHtml(conn.excluded_te || '') + '"></div>';
            html += '</div>';

            html += '</div>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="busbar-save"><i class="fa fa-save"></i> Speichern</button> ';
            html += '<button type="button" class="button" id="busbar-delete" style="background:#c0392b;color:#fff;"><i class="fa fa-trash"></i> Löschen</button> ';
            html += '<button type="button" class="button" id="busbar-cancel">Abbrechen</button>';
            html += '</div></div></div>';

            $('body').append(html);
            $('#kundenkarte-busbar-dialog').addClass('visible');

            // Save
            $('#busbar-save').on('click', function() {
                self.updateBusbar(connectionId, carrierId);
            });

            // Delete
            $('#busbar-delete').on('click', function() {
                $('#kundenkarte-busbar-dialog').remove();
                self.deleteConnection(connectionId, carrierId);
            });

            // Close
            $('#busbar-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-busbar-dialog').remove();
            });
        },

        updateBusbar: function(connectionId, carrierId) {
            var self = this;

            var data = {
                action: 'update',
                connection_id: connectionId,
                carrier_id: carrierId,
                connection_type: $('input[name="busbar_type"]').val(),
                color: $('input[name="busbar_color"]').val(),
                rail_start_te: $('input[name="busbar_start"]').val(),
                rail_end_te: $('input[name="busbar_end"]').val(),
                rail_phases: $('select[name="busbar_phases"]').val(),
                excluded_te: $('input[name="busbar_excluded"]').val(),
                is_rail: 1,
                position_y: 0,
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-busbar-dialog').remove();
                        self.loadAndRenderEditor(carrierId);
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                }
            });
        },

        showConnectionDialog: function(carrierId) {
            var self = this;

            if ($('#kundenkarte-conn-dialog').length) return;

            var html = '<div id="kundenkarte-conn-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:500px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Verbindung hinzufügen</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';

            html += '<div class="kundenkarte-connection-form">';

            // Source equipment
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Von (Quelle)</label>';
            html += '<select name="conn_source">';
            html += '<option value="">-- Auswählen --</option>';
            self.equipment.forEach(function(eq) {
                html += '<option value="' + eq.id + '">' + self.escapeHtml(eq.label || eq.type_label || 'Equipment ' + eq.id) + '</option>';
            });
            html += '</select></div>';
            html += '</div>';

            // Source terminal
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Anschluss (Quelle)</label>';
            html += '<select name="conn_source_terminal">';
            html += '<option value="output">Ausgang (unten)</option>';
            html += '<option value="input">Eingang (oben)</option>';
            html += '</select></div>';
            html += '</div>';

            // Target equipment
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Nach (Ziel)</label>';
            html += '<select name="conn_target">';
            html += '<option value="">-- Auswählen --</option>';
            self.equipment.forEach(function(eq) {
                html += '<option value="' + eq.id + '">' + self.escapeHtml(eq.label || eq.type_label || 'Equipment ' + eq.id) + '</option>';
            });
            html += '</select></div>';
            html += '</div>';

            // Target terminal
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Anschluss (Ziel)</label>';
            html += '<select name="conn_target_terminal">';
            html += '<option value="input">Eingang (oben)</option>';
            html += '<option value="output">Ausgang (unten)</option>';
            html += '</select></div>';
            html += '</div>';

            // Connection type
            html += '<div class="form-row">';
            html += '<div class="form-group"><label>Typ</label>';
            html += '<input type="text" name="conn_type" value="L1N" placeholder="z.B. L1N, 3P"></div>';
            html += '<div class="form-group"><label>Farbe</label>';
            html += '<input type="color" name="conn_color" value="#3498db"></div>';
            html += '</div>';

            // Label
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Beschriftung (optional)</label>';
            html += '<input type="text" name="conn_label" placeholder="z.B. Küche"></div>';
            html += '</div>';

            html += '</div>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="conn-save"><i class="fa fa-save"></i> Erstellen</button> ';
            html += '<button type="button" class="button" id="conn-cancel">Abbrechen</button>';
            html += '</div></div></div>';

            $('body').append(html);
            $('#kundenkarte-conn-dialog').addClass('visible');

            // Save
            $('#conn-save').on('click', function() {
                self.saveConnection(carrierId);
            });

            // Close
            $('#conn-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-conn-dialog').remove();
            });
        },

        saveConnection: function(carrierId) {
            var self = this;

            var sourceId = $('select[name="conn_source"]').val();
            var targetId = $('select[name="conn_target"]').val();

            if (!sourceId || !targetId) {
                KundenKarte.showAlert('Hinweis', 'Bitte Quelle und Ziel auswählen');
                return;
            }

            var data = {
                action: 'create',
                carrier_id: carrierId,
                fk_source: sourceId,
                source_terminal: $('select[name="conn_source_terminal"]').val(),
                fk_target: targetId,
                target_terminal: $('select[name="conn_target_terminal"]').val(),
                connection_type: $('input[name="conn_type"]').val(),
                color: $('input[name="conn_color"]').val(),
                output_label: $('input[name="conn_label"]').val(),
                is_rail: 0,
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-conn-dialog').remove();
                        self.loadAndRenderEditor(carrierId);
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                }
            });
        },

        showEditConnectionDialog: function(connectionId, carrierId) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                data: { action: 'get', connection_id: connectionId },
                dataType: 'json',
                success: function(response) {
                    if (response.success && response.connection) {
                        self.renderEditConnectionDialog(connectionId, carrierId, response.connection);
                    }
                }
            });
        },

        renderEditConnectionDialog: function(connectionId, carrierId, conn) {
            var self = this;

            var html = '<div id="kundenkarte-conn-dialog" class="kundenkarte-modal">';
            html += '<div class="kundenkarte-modal-content" style="max-width:500px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Verbindung bearbeiten</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';

            html += '<div class="kundenkarte-connection-form">';
            html += '<input type="hidden" name="conn_id" value="' + connectionId + '">';

            // Connection type
            html += '<div class="form-row">';
            html += '<div class="form-group"><label>Typ</label>';
            html += '<input type="text" name="conn_type" value="' + this.escapeHtml(conn.connection_type || '') + '"></div>';
            html += '<div class="form-group"><label>Farbe</label>';
            html += '<input type="color" name="conn_color" value="' + (conn.color || '#3498db') + '"></div>';
            html += '</div>';

            // Label
            html += '<div class="form-row">';
            html += '<div class="form-group" style="width:100%;"><label>Beschriftung</label>';
            html += '<input type="text" name="conn_label" value="' + this.escapeHtml(conn.output_label || '') + '"></div>';
            html += '</div>';

            html += '</div>';
            html += '</div>';
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="conn-save"><i class="fa fa-save"></i> Speichern</button> ';
            html += '<button type="button" class="button" id="conn-delete" style="background:#c0392b;color:#fff;"><i class="fa fa-trash"></i> Löschen</button> ';
            html += '<button type="button" class="button" id="conn-cancel">Abbrechen</button>';
            html += '</div></div></div>';

            $('body').append(html);
            $('#kundenkarte-conn-dialog').addClass('visible');

            // Save
            $('#conn-save').on('click', function() {
                self.updateConnection(connectionId, carrierId, conn);
            });

            // Delete
            $('#conn-delete').on('click', function() {
                $('#kundenkarte-conn-dialog').remove();
                self.deleteConnection(connectionId, carrierId);
            });

            // Close
            $('#conn-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#kundenkarte-conn-dialog').remove();
            });
        },

        updateConnection: function(connectionId, carrierId, originalConn) {
            var self = this;

            var data = {
                action: 'update',
                connection_id: connectionId,
                carrier_id: carrierId,
                fk_source: originalConn.fk_source,
                source_terminal: originalConn.source_terminal,
                fk_target: originalConn.fk_target,
                target_terminal: originalConn.target_terminal,
                connection_type: $('input[name="conn_type"]').val(),
                color: $('input[name="conn_color"]').val(),
                output_label: $('input[name="conn_label"]').val(),
                is_rail: 0,
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('#kundenkarte-conn-dialog').remove();
                        self.loadAndRenderEditor(carrierId);
                    } else {
                        KundenKarte.showAlert('Fehler', response.error);
                    }
                }
            });
        },

        deleteConnection: function(connectionId, carrierId) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'delete',
                    connection_id: connectionId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.loadAndRenderEditor(carrierId);
                    } else {
                        self.showMessage(response.error || 'Fehler beim Löschen', 'error');
                    }
                }
            });
        },

        // Demo view when no busbars exist
        renderDemoView: function(carrierId, totalTE, totalWidth) {
            var self = this;
            var html = '';
            var BUSBAR_Y = 15;
            var BUSBAR_HEIGHT = this.BUSBAR_HEIGHT;
            var phaseList = ['L1', 'L2', 'L3', 'N'];
            var phaseHeight = 6;
            var phaseSpacing = 2;
            var totalPhaseHeight = phaseList.length * phaseHeight + (phaseList.length - 1) * phaseSpacing;
            var phaseStartY = BUSBAR_Y + (BUSBAR_HEIGHT - totalPhaseHeight) / 2;

            // Demo background overlay
            html += '<rect x="0" y="0" width="' + totalWidth + '" height="200" fill="#1a1a2e" opacity="0.3"/>';

            // Demo label
            html += '<text x="' + (totalWidth / 2) + '" y="10" text-anchor="middle" fill="#888" font-size="10" font-style="italic">';
            html += 'Demo-Ansicht - Klicken Sie auf "Sammelschiene" um eine echte Schiene hinzuzufügen';
            html += '</text>';

            // Background grid for TE positions
            for (var i = 0; i <= totalTE; i++) {
                var x = i * this.TE_WIDTH;
                html += '<line x1="' + x + '" y1="15" x2="' + x + '" y2="180" stroke="#333" stroke-width="0.5" stroke-dasharray="2,2"/>';
                // TE number label
                if (i < totalTE) {
                    html += '<text x="' + (x + this.TE_WIDTH / 2) + '" y="190" text-anchor="middle" fill="#555" font-size="8">' + (i + 1) + '</text>';
                }
            }

            // Render demo 3P+N busbar
            html += '<g class="kundenkarte-demo-busbar" opacity="0.8">';

            // Busbar background
            html += '<rect x="20" y="' + BUSBAR_Y + '" width="' + (totalWidth - 40) + '" height="' + BUSBAR_HEIGHT + '" ';
            html += 'fill="#2d2d44" rx="3" ry="3" stroke="#555" stroke-width="1" stroke-dasharray="4,2"/>';

            // Draw each phase line
            phaseList.forEach(function(phase, idx) {
                var phaseY = phaseStartY + idx * (phaseHeight + phaseSpacing);
                var phaseColor = self.PHASE_COLORS[phase];

                // Phase line
                html += '<rect x="25" y="' + phaseY + '" width="' + (totalWidth - 50) + '" height="' + phaseHeight + '" ';
                html += 'fill="' + phaseColor + '" rx="1" ry="1" opacity="0.9"/>';

                // Phase label on the left
                html += '<text x="18" y="' + (phaseY + phaseHeight / 2 + 3) + '" ';
                html += 'text-anchor="end" fill="' + phaseColor + '" font-size="9" font-weight="bold">';
                html += phase;
                html += '</text>';

                // Connection endpoints for each TE
                for (var te = 1; te <= totalTE; te++) {
                    var epX = (te - 0.5) * self.TE_WIDTH;
                    var epY = phaseY + phaseHeight;

                    html += '<circle class="kundenkarte-endpoint kundenkarte-demo-endpoint" ';
                    html += 'cx="' + epX + '" cy="' + epY + '" r="4" ';
                    html += 'fill="' + phaseColor + '" stroke="#fff" stroke-width="1" opacity="0.7"/>';
                }
            });

            // Busbar type label
            html += '<text x="' + (totalWidth - 25) + '" y="' + (BUSBAR_Y + BUSBAR_HEIGHT - 2) + '" ';
            html += 'text-anchor="end" fill="#888" font-size="8">3P+N</text>';

            html += '</g>'; // End demo busbar group

            // Equipment visualization layer
            var equipmentY = BUSBAR_Y + BUSBAR_HEIGHT + 40;
            html += '<g class="kundenkarte-demo-equipment">';

            // Draw existing equipment with connection endpoints
            this.equipment.forEach(function(eq) {
                var width = eq.width_te * self.TE_WIDTH;
                var centerX = (eq.position_te - 1) * self.TE_WIDTH + width / 2;
                var color = eq.block_color || eq.type_color || '#3498db';

                // Equipment block
                html += '<rect x="' + ((eq.position_te - 1) * self.TE_WIDTH + 2) + '" y="' + (equipmentY - 8) + '" ';
                html += 'width="' + (width - 4) + '" height="16" rx="3" ry="3" fill="' + color + '" stroke="#333" stroke-width="1"/>';

                // Label
                html += '<text x="' + centerX + '" y="' + (equipmentY + 4) + '" text-anchor="middle" fill="#fff" font-size="9" font-weight="bold">';
                html += self.escapeHtml(eq.type_label_short || eq.label || '');
                html += '</text>';

                // Input endpoint (top)
                html += '<circle class="kundenkarte-endpoint kundenkarte-equipment-input" ';
                html += 'data-type="equipment-input" data-equipment-id="' + eq.id + '" ';
                html += 'cx="' + centerX + '" cy="' + (equipmentY - 15) + '" r="' + self.ENDPOINT_RADIUS + '" ';
                html += 'fill="#fff" stroke="' + color + '" stroke-width="2"/>';

                // Output endpoint (bottom)
                html += '<circle class="kundenkarte-endpoint kundenkarte-equipment-output" ';
                html += 'data-type="equipment-output" data-equipment-id="' + eq.id + '" ';
                html += 'cx="' + centerX + '" cy="' + (equipmentY + 15) + '" r="' + self.ENDPOINT_RADIUS + '" ';
                html += 'fill="#fff" stroke="' + color + '" stroke-width="2"/>';

                // Draw demo connections from phases to equipment
                // Distribute phases across equipment
                var phaseIndex = (eq.position_te - 1) % 3; // Rotate through L1, L2, L3
                var phase = phaseList[phaseIndex];
                var phaseColor = self.PHASE_COLORS[phase];
                var phaseY = phaseStartY + phaseIndex * (phaseHeight + phaseSpacing) + phaseHeight;

                // Demo connection line
                html += '<path class="kundenkarte-demo-connection" ';
                html += 'd="M ' + centerX + ' ' + phaseY + ' L ' + centerX + ' ' + (equipmentY - 15) + '" ';
                html += 'fill="none" stroke="' + phaseColor + '" stroke-width="2" stroke-dasharray="4,2" opacity="0.6"/>';

                // Phase indicator text below equipment
                html += '<text x="' + centerX + '" y="' + (equipmentY + 30) + '" text-anchor="middle" fill="' + phaseColor + '" font-size="8" font-weight="bold">';
                html += phase;
                html += '</text>';
            });

            html += '</g>'; // End demo equipment group

            // Legend
            html += '<g class="kundenkarte-demo-legend" transform="translate(10, 160)">';
            html += '<text x="0" y="0" fill="#888" font-size="9">Legende:</text>';

            phaseList.forEach(function(phase, idx) {
                var x = 60 + idx * 50;
                html += '<rect x="' + x + '" y="-8" width="12" height="8" fill="' + self.PHASE_COLORS[phase] + '" rx="1"/>';
                html += '<text x="' + (x + 16) + '" y="0" fill="' + self.PHASE_COLORS[phase] + '" font-size="9" font-weight="bold">' + phase + '</text>';
            });

            html += '</g>';

            return html;
        },

        // Helpers
        darkenColor: function(color, percent) {
            var num = parseInt(color.replace('#', ''), 16);
            var amt = Math.round(2.55 * percent);
            var R = (num >> 16) - amt;
            var G = (num >> 8 & 0x00FF) - amt;
            var B = (num & 0x0000FF) - amt;
            return '#' + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
                (G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
                (B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1);
        },

        escapeHtml: function(text) {
            if (!text) return '';
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }
    };

    /**
     * SchematicEditor - Interaktiver Schaltplan-Editor
     *
     * Features:
     * - Hutschienen als feste Zeilen
     * - Equipment-Blöcke verschiebbar auf Hutschiene
     * - Konfigurierbare Terminals pro Equipment-Typ
     * - Klick-Verbindungen: Ausgang klicken → Eingang klicken
     * - Rechtsklick zum Löschen
     * - Orthogonale Verbindungspfade
     */
    KundenKarte.SchematicEditor = {
        // Constants (40% larger for better visibility)
        TE_WIDTH: 56,
        RAIL_HEIGHT: 14,        // Hutschiene Höhe
        RAIL_SPACING: 308,      // Abstand zwischen Hutschienen (Platz für Blöcke + Verbindungen)
        BLOCK_HEIGHT: 112,
        TERMINAL_RADIUS: 8,
        GRID_SIZE: 14,
        MIN_TOP_MARGIN: 100,    // Minimaler Platz oben für Panel (inkl. Hauptsammelschienen)
        MAIN_BUSBAR_HEIGHT: 60, // Höhe des Hauptsammelschienen-Bereichs (L1,L2,L3,N,PE)
        BLOCK_INNER_OFFSET: 80, // Zusätzlicher Offset für Blöcke innerhalb des Panels
        BOTTOM_MARGIN: 56,      // Platz unten
        PANEL_GAP: 56,          // Abstand zwischen Panels
        PANEL_PADDING: 28,      // Innenabstand Panel
        CONNECTION_ROUTE_SPACE: 17, // Platz pro Verbindungsroute

        // Colors
        COLORS: {
            rail: '#666',
            railBg: '#444',
            block: '#3498db',
            input: '#e74c3c',
            output: '#27ae60',
            connection: '#f1c40f',
            selected: '#9b59b6',
            hover: '#fff',
            grid: '#2a2a2a',
            panelBg: '#1e1e1e',
            panelBorder: '#333'
        },

        PHASE_COLORS: {
            'L1': '#8B4513',
            'L2': '#1a1a1a',
            'L3': '#666666',
            'N': '#0066cc',
            'PE': '#27ae60'
        },

        // State
        anlageId: null,
        panels: [],
        carriers: [],
        equipment: [],
        connections: [],
        bridges: [],  // Terminal bridges (Brücken zwischen Klemmen)
        selectedTerminal: null,
        dragState: null,
        isInitialized: false,
        isLoading: false,
        svgElement: null,
        scale: 1,

        // Manual wire drawing mode
        wireDrawMode: false,
        wireDrawPoints: [],      // Array of {x, y} points for current wire
        wireDrawSourceEq: null,  // Source equipment ID
        wireDrawSourceTerm: null, // Source terminal ID
        WIRE_GRID_SIZE: 25,      // Snap grid size in pixels (larger = fewer points)

        // Default terminal configs for common types
        // Terminals are bidirectional - no strict input/output
        DEFAULT_TERMINALS: {
            'LS': { terminals: [{id: 't1', label: '●', pos: 'top'}, {id: 't2', label: '●', pos: 'bottom'}] },
            'FI': { terminals: [{id: 't1', label: 'L1', pos: 'top'}, {id: 't2', label: 'L2', pos: 'top'}, {id: 't3', label: 'L3', pos: 'top'}, {id: 't4', label: 'N', pos: 'top'}, {id: 't5', label: 'L1', pos: 'bottom'}, {id: 't6', label: 'L2', pos: 'bottom'}, {id: 't7', label: 'L3', pos: 'bottom'}, {id: 't8', label: 'N', pos: 'bottom'}] },
            'FI4P': { terminals: [{id: 't1', label: 'L1', pos: 'top'}, {id: 't2', label: 'L2', pos: 'top'}, {id: 't3', label: 'L3', pos: 'top'}, {id: 't4', label: 'N', pos: 'top'}, {id: 't5', label: 'L1', pos: 'bottom'}, {id: 't6', label: 'L2', pos: 'bottom'}, {id: 't7', label: 'L3', pos: 'bottom'}, {id: 't8', label: 'N', pos: 'bottom'}] },
            'SCHUETZ': { terminals: [{id: 't1', label: 'A1', pos: 'top'}, {id: 't2', label: '1', pos: 'top'}, {id: 't3', label: 'A2', pos: 'bottom'}, {id: 't4', label: '2', pos: 'bottom'}] },
            'KLEMME': { terminals: [{id: 't1', label: '●', pos: 'top'}, {id: 't2', label: '●', pos: 'bottom'}] },
            'LS3P': { terminals: [{id: 't1', label: 'L1', pos: 'top'}, {id: 't2', label: 'L2', pos: 'top'}, {id: 't3', label: 'L3', pos: 'top'}, {id: 't4', label: 'L1', pos: 'bottom'}, {id: 't5', label: 'L2', pos: 'bottom'}, {id: 't6', label: 'L3', pos: 'bottom'}] }
        },

        init: function(anlageId) {
            if (!anlageId) {
                console.error('SchematicEditor.init: No anlageId provided!');
                return;
            }
            this.anlageId = anlageId;
            this.bindEvents();
            this.loadData();
        },

        bindEvents: function() {
            var self = this;

            // Terminal click - only used in wire draw mode
            $(document).off('click.terminal').on('click.terminal', '.schematic-terminal', function(e) {
                e.preventDefault();
                e.stopPropagation();
                // Only handle in manual wire draw mode
                if (self.wireDrawMode) {
                    self.handleTerminalClick($(this));
                }
            });

            // Block drag - track if dragged to distinguish from click
            $(document).off('mousedown.blockDrag').on('mousedown.blockDrag', '.schematic-block', function(e) {
                if ($(e.target).hasClass('schematic-terminal')) return;
                e.preventDefault();
                self.blockDragStartPos = { x: e.clientX, y: e.clientY };
                self.blockWasDragged = false;
                self.clickedEquipmentId = $(this).data('equipment-id');
                self.startDragBlock($(this), e);
            });

            $(document).off('mousemove.blockDrag').on('mousemove.blockDrag', function(e) {
                if (self.dragState && self.dragState.type === 'block') {
                    // Check if moved more than 5px - then it's a drag, not a click
                    if (self.blockDragStartPos) {
                        var dx = Math.abs(e.clientX - self.blockDragStartPos.x);
                        var dy = Math.abs(e.clientY - self.blockDragStartPos.y);
                        if (dx > 5 || dy > 5) {
                            self.blockWasDragged = true;
                        }
                    }
                    self.updateDragBlock(e);
                }
            });

            $(document).off('mouseup.blockDrag').on('mouseup.blockDrag', function(e) {
                var equipmentId = self.clickedEquipmentId;

                if (self.dragState && self.dragState.type === 'block') {
                    self.endDragBlock(e);
                }

                // If not dragged, show popup
                if (!self.blockWasDragged && equipmentId) {
                    self.showEquipmentPopup(equipmentId, e.clientX, e.clientY);
                }

                self.blockDragStartPos = null;
                self.blockWasDragged = false;
                self.clickedEquipmentId = null;
            });

            // Hide popups when clicking elsewhere
            $(document).off('mousedown.hidePopup').on('mousedown.hidePopup', function(e) {
                // Don't hide if clicking on popup buttons
                if ($(e.target).closest('.schematic-connection-popup, .schematic-equipment-popup, .schematic-carrier-popup').length) {
                    return;
                }
                // Don't hide if clicking on SVG elements (handlers will handle it)
                if ($(e.target).closest('svg').length) {
                    return;
                }
                self.hideConnectionPopup();
                self.hideEquipmentPopup();
                self.hideCarrierPopup();
            });

            // Clear all connections
            $(document).off('click.clearConns').on('click.clearConns', '.schematic-clear-connections', function(e) {
                e.preventDefault();
                self.showConfirmDialog('Alle löschen', 'Alle Verbindungen wirklich löschen?', function() {
                    self.clearAllConnections();
                });
            });

            // BOM (Bill of Materials) / Stückliste
            $(document).off('click.bomGenerate').on('click.bomGenerate', '.schematic-bom-generate', function(e) {
                e.preventDefault();
                self.showBOMDialog();
            });

            // Audit Log
            $(document).off('click.auditLog').on('click.auditLog', '.schematic-audit-log', function(e) {
                e.preventDefault();
                self.showAuditLogDialog();
            });

            // Escape key - no longer needed for auto-selection, wire draw has its own handler

            // Zoom with mouse wheel
            $(document).off('wheel.schematicZoom').on('wheel.schematicZoom', '.schematic-editor-canvas', function(e) {
                if (e.ctrlKey || e.metaKey) {
                    e.preventDefault();
                    var delta = e.originalEvent.deltaY > 0 ? -0.1 : 0.1;
                    self.setZoom(self.scale + delta);
                }
            });

            // Zoom buttons
            $(document).off('click.zoomIn').on('click.zoomIn', '.schematic-zoom-in', function(e) {
                e.preventDefault();
                self.setZoom(self.scale + 0.1);
            });
            $(document).off('click.zoomOut').on('click.zoomOut', '.schematic-zoom-out', function(e) {
                e.preventDefault();
                self.setZoom(self.scale - 0.1);
            });
            $(document).off('click.zoomReset').on('click.zoomReset', '.schematic-zoom-reset', function(e) {
                e.preventDefault();
                self.setZoom(1);
            });
            $(document).off('click.zoomFit').on('click.zoomFit', '.schematic-zoom-fit', function(e) {
                e.preventDefault();
                self.zoomToFit();
            });

            // ======================================
            // Keyboard Shortcuts
            // ======================================
            $(document).off('keydown.schematicShortcuts').on('keydown.schematicShortcuts', function(e) {
                // Only handle shortcuts when we're in the schematic editor
                if (!$('.schematic-editor-canvas').length) return;

                // Don't handle if user is typing in an input/textarea
                if ($(e.target).is('input, textarea, select, [contenteditable]')) return;

                // Ctrl+S / Cmd+S - Save (reload data to ensure fresh state)
                if ((e.ctrlKey || e.metaKey) && e.key === 's') {
                    e.preventDefault();
                    self.showSaveIndicator();
                    return;
                }

                // Escape - Close all popups, cancel wire draw mode
                if (e.key === 'Escape') {
                    e.preventDefault();
                    // Close all popups
                    $('.schematic-equipment-popup, .schematic-carrier-popup, .schematic-connection-popup, .schematic-busbar-popup, .schematic-bridge-popup').remove();

                    // Cancel wire draw mode
                    if (self.wireDrawMode) {
                        self.cancelWireDraw();
                    }
                    return;
                }

                // Delete/Backspace - Delete selected equipment (if popup is open)
                if (e.key === 'Delete' || e.key === 'Backspace') {
                    var $popup = $('.schematic-equipment-popup');
                    if ($popup.length) {
                        e.preventDefault();
                        var equipmentId = $popup.data('equipment-id');
                        if (equipmentId) {
                            $popup.remove();
                            self.deleteEquipment(equipmentId);
                        }
                    }
                    return;
                }

                // + / = - Zoom in
                if (e.key === '+' || e.key === '=') {
                    e.preventDefault();
                    self.setZoom(self.scale + 0.1);
                    return;
                }

                // - - Zoom out
                if (e.key === '-') {
                    e.preventDefault();
                    self.setZoom(self.scale - 0.1);
                    return;
                }

                // 0 - Reset zoom
                if (e.key === '0' && !e.ctrlKey && !e.metaKey) {
                    e.preventDefault();
                    self.setZoom(1);
                    return;
                }

                // F - Fit to screen
                if (e.key === 'f' || e.key === 'F') {
                    e.preventDefault();
                    self.zoomToFit();
                    return;
                }

                // R - Reload/Refresh data
                if (e.key === 'r' || e.key === 'R') {
                    if (!e.ctrlKey && !e.metaKey) {
                        e.preventDefault();
                        self.loadData();
                        return;
                    }
                }
            });

            // Bridge click - show delete popup
            $(document).off('click.bridge').on('click.bridge', '.schematic-bridge', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var bridgeId = $(this).data('bridge-id');
                self.showBridgePopup(bridgeId, e.clientX, e.clientY);
            });

            // Busbar click - show edit/delete popup (only if not dragging)
            $(document).off('click.busbar').on('click.busbar', '.schematic-busbar', function(e) {
                if (self.busbarDragging) return; // Don't show popup if we just finished dragging
                e.preventDefault();
                e.stopPropagation();
                var connectionId = $(this).data('connection-id');
                self.showBusbarPopup(connectionId, e.clientX, e.clientY);
            });

            // Busbar drag - allow repositioning by dragging (keeps width, can move to other carriers)
            $(document).off('mousedown.busbarDrag').on('mousedown.busbarDrag', '.schematic-busbar', function(e) {
                if (e.button !== 0) return; // Only left mouse button
                e.preventDefault();
                e.stopPropagation();

                var $busbar = $(this);
                var connectionId = $busbar.data('connection-id');
                var conn = self.connections.find(function(c) { return String(c.id) === String(connectionId); });
                if (!conn) return;

                // Get carrier for this busbar
                var carrier = self.carriers.find(function(c) { return String(c.id) === String(conn.fk_carrier); });
                if (!carrier) return;

                // Calculate busbar width in TE (this should stay constant)
                var originalStartTE = parseInt(conn.rail_start_te) || 1;
                var originalEndTE = parseInt(conn.rail_end_te) || 1;
                var busbarWidthTE = originalEndTE - originalStartTE + 1;

                self.busbarDragData = {
                    connectionId: connectionId,
                    conn: conn,
                    originalCarrier: carrier,
                    currentCarrier: carrier,
                    startX: e.clientX,
                    startY: e.clientY,
                    originalStartTE: originalStartTE,
                    originalEndTE: originalEndTE,
                    busbarWidthTE: busbarWidthTE, // Keep width constant
                    moved: false
                };

                $busbar.css('cursor', 'grabbing');
            });

            $(document).off('mousemove.busbarDrag').on('mousemove.busbarDrag', function(e) {
                if (!self.busbarDragData) return;

                var data = self.busbarDragData;
                var dx = e.clientX - data.startX;
                var dy = e.clientY - data.startY;

                // Only start dragging after 5px movement
                if (!data.moved && Math.abs(dx) < 5 && Math.abs(dy) < 5) return;
                data.moved = true;
                self.busbarDragging = true;

                // Find which carrier the mouse is over (based on Y position)
                var svgRect = $(self.svgElement)[0].getBoundingClientRect();
                var mouseY = e.clientY - svgRect.top;
                var targetCarrier = data.originalCarrier;

                // Check all carriers to find which one we're over
                self.carriers.forEach(function(carrier) {
                    if (typeof carrier._y !== 'undefined') {
                        var carrierTop = carrier._y - self.BLOCK_HEIGHT / 2 - 50;
                        var carrierBottom = carrier._y + self.BLOCK_HEIGHT / 2 + 50;
                        if (mouseY >= carrierTop && mouseY <= carrierBottom) {
                            targetCarrier = carrier;
                        }
                    }
                });

                data.currentCarrier = targetCarrier;

                // Calculate new start TE based on horizontal movement relative to target carrier
                var mouseX = e.clientX - svgRect.left;
                var relativeX = mouseX - targetCarrier._x;
                var newStartTE = Math.round(relativeX / self.TE_WIDTH) + 1;

                // Keep width constant - calculate new end based on fixed width
                var newEndTE = newStartTE + data.busbarWidthTE - 1;

                // Clamp to carrier bounds (shift if needed to fit)
                var totalTE = parseInt(targetCarrier.total_te) || 12;
                if (newStartTE < 1) {
                    newStartTE = 1;
                    newEndTE = newStartTE + data.busbarWidthTE - 1;
                }
                if (newEndTE > totalTE) {
                    newEndTE = totalTE;
                    newStartTE = Math.max(1, newEndTE - data.busbarWidthTE + 1);
                }

                // Update visual preview
                var $busbar = $('.schematic-busbar[data-connection-id="' + data.connectionId + '"]');
                var startX = targetCarrier._x + (newStartTE - 1) * self.TE_WIDTH;
                var width = data.busbarWidthTE * self.TE_WIDTH;

                // Calculate new Y position based on target carrier
                var posY = parseInt(data.conn.position_y) || 0;
                var railCenterY = targetCarrier._y + self.RAIL_HEIGHT / 2;
                var blockTop = railCenterY - self.BLOCK_HEIGHT / 2;
                var blockBottom = railCenterY + self.BLOCK_HEIGHT / 2;
                var busbarHeight = 24;
                var newBusbarY;
                if (posY === 0) {
                    newBusbarY = blockTop - busbarHeight - 25;
                } else {
                    newBusbarY = blockBottom + 25;
                }

                $busbar.find('rect').each(function(idx) {
                    $(this).attr('x', startX);
                    $(this).attr('width', width);
                    // Update Y position (with shadow offset for second rect)
                    var yOffset = idx === 0 ? 2 : 0; // Shadow has +2 offset
                    $(this).attr('y', newBusbarY + yOffset);
                });

                // Store new positions for drop
                data.newStartTE = newStartTE;
                data.newEndTE = newEndTE;
                data.newCarrierId = targetCarrier.id;
            });

            $(document).off('mouseup.busbarDrag').on('mouseup.busbarDrag', function(e) {
                if (!self.busbarDragData) return;

                var data = self.busbarDragData;
                self.busbarDragData = null;

                $('.schematic-busbar').css('cursor', 'pointer');

                if (data.moved && data.newStartTE && data.newEndTE) {
                    // Save new position (and possibly new carrier)
                    self.updateBusbarPosition(data.connectionId, data.newStartTE, data.newEndTE, data.newCarrierId);
                }

                // Clear drag flag after a short delay (to prevent click popup)
                setTimeout(function() {
                    self.busbarDragging = false;
                }, 100);
            });

            // Rail (Hutschiene) click - show popup for editing
            $(document).off('click.rail').on('click.rail', '.schematic-rail', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var carrierId = $(this).data('carrier-id');
                if (carrierId) {
                    self.showCarrierPopup(carrierId, e.clientX, e.clientY);
                }
            });

            // Terminal right-click - show output/cable dialog
            $(document).off('contextmenu.terminal').on('contextmenu.terminal', '.schematic-terminal', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $terminal = $(this);
                var eqId = $terminal.data('equipment-id');
                var termId = $terminal.data('terminal-id');
                self.showOutputDialog(eqId, termId, e.clientX, e.clientY);
            });

            // Toggle manual wire draw mode
            $(document).off('click.toggleWireDraw').on('click.toggleWireDraw', '.schematic-wire-draw-toggle', function(e) {
                e.preventDefault();
                self.toggleWireDrawMode();
            });

            // SVG click for wire drawing - add waypoint
            $(document).off('click.wireDrawSvg').on('click.wireDrawSvg', '.schematic-editor-canvas svg', function(e) {
                if (!self.wireDrawMode) return;
                // Only add waypoints after source terminal is selected
                if (!self.wireDrawSourceEq) {
                    // Show hint if clicking on canvas without selecting terminal first
                    if (!$(e.target).closest('.schematic-terminal').length) {
                        self.showMessage('Zuerst ein START-Terminal anklicken!', 'warning');
                    }
                    return;
                }
                // Don't add point if clicking on terminal or block
                if ($(e.target).closest('.schematic-terminal, .schematic-block').length) return;

                var svg = self.svgElement;
                var pt = svg.createSVGPoint();
                pt.x = e.clientX;
                pt.y = e.clientY;
                var svgP = pt.matrixTransform(svg.getScreenCTM().inverse());

                // Snap to nearest terminal-aligned grid point
                var snapped = self.snapToTerminalGrid(svgP.x, svgP.y);

                self.wireDrawPoints.push({x: snapped.x, y: snapped.y});
                self.updateWirePreview();
                console.log('Wire point added:', snapped.x, snapped.y, 'Total points:', self.wireDrawPoints.length);
            });

            // SVG mousemove for wire preview - show cursor and preview line
            $(document).off('mousemove.wireDraw').on('mousemove.wireDraw', '.schematic-editor-canvas svg', function(e) {
                if (!self.wireDrawMode) return;

                var svg = self.svgElement;
                var pt = svg.createSVGPoint();
                pt.x = e.clientX;
                pt.y = e.clientY;
                var svgP = pt.matrixTransform(svg.getScreenCTM().inverse());

                // Snap to nearest terminal-aligned grid point
                var snapped = self.snapToTerminalGrid(svgP.x, svgP.y);

                // Always update cursor position (even before source is selected)
                self.updateWirePreviewCursor(snapped.x, snapped.y);
            });

            // Right-click to cancel wire drawing completely
            $(document).off('contextmenu.wireDraw').on('contextmenu.wireDraw', '.schematic-editor-canvas svg', function(e) {
                if (!self.wireDrawMode) return;
                e.preventDefault();
                if (self.wireDrawSourceEq) {
                    // Cancel entire drawing
                    self.cancelWireDrawing();
                }
            });

            // Escape to cancel wire drawing
            $(document).off('keydown.wireDraw').on('keydown.wireDraw', function(e) {
                if (e.key === 'Escape' && self.wireDrawMode && self.wireDrawSourceEq) {
                    self.cancelWireDrawing();
                }
            });
        },

        showBusbarPopup: function(connectionId, x, y) {
            var self = this;
            this.hideBusbarPopup();

            var conn = this.connections.find(function(c) { return String(c.id) === String(connectionId); });
            if (!conn) return;

            var html = '<div class="schematic-busbar-popup" style="position:fixed;left:' + x + 'px;top:' + y + 'px;background:#2d2d44;border:1px solid #555;border-radius:6px;padding:10px;z-index:100002;min-width:150px;">';
            html += '<div style="color:#fff;font-weight:bold;margin-bottom:8px;">Sammelschiene</div>';
            html += '<div style="color:#aaa;font-size:12px;margin-bottom:8px;">' + (conn.rail_phases || conn.connection_type || 'Unbekannt') + '</div>';
            html += '<div style="display:flex;gap:8px;">';
            html += '<button class="busbar-edit-btn" data-id="' + connectionId + '" style="flex:1;background:#3498db;color:#fff;border:none;border-radius:4px;padding:6px 10px;cursor:pointer;">Bearbeiten</button>';
            html += '<button class="busbar-delete-btn" data-id="' + connectionId + '" style="flex:1;background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:6px 10px;cursor:pointer;">Löschen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.busbar-edit-btn').on('click', function() {
                var id = $(this).data('id');
                self.hideBusbarPopup();
                self.showEditBusbarDialog(id);
            });

            $('.busbar-delete-btn').on('click', function() {
                var id = $(this).data('id');
                self.hideBusbarPopup();
                self.deleteBusbar(id);
            });

            // Close on click outside
            setTimeout(function() {
                $(document).one('click', function() {
                    self.hideBusbarPopup();
                });
            }, 100);
        },

        hideBusbarPopup: function() {
            $('.schematic-busbar-popup').remove();
        },

        // Show a brief save/refresh indicator
        showSaveIndicator: function() {
            var self = this;
            var $indicator = $('<div class="schematic-save-indicator" style="position:fixed;top:20px;left:50%;transform:translateX(-50%);background:#27ae60;color:#fff;padding:10px 20px;border-radius:6px;z-index:100003;font-weight:bold;box-shadow:0 4px 12px rgba(0,0,0,0.3);"><i class="fa fa-check"></i> Gespeichert</div>');
            $('body').append($indicator);

            // Reload data to ensure fresh state
            this.loadData();

            setTimeout(function() {
                $indicator.fadeOut(300, function() { $(this).remove(); });
            }, 1500);
        },

        // Cancel wire draw mode
        cancelWireDraw: function() {
            this.wireDrawMode = false;
            this.wireDrawPoints = [];
            this.wireDrawSourceEq = null;
            this.wireDrawSourceTerm = null;
            // Remove any temporary wire preview
            $('.schematic-wire-preview').remove();
            // Remove the preview path if exists
            if (this.svgElement) {
                $(this.svgElement).find('.temp-wire-path').remove();
            }
        },

        showBridgePopup: function(bridgeId, x, y) {
            var self = this;
            this.hideBridgePopup();

            var bridge = this.bridges.find(function(b) { return String(b.id) === String(bridgeId); });
            if (!bridge) return;

            var html = '<div class="schematic-bridge-popup" style="position:fixed;left:' + x + 'px;top:' + y + 'px;background:#2d2d44;border:1px solid #555;border-radius:6px;padding:10px;z-index:100002;min-width:150px;">';
            html += '<div style="color:#fff;font-weight:bold;margin-bottom:8px;">Brücke</div>';
            html += '<div style="color:#aaa;font-size:12px;margin-bottom:8px;">TE ' + bridge.start_te + ' - ' + bridge.end_te + ' (' + bridge.terminal_side + ')</div>';
            html += '<div style="display:flex;gap:8px;">';
            html += '<button class="bridge-delete-btn" data-id="' + bridgeId + '" style="flex:1;background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:6px 10px;cursor:pointer;">Löschen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.bridge-delete-btn').on('click', function() {
                var id = $(this).data('id');
                self.hideBridgePopup();
                self.deleteBridge(id);
            });

            // Close on click outside
            setTimeout(function() {
                $(document).one('click', function() {
                    self.hideBridgePopup();
                });
            }, 100);
        },

        hideBridgePopup: function() {
            $('.schematic-bridge-popup').remove();
        },

        deleteBridge: function(bridgeId) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'delete_bridge',
                    bridge_id: bridgeId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Brücke gelöscht', 'success');
                        // Remove from local data
                        self.bridges = self.bridges.filter(function(b) { return String(b.id) !== String(bridgeId); });
                        self.render();
                    } else {
                        self.showMessage(response.error || 'Fehler beim Löschen', 'error');
                    }
                }
            });
        },

        createBridge: function(carrierId, startTE, endTE, terminalSide, terminalRow, color) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'create_bridge',
                    anlage_id: this.anlageId,
                    carrier_id: carrierId,
                    start_te: startTE,
                    end_te: endTE,
                    terminal_side: terminalSide || 'top',
                    terminal_row: terminalRow || 0,
                    color: color || '#e74c3c',
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Brücke erstellt', 'success');
                        // Add to local data
                        self.bridges.push(response.bridge);
                        self.render();
                    } else {
                        self.showMessage(response.error || 'Fehler beim Erstellen', 'error');
                    }
                }
            });
        },

        showCreateBridgeDialog: function(carrierId, defaultStartTE, defaultEndTE) {
            var self = this;
            var carrier = this.carriers.find(function(c) { return String(c.id) === String(carrierId); });
            if (!carrier) return;

            var html = '<div class="schematic-dialog-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';
            html += '<div class="schematic-dialog" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;z-index:100001;min-width:300px;">';
            html += '<h3 style="margin:0 0 15px 0;color:#fff;">Brücke erstellen</h3>';

            // Start TE
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Von TE:</label>';
            html += '<input type="number" class="dialog-bridge-start" value="' + (defaultStartTE || 1) + '" min="1" max="' + carrier.total_te + '" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // End TE
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Bis TE:</label>';
            html += '<input type="number" class="dialog-bridge-end" value="' + (defaultEndTE || 2) + '" min="1" max="' + carrier.total_te + '" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Terminal Side
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Seite:</label>';
            html += '<select class="dialog-bridge-side" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;">';
            html += '<option value="top">Oben</option>';
            html += '<option value="bottom">Unten</option>';
            html += '</select></div>';

            // Terminal Row
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Reihe (0=erste):</label>';
            html += '<input type="number" class="dialog-bridge-row" value="0" min="0" max="5" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Color
            html += '<div style="margin-bottom:15px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Farbe:</label>';
            html += '<input type="color" class="dialog-bridge-color" value="#e74c3c" style="width:100%;padding:4px;border:1px solid #555;border-radius:4px;background:#1e1e1e;height:36px;box-sizing:border-box;"/></div>';

            // Buttons
            html += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button class="dialog-cancel" style="padding:8px 16px;border:1px solid #555;border-radius:4px;background:#444;color:#fff;cursor:pointer;">Abbrechen</button>';
            html += '<button class="dialog-save" style="padding:8px 16px;border:none;border-radius:4px;background:#27ae60;color:#fff;cursor:pointer;">Erstellen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.dialog-cancel').on('click', function() {
                $('.schematic-dialog-overlay, .schematic-dialog').remove();
            });

            $('.dialog-save').on('click', function() {
                var startTE = parseInt($('.dialog-bridge-start').val()) || 1;
                var endTE = parseInt($('.dialog-bridge-end').val()) || 2;
                var side = $('.dialog-bridge-side').val();
                var row = parseInt($('.dialog-bridge-row').val()) || 0;
                var color = $('.dialog-bridge-color').val();

                $('.schematic-dialog-overlay, .schematic-dialog').remove();
                self.createBridge(carrierId, startTE, endTE, side, row, color);
            });

            // Close on Escape
            $(document).on('keydown.dialog', function(e) {
                if (e.key === 'Escape') {
                    $('.schematic-dialog-overlay, .schematic-dialog').remove();
                    $(document).off('keydown.dialog');
                }
            });
        },

        showCarrierPopup: function(carrierId, x, y) {
            var self = this;
            this.hideCarrierPopup();

            var carrier = this.carriers.find(function(c) { return String(c.id) === String(carrierId); });
            if (!carrier) return;

            var html = '<div class="schematic-carrier-popup" style="position:fixed;left:' + x + 'px;top:' + y + 'px;background:#2d2d44;border:1px solid #555;border-radius:6px;padding:10px;z-index:100002;min-width:180px;">';
            html += '<div style="color:#fff;font-weight:bold;margin-bottom:8px;">Hutschiene</div>';
            html += '<div style="color:#aaa;font-size:12px;margin-bottom:8px;">' + this.escapeHtml(carrier.label || 'Ohne Name') + ' (' + carrier.total_te + ' TE)</div>';
            html += '<div style="display:flex;flex-direction:column;gap:8px;">';
            html += '<div style="display:flex;gap:8px;">';
            html += '<button class="carrier-edit-btn" data-id="' + carrierId + '" style="flex:1;background:#3498db;color:#fff;border:none;border-radius:4px;padding:6px 10px;cursor:pointer;">Bearbeiten</button>';
            html += '<button class="carrier-delete-btn" data-id="' + carrierId + '" style="flex:1;background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:6px 10px;cursor:pointer;">Löschen</button>';
            html += '</div>';
            html += '<button class="carrier-add-bridge-btn" data-id="' + carrierId + '" style="background:#f39c12;color:#fff;border:none;border-radius:4px;padding:6px 10px;cursor:pointer;"><i class="fa fa-link"></i> Brücke hinzufügen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.carrier-edit-btn').on('click', function() {
                var id = $(this).data('id');
                self.hideCarrierPopup();
                self.showEditCarrierDialog(id);
            });

            $('.carrier-delete-btn').on('click', function() {
                var id = $(this).data('id');
                self.hideCarrierPopup();
                self.deleteCarrier(id);
            });

            $('.carrier-add-bridge-btn').on('click', function() {
                var id = $(this).data('id');
                self.hideCarrierPopup();
                self.showCreateBridgeDialog(id, 1, 2);
            });

            // Close on click outside
            setTimeout(function() {
                $(document).one('click', function() {
                    self.hideCarrierPopup();
                });
            }, 100);
        },

        hideCarrierPopup: function() {
            $('.schematic-carrier-popup').remove();
        },

        showEditCarrierDialog: function(carrierId) {
            var self = this;
            var carrier = this.carriers.find(function(c) { return String(c.id) === String(carrierId); });
            if (!carrier) return;

            var html = '<div class="schematic-dialog-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';
            html += '<div class="schematic-dialog" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;z-index:100001;min-width:300px;">';
            html += '<h3 style="margin:0 0 15px 0;color:#fff;">Hutschiene bearbeiten</h3>';

            // Label
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Bezeichnung:</label>';
            html += '<input type="text" class="dialog-carrier-label" value="' + this.escapeHtml(carrier.label || '') + '" placeholder="z.B. H1" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Total TE
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Breite (TE):</label>';
            html += '<input type="number" class="dialog-carrier-te" value="' + (carrier.total_te || 12) + '" min="1" max="100" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Buttons
            html += '<div style="display:flex;gap:10px;margin-top:15px;">';
            html += '<button class="dialog-carrier-save" style="flex:1;background:#27ae60;color:#fff;border:none;border-radius:4px;padding:10px;cursor:pointer;font-weight:bold;">Speichern</button>';
            html += '<button class="dialog-carrier-cancel" style="flex:1;background:#555;color:#fff;border:none;border-radius:4px;padding:10px;cursor:pointer;">Abbrechen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.dialog-carrier-save').on('click', function() {
                var label = $('.dialog-carrier-label').val();
                var totalTe = parseInt($('.dialog-carrier-te').val()) || 12;
                self.updateCarrier(carrierId, label, totalTe);
                self.closeDialog();
            });

            $('.dialog-carrier-cancel, .schematic-dialog-overlay').on('click', function() {
                self.closeDialog();
            });
        },

        updateCarrier: function(carrierId, label, totalTe) {
            var self = this;
            var baseUrl = $('body').data('base-url') || '';

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                method: 'POST',
                data: {
                    action: 'update',
                    carrier_id: carrierId,
                    label: label,
                    total_te: totalTe,
                    token: KundenKarte.token
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.loadData();
                        self.showMessage('Hutschiene aktualisiert', 'success');
                    } else {
                        self.showMessage('Fehler: ' + (response.error || 'Unbekannt'), 'error');
                    }
                },
                error: function() {
                    self.showMessage('Fehler beim Speichern', 'error');
                }
            });
        },

        deleteCarrier: function(carrierId) {
            var self = this;
            var baseUrl = $('body').data('base-url') || '';

            this.showConfirmDialog('Hutschiene löschen', 'Diese Hutschiene und alle Equipments darauf wirklich löschen?', function() {
                $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                    method: 'POST',
                    data: {
                        action: 'delete',
                        carrier_id: carrierId,
                        token: KundenKarte.token
                    },
                    dataType: 'json',
                    success: function(response) {
                        if (response.success) {
                            self.loadData();
                            self.showMessage('Hutschiene gelöscht', 'success');
                        } else {
                            self.showMessage('Fehler: ' + (response.error || 'Unbekannt'), 'error');
                        }
                    },
                    error: function() {
                        self.showMessage('Fehler beim Löschen', 'error');
                    }
                });
            });
        },

        showEditBusbarDialog: function(connectionId) {
            var self = this;
            var conn = this.connections.find(function(c) { return String(c.id) === String(connectionId); });
            if (!conn) return;

            var carrier = this.carriers.find(function(c) { return String(c.id) === String(conn.fk_carrier); });
            var totalTE = carrier ? (parseInt(carrier.total_te) || 12) : 12;

            var html = '<div class="schematic-dialog-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';
            html += '<div class="schematic-dialog" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;z-index:100001;min-width:350px;">';
            html += '<h3 style="margin:0 0 15px 0;color:#fff;">Sammelschiene bearbeiten</h3>';

            // Phase type selection
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Phasen:</label>';
            html += '<select class="dialog-busbar-phases" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            var phases = conn.rail_phases || conn.connection_type || 'L1L2L3';
            html += '<option value="L1"' + (phases === 'L1' ? ' selected' : '') + '>L1 (Phase 1)</option>';
            html += '<option value="L2"' + (phases === 'L2' ? ' selected' : '') + '>L2 (Phase 2)</option>';
            html += '<option value="L3"' + (phases === 'L3' ? ' selected' : '') + '>L3 (Phase 3)</option>';
            html += '<option value="L1L2L3"' + (phases === 'L1L2L3' ? ' selected' : '') + '>L1+L2+L3 (Dreiphasig)</option>';
            html += '<option value="N"' + (phases === 'N' ? ' selected' : '') + '>N (Neutralleiter)</option>';
            html += '<option value="PE"' + (phases === 'PE' ? ' selected' : '') + '>PE (Schutzleiter)</option>';
            html += '</select></div>';

            // Start TE
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Von TE:</label>';
            html += '<input type="number" class="dialog-busbar-start" value="' + (conn.rail_start_te || 1) + '" min="1" max="' + totalTE + '" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // End TE
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Bis TE:</label>';
            html += '<input type="number" class="dialog-busbar-end" value="' + (conn.rail_end_te || totalTE) + '" min="1" max="' + totalTE + '" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Position (above/below)
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Position:</label>';
            html += '<select class="dialog-busbar-position" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            var posY = parseInt(conn.position_y) || 0;
            html += '<option value="0"' + (posY === 0 ? ' selected' : '') + '>Oben</option>';
            html += '<option value="1"' + (posY === 1 ? ' selected' : '') + '>Unten</option>';
            html += '</select></div>';

            // Excluded TEs
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">TEs auslassen (z.B. 3,5,7):</label>';
            html += '<input type="text" class="dialog-busbar-excluded" value="' + (conn.excluded_te || '') + '" placeholder="Kommagetrennte TE-Nummern" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Color
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Farbe:</label>';
            html += '<input type="color" class="dialog-busbar-color" value="' + (conn.color || '#e74c3c') + '" style="width:100%;padding:4px;height:40px;border:1px solid #555;border-radius:4px;background:#1e1e1e;cursor:pointer;"/></div>';

            html += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button type="button" class="dialog-cancel" style="background:#555;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Abbrechen</button>';
            html += '<button type="button" class="dialog-save" style="background:#27ae60;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Speichern</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.dialog-cancel, .schematic-dialog-overlay').on('click', function() {
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });

            $('.dialog-save').on('click', function() {
                var newPhases = $('.dialog-busbar-phases').val();
                var startTE = parseInt($('.dialog-busbar-start').val()) || 1;
                var endTE = parseInt($('.dialog-busbar-end').val()) || totalTE;
                var newPosY = parseInt($('.dialog-busbar-position').val()) || 0;
                var excludedTE = $('.dialog-busbar-excluded').val() || '';
                var color = $('.dialog-busbar-color').val();

                self.updateBusbar(connectionId, newPhases, startTE, endTE, newPosY, color, excludedTE);
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });
        },

        updateBusbar: function(connectionId, phases, startTE, endTE, positionY, color, excludedTE) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'update',
                    connection_id: connectionId,
                    rail_start_te: startTE,
                    rail_end_te: endTE,
                    rail_phases: phases,
                    position_y: positionY,
                    color: color,
                    excluded_te: excludedTE,
                    connection_type: phases,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Sammelschiene aktualisiert', 'success');
                        // Update local data
                        var conn = self.connections.find(function(c) { return String(c.id) === String(connectionId); });
                        if (conn) {
                            conn.rail_start_te = startTE;
                            conn.rail_end_te = endTE;
                            conn.rail_phases = phases;
                            conn.position_y = positionY;
                            conn.color = color;
                            conn.excluded_te = excludedTE;
                            conn.connection_type = phases;
                        }
                        self.render();
                    } else {
                        self.showMessage(response.error || 'Fehler beim Aktualisieren', 'error');
                    }
                }
            });
        },

        deleteBusbar: function(connectionId) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'delete',
                    connection_id: connectionId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Sammelschiene gelöscht', 'success');
                        // Remove from local data
                        self.connections = self.connections.filter(function(c) { return String(c.id) !== String(connectionId); });
                        self.render();
                    } else {
                        self.showMessage(response.error || 'Fehler beim Löschen', 'error');
                    }
                }
            });
        },

        loadData: function() {
            var self = this;

            // Prevent multiple simultaneous loads (race condition fix)
            if (this.isLoading) {
                return;
            }
            this.isLoading = true;

            // Load panels with carriers for this anlage
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                data: { action: 'list_with_carriers', anlage_id: this.anlageId },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.panels = response.panels || [];
                        // Flatten carriers from all panels
                        self.carriers = [];
                        self.panels.forEach(function(panel) {
                            if (panel.carriers) {
                                panel.carriers.forEach(function(c) {
                                    c.panel_id = panel.id;
                                    self.carriers.push(c);
                                });
                            }
                        });
                        self.loadEquipment();
                    } else {
                        self.isLoading = false;
                    }
                },
                error: function(xhr, status, error) {
                    self.isLoading = false;
                    // Show visible error
                    $('.schematic-editor-canvas').html('<div style="padding:20px;color:#e74c3c;">AJAX Fehler beim Laden: ' + error + '</div>');
                }
            });
        },

        loadEquipment: function() {
            var self = this;
            var promises = [];

            this.equipment = [];

            this.carriers.forEach(function(carrier) {
                var promise = $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                    data: { action: 'list', carrier_id: carrier.id },
                    dataType: 'json'
                }).then(function(response) {
                    if (response.success && response.equipment) {
                        response.equipment.forEach(function(eq) {
                            eq.carrier_id = carrier.id;
                            eq.panel_id = carrier.panel_id;
                            self.equipment.push(eq);
                        });
                    }
                });
                promises.push(promise);
            });

            $.when.apply($, promises).then(function() {
                self.loadConnections();
            }).fail(function() {
                self.isLoading = false;
            });
        },

        loadConnections: function() {
            var self = this;

            // Load connections and bridges in parallel
            var connectionsLoaded = false;
            var bridgesLoaded = false;

            var checkComplete = function() {
                if (connectionsLoaded && bridgesLoaded) {
                    // Initialize canvas now that all data is loaded
                    if (!self.isInitialized) {
                        self.initCanvas();
                    } else {
                        self.render();
                    }
                    // Reset loading flag
                    self.isLoading = false;
                }
            };

            // Load connections
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                data: { action: 'list_all', anlage_id: this.anlageId },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.connections = response.connections || [];

                        // Restore any manually drawn paths
                        if (self._manualPaths) {
                            self.connections.forEach(function(conn) {
                                if (self._manualPaths[conn.id]) {
                                    conn._manualPath = self._manualPaths[conn.id];
                                }
                            });
                        }
                    }
                    connectionsLoaded = true;
                    checkComplete();
                },
                error: function() {
                    connectionsLoaded = true;
                    checkComplete();
                }
            });

            // Load bridges
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                data: { action: 'list_bridges', anlage_id: this.anlageId },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.bridges = response.bridges || [];
                    }
                    bridgesLoaded = true;
                    checkComplete();
                },
                error: function() {
                    bridgesLoaded = true;
                    checkComplete();
                }
            });
        },

        calculateLayout: function() {
            var self = this;

            // Calculate dynamic TOP_MARGIN based on number of connections going up
            // Count connections that route above blocks (top-to-top connections)
            var topConnections = 0;
            this.connections.forEach(function(conn) {
                if (parseInt(conn.is_rail) !== 1 && conn.fk_source && conn.fk_target) {
                    topConnections++;
                }
            });
            // Panel top margin (where the panel border starts)
            this.panelTopMargin = this.MIN_TOP_MARGIN;
            // Block top margin = panel margin + inner offset + connection routing space
            this.calculatedTopMargin = this.panelTopMargin + this.BLOCK_INNER_OFFSET + topConnections * this.CONNECTION_ROUTE_SPACE;

            // Calculate canvas size based on panels
            // Panels nebeneinander, Hutschienen pro Panel untereinander
            var totalWidth = this.PANEL_PADDING;
            var maxPanelHeight = 0;

            this.panels.forEach(function(panel) {
                var panelCarriers = self.carriers.filter(function(c) { return c.panel_id == panel.id; });
                var maxTE = 12;
                panelCarriers.forEach(function(c) {
                    if ((c.total_te || 12) > maxTE) maxTE = c.total_te;
                });

                // Panel width includes: left margin for label (60px) + rail overhang (30px) + TE width + rail overhang (30px) + padding
                var panelWidth = 60 + 30 + maxTE * self.TE_WIDTH + 30 + self.PANEL_PADDING;
                // Panel height calculation:
                // - calculatedTopMargin: space for main busbars at top
                // - BLOCK_HEIGHT/2: half block above first rail
                // - (carriers-1) * RAIL_SPACING: spacing between rails
                // - BLOCK_HEIGHT/2: half block below last rail
                // - BOTTOM_MARGIN: margin at bottom
                // Simplified: calculatedTopMargin + BLOCK_HEIGHT + (carriers * RAIL_SPACING) + BOTTOM_MARGIN
                var carrierCount = Math.max(panelCarriers.length, 1);
                var panelHeight = self.calculatedTopMargin + self.BLOCK_HEIGHT + (carrierCount * self.RAIL_SPACING) + self.BOTTOM_MARGIN;

                panel._x = totalWidth;
                panel._width = panelWidth;
                panel._height = panelHeight;

                totalWidth += panelWidth + self.PANEL_GAP;
                if (panelHeight > maxPanelHeight) maxPanelHeight = panelHeight;
            });

            totalWidth = Math.max(totalWidth, 400);
            var totalHeight = Math.max(maxPanelHeight, 300);

            // Fallback: wenn keine Panels, basierend auf Carriers
            if (this.panels.length === 0 && this.carriers.length > 0) {
                var fallbackMaxTE = 12;
                this.carriers.forEach(function(c) {
                    if ((c.total_te || 12) > fallbackMaxTE) fallbackMaxTE = c.total_te;
                });
                totalWidth = fallbackMaxTE * self.TE_WIDTH + 150;
                totalHeight = self.calculatedTopMargin + self.BLOCK_HEIGHT + (this.carriers.length * self.RAIL_SPACING) + self.BOTTOM_MARGIN;
            }

            this.layoutWidth = Math.max(totalWidth, 800);
            this.layoutHeight = Math.max(totalHeight, 400);
        },

        initCanvas: function() {
            var $canvas = $('.schematic-editor-canvas');

            if (!$canvas.length) {
                return;
            }

            // Loading message
            $canvas.html('<div style="padding:20px;color:#888;">Initialisiere Schaltplan-Editor...</div>');

            // Calculate layout first
            this.calculateLayout();

            // Create SVG using calculated dimensions
            var svg = '<svg class="schematic-svg" width="' + this.layoutWidth + '" height="' + this.layoutHeight + '" xmlns="http://www.w3.org/2000/svg">';

            // Defs for markers and patterns
            svg += '<defs>';
            svg += '<pattern id="grid" width="' + this.GRID_SIZE + '" height="' + this.GRID_SIZE + '" patternUnits="userSpaceOnUse">';
            svg += '<path d="M ' + this.GRID_SIZE + ' 0 L 0 0 0 ' + this.GRID_SIZE + '" fill="none" stroke="' + this.COLORS.grid + '" stroke-width="0.5"/>';
            svg += '</pattern>';
            svg += '<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0, 10 3.5, 0 7" fill="#888"/></marker>';
            svg += '</defs>';

            // Background grid
            svg += '<rect width="100%" height="100%" fill="url(#grid)"/>';

            // Layers (order matters: back to front)
            svg += '<g class="schematic-rails-layer"></g>';
            svg += '<g class="schematic-blocks-layer"></g>';
            svg += '<g class="schematic-busbars-layer"></g>';      // Distribution busbars (Phasenschienen)
            svg += '<g class="schematic-connections-layer"></g>';
            svg += '<g class="schematic-terminals-layer"></g>';

            // Connection preview line
            svg += '<line class="schematic-connection-preview" x1="0" y1="0" x2="0" y2="0" stroke="#3498db" stroke-width="2" stroke-dasharray="5,5" style="display:none;"/>';

            svg += '</svg>';

            // Wrap SVG in zoom wrapper for coordinated scaling with controls
            $canvas.html('<div class="schematic-zoom-wrapper" style="transform-origin:0 0;position:relative;">' + svg + '</div>');
            this.svgElement = $canvas.find('.schematic-svg')[0];
            this.isInitialized = true;

            // Render content
            this.render();

        },

        render: function() {
            if (!this.isInitialized) return;

            // Recalculate layout (panels may have changed)
            this.calculateLayout();

            // Update SVG size
            var $svg = $(this.svgElement);
            $svg.attr('width', this.layoutWidth);
            $svg.attr('height', this.layoutHeight);

            this.renderRails();
            this.renderBlocks();
            this.renderBridges();
            this.renderBusbars();
            this.renderConnections();
            this.renderControls();
        },

        renderRails: function() {
            var self = this;
            var $layer = $(this.svgElement).find('.schematic-rails-layer');
            $layer.empty();

            var html = '';

            // Render by panels (nebeneinander)
            if (this.panels.length > 0) {
                this.panels.forEach(function(panel) {
                    var panelX = panel._x || self.PANEL_PADDING;
                    var panelCarriers = self.carriers.filter(function(c) { return c.panel_id == panel.id; });

                    // Panel background - starts at panel top margin (before block offset)
                    if (panel._width && panel._height) {
                        var panelTop = self.panelTopMargin;
                        var panelContentHeight = panel._height - self.panelTopMargin;

                        html += '<rect class="schematic-panel-bg" x="' + (panelX - 14) + '" y="' + (panelTop - 14) + '" ';
                        html += 'width="' + (panel._width + 28) + '" height="' + (panelContentHeight + 28) + '" ';
                        html += 'fill="' + self.COLORS.panelBg + '" stroke="' + self.COLORS.panelBorder + '" stroke-width="1.5" rx="6"/>';

                        // Panel label
                        html += '<text x="' + (panelX + panel._width / 2) + '" y="' + (panelTop - 28) + '" ';
                        html += 'text-anchor="middle" fill="#aaa" font-size="17" font-weight="bold">';
                        html += self.escapeHtml(panel.label || 'Feld');
                        html += '</text>';
                    }

                    // Carriers untereinander im Panel
                    // Layout: [LEFT_MARGIN for label+overhang] [TE slots] [RIGHT overhang+padding]
                    panelCarriers.forEach(function(carrier, carrierIdx) {
                        // Hutschiene is centered, blocks are centered on the Hutschiene
                        // Calculate rail position: TOP_MARGIN + half block height + carrier spacing
                        var railY = self.calculatedTopMargin + (self.BLOCK_HEIGHT / 2) + carrierIdx * self.RAIL_SPACING;
                        var width = (carrier.total_te || 12) * self.TE_WIDTH;
                        // x position: panelX + left margin (60px for label) + overhang (30px)
                        var x = panelX + 60 + 30;

                        // Store carrier position (rail Y position)
                        carrier._y = railY;
                        carrier._x = x;

                        // Rail overhang on both sides for label visibility
                        var railOverhang = 30;

                        // Rail background - Hutschiene (mit Überstand links und rechts)
                        html += '<rect class="schematic-rail-bg" x="' + (x - railOverhang) + '" y="' + railY + '" width="' + (width + railOverhang * 2) + '" height="' + self.RAIL_HEIGHT + '" ';
                        html += 'fill="' + self.COLORS.railBg + '" rx="2"/>';

                        // Rail (mit Überstand links und rechts) - klickbar für Bearbeitung
                        html += '<rect class="schematic-rail" data-carrier-id="' + carrier.id + '" x="' + (x - railOverhang) + '" y="' + (railY + 1) + '" width="' + (width + railOverhang * 2) + '" height="' + (self.RAIL_HEIGHT - 2) + '" ';
                        html += 'fill="' + self.COLORS.rail + '" rx="1" style="cursor:pointer;"/>';

                        // Rail label (links vom Überstand, centered with rail)
                        html += '<text x="' + (x - railOverhang - 7) + '" y="' + (railY + self.RAIL_HEIGHT / 2 + 4) + '" text-anchor="end" fill="#888" font-size="13">';
                        html += self.escapeHtml(carrier.label || 'H' + (carrierIdx + 1));
                        html += '</text>';

                        // TE markers on the rail
                        for (var te = 0; te <= (carrier.total_te || 12); te++) {
                            var teX = x + te * self.TE_WIDTH;
                            html += '<line x1="' + teX + '" y1="' + railY + '" x2="' + teX + '" y2="' + (railY + self.RAIL_HEIGHT) + '" stroke="#555" stroke-width="0.5"/>';
                        }
                    });
                });
            } else {
                // Fallback: Carriers ohne Panels
                this.carriers.forEach(function(carrier, idx) {
                    var blockTop = self.calculatedTopMargin + idx * self.RAIL_SPACING;
                    var railY = blockTop + self.BLOCK_HEIGHT + 10;
                    var width = (carrier.total_te || 12) * self.TE_WIDTH;
                    var x = self.PANEL_PADDING + 50;

                    carrier._y = railY;
                    carrier._x = x;
                    carrier._blockTop = blockTop;

                    // Rail overhang on both sides
                    var railOverhang = 30;

                    html += '<rect class="schematic-rail-bg" x="' + (x - railOverhang) + '" y="' + railY + '" width="' + (width + railOverhang * 2) + '" height="' + self.RAIL_HEIGHT + '" ';
                    html += 'fill="' + self.COLORS.railBg + '" rx="2"/>';

                    html += '<rect class="schematic-rail" data-carrier-id="' + carrier.id + '" x="' + (x - railOverhang) + '" y="' + (railY + 1) + '" width="' + (width + railOverhang * 2) + '" height="' + (self.RAIL_HEIGHT - 2) + '" ';
                    html += 'fill="' + self.COLORS.rail + '" rx="1" style="cursor:pointer;"/>';

                    html += '<text x="' + (x - railOverhang - 14) + '" y="' + (railY + self.RAIL_HEIGHT / 2 + 4) + '" text-anchor="end" fill="#888" font-size="15">';
                    html += self.escapeHtml(carrier.label || 'Hutschiene ' + (idx + 1));
                    html += '</text>';

                    for (var te = 0; te <= (carrier.total_te || 12); te++) {
                        var teX = x + te * self.TE_WIDTH;
                        html += '<line x1="' + teX + '" y1="' + railY + '" x2="' + teX + '" y2="' + (railY + self.RAIL_HEIGHT) + '" stroke="#555" stroke-width="0.5"/>';
                    }
                });
            }

            $layer.html(html);
        },

        renderBlocks: function() {
            var self = this;
            var $layer = $(this.svgElement).find('.schematic-blocks-layer');
            var $terminalLayer = $(this.svgElement).find('.schematic-terminals-layer');
            $layer.empty();
            $terminalLayer.empty();

            var blockHtml = '';
            var terminalHtml = '';

            this.equipment.forEach(function(eq) {
                var carrier = self.carriers.find(function(c) { return String(c.id) === String(eq.carrier_id); });
                if (!carrier) {
                    return;
                }
                if (typeof carrier._x === 'undefined' || carrier._x === null) {
                    console.log('  Equipment #' + eq.id + ' (' + eq.label + '): Carrier has no _x position set, skipping');
                    return;
                }

                var blockWidth = (eq.width_te || 1) * self.TE_WIDTH - 4;
                var blockHeight = self.BLOCK_HEIGHT;
                var x = parseFloat(carrier._x) + ((parseInt(eq.position_te) || 1) - 1) * self.TE_WIDTH + 2;
                // Position blocks centered on the rail (Hutschiene)
                // Rail is at carrier._y, block center should align with rail center
                var railCenterY = carrier._y + self.RAIL_HEIGHT / 2;
                var y = railCenterY - blockHeight / 2;

                // Store position
                eq._x = x;
                eq._y = y;
                eq._width = blockWidth;
                eq._height = blockHeight;

                var color = eq.block_color || eq.type_color || self.COLORS.block;

                // Block group
                blockHtml += '<g class="schematic-block" data-equipment-id="' + eq.id + '" data-carrier-id="' + carrier.id + '" transform="translate(' + x + ',' + y + ')">';

                // Check if we have a block image
                var hasBlockImage = eq.type_block_image && eq.type_block_image_url;

                if (hasBlockImage) {
                    // Render image instead of colored rectangle
                    // Use xMidYMid slice to fill the block and crop if needed
                    blockHtml += '<image class="schematic-block-image" href="' + eq.type_block_image_url + '" ';
                    blockHtml += 'x="0" y="0" width="' + blockWidth + '" height="' + blockHeight + '" preserveAspectRatio="xMidYMid slice"/>';
                    // Border around the image block
                    blockHtml += '<rect class="schematic-block-bg" width="' + blockWidth + '" height="' + blockHeight + '" ';
                    blockHtml += 'fill="none" stroke="#333" stroke-width="1" rx="2"/>';
                } else {
                    // Block background with gradient (original behavior)
                    blockHtml += '<rect class="schematic-block-bg" width="' + blockWidth + '" height="' + blockHeight + '" ';
                    blockHtml += 'fill="' + color + '" stroke="#222" stroke-width="1.5" rx="4"/>';

                    // Label - zentriert im Block
                    var labelY = blockHeight / 2;
                    blockHtml += '<text x="' + (blockWidth / 2) + '" y="' + (labelY - 7) + '" text-anchor="middle" fill="#fff" font-size="14" font-weight="bold">';
                    blockHtml += self.escapeHtml(eq.type_label_short || eq.label || '');
                    blockHtml += '</text>';

                    // Additional info line
                    if (eq.label && eq.type_label_short) {
                        blockHtml += '<text x="' + (blockWidth / 2) + '" y="' + (labelY + 11) + '" text-anchor="middle" fill="rgba(255,255,255,0.7)" font-size="11">';
                        blockHtml += self.escapeHtml(eq.label);
                        blockHtml += '</text>';
                    }

                    // Richtungspfeile (flow_direction)
                    var flowDir = eq.type_flow_direction;
                    if (flowDir) {
                        var arrowX = blockWidth - 12;
                        var arrowY1, arrowY2, arrowY3;
                        if (flowDir === 'top_to_bottom') {
                            // Pfeil nach unten ↓
                            arrowY1 = 10;
                            arrowY2 = blockHeight - 10;
                            blockHtml += '<line x1="' + arrowX + '" y1="' + arrowY1 + '" x2="' + arrowX + '" y2="' + arrowY2 + '" stroke="rgba(255,255,255,0.6)" stroke-width="2"/>';
                            blockHtml += '<polygon points="' + (arrowX - 5) + ',' + (arrowY2 - 8) + ' ' + arrowX + ',' + arrowY2 + ' ' + (arrowX + 5) + ',' + (arrowY2 - 8) + '" fill="rgba(255,255,255,0.6)"/>';
                        } else if (flowDir === 'bottom_to_top') {
                            // Pfeil nach oben ↑
                            arrowY1 = blockHeight - 10;
                            arrowY2 = 10;
                            blockHtml += '<line x1="' + arrowX + '" y1="' + arrowY1 + '" x2="' + arrowX + '" y2="' + arrowY2 + '" stroke="rgba(255,255,255,0.6)" stroke-width="2"/>';
                            blockHtml += '<polygon points="' + (arrowX - 5) + ',' + (arrowY2 + 8) + ' ' + arrowX + ',' + arrowY2 + ' ' + (arrowX + 5) + ',' + (arrowY2 + 8) + '" fill="rgba(255,255,255,0.6)"/>';
                        }
                    }
                }

                blockHtml += '</g>';

                // Terminals (bidirectional)
                // WICHTIG: Terminals werden im festen TE-Raster platziert
                // Jeder Terminal nimmt 1 TE ein - ein 3TE Block mit 3 Terminals
                // sieht genauso aus wie 3 einzelne 1TE Blöcke
                var terminals = self.getTerminals(eq);
                var topTerminals = terminals.filter(function(t) { return t.pos === 'top'; });
                var bottomTerminals = terminals.filter(function(t) { return t.pos === 'bottom'; });

                var widthTE = parseInt(eq.width_te) || 1;

                // Check if this equipment is covered by a busbar (returns { top: bool, bottom: bool })
                var busbarCoverage = self.isEquipmentCoveredByBusbar(eq);

                // Terminal-Position aus Equipment-Typ (both, top_only, bottom_only)
                var terminalPos = eq.type_terminal_position || 'both';
                var showTopTerminals = (terminalPos === 'both' || terminalPos === 'top_only') && !busbarCoverage.top;
                var showBottomTerminals = (terminalPos === 'both' || terminalPos === 'bottom_only') && !busbarCoverage.bottom;

                // Top terminals - im TE-Raster platziert (hide if busbar covers this equipment or terminal_position)
                // Now supports stacked terminals with 'row' property (for Reihenklemmen)
                var terminalColor = '#666'; // Grau wie die Hutschienen
                var terminalSpacing = 14; // Vertical spacing between stacked terminals

                if (showTopTerminals) {
                    // Group terminals by column (teIndex) for stacking
                    var topTerminalsByCol = {};
                    topTerminals.forEach(function(term, idx) {
                        var teIndex = term.col !== undefined ? term.col : (idx % widthTE);
                        if (!topTerminalsByCol[teIndex]) topTerminalsByCol[teIndex] = [];
                        topTerminalsByCol[teIndex].push(term);
                    });

                    Object.keys(topTerminalsByCol).forEach(function(colKey) {
                        var colTerminals = topTerminalsByCol[colKey];
                        var teIndex = parseInt(colKey);
                        var tx = x + (teIndex * self.TE_WIDTH) + (self.TE_WIDTH / 2);

                        colTerminals.forEach(function(term, rowIdx) {
                            var row = term.row !== undefined ? term.row : rowIdx;
                            var ty = y - 7 - (row * terminalSpacing);

                            terminalHtml += '<g class="schematic-terminal" ';
                            terminalHtml += 'data-equipment-id="' + eq.id + '" data-terminal-id="' + term.id + '" ';
                            terminalHtml += 'transform="translate(' + tx + ',' + ty + ')">';

                            terminalHtml += '<circle r="' + self.TERMINAL_RADIUS + '" fill="' + terminalColor + '" stroke="#fff" stroke-width="2" class="schematic-terminal-circle"/>';

                            // Label - position depends on whether there are stacked terminals
                            var labelText = self.escapeHtml(term.label);
                            var labelWidth = labelText.length * 6 + 6;

                            if (colTerminals.length > 1) {
                                // Stacked: place label to the left of the terminal
                                terminalHtml += '<rect x="' + (-labelWidth - 8) + '" y="-7" width="' + labelWidth + '" height="14" rx="3" fill="rgba(0,0,0,0.85)"/>';
                                terminalHtml += '<text x="' + (-labelWidth/2 - 8) + '" y="3" text-anchor="middle" fill="#fff" font-size="9" font-weight="bold">' + labelText + '</text>';
                            } else {
                                // Single: place label below in block
                                terminalHtml += '<rect x="' + (-labelWidth/2) + '" y="14" width="' + labelWidth + '" height="14" rx="3" fill="rgba(0,0,0,0.85)"/>';
                                terminalHtml += '<text y="24" text-anchor="middle" fill="#fff" font-size="10" font-weight="bold">' + labelText + '</text>';
                            }
                            terminalHtml += '</g>';
                        });
                    });
                }

                // Bottom terminals - im TE-Raster platziert (hide if busbar covers bottom)
                // Now supports stacked terminals with 'row' property
                if (showBottomTerminals) {
                    // Group terminals by column (teIndex) for stacking
                    var bottomTerminalsByCol = {};
                    bottomTerminals.forEach(function(term, idx) {
                        var teIndex = term.col !== undefined ? term.col : (idx % widthTE);
                        if (!bottomTerminalsByCol[teIndex]) bottomTerminalsByCol[teIndex] = [];
                        bottomTerminalsByCol[teIndex].push(term);
                    });

                    Object.keys(bottomTerminalsByCol).forEach(function(colKey) {
                        var colTerminals = bottomTerminalsByCol[colKey];
                        var teIndex = parseInt(colKey);
                        var tx = x + (teIndex * self.TE_WIDTH) + (self.TE_WIDTH / 2);

                        colTerminals.forEach(function(term, rowIdx) {
                            var row = term.row !== undefined ? term.row : rowIdx;
                            var ty = y + blockHeight + 7 + (row * terminalSpacing);

                            terminalHtml += '<g class="schematic-terminal" ';
                            terminalHtml += 'data-equipment-id="' + eq.id + '" data-terminal-id="' + term.id + '" ';
                            terminalHtml += 'transform="translate(' + tx + ',' + ty + ')">';

                            terminalHtml += '<circle r="' + self.TERMINAL_RADIUS + '" fill="' + terminalColor + '" stroke="#fff" stroke-width="2" class="schematic-terminal-circle"/>';

                            // Label - position depends on whether there are stacked terminals
                            var labelText = self.escapeHtml(term.label);
                            var labelWidth = labelText.length * 6 + 6;

                            if (colTerminals.length > 1) {
                                // Stacked: place label to the right of the terminal
                                terminalHtml += '<rect x="8" y="-7" width="' + labelWidth + '" height="14" rx="3" fill="rgba(0,0,0,0.85)"/>';
                                terminalHtml += '<text x="' + (8 + labelWidth/2) + '" y="3" text-anchor="middle" fill="#fff" font-size="9" font-weight="bold">' + labelText + '</text>';
                            } else {
                                // Single: place label above in block
                                terminalHtml += '<rect x="' + (-labelWidth/2) + '" y="-25" width="' + labelWidth + '" height="14" rx="3" fill="rgba(0,0,0,0.85)"/>';
                                terminalHtml += '<text y="-15" text-anchor="middle" fill="#fff" font-size="10" font-weight="bold">' + labelText + '</text>';
                            }
                            terminalHtml += '</g>';
                        });
                    });
                }
            });

            $layer.html(blockHtml);
            $terminalLayer.html(terminalHtml);
        },

        renderBridges: function() {
            // Render terminal bridges (Brücken zwischen Reihenklemmen)
            var self = this;

            // Create or get bridge layer (between terminals and busbars)
            var $bridgeLayer = $(this.svgElement).find('.schematic-bridges-layer');
            if ($bridgeLayer.length === 0) {
                // Insert after terminals layer
                var $terminalLayer = $(this.svgElement).find('.schematic-terminals-layer');
                $terminalLayer.after('<g class="schematic-bridges-layer"></g>');
                $bridgeLayer = $(this.svgElement).find('.schematic-bridges-layer');
            }
            $bridgeLayer.empty();

            if (!this.bridges || this.bridges.length === 0) {
                return;
            }

            var html = '';

            this.bridges.forEach(function(bridge) {
                // Find carrier for this bridge
                var carrier = self.carriers.find(function(c) {
                    return String(c.id) === String(bridge.fk_carrier);
                });

                if (!carrier || typeof carrier._x === 'undefined') {
                    return;
                }

                // Calculate bridge positions
                var startTE = parseInt(bridge.start_te) || 1;
                var endTE = parseInt(bridge.end_te) || startTE;
                var terminalSide = bridge.terminal_side || 'top';
                var terminalRow = parseInt(bridge.terminal_row) || 0;
                var color = bridge.color || '#e74c3c';

                // X positions for bridge endpoints (center of each TE)
                var x1 = carrier._x + (startTE - 1) * self.TE_WIDTH + self.TE_WIDTH / 2;
                var x2 = carrier._x + (endTE - 1) * self.TE_WIDTH + self.TE_WIDTH / 2;

                // Y position based on carrier and terminal side
                var railY = carrier._y;
                var blockTop = railY + self.RAIL_HEIGHT / 2 - self.BLOCK_HEIGHT / 2;
                var blockBottom = blockTop + self.BLOCK_HEIGHT;

                var terminalSpacing = 14;
                var y;

                if (terminalSide === 'top') {
                    // Bridge above block, at terminal level
                    y = blockTop - 7 - (terminalRow * terminalSpacing);
                } else {
                    // Bridge below block, at terminal level
                    y = blockBottom + 7 + (terminalRow * terminalSpacing);
                }

                // Bridge is a horizontal bar connecting terminals
                var bridgeHeight = 6;

                html += '<g class="schematic-bridge" data-bridge-id="' + bridge.id + '" data-carrier-id="' + carrier.id + '">';

                // Bridge bar (horizontal rectangle)
                html += '<rect x="' + x1 + '" y="' + (y - bridgeHeight/2) + '" ';
                html += 'width="' + (x2 - x1) + '" height="' + bridgeHeight + '" ';
                html += 'fill="' + color + '" stroke="#333" stroke-width="1" rx="2" ';
                html += 'style="cursor:pointer;" class="schematic-bridge-bar"/>';

                // Connection points at each end
                html += '<circle cx="' + x1 + '" cy="' + y + '" r="4" fill="' + color + '" stroke="#333" stroke-width="1"/>';
                html += '<circle cx="' + x2 + '" cy="' + y + '" r="4" fill="' + color + '" stroke="#333" stroke-width="1"/>';

                // Optional label
                if (bridge.label) {
                    var labelX = (x1 + x2) / 2;
                    html += '<text x="' + labelX + '" y="' + (y - bridgeHeight/2 - 3) + '" ';
                    html += 'text-anchor="middle" fill="#333" font-size="9" font-weight="bold">';
                    html += self.escapeHtml(bridge.label);
                    html += '</text>';
                }

                html += '</g>';
            });

            $bridgeLayer.html(html);
        },

        renderBusbars: function() {
            // Render Sammelschienen (busbars) - connections with is_rail=1
            var self = this;
            var $layer = $(this.svgElement).find('.schematic-busbars-layer');
            $layer.empty();

            var html = '';
            var renderedCount = 0;

            // First, group busbars by carrier and position for stacking
            var busbarsByCarrierAndPos = {};
            this.connections.forEach(function(conn) {
                if (parseInt(conn.is_rail) !== 1) return;
                var key = conn.fk_carrier + '_' + (parseInt(conn.position_y) || 0);
                if (!busbarsByCarrierAndPos[key]) busbarsByCarrierAndPos[key] = [];
                busbarsByCarrierAndPos[key].push(conn);
            });

            this.connections.forEach(function(conn) {
                // Only process rails/busbars
                if (parseInt(conn.is_rail) !== 1) {
                    return;
                }

                // Get carrier for this busbar
                var carrier = self.carriers.find(function(c) {
                    return String(c.id) === String(conn.fk_carrier);
                });

                if (!carrier || typeof carrier._x === 'undefined') {
                    console.log('  Busbar #' + conn.id + ': No carrier found or carrier has no position');
                    return;
                }

                // Busbar spans from rail_start_te to rail_end_te
                var startTE = parseInt(conn.rail_start_te) || 1;
                var endTE = parseInt(conn.rail_end_te) || startTE + 1;

                // Calculate pixel positions
                var startX = carrier._x + (startTE - 1) * self.TE_WIDTH;
                var endX = carrier._x + endTE * self.TE_WIDTH;
                var width = endX - startX;

                // Position busbar above or below the blocks based on position_y
                // position_y: 0 = above (top), 1 = below (bottom)
                var posY = parseInt(conn.position_y) || 0;
                var railCenterY = carrier._y + self.RAIL_HEIGHT / 2;
                var blockTop = railCenterY - self.BLOCK_HEIGHT / 2;
                var blockBottom = railCenterY + self.BLOCK_HEIGHT / 2;

                // Count how many busbars are already at this position (to stack them)
                var key = conn.fk_carrier + '_' + posY;
                var carrierBusbars = busbarsByCarrierAndPos[key] || [];
                var busbarIndex = carrierBusbars.indexOf(conn);
                if (busbarIndex < 0) busbarIndex = 0;

                // Busbar height and position - stack multiple busbars
                var busbarHeight = 24;
                var busbarSpacing = busbarHeight + 20; // Space between stacked busbars (including label space)
                var busbarY;
                if (posY === 0) {
                    // Above blocks - stack upwards
                    busbarY = blockTop - busbarHeight - 25 - (busbarIndex * busbarSpacing);
                } else {
                    // Below blocks - stack downwards
                    busbarY = blockBottom + 25 + (busbarIndex * busbarSpacing);
                }

                // Color from connection or default phase color
                var color = conn.color || self.PHASE_COLORS[conn.connection_type] || '#e74c3c';

                // Draw busbar as rounded rectangle
                html += '<g class="schematic-busbar" data-connection-id="' + conn.id + '">';

                // Shadow
                html += '<rect x="' + startX + '" y="' + (busbarY + 2) + '" ';
                html += 'width="' + width + '" height="' + busbarHeight + '" ';
                html += 'rx="2" fill="rgba(0,0,0,0.3)"/>';

                // Main bar
                html += '<rect x="' + startX + '" y="' + busbarY + '" ';
                html += 'width="' + width + '" height="' + busbarHeight + '" ';
                html += 'rx="2" fill="' + color + '" stroke="#222" stroke-width="1" style="cursor:pointer;"/>';

                // Parse excluded TEs
                var excludedTEs = [];
                if (conn.excluded_te) {
                    excludedTEs = conn.excluded_te.split(',').map(function(t) { return parseInt(t.trim()); }).filter(function(t) { return !isNaN(t); });
                }

                // Determine phase labels based on rail_phases
                var phases = conn.rail_phases || conn.connection_type || '';
                var phaseLabels = [];
                if (phases === 'L1L2L3') {
                    phaseLabels = ['L1', 'L2', 'L3'];
                } else if (phases === 'L1') {
                    phaseLabels = ['L1'];
                } else if (phases === 'L2') {
                    phaseLabels = ['L2'];
                } else if (phases === 'L3') {
                    phaseLabels = ['L3'];
                } else if (phases === 'N') {
                    phaseLabels = ['N'];
                } else if (phases === 'PE') {
                    phaseLabels = ['PE'];
                } else if (phases) {
                    phaseLabels = [phases];
                }

                // Draw taps per TE (not per block) - each TE gets its own connection point
                // Phase index counts ALL TEs from start (including excluded ones) for correct phase assignment
                for (var te = startTE; te <= endTE; te++) {
                    // Calculate phase for this TE position (based on position from start, not rendered count)
                    var teOffset = te - startTE; // 0-based offset from start
                    var currentPhase = phaseLabels.length > 0 ? phaseLabels[teOffset % phaseLabels.length] : '';

                    // Skip excluded TEs (but phase still counts)
                    if (excludedTEs.indexOf(te) !== -1) continue;

                    // Calculate X position for this TE - center of the TE slot
                    // TE 1 starts at carrier._x, so center of TE 1 is at carrier._x + TE_WIDTH/2
                    // TE n center is at carrier._x + (n-1) * TE_WIDTH + TE_WIDTH/2
                    var teX = carrier._x + (te - 1) * self.TE_WIDTH + self.TE_WIDTH / 2;

                    // Draw tap line from busbar to block/terminal area
                    var tapStartY = posY === 0 ? busbarY + busbarHeight : busbarY;
                    var tapEndY;
                    if (posY === 0) {
                        tapEndY = blockTop - 7;
                    } else {
                        tapEndY = blockBottom + 7;
                    }

                    html += '<line x1="' + teX + '" y1="' + tapStartY + '" ';
                    html += 'x2="' + teX + '" y2="' + tapEndY + '" ';
                    html += 'stroke="' + color + '" stroke-width="2" stroke-linecap="round"/>';

                    // Connector dot at equipment end - same size as block terminals
                    html += '<circle cx="' + teX + '" cy="' + tapEndY + '" r="' + self.TERMINAL_RADIUS + '" ';
                    html += 'fill="' + color + '" stroke="#fff" stroke-width="2"/>';

                    // Phase label at this TE connection
                    if (currentPhase) {
                        // Position label on the busbar
                        var phaseLabelY = busbarY + busbarHeight / 2 + 4;
                        html += '<text x="' + teX + '" y="' + phaseLabelY + '" ';
                        html += 'text-anchor="middle" fill="#fff" font-size="9" font-weight="bold">';
                        html += self.escapeHtml(currentPhase);
                        html += '</text>';
                    }
                }

                // Main phase label in the CENTER of the busbar
                if (phases) {
                    var labelX = startX + width / 2;
                    var labelY = busbarY + busbarHeight / 2 + 4;
                    html += '<text class="busbar-label" x="' + labelX + '" y="' + labelY + '" ';
                    html += 'data-label-x="' + labelX + '" data-label-width="' + (phases.length * 8) + '" data-label-y="' + busbarY + '" ';
                    html += 'text-anchor="middle" fill="#fff" font-size="11" font-weight="bold">';
                    html += self.escapeHtml(phases);
                    html += '</text>';
                }

                html += '</g>';
                renderedCount++;
                console.log('  Busbar #' + conn.id + ': Rendered from TE ' + startTE + ' to ' + endTE + ' on carrier ' + carrier.id +
                    ', x=' + startX + ', y=' + busbarY + ', width=' + width + ', color=' + color);
            });

            $layer.html(html);
        },

        renderConnections: function() {
            var self = this;
            var $layer = $(this.svgElement).find('.schematic-connections-layer');
            $layer.empty();

            var html = '';
            var renderedCount = 0;

            this.connections.forEach(function(conn, connIndex) {
                // Check is_rail as integer (PHP may return string "1" or "0")
                if (parseInt(conn.is_rail) === 1) {
                    return;
                }

                var sourceEq = conn.fk_source ? self.equipment.find(function(e) { return String(e.id) === String(conn.fk_source); }) : null;
                var targetEq = conn.fk_target ? self.equipment.find(function(e) { return String(e.id) === String(conn.fk_target); }) : null;

                var color = conn.color || self.PHASE_COLORS[conn.connection_type] || self.COLORS.connection;

                // ========================================
                // ABGANG (Output) - source exists, no target
                // Direction depends on terminal: top terminal = line goes UP, bottom terminal = line goes DOWN
                // ========================================
                if (sourceEq && !conn.fk_target) {
                    var sourceTerminals = self.getTerminals(sourceEq);
                    var sourceTermId = conn.source_terminal_id || 't2';
                    var sourcePos = self.getTerminalPosition(sourceEq, sourceTermId, sourceTerminals);

                    if (!sourcePos) {
                        // Fallback: center bottom of equipment
                        sourcePos = {
                            x: sourceEq._x + (sourceEq._width || sourceEq.width_te * self.TE_WIDTH) / 2,
                            y: sourceEq._y + (sourceEq._height || 60) + 5,
                            isTop: false
                        };
                    }

                    // Calculate line length based on label text
                    var labelText = conn.output_label || '';
                    var cableText = (conn.medium_type || '') + ' ' + (conn.medium_spec || '');
                    var maxTextLen = Math.max(labelText.length, cableText.trim().length);
                    var lineLength = Math.min(120, Math.max(50, maxTextLen * 6 + 20));

                    // Direction: top terminal = UP, bottom terminal = DOWN
                    var goingUp = sourcePos.isTop;
                    var startY = sourcePos.y;
                    var endY = goingUp ? (startY - lineLength) : (startY + lineLength);

                    // Draw vertical line
                    var path = 'M ' + sourcePos.x + ' ' + startY + ' L ' + sourcePos.x + ' ' + endY;

                    html += '<g class="schematic-output-group" data-connection-id="' + conn.id + '" style="cursor:pointer;">';

                    // Invisible hit area for clicking
                    var hitY = goingUp ? endY : startY;
                    html += '<rect x="' + (sourcePos.x - 20) + '" y="' + hitY + '" width="40" height="' + lineLength + '" fill="transparent"/>';

                    // Connection line
                    html += '<path class="schematic-connection" data-connection-id="' + conn.id + '" d="' + path + '" ';
                    html += 'fill="none" stroke="' + color + '" stroke-width="3" stroke-linecap="round"/>';

                    // Arrow at end (pointing away from equipment)
                    if (goingUp) {
                        // Arrow pointing UP
                        html += '<polygon points="' + (sourcePos.x - 5) + ',' + (endY + 6) + ' ' + sourcePos.x + ',' + endY + ' ' + (sourcePos.x + 5) + ',' + (endY + 6) + '" fill="' + color + '"/>';
                    } else {
                        // Arrow pointing DOWN
                        html += '<polygon points="' + (sourcePos.x - 5) + ',' + (endY - 6) + ' ' + sourcePos.x + ',' + endY + ' ' + (sourcePos.x + 5) + ',' + (endY - 6) + '" fill="' + color + '"/>';
                    }

                    // Labels - vertical text on both sides
                    var labelY = (startY + endY) / 2;

                    // Left side: Bezeichnung (output_label)
                    if (conn.output_label) {
                        html += '<text x="' + (sourcePos.x - 10) + '" y="' + labelY + '" ';
                        html += 'text-anchor="middle" fill="#fff" font-size="11" font-weight="bold" ';
                        html += 'transform="rotate(-90 ' + (sourcePos.x - 10) + ' ' + labelY + ')">';
                        html += self.escapeHtml(conn.output_label);
                        html += '</text>';
                    }

                    // Right side: Kabeltyp + Größe
                    var cableInfo = '';
                    if (conn.medium_type) cableInfo = conn.medium_type;
                    if (conn.medium_spec) cableInfo += ' ' + conn.medium_spec;
                    if (cableInfo) {
                        html += '<text x="' + (sourcePos.x + 10) + '" y="' + labelY + '" ';
                        html += 'text-anchor="middle" fill="#888" font-size="10" ';
                        html += 'transform="rotate(-90 ' + (sourcePos.x + 10) + ' ' + labelY + ')">';
                        html += self.escapeHtml(cableInfo.trim());
                        html += '</text>';
                    }

                    // Phase type at end of line
                    if (conn.connection_type) {
                        var phaseY = goingUp ? (endY - 10) : (endY + 14);
                        html += '<text x="' + sourcePos.x + '" y="' + phaseY + '" ';
                        html += 'text-anchor="middle" fill="' + color + '" font-size="11" font-weight="bold">';
                        html += conn.connection_type;
                        html += '</text>';
                    }

                    html += '</g>';
                    renderedCount++;
                    return;
                }

                // ========================================
                // ANSCHLUSSPUNKT (Input) - no source, target exists
                // Draw a line coming FROM ABOVE into the terminal
                // All Anschlusspunkte use a uniform color (light blue)
                // ========================================
                if (!conn.fk_source && targetEq) {
                    var targetTerminals = self.getTerminals(targetEq);
                    var targetTermId = conn.target_terminal_id || 't1';
                    var targetPos = self.getTerminalPosition(targetEq, targetTermId, targetTerminals);
                    if (!targetPos) return;

                    // Uniform color for all Anschlusspunkte (inputs)
                    var inputColor = '#4fc3f7'; // Light blue - uniform for all inputs

                    // Calculate line length based on label
                    var inputLabel = conn.output_label || '';
                    var inputLineLength = Math.min(80, Math.max(45, inputLabel.length * 5 + 30));
                    var startY = targetPos.y - inputLineLength;

                    // Draw vertical line coming down into terminal
                    var path = 'M ' + targetPos.x + ' ' + startY + ' L ' + targetPos.x + ' ' + targetPos.y;

                    html += '<g class="schematic-input-group" data-connection-id="' + conn.id + '" style="cursor:pointer;">';

                    // Invisible hit area for clicking
                    html += '<rect x="' + (targetPos.x - 20) + '" y="' + startY + '" width="40" height="' + inputLineLength + '" fill="transparent"/>';

                    // Connection line
                    html += '<path class="schematic-connection" data-connection-id="' + conn.id + '" d="' + path + '" ';
                    html += 'fill="none" stroke="' + inputColor + '" stroke-width="3" stroke-linecap="round"/>';

                    // Circle at top (external source indicator)
                    html += '<circle cx="' + targetPos.x + '" cy="' + startY + '" r="6" fill="' + inputColor + '" stroke="#fff" stroke-width="2"/>';

                    // Arrow pointing down into terminal
                    html += '<polygon points="' + (targetPos.x - 5) + ',' + (targetPos.y - 8) + ' ' + targetPos.x + ',' + (targetPos.y - 2) + ' ' + (targetPos.x + 5) + ',' + (targetPos.y - 8) + '" fill="' + inputColor + '"/>';

                    // Phase label at top (big, prominent)
                    html += '<text x="' + targetPos.x + '" y="' + (startY - 10) + '" ';
                    html += 'text-anchor="middle" fill="' + inputColor + '" font-size="13" font-weight="bold">';
                    html += conn.connection_type || 'L1';
                    html += '</text>';

                    // Optional label on side (vertical)
                    if (conn.output_label) {
                        var labelY = targetPos.y - inputLineLength / 2;
                        html += '<text x="' + (targetPos.x + 10) + '" y="' + labelY + '" ';
                        html += 'text-anchor="middle" fill="#aaa" font-size="10" ';
                        html += 'transform="rotate(-90 ' + (targetPos.x + 10) + ' ' + labelY + ')">';
                        html += self.escapeHtml(conn.output_label);
                        html += '</text>';
                    }

                    html += '</g>';
                    renderedCount++;
                    return;
                }

                // ========================================
                // NORMAL CONNECTION - both source and target exist
                // ========================================
                if (!sourceEq || !targetEq) {
                    return;
                }

                var sourceTerminals = self.getTerminals(sourceEq);
                var targetTerminals = self.getTerminals(targetEq);

                var sourceTermId = conn.source_terminal_id || 't2';
                var targetTermId = conn.target_terminal_id || 't1';

                var sourcePos = self.getTerminalPosition(sourceEq, sourceTermId, sourceTerminals);
                var targetPos = self.getTerminalPosition(targetEq, targetTermId, targetTerminals);

                if (!sourcePos || !targetPos) return;

                var routeOffset = connIndex * 8;

                var path;
                if (conn.path_data) {
                    path = conn.path_data;
                } else {
                    path = self.createOrthogonalPath(sourcePos, targetPos, routeOffset, sourceEq, targetEq);
                }

                html += '<path class="schematic-connection-shadow" d="' + path + '" fill="none" stroke="rgba(0,0,0,0.4)" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>';

                html += '<g class="schematic-connection-group" data-connection-id="' + conn.id + '">';
                html += '<path class="schematic-connection-hitarea" d="' + path + '" ';
                html += 'fill="none" stroke="transparent" stroke-width="15" stroke-linecap="round" stroke-linejoin="round" style="cursor:pointer;"/>';

                html += '<path class="schematic-connection" data-connection-id="' + conn.id + '" d="' + path + '" ';
                html += 'fill="none" stroke="' + color + '" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" style="pointer-events:none;"/>';

                if (conn.output_label) {
                    var labelX = (sourcePos.x + targetPos.x) / 2;
                    var labelY = sourcePos.isTop ? sourcePos.y - 70 - routeOffset : sourcePos.y + 70 + routeOffset;

                    var labelWidth = Math.min(conn.output_label.length * 8 + 14, 112);
                    html += '<rect x="' + (labelX - labelWidth/2) + '" y="' + (labelY - 11) + '" width="' + labelWidth + '" height="20" rx="3" fill="#1e1e1e" opacity="0.95"/>';
                    html += '<text x="' + labelX + '" y="' + (labelY + 4) + '" text-anchor="middle" fill="' + color + '" font-size="13" font-weight="bold">';
                    html += self.escapeHtml(conn.output_label);
                    html += '</text>';
                }

                if (conn.connection_type && !conn.output_label) {
                    var typeX = (sourcePos.x + targetPos.x) / 2;
                    var typeY = (sourcePos.y + targetPos.y) / 2;
                    html += '<text x="' + typeX + '" y="' + typeY + '" text-anchor="middle" fill="' + color + '" font-size="11" font-weight="bold">';
                    html += conn.connection_type;
                    html += '</text>';
                }

                html += '</g>';
                renderedCount++;
            });

            $layer.html(html);

            // Bind click events to SVG connection elements (must be done after rendering)
            var self = this;

            // Normal connections
            $layer.find('.schematic-connection-group').each(function() {
                var $group = $(this);
                var connId = $group.data('connection-id');
                var $visiblePath = $group.find('.schematic-connection');

                this.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    if (connId) {
                        self.showConnectionPopup(connId, e.clientX, e.clientY);
                    }
                });

                this.addEventListener('mouseenter', function() {
                    $visiblePath.attr('stroke-width', '5');
                });
                this.addEventListener('mouseleave', function() {
                    $visiblePath.attr('stroke-width', '3.5');
                });
                this.style.cursor = 'pointer';
            });

            // Abgang (Output) groups - click to edit
            $layer.find('.schematic-output-group').each(function() {
                var $group = $(this);
                var connId = $group.data('connection-id');
                var $visiblePath = $group.find('.schematic-connection');

                this.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    if (connId) {
                        self.showConnectionPopup(connId, e.clientX, e.clientY);
                    }
                });

                this.addEventListener('mouseenter', function() {
                    $visiblePath.attr('stroke-width', '5');
                });
                this.addEventListener('mouseleave', function() {
                    $visiblePath.attr('stroke-width', '3');
                });
            });

            // Anschlusspunkt (Input) groups - click to edit
            $layer.find('.schematic-input-group').each(function() {
                var $group = $(this);
                var connId = $group.data('connection-id');
                var $visiblePath = $group.find('.schematic-connection');

                this.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    if (connId) {
                        self.showConnectionPopup(connId, e.clientX, e.clientY);
                    }
                });

                this.addEventListener('mouseenter', function() {
                    $visiblePath.attr('stroke-width', '5');
                });
                this.addEventListener('mouseleave', function() {
                    $visiblePath.attr('stroke-width', '3');
                });
            });
        },

        renderControls: function() {
            var self = this;
            var $canvas = $('.schematic-editor-canvas');

            // Remove existing controls
            $canvas.find('.schematic-controls').remove();

            // Find wrapper or canvas for control placement
            var $wrapper = $canvas.find('.schematic-zoom-wrapper');
            var $controlsParent = $wrapper.length ? $wrapper : $canvas;

            // Create controls container (positioned absolute over SVG)
            var $controls = $('<div class="schematic-controls" style="position:absolute;top:0;left:0;pointer-events:none;"></div>');

            // Button style
            var btnStyle = 'pointer-events:auto;width:28px;height:28px;border-radius:50%;border:2px solid #3498db;' +
                'background:#2d2d44;color:#3498db;font-size:18px;font-weight:bold;cursor:pointer;' +
                'display:flex;align-items:center;justify-content:center;transition:all 0.2s;';
            var btnHoverStyle = 'background:#3498db;color:#fff;';

            // Add Panel button (right of last panel)
            if (this.panels.length > 0) {
                var lastPanel = this.panels[this.panels.length - 1];
                var addPanelX = (lastPanel._x || 0) + (lastPanel._width || 200) + 20;
                var addPanelY = this.panelTopMargin + 50;

                var $addPanel = $('<button class="schematic-add-panel" title="Neues Feld hinzufügen" style="position:absolute;left:' + addPanelX + 'px;top:' + addPanelY + 'px;' + btnStyle + '">+</button>');
                $controls.append($addPanel);

                // Copy Panel button (if more than one panel exists)
                if (this.panels.length >= 1) {
                    var $copyPanel = $('<button class="schematic-copy-panel" data-panel-id="' + lastPanel.id + '" title="Feld kopieren" style="position:absolute;left:' + (addPanelX) + 'px;top:' + (addPanelY + 40) + 'px;' + btnStyle + '"><i class="fas fa-copy" style="font-size:12px;"></i></button>');
                    $controls.append($copyPanel);
                }
            } else {
                // No panels - show add panel button
                var $addPanel = $('<button class="schematic-add-panel" title="Neues Feld hinzufügen" style="position:absolute;left:50px;top:50px;' + btnStyle + '">+</button>');
                $controls.append($addPanel);
            }

            // Add Carrier button (below each panel's last carrier, or at top if no carriers)
            this.panels.forEach(function(panel) {
                var panelCarriers = self.carriers.filter(function(c) { return c.panel_id == panel.id; });
                var lastCarrier = panelCarriers[panelCarriers.length - 1];

                if (lastCarrier && lastCarrier._y) {
                    var addCarrierY = lastCarrier._y + self.RAIL_HEIGHT + 30;
                    var addCarrierX = (panel._x || 0) + 60;

                    var $addCarrier = $('<button class="schematic-add-carrier" data-panel-id="' + panel.id + '" title="Hutschiene hinzufügen" style="position:absolute;left:' + addCarrierX + 'px;top:' + addCarrierY + 'px;' + btnStyle + '">+</button>');
                    $controls.append($addCarrier);

                    // Copy Carrier button
                    if (panelCarriers.length >= 1) {
                        var $copyCarrier = $('<button class="schematic-copy-carrier" data-carrier-id="' + lastCarrier.id + '" data-panel-id="' + panel.id + '" title="Hutschiene kopieren" style="position:absolute;left:' + (addCarrierX + 35) + 'px;top:' + addCarrierY + 'px;' + btnStyle + '"><i class="fas fa-copy" style="font-size:12px;"></i></button>');
                        $controls.append($copyCarrier);
                    }
                } else {
                    // No carriers in this panel - show add carrier button at top
                    var addCarrierY = self.calculatedTopMargin + 20;
                    var addCarrierX = (panel._x || 0) + 60;

                    var $addCarrier = $('<button class="schematic-add-carrier" data-panel-id="' + panel.id + '" title="Hutschiene hinzufügen" style="position:absolute;left:' + addCarrierX + 'px;top:' + addCarrierY + 'px;' + btnStyle + '">+</button>');
                    $controls.append($addCarrier);
                }
            });

            // Add Equipment button & Copy button (next to last equipment on each carrier)
            this.carriers.forEach(function(carrier) {
                var carrierEquipment = self.equipment.filter(function(e) { return String(e.carrier_id) === String(carrier.id); });

                // Check if carrier has position data (use typeof to allow 0 values)
                if (typeof carrier._x !== 'undefined' && typeof carrier._y !== 'undefined') {
                    // Find last equipment position
                    var lastPos = 0;
                    var lastEquipment = null;
                    carrierEquipment.forEach(function(eq) {
                        var endPos = (parseInt(eq.position_te) || 1) + (parseInt(eq.width_te) || 1) - 1;
                        if (endPos > lastPos) {
                            lastPos = endPos;
                            lastEquipment = eq;
                        }
                    });

                    // Calculate button positions - place buttons on the LEFT side of the carrier
                    // Rail label is at about carrier._x - 44, so buttons need to be further left
                    var btnX = carrier._x - 100; // Left of the carrier and rail label
                    var btnY = carrier._y - self.BLOCK_HEIGHT / 2 + 10; // Aligned with blocks

                    // Check if there's space left
                    var totalTE = parseInt(carrier.total_te) || 12;
                    console.log('Carrier ' + carrier.id + ' (' + carrier.label + '): lastPos=' + lastPos + ', totalTE=' + totalTE + ', hasSpace=' + (lastPos < totalTE) + ', lastEquipment=' + (lastEquipment ? lastEquipment.id : 'none'));

                    if (lastPos < totalTE) {
                        // Add Equipment button - positioned left of carrier
                        var $addEquipment = $('<button class="schematic-add-equipment" data-carrier-id="' + carrier.id + '" title="Equipment hinzufügen" style="position:absolute;left:' + btnX + 'px;top:' + btnY + 'px;' + btnStyle + '">+</button>');
                        $controls.append($addEquipment);

                        // Copy Equipment button (below the + button)
                        if (lastEquipment) {
                            var copyBtnY = btnY + 30;
                            var $copyEquipment = $('<button class="schematic-copy-equipment" data-equipment-id="' + lastEquipment.id + '" data-carrier-id="' + carrier.id + '" title="Letztes Equipment kopieren" style="position:absolute;left:' + btnX + 'px;top:' + copyBtnY + 'px;' + btnStyle + '"><i class="fas fa-copy" style="font-size:12px;"></i></button>');
                            $controls.append($copyEquipment);
                        }
                    }

                    // Add Busbar button (below copy button or + button) - now blue and round like other buttons
                    var busbarBtnX = btnX;
                    var busbarBtnY = btnY + (lastEquipment ? 60 : 30);
                    var $addBusbar = $('<button class="schematic-add-busbar" data-carrier-id="' + carrier.id + '" title="Sammelschiene hinzufügen" style="position:absolute;left:' + busbarBtnX + 'px;top:' + busbarBtnY + 'px;' + btnStyle + '"><i class="fas fa-grip-lines" style="font-size:10px;"></i></button>');
                    $controls.append($addBusbar);
                } else {
                    console.log('Carrier ' + carrier.id + ' (' + carrier.label + '): Missing _x or _y position');
                }
            });

            // Append controls to wrapper (if exists) or canvas
            $canvas.css('position', 'relative');
            $controlsParent.css('position', 'relative').append($controls);

            // Bind control events
            this.bindControlEvents();
        },

        bindControlEvents: function() {
            var self = this;

            // Add Panel
            $(document).off('click.addPanel').on('click.addPanel', '.schematic-add-panel', function(e) {
                e.preventDefault();
                self.showAddPanelDialog();
            });

            // Copy Panel
            $(document).off('click.copyPanel').on('click.copyPanel', '.schematic-copy-panel', function(e) {
                e.preventDefault();
                var panelId = $(this).data('panel-id');
                self.duplicatePanel(panelId);
            });

            // Add Carrier
            $(document).off('click.addCarrier').on('click.addCarrier', '.schematic-add-carrier', function(e) {
                e.preventDefault();
                var panelId = $(this).data('panel-id');
                self.showAddCarrierDialog(panelId);
            });

            // Copy Carrier
            $(document).off('click.copyCarrier').on('click.copyCarrier', '.schematic-copy-carrier', function(e) {
                e.preventDefault();
                var carrierId = $(this).data('carrier-id');
                self.duplicateCarrier(carrierId);
            });

            // Add Equipment
            $(document).off('click.addEquipment').on('click.addEquipment', '.schematic-add-equipment', function(e) {
                e.preventDefault();
                var carrierId = $(this).data('carrier-id');
                self.showAddEquipmentDialog(carrierId);
            });

            // Copy Equipment (single copy)
            $(document).off('click.copyEquipment').on('click.copyEquipment', '.schematic-copy-equipment', function(e) {
                e.preventDefault();
                var equipmentId = $(this).data('equipment-id');
                self.duplicateSingleEquipment(equipmentId);
            });

            // Add Busbar (Sammelschiene)
            $(document).off('click.addBusbar').on('click.addBusbar', '.schematic-add-busbar', function(e) {
                e.preventDefault();
                var carrierId = $(this).data('carrier-id');
                self.showAddBusbarDialog(carrierId);
            });

            // Hover effects
            $('.schematic-controls button').hover(
                function() { $(this).css({ background: '#3498db', color: '#fff' }); },
                function() { $(this).css({ background: '#2d2d44', color: '#3498db' }); }
            );

            // Special hover for busbar button
            $('.schematic-add-busbar').hover(
                function() { $(this).css({ background: '#e74c3c', color: '#fff' }); },
                function() { $(this).css({ background: '#2d2d44', color: '#e74c3c' }); }
            );
        },

        showAddPanelDialog: function() {
            var self = this;
            var html = '<div class="schematic-dialog-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';
            html += '<div class="schematic-dialog" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;z-index:100001;min-width:300px;">';
            html += '<h3 style="margin:0 0 15px 0;color:#fff;">Neues Feld hinzufügen</h3>';
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Bezeichnung:</label>';
            html += '<input type="text" class="dialog-panel-label" value="Feld ' + (this.panels.length + 1) + '" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';
            html += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button type="button" class="dialog-cancel" style="background:#555;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Abbrechen</button>';
            html += '<button type="button" class="dialog-save" style="background:#27ae60;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Erstellen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.dialog-cancel, .schematic-dialog-overlay').on('click', function() {
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });

            $('.dialog-save').on('click', function() {
                var label = $('.dialog-panel-label').val();
                self.createPanel(label);
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });
        },

        createPanel: function(label) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                method: 'POST',
                data: {
                    action: 'create',
                    anlage_id: this.anlageId,
                    label: label,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Feld erstellt', 'success');
                        self.loadData();
                    } else {
                        self.showMessage(response.error || 'Fehler', 'error');
                    }
                }
            });
        },

        duplicatePanel: function(panelId) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                method: 'POST',
                data: {
                    action: 'duplicate',
                    panel_id: panelId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Feld kopiert', 'success');
                        self.loadData();
                    } else {
                        self.showMessage(response.error || 'Fehler', 'error');
                    }
                }
            });
        },

        showAddCarrierDialog: function(panelId) {
            var self = this;
            var html = '<div class="schematic-dialog-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';
            html += '<div class="schematic-dialog" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;z-index:100001;min-width:300px;">';
            html += '<h3 style="margin:0 0 15px 0;color:#fff;">Neue Hutschiene hinzufügen</h3>';
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Bezeichnung:</label>';
            html += '<input type="text" class="dialog-carrier-label" value="" placeholder="z.B. H1" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Teilungseinheiten (TE):</label>';
            html += '<input type="number" class="dialog-carrier-te" value="12" min="1" max="48" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';
            html += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button type="button" class="dialog-cancel" style="background:#555;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Abbrechen</button>';
            html += '<button type="button" class="dialog-save" style="background:#27ae60;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Erstellen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.dialog-cancel, .schematic-dialog-overlay').on('click', function() {
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });

            $('.dialog-save').on('click', function() {
                var label = $('.dialog-carrier-label').val();
                var totalTE = parseInt($('.dialog-carrier-te').val()) || 12;
                self.createCarrier(panelId, label, totalTE);
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });
        },

        createCarrier: function(panelId, label, totalTE) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                method: 'POST',
                data: {
                    action: 'create',
                    anlage_id: this.anlageId,
                    panel_id: panelId,
                    label: label,
                    total_te: totalTE,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Hutschiene erstellt', 'success');
                        self.loadData();
                    } else {
                        self.showMessage(response.error || 'Fehler', 'error');
                    }
                }
            });
        },

        duplicateCarrier: function(carrierId) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                method: 'POST',
                data: {
                    action: 'duplicate',
                    carrier_id: carrierId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Hutschiene kopiert', 'success');
                        self.loadData();
                    } else {
                        self.showMessage(response.error || 'Fehler', 'error');
                    }
                }
            });
        },

        showAddBusbarDialog: function(carrierId) {
            var self = this;
            var carrier = this.carriers.find(function(c) { return String(c.id) === String(carrierId); });
            var totalTE = carrier ? (parseInt(carrier.total_te) || 12) : 12;

            var html = '<div class="schematic-dialog-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';
            html += '<div class="schematic-dialog" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;z-index:100001;min-width:350px;">';
            html += '<h3 style="margin:0 0 15px 0;color:#fff;">Sammelschiene hinzufügen</h3>';

            // Phase type selection
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Phasen:</label>';
            html += '<select class="dialog-busbar-phases" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            html += '<option value="L1">L1 (Phase 1)</option>';
            html += '<option value="L2">L2 (Phase 2)</option>';
            html += '<option value="L3">L3 (Phase 3)</option>';
            html += '<option value="L1L2L3" selected>L1+L2+L3 (Dreiphasig)</option>';
            html += '<option value="N">N (Neutralleiter)</option>';
            html += '<option value="PE">PE (Schutzleiter)</option>';
            html += '</select></div>';

            // Start TE
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Von TE:</label>';
            html += '<input type="number" class="dialog-busbar-start" value="1" min="1" max="' + totalTE + '" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // End TE
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Bis TE:</label>';
            html += '<input type="number" class="dialog-busbar-end" value="' + totalTE + '" min="1" max="' + totalTE + '" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Position (above/below)
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Position:</label>';
            html += '<select class="dialog-busbar-position" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            html += '<option value="0">Oben</option>';
            html += '<option value="1">Unten</option>';
            html += '</select></div>';

            // Excluded TEs
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">TEs auslassen (z.B. 3,5,7):</label>';
            html += '<input type="text" class="dialog-busbar-excluded" placeholder="Kommagetrennte TE-Nummern" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Color
            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Farbe:</label>';
            html += '<input type="color" class="dialog-busbar-color" value="#e74c3c" style="width:100%;padding:4px;height:40px;border:1px solid #555;border-radius:4px;background:#1e1e1e;cursor:pointer;"/></div>';

            html += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button type="button" class="dialog-cancel" style="background:#555;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Abbrechen</button>';
            html += '<button type="button" class="dialog-save" style="background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Erstellen</button>';
            html += '</div></div>';

            $('body').append(html);

            // Auto-set color based on phase selection
            $('.dialog-busbar-phases').on('change', function() {
                var phase = $(this).val();
                var color = '#e74c3c'; // default red
                if (phase === 'L1') color = '#8B4513'; // brown
                else if (phase === 'L2') color = '#000000'; // black
                else if (phase === 'L3') color = '#808080'; // gray
                else if (phase === 'N') color = '#3498db'; // blue
                else if (phase === 'PE') color = '#f1c40f'; // yellow-green
                else if (phase === 'L1L2L3') color = '#e74c3c'; // red for 3-phase
                $('.dialog-busbar-color').val(color);
            });

            $('.dialog-cancel, .schematic-dialog-overlay').on('click', function() {
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });

            $('.dialog-save').on('click', function() {
                var phases = $('.dialog-busbar-phases').val();
                var startTE = parseInt($('.dialog-busbar-start').val()) || 1;
                var endTE = parseInt($('.dialog-busbar-end').val()) || totalTE;
                var positionY = parseInt($('.dialog-busbar-position').val()) || 0;
                var color = $('.dialog-busbar-color').val();
                var excludedTE = $('.dialog-busbar-excluded').val() || '';

                self.createBusbar(carrierId, phases, startTE, endTE, positionY, color, excludedTE);
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });
        },

        createBusbar: function(carrierId, phases, startTE, endTE, positionY, color, excludedTE) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'create_rail',
                    carrier_id: carrierId,
                    rail_start_te: startTE,
                    rail_end_te: endTE,
                    rail_phases: phases,
                    position_y: positionY,
                    color: color,
                    excluded_te: excludedTE,
                    connection_type: phases,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Sammelschiene erstellt', 'success');
                        // Add to local connections and re-render
                        self.connections.push({
                            id: response.connection_id,
                            is_rail: 1,
                            fk_carrier: carrierId,
                            rail_start_te: startTE,
                            rail_end_te: endTE,
                            rail_phases: phases,
                            position_y: positionY,
                            color: color,
                            excluded_te: excludedTE,
                            connection_type: phases
                        });
                        self.render();
                    } else {
                        self.showMessage(response.error || 'Fehler', 'error');
                    }
                }
            });
        },

        updateBusbarPosition: function(connectionId, newStartTE, newEndTE, newCarrierId) {
            var self = this;
            var data = {
                action: 'update_rail_position',
                connection_id: connectionId,
                rail_start_te: newStartTE,
                rail_end_te: newEndTE,
                token: $('input[name="token"]').val()
            };

            // Add carrier_id if provided (for moving to different carrier/panel)
            if (newCarrierId) {
                data.carrier_id = newCarrierId;
            }

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        // Update local connection data
                        var conn = self.connections.find(function(c) { return String(c.id) === String(connectionId); });
                        if (conn) {
                            conn.rail_start_te = newStartTE;
                            conn.rail_end_te = newEndTE;
                            if (newCarrierId) {
                                conn.fk_carrier = newCarrierId;
                            }
                        }
                        self.render();
                    } else {
                        self.showMessage(response.error || 'Fehler beim Verschieben', 'error');
                        self.render(); // Re-render to reset visual position
                    }
                },
                error: function() {
                    self.showMessage('Fehler beim Verschieben', 'error');
                    self.render();
                }
            });
        },

        showAddEquipmentDialog: function(carrierId) {
            var self = this;

            // Load equipment types first
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                data: { action: 'get_types', system_id: 1 },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showEquipmentTypeSelector(carrierId, response.types);
                    }
                }
            });
        },

        showEquipmentTypeSelector: function(carrierId, types) {
            var self = this;
            var html = '<div class="schematic-dialog-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';
            html += '<div class="schematic-dialog" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;z-index:100001;min-width:350px;max-height:80vh;overflow-y:auto;">';
            html += '<h3 style="margin:0 0 15px 0;color:#fff;">Equipment hinzufügen</h3>';

            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Typ:</label>';
            html += '<select class="dialog-equipment-type" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            types.forEach(function(t) {
                html += '<option value="' + t.id + '" data-width="' + t.width_te + '">' + self.escapeHtml(t.label) + ' (' + t.width_te + ' TE)</option>';
            });
            html += '</select></div>';

            html += '<div style="margin-bottom:12px;"><label style="display:block;color:#aaa;margin-bottom:4px;">Bezeichnung (optional):</label>';
            html += '<input type="text" class="dialog-equipment-label" value="" placeholder="z.B. Küche Licht" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            html += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button type="button" class="dialog-cancel" style="background:#555;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Abbrechen</button>';
            html += '<button type="button" class="dialog-save" style="background:#27ae60;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Erstellen</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.dialog-cancel, .schematic-dialog-overlay').on('click', function() {
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });

            $('.dialog-save').on('click', function() {
                var typeId = $('.dialog-equipment-type').val();
                var label = $('.dialog-equipment-label').val();
                self.createEquipment(carrierId, typeId, label);
                $('.schematic-dialog, .schematic-dialog-overlay').remove();
            });
        },

        createEquipment: function(carrierId, typeId, label) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'create',
                    carrier_id: carrierId,
                    type_id: typeId,
                    label: label,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Equipment erstellt', 'success');
                        self.loadData();
                    } else {
                        self.showMessage(response.error || 'Fehler', 'error');
                    }
                }
            });
        },

        duplicateSingleEquipment: function(equipmentId) {
            var self = this;

            // Find original equipment to get carrier info
            var originalEq = this.equipment.find(function(e) { return String(e.id) === String(equipmentId); });

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'duplicate',
                    equipment_id: equipmentId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success && response.equipment) {
                        self.showMessage('Equipment kopiert', 'success');
                        // Add new equipment to local array instead of reloading everything
                        var newEq = response.equipment;
                        newEq.carrier_id = originalEq ? originalEq.carrier_id : newEq.fk_carrier;
                        newEq.panel_id = originalEq ? originalEq.panel_id : null;
                        self.equipment.push(newEq);
                        self.render();
                    } else if (response.success) {
                        // Fallback if no equipment data returned
                        self.showMessage('Equipment kopiert', 'success');
                        self.loadData();
                    } else {
                        self.showMessage(response.error || 'Kein Platz mehr', 'warning');
                    }
                },
                error: function() {
                    self.showMessage('Netzwerkfehler', 'error');
                }
            });
        },

        // Check if an equipment position is covered by a busbar
        // Returns: { top: boolean, bottom: boolean } indicating which terminals are covered
        isEquipmentCoveredByBusbar: function(eq) {
            var eqCarrierId = eq.carrier_id || eq.fk_carrier;
            var eqPosTE = parseInt(eq.position_te) || 1;
            var eqWidthTE = parseInt(eq.width_te) || 1;
            var eqEndTE = eqPosTE + eqWidthTE - 1;

            var result = { top: false, bottom: false };

            this.connections.forEach(function(conn) {
                // Must be a rail/busbar
                if (!conn.is_rail || conn.is_rail === '0' || conn.is_rail === 0) return;
                if (parseInt(conn.is_rail) !== 1) return;

                // Busbar must be on same carrier
                if (String(conn.fk_carrier) !== String(eqCarrierId)) return;

                var railStart = parseInt(conn.rail_start_te) || 1;
                var railEnd = parseInt(conn.rail_end_te) || railStart;
                var positionY = parseInt(conn.position_y) || 0;

                // Check if equipment overlaps with busbar range
                var overlaps = !(eqEndTE < railStart || eqPosTE > railEnd);
                if (!overlaps) return;

                // Determine if busbar is above (position_y = 0) or below (position_y > 0)
                if (positionY === 0) {
                    result.top = true;
                } else {
                    result.bottom = true;
                }
            });

            return result;
        },

        // Legacy compatibility - returns true if top terminals are covered
        isEquipmentCoveredByBusbarLegacy: function(eq) {
            var result = this.isEquipmentCoveredByBusbar(eq);
            return result.top;
        },

        getTerminals: function(eq) {
            // Try to parse terminals_config from equipment type
            if (eq.terminals_config) {
                try {
                    var config = JSON.parse(eq.terminals_config);
                    // Handle both old format (inputs/outputs) and new format (terminals)
                    if (config.terminals) {
                        return config.terminals;
                    } else if (config.inputs || config.outputs) {
                        // Convert old format to new
                        var terminals = [];
                        if (config.inputs) {
                            config.inputs.forEach(function(t) {
                                terminals.push({ id: t.id, label: t.label, pos: 'top' });
                            });
                        }
                        if (config.outputs) {
                            config.outputs.forEach(function(t) {
                                terminals.push({ id: t.id, label: t.label, pos: 'bottom' });
                            });
                        }
                        return terminals;
                    }
                } catch (e) {}
            }

            // Look up by type ref
            var typeRef = (eq.type_ref || '').toUpperCase();
            if (this.DEFAULT_TERMINALS[typeRef] && this.DEFAULT_TERMINALS[typeRef].terminals) {
                return this.DEFAULT_TERMINALS[typeRef].terminals;
            }

            // Check for FI pattern
            if (typeRef.indexOf('FI') !== -1 || typeRef.indexOf('RCD') !== -1) {
                if (typeRef.indexOf('4P') !== -1) {
                    return this.DEFAULT_TERMINALS['FI4P'].terminals;
                }
                return this.DEFAULT_TERMINALS['FI'].terminals;
            }

            // Default: 1 top, 1 bottom
            return this.DEFAULT_TERMINALS['LS'].terminals;
        },

        getTerminalPosition: function(eq, terminalId, terminals) {
            // Find the terminal
            var terminal = null;
            var termIndex = 0;
            var samePosList = [];

            // Map legacy terminal names to positions
            var legacyMap = {
                'in': 'top', 'input': 'top', 'in_L': 'top', 'in_N': 'top',
                'out': 'bottom', 'output': 'bottom', 'out_L': 'bottom', 'out_N': 'bottom'
            };

            for (var i = 0; i < terminals.length; i++) {
                if (terminals[i].id === terminalId) {
                    terminal = terminals[i];
                    break;
                }
            }

            // If not found by exact match, try legacy mapping
            if (!terminal && legacyMap[terminalId]) {
                var targetPos = legacyMap[terminalId];
                for (var k = 0; k < terminals.length; k++) {
                    if (terminals[k].pos === targetPos) {
                        terminal = terminals[k];
                        break;
                    }
                }
            }

            if (!terminal) {
                // Default: use first bottom terminal for 'out', first top for anything else
                var defaultPos = (terminalId && (terminalId.indexOf('out') !== -1 || terminalId === 't2')) ? 'bottom' : 'top';
                for (var m = 0; m < terminals.length; m++) {
                    if (terminals[m].pos === defaultPos) {
                        terminal = terminals[m];
                        break;
                    }
                }
                if (!terminal) {
                    terminal = terminals[0] || { pos: 'top' };
                }
            }

            // Get all terminals with same position
            for (var j = 0; j < terminals.length; j++) {
                if (terminals[j].pos === terminal.pos) {
                    if (terminals[j].id === terminal.id) termIndex = samePosList.length;
                    samePosList.push(terminals[j]);
                }
            }

            var isTop = terminal.pos === 'top';
            var widthTE = parseInt(eq.width_te) || 1;

            // Terminal im festen TE-Raster platzieren
            // Jeder Terminal belegt 1 TE - Index bestimmt welches TE
            var teIndex = termIndex % widthTE;
            var x = eq._x + (teIndex * this.TE_WIDTH) + (this.TE_WIDTH / 2);
            var y = isTop ? (eq._y - 5) : (eq._y + eq._height + 5);

            return { x: x, y: y, isTop: isTop };
        },

        createOrthogonalPath: function(source, target, routeOffset, sourceEq, targetEq) {
            var x1 = source.x, y1 = source.y;
            var x2 = target.x, y2 = target.y;

            // Connection index for spreading
            var connIndex = Math.floor(routeOffset / 8);

            // Use pathfinding with obstacle avoidance
            if (typeof PF !== 'undefined') {
                try {
                    var path = this.createPathfindingRoute(x1, y1, x2, y2, connIndex);
                    if (path) return path;
                } catch (e) {
                    console.error('Pathfinding error:', e);
                }
            }

            // Fallback to simple route
            return this.createSimpleRoute(x1, y1, x2, y2, source.isTop, target.isTop, routeOffset);
        },

        // Pathfinding-based routing with obstacle avoidance and connection spreading
        createPathfindingRoute: function(x1, y1, x2, y2, connIndex) {
            var self = this;
            var GRID_SIZE = 5;
            var PADDING = 60;
            var BLOCK_MARGIN = 2;
            var WIRE_SPREAD = 10; // Pixels between parallel wires

            // Apply offset to spread parallel wires apart
            var spreadOffset = connIndex * WIRE_SPREAD;
            // Alternate left/right to spread evenly
            var spreadDir = (connIndex % 2 === 0) ? 1 : -1;
            var xSpread = spreadDir * Math.floor(connIndex / 2) * WIRE_SPREAD;

            // Find bounds of all equipment
            var minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
            this.equipment.forEach(function(eq) {
                if (eq._x !== undefined && eq._y !== undefined) {
                    minX = Math.min(minX, eq._x);
                    maxX = Math.max(maxX, eq._x + (eq._width || self.TE_WIDTH * eq.width_te));
                    minY = Math.min(minY, eq._y);
                    maxY = Math.max(maxY, eq._y + (eq._height || self.BLOCK_HEIGHT));
                }
            });

            // Include start and end points with padding
            minX = Math.min(minX, x1, x2) - PADDING;
            maxX = Math.max(maxX, x1, x2) + PADDING;
            minY = Math.min(minY, y1, y2) - PADDING;
            maxY = Math.max(maxY, y1, y2) + PADDING;

            // Create grid
            var gridWidth = Math.ceil((maxX - minX) / GRID_SIZE);
            var gridHeight = Math.ceil((maxY - minY) / GRID_SIZE);

            // Limit grid size for performance
            if (gridWidth > 300) gridWidth = 300;
            if (gridHeight > 300) gridHeight = 300;

            var grid = new PF.Grid(gridWidth, gridHeight);

            // Mark ALL equipment as obstacles (unwalkable) - including source and target blocks
            this.equipment.forEach(function(eq) {
                if (eq._x === undefined || eq._y === undefined) return;

                var eqWidth = eq._width || (self.TE_WIDTH * (parseInt(eq.width_te) || 1));
                var eqHeight = eq._height || self.BLOCK_HEIGHT;

                var eqX1 = Math.floor((eq._x - minX) / GRID_SIZE);
                var eqY1 = Math.floor((eq._y - minY) / GRID_SIZE);
                var eqX2 = Math.ceil((eq._x + eqWidth - minX) / GRID_SIZE);
                var eqY2 = Math.ceil((eq._y + eqHeight - minY) / GRID_SIZE);

                // Add margin around blocks to keep lines away
                eqX1 = Math.max(0, eqX1 - BLOCK_MARGIN);
                eqY1 = Math.max(0, eqY1 - BLOCK_MARGIN);
                eqX2 = Math.min(gridWidth - 1, eqX2 + BLOCK_MARGIN);
                eqY2 = Math.min(gridHeight - 1, eqY2 + BLOCK_MARGIN);

                for (var gx = eqX1; gx <= eqX2; gx++) {
                    for (var gy = eqY1; gy <= eqY2; gy++) {
                        if (gx >= 0 && gx < gridWidth && gy >= 0 && gy < gridHeight) {
                            grid.setWalkableAt(gx, gy, false);
                        }
                    }
                }
            });

            // Mark busbars/rails as obstacles too (Phasenschienen)
            this.connections.forEach(function(conn) {
                if (parseInt(conn.is_rail) !== 1) return;

                // Find the carrier for this busbar
                var carrier = self.carriers.find(function(c) {
                    return String(c.id) === String(conn.fk_carrier);
                });
                if (!carrier || carrier._x === undefined) return;

                var startTE = parseInt(conn.rail_start_te) || 1;
                var endTE = parseInt(conn.rail_end_te) || 12;

                // Calculate busbar position
                var busbarX = carrier._x + (startTE - 1) * self.TE_WIDTH;
                var busbarWidth = (endTE - startTE + 1) * self.TE_WIDTH;
                var busbarY = carrier._y + self.BLOCK_HEIGHT + 15; // Position below blocks
                var busbarHeight = 20; // Approximate busbar height

                var bbX1 = Math.floor((busbarX - minX) / GRID_SIZE);
                var bbY1 = Math.floor((busbarY - minY) / GRID_SIZE);
                var bbX2 = Math.ceil((busbarX + busbarWidth - minX) / GRID_SIZE);
                var bbY2 = Math.ceil((busbarY + busbarHeight - minY) / GRID_SIZE);

                // Add margin around busbars
                bbX1 = Math.max(0, bbX1 - BLOCK_MARGIN);
                bbY1 = Math.max(0, bbY1 - BLOCK_MARGIN);
                bbX2 = Math.min(gridWidth - 1, bbX2 + BLOCK_MARGIN);
                bbY2 = Math.min(gridHeight - 1, bbY2 + BLOCK_MARGIN);

                for (var bx = bbX1; bx <= bbX2; bx++) {
                    for (var by = bbY1; by <= bbY2; by++) {
                        if (bx >= 0 && bx < gridWidth && by >= 0 && by < gridHeight) {
                            grid.setWalkableAt(bx, by, false);
                        }
                    }
                }

                // Also mark the CENTER LABEL of the busbar as obstacle
                // Label is in the center of the busbar
                var phases = conn.rail_phases || conn.connection_type || '';
                if (phases) {
                    var labelWidth = phases.length * 10 + 10; // Approximate text width + padding
                    var labelHeight = 16; // Font size + padding
                    var labelX = busbarX + busbarWidth / 2 - labelWidth / 2;
                    var labelY = busbarY - 5; // Label is on top of busbar

                    var lblX1 = Math.floor((labelX - minX) / GRID_SIZE);
                    var lblY1 = Math.floor((labelY - minY) / GRID_SIZE);
                    var lblX2 = Math.ceil((labelX + labelWidth - minX) / GRID_SIZE);
                    var lblY2 = Math.ceil((labelY + labelHeight - minY) / GRID_SIZE);

                    // Add margin around label
                    lblX1 = Math.max(0, lblX1 - 1);
                    lblY1 = Math.max(0, lblY1 - 1);
                    lblX2 = Math.min(gridWidth - 1, lblX2 + 1);
                    lblY2 = Math.min(gridHeight - 1, lblY2 + 1);

                    for (var lx = lblX1; lx <= lblX2; lx++) {
                        for (var ly = lblY1; ly <= lblY2; ly++) {
                            if (lx >= 0 && lx < gridWidth && ly >= 0 && ly < gridHeight) {
                                grid.setWalkableAt(lx, ly, false);
                            }
                        }
                    }
                }
            });

            // Apply horizontal spread to separate parallel wires
            var x1Spread = x1 + xSpread;
            var x2Spread = x2 + xSpread;

            // Convert pixel coords to grid coords
            var startX = Math.round((x1Spread - minX) / GRID_SIZE);
            var startY = Math.round((y1 - minY) / GRID_SIZE);
            var endX = Math.round((x2Spread - minX) / GRID_SIZE);
            var endY = Math.round((y2 - minY) / GRID_SIZE);

            // Clamp to grid bounds
            startX = Math.max(0, Math.min(gridWidth - 1, startX));
            startY = Math.max(0, Math.min(gridHeight - 1, startY));
            endX = Math.max(0, Math.min(gridWidth - 1, endX));
            endY = Math.max(0, Math.min(gridHeight - 1, endY));

            // Make sure start and end points and their immediate surroundings are walkable
            // This creates a "corridor" from the terminal into the routing space
            for (var dx = -3; dx <= 3; dx++) {
                for (var dy = -3; dy <= 3; dy++) {
                    var sx = startX + dx;
                    var sy = startY + dy;
                    var ex = endX + dx;
                    var ey = endY + dy;
                    if (sx >= 0 && sx < gridWidth && sy >= 0 && sy < gridHeight) {
                        grid.setWalkableAt(sx, sy, true);
                    }
                    if (ex >= 0 && ex < gridWidth && ey >= 0 && ey < gridHeight) {
                        grid.setWalkableAt(ex, ey, true);
                    }
                }
            }

            // Find path using JumpPoint finder - produces cleaner orthogonal paths
            var finder = new PF.JumpPointFinder({
                allowDiagonal: false
            });

            var path = finder.findPath(startX, startY, endX, endY, grid.clone());

            // If no path found, use simple fallback
            if (!path || path.length === 0) {
                return this.createSimpleRoute(x1, y1, x2, y2, true, true, routeOffset);
            }

            // Convert path to orthogonal (only horizontal and vertical segments)
            // This eliminates the "snake" effect by keeping only direction changes
            var orthogonalPath = this.makeOrthogonal(path);

            // Convert grid path back to pixel coordinates
            var pixelPath = [];
            for (var i = 0; i < orthogonalPath.length; i++) {
                pixelPath.push({
                    x: minX + orthogonalPath[i][0] * GRID_SIZE,
                    y: minY + orthogonalPath[i][1] * GRID_SIZE
                });
            }

            // Build SVG path starting from exact source position
            var svgPath = 'M ' + x1 + ' ' + y1;

            // Add intermediate waypoints (skip first if too close to start)
            for (var j = 0; j < pixelPath.length; j++) {
                svgPath += ' L ' + pixelPath[j].x + ' ' + pixelPath[j].y;
            }

            // End at exact target position
            svgPath += ' L ' + x2 + ' ' + y2;

            return svgPath;
        },

        // Simplify path to only keep corner points (where direction changes)
        makeOrthogonal: function(path) {
            if (path.length < 3) return path;

            var result = [path[0]]; // Always keep start
            var prevDir = null;

            for (var i = 1; i < path.length; i++) {
                var dx = path[i][0] - path[i-1][0];
                var dy = path[i][1] - path[i-1][1];

                // Determine direction: 'h' for horizontal, 'v' for vertical
                var dir = (dx !== 0) ? 'h' : 'v';

                // If direction changed, add the previous point as a corner
                if (prevDir !== null && dir !== prevDir) {
                    result.push(path[i-1]);
                }

                prevDir = dir;
            }

            // Always keep end point
            result.push(path[path.length - 1]);

            return result;
        },

        // Simple fallback routing
        createSimpleRoute: function(x1, y1, x2, y2, sourceIsTop, targetIsTop, routeOffset) {
            var MARGIN = 25 + (routeOffset || 0);

            // Simple L-shaped or U-shaped route
            if (sourceIsTop && targetIsTop) {
                var routeY = Math.min(y1, y2) - MARGIN;
                return 'M ' + x1 + ' ' + y1 +
                       ' L ' + x1 + ' ' + routeY +
                       ' L ' + x2 + ' ' + routeY +
                       ' L ' + x2 + ' ' + y2;
            } else if (!sourceIsTop && !targetIsTop) {
                var routeYBot = Math.max(y1, y2) + MARGIN;
                return 'M ' + x1 + ' ' + y1 +
                       ' L ' + x1 + ' ' + routeYBot +
                       ' L ' + x2 + ' ' + routeYBot +
                       ' L ' + x2 + ' ' + y2;
            } else {
                // Mixed - route through middle
                var midY = (y1 + y2) / 2;
                return 'M ' + x1 + ' ' + y1 +
                       ' L ' + x1 + ' ' + midY +
                       ' L ' + x2 + ' ' + midY +
                       ' L ' + x2 + ' ' + y2;
            }
        },

        // Handle terminal click - only in wire draw mode
        handleTerminalClick: function($terminal) {
            var eqId = $terminal.data('equipment-id');
            var termId = $terminal.data('terminal-id');

            // Only works in manual wire draw mode
            if (!this.wireDrawMode) return;

            if (!this.wireDrawSourceEq) {
                // First terminal - start drawing
                this.wireDrawSourceEq = eqId;
                this.wireDrawSourceTerm = termId;
                this.wireDrawPoints = [];

                // Get terminal position as first point
                var eq = this.equipment.find(function(e) { return String(e.id) === String(eqId); });
                if (eq) {
                    var terminals = this.getTerminals(eq);
                    var termPos = this.getTerminalPosition(eq, termId, terminals);
                    if (termPos) {
                        this.wireDrawPoints.push({x: termPos.x, y: termPos.y});
                    }
                }

                $terminal.find('.schematic-terminal-circle').attr('stroke', '#ff0').attr('stroke-width', '3');
                this.showMessage('Rasterpunkte klicken, Rechtsklick = Abbruch, dann Ziel-Terminal klicken', 'info');
                this.showWireGrid();
            } else if (eqId !== this.wireDrawSourceEq) {
                // Second terminal - finish and save
                this.finishWireDrawing(eqId, termId);
            }
        },

        // Wire draw mode functions
        toggleWireDrawMode: function() {
            this.wireDrawMode = !this.wireDrawMode;
            var $btn = $('.schematic-wire-draw-toggle');

            if (this.wireDrawMode) {
                $btn.addClass('active').css('background', '#27ae60');
                this.showMessage('Manueller Zeichenmodus: Klicken Sie auf ein START-Terminal (roter Kreis)', 'info');
                this.showWireGrid();
                // Highlight all terminals to show they are clickable
                $(this.svgElement).find('.schematic-terminal-circle').css('cursor', 'crosshair');
            } else {
                $btn.removeClass('active').css('background', '');
                this.cancelWireDrawing();
                this.hideWireGrid();
                this.showMessage('Automatischer Modus aktiviert', 'info');
            }
        },

        showWireGrid: function() {
            console.log('showWireGrid called, svgElement:', this.svgElement);
            if (!this.svgElement) {
                console.error('No SVG element found!');
                return;
            }

            // Remove existing wire grid
            var existing = this.svgElement.querySelector('.schematic-wire-grid-layer');
            if (existing) existing.remove();

            var self = this;
            var svgNS = 'http://www.w3.org/2000/svg';
            var gridLayer = document.createElementNS(svgNS, 'g');
            gridLayer.setAttribute('class', 'schematic-wire-grid-layer');
            gridLayer.setAttribute('pointer-events', 'none');

            // Collect all terminal positions and routing Y-lines
            this.wireGridPoints = [];
            var pointCount = 0;

            // Get X positions from all TE slots on all carriers
            var xPositions = [];
            this.carriers.forEach(function(carrier) {
                if (typeof carrier._x === 'undefined') return;
                var totalTE = carrier.total_te || 12;
                for (var te = 1; te <= totalTE; te++) {
                    // Terminal center X position for this TE
                    var teX = carrier._x + (te - 1) * self.TE_WIDTH + (self.TE_WIDTH / 2);
                    if (xPositions.indexOf(teX) === -1) xPositions.push(teX);
                }
            });

            // Get Y positions from equipment terminals and routing space
            var yPositions = [];
            this.equipment.forEach(function(eq) {
                if (typeof eq._y === 'undefined') return;
                // Top terminal Y
                var topY = eq._y - 7;
                // Bottom terminal Y
                var bottomY = eq._y + (eq._height || self.BLOCK_HEIGHT) + 7;
                if (yPositions.indexOf(topY) === -1) yPositions.push(topY);
                if (yPositions.indexOf(bottomY) === -1) yPositions.push(bottomY);
            });

            // Add routing Y lines between carriers (for horizontal routing)
            this.carriers.forEach(function(carrier) {
                if (typeof carrier._y === 'undefined') return;
                var railCenterY = carrier._y + self.RAIL_HEIGHT / 2;
                var blockTop = railCenterY - self.BLOCK_HEIGHT / 2;
                var blockBottom = railCenterY + self.BLOCK_HEIGHT / 2;

                // Add grid lines above and below the busbar area
                var busbarSpace = 60; // Space for busbars
                for (var offsetY = busbarSpace + 20; offsetY < busbarSpace + 100; offsetY += self.WIRE_GRID_SIZE) {
                    var routeY = blockTop - offsetY;
                    if (routeY > 0 && yPositions.indexOf(routeY) === -1) yPositions.push(routeY);
                }
                for (var offsetY2 = busbarSpace + 20; offsetY2 < busbarSpace + 100; offsetY2 += self.WIRE_GRID_SIZE) {
                    var routeY2 = blockBottom + offsetY2;
                    if (yPositions.indexOf(routeY2) === -1) yPositions.push(routeY2);
                }
            });

            // Sort positions
            xPositions.sort(function(a, b) { return a - b; });
            yPositions.sort(function(a, b) { return a - b; });

            // Draw grid points at terminal-aligned positions
            xPositions.forEach(function(x) {
                yPositions.forEach(function(y) {
                    var circle = document.createElementNS(svgNS, 'circle');
                    circle.setAttribute('cx', x);
                    circle.setAttribute('cy', y);
                    circle.setAttribute('r', '1.5');
                    circle.setAttribute('fill', '#888');
                    circle.setAttribute('opacity', '0.4');
                    gridLayer.appendChild(circle);
                    self.wireGridPoints.push({x: x, y: y});
                    pointCount++;
                });
            });

            console.log('Wire grid: ' + xPositions.length + ' x-positions, ' + yPositions.length + ' y-positions');

            // Create magnetic cursor indicator (shows nearest grid point)
            var magnetCursor = document.createElementNS(svgNS, 'circle');
            magnetCursor.setAttribute('class', 'wire-grid-magnet');
            magnetCursor.setAttribute('r', '6');
            magnetCursor.setAttribute('fill', 'none');
            magnetCursor.setAttribute('stroke', '#27ae60');
            magnetCursor.setAttribute('stroke-width', '2');
            magnetCursor.setAttribute('opacity', '0');
            magnetCursor.setAttribute('pointer-events', 'none');
            gridLayer.appendChild(magnetCursor);

            // Append grid layer at the end of SVG (on top of everything)
            this.svgElement.appendChild(gridLayer);
            console.log('Wire grid created with ' + pointCount + ' points');

            // Setup magnetic snap behavior
            this.setupMagneticSnap();
        },

        setupMagneticSnap: function() {
            var self = this;
            var $svg = $(this.svgElement);
            var magnetRadius = 20; // Distance in pixels to activate magnetic snap

            // Remove old handler if exists
            $svg.off('mousemove.magneticSnap');

            $svg.on('mousemove.magneticSnap', function(e) {
                if (!self.wireDrawMode) return;

                var rect = self.svgElement.getBoundingClientRect();
                var x = e.clientX - rect.left;
                var y = e.clientY - rect.top;

                // Find nearest grid point from terminal-aligned points
                var nearestX = x, nearestY = y;
                var minDist = Infinity;

                if (self.wireGridPoints && self.wireGridPoints.length > 0) {
                    self.wireGridPoints.forEach(function(pt) {
                        var d = Math.sqrt(Math.pow(x - pt.x, 2) + Math.pow(y - pt.y, 2));
                        if (d < minDist) {
                            minDist = d;
                            nearestX = pt.x;
                            nearestY = pt.y;
                        }
                    });
                }

                var magnetCursor = self.svgElement.querySelector('.wire-grid-magnet');
                if (magnetCursor) {
                    if (minDist <= magnetRadius) {
                        // Show magnetic indicator at nearest grid point
                        magnetCursor.setAttribute('cx', nearestX);
                        magnetCursor.setAttribute('cy', nearestY);
                        magnetCursor.setAttribute('opacity', '1');

                        // Store snapped position for click handling
                        self.magnetSnappedPos = {x: nearestX, y: nearestY};
                    } else {
                        magnetCursor.setAttribute('opacity', '0');
                        self.magnetSnappedPos = null;
                    }
                }
            });
        },

        // Snap coordinates to nearest terminal-aligned grid point
        snapToTerminalGrid: function(x, y) {
            var self = this;

            // If we have pre-calculated grid points, find nearest
            if (this.wireGridPoints && this.wireGridPoints.length > 0) {
                var nearestX = x, nearestY = y;
                var minDist = Infinity;

                this.wireGridPoints.forEach(function(pt) {
                    var d = Math.sqrt(Math.pow(x - pt.x, 2) + Math.pow(y - pt.y, 2));
                    if (d < minDist) {
                        minDist = d;
                        nearestX = pt.x;
                        nearestY = pt.y;
                    }
                });

                return {x: nearestX, y: nearestY};
            }

            // Fallback: snap to TE centers for X, and nearest terminal Y
            var nearestX = x, nearestY = y;

            // Find nearest TE center X
            var minDistX = Infinity;
            this.carriers.forEach(function(carrier) {
                if (typeof carrier._x === 'undefined') return;
                var totalTE = carrier.total_te || 12;
                for (var te = 1; te <= totalTE; te++) {
                    var teX = carrier._x + (te - 1) * self.TE_WIDTH + (self.TE_WIDTH / 2);
                    var dx = Math.abs(x - teX);
                    if (dx < minDistX) {
                        minDistX = dx;
                        nearestX = teX;
                    }
                }
            });

            // Find nearest terminal Y
            var minDistY = Infinity;
            this.equipment.forEach(function(eq) {
                if (typeof eq._y === 'undefined') return;
                var topY = eq._y - 7;
                var bottomY = eq._y + (eq._height || self.BLOCK_HEIGHT) + 7;

                var dyTop = Math.abs(y - topY);
                var dyBottom = Math.abs(y - bottomY);

                if (dyTop < minDistY) {
                    minDistY = dyTop;
                    nearestY = topY;
                }
                if (dyBottom < minDistY) {
                    minDistY = dyBottom;
                    nearestY = bottomY;
                }
            });

            return {x: nearestX, y: nearestY};
        },

        hideWireGrid: function() {
            if (this.svgElement) {
                var grid = this.svgElement.querySelector('.schematic-wire-grid-layer');
                if (grid) grid.remove();
            }
            // Remove magnetic snap handler
            $(this.svgElement).off('mousemove.magneticSnap');
            this.magnetSnappedPos = null;
            this.wireGridPoints = null;
            console.log('Wire grid hidden');
        },

        updateWirePreview: function() {
            var svgNS = 'http://www.w3.org/2000/svg';
            var preview = this.svgElement.querySelector('.wire-draw-preview');

            if (!preview) {
                // Create preview path using native DOM (jQuery doesn't work with SVG namespaces)
                preview = document.createElementNS(svgNS, 'path');
                preview.setAttribute('class', 'wire-draw-preview');
                preview.setAttribute('fill', 'none');
                preview.setAttribute('stroke', '#27ae60');
                preview.setAttribute('stroke-width', '3');
                this.svgElement.appendChild(preview); // Add to end of SVG (on top)
            }

            if (this.wireDrawPoints.length < 1) {
                preview.setAttribute('d', '');
                return;
            }

            // Build path from all points
            var d = 'M ' + this.wireDrawPoints[0].x + ' ' + this.wireDrawPoints[0].y;
            for (var i = 1; i < this.wireDrawPoints.length; i++) {
                d += ' L ' + this.wireDrawPoints[i].x + ' ' + this.wireDrawPoints[i].y;
            }
            preview.setAttribute('d', d);
            console.log('Wire preview updated:', d);
        },

        updateWirePreviewCursor: function(x, y) {
            var svgNS = 'http://www.w3.org/2000/svg';
            var cursor = this.svgElement.querySelector('.wire-draw-cursor');
            var cursorDot = this.svgElement.querySelector('.wire-draw-cursor-dot');
            var cursorLine = this.svgElement.querySelector('.wire-draw-cursor-line');

            if (!cursor) {
                // Create cursor elements using native DOM
                cursor = document.createElementNS(svgNS, 'circle');
                cursor.setAttribute('class', 'wire-draw-cursor');
                cursor.setAttribute('r', '8');
                cursor.setAttribute('fill', 'none');
                cursor.setAttribute('stroke', '#27ae60');
                cursor.setAttribute('stroke-width', '2');
                this.svgElement.appendChild(cursor);

                cursorDot = document.createElementNS(svgNS, 'circle');
                cursorDot.setAttribute('class', 'wire-draw-cursor-dot');
                cursorDot.setAttribute('r', '3');
                cursorDot.setAttribute('fill', '#27ae60');
                this.svgElement.appendChild(cursorDot);

                cursorLine = document.createElementNS(svgNS, 'line');
                cursorLine.setAttribute('class', 'wire-draw-cursor-line');
                cursorLine.setAttribute('stroke', '#27ae60');
                cursorLine.setAttribute('stroke-width', '2');
                cursorLine.setAttribute('stroke-dasharray', '5,5');
                cursorLine.setAttribute('opacity', '0.7');
                this.svgElement.appendChild(cursorLine);
            }

            // Update cursor position (green snap indicator)
            cursor.setAttribute('cx', x);
            cursor.setAttribute('cy', y);
            cursorDot.setAttribute('cx', x);
            cursorDot.setAttribute('cy', y);

            // Draw line from last point to cursor (if we have points)
            if (this.wireDrawPoints.length > 0) {
                var lastPt = this.wireDrawPoints[this.wireDrawPoints.length - 1];
                cursorLine.setAttribute('x1', lastPt.x);
                cursorLine.setAttribute('y1', lastPt.y);
                cursorLine.setAttribute('x2', x);
                cursorLine.setAttribute('y2', y);
                cursorLine.style.display = '';
            } else {
                // No points yet - hide line
                cursorLine.style.display = 'none';
            }
        },

        cancelWireDrawing: function() {
            this.wireDrawSourceEq = null;
            this.wireDrawSourceTerm = null;
            this.wireDrawPoints = [];

            // Remove all preview elements using native DOM
            var elements = this.svgElement.querySelectorAll('.wire-draw-preview, .wire-draw-cursor, .wire-draw-cursor-dot, .wire-draw-cursor-line');
            elements.forEach(function(el) { el.remove(); });

            // Reset terminal highlight
            $(this.svgElement).find('.schematic-terminal-circle').attr('stroke', '#fff').attr('stroke-width', '2').css('cursor', '');

            this.showMessage('Zeichnung abgebrochen', 'info');
        },

        finishWireDrawing: function(targetEqId, targetTermId) {
            var self = this;

            // Get target terminal position
            var eq = this.equipment.find(function(e) { return String(e.id) === String(targetEqId); });
            if (eq) {
                var terminals = this.getTerminals(eq);
                var termPos = this.getTerminalPosition(eq, targetTermId, terminals);
                if (termPos) {
                    this.wireDrawPoints.push({x: termPos.x, y: termPos.y});
                }
            }

            // Build path string from points
            var pathData = '';
            for (var i = 0; i < this.wireDrawPoints.length; i++) {
                pathData += (i === 0 ? 'M' : 'L') + ' ' + this.wireDrawPoints[i].x + ' ' + this.wireDrawPoints[i].y + ' ';
            }

            // Show connection dialog to set labels and save
            this.showConnectionLabelDialogWithPath(
                this.wireDrawSourceEq,
                this.wireDrawSourceTerm,
                targetEqId,
                targetTermId,
                pathData.trim()
            );

            // Cleanup
            this.wireDrawSourceEq = null;
            this.wireDrawSourceTerm = null;
            this.wireDrawPoints = [];
            var elements = this.svgElement.querySelectorAll('.wire-draw-preview, .wire-draw-cursor, .wire-draw-cursor-dot, .wire-draw-cursor-line');
            elements.forEach(function(el) { el.remove(); });
            $(this.svgElement).find('.schematic-terminal-circle').attr('stroke', '#fff').attr('stroke-width', '2').css('cursor', '');
        },

        showConnectionLabelDialogWithPath: function(sourceEqId, sourceTermId, targetEqId, targetTermId, pathData) {
            // Store path data for later use when creating connection
            this._pendingPathData = pathData;
            this.showConnectionLabelDialog(sourceEqId, sourceTermId, targetEqId, targetTermId);
        },

        showConnectionLabelDialog: function(sourceEqId, sourceTermId, targetEqId, targetTermId) {
            var self = this;

            // Find equipment labels for context
            var sourceEq = this.equipment.find(function(e) { return e.id == sourceEqId; });
            var targetEq = this.equipment.find(function(e) { return e.id == targetEqId; });

            var html = '<div id="schematic-conn-dialog" class="kundenkarte-modal visible">';
            html += '<div class="kundenkarte-modal-content" style="max-width:450px;">';
            html += '<div class="kundenkarte-modal-header"><h3>Verbindung erstellen</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body">';

            html += '<div style="margin-bottom:15px;padding:10px;background:#2a2a2a;border-radius:4px;">';
            html += '<strong style="color:#3498db;">' + this.escapeHtml((sourceEq ? sourceEq.label || sourceEq.type_label_short : 'Gerät')) + '</strong>';
            html += ' <i class="fa fa-arrow-right" style="color:#888;margin:0 10px;"></i> ';
            html += '<strong style="color:#27ae60;">' + this.escapeHtml((targetEq ? targetEq.label || targetEq.type_label_short : 'Gerät')) + '</strong>';
            html += '</div>';

            html += '<div class="form-group" style="margin-bottom:12px;">';
            html += '<label style="display:block;margin-bottom:5px;color:#aaa;">Bezeichnung / Stromkreis</label>';
            html += '<input type="text" id="conn-label" class="flat" style="width:100%;padding:8px;" placeholder="z.B. Küche Steckdosen, Bad Licht, L1">';
            html += '</div>';

            html += '<div class="form-group" style="margin-bottom:12px;">';
            html += '<label style="display:block;margin-bottom:5px;color:#aaa;">Typ (optional)</label>';
            html += '<div style="display:flex;gap:8px;flex-wrap:wrap;">';

            var typePresets = ['L1', 'L2', 'L3', 'N', 'PE', 'L1N', '3P'];
            typePresets.forEach(function(t) {
                var color = self.PHASE_COLORS[t] || self.COLORS.connection;
                html += '<button type="button" class="conn-type-btn" data-type="' + t + '" data-color="' + color + '" ';
                html += 'style="padding:5px 12px;background:' + color + ';color:#fff;border:none;border-radius:3px;cursor:pointer;font-size:12px;">';
                html += t + '</button>';
            });

            html += '</div>';
            html += '<input type="hidden" id="conn-type" value="L1N">';
            html += '<input type="hidden" id="conn-color" value="' + this.COLORS.connection + '">';
            html += '</div>';

            html += '<div class="form-group">';
            html += '<label style="display:block;margin-bottom:5px;color:#aaa;">Kabel (optional)</label>';
            html += '<div style="display:flex;gap:8px;">';
            html += '<input type="text" id="conn-medium" class="flat" style="flex:1;padding:8px;" placeholder="z.B. NYM-J 3x1.5">';
            html += '<input type="text" id="conn-length" class="flat" style="width:80px;padding:8px;" placeholder="Länge">';
            html += '</div>';
            html += '</div>';

            html += '</div>';
            html += '<div class="kundenkarte-modal-footer">';
            html += '<button type="button" class="button" id="conn-save"><i class="fa fa-check"></i> Erstellen</button> ';
            html += '<button type="button" class="button" id="conn-cancel">Abbrechen</button>';
            html += '</div></div></div>';

            $('body').append(html);

            // Type preset buttons
            $('.conn-type-btn').on('click', function() {
                $('.conn-type-btn').css('outline', 'none');
                $(this).css('outline', '2px solid #fff');
                $('#conn-type').val($(this).data('type'));
                $('#conn-color').val($(this).data('color'));
            });

            // Save
            $('#conn-save').on('click', function() {
                var label = $('#conn-label').val();
                var connType = $('#conn-type').val();
                var color = $('#conn-color').val();
                var medium = $('#conn-medium').val();
                var length = $('#conn-length').val();

                // Check if there's a manually drawn path
                var pathData = self._pendingPathData || null;
                self._pendingPathData = null;

                self.createConnection(sourceEqId, sourceTermId, targetEqId, targetTermId, {
                    label: label,
                    type: connType,
                    color: color,
                    medium: medium,
                    length: length,
                    pathData: pathData
                });

                $('#schematic-conn-dialog').remove();
                self.cancelSelection();
            });

            // Cancel
            $('#conn-cancel, .kundenkarte-modal-close').on('click', function() {
                $('#schematic-conn-dialog').remove();
                self.cancelSelection();
            });

            // Focus label input
            setTimeout(function() { $('#conn-label').focus(); }, 100);
        },

        updateConnectionPreview: function(e) {
            if (!this.selectedTerminal) return;

            var $svg = $(this.svgElement);
            var offset = $svg.offset();
            var x = e.pageX - offset.left;
            var y = e.pageY - offset.top;

            var $terminal = this.selectedTerminal.element;
            var transform = $terminal.attr('transform');
            var match = transform.match(/translate\(([^,]+),([^)]+)\)/);
            if (match) {
                var startX = parseFloat(match[1]);
                var startY = parseFloat(match[2]);

                var $preview = $svg.find('.schematic-connection-preview');
                $preview.attr({
                    x1: startX,
                    y1: startY,
                    x2: x,
                    y2: y
                });
            }
        },

        cancelSelection: function() {
            if (this.selectedTerminal) {
                this.selectedTerminal.element.find('.schematic-terminal-circle')
                    .attr('stroke', '#fff')
                    .attr('stroke-width', '1.5');
            }
            this.selectedTerminal = null;
            $('.schematic-connection-preview').hide();
            this.hideMessage();
        },

        createConnection: function(sourceEqId, sourceTermId, targetEqId, targetTermId, options) {
            var self = this;
            options = options || {};

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'create',
                    fk_source: sourceEqId,
                    source_terminal_id: sourceTermId,
                    fk_target: targetEqId,
                    target_terminal_id: targetTermId,
                    connection_type: options.type || 'L1N',
                    color: options.color || self.COLORS.connection,
                    output_label: options.label || '',
                    medium_type: options.medium || '',
                    medium_length: options.length || '',
                    path_data: options.pathData || '',  // Save manual path to database
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Verbindung erstellt!', 'success');
                        self.loadConnections();
                    } else {
                        self.showMessage('Fehler: ' + response.error, 'error');
                    }
                },
                error: function() {
                    self.showMessage('Netzwerkfehler', 'error');
                }
            });
        },

        deleteConnection: function(connId) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'delete',
                    connection_id: connId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.hideConnectionPopup();
                        self.showMessage('Verbindung gelöscht', 'success');
                        self.loadConnections();
                    }
                }
            });
        },

        // Show terminal context menu - choice between Anschlusspunkt (input) and Abgang (output)
        showOutputDialog: function(eqId, termId, x, y) {
            var self = this;

            // Remove any existing popup
            this.hideConnectionPopup();
            this.hideEquipmentPopup();
            $('.schematic-terminal-menu').remove();
            $('.schematic-output-dialog').remove();

            // Check for existing connections on this terminal
            var existingInput = this.connections.find(function(c) {
                return !c.fk_source && c.fk_target == eqId && c.target_terminal_id === termId;
            });
            var existingOutput = this.connections.find(function(c) {
                return c.fk_source == eqId && c.source_terminal_id === termId && !c.fk_target;
            });

            // Show context menu
            var html = '<div class="schematic-terminal-menu" style="' +
                'position:fixed;left:' + x + 'px;top:' + y + 'px;' +
                'background:#2d2d44;border:1px solid #555;border-radius:6px;' +
                'box-shadow:0 4px 15px rgba(0,0,0,0.5);z-index:100001;min-width:180px;overflow:hidden;">';

            // Anschlusspunkt (Input) option
            html += '<div class="terminal-menu-item terminal-menu-input" style="' +
                'padding:12px 15px;cursor:pointer;display:flex;align-items:center;gap:10px;' +
                'border-bottom:1px solid #444;color:#fff;' + (existingInput ? 'background:#1a4a1a;' : '') + '">';
            html += '<i class="fas fa-arrow-down" style="color:#f39c12;"></i>';
            html += '<span>Anschlusspunkt (L1/L2/L3)</span>';
            if (existingInput) html += '<i class="fas fa-check" style="margin-left:auto;color:#27ae60;"></i>';
            html += '</div>';

            // Abgang (Output) option
            html += '<div class="terminal-menu-item terminal-menu-output" style="' +
                'padding:12px 15px;cursor:pointer;display:flex;align-items:center;gap:10px;color:#fff;' +
                (existingOutput ? 'background:#1a4a1a;' : '') + '">';
            html += '<i class="fas fa-arrow-up" style="color:#3498db;"></i>';
            html += '<span>Abgang (Verbraucher/N)</span>';
            if (existingOutput) html += '<i class="fas fa-check" style="margin-left:auto;color:#27ae60;"></i>';
            html += '</div>';

            html += '</div>';

            $('body').append(html);

            // Hover effect
            $('.terminal-menu-item').hover(
                function() { $(this).css('background', '#3a3a5a'); },
                function() {
                    var $item = $(this);
                    if ($item.hasClass('terminal-menu-input') && existingInput) {
                        $item.css('background', '#1a4a1a');
                    } else if ($item.hasClass('terminal-menu-output') && existingOutput) {
                        $item.css('background', '#1a4a1a');
                    } else {
                        $item.css('background', '');
                    }
                }
            );

            // Click handlers
            $('.terminal-menu-input').on('click', function() {
                $('.schematic-terminal-menu').remove();
                self.showInputDialog(eqId, termId, x, y, existingInput);
            });

            $('.terminal-menu-output').on('click', function() {
                $('.schematic-terminal-menu').remove();
                self.showAbgangDialog(eqId, termId, x, y, existingOutput);
            });

            // Close on click outside
            setTimeout(function() {
                $(document).one('click', function() {
                    $('.schematic-terminal-menu').remove();
                });
            }, 100);

            // Close on Escape
            $(document).one('keydown.terminalMenu', function(e) {
                if (e.key === 'Escape') {
                    $('.schematic-terminal-menu').remove();
                }
            });
        },

        // Show dialog for creating an INPUT connection (Anschlusspunkt for L1, L2, L3)
        showInputDialog: function(eqId, termId, x, y, existingInput) {
            var self = this;
            $('.schematic-output-dialog').remove();

            var html = '<div class="schematic-output-dialog" style="' +
                'position:fixed;left:' + x + 'px;top:' + y + 'px;' +
                'background:#2d2d44;border:1px solid #555;border-radius:8px;padding:15px;' +
                'box-shadow:0 4px 20px rgba(0,0,0,0.5);z-index:100001;min-width:280px;">';

            html += '<h4 style="margin:0 0 12px 0;color:#fff;font-size:14px;">' +
                '<i class="fas fa-arrow-down" style="color:#f39c12;"></i> Anschlusspunkt (Eingang)</h4>';

            // Phase selection
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;color:#aaa;font-size:11px;margin-bottom:3px;">Phase:</label>';
            html += '<select class="input-phase" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            ['L1', 'L2', 'L3', '3P', '3P+N', 'PE'].forEach(function(p) {
                var selected = existingInput && existingInput.connection_type === p ? ' selected' : '';
                html += '<option value="' + p + '"' + selected + '>' + p + '</option>';
            });
            html += '</select>';
            html += '</div>';

            // Bezeichnung (optional)
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;color:#aaa;font-size:11px;margin-bottom:3px;">Bezeichnung (optional):</label>';
            html += '<input type="text" class="input-label" placeholder="z.B. Zähler, EVU" value="' +
                self.escapeHtml(existingInput ? existingInput.output_label || '' : '') + '" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;">';
            html += '</div>';

            // Buttons
            html += '<div style="display:flex;gap:8px;justify-content:flex-end;">';
            if (existingInput) {
                html += '<button type="button" class="input-delete-btn" data-id="' + existingInput.id + '" ' +
                    'style="background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:8px 14px;cursor:pointer;">' +
                    '<i class="fa fa-trash"></i></button>';
            }
            html += '<button type="button" class="input-cancel-btn" ' +
                'style="background:#555;color:#fff;border:none;border-radius:4px;padding:8px 14px;cursor:pointer;">Abbrechen</button>';
            html += '<button type="button" class="input-save-btn" ' +
                'style="background:#f39c12;color:#fff;border:none;border-radius:4px;padding:8px 14px;cursor:pointer;">' +
                '<i class="fa fa-check"></i> ' + (existingInput ? 'Aktualisieren' : 'Erstellen') + '</button>';
            html += '</div></div>';

            $('body').append(html);

            $('.input-cancel-btn').on('click', function() { $('.schematic-output-dialog').remove(); });
            $('.input-delete-btn').on('click', function() {
                var id = $(this).data('id');
                $('.schematic-output-dialog').remove();
                self.deleteConnection(id);
            });
            $('.input-save-btn').on('click', function() {
                var phase = $('.input-phase').val();
                var label = $('.input-label').val();
                if (existingInput) {
                    self.updateInput(existingInput.id, phase, label);
                } else {
                    self.createInput(eqId, termId, phase, label);
                }
                $('.schematic-output-dialog').remove();
            });

            $(document).one('keydown.inputDialog', function(e) {
                if (e.key === 'Escape') $('.schematic-output-dialog').remove();
            });
        },

        // Show dialog for creating an OUTPUT connection (Abgang for Verbraucher, N)
        showAbgangDialog: function(eqId, termId, x, y, existingOutput) {
            var self = this;
            $('.schematic-output-dialog').remove();

            // First load medium types from database
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/medium_types.php',
                data: { action: 'list_grouped', system_id: 0 },
                dataType: 'json',
                success: function(response) {
                    self.renderAbgangDialog(eqId, termId, x, y, existingOutput, response.success ? response.groups : []);
                },
                error: function() {
                    // Fallback with empty types
                    self.renderAbgangDialog(eqId, termId, x, y, existingOutput, []);
                }
            });
        },

        // Render the Abgang dialog with loaded medium types
        renderAbgangDialog: function(eqId, termId, x, y, existingOutput, mediumGroups) {
            var self = this;

            var html = '<div class="schematic-output-dialog" style="' +
                'position:fixed;left:' + x + 'px;top:' + y + 'px;' +
                'background:#2d2d44;border:1px solid #555;border-radius:8px;padding:15px;' +
                'box-shadow:0 4px 20px rgba(0,0,0,0.5);z-index:100001;min-width:320px;max-width:400px;">';

            html += '<h4 style="margin:0 0 12px 0;color:#fff;font-size:14px;">' +
                '<i class="fas fa-arrow-up" style="color:#3498db;"></i> Abgang (Ausgang)</h4>';

            // Bezeichnung (Label)
            html += '<div style="margin-bottom:10px;">';
            html += '<label style="display:block;color:#aaa;font-size:11px;margin-bottom:3px;">Bezeichnung (Verbraucher):</label>';
            html += '<input type="text" class="output-label" placeholder="z.B. Küche Steckdosen" value="' +
                self.escapeHtml(existingOutput ? existingOutput.output_label || '' : '') + '" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;">';
            html += '</div>';

            // Kabeltyp (from database)
            html += '<div style="margin-bottom:10px;">';
            html += '<label style="display:block;color:#aaa;font-size:11px;margin-bottom:3px;">Kabeltyp:</label>';
            html += '<select class="output-cable-type" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            html += '<option value="">-- Auswählen --</option>';

            if (mediumGroups && mediumGroups.length > 0) {
                mediumGroups.forEach(function(group) {
                    html += '<optgroup label="' + self.escapeHtml(group.category_label) + '">';
                    group.types.forEach(function(t) {
                        var selected = existingOutput && existingOutput.medium_type === t.ref ? ' selected' : '';
                        var specs = t.available_specs && t.available_specs.length > 0 ? ' data-specs=\'' + JSON.stringify(t.available_specs) + '\'' : '';
                        var defSpec = t.default_spec ? ' data-default="' + self.escapeHtml(t.default_spec) + '"' : '';
                        html += '<option value="' + self.escapeHtml(t.ref) + '"' + selected + specs + defSpec + '>' +
                            self.escapeHtml(t.label) + '</option>';
                    });
                    html += '</optgroup>';
                });
            } else {
                // Fallback
                ['NYM-J', 'NYY-J', 'H07V-K', 'CAT6', 'CAT7'].forEach(function(t) {
                    var selected = existingOutput && existingOutput.medium_type === t ? ' selected' : '';
                    html += '<option value="' + t + '"' + selected + '>' + t + '</option>';
                });
            }
            html += '</select></div>';

            // Spezifikation (Querschnitt) - dynamic based on selected cable type
            html += '<div style="margin-bottom:10px;">';
            html += '<label style="display:block;color:#aaa;font-size:11px;margin-bottom:3px;">Querschnitt/Typ:</label>';
            html += '<select class="output-cable-spec" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            html += '<option value="">-- Zuerst Kabeltyp wählen --</option>';
            html += '</select></div>';

            // Länge
            html += '<div style="margin-bottom:10px;">';
            html += '<label style="display:block;color:#aaa;font-size:11px;margin-bottom:3px;">Länge (m):</label>';
            html += '<input type="text" class="output-length" placeholder="z.B. 15, ca. 20" value="' +
                self.escapeHtml(existingOutput ? existingOutput.medium_length || '' : '') + '" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;">';
            html += '</div>';

            // Phase type
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;color:#aaa;font-size:11px;margin-bottom:3px;">Phase/Anschluss:</label>';
            html += '<select class="output-phase-type" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            ['L1N', 'L2N', 'L3N', 'N', '3P+N', 'PE', 'DATA'].forEach(function(p) {
                var selected = existingOutput && existingOutput.connection_type === p ? ' selected' : '';
                html += '<option value="' + p + '"' + selected + '>' + p + '</option>';
            });
            html += '</select></div>';

            // Buttons
            html += '<div style="display:flex;gap:8px;justify-content:flex-end;">';
            if (existingOutput) {
                html += '<button type="button" class="output-delete-btn" data-id="' + existingOutput.id + '" ' +
                    'style="background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:8px 14px;cursor:pointer;">' +
                    '<i class="fa fa-trash"></i></button>';
            }
            html += '<button type="button" class="output-cancel-btn" ' +
                'style="background:#555;color:#fff;border:none;border-radius:4px;padding:8px 14px;cursor:pointer;">Abbrechen</button>';
            html += '<button type="button" class="output-save-btn" ' +
                'style="background:#3498db;color:#fff;border:none;border-radius:4px;padding:8px 14px;cursor:pointer;">' +
                '<i class="fa fa-check"></i> ' + (existingOutput ? 'Aktualisieren' : 'Erstellen') + '</button>';
            html += '</div></div>';

            $('body').append(html);
            $('.output-label').focus();

            // Update specs dropdown when cable type changes
            $('.output-cable-type').on('change', function() {
                var $opt = $(this).find('option:selected');
                var specs = $opt.data('specs');
                var defSpec = $opt.data('default');
                var $specSelect = $('.output-cable-spec');

                $specSelect.empty();
                if (specs && specs.length > 0) {
                    specs.forEach(function(s) {
                        var selected = (existingOutput && existingOutput.medium_spec === s) || (!existingOutput && s === defSpec) ? ' selected' : '';
                        $specSelect.append('<option value="' + self.escapeHtml(s) + '"' + selected + '>' + self.escapeHtml(s) + '</option>');
                    });
                } else {
                    $specSelect.append('<option value="">--</option>');
                }
            });

            // Trigger change to populate specs if editing
            if (existingOutput && existingOutput.medium_type) {
                $('.output-cable-type').val(existingOutput.medium_type).trigger('change');
                if (existingOutput.medium_spec) {
                    $('.output-cable-spec').val(existingOutput.medium_spec);
                }
            }

            $('.output-cancel-btn').on('click', function() { $('.schematic-output-dialog').remove(); });
            $('.output-delete-btn').on('click', function() {
                var id = $(this).data('id');
                $('.schematic-output-dialog').remove();
                self.deleteConnection(id);
            });
            $('.output-save-btn').on('click', function() {
                var label = $('.output-label').val();
                var cableType = $('.output-cable-type').val();
                var cableSpec = $('.output-cable-spec').val();
                var cableLength = $('.output-length').val();
                var phaseType = $('.output-phase-type').val();

                if (existingOutput) {
                    self.updateOutput(existingOutput.id, label, cableType, cableSpec, phaseType, cableLength);
                } else {
                    self.createOutput(eqId, termId, label, cableType, cableSpec, phaseType, cableLength);
                }
                $('.schematic-output-dialog').remove();
            });

            $(document).one('keydown.outputDialog', function(e) {
                if (e.key === 'Escape') $('.schematic-output-dialog').remove();
            });

            // Adjust position
            setTimeout(function() {
                var $dialog = $('.schematic-output-dialog');
                var dw = $dialog.outerWidth(), dh = $dialog.outerHeight();
                var ww = $(window).width(), wh = $(window).height();
                if (x + dw > ww - 10) $dialog.css('left', (ww - dw - 10) + 'px');
                if (y + dh > wh - 10) $dialog.css('top', (wh - dh - 10) + 'px');
            }, 10);
        },

        // Create INPUT connection (external source -> equipment terminal)
        createInput: function(eqId, termId, phase, label) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'create',
                    fk_source: '',  // NULL = external input
                    source_terminal_id: '',
                    fk_target: eqId,
                    target_terminal_id: termId,
                    connection_type: phase,
                    output_label: label,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Anschlusspunkt erstellt', 'success');
                        self.loadConnections();
                    } else {
                        self.showMessage('Fehler: ' + response.error, 'error');
                    }
                }
            });
        },

        // Update INPUT connection
        updateInput: function(connId, phase, label) {
            var self = this;
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'update',
                    connection_id: connId,
                    connection_type: phase,
                    output_label: label,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Anschlusspunkt aktualisiert', 'success');
                        self.loadConnections();
                    } else {
                        self.showMessage('Fehler: ' + response.error, 'error');
                    }
                }
            });
        },

        // Create a new cable output (no target, fk_target = NULL)
        createOutput: function(eqId, termId, label, cableType, cableSpec, phaseType, cableLength) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'create',
                    fk_source: eqId,
                    source_terminal_id: termId,
                    fk_target: '',  // NULL target = output/endpoint
                    target_terminal_id: '',
                    connection_type: phaseType || 'L1N',
                    output_label: label,
                    medium_type: cableType,
                    medium_spec: cableSpec,
                    medium_length: cableLength || '',
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Abgang erstellt', 'success');
                        self.loadConnections();
                    } else {
                        self.showMessage('Fehler: ' + response.error, 'error');
                    }
                },
                error: function() {
                    self.showMessage('Netzwerkfehler', 'error');
                }
            });
        },

        // Update existing output
        updateOutput: function(connId, label, cableType, cableSpec, phaseType, cableLength) {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'update',
                    connection_id: connId,
                    connection_type: phaseType || 'L1N',
                    output_label: label,
                    medium_type: cableType,
                    medium_spec: cableSpec,
                    medium_length: cableLength || '',
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Abgang aktualisiert', 'success');
                        self.loadConnections();
                    } else {
                        self.showMessage('Fehler: ' + response.error, 'error');
                    }
                },
                error: function() {
                    self.showMessage('Netzwerkfehler', 'error');
                }
            });
        },

        showConnectionPopup: function(connId, x, y) {
            var self = this;
            console.log('showConnectionPopup called with connId:', connId, 'type:', typeof connId);
            console.log('Available connections:', this.connections.map(function(c) { return c.id; }));

            // Remove any existing popup
            this.hideConnectionPopup();

            // Find connection data (convert to int for comparison)
            var connIdInt = parseInt(connId);
            var conn = this.connections.find(function(c) { return parseInt(c.id) === connIdInt; });
            console.log('Found connection:', conn);
            if (!conn) {
                console.warn('Connection not found for id:', connId);
                return;
            }

            // Create popup - use very high z-index to ensure visibility
            console.log('Creating popup at position:', x, y);
            var popupHtml = '<div class="schematic-connection-popup" data-connection-id="' + connId + '" style="' +
                'position:fixed !important;left:' + x + 'px !important;top:' + y + 'px !important;' +
                'background:#2d2d44 !important;border:2px solid #3498db !important;border-radius:6px;padding:10px;' +
                'box-shadow:0 4px 20px rgba(0,0,0,0.8);z-index:2147483647 !important;display:flex !important;gap:8px;' +
                'visibility:visible !important;opacity:1 !important;">';

            // Edit button
            popupHtml += '<button type="button" class="schematic-popup-edit" style="' +
                'background:#3498db;color:#fff;border:none;border-radius:4px;padding:8px 12px;' +
                'cursor:pointer;font-size:13px;display:flex;align-items:center;gap:5px;">' +
                '<i class="fas fa-edit"></i> Bearbeiten</button>';

            // Delete button
            popupHtml += '<button type="button" class="schematic-popup-delete" style="' +
                'background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:8px 12px;' +
                'cursor:pointer;font-size:13px;display:flex;align-items:center;gap:5px;">' +
                '<i class="fas fa-trash"></i> Löschen</button>';

            popupHtml += '</div>';

            $('body').append(popupHtml);
            console.log('Popup appended to body, checking if exists:', $('.schematic-connection-popup').length);

            // Bind button events
            $('.schematic-popup-edit').on('click', function(e) {
                e.stopPropagation();
                self.editConnection(connId);
            });

            $('.schematic-popup-delete').on('click', function(e) {
                e.stopPropagation();
                self.hideConnectionPopup();
                self.deleteConnection(connId);
            });

            // Adjust position if popup goes off screen
            var $popup = $('.schematic-connection-popup');
            var popupWidth = $popup.outerWidth();
            var popupHeight = $popup.outerHeight();
            var windowWidth = $(window).width();
            var windowHeight = $(window).height();

            if (x + popupWidth > windowWidth - 10) {
                $popup.css('left', (x - popupWidth) + 'px');
            }
            if (y + popupHeight > windowHeight - 10) {
                $popup.css('top', (y - popupHeight) + 'px');
            }
        },

        hideConnectionPopup: function() {
            $('.schematic-connection-popup').remove();
        },

        editConnection: function(connId) {
            var self = this;

            // Hide popup first
            this.hideConnectionPopup();

            // Find connection data
            var conn = this.connections.find(function(c) { return c.id == connId; });
            if (!conn) return;

            // Build edit dialog
            var dialogHtml = '<div class="schematic-edit-dialog" style="' +
                'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);' +
                'background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;' +
                'box-shadow:0 8px 24px rgba(0,0,0,0.5);z-index:10001;min-width:350px;">';

            dialogHtml += '<h3 style="margin:0 0 15px 0;color:#fff;font-size:16px;">Verbindung bearbeiten</h3>';

            // Connection type
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Typ:</label>';
            dialogHtml += '<select class="edit-connection-type" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            dialogHtml += '<option value="">-- Kein Typ --</option>';
            ['L1', 'L2', 'L3', 'N', 'PE', 'L1N', '3P', '3P+N'].forEach(function(t) {
                dialogHtml += '<option value="' + t + '"' + (conn.connection_type === t ? ' selected' : '') + '>' + t + '</option>';
            });
            dialogHtml += '</select></div>';

            // Output label
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Bezeichnung:</label>';
            dialogHtml += '<input type="text" class="edit-output-label" value="' + self.escapeHtml(conn.output_label || '') + '" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Color
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Farbe:</label>';
            dialogHtml += '<input type="color" class="edit-connection-color" value="' + (conn.color || '#3498db') + '" ' +
                'style="width:100%;height:36px;padding:2px;border:1px solid #555;border-radius:4px;background:#1e1e1e;cursor:pointer;"/></div>';

            // Medium type
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Medium:</label>';
            dialogHtml += '<input type="text" class="edit-medium-type" value="' + self.escapeHtml(conn.medium_type || '') + '" ' +
                'placeholder="z.B. NYM-J, CAT6" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Medium spec
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Spezifikation:</label>';
            dialogHtml += '<input type="text" class="edit-medium-spec" value="' + self.escapeHtml(conn.medium_spec || '') + '" ' +
                'placeholder="z.B. 3x1.5mm²" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Medium length
            dialogHtml += '<div style="margin-bottom:15px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Länge:</label>';
            dialogHtml += '<input type="text" class="edit-medium-length" value="' + self.escapeHtml(conn.medium_length || '') + '" ' +
                'placeholder="z.B. 5m" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Buttons
            dialogHtml += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            dialogHtml += '<button type="button" class="edit-dialog-cancel" style="' +
                'background:#555;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Abbrechen</button>';
            dialogHtml += '<button type="button" class="edit-dialog-save" style="' +
                'background:#27ae60;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Speichern</button>';
            dialogHtml += '</div>';

            dialogHtml += '</div>';

            // Overlay
            var overlayHtml = '<div class="schematic-edit-overlay" style="' +
                'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:10000;"></div>';

            $('body').append(overlayHtml).append(dialogHtml);

            // Bind events
            $('.edit-dialog-cancel, .schematic-edit-overlay').on('click', function() {
                self.closeEditDialog();
            });

            $('.edit-dialog-save').on('click', function() {
                self.saveConnectionEdit(connId);
            });

            // Enter key to save
            $('.schematic-edit-dialog input').on('keypress', function(e) {
                if (e.which === 13) {
                    self.saveConnectionEdit(connId);
                }
            });
        },

        closeEditDialog: function() {
            $('.schematic-edit-dialog, .schematic-edit-overlay').remove();
        },

        saveConnectionEdit: function(connId) {
            var self = this;

            var data = {
                action: 'update',
                connection_id: connId,
                connection_type: $('.edit-connection-type').val(),
                output_label: $('.edit-output-label').val(),
                color: $('.edit-connection-color').val(),
                medium_type: $('.edit-medium-type').val(),
                medium_spec: $('.edit-medium-spec').val(),
                medium_length: $('.edit-medium-length').val(),
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.closeEditDialog();
                        self.showMessage('Verbindung aktualisiert', 'success');
                        self.loadConnections();
                    } else {
                        self.showMessage(response.error || 'Fehler beim Speichern', 'error');
                    }
                },
                error: function() {
                    self.showMessage('Netzwerkfehler', 'error');
                }
            });
        },

        clearAllConnections: function() {
            var self = this;

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_connection.php',
                method: 'POST',
                data: {
                    action: 'clear_all',
                    anlage_id: this.anlageId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.connections = [];
                        self.renderConnections();
                        self.showMessage('Alle Verbindungen gelöscht', 'success');
                    }
                }
            });
        },

        // Equipment Popup functions
        showEquipmentPopup: function(equipmentId, x, y) {
            var self = this;

            // Remove any existing popup
            this.hideEquipmentPopup();
            this.hideConnectionPopup();

            // Find equipment data
            var eq = this.equipment.find(function(e) { return parseInt(e.id) === parseInt(equipmentId); });
            if (!eq) {
                console.warn('Equipment not found for id:', equipmentId);
                return;
            }

            // Create popup
            var popupHtml = '<div class="schematic-equipment-popup" data-equipment-id="' + equipmentId + '" style="' +
                'position:fixed;left:' + x + 'px;top:' + y + 'px;' +
                'background:#2d2d44;border:2px solid #3498db;border-radius:6px;padding:10px;' +
                'box-shadow:0 4px 20px rgba(0,0,0,0.6);z-index:2147483647;display:flex;flex-direction:column;gap:8px;min-width:150px;">';

            // Equipment info
            popupHtml += '<div style="color:#fff;font-size:12px;border-bottom:1px solid #555;padding-bottom:6px;margin-bottom:2px;">';
            popupHtml += '<strong>' + self.escapeHtml(eq.type_label || eq.label || 'Equipment') + '</strong>';
            if (eq.label && eq.type_label) {
                popupHtml += '<br><span style="color:#aaa;">' + self.escapeHtml(eq.label) + '</span>';
            }
            popupHtml += '</div>';

            // Buttons row
            popupHtml += '<div style="display:flex;gap:8px;">';

            // Edit button
            popupHtml += '<button type="button" class="schematic-eq-popup-edit" style="' +
                'flex:1;background:#3498db;color:#fff;border:none;border-radius:4px;padding:8px 12px;' +
                'cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;gap:5px;">' +
                '<i class="fas fa-edit"></i> Bearbeiten</button>';

            // Delete button
            popupHtml += '<button type="button" class="schematic-eq-popup-delete" style="' +
                'flex:1;background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:8px 12px;' +
                'cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;gap:5px;">' +
                '<i class="fas fa-trash"></i> Löschen</button>';

            popupHtml += '</div></div>';

            $('body').append(popupHtml);

            // Bind button events
            $('.schematic-eq-popup-edit').on('click', function(e) {
                e.stopPropagation();
                self.editEquipment(equipmentId);
            });

            $('.schematic-eq-popup-delete').on('click', function(e) {
                e.stopPropagation();
                self.hideEquipmentPopup();
                self.deleteEquipment(equipmentId);
            });

            // Adjust position if popup goes off screen
            var $popup = $('.schematic-equipment-popup');
            var popupWidth = $popup.outerWidth();
            var popupHeight = $popup.outerHeight();
            var windowWidth = $(window).width();
            var windowHeight = $(window).height();

            if (x + popupWidth > windowWidth - 10) {
                $popup.css('left', (x - popupWidth) + 'px');
            }
            if (y + popupHeight > windowHeight - 10) {
                $popup.css('top', (y - popupHeight) + 'px');
            }
        },

        hideEquipmentPopup: function() {
            $('.schematic-equipment-popup').remove();
        },

        showCarrierPopup: function(carrierId, x, y) {
            var self = this;

            // Remove any existing popup
            this.hideCarrierPopup();
            this.hideEquipmentPopup();
            this.hideConnectionPopup();

            // Find carrier data
            var carrier = this.carriers.find(function(c) { return parseInt(c.id) === parseInt(carrierId); });
            if (!carrier) {
                console.warn('Carrier not found for id:', carrierId);
                return;
            }

            // Create popup
            var popupHtml = '<div class="schematic-carrier-popup" data-carrier-id="' + carrierId + '" style="' +
                'position:fixed;left:' + x + 'px;top:' + y + 'px;' +
                'background:#2d2d44;border:2px solid #f39c12;border-radius:6px;padding:10px;' +
                'box-shadow:0 4px 20px rgba(0,0,0,0.6);z-index:2147483647;display:flex;flex-direction:column;gap:8px;min-width:180px;">';

            // Carrier info
            popupHtml += '<div style="color:#fff;font-size:12px;border-bottom:1px solid #555;padding-bottom:6px;margin-bottom:2px;">';
            popupHtml += '<strong>' + self.escapeHtml(carrier.label || 'Hutschiene') + '</strong>';
            popupHtml += '<br><span style="color:#aaa;">' + (carrier.total_te || 12) + ' TE</span>';
            popupHtml += '</div>';

            // Buttons row
            popupHtml += '<div style="display:flex;gap:8px;">';

            // Edit button
            popupHtml += '<button type="button" class="schematic-carrier-popup-edit" style="' +
                'flex:1;background:#f39c12;color:#fff;border:none;border-radius:4px;padding:8px 12px;' +
                'cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;gap:5px;">' +
                '<i class="fas fa-edit"></i> Bearbeiten</button>';

            // Delete button
            popupHtml += '<button type="button" class="schematic-carrier-popup-delete" style="' +
                'flex:1;background:#e74c3c;color:#fff;border:none;border-radius:4px;padding:8px 12px;' +
                'cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center;gap:5px;">' +
                '<i class="fas fa-trash"></i> Löschen</button>';

            popupHtml += '</div></div>';

            $('body').append(popupHtml);

            // Bind button events
            $('.schematic-carrier-popup-edit').on('click', function(e) {
                e.stopPropagation();
                self.editCarrier(carrierId);
            });

            $('.schematic-carrier-popup-delete').on('click', function(e) {
                e.stopPropagation();
                self.hideCarrierPopup();
                self.deleteCarrier(carrierId);
            });

            // Adjust position if popup goes off screen
            var $popup = $('.schematic-carrier-popup');
            var popupWidth = $popup.outerWidth();
            var popupHeight = $popup.outerHeight();
            var windowWidth = $(window).width();
            var windowHeight = $(window).height();

            if (x + popupWidth > windowWidth - 10) {
                $popup.css('left', (x - popupWidth) + 'px');
            }
            if (y + popupHeight > windowHeight - 10) {
                $popup.css('top', (y - popupHeight) + 'px');
            }
        },

        hideCarrierPopup: function() {
            $('.schematic-carrier-popup').remove();
        },

        editCarrier: function(carrierId) {
            var self = this;

            // Hide popup first
            this.hideCarrierPopup();

            // Find carrier data
            var carrier = this.carriers.find(function(c) { return parseInt(c.id) === parseInt(carrierId); });
            if (!carrier) return;

            // Load panels for dropdown
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment_panel.php',
                data: { action: 'list', anlage_id: self.anlageId },
                dataType: 'json',
                success: function(response) {
                    var panels = response.success ? response.panels : [];
                    self.showEditCarrierDialog(carrier, panels);
                }
            });
        },

        showEditCarrierDialog: function(carrier, panels) {
            var self = this;

            // Remove existing dialog
            $('.schematic-edit-overlay').remove();

            var html = '<div class="schematic-edit-overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.7);z-index:2147483647;display:flex;align-items:center;justify-content:center;">';
            html += '<div class="schematic-edit-dialog" style="background:#2d2d44;border:2px solid #f39c12;border-radius:8px;padding:20px;min-width:350px;max-width:450px;">';

            html += '<h3 style="color:#fff;margin:0 0 15px 0;padding-bottom:10px;border-bottom:1px solid #555;">Hutschiene bearbeiten</h3>';

            html += '<table style="width:100%;border-collapse:collapse;">';

            // Label
            html += '<tr><td style="color:#aaa;padding:8px 0;">Bezeichnung</td>';
            html += '<td><input type="text" class="carrier-edit-label" value="' + self.escapeHtml(carrier.label || '') + '" style="width:100%;padding:8px;background:#1a1a2e;border:1px solid #555;border-radius:4px;color:#fff;"></td></tr>';

            // Total TE
            html += '<tr><td style="color:#aaa;padding:8px 0;">Kapazität (TE)</td>';
            html += '<td><input type="number" class="carrier-edit-total-te" value="' + (carrier.total_te || 12) + '" min="1" max="72" style="width:100%;padding:8px;background:#1a1a2e;border:1px solid #555;border-radius:4px;color:#fff;"></td></tr>';

            // Panel dropdown
            if (panels && panels.length > 0) {
                html += '<tr><td style="color:#aaa;padding:8px 0;">Feld</td>';
                html += '<td><select class="carrier-edit-panel" style="width:100%;padding:8px;background:#1a1a2e;border:1px solid #555;border-radius:4px;color:#fff;">';
                html += '<option value="0">-- Kein Feld --</option>';
                panels.forEach(function(p) {
                    var selected = (carrier.panel_id == p.id) ? ' selected' : '';
                    html += '<option value="' + p.id + '"' + selected + '>' + self.escapeHtml(p.label) + '</option>';
                });
                html += '</select></td></tr>';
            }

            html += '</table>';

            // Buttons
            html += '<div style="margin-top:20px;display:flex;gap:10px;justify-content:flex-end;">';
            html += '<button type="button" class="edit-dialog-save" style="background:#f39c12;color:#fff;border:none;border-radius:4px;padding:10px 20px;cursor:pointer;font-size:14px;"><i class="fas fa-save"></i> Speichern</button>';
            html += '<button type="button" class="edit-dialog-cancel" style="background:#555;color:#fff;border:none;border-radius:4px;padding:10px 20px;cursor:pointer;font-size:14px;">Abbrechen</button>';
            html += '</div>';

            html += '</div></div>';

            $('body').append(html);

            // Save handler
            $('.edit-dialog-save').on('click', function() {
                var label = $('.carrier-edit-label').val();
                var totalTe = parseInt($('.carrier-edit-total-te').val()) || 12;
                var panelId = parseInt($('.carrier-edit-panel').val()) || 0;

                $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                    method: 'POST',
                    data: {
                        action: 'update',
                        carrier_id: carrier.id,
                        label: label,
                        total_te: totalTe,
                        panel_id: panelId
                    },
                    dataType: 'json',
                    success: function(response) {
                        if (response.success) {
                            $('.schematic-edit-overlay').remove();
                            self.loadData(); // Reload all data
                        } else {
                            alert('Fehler: ' + (response.error || 'Unbekannter Fehler'));
                        }
                    }
                });
            });

            // Cancel handler
            $('.edit-dialog-cancel, .schematic-edit-overlay').on('click', function(e) {
                if (e.target === this) {
                    $('.schematic-edit-overlay').remove();
                }
            });
        },

        deleteCarrier: function(carrierId) {
            var self = this;

            // Find carrier data for confirmation
            var carrier = this.carriers.find(function(c) { return parseInt(c.id) === parseInt(carrierId); });
            var carrierLabel = carrier ? (carrier.label || 'Hutschiene') : 'Hutschiene';

            this.showConfirmDialog('Hutschiene löschen', 'Hutschiene "' + carrierLabel + '" wirklich löschen? Alle darauf platzierten Geräte werden ebenfalls gelöscht!', function() {
                $.ajax({
                    url: baseUrl + '/custom/kundenkarte/ajax/equipment_carrier.php',
                    method: 'POST',
                    data: {
                        action: 'delete',
                        carrier_id: carrierId
                    },
                    dataType: 'json',
                    success: function(response) {
                        if (response.success) {
                            self.loadData(); // Reload all data
                        } else {
                            alert('Fehler: ' + (response.error || 'Unbekannter Fehler'));
                        }
                    }
                });
            });
        },

        editEquipment: function(equipmentId) {
            var self = this;

            // Hide popup first
            this.hideEquipmentPopup();

            // Find equipment data
            var eq = this.equipment.find(function(e) { return parseInt(e.id) === parseInt(equipmentId); });
            if (!eq) return;

            // Load equipment types for dropdown
            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                data: { action: 'get_types', system_id: 1 },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showEditEquipmentDialog(eq, response.types);
                    }
                }
            });
        },

        showEditEquipmentDialog: function(eq, types) {
            var self = this;

            var dialogHtml = '<div class="schematic-edit-overlay" style="' +
                'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);z-index:100000;"></div>';

            dialogHtml += '<div class="schematic-edit-dialog" style="' +
                'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);' +
                'background:#2d2d44;border:1px solid #555;border-radius:8px;padding:20px;' +
                'box-shadow:0 8px 24px rgba(0,0,0,0.5);z-index:100001;min-width:350px;">';

            dialogHtml += '<h3 style="margin:0 0 15px 0;color:#fff;font-size:16px;">Equipment bearbeiten</h3>';

            // Equipment type
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Typ:</label>';
            dialogHtml += '<select class="edit-equipment-type" style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;">';
            types.forEach(function(t) {
                var selected = (parseInt(t.id) === parseInt(eq.type_id)) ? ' selected' : '';
                dialogHtml += '<option value="' + t.id + '" data-width="' + t.width_te + '"' + selected + '>' + self.escapeHtml(t.label) + ' (' + t.width_te + ' TE)</option>';
            });
            dialogHtml += '</select></div>';

            // Label
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Bezeichnung:</label>';
            dialogHtml += '<input type="text" class="edit-equipment-label" value="' + self.escapeHtml(eq.label || '') + '" ' +
                'placeholder="z.B. Küche Licht" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Position
            dialogHtml += '<div style="margin-bottom:12px;">';
            dialogHtml += '<label style="display:block;color:#aaa;font-size:12px;margin-bottom:4px;">Position (TE):</label>';
            dialogHtml += '<input type="number" class="edit-equipment-position" value="' + (eq.position_te || 1) + '" min="1" ' +
                'style="width:100%;padding:8px;border:1px solid #555;border-radius:4px;background:#1e1e1e;color:#fff;box-sizing:border-box;"/></div>';

            // Buttons
            dialogHtml += '<div style="display:flex;gap:10px;justify-content:flex-end;">';
            dialogHtml += '<button type="button" class="edit-dialog-cancel" style="' +
                'background:#555;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Abbrechen</button>';
            dialogHtml += '<button type="button" class="edit-dialog-save" style="' +
                'background:#27ae60;color:#fff;border:none;border-radius:4px;padding:10px 16px;cursor:pointer;">Speichern</button>';
            dialogHtml += '</div>';

            dialogHtml += '</div>';

            $('body').append(dialogHtml);

            // Bind events
            $('.edit-dialog-cancel, .schematic-edit-overlay').on('click', function() {
                $('.schematic-edit-dialog, .schematic-edit-overlay').remove();
            });

            $('.edit-dialog-save').on('click', function() {
                self.saveEquipmentEdit(eq.id);
            });

            // Enter key to save
            $('.schematic-edit-dialog input').on('keypress', function(e) {
                if (e.which === 13) {
                    self.saveEquipmentEdit(eq.id);
                }
            });
        },

        saveEquipmentEdit: function(equipmentId) {
            var self = this;

            var data = {
                action: 'update',
                equipment_id: equipmentId,
                type_id: $('.edit-equipment-type').val(),
                label: $('.edit-equipment-label').val(),
                position_te: $('.edit-equipment-position').val(),
                token: $('input[name="token"]').val()
            };

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: data,
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        $('.schematic-edit-dialog, .schematic-edit-overlay').remove();
                        self.showMessage('Equipment aktualisiert', 'success');
                        self.loadData();
                    } else {
                        self.showMessage(response.error || 'Fehler beim Speichern', 'error');
                    }
                },
                error: function() {
                    self.showMessage('Netzwerkfehler', 'error');
                }
            });
        },

        deleteEquipment: function(equipmentId) {
            var self = this;

            this.hideEquipmentPopup();

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'delete',
                    equipment_id: equipmentId,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        self.showMessage('Equipment gelöscht', 'success');
                        // Remove from local array instead of reloading everything
                        self.equipment = self.equipment.filter(function(e) {
                            return String(e.id) !== String(equipmentId);
                        });
                        // Also remove connections involving this equipment
                        self.connections = self.connections.filter(function(c) {
                            return String(c.fk_source) !== String(equipmentId) &&
                                   String(c.fk_target) !== String(equipmentId);
                        });
                        self.render();
                    } else {
                        self.showMessage(response.error || 'Fehler', 'error');
                    }
                }
            });
        },

        // Block dragging
        startDragBlock: function($block, e) {
            var eqId = $block.data('equipment-id');
            var carrierId = $block.data('carrier-id');
            var eq = this.equipment.find(function(e) { return String(e.id) === String(eqId); });
            var carrier = this.carriers.find(function(c) { return String(c.id) === String(carrierId); });

            if (!eq || !carrier) {
                console.log('startDragBlock: Equipment or carrier not found', eqId, carrierId);
                return;
            }

            if (typeof carrier._x === 'undefined') {
                console.log('startDragBlock: Carrier has no _x position', carrier);
                return;
            }

            var $svg = $(this.svgElement);
            var offset = $svg.offset();

            this.dragState = {
                type: 'block',
                equipmentId: eqId,
                equipment: eq,
                carrier: carrier,
                element: $block,
                startX: e.pageX,
                startY: e.pageY,
                originalTE: parseInt(eq.position_te) || 1,
                originalX: parseFloat(carrier._x) + ((parseInt(eq.position_te) || 1) - 1) * this.TE_WIDTH + 2,
                originalY: eq._y
            };

            $block.addClass('dragging');
        },

        updateDragBlock: function(e) {
            if (!this.dragState || this.dragState.type !== 'block') return;

            var dx = e.pageX - this.dragState.startX;
            var dy = e.pageY - this.dragState.startY;

            // Find target carrier based on mouse position (supports cross-panel drag)
            var $svg = $(this.svgElement);
            var svgOffset = $svg.offset();
            var mouseY = (e.pageY - svgOffset.top) / this.scale;
            var mouseX = (e.pageX - svgOffset.left) / this.scale;

            // Find closest carrier (checks both Y and X for cross-panel support)
            var targetCarrier = this.findClosestCarrier(mouseY, mouseX);
            if (!targetCarrier) targetCarrier = this.dragState.carrier;

            // Calculate TE position on target carrier based on absolute X position
            var relativeX = mouseX - targetCarrier._x;
            var newTE = Math.round(relativeX / this.TE_WIDTH) + 1;

            // Clamp to valid range on TARGET carrier
            var maxTE = (parseInt(targetCarrier.total_te) || 12) - (parseInt(this.dragState.equipment.width_te) || 1) + 1;
            newTE = Math.max(1, Math.min(newTE, maxTE));

            // Calculate visual position
            var newX, newY;
            if (targetCarrier.id === this.dragState.carrier.id) {
                // Same carrier - use offset from original
                var teOffset = newTE - this.dragState.originalTE;
                newX = this.dragState.originalX + teOffset * this.TE_WIDTH;
                newY = this.dragState.originalY;
            } else {
                // Different carrier - calculate new position
                newX = parseFloat(targetCarrier._x) + (newTE - 1) * this.TE_WIDTH + 2;
                // Block Y position: carrier Y - half block height (block sits on rail)
                newY = parseFloat(targetCarrier._y) - this.BLOCK_HEIGHT / 2;
            }

            if (!isNaN(newX) && !isNaN(newY)) {
                this.dragState.element.attr('transform', 'translate(' + newX + ',' + newY + ')');
            }

            // Store target info
            this.dragState.newTE = newTE;
            this.dragState.targetCarrier = targetCarrier;

            // Highlight target carrier
            this.highlightTargetCarrier(targetCarrier.id);
        },

        findClosestCarrier: function(mouseY, mouseX) {
            var self = this;
            var closest = null;
            var closestDist = Infinity;

            this.carriers.forEach(function(carrier) {
                if (typeof carrier._y === 'undefined' || typeof carrier._x === 'undefined') return;
                var carrierY = parseFloat(carrier._y);
                var carrierX = parseFloat(carrier._x);
                var carrierWidth = (carrier.total_te || 12) * self.TE_WIDTH;

                // Calculate distance - prioritize Y but also check X is within carrier bounds
                var distY = Math.abs(mouseY - carrierY);

                // Check if mouseX is within carrier X range (with some tolerance)
                var tolerance = 50;
                var inXRange = mouseX >= (carrierX - tolerance) && mouseX <= (carrierX + carrierWidth + tolerance);

                // Use combined distance for carriers in range, otherwise penalize
                var dist = inXRange ? distY : distY + 1000;

                if (dist < closestDist) {
                    closestDist = dist;
                    closest = carrier;
                }
            });

            // Only return if within reasonable distance (half rail spacing)
            if (closestDist < this.RAIL_SPACING / 2) {
                return closest;
            }
            return null;
        },

        highlightTargetCarrier: function(carrierId) {
            // Remove previous highlights
            $('.schematic-rail').removeClass('drop-target');
            // Add highlight to target
            $('.schematic-rail[data-carrier-id="' + carrierId + '"]').addClass('drop-target');
        },

        endDragBlock: function(e) {
            if (!this.dragState || this.dragState.type !== 'block') return;

            var newTE = this.dragState.newTE || this.dragState.originalTE;
            var element = this.dragState.element;
            var targetCarrier = this.dragState.targetCarrier || this.dragState.carrier;
            var originalCarrier = this.dragState.carrier;

            // Remove highlight
            $('.schematic-rail').removeClass('drop-target');

            // Check if carrier changed or position changed
            var carrierChanged = String(targetCarrier.id) !== String(originalCarrier.id);
            var positionChanged = newTE !== this.dragState.originalTE;

            console.log('endDragBlock: carrierChanged=', carrierChanged, 'positionChanged=', positionChanged,
                'newTE=', newTE, 'originalTE=', this.dragState.originalTE,
                'targetCarrier=', targetCarrier.id, 'originalCarrier=', originalCarrier.id);

            if (carrierChanged) {
                // Move to different carrier
                this.moveEquipmentToCarrier(this.dragState.equipment.id, targetCarrier.id, newTE);
            } else if (positionChanged) {
                // Same carrier, different position
                this.updateEquipmentPosition(this.dragState.equipment.id, newTE);
            } else {
                // No change, reset visual position
                console.log('No change detected, resetting position');
                element.attr('transform', 'translate(' + this.dragState.originalX + ',' + this.dragState.originalY + ')');
            }

            element.removeClass('dragging');
            this.dragState = null;
        },

        moveEquipmentToCarrier: function(eqId, newCarrierId, newTE) {
            var self = this;

            console.log('moveEquipmentToCarrier:', eqId, 'to carrier', newCarrierId, 'position', newTE);

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'move_to_carrier',
                    equipment_id: eqId,
                    carrier_id: newCarrierId,
                    position_te: newTE,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    console.log('moveEquipmentToCarrier response:', response);
                    if (response.success) {
                        self.showMessage('Equipment verschoben', 'success');
                        self.loadData(); // Reload to update all positions
                    } else {
                        self.showMessage(response.error || 'Fehler beim Verschieben', 'error');
                        self.render();
                    }
                },
                error: function(xhr, status, error) {
                    console.log('moveEquipmentToCarrier error:', status, error, xhr.responseText);
                    self.showMessage('Netzwerkfehler', 'error');
                    self.render();
                }
            });
        },

        updateEquipmentPosition: function(eqId, newTE) {
            var self = this;

            console.log('updateEquipmentPosition:', eqId, newTE);

            $.ajax({
                url: baseUrl + '/custom/kundenkarte/ajax/equipment.php',
                method: 'POST',
                data: {
                    action: 'update_position',
                    equipment_id: eqId,
                    position_te: newTE,
                    token: $('input[name="token"]').val()
                },
                dataType: 'json',
                success: function(response) {
                    if (response.success) {
                        // Update local data and re-render
                        var eq = self.equipment.find(function(e) { return String(e.id) === String(eqId); });
                        if (eq) {
                            eq.position_te = newTE;
                        }
                        // Full re-render to ensure carrier positions are set
                        self.render();
                    } else {
                        // Revert visual position on error
                        self.showMessage(response.error || 'Position nicht verfügbar', 'error');
                        self.render();
                    }
                },
                error: function() {
                    // Revert on error
                    self.showMessage('Netzwerkfehler', 'error');
                    self.render();
                }
            });
        },

        // Zoom functions
        setZoom: function(newScale) {
            // Clamp zoom level between 0.25 and 2.0
            this.scale = Math.max(0.25, Math.min(2.0, newScale));

            // Apply transform to wrapper (SVG + controls)
            var $wrapper = $('.schematic-zoom-wrapper');
            if ($wrapper.length) {
                $wrapper.css('transform', 'scale(' + this.scale + ')');
                $wrapper.css('transform-origin', '0 0');

                // Update container size to account for scaling
                var $svg = $wrapper.find('.schematic-svg');
                if ($svg.length) {
                    var actualWidth = $svg.attr('width') * this.scale;
                    var actualHeight = $svg.attr('height') * this.scale;
                    $wrapper.parent().css({
                        'min-width': actualWidth + 'px',
                        'min-height': actualHeight + 'px'
                    });
                }
            }

            // Update zoom display
            this.updateZoomDisplay();
        },

        zoomToFit: function() {
            if (!this.svgElement) return;

            var $canvas = $('.schematic-editor-canvas');
            var $svg = $(this.svgElement);

            var canvasWidth = $canvas.width() - 40; // Padding
            var canvasHeight = $canvas.height() - 40;
            var svgWidth = parseFloat($svg.attr('width')) || 800;
            var svgHeight = parseFloat($svg.attr('height')) || 600;

            // Calculate scale to fit both dimensions
            var scaleX = canvasWidth / svgWidth;
            var scaleY = canvasHeight / svgHeight;
            var newScale = Math.min(scaleX, scaleY, 1); // Don't zoom in beyond 100%

            this.setZoom(newScale);
        },

        updateZoomDisplay: function() {
            var percentage = Math.round(this.scale * 100);
            $('.schematic-zoom-level').text(percentage + '%');
        },

        showMessage: function(text, type) {
            var $msg = $('.schematic-message');
            if (!$msg.length) {
                // Create permanent status bar with fixed height
                $msg = $('<div class="schematic-message" style="min-height:28px;display:block !important;visibility:visible;"></div>');
                $('.schematic-editor-canvas').prepend($msg);
            }

            // Clear any pending hide timeout
            if (this.messageTimeout) {
                clearTimeout(this.messageTimeout);
                this.messageTimeout = null;
            }

            $msg.removeClass('success error warning info').addClass(type).text(text).css('opacity', 1);

            if (type === 'success' || type === 'error') {
                this.messageTimeout = setTimeout(function() {
                    // Don't hide, just clear the message text but keep the bar
                    $msg.removeClass('success error warning info').addClass('info').text('Bereit');
                }, 2500);
            }
        },

        hideMessage: function() {
            var $msg = $('.schematic-message');
            // Don't hide, just reset to default state
            $msg.removeClass('success error warning info').addClass('info').text('Bereit');
        },

        escapeHtml: function(text) {
            if (!text) return '';
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }
    };

    // Initialize on DOM ready
    $(document).ready(function() {
        KundenKarte.Tree.init();
        KundenKarte.Favorites.init();
        KundenKarte.SystemTabs.init();
        KundenKarte.IconPicker.init();
        KundenKarte.DynamicFields.init();

        // Initialize Equipment if container exists
        var $equipmentContainer = $('.kundenkarte-equipment-container');
        if ($equipmentContainer.length) {
            var anlageId = $equipmentContainer.data('anlage-id');
            var systemId = $equipmentContainer.data('system-id');
            KundenKarte.Equipment.init(anlageId, systemId);

            // Initialize Schematic Editor
            KundenKarte.SchematicEditor.init(anlageId);
        }

        // Initialize Anlage Connection handlers
        KundenKarte.AnlageConnection.init();
    });

    // ===========================================
    // Anlage Connections (cable connections between tree elements)
    // ===========================================
    KundenKarte.AnlageConnection = {
        baseUrl: '',

        init: function() {
            var self = this;
            this.baseUrl = (typeof baseUrl !== 'undefined') ? baseUrl : '';
            this.tooltipTimer = null;

            // Create tooltip container if not exists
            if ($('#kundenkarte-conn-tooltip').length === 0) {
                $('body').append('<div id="kundenkarte-conn-tooltip" class="kundenkarte-conn-tooltip"></div>');
            }

            // Add connection button
            $(document).on('click', '.anlage-connection-add', function(e) {
                e.preventDefault();
                var anlageId = $(this).data('anlage-id');
                var socId = $(this).data('soc-id');
                var systemId = $(this).data('system-id');
                self.showConnectionDialog(anlageId, socId, systemId, null);
            });

            // Edit connection (old style)
            $(document).on('click', '.anlage-connection-edit', function(e) {
                e.preventDefault();
                var connId = $(this).data('id');
                self.loadAndEditConnection(connId);
            });

            // Delete connection (old style)
            $(document).on('click', '.anlage-connection-delete', function(e) {
                e.preventDefault();
                var connId = $(this).data('id');
                self.deleteConnection(connId);
            });

            // Hover on connection row - show tooltip
            $(document).on('mouseenter', '.kundenkarte-tree-conn', function(e) {
                var $el = $(this);
                var tooltipData = $el.data('conn-tooltip');
                if (tooltipData) {
                    self.showConnTooltip(e, tooltipData);
                }
            });

            $(document).on('mousemove', '.kundenkarte-tree-conn', function(e) {
                self.moveConnTooltip(e);
            });

            $(document).on('mouseleave', '.kundenkarte-tree-conn', function() {
                self.hideConnTooltip();
            });
        },

        showConnTooltip: function(e, data) {
            var $tooltip = $('#kundenkarte-conn-tooltip');

            var html = '<div class="kundenkarte-conn-tooltip-header">';
            html += '<i class="fa fa-plug"></i>';
            html += '<span class="conn-route">' + this.escapeHtml(data.source || '') + ' → ' + this.escapeHtml(data.target || '') + '</span>';
            html += '</div>';

            html += '<div class="kundenkarte-conn-tooltip-fields">';

            if (data.medium_type) {
                html += '<span class="field-label">Kabeltyp:</span>';
                html += '<span class="field-value">' + this.escapeHtml(data.medium_type) + '</span>';
            }
            if (data.medium_spec) {
                html += '<span class="field-label">Querschnitt:</span>';
                html += '<span class="field-value">' + this.escapeHtml(data.medium_spec) + '</span>';
            }
            if (data.medium_length) {
                html += '<span class="field-label">Länge:</span>';
                html += '<span class="field-value">' + this.escapeHtml(data.medium_length) + '</span>';
            }
            if (data.medium_color) {
                html += '<span class="field-label">Farbe:</span>';
                html += '<span class="field-value">' + this.escapeHtml(data.medium_color) + '</span>';
            }
            if (data.route_description) {
                html += '<span class="field-label">Route:</span>';
                html += '<span class="field-value">' + this.escapeHtml(data.route_description) + '</span>';
            }
            if (data.installation_date) {
                html += '<span class="field-label">Installiert:</span>';
                html += '<span class="field-value">' + this.escapeHtml(data.installation_date) + '</span>';
            }
            if (data.label) {
                html += '<span class="field-label">Beschreibung:</span>';
                html += '<span class="field-value">' + this.escapeHtml(data.label) + '</span>';
            }

            html += '</div>';
            html += '<div class="kundenkarte-conn-tooltip-hint"><i class="fa fa-mouse-pointer"></i>Klicken zum Bearbeiten</div>';

            $tooltip.html(html);
            this.moveConnTooltip(e);
            $tooltip.addClass('visible');
        },

        moveConnTooltip: function(e) {
            var $tooltip = $('#kundenkarte-conn-tooltip');
            var x = e.pageX + 15;
            var y = e.pageY + 10;

            // Keep tooltip in viewport
            var tooltipWidth = $tooltip.outerWidth();
            var tooltipHeight = $tooltip.outerHeight();
            var windowWidth = $(window).width();
            var windowHeight = $(window).height();
            var scrollTop = $(window).scrollTop();

            if (x + tooltipWidth > windowWidth - 20) {
                x = e.pageX - tooltipWidth - 15;
            }
            if (y + tooltipHeight > scrollTop + windowHeight - 20) {
                y = e.pageY - tooltipHeight - 10;
            }

            $tooltip.css({ left: x, top: y });
        },

        hideConnTooltip: function() {
            $('#kundenkarte-conn-tooltip').removeClass('visible');
        },

        loadAndEditConnection: function(connId) {
            var self = this;
            console.log('loadAndEditConnection called with connId:', connId);
            $.ajax({
                url: this.baseUrl + '/custom/kundenkarte/ajax/anlage_connection.php',
                data: { action: 'get', connection_id: connId },
                dataType: 'json',
                success: function(response) {
                    console.log('Connection fetch response:', response);
                    if (response.success) {
                        // Get soc_id and system_id from the tree container or add button
                        var $tree = $('.kundenkarte-tree');
                        var socId = $tree.data('socid');
                        var systemId = $tree.data('system');
                        console.log('From tree element - socId:', socId, 'systemId:', systemId, '$tree.length:', $tree.length);

                        // Fallback to add button if tree doesn't have data
                        if (!socId) {
                            var $btn = $('.anlage-connection-add').first();
                            socId = $btn.data('soc-id');
                            systemId = $btn.data('system-id');
                            console.log('From fallback button - socId:', socId, 'systemId:', systemId);
                        }

                        self.showConnectionDialog(response.connection.fk_source, socId, systemId, response.connection);
                    } else {
                        KundenKarte.showAlert('Fehler', response.error || 'Fehler beim Laden');
                    }
                }
            });
        },

        showConnectionDialog: function(anlageId, socId, systemId, existingConn) {
            var self = this;
            console.log('showConnectionDialog called:', {anlageId: anlageId, socId: socId, systemId: systemId, existingConn: existingConn});

            // Ensure systemId is a number (0 if not set)
            systemId = systemId || 0;

            // First load anlagen list and medium types
            $.when(
                $.ajax({
                    url: this.baseUrl + '/custom/kundenkarte/ajax/anlage.php',
                    data: { action: 'tree', socid: socId, system_id: systemId },
                    dataType: 'json'
                }),
                $.ajax({
                    url: this.baseUrl + '/custom/kundenkarte/ajax/medium_types.php',
                    data: { action: 'list_grouped', system_id: systemId },
                    dataType: 'json'
                })
            ).done(function(anlagenResp, mediumResp) {
                console.log('AJAX responses:', {anlagenResp: anlagenResp, mediumResp: mediumResp});
                var anlagen = anlagenResp[0].success ? anlagenResp[0].tree : [];
                var mediumGroups = mediumResp[0].success ? mediumResp[0].groups : [];
                console.log('Parsed data:', {anlagen: anlagen, mediumGroups: mediumGroups});
                self.renderConnectionDialog(anlageId, anlagen, mediumGroups, existingConn);
            });
        },

        flattenTree: function(tree, result, prefix) {
            result = result || [];
            prefix = prefix || '';
            for (var i = 0; i < tree.length; i++) {
                var node = tree[i];
                result.push({
                    id: node.id,
                    label: prefix + (node.label || node.ref),
                    ref: node.ref
                });
                if (node.children && node.children.length > 0) {
                    this.flattenTree(node.children, result, prefix + '  ');
                }
            }
            return result;
        },

        renderConnectionDialog: function(anlageId, anlagenTree, mediumGroups, existingConn) {
            var self = this;
            console.log('renderConnectionDialog - anlagenTree:', anlagenTree);
            var anlagen = this.flattenTree(anlagenTree);
            console.log('renderConnectionDialog - flattened anlagen:', anlagen);

            // Remove existing dialog
            $('#anlage-connection-dialog').remove();

            var isEdit = existingConn !== null;
            var title = isEdit ? 'Verbindung bearbeiten' : 'Neue Verbindung';

            var html = '<div id="anlage-connection-dialog" class="kundenkarte-modal visible">';
            html += '<div class="kundenkarte-modal-content" style="max-width:500px;">';
            html += '<div class="kundenkarte-modal-header"><h3>' + title + '</h3>';
            html += '<span class="kundenkarte-modal-close">&times;</span></div>';
            html += '<div class="kundenkarte-modal-body" style="padding:20px;">';

            // Source
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;font-weight:bold;margin-bottom:3px;">Von (Quelle):</label>';
            html += '<select class="conn-source flat" style="width:100%;">';
            for (var i = 0; i < anlagen.length; i++) {
                var sel = (existingConn && parseInt(existingConn.fk_source) === parseInt(anlagen[i].id)) || (!existingConn && parseInt(anlagen[i].id) === parseInt(anlageId)) ? ' selected' : '';
                html += '<option value="' + anlagen[i].id + '"' + sel + '>' + self.escapeHtml(anlagen[i].label) + '</option>';
            }
            html += '</select></div>';

            // Target
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;font-weight:bold;margin-bottom:3px;">Nach (Ziel):</label>';
            html += '<select class="conn-target flat" style="width:100%;">';
            html += '<option value="">-- Ziel wählen --</option>';
            for (var i = 0; i < anlagen.length; i++) {
                var sel = (existingConn && parseInt(existingConn.fk_target) === parseInt(anlagen[i].id)) ? ' selected' : '';
                html += '<option value="' + anlagen[i].id + '"' + sel + '>' + self.escapeHtml(anlagen[i].label) + '</option>';
            }
            html += '</select></div>';

            // Medium type
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;font-weight:bold;margin-bottom:3px;">Kabeltyp:</label>';
            html += '<select class="conn-medium-type flat" style="width:100%;">';
            html += '<option value="">-- Freitext oder wählen --</option>';
            for (var g = 0; g < mediumGroups.length; g++) {
                html += '<optgroup label="' + self.escapeHtml(mediumGroups[g].category_label) + '">';
                var types = mediumGroups[g].types;
                for (var t = 0; t < types.length; t++) {
                    var sel = (existingConn && existingConn.fk_medium_type == types[t].id) ? ' selected' : '';
                    html += '<option value="' + types[t].id + '" data-specs=\'' + JSON.stringify(types[t].available_specs || []) + '\' data-default="' + self.escapeHtml(types[t].default_spec || '') + '"' + sel + '>' + self.escapeHtml(types[t].label) + '</option>';
                }
                html += '</optgroup>';
            }
            html += '</select>';
            html += '<input type="text" class="conn-medium-text flat" placeholder="oder Freitext eingeben" style="width:100%;margin-top:5px;" value="' + self.escapeHtml(existingConn ? existingConn.medium_type_text || '' : '') + '">';
            html += '</div>';

            // Spec
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;font-weight:bold;margin-bottom:3px;">Querschnitt/Typ:</label>';
            html += '<select class="conn-spec flat" style="width:100%;"><option value="">--</option></select>';
            html += '<input type="text" class="conn-spec-text flat" placeholder="oder Freitext" style="width:100%;margin-top:5px;" value="' + self.escapeHtml(existingConn ? existingConn.medium_spec || '' : '') + '">';
            html += '</div>';

            // Length
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;font-weight:bold;margin-bottom:3px;">Länge:</label>';
            html += '<input type="text" class="conn-length flat" placeholder="z.B. 15m, ca. 20m" style="width:100%;" value="' + self.escapeHtml(existingConn ? existingConn.medium_length || '' : '') + '">';
            html += '</div>';

            // Label
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;font-weight:bold;margin-bottom:3px;">Bezeichnung (optional):</label>';
            html += '<input type="text" class="conn-label flat" placeholder="z.B. Zuleitung HAK" style="width:100%;" value="' + self.escapeHtml(existingConn ? existingConn.label || '' : '') + '">';
            html += '</div>';

            // Route description
            html += '<div style="margin-bottom:12px;">';
            html += '<label style="display:block;font-weight:bold;margin-bottom:3px;">Verlegungsweg (optional):</label>';
            html += '<textarea class="conn-route flat" rows="2" style="width:100%;" placeholder="z.B. Erdverlegung, Kabelkanal links">' + self.escapeHtml(existingConn ? existingConn.route_description || '' : '') + '</textarea>';
            html += '</div>';

            html += '</div>'; // modal-body

            // Footer
            html += '<div class="kundenkarte-modal-footer" style="display:flex;justify-content:flex-end;gap:10px;">';
            html += '<button type="button" class="button conn-cancel">Abbrechen</button>';
            html += '<button type="button" class="button button-primary conn-save"><i class="fa fa-check"></i> ' + (isEdit ? 'Aktualisieren' : 'Erstellen') + '</button>';
            html += '</div>';

            html += '</div></div>';

            $('body').append(html);

            // Spec dropdown update
            $('.conn-medium-type').on('change', function() {
                var $opt = $(this).find('option:selected');
                var specs = $opt.data('specs') || [];
                var defSpec = $opt.data('default') || '';
                var $specSelect = $('.conn-spec');
                $specSelect.empty().append('<option value="">--</option>');
                for (var i = 0; i < specs.length; i++) {
                    var sel = (existingConn && existingConn.medium_spec === specs[i]) || (!existingConn && specs[i] === defSpec) ? ' selected' : '';
                    $specSelect.append('<option value="' + self.escapeHtml(specs[i]) + '"' + sel + '>' + self.escapeHtml(specs[i]) + '</option>');
                }
            });

            // Trigger to populate specs if editing
            if (existingConn && existingConn.fk_medium_type) {
                $('.conn-medium-type').trigger('change');
                if (existingConn.medium_spec) {
                    $('.conn-spec').val(existingConn.medium_spec);
                }
            }

            // Close handlers
            $('.conn-cancel, #anlage-connection-dialog .kundenkarte-modal-close').on('click', function() {
                $('#anlage-connection-dialog').remove();
            });

            // Save handler
            $('.conn-save').on('click', function() {
                var data = {
                    fk_source: $('.conn-source').val(),
                    fk_target: $('.conn-target').val(),
                    fk_medium_type: $('.conn-medium-type').val(),
                    medium_type_text: $('.conn-medium-text').val(),
                    medium_spec: $('.conn-spec').val() || $('.conn-spec-text').val(),
                    medium_length: $('.conn-length').val(),
                    label: $('.conn-label').val(),
                    route_description: $('.conn-route').val(),
                    token: $('input[name="token"]').val()
                };

                if (!data.fk_target) {
                    KundenKarte.showAlert('Fehler', 'Bitte wählen Sie ein Ziel aus.');
                    return;
                }

                if (isEdit) {
                    data.action = 'update';
                    data.connection_id = existingConn.id;
                } else {
                    data.action = 'create';
                }

                $.ajax({
                    url: self.baseUrl + '/custom/kundenkarte/ajax/anlage_connection.php',
                    method: 'POST',
                    data: data,
                    dataType: 'json',
                    success: function(response) {
                        if (response.success) {
                            $('#anlage-connection-dialog').remove();
                            location.reload();
                        } else {
                            KundenKarte.showAlert('Fehler', response.error || 'Speichern fehlgeschlagen');
                        }
                    }
                });
            });
        },

        deleteConnection: function(connId) {
            var self = this;
            KundenKarte.showConfirm('Verbindung löschen', 'Möchten Sie diese Verbindung wirklich löschen?', function(confirmed) {
                if (confirmed) {
                    $.ajax({
                        url: self.baseUrl + '/custom/kundenkarte/ajax/anlage_connection.php',
                        method: 'POST',
                        data: {
                            action: 'delete',
                            connection_id: connId,
                            token: $('input[name="token"]').val()
                        },
                        dataType: 'json',
                        success: function(response) {
                            if (response.success) {
                                location.reload();
                            } else {
                                KundenKarte.showAlert('Fehler', response.error || 'Löschen fehlgeschlagen');
                            }
                        }
                    });
                }
            });
        },

        escapeHtml: function(text) {
            if (!text) return '';
            var div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }
    };

    // ===========================================
    // File Upload Dropzone
    // ===========================================

    KundenKarte.initFileDropzone = function() {
        var dropzone = document.getElementById('fileDropzone');
        var fileInput = document.getElementById('fileInput');
        var selectedFilesDiv = document.getElementById('selectedFiles');
        var uploadBtn = document.getElementById('uploadBtn');
        var fileCountSpan = document.getElementById('fileCount');
        var form = document.getElementById('fileUploadForm');

        if (!dropzone || !fileInput) return;

        var selectedFiles = [];

        // Click to open file dialog
        dropzone.addEventListener('click', function(e) {
            if (e.target.tagName !== 'A') {
                fileInput.click();
            }
        });

        // Drag & Drop handlers
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {
            dropzone.addEventListener(eventName, function(e) {
                e.preventDefault();
                e.stopPropagation();
            });
        });

        ['dragenter', 'dragover'].forEach(function(eventName) {
            dropzone.addEventListener(eventName, function() {
                dropzone.classList.add('dragover');
            });
        });

        ['dragleave', 'drop'].forEach(function(eventName) {
            dropzone.addEventListener(eventName, function() {
                dropzone.classList.remove('dragover');
            });
        });

        dropzone.addEventListener('drop', function(e) {
            var files = e.dataTransfer.files;
            handleFiles(files);
        });

        fileInput.addEventListener('change', function() {
            handleFiles(this.files);
        });

        function handleFiles(files) {
            for (var i = 0; i < files.length; i++) {
                var file = files[i];
                // Check for duplicates
                var isDuplicate = selectedFiles.some(function(f) {
                    return f.name === file.name && f.size === file.size;
                });
                if (!isDuplicate) {
                    selectedFiles.push(file);
                }
            }
            updateFileList();
        }

        function updateFileList() {
            selectedFilesDiv.innerHTML = '';

            if (selectedFiles.length === 0) {
                selectedFilesDiv.style.display = 'none';
                uploadBtn.style.display = 'none';
                return;
            }

            selectedFilesDiv.style.display = 'flex';
            uploadBtn.style.display = 'inline-block';
            fileCountSpan.textContent = selectedFiles.length;

            selectedFiles.forEach(function(file, index) {
                var fileDiv = document.createElement('div');
                fileDiv.className = 'kundenkarte-dropzone-file';

                var icon = getFileIcon(file.name);
                fileDiv.innerHTML = '<i class="fa ' + icon + '"></i> ' +
                    '<span>' + KundenKarte.AnlageConnection.escapeHtml(file.name) + '</span>' +
                    '<span class="remove-file" data-index="' + index + '"><i class="fa fa-times"></i></span>';

                selectedFilesDiv.appendChild(fileDiv);
            });

            // Add remove handlers
            selectedFilesDiv.querySelectorAll('.remove-file').forEach(function(btn) {
                btn.addEventListener('click', function(e) {
                    e.stopPropagation();
                    var idx = parseInt(this.getAttribute('data-index'));
                    selectedFiles.splice(idx, 1);
                    updateFileList();
                });
            });

            // Update file input with DataTransfer
            updateFileInput();
        }

        function updateFileInput() {
            var dt = new DataTransfer();
            selectedFiles.forEach(function(file) {
                dt.items.add(file);
            });
            fileInput.files = dt.files;
        }

        function getFileIcon(filename) {
            var ext = filename.split('.').pop().toLowerCase();
            if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'].indexOf(ext) !== -1) {
                return 'fa-image';
            } else if (ext === 'pdf') {
                return 'fa-file-pdf-o';
            } else if (['doc', 'docx'].indexOf(ext) !== -1) {
                return 'fa-file-word-o';
            } else if (['xls', 'xlsx'].indexOf(ext) !== -1) {
                return 'fa-file-excel-o';
            }
            return 'fa-file-o';
        }
    };

    // Auto-init on DOM ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', KundenKarte.initFileDropzone);
    } else {
        KundenKarte.initFileDropzone();
    }

    // ===========================================
    // Field Autocomplete
    // ===========================================

    KundenKarte.FieldAutocomplete = {
        baseUrl: '',
        activeInput: null,
        dropdown: null,
        debounceTimer: null,

        init: function(baseUrl) {
            this.baseUrl = baseUrl || '';
            this.createDropdown();
            this.bindEvents();
        },

        createDropdown: function() {
            // Create dropdown element if not exists
            if (!document.getElementById('kk-autocomplete-dropdown')) {
                var dropdown = document.createElement('div');
                dropdown.id = 'kk-autocomplete-dropdown';
                dropdown.className = 'kk-autocomplete-dropdown';
                dropdown.style.cssText = 'display:none;position:absolute;z-index:10000;background:#2d2d2d;border:1px solid #555;border-radius:4px;max-height:200px;overflow-y:auto;box-shadow:0 4px 12px rgba(0,0,0,0.3);';
                document.body.appendChild(dropdown);
                this.dropdown = dropdown;
            } else {
                this.dropdown = document.getElementById('kk-autocomplete-dropdown');
            }
        },

        bindEvents: function() {
            var self = this;

            // Delegate events for autocomplete inputs
            document.addEventListener('input', function(e) {
                if (e.target.classList.contains('kk-autocomplete')) {
                    self.onInput(e.target);
                }
            });

            document.addEventListener('focus', function(e) {
                if (e.target.classList.contains('kk-autocomplete')) {
                    self.onFocus(e.target);
                }
            }, true);

            document.addEventListener('blur', function(e) {
                if (e.target.classList.contains('kk-autocomplete')) {
                    // Delay to allow click on dropdown item
                    setTimeout(function() {
                        self.hideDropdown();
                    }, 200);
                }
            }, true);

            document.addEventListener('keydown', function(e) {
                if (e.target.classList.contains('kk-autocomplete') && self.dropdown.style.display !== 'none') {
                    self.onKeydown(e);
                }
            });

            // Click on dropdown item
            this.dropdown.addEventListener('click', function(e) {
                var item = e.target.closest('.kk-autocomplete-item');
                if (item) {
                    self.selectItem(item);
                }
            });
        },

        onInput: function(input) {
            var self = this;
            this.activeInput = input;

            clearTimeout(this.debounceTimer);
            this.debounceTimer = setTimeout(function() {
                self.fetchSuggestions(input);
            }, 150);
        },

        onFocus: function(input) {
            this.activeInput = input;
            if (input.value.length >= 1) {
                this.fetchSuggestions(input);
            }
        },

        onKeydown: function(e) {
            var items = this.dropdown.querySelectorAll('.kk-autocomplete-item');
            var activeItem = this.dropdown.querySelector('.kk-autocomplete-item.active');
            var activeIndex = -1;

            items.forEach(function(item, idx) {
                if (item.classList.contains('active')) activeIndex = idx;
            });

            if (e.key === 'ArrowDown') {
                e.preventDefault();
                if (activeIndex < items.length - 1) {
                    if (activeItem) activeItem.classList.remove('active');
                    items[activeIndex + 1].classList.add('active');
                    items[activeIndex + 1].scrollIntoView({ block: 'nearest' });
                }
            } else if (e.key === 'ArrowUp') {
                e.preventDefault();
                if (activeIndex > 0) {
                    if (activeItem) activeItem.classList.remove('active');
                    items[activeIndex - 1].classList.add('active');
                    items[activeIndex - 1].scrollIntoView({ block: 'nearest' });
                }
            } else if (e.key === 'Enter' && activeItem) {
                e.preventDefault();
                this.selectItem(activeItem);
            } else if (e.key === 'Escape') {
                this.hideDropdown();
            }
        },

        fetchSuggestions: function(input) {
            var self = this;
            var fieldCode = input.getAttribute('data-field-code');
            var typeId = input.getAttribute('data-type-id') || 0;
            var query = input.value;

            if (!fieldCode) return;

            $.ajax({
                url: this.baseUrl + '/custom/kundenkarte/ajax/field_autocomplete.php',
                method: 'GET',
                data: {
                    action: 'suggest',
                    field_code: fieldCode,
                    type_id: typeId,
                    query: query
                },
                dataType: 'json',
                success: function(response) {
                    if (response.suggestions && response.suggestions.length > 0) {
                        self.showSuggestions(input, response.suggestions, query);
                    } else {
                        self.hideDropdown();
                    }
                }
            });
        },

        showSuggestions: function(input, suggestions, query) {
            var self = this;
            var rect = input.getBoundingClientRect();

            this.dropdown.innerHTML = '';
            this.dropdown.style.top = (rect.bottom + window.scrollY) + 'px';
            this.dropdown.style.left = rect.left + 'px';
            this.dropdown.style.width = rect.width + 'px';
            this.dropdown.style.display = 'block';

            suggestions.forEach(function(suggestion, idx) {
                var item = document.createElement('div');
                item.className = 'kk-autocomplete-item';
                if (idx === 0) item.classList.add('active');
                item.style.cssText = 'padding:8px 12px;cursor:pointer;color:#e0e0e0;border-bottom:1px solid #444;';
                item.setAttribute('data-value', suggestion);

                // Highlight matching text
                var html = self.highlightMatch(suggestion, query);
                item.innerHTML = html;

                self.dropdown.appendChild(item);
            });

            // Hover effect
            this.dropdown.querySelectorAll('.kk-autocomplete-item').forEach(function(item) {
                item.addEventListener('mouseenter', function() {
                    self.dropdown.querySelectorAll('.kk-autocomplete-item').forEach(function(i) {
                        i.classList.remove('active');
                    });
                    item.classList.add('active');
                });
            });
        },

        highlightMatch: function(text, query) {
            if (!query) return text;
            var regex = new RegExp('(' + query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ')', 'gi');
            return text.replace(regex, '<strong style="color:#3498db;">$1</strong>');
        },

        selectItem: function(item) {
            var value = item.getAttribute('data-value');
            if (this.activeInput) {
                this.activeInput.value = value;
                // Trigger change event
                var event = new Event('change', { bubbles: true });
                this.activeInput.dispatchEvent(event);
            }
            this.hideDropdown();
        },

        hideDropdown: function() {
            if (this.dropdown) {
                this.dropdown.style.display = 'none';
            }
        }
    };

    // Auto-init autocomplete
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() {
            KundenKarte.FieldAutocomplete.init('');
        });
    } else {
        KundenKarte.FieldAutocomplete.init('');
    }

})();
