﻿{"id":2279,"date":"2025-10-22T07:25:23","date_gmt":"2025-10-22T07:25:23","guid":{"rendered":"https:\/\/liautoyerevan.am\/?page_id=2279"},"modified":"2026-04-13T06:06:26","modified_gmt":"2026-04-13T06:06:26","slug":"configurator-mega","status":"publish","type":"page","link":"https:\/\/liautoyerevan.am\/am\/configurator-mega\/","title":{"rendered":"Configurator MEGA"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"2279\" class=\"elementor elementor-2279\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3ec2409 e-con-full e-flex e-con e-parent\" data-id=\"3ec2409\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9568685 elementor-widget__width-inherit elementor-widget elementor-widget-html\" data-id=\"9568685\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n    <meta charset=\"UTF-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\r\n    <title>2026 Li Auto Configurator<\/title>\r\n    <style>\r\n        * {\r\n            margin: 0;\r\n            padding: 0;\r\n            box-sizing: border-box;\r\n        }\r\n\r\n        body {\r\n            font-family: 'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\r\n            background: #fafafa;\r\n            color: #1a1a1a;\r\n            line-height: 1.5;\r\n            overflow-x: hidden;\r\n            -webkit-font-smoothing: antialiased;\r\n            -moz-osx-font-smoothing: grayscale;\r\n            touch-action: manipulation;\r\n        }\r\n\r\n        .configurator {\r\n            width: 100%;\r\n            max-width: none;\r\n            margin: 0;\r\n            padding: 0;\r\n            height: 95vh;\r\n            display: flex;\r\n            background: white;\r\n        }\r\n\r\n        .car-studio {\r\n            flex: 0 0 60%;\r\n            height: 95vh;\r\n            position: relative;\r\n            background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            overflow: hidden;\r\n        }\r\n\r\n        .car-display {\r\n            width: 90%;\r\n            height: 85%;\r\n            position: relative;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n        }\r\n\r\n        .car-view {\r\n            position: absolute;\r\n            top: 2vh;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 100%;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            opacity: 0;\r\n            transition: opacity 0.6s ease;\r\n            pointer-events: none;\r\n        }\r\n\r\n            .car-view.active {\r\n                opacity: 1;\r\n                pointer-events: auto;\r\n            }\r\n\r\n\r\n        div#exteriorView {\r\n            top: 2vh;\r\n        }\r\n\r\n\r\n\r\n        .car-image {\r\n            max-width: 110% !important;\r\n            max-height: 110% !important;\r\n            height: auto !important;\r\n            object-fit: contain;\r\n            transition: transform 0.3s ease, opacity 0.3s ease;\r\n            user-select: none;\r\n            -webkit-user-select: none;\r\n            -moz-user-select: none;\r\n            -ms-user-select: none;\r\n            -webkit-user-drag: none;\r\n            -webkit-touch-callout: none;\r\n        }\r\n\r\n        \/* Interior images use cover to fill the viewport *\/\r\n        .interior-view .car-picture {\r\n            align-items: stretch !important;\r\n            justify-content: stretch !important;\r\n        }\r\n\r\n        .interior-view .car-image {\r\n            width: 100% !important;\r\n            height: 100% !important;\r\n            max-width: none !important;\r\n            max-height: none !important;\r\n            object-fit: cover !important;\r\n            object-position: center center !important;\r\n        }\r\n\r\n        \/* Crossfade support - stack picture elements *\/\r\n        .car-picture {\r\n            position: absolute;\r\n            top: 0;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 100%;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            transition: opacity 0.8s ease;\r\n        }\r\n\r\n        .car-picture.front {\r\n            z-index: 2;\r\n            opacity: 1;\r\n        }\r\n\r\n        .car-picture.back {\r\n            z-index: 1;\r\n            opacity: 0;\r\n        }\r\n\r\n        \/* Base scale for views - handled by JS zoom system *\/\r\n        @media (min-width: 769px) {\r\n            \/* Scales set by updateZoom(): exterior 1.2, interior 1.3 *\/\r\n        }\r\n\r\n        \/* Mobile scales handled by JS zoom system *\/\r\n        @media (max-width: 768px) {\r\n            .car-image {\r\n                transition: opacity 0.3s ease;\r\n            }\r\n\r\n            .interior-view .car-image {\r\n                \/* Keep cover behavior on mobile too *\/\r\n                width: 100% !important;\r\n                height: 100% !important;\r\n                max-width: none !important;\r\n                max-height: none !important;\r\n                object-fit: cover;\r\n            }\r\n        }\r\n\r\n        .image-skeleton {\r\n            position: absolute;\r\n            top: 50%;\r\n            left: 50%;\r\n            transform: translate(-50%, -50%);\r\n            width: 80%;\r\n            height: 60%;\r\n            background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);\r\n            background-size: 200% 100%;\r\n            animation: skeleton-loading 1.5s infinite;\r\n            border-radius: 8px;\r\n            opacity: 0;\r\n            transition: opacity 0.3s ease;\r\n        }\r\n\r\n            .image-skeleton.show {\r\n                opacity: 1;\r\n            }\r\n\r\n        @keyframes skeleton-loading {\r\n            0% {\r\n                background-position: 200% 0;\r\n            }\r\n\r\n            100% {\r\n                background-position: -200% 0;\r\n            }\r\n        }\r\n\r\n        .car-image-overlay {\r\n            position: absolute;\r\n            top: 0;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 100%;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            opacity: 0;\r\n            transition: opacity 0.4s ease;\r\n            pointer-events: none;\r\n        }\r\n\r\n            .car-image-overlay.active {\r\n                opacity: 1;\r\n            }\r\n\r\n        .car-info-overlay {\r\n            position: absolute;\r\n            top: 40px;\r\n            left: 40px;\r\n            background: rgba(255,255,255,0.95);\r\n            backdrop-filter: blur(10px);\r\n            padding: 16px 24px;\r\n            border-radius: 12px;\r\n            box-shadow: 0 8px 32px rgba(0,0,0,0.12);\r\n            z-index: 0;\r\n            max-width: 350px;\r\n            transition: opacity 0.3s ease, transform 0.3s ease;\r\n        }\r\n\r\n        .car-info-title {\r\n            font-size: 28px;\r\n            font-weight: 300;\r\n            color: #1a1a1a;\r\n            margin-bottom: 4px;\r\n            letter-spacing: -0.5px;\r\n        }\r\n\r\n        .car-info-subtitle {\r\n            color: #6b7280;\r\n            font-size: 14px;\r\n            margin-bottom: 12px;\r\n        }\r\n\r\n        .detail-text {\r\n            color: #374151;\r\n            font-size: 13px;\r\n            line-height: 1.4;\r\n            font-weight: 500;\r\n            \/* Allow wrapping for better layout *\/\r\n            word-wrap: break-word;\r\n        }\r\n\r\n        .studio-controls {\r\n            position: absolute;\r\n            bottom: 40px;\r\n            left: 50%;\r\n            transform: translateX(-50%);\r\n            display: flex;\r\n            gap: 12px;\r\n            background: rgba(255,255,255,0.95);\r\n            backdrop-filter: blur(10px);\r\n            padding: 12px 20px;\r\n            border-radius: 50px;\r\n            box-shadow: 0 8px 32px rgba(0,0,0,0.12);\r\n            z-index: 10;\r\n        }\r\n\r\n            .studio-controls::before {\r\n                content: '';\r\n                position: absolute;\r\n                background: #1a1a1a;\r\n                border-radius: 20px;\r\n                transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);\r\n                z-index: 0;\r\n                top: 12px;\r\n                bottom: 12px;\r\n                left: var(--indicator-left, 0);\r\n                width: var(--indicator-width, 0);\r\n            }\r\n\r\n        .view-tab {\r\n            padding: 8px 16px;\r\n            border: none;\r\n            background: transparent !important;\r\n            color: #666 !important;\r\n            font-size: 14px;\r\n            font-weight: 500;\r\n            cursor: pointer;\r\n            border-radius: 20px;\r\n            transition: color 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n            text-transform: uppercase;\r\n            letter-spacing: 0.5px;\r\n            min-height: 44px;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            position: relative;\r\n            z-index: 1;\r\n        }\r\n\r\n            .view-tab:hover {\r\n                color: #333 !important;\r\n            }\r\n\r\n            .view-tab.active {\r\n                color: white !important;\r\n                font-weight: 600;\r\n            }\r\n\r\n            .view-tab.active:hover {\r\n                color: white !important;\r\n            }\r\n\r\n            .view-tab.hidden {\r\n                display: none;\r\n            }\r\n\r\n        .zoom-controls {\r\n            position: absolute;\r\n            top: 40px;\r\n            right: 40px;\r\n            display: flex;\r\n            gap: 8px;\r\n            background: rgba(255,255,255,0.95);\r\n            backdrop-filter: blur(10px);\r\n            padding: 8px;\r\n            border-radius: 50px;\r\n            box-shadow: 0 4px 20px rgba(0,0,0,0.1);\r\n            z-index: 10;\r\n            transition: opacity 0.3s ease, transform 0.3s ease;\r\n        }\r\n\r\n        \/* Hide +\/- zoom buttons on mobile, keep reset button *\/\r\n        @media (max-width: 768px) {\r\n            .zoom-controls .zoom-btn:nth-child(1),\r\n            .zoom-controls .zoom-btn:nth-child(2) {\r\n                display: none;\r\n            }\r\n\r\n            \/* Hide entire zoom controls on mobile when at base scale *\/\r\n            .zoom-controls.hide-on-mobile {\r\n                opacity: 0;\r\n                pointer-events: none;\r\n                transform: scale(0.95) translateX(10px);\r\n            }\r\n        }\r\n\r\n        .zoom-btn {\r\n            width: 44px;\r\n            height: 44px;\r\n            border: none;\r\n            background: transparent;\r\n            border-radius: 50%;\r\n            cursor: pointer;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n            font-size: 16px;\r\n            color: #666;\r\n            transition: all 0.2s ease;\r\n            touch-action: manipulation;\r\n        }\r\n\r\n            .zoom-btn:hover {\r\n                background: #1a1a1a;\r\n                color: white;\r\n            }\r\n\r\n        .config-panel {\r\n            flex: 0 0 40%;\r\n            height: 95vh;\r\n            background: white;\r\n            border-left: 1px solid #e5e7eb;\r\n            display: flex;\r\n            flex-direction: column;\r\n            overflow: hidden;\r\n        }\r\n\r\n        .config-header {\r\n            padding: 10px 32px 32px 32px;\r\n            border-bottom: 1px solid #e5e7eb;\r\n            flex-shrink: 0;\r\n        }\r\n\r\n        .config-content {\r\n            flex: 1;\r\n            overflow-y: auto;\r\n            padding: 0 32px;\r\n            scrollbar-width: none;\r\n            -ms-overflow-style: none;\r\n        }\r\n\r\n            .config-content::-webkit-scrollbar {\r\n                display: none;\r\n            }\r\n\r\n        .config-section {\r\n            margin-bottom: 25px;\r\n            margin-top: 25px;\r\n        }\r\n\r\n        .section-title {\r\n            font-size: 20px;\r\n            font-weight: 500;\r\n            color: #1a1a1a;\r\n            margin-bottom: 24px;\r\n            letter-spacing: -0.2px;\r\n        }\r\n\r\n        .wheel-grid {\r\n            display: grid;\r\n            grid-template-columns: repeat(2, 1fr);\r\n            gap: 16px;\r\n        }\r\n\r\n        .wheel-option, .audio-option {\r\n            border: 2px solid #e5e7eb;\r\n            border-radius: 12px;\r\n            padding: 20px;\r\n            cursor: pointer;\r\n            transition: all 0.3s ease;\r\n            text-align: center;\r\n            background: white;\r\n            min-height: 44px;\r\n            touch-action: manipulation;\r\n        }\r\n\r\n            .wheel-option:hover, .audio-option:hover {\r\n                border-color: #9ca3af;\r\n                transform: translateY(-2px);\r\n                box-shadow: 0 8px 24px rgba(0,0,0,0.08);\r\n            }\r\n\r\n            .wheel-option.selected, .audio-option.selected {\r\n                border-color: #1a1a1a;\r\n                background: #f9fafb;\r\n            }\r\n\r\n        .wheel-image {\r\n            width: 80px;\r\n            height: 80px;\r\n            margin: 0 auto 12px;\r\n            border-radius: 50%;\r\n            overflow: hidden;\r\n            background: #f3f4f6;\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: center;\r\n        }\r\n\r\n            .wheel-image img,\r\n            .wheel-image picture {\r\n                height: 80px !important;\r\n                width: auto !important;\r\n                max-width: none !important;\r\n            }\r\n\r\n        \/* Larger image for rear entertainment screen *\/\r\n        #option-screen {\r\n            display: flex;\r\n            flex-direction: row;\r\n            align-items: center;\r\n            gap: 20px;\r\n            text-align: left;\r\n        }\r\n\r\n        #option-screen .wheel-image {\r\n            width: 240px;\r\n            height: 240px;\r\n            border-radius: 12px;\r\n            margin: 0;\r\n            flex-shrink: 0;\r\n            background: transparent;\r\n        }\r\n\r\n        #option-screen .wheel-image img,\r\n        #option-screen .wheel-image picture {\r\n            height: 80px !important;\r\n            width: auto !important;\r\n            max-width: none !important;\r\n        }\r\n\r\n        #option-screen .option-text-content {\r\n            display: flex;\r\n            flex-direction: column;\r\n            gap: 8px;\r\n            flex: 1;\r\n        }\r\n\r\n        #option-screen .audio-name {\r\n            text-align: left;\r\n        }\r\n\r\n        #option-screen .price-tag {\r\n            text-align: left;\r\n        }\r\n\r\n        .wheel-name, .audio-name {\r\n            font-weight: 600;\r\n            color: #1a1a1a;\r\n            margin-bottom: 4px;\r\n            font-size: 14px;\r\n        }\r\n\r\n        .wheel-desc, .audio-desc {\r\n            color: #6b7280;\r\n            font-size: 12px;\r\n            line-height: 1.6;\r\n        }\r\n\r\n        .spec-label {\r\n            color: #374151;\r\n            font-weight: 600;\r\n        }\r\n\r\n        .color-grid {\r\n            display: grid;\r\n            grid-template-columns: repeat(3, 1fr);\r\n            gap: 16px;\r\n        }\r\n\r\n        .interior-color-grid {\r\n            display: grid;\r\n            grid-template-columns: repeat(3, 1fr);\r\n            gap: 16px;\r\n        }\r\n\r\n        .color-option {\r\n            aspect-ratio: 16\/9;\r\n            border: 3px solid #e5e7eb;\r\n            border-radius: 12px;\r\n            cursor: pointer;\r\n            transition: all 0.3s ease;\r\n            position: relative;\r\n            overflow: hidden;\r\n            background-size: cover;\r\n            background-position: center;\r\n            background-repeat: no-repeat;\r\n            min-height: 44px;\r\n            touch-action: manipulation;\r\n        }\r\n\r\n            .color-option:hover {\r\n                transform: scale(1.02);\r\n                box-shadow: 0 8px 24px rgba(0,0,0,0.12);\r\n            }\r\n\r\n            .color-option.selected {\r\n                border-color: #1a1a1a;\r\n                transform: scale(1.05);\r\n                box-shadow: 0 12px 32px rgba(0,0,0,0.15);\r\n            }\r\n\r\n                .color-option.selected::after {\r\n                    content: '\u2713';\r\n                    position: absolute;\r\n                    top: 50%;\r\n                    left: 50%;\r\n                    transform: translate(-50%, -50%);\r\n                    color: white;\r\n                    font-size: 20px;\r\n                    font-weight: bold;\r\n                    background: rgba(0,0,0,0.8);\r\n                    width: 36px;\r\n                    height: 36px;\r\n                    border-radius: 50%;\r\n                    display: flex;\r\n                    align-items: center;\r\n                    justify-content: center;\r\n                }\r\n\r\n        .color-label {\r\n            position: absolute;\r\n            bottom: 0;\r\n            left: 0;\r\n            right: 0;\r\n            background: linear-gradient(transparent, rgba(0,0,0,0.8));\r\n            color: white;\r\n            padding: 16px 12px 8px;\r\n            font-size: 12px;\r\n            font-weight: 500;\r\n            text-align: center;\r\n        }\r\n\r\n        .config-footer {\r\n            padding: 32px;\r\n            border-top: 1px solid #e5e7eb;\r\n            flex-shrink: 0;\r\n            background: #f9fafb;\r\n            box-shadow: 0px -10px 20px -20px #000000;\r\n        }\r\n\r\n        .status-row {\r\n            display: flex;\r\n            justify-content: space-between;\r\n            align-items: flex-start;\r\n            margin-bottom: 12px;\r\n        }\r\n\r\n        .status-label {\r\n            font-size: 14px;\r\n            font-weight: 500;\r\n            color: #6b7280;\r\n            \/* Allow wrapping for long option lists *\/\r\n            word-wrap: break-word;\r\n            max-width: 70%;\r\n        }\r\n\r\n        .status-value {\r\n            font-size: 14px;\r\n            font-weight: 600;\r\n            color: #1a1a1a;\r\n            transition: opacity 0.3s ease;\r\n        }\r\n\r\n        .total-row {\r\n            padding-top: 12px;\r\n            border-top: 2px solid #1a1a1a;\r\n            margin-bottom: 24px;\r\n        }\r\n\r\n            .total-row .status-label {\r\n                font-size: 18px;\r\n                font-weight: 600;\r\n                color: #1a1a1a;\r\n            }\r\n\r\n            .total-row .status-value {\r\n                font-size: 18px;\r\n                font-weight: 700;\r\n                color: #1a1a1a;\r\n            }\r\n\r\n        .cta-button {\r\n            width: 100%;\r\n            padding: 16px 24px;\r\n            background: #1a1a1a;\r\n            color: white;\r\n            border: none;\r\n            border-radius: 12px;\r\n            font-size: 16px;\r\n            font-weight: 600;\r\n            cursor: pointer;\r\n            transition: all 0.3s ease;\r\n            text-transform: uppercase;\r\n            letter-spacing: 0.5px;\r\n            min-height: 56px;\r\n            touch-action: manipulation;\r\n        }\r\n\r\n            .cta-button:hover {\r\n                background: #374151;\r\n                transform: translateY(-2px);\r\n                box-shadow: 0 8px 24px rgba(0,0,0,0.2);\r\n            }\r\n\r\n        .contact-form {\r\n            position: fixed;\r\n            top: 0;\r\n            left: 0;\r\n            right: 0;\r\n            bottom: 0;\r\n            background: white;\r\n            transform: translateY(100%);\r\n            transition: transform 0.4s cubic-bezier(0.4, 0.0, 0.2, 1);\r\n            overflow-y: auto;\r\n            z-index: 1000;\r\n            visibility: hidden;\r\n        }\r\n\r\n            .contact-form.show {\r\n                visibility: visible;\r\n                transform: translateY(0);\r\n            }\r\n\r\n        body.form-open {\r\n            overflow: hidden;\r\n        }\r\n\r\n        .form-header {\r\n            padding: 32px;\r\n            border-bottom: 1px solid #e5e7eb;\r\n            background: #f9fafb;\r\n        }\r\n\r\n        .form-title {\r\n            font-size: 24px;\r\n            font-weight: 500;\r\n            color: #1a1a1a;\r\n            margin-bottom: 8px;\r\n        }\r\n\r\n        .form-subtitle {\r\n            color: #6b7280;\r\n            font-size: 14px;\r\n        }\r\n\r\n        .form-content {\r\n            padding: 32px;\r\n        }\r\n\r\n        .form-grid {\r\n            display: grid;\r\n            grid-template-columns: 1fr 1fr;\r\n            gap: 20px;\r\n            margin-bottom: 20px;\r\n        }\r\n\r\n        .form-group {\r\n            display: flex;\r\n            flex-direction: column;\r\n            gap: 8px;\r\n        }\r\n\r\n            .form-group.full-width {\r\n                grid-column: 1 \/ -1;\r\n            }\r\n\r\n        .form-label {\r\n            font-size: 14px;\r\n            font-weight: 500;\r\n            color: #374151;\r\n        }\r\n\r\n        .form-input {\r\n            padding: 12px 16px;\r\n            border: 2px solid #e5e7eb;\r\n            border-radius: 8px;\r\n            font-size: 16px;\r\n            transition: border-color 0.2s ease;\r\n            background: white;\r\n            min-height: 48px;\r\n        }\r\n\r\n            .form-input:focus {\r\n                outline: none;\r\n                border-color: #1a1a1a;\r\n            }\r\n\r\n            .form-input.error {\r\n                border-color: #ef4444;\r\n            }\r\n\r\n        .form-error {\r\n            color: #ef4444;\r\n            font-size: 12px;\r\n        }\r\n\r\n        .form-buttons {\r\n            display: flex;\r\n            gap: 16px;\r\n            margin-top: 32px;\r\n        }\r\n\r\n        .cancel-btn {\r\n            flex: 1;\r\n            padding: 14px;\r\n            border: 2px solid #e5e7eb;\r\n            background: white;\r\n            color: #6b7280;\r\n            border-radius: 8px;\r\n            cursor: pointer;\r\n            font-weight: 500;\r\n            text-transform: uppercase;\r\n            letter-spacing: 0.5px;\r\n            transition: all 0.2s ease;\r\n            min-height: 56px;\r\n            touch-action: manipulation;\r\n        }\r\n\r\n            .cancel-btn:hover {\r\n                border-color: #9ca3af;\r\n                color: #374151;\r\n            }\r\n\r\n        .submit-btn {\r\n            flex: 2;\r\n            padding: 14px;\r\n            background: #1a1a1a;\r\n            color: white;\r\n            border: none;\r\n            border-radius: 8px;\r\n            cursor: pointer;\r\n            font-weight: 600;\r\n            text-transform: uppercase;\r\n            letter-spacing: 0.5px;\r\n            transition: all 0.2s ease;\r\n            min-height: 56px;\r\n            touch-action: manipulation;\r\n        }\r\n\r\n            .submit-btn:hover:not(:disabled) {\r\n                background: #374151;\r\n            }\r\n\r\n            .submit-btn:disabled {\r\n                background: #9ca3af;\r\n                cursor: not-allowed;\r\n            }\r\n\r\n        .message {\r\n            padding: 16px;\r\n            border-radius: 8px;\r\n            margin-bottom: 20px;\r\n            text-align: center;\r\n            font-weight: 500;\r\n        }\r\n\r\n            .message.success {\r\n                background: #d1fae5;\r\n                color: #065f46;\r\n                border: 1px solid #a7f3d0;\r\n            }\r\n\r\n            .message.error {\r\n                background: #fee2e2;\r\n                color: #991b1b;\r\n                border: 1px solid #fecaca;\r\n            }\r\n\r\n        .price-tag {\r\n            font-size: 11px;\r\n            color: #059669;\r\n            font-weight: 600;\r\n            margin-top: 4px;\r\n        }\r\n\r\n            .price-tag.paid {\r\n                color: #dc2626;\r\n            }\r\n\r\n        .note-text {\r\n            font-size: 12px;\r\n            color: #6b7280;\r\n            font-style: italic;\r\n            margin-top: 8px;\r\n        }\r\n        \/* Color backgrounds dynamically generated by generateColorPreviewCSS() *\/\r\n\r\n        \/* Mobile Optimizations *\/\r\n        @media (max-width: 1024px) {\r\n            .configurator {\r\n                flex-direction: column;\r\n                height: auto;\r\n                padding: 0;\r\n                margin-top: 8vh;\r\n            }\r\n\r\n            .car-studio {\r\n                flex: none;\r\n                height: 41vh;\r\n                min-height: 400px;\r\n                position: sticky;\r\n                top: 75px;\r\n                z-index: 1;\r\n            }\r\n\r\n            .car-info-overlay.interior-hidden {\r\n                opacity: 0;\r\n                pointer-events: none;\r\n                transform: scale(0.95) translateY(-10px);\r\n            }\r\n\r\n            .config-panel {\r\n                flex: none;\r\n                border-left: none;\r\n                height: auto;\r\n            }\r\n\r\n            .config-header {\r\n                padding: 24px 20px;\r\n            }\r\n\r\n            .config-content {\r\n                padding: 0 20px;\r\n                max-height: none;\r\n            }\r\n\r\n            .config-footer {\r\n                padding: 20px;\r\n            }\r\n\r\n            .studio-controls {\r\n                bottom: 20px;\r\n                padding: 10px 16px;\r\n            }\r\n\r\n            .car-info-overlay {\r\n                top: 20px;\r\n                left: 20px;\r\n                padding: 12px 16px;\r\n                max-width: 295px;\r\n                z-index: 0;\r\n            }\r\n\r\n            .car-info-title {\r\n                font-size: 24px !important;\r\n                margin-bottom: 3px;\r\n            }\r\n\r\n            .car-info-subtitle {\r\n                font-size: 12px;\r\n                margin-bottom: 8px;\r\n            }\r\n\r\n            .color-grid {\r\n                grid-template-columns: repeat(2, 1fr);\r\n                gap: 12px;\r\n            }\r\n\r\n            .wheel-grid {\r\n                grid-template-columns: 1fr;\r\n                gap: 12px;\r\n            }\r\n\r\n            .form-grid {\r\n                grid-template-columns: 1fr;\r\n            }\r\n\r\n            .section-title {\r\n                font-size: 18px;\r\n                margin-bottom: 20px;\r\n            }\r\n        }\r\n\r\n        @media (max-width: 768px) {\r\n            .car-studio {\r\n                height: 45vh;\r\n                min-height: 350px;\r\n            }\r\n\r\n            .config-header {\r\n                padding: 20px 16px;\r\n            }\r\n\r\n            .config-content {\r\n                padding: 0 16px;\r\n            }\r\n\r\n            .config-footer {\r\n                padding: 16px;\r\n            }\r\n\r\n            .form-content, .form-header {\r\n                padding: 20px 16px;\r\n            }\r\n\r\n            .section-title {\r\n                font-size: 16px;\r\n                margin-bottom: 16px;\r\n            }\r\n\r\n            .color-grid, .interior-color-grid {\r\n                grid-template-columns: 1fr;\r\n                gap: 12px;\r\n            }\r\n\r\n            .color-option {\r\n                aspect-ratio: 20\/9;\r\n                min-height: 60px;\r\n            }\r\n\r\n            .wheel-option, .audio-option {\r\n                padding: 16px;\r\n            }\r\n\r\n            .wheel-image {\r\n                width: 60px;\r\n                height: 60px;\r\n                margin-bottom: 8px;\r\n            }\r\n\r\n            #option-screen .wheel-image {\r\n                width: 200px;\r\n                height: 200px;\r\n                margin: 0;\r\n            }\r\n\r\n            #option-screen {\r\n                gap: 16px;\r\n            }\r\n\r\n            .view-tab {\r\n                padding: 8px 12px;\r\n                font-size: 12px;\r\n                min-height: 40px;\r\n            }\r\n\r\n            .studio-controls {\r\n                gap: 8px;\r\n                padding: 8px 12px;\r\n            }\r\n\r\n            .studio-controls::before {\r\n                top: 8px;\r\n                bottom: 8px;\r\n            }\r\n\r\n            .status-label, .status-value {\r\n                font-size: 12px;\r\n            }\r\n\r\n            .total-row .status-label, .total-row .status-value {\r\n                font-size: 16px;\r\n            }\r\n\r\n            .cta-button {\r\n                font-size: 15px;\r\n                padding: 14px 20px;\r\n            }\r\n\r\n            .form-buttons {\r\n                flex-direction: column;\r\n                gap: 12px;\r\n            }\r\n\r\n            .cancel-btn, .submit-btn {\r\n                flex: none;\r\n                width: 100%;\r\n            }\r\n\r\n            .config-section {\r\n                margin-bottom: 32px;\r\n            }\r\n        }\r\n\r\n        @media (max-width: 480px) {\r\n            .car-studio {\r\n                height: 40vh;\r\n                min-height: 300px;\r\n                border-bottom: 2px solid #dddddd;\r\n                border-radius: 0px 0px 12px 12px;\r\n                box-shadow: 0px 10px 20px -20px #000000;\r\n            }\r\n\r\n            .config-header {\r\n                padding: 16px 12px;\r\n            }\r\n\r\n            .config-content {\r\n                padding: 0 12px;\r\n            }\r\n\r\n            .config-footer {\r\n                padding: 12px;\r\n                z-index: 2;\r\n            }\r\n\r\n            .form-content, .form-header {\r\n                padding: 16px 12px;\r\n            }\r\n\r\n            .detail-text {\r\n                font-size: 11px;\r\n            }\r\n\r\n            .section-title {\r\n                font-size: 14px;\r\n                margin-bottom: 12px;\r\n            }\r\n\r\n            .color-option {\r\n                aspect-ratio: 18\/9;\r\n                min-height: 50px;\r\n            }\r\n\r\n            .color-label {\r\n                font-size: 11px;\r\n                padding: 12px 8px 6px;\r\n            }\r\n\r\n            .wheel-option, .audio-option {\r\n                padding: 12px;\r\n            }\r\n\r\n            .wheel-image {\r\n                width: 50px;\r\n                height: 50px;\r\n            }\r\n\r\n            #option-screen .wheel-image {\r\n                width: 180px;\r\n                height: 180px;\r\n                margin: 0;\r\n            }\r\n\r\n            #option-screen {\r\n                gap: 12px;\r\n            }\r\n\r\n            .wheel-name, .audio-name {\r\n                font-size: 12px;\r\n            }\r\n\r\n            .wheel-desc, .audio-desc {\r\n                font-size: 10px;\r\n            }\r\n\r\n            .view-tab {\r\n                padding: 6px 10px;\r\n                font-size: 11px;\r\n                min-height: 36px;\r\n            }\r\n\r\n            .studio-controls {\r\n                bottom: 16px;\r\n                gap: 6px;\r\n                padding: 6px 10px;\r\n            }\r\n\r\n            .studio-controls::before {\r\n                top: 6px;\r\n                bottom: 6px;\r\n            }\r\n\r\n            .car-info-overlay {\r\n                top: 16px;\r\n                padding: 8px 12px;\r\n                z-index: 0;\r\n            }\r\n\r\n            .car-info-title {\r\n                font-size: 20px;\r\n            }\r\n\r\n            .car-info-subtitle {\r\n                font-size: 11px;\r\n            }\r\n\r\n            .detail-text {\r\n                font-size: 10px;\r\n            }\r\n\r\n            .cta-button {\r\n                font-size: 14px;\r\n                padding: 12px 16px;\r\n                min-height: 48px;\r\n            }\r\n\r\n            .form-input {\r\n                font-size: 16px;\r\n                padding: 10px 12px;\r\n                min-height: 44px;\r\n            }\r\n\r\n            .cancel-btn, .submit-btn {\r\n                min-height: 48px;\r\n                font-size: 14px;\r\n            }\r\n\r\n            .config-section {\r\n                margin-bottom: 24px;\r\n            }\r\n\r\n            .form-title {\r\n                font-size: 20px;\r\n            }\r\n\r\n            .form-subtitle {\r\n                font-size: 13px;\r\n            }\r\n        }\r\n\r\n        \/* Prevent zoom on input focus *\/\r\n        @media screen and (max-width: 768px) {\r\n            .form-input {\r\n                font-size: 16px !important;\r\n            }\r\n        }\r\n    <\/style>\r\n<\/head>\r\n<body>\r\n    <div class=\"configurator\">\r\n        <!-- Left Side - Car Studio -->\r\n        <div class=\"car-studio\">\r\n            <div class=\"car-info-overlay\">\r\n                <h1 class=\"car-info-title\" id=\"carTitle\">Loading... 2026<\/h1>\r\n                <p class=\"car-info-subtitle\" id=\"carSubtitle\">\u054a\u0580\u0565\u0574\u056b\u0578\u0582\u0574 \u0567\u056c\u0565\u056f\u057f\u0580\u0561\u056f\u0561\u0576 \u0561\u057e\u057f\u0578\u0574\u0565\u0584\u0565\u0576\u0561<\/p>\r\n                <p class=\"detail-text\" id=\"configDetails\">Loading configuration...<\/p>\r\n            <\/div>\r\n\r\n            <div class=\"car-display\">\r\n                <div class=\"car-view exterior-view active\" id=\"exteriorView\">\r\n                    <div class=\"image-skeleton\" id=\"exteriorSkeleton\"><\/div>\r\n                    <picture id=\"exteriorPicture\" class=\"car-picture front\">\r\n                        <source id=\"exteriorSourceAvif\" type=\"image\/avif\">\r\n                        <source id=\"exteriorSourceWebp\" type=\"image\/webp\">\r\n                        <img class=\"car-image\" id=\"exteriorImage\" alt=\"Li i8 Exterior\">\r\n                    <\/picture>\r\n                    <picture id=\"exteriorPictureBack\" class=\"car-picture back\">\r\n                        <source id=\"exteriorSourceAvifBack\" type=\"image\/avif\">\r\n                        <source id=\"exteriorSourceWebpBack\" type=\"image\/webp\">\r\n                        <img class=\"car-image\" id=\"exteriorImageBack\" alt=\"Li i8 Exterior\">\r\n                    <\/picture>\r\n                <\/div>\r\n                <div class=\"car-view interior-view\" id=\"interiorView\">\r\n                    <div class=\"image-skeleton\" id=\"interiorSkeleton\"><\/div>\r\n                    <picture id=\"interiorPicture\" class=\"car-picture front\">\r\n                        <source id=\"interiorSourceAvif\" type=\"image\/avif\">\r\n                        <source id=\"interiorSourceWebp\" type=\"image\/webp\">\r\n                        <img class=\"car-image\" id=\"interiorImage\" alt=\"Li i8 Interior\">\r\n                    <\/picture>\r\n                    <picture id=\"interiorPictureBack\" class=\"car-picture back\">\r\n                        <source id=\"interiorSourceAvifBack\" type=\"image\/avif\">\r\n                        <source id=\"interiorSourceWebpBack\" type=\"image\/webp\">\r\n                        <img class=\"car-image\" id=\"interiorImageBack\" alt=\"Li i8 Interior\">\r\n                    <\/picture>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <div class=\"studio-controls\">\r\n                <button class=\"view-tab active\" data-view=\"exterior\" onclick=\"switchView('exterior', event)\">\u0537\u0584\u057d\u057f\u0565\u0580\u056b\u0565\u0580<\/button>\r\n                <button class=\"view-tab\" data-view=\"interior\" onclick=\"switchView('interior', event)\">\u053b\u0576\u057f\u0565\u0580\u056b\u0565\u0580<\/button>\r\n            <\/div>\r\n\r\n            <div class=\"zoom-controls\">\r\n                <button class=\"zoom-btn\" onclick=\"zoomIn()\">+<\/button>\r\n                <button class=\"zoom-btn\" onclick=\"zoomOut()\">\u2212<\/button>\r\n                <button class=\"zoom-btn\" onclick=\"resetZoom()\">\u21ba<\/button>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- Right Side - Configuration Panel -->\r\n        <div class=\"config-panel\">\r\n\r\n            <div class=\"config-content\" id=\"configContent\">\r\n                <!-- Dynamically populated by JavaScript -->\r\n            <\/div>\r\n\r\n            <div class=\"config-footer\">\r\n                <div class=\"status-row\">\r\n                    <span class=\"status-label\">\u0540\u056b\u0574\u0576\u0561\u056f\u0561\u0576 \u0561\u0580\u056a\u0565\u0584<\/span>\r\n                    <span class=\"status-value\" id=\"basePrice\">22,750,000 AMD<\/span>\r\n                <\/div>\r\n                <div class=\"status-row\">\r\n                    <span class=\"status-label\">\u0555\u057a\u0581\u056b\u0561<\/span>\r\n                    <span class=\"status-value\" id=\"optionsPrice\">0 AMD<\/span>\r\n                <\/div>\r\n                <div class=\"status-row total-row\">\r\n                    <span class=\"status-label\">\u054e\u0565\u0580\u057b\u0576\u0561\u056f\u0561\u0576 \u0561\u0580\u056a\u0565\u0584<\/span>\r\n                    <span class=\"status-value\" id=\"totalPrice\">22,750,000 AMD<\/span>\r\n                <\/div>\r\n                <button class=\"cta-button\" onclick=\"showContactForm()\">\u054d\u057f\u0561\u0581\u056b\u0580 \u0570\u0561\u057f\u0578\u0582\u056f \u0561\u057c\u0561\u057b\u0561\u0580\u056f<\/button>\r\n            <\/div>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <!-- Contact Form Modal -->\r\n    <div class=\"contact-form\" id=\"contactForm\">\r\n        <div class=\"form-header\">\r\n            <h3 class=\"form-title\">\u054d\u057f\u0561\u0581\u056b\u0580 \u0570\u0561\u057f\u0578\u0582\u056f \u0561\u057c\u0561\u057b\u0561\u0580\u056f<\/h3>\r\n            <p class=\"form-subtitle\" id=\"formSubtitle\">Configure your perfect car and get a special price.<\/p>\r\n        <\/div>\r\n        <div class=\"form-content\">\r\n            <div id=\"messageContainer\"><\/div>\r\n            <form id=\"notificationForm\">\r\n                <div class=\"form-grid\">\r\n                    <div class=\"form-group\">\r\n                        <label class=\"form-label\" for=\"firstName\">First Name *<\/label>\r\n                        <input type=\"text\" id=\"firstName\" name=\"firstName\" class=\"form-input\" required>\r\n                        <div class=\"form-error\" id=\"firstNameError\"><\/div>\r\n                    <\/div>\r\n                    <div class=\"form-group\">\r\n                        <label class=\"form-label\" for=\"lastName\">Last Name *<\/label>\r\n                        <input type=\"text\" id=\"lastName\" name=\"lastName\" class=\"form-input\" required>\r\n                        <div class=\"form-error\" id=\"lastNameError\"><\/div>\r\n                    <\/div>\r\n                    <div class=\"form-group full-width\">\r\n                        <label class=\"form-label\" for=\"email\">Email Address<\/label>\r\n                        <input type=\"email\" id=\"email\" name=\"email\" class=\"form-input\">\r\n                        <div class=\"form-error\" id=\"emailError\"><\/div>\r\n                    <\/div>\r\n                    <div class=\"form-group full-width\">\r\n                        <label class=\"form-label\" for=\"phone\">Phone Number *<\/label>\r\n                        <input type=\"tel\" id=\"phone\" name=\"phone\" class=\"form-input\" required>\r\n                        <div class=\"form-error\" id=\"phoneError\"><\/div>\r\n                    <\/div>\r\n                <\/div>\r\n                <div class=\"form-buttons\">\r\n                    <button type=\"button\" class=\"cancel-btn\" onclick=\"hideContactForm()\">Cancel<\/button>\r\n                    <button type=\"submit\" class=\"submit-btn\" id=\"submitButton\">\r\n                        <span id=\"submitText\">\u0548\u0582\u0572\u0561\u0580\u056f\u0565\u056c<\/span>\r\n                    <\/button>\r\n                <\/div>\r\n            <input type=\"hidden\" name=\"trp-form-language\" value=\"am\"\/><\/form>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <script>\r\n        \/\/ Universal configurator - loads config based on URL parameter\r\n        let currentView = 'exterior';\r\n        let currentZoom = 1;\r\n        const zoomStep = 0.1;\r\n        const maxZoom = 2;\r\n        const minZoom = 0.8;\r\n        let isResettingZoom = false; \/\/ Flag to prevent UI flicker during reset animation\r\n\r\n        \/\/ Pan state\r\n        let panX = 0;\r\n        let panY = 0;\r\n        let isDragging = false;\r\n        let startX = 0;\r\n        let startY = 0;\r\n\r\n        \/\/ Touch state for pinch-to-zoom\r\n        let initialDistance = 0;\r\n        let initialZoom = 1;\r\n\r\n        \/\/ Crossfade state to prevent overlapping transitions\r\n        let isTransitioning = {\r\n            exterior: false,\r\n            interior: false\r\n        };\r\n\r\n        \/\/ Global config storage - loaded from JSON\r\n        let MODEL_CONFIG = null;\r\n        let currentModelKey = '';\r\n        let chineseNames = {};\r\n        let pricing = {};\r\n\r\n        \/\/ Base path for local images\r\n        const imagePath = 'https:\/\/liautoyerevan.am\/configurator_images\/downloaded-images-';\r\n\r\n        let selectedConfig = {\r\n            model: { id: '', name: '', price: 0 },\r\n            wheels: { id: '', name: '', desc: '', price: 0 },\r\n            exterior: { id: '', name: '', price: 0 },\r\n            interior: { id: '', name: '', price: 0 },\r\n            option: { id: 'none', name: 'N\/A', price: 0 },\r\n            options: [] \/\/ For multi-option models like i6\r\n        };\r\n\r\n        \/\/ Generate image path based on current configuration\r\n        function getImagePaths(viewType = 'exterior') {\r\n            if (!MODEL_CONFIG) return { avif: '', webp: '' };\r\n\r\n            const ext = chineseNames.exteriorColors[selectedConfig.exterior.id];\r\n            const wheel = chineseNames.wheels[selectedConfig.wheels.id];\r\n            const int = chineseNames.interiorColors[selectedConfig.interior.id];\r\n            const chineseFolder = MODEL_CONFIG.chineseFolder;\r\n\r\n            \/\/ Get variant folder from selected model\r\n            \/\/ Special case: L6 Pro with platinum speakers uses Max interior images\r\n            let modelId = selectedConfig.model.id;\r\n            if (viewType === 'interior' &&\r\n                selectedConfig.option.id === 'platinum' &&\r\n                selectedConfig.model.id === 'pro' &&\r\n                MODEL_CONFIG.models['max']) {\r\n                modelId = 'max'; \/\/ Use Max variant folder for interior when Pro has platinum speakers\r\n            }\r\n            const currentModel = MODEL_CONFIG.models[modelId];\r\n            const variantFolder = currentModel.variantFolder;\r\n\r\n            \/\/ Check if wheels should be included in filename (MEGA doesn't include wheels)\r\n            const includeWheels = MODEL_CONFIG.includeWheelsInFilename !== false;\r\n\r\n            \/\/ Check filename patterns (different models have different orders)\r\n            const exteriorPattern = MODEL_CONFIG.exteriorPattern || 'default'; \/\/ 'default' or 'interior-before-wheels'\r\n            const interiorPattern = MODEL_CONFIG.interiorPattern || 'default'; \/\/ 'default' or 'exterior-first'\r\n\r\n            let filename, basePath;\r\n\r\n            if (viewType === 'exterior') {\r\n                \/\/ Exterior patterns:\r\n                \/\/ Default (i8, L6, L7): {exteriorColor}-{wheelType}-{interiorColor}[-{option}]\r\n                \/\/ L9: {exteriorColor}-{interiorColor}-{wheelType}[-{option}]\r\n                \/\/ MEGA: {exteriorColor}-{interiorColor} (no wheels)\r\n                const parts = [ext];\r\n\r\n                if (exteriorPattern === 'interior-before-wheels') {\r\n                    \/\/ L9 pattern: color -> interior -> wheel\r\n                    parts.push(int);\r\n                    if (includeWheels) {\r\n                        parts.push(wheel);\r\n                    }\r\n                } else {\r\n                    \/\/ Default pattern: color -> wheel -> interior\r\n                    if (includeWheels) {\r\n                        parts.push(wheel);\r\n                    }\r\n                    parts.push(int);\r\n                }\r\n\r\n                \/\/ Handle options in filename\r\n                \/\/ i6 multi-option model: rear screen affects exterior\r\n                if (currentModelKey === 'i6' && MODEL_CONFIG.optionMode === 'multiple') {\r\n                    \/\/ Check if rear-screen option is selected\r\n                    const hasRearScreen = selectedConfig.options.some(opt => opt.id === 'rear-screen');\r\n                    const rearScreenOption = MODEL_CONFIG.options['rear-screen'];\r\n\r\n                    if (hasRearScreen && rearScreenOption) {\r\n                        parts.push(rearScreenOption.chinese); \/\/ \u540e\u8231\u5a31\u4e50\u5c4f+\u6d41\u5a92\u4f53\u540e\u89c6\u955c\r\n                    } else if (rearScreenOption && rearScreenOption.chineseBase) {\r\n                        parts.push(rearScreenOption.chineseBase); \/\/ \u65e0\u540e\u8231\u5a31\u4e50\u5c4f\r\n                    }\r\n                } else {\r\n                    \/\/ Single-option models: include option if it affects exterior\r\n                    if (selectedConfig.option.id !== 'none') {\r\n                        const optionData = MODEL_CONFIG.options[selectedConfig.option.id];\r\n                        \/\/ Check view-specific flag (affectsExterior) or fall back to legacy affectsVisuals flag\r\n                        const affectsThisView = optionData && optionData.affectsExterior !== undefined\r\n                            ? optionData.affectsExterior\r\n                            : (optionData && optionData.affectsVisuals !== false);\r\n                        if (affectsThisView) {\r\n                            parts.push(chineseNames.options[selectedConfig.option.id]);\r\n                        }\r\n                    }\r\n                }\r\n                filename = parts.join('-');\r\n                basePath = `${chineseFolder}\/${variantFolder}\/variant-attribute\/exterior\/angle-0\/`;\r\n            } else {\r\n                \/\/ Interior patterns:\r\n                \/\/ Default (i8, L6): {interiorColor}-{exteriorColor}[-{option}]\r\n                \/\/ L7, L9, MEGA: {exteriorColor}-{interiorColor}[-{option}]\r\n                let parts;\r\n                if (interiorPattern === 'exterior-first') {\r\n                    \/\/ L7\/L9\/MEGA pattern: exterior -> interior\r\n                    parts = [ext, int];\r\n                } else {\r\n                    \/\/ Default pattern: interior -> exterior\r\n                    parts = [int, ext];\r\n                }\r\n\r\n                \/\/ Handle options in filename\r\n                \/\/ i6 multi-option model: audio, rear screen, and drivetrain affect interior\r\n                if (currentModelKey === 'i6' && MODEL_CONFIG.optionMode === 'multiple') {\r\n                    \/\/ i6 interior pattern: {interior}-{color}-{audio}-{rear_screen}-{drivetrain}\r\n                    \/\/ Audio: platinum or base (always present)\r\n                    const hasPlatinumAudio = selectedConfig.options.some(opt => opt.id === 'platinum-audio');\r\n                    const audioOption = MODEL_CONFIG.options['platinum-audio'];\r\n                    if (hasPlatinumAudio && audioOption) {\r\n                        parts.push(audioOption.chinese); \/\/ \u94c2\u91d1\u97f3\u54cd\r\n                    } else if (audioOption && audioOption.chineseBase) {\r\n                        parts.push(audioOption.chineseBase); \/\/ \u9ad8\u7ea7\u97f3\u54cd\r\n                    }\r\n\r\n                    \/\/ Rear screen: with or without (always present)\r\n                    const hasRearScreen = selectedConfig.options.some(opt => opt.id === 'rear-screen');\r\n                    const rearScreenOption = MODEL_CONFIG.options['rear-screen'];\r\n                    if (hasRearScreen && rearScreenOption) {\r\n                        parts.push(rearScreenOption.chinese); \/\/ \u540e\u8231\u5a31\u4e50\u5c4f+\u6d41\u5a92\u4f53\u540e\u89c6\u955c\r\n                    } else if (rearScreenOption && rearScreenOption.chineseBase) {\r\n                        parts.push(rearScreenOption.chineseBase); \/\/ \u65e0\u540e\u8231\u5a31\u4e50\u5c4f\r\n                    }\r\n\r\n                    \/\/ Drivetrain: AWD or base RWD (always present)\r\n                    const hasAWD = selectedConfig.options.some(opt => opt.id === 'awd-system');\r\n                    const awdOption = MODEL_CONFIG.options['awd-system'];\r\n                    if (hasAWD && awdOption) {\r\n                        parts.push(awdOption.chinese); \/\/ \u53cc\u7535\u673a\u56db\u9a71\r\n                    } else if (awdOption && awdOption.chineseBase) {\r\n                        parts.push(awdOption.chineseBase); \/\/ \u540e\u9a71\r\n                    }\r\n                } else {\r\n                    \/\/ Single-option models\r\n                    \/\/ Don't add suffix if we switched variant folders (folder switch IS the visual change)\r\n                    if (selectedConfig.option.id !== 'none') {\r\n                        const optionData = MODEL_CONFIG.options[selectedConfig.option.id];\r\n                        \/\/ Check if we switched variant folders for this option\r\n                        const didVariantSwitch = (selectedConfig.option.id === 'platinum' &&\r\n                                                  selectedConfig.model.id === 'pro' &&\r\n                                                  MODEL_CONFIG.models['max']);\r\n\r\n                        if (!didVariantSwitch) {\r\n                            \/\/ Check view-specific flag (affectsInterior) or fall back to legacy affectsVisuals flag\r\n                            const affectsThisView = optionData && optionData.affectsInterior !== undefined\r\n                                ? optionData.affectsInterior\r\n                                : (optionData && optionData.affectsVisuals !== false);\r\n                            if (affectsThisView) {\r\n                                parts.push(chineseNames.options[selectedConfig.option.id]);\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                filename = parts.join('-');\r\n                basePath = `${chineseFolder}\/${variantFolder}\/variant-attribute\/interior\/angle-0\/`;\r\n            }\r\n\r\n            return {\r\n                avif: `${imagePath}avif\/${basePath}${filename}.avif`,\r\n                webp: `${imagePath}webp\/${basePath}${filename}.webp`\r\n            };\r\n        }\r\n\r\n        \/\/ Update image sources with crossfade effect\r\n        function updateImage(viewType, skipCrossfade = false) {\r\n            const paths = getImagePaths(viewType);\r\n\r\n            if (viewType === 'exterior') {\r\n                crossfadeImage(\r\n                    'exteriorPicture',\r\n                    'exteriorPictureBack',\r\n                    'exteriorSourceAvif',\r\n                    'exteriorSourceWebp',\r\n                    'exteriorImage',\r\n                    'exteriorSourceAvifBack',\r\n                    'exteriorSourceWebpBack',\r\n                    'exteriorImageBack',\r\n                    paths,\r\n                    skipCrossfade,\r\n                    'exterior'\r\n                );\r\n            } else if (viewType === 'interior') {\r\n                crossfadeImage(\r\n                    'interiorPicture',\r\n                    'interiorPictureBack',\r\n                    'interiorSourceAvif',\r\n                    'interiorSourceWebp',\r\n                    'interiorImage',\r\n                    'interiorSourceAvifBack',\r\n                    'interiorSourceWebpBack',\r\n                    'interiorImageBack',\r\n                    paths,\r\n                    skipCrossfade,\r\n                    'interior'\r\n                );\r\n            }\r\n        }\r\n\r\n        \/\/ Crossfade between two picture elements\r\n        \/\/ New image loads underneath, old image fades out on top to reveal it\r\n        function crossfadeImage(frontPicId, backPicId, frontAvifId, frontWebpId, frontImgId, backAvifId, backWebpId, backImgId, paths, skipCrossfade, viewType) {\r\n            const pic1 = document.getElementById(frontPicId);\r\n            const pic2 = document.getElementById(backPicId);\r\n\r\n            if (skipCrossfade) {\r\n                \/\/ Direct update without crossfade (for initial load)\r\n                \/\/ Load into whichever has front class\r\n                const frontPic = pic1.classList.contains('front') ? pic1 : pic2;\r\n                const frontAvif = frontPic.querySelector('source[type=\"image\/avif\"]');\r\n                const frontWebp = frontPic.querySelector('source[type=\"image\/webp\"]');\r\n                const frontImg = frontPic.querySelector('img');\r\n                frontAvif.srcset = paths.avif;\r\n                frontWebp.srcset = paths.webp;\r\n                frontImg.src = paths.webp;\r\n                return;\r\n            }\r\n\r\n            \/\/ Check if a transition is already in progress for this view\r\n            if (isTransitioning[viewType]) {\r\n                \/\/ Transition in progress, skip this update to prevent jarring overlap\r\n                return;\r\n            }\r\n\r\n            \/\/ Lock transitions for this view\r\n            isTransitioning[viewType] = true;\r\n\r\n            \/\/ Determine which element currently has which class\r\n            const currentFront = pic1.classList.contains('front') ? pic1 : pic2;\r\n            const currentBack = pic1.classList.contains('back') ? pic1 : pic2;\r\n\r\n            \/\/ Get sources for the back layer (where we'll load new image)\r\n            const backAvif = currentBack.querySelector('source[type=\"image\/avif\"]');\r\n            const backWebp = currentBack.querySelector('source[type=\"image\/webp\"]');\r\n            const backImg = currentBack.querySelector('img');\r\n\r\n            \/\/ Load new image into back picture (underneath)\r\n            backAvif.srcset = paths.avif;\r\n            backWebp.srcset = paths.webp;\r\n            backImg.src = paths.webp;\r\n\r\n            \/\/ Wait for image to load, then crossfade\r\n            backImg.onload = () => {\r\n                \/\/ Disable transition on back layer temporarily\r\n                currentBack.style.transition = 'none';\r\n\r\n                \/\/ Set back picture to fully visible immediately (no transition)\r\n                currentBack.style.opacity = '1';\r\n\r\n                \/\/ Force a reflow to ensure the opacity change is applied\r\n                currentBack.offsetHeight;\r\n\r\n                \/\/ Re-enable transitions for future changes\r\n                currentBack.style.transition = '';\r\n\r\n                \/\/ Now fade OUT front picture to reveal new image underneath\r\n                \/\/ Use requestAnimationFrame to ensure it happens in next frame\r\n                requestAnimationFrame(() => {\r\n                    currentFront.style.opacity = '0';\r\n                });\r\n\r\n                \/\/ After crossfade completes, swap layers for next transition\r\n                setTimeout(() => {\r\n                    \/\/ Swap z-index classes\r\n                    currentFront.classList.remove('front');\r\n                    currentFront.classList.add('back');\r\n                    currentBack.classList.remove('back');\r\n                    currentBack.classList.add('front');\r\n\r\n                    \/\/ Reset opacity - old image (now back) hidden, new image (now front) visible\r\n                    currentFront.style.opacity = '0';\r\n                    currentBack.style.opacity = '1';\r\n\r\n                    \/\/ Unlock transitions for this view\r\n                    isTransitioning[viewType] = false;\r\n                }, 800); \/\/ Match CSS transition duration\r\n            };\r\n\r\n            \/\/ Handle image load error - unlock transitions so user can try again\r\n            backImg.onerror = () => {\r\n                isTransitioning[viewType] = false;\r\n            };\r\n        }\r\n\r\n        \/\/ Preloading functions for adjacent options\r\n        const preloadCache = new Set();\r\n\r\n        function preloadImage(avifPath, webpPath) {\r\n            \/\/ Skip if already preloaded\r\n            const cacheKey = avifPath + '|' + webpPath;\r\n            if (preloadCache.has(cacheKey)) return;\r\n            preloadCache.add(cacheKey);\r\n\r\n            \/\/ Preload AVIF\r\n            const avifImg = new Image();\r\n            avifImg.src = avifPath;\r\n\r\n            \/\/ Preload WebP\r\n            const webpImg = new Image();\r\n            webpImg.src = webpPath;\r\n        }\r\n\r\n        function preloadAdjacentOptions() {\r\n            if (!MODEL_CONFIG) return;\r\n\r\n            const exteriorColors = Object.keys(MODEL_CONFIG.exteriorColors);\r\n            const interiorColors = Object.keys(MODEL_CONFIG.interiorColors);\r\n\r\n            \/\/ Filter out disabled wheels for current model\r\n            const wheels = Object.keys(MODEL_CONFIG.wheels).filter(wheelId => {\r\n                const wheelData = MODEL_CONFIG.wheels[wheelId];\r\n                return !wheelData.disabledFor || !wheelData.disabledFor.includes(selectedConfig.model.id);\r\n            });\r\n\r\n            \/\/ Find current indices\r\n            const extIdx = exteriorColors.indexOf(selectedConfig.exterior.id);\r\n            const wheelIdx = wheels.indexOf(selectedConfig.wheels.id);\r\n            const intIdx = interiorColors.indexOf(selectedConfig.interior.id);\r\n\r\n            \/\/ Create temporary configs for adjacent options\r\n            const tempConfig = { ...selectedConfig };\r\n\r\n            \/\/ Preload previous\/next exterior color\r\n            if (extIdx > 0) {\r\n                tempConfig.exterior = { ...selectedConfig.exterior, id: exteriorColors[extIdx - 1] };\r\n                const paths = getImagePathsFromConfig(tempConfig, currentView);\r\n                preloadImage(paths.avif, paths.webp);\r\n            }\r\n            if (extIdx < exteriorColors.length - 1) {\r\n                tempConfig.exterior = { ...selectedConfig.exterior, id: exteriorColors[extIdx + 1] };\r\n                const paths = getImagePathsFromConfig(tempConfig, currentView);\r\n                preloadImage(paths.avif, paths.webp);\r\n            }\r\n\r\n            \/\/ Preload previous\/next wheel (only available wheels)\r\n            tempConfig.exterior = selectedConfig.exterior;\r\n            if (wheelIdx > 0) {\r\n                tempConfig.wheels = { ...selectedConfig.wheels, id: wheels[wheelIdx - 1] };\r\n                const paths = getImagePathsFromConfig(tempConfig, currentView);\r\n                preloadImage(paths.avif, paths.webp);\r\n            }\r\n            if (wheelIdx < wheels.length - 1) {\r\n                tempConfig.wheels = { ...selectedConfig.wheels, id: wheels[wheelIdx + 1] };\r\n                const paths = getImagePathsFromConfig(tempConfig, currentView);\r\n                preloadImage(paths.avif, paths.webp);\r\n            }\r\n\r\n            \/\/ Preload previous\/next interior color\r\n            tempConfig.wheels = selectedConfig.wheels;\r\n            if (intIdx > 0) {\r\n                tempConfig.interior = { ...selectedConfig.interior, id: interiorColors[intIdx - 1] };\r\n                const paths = getImagePathsFromConfig(tempConfig, currentView);\r\n                preloadImage(paths.avif, paths.webp);\r\n            }\r\n            if (intIdx < interiorColors.length - 1) {\r\n                tempConfig.interior = { ...selectedConfig.interior, id: interiorColors[intIdx + 1] };\r\n                const paths = getImagePathsFromConfig(tempConfig, currentView);\r\n                preloadImage(paths.avif, paths.webp);\r\n            }\r\n\r\n            \/\/ Preload alternate view (exterior <-> interior)\r\n            const alternateView = currentView === 'exterior' ? 'interior' : 'exterior';\r\n            const alternatePaths = getImagePaths(alternateView);\r\n            preloadImage(alternatePaths.avif, alternatePaths.webp);\r\n        }\r\n\r\n        function getImagePathsFromConfig(config, viewType = 'exterior') {\r\n            if (!MODEL_CONFIG) return { avif: '', webp: '' };\r\n\r\n            const ext = chineseNames.exteriorColors[config.exterior.id];\r\n            const wheel = chineseNames.wheels[config.wheels.id];\r\n            const int = chineseNames.interiorColors[config.interior.id];\r\n            const chineseFolder = MODEL_CONFIG.chineseFolder;\r\n\r\n            \/\/ Get variant folder from config's model\r\n            \/\/ Special case: L6 Pro with platinum speakers uses Max interior images\r\n            let modelId = config.model.id;\r\n            if (viewType === 'interior' &&\r\n                config.option.id === 'platinum' &&\r\n                config.model.id === 'pro' &&\r\n                MODEL_CONFIG.models['max']) {\r\n                modelId = 'max'; \/\/ Use Max variant folder for interior when Pro has platinum speakers\r\n            }\r\n            const currentModel = MODEL_CONFIG.models[modelId];\r\n            const variantFolder = currentModel.variantFolder;\r\n\r\n            let filename, basePath;\r\n\r\n            if (viewType === 'exterior') {\r\n                const parts = [ext, wheel, int];\r\n                if (config.option.id !== 'none') {\r\n                    const optionData = MODEL_CONFIG.options[config.option.id];\r\n                    \/\/ Check if option affects exterior view\r\n                    const affectsThisView = optionData && optionData.affectsExterior !== undefined\r\n                        ? optionData.affectsExterior\r\n                        : (optionData && optionData.affectsVisuals !== false);\r\n                    if (affectsThisView) {\r\n                        parts.push(chineseNames.options[config.option.id]);\r\n                    }\r\n                }\r\n                filename = parts.join('-');\r\n                basePath = `${chineseFolder}\/${variantFolder}\/variant-attribute\/exterior\/angle-0\/`;\r\n            } else {\r\n                const parts = [int, ext];\r\n                if (config.option.id !== 'none') {\r\n                    const optionData = MODEL_CONFIG.options[config.option.id];\r\n                    \/\/ Check if we switched variant folders for this option\r\n                    const didVariantSwitch = (config.option.id === 'platinum' &&\r\n                                              config.model.id === 'pro' &&\r\n                                              MODEL_CONFIG.models['max']);\r\n\r\n                    if (!didVariantSwitch) {\r\n                        \/\/ Check if option affects interior view\r\n                        const affectsThisView = optionData && optionData.affectsInterior !== undefined\r\n                            ? optionData.affectsInterior\r\n                            : (optionData && optionData.affectsVisuals !== false);\r\n                        if (affectsThisView) {\r\n                            parts.push(chineseNames.options[config.option.id]);\r\n                        }\r\n                    }\r\n                }\r\n                filename = parts.join('-');\r\n                basePath = `${chineseFolder}\/${variantFolder}\/variant-attribute\/interior\/angle-0\/`;\r\n            }\r\n\r\n            return {\r\n                avif: `${imagePath}avif\/${basePath}${filename}.avif`,\r\n                webp: `${imagePath}webp\/${basePath}${filename}.webp`\r\n            };\r\n        }\r\n\r\n        function isMobile() {\r\n            return window.innerWidth <= 768;\r\n        }\r\n\r\n        function formatPrice(price) {\r\n            return price.toLocaleString('en-US') + ' AMD';\r\n        }\r\n\r\n        function calculateTotalPrice() {\r\n            \/\/ Calculate sum of multi-options for models with optionMode: 'multiple'\r\n            let multiOptionsSum = 0;\r\n            if (MODEL_CONFIG && MODEL_CONFIG.optionMode === 'multiple') {\r\n                multiOptionsSum = selectedConfig.options.reduce((sum, opt) => sum + opt.price, 0);\r\n            }\r\n\r\n            return selectedConfig.model.price +\r\n                selectedConfig.exterior.price +\r\n                selectedConfig.wheels.price +\r\n                selectedConfig.interior.price +\r\n                selectedConfig.option.price +\r\n                multiOptionsSum;\r\n        }\r\n\r\n        function updatePricing() {\r\n            const basePrice = selectedConfig.model.price;\r\n\r\n            \/\/ Calculate options price including multi-options\r\n            let multiOptionsSum = 0;\r\n            if (MODEL_CONFIG && MODEL_CONFIG.optionMode === 'multiple') {\r\n                multiOptionsSum = selectedConfig.options.reduce((sum, opt) => sum + opt.price, 0);\r\n            }\r\n\r\n            const optionsPrice = selectedConfig.exterior.price + selectedConfig.wheels.price + selectedConfig.interior.price + selectedConfig.option.price + multiOptionsSum;\r\n            const totalPrice = calculateTotalPrice();\r\n\r\n            const basePriceEl = document.getElementById('basePrice');\r\n            const optionsPriceEl = document.getElementById('optionsPrice');\r\n            const totalPriceEl = document.getElementById('totalPrice');\r\n\r\n            const basePriceText = formatPrice(basePrice);\r\n            const optionsPriceText = formatPrice(optionsPrice);\r\n            const totalPriceText = formatPrice(totalPrice);\r\n\r\n            \/\/ Collect names of options that add to the price\r\n            const paidOptionNames = [];\r\n            if (selectedConfig.exterior.price > 0) {\r\n                paidOptionNames.push(selectedConfig.exterior.name);\r\n            }\r\n            if (selectedConfig.wheels.price > 0) {\r\n                paidOptionNames.push(selectedConfig.wheels.name);\r\n            }\r\n            if (selectedConfig.interior.price > 0) {\r\n                paidOptionNames.push(selectedConfig.interior.name);\r\n            }\r\n            if (selectedConfig.option.price > 0 && selectedConfig.option.id !== 'none') {\r\n                paidOptionNames.push(selectedConfig.option.name);\r\n            }\r\n            \/\/ Add multi-options with price > 0\r\n            if (MODEL_CONFIG && MODEL_CONFIG.optionMode === 'multiple') {\r\n                selectedConfig.options.forEach(opt => {\r\n                    if (opt.price > 0) {\r\n                        paidOptionNames.push(opt.name);\r\n                    }\r\n                });\r\n            }\r\n\r\n            \/\/ Update the Options label to include option names\r\n            const optionsLabel = optionsPriceEl.previousElementSibling;\r\n            if (optionsLabel && optionsLabel.classList.contains('status-label')) {\r\n                if (paidOptionNames.length > 0) {\r\n                    optionsLabel.textContent = 'Options: ' + paidOptionNames.join(' - ');\r\n                } else {\r\n                    optionsLabel.textContent = 'Options:';\r\n                }\r\n            }\r\n\r\n            \/\/ Fade out, update, fade in animation\r\n            function updateWithFade(element, newText) {\r\n                if (element.textContent !== newText) {\r\n                    element.style.opacity = '0.4';\r\n                    setTimeout(() => {\r\n                        element.textContent = newText;\r\n                        element.style.opacity = '1';\r\n                    }, 150);\r\n                }\r\n            }\r\n\r\n            updateWithFade(basePriceEl, basePriceText);\r\n            updateWithFade(optionsPriceEl, optionsPriceText);\r\n            updateWithFade(totalPriceEl, totalPriceText);\r\n        }\r\n\r\n        function selectModel(id, name, price) {\r\n            selectedConfig.model = { id, name, price };\r\n\r\n            document.querySelectorAll('.config-section:first-child .wheel-option').forEach(option => {\r\n                option.classList.remove('selected');\r\n            });\r\n            event.currentTarget.classList.add('selected');\r\n\r\n            \/\/ Update wheel pricing if dependent on model\r\n            if (MODEL_CONFIG) {\r\n                const currentWheelData = MODEL_CONFIG.wheels[selectedConfig.wheels.id];\r\n                if (currentWheelData && typeof currentWheelData.price === 'object') {\r\n                    selectedConfig.wheels.price = currentWheelData.price[id] || 0;\r\n                }\r\n\r\n                \/\/ Check if current wheel is disabled for this model, switch to first available\r\n                if (currentWheelData && currentWheelData.disabledFor && currentWheelData.disabledFor.includes(id)) {\r\n                    const availableWheelId = Object.keys(MODEL_CONFIG.wheels).find(wheelId => {\r\n                        const wheelData = MODEL_CONFIG.wheels[wheelId];\r\n                        return !wheelData.disabledFor || !wheelData.disabledFor.includes(id);\r\n                    });\r\n                    if (availableWheelId) {\r\n                        const wheelData = MODEL_CONFIG.wheels[availableWheelId];\r\n                        let wheelPrice = wheelData.price;\r\n                        if (typeof wheelPrice === 'object') {\r\n                            wheelPrice = wheelPrice[id] || 0;\r\n                        }\r\n                        selectedConfig.wheels = {\r\n                            id: availableWheelId,\r\n                            name: wheelData.name,\r\n                            desc: wheelData.desc || '',\r\n                            price: wheelPrice\r\n                        };\r\n                    }\r\n                }\r\n\r\n                \/\/ Update option pricing if dependent on model\r\n                if (selectedConfig.option.id !== 'none') {\r\n                    const optionData = MODEL_CONFIG.options[selectedConfig.option.id];\r\n                    if (optionData && typeof optionData.price === 'object') {\r\n                        selectedConfig.option.price = optionData.price[id] || 0;\r\n                    }\r\n                }\r\n\r\n                \/\/ Re-render UI to update prices\r\n                renderConfigUI();\r\n            }\r\n\r\n            updatePricing();\r\n            updateConfigDetails();\r\n            updateImage(currentView); \/\/ Update current view (exterior or interior)\r\n        }\r\n\r\n        function selectOption(id, name) {\r\n            if (!MODEL_CONFIG) return;\r\n            const optionType = MODEL_CONFIG.optionType;\r\n            const optionMode = MODEL_CONFIG.optionMode;\r\n            const optionData = MODEL_CONFIG.options[id];\r\n\r\n            \/\/ Get option price (can be object or number)\r\n            let optionPrice = 0;\r\n            if (optionData) {\r\n                if (typeof optionData.price === 'number') {\r\n                    optionPrice = optionData.price;\r\n                } else if (typeof optionData.price === 'object') {\r\n                    optionPrice = optionData.price[selectedConfig.model.id] || 0;\r\n                }\r\n            }\r\n\r\n            \/\/ Handle multi-option mode (i6 model)\r\n            if (optionMode === 'multiple') {\r\n                \/\/ Check if option is already selected\r\n                const index = selectedConfig.options.findIndex(opt => opt.id === id);\r\n\r\n                if (index >= 0) {\r\n                    \/\/ Deselect option\r\n                    selectedConfig.options.splice(index, 1);\r\n                } else {\r\n                    \/\/ Select option\r\n                    selectedConfig.options.push({ id, name, price: optionPrice });\r\n                }\r\n\r\n                \/\/ Handle AWD + 21\" wheels bundle (i6 specific)\r\n                \/\/ When AWD is selected, check if user has 21\" wheels and make them free\r\n                if (currentModelKey === 'i6') {\r\n                    const hasAWD = selectedConfig.options.some(opt => opt.id === 'awd-system');\r\n                    const has21Wheels = selectedConfig.wheels.id === '21-7-spoke';\r\n\r\n                    if (hasAWD && has21Wheels) {\r\n                        \/\/ AWD bundles with 21\" wheels - make wheels free\r\n                        selectedConfig.wheels.price = 0;\r\n                    } else if (!hasAWD && has21Wheels) {\r\n                        \/\/ No AWD but has 21\" wheels - restore original price\r\n                        const wheelData = MODEL_CONFIG.wheels['21-7-spoke'];\r\n                        selectedConfig.wheels.price = wheelData.price || 0;\r\n                    }\r\n                }\r\n\r\n                \/\/ Re-render UI to update selected state on option buttons\r\n                renderConfigUI();\r\n            } else {\r\n                \/\/ Single-option mode (existing behavior)\r\n                const optionEl = document.querySelector('[data-option-id]');\r\n\r\n                \/\/ Toggle functionality\r\n                if (selectedConfig.option.id === id) {\r\n                    if (optionEl) optionEl.classList.remove('selected');\r\n                    selectedConfig.option = { id: 'none', name: 'N\/A', price: 0 };\r\n                } else {\r\n                    selectedConfig.option = { id, name, price: optionPrice };\r\n                    if (optionEl) optionEl.classList.add('selected');\r\n                }\r\n            }\r\n\r\n            updatePricing();\r\n            updateConfigDetails();\r\n\r\n            \/\/ Only reload image if option affects any view's visuals\r\n            if (optionData) {\r\n                \/\/ Check if option affects exterior or interior using view-specific flags\r\n                const affectsExterior = optionData.affectsExterior !== undefined\r\n                    ? optionData.affectsExterior\r\n                    : (optionData.affectsVisuals !== false);\r\n                const affectsInterior = optionData.affectsInterior !== undefined\r\n                    ? optionData.affectsInterior\r\n                    : (optionData.affectsVisuals !== false);\r\n\r\n                \/\/ If option affects any view, reload current view image and preload adjacent\r\n                if (affectsExterior || affectsInterior) {\r\n                    \/\/ Switch to interior view for audio\/speaker options before updating\r\n                    if (optionType === 'audio' && affectsInterior && currentView !== 'interior') {\r\n                        switchView('interior');\r\n                    } else {\r\n                        updateImage(currentView);\r\n                        preloadAdjacentOptions();\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\t\t\r\n\t\t\/\/ Embedded model configurations (avoids CORS issues with file:\/\/ protocol)\r\n\t\tconst ALL_MODEL_CONFIGS = {\r\n\t\t\r\n  \"i8\": {\r\n    \"displayName\": \"Li i8\",\r\n    \"subtitle\": \"Premium Electric Vehicle\",\r\n    \"chineseFolder\": \"\u7406\u60f3i8\",\r\n    \"optionType\": \"option\",\r\n    \"includeWheelsInFilename\": true,\r\n    \"models\": {\r\n      \"i8\": {\r\n        \"name\": \"i8\",\r\n        \"variantFolder\": \"\u7406\u60f3i8\",\r\n        \"price\": 22750000,\r\n        \"specs\": \"5C Fast Charging: up to 500 km range in just 10 minutes<br>CLTC Range: 720 km<br>Battery Capacity: 97.8 kWh<br>Drivetrain: 4\u00d74 (All-Wheel Drive)<br>System: NVIDIA DRIVE Thor-U<br>Air Suspension: height-adjustable pneumatic system\"\r\n      }\r\n    },\r\n    \"exteriorColors\": {\r\n      \"white-pearl\": { \"name\": \"White Pearl\", \"chinese\": \"\u767d\u8272\u73cd\u73e0\u6f06\", \"price\": 0 },\r\n      \"silver-metallic\": { \"name\": \"Silver Metallic\", \"chinese\": \"\u94f6\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"black-metallic\": { \"name\": \"Black Metallic\", \"chinese\": \"\u9ed1\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"elephant-gray\": { \"name\": \"Elephant Gray\", \"chinese\": \"\u5c0f\u8c61\u7070\u7279\u522b\u7248\u51b7\u5149\u6f06\", \"price\": 350000 },\r\n      \"sky-blue\": { \"name\": \"Sky Blue\", \"chinese\": \"\u5929\u7a7a\u84dd\u7279\u522b\u7248\u51b7\u5149\u6f06\", \"price\": 350000 }\r\n    },\r\n    \"wheels\": {\r\n      \"20-aero\": { \"name\": \"20\u2033 Aero Wheels\", \"desc\": \"255\/50 R20 Silent Tires\", \"chinese\": \"20\u82f1\u5bf8\u4f4e\u98ce\u963b\u8f6e\u6bc2\", \"price\": 0 },\r\n      \"21-aero\": { \"name\": \"21\u2033 Aero Wheels\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"21\u82f1\u5bf8\u4f4e\u98ce\u963b\u8f6e\u6bc2\", \"price\": 350000 },\r\n      \"21-7-spoke\": { \"name\": \"21\u2033 7-Spoke Sport Wheels\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"21\u82f1\u5bf8\u4e03\u8f90\u8fd0\u52a8\u8f6e\u6bc2\", \"price\": 350000 }\r\n    },\r\n    \"interiorColors\": {\r\n      \"cream\": { \"name\": \"Cream\", \"chinese\": \"\u767d\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"brown\": { \"name\": \"Brown\", \"chinese\": \"\u7070\u68d5\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"orange\": { \"name\": \"Orange\", \"chinese\": \"\u6a59\u9ec4\u8272\u5185\u9970\", \"price\": 0 }\r\n    },\r\n    \"options\": {\r\n      \"rear-screen\": { \"name\": \"Rear Entertainment Screen\", \"chinese\": \"\u540e\u8231\u5a31\u4e50\u5c4f\u5957\u88c5\", \"price\": 700000 }\r\n    },\r\n    \"defaultConfig\": {\r\n      \"model\": \"i8\",\r\n      \"wheels\": \"20-aero\",\r\n      \"exterior\": \"white-pearl\",\r\n      \"interior\": \"cream\",\r\n      \"option\": \"none\"\r\n    }\r\n  },\r\n  \"i6\": {\r\n    \"displayName\": \"Li i6\",\r\n    \"subtitle\": \"Premium Electric Vehicle\",\r\n    \"chineseFolder\": \"\u7406\u60f3i6\",\r\n    \"optionMode\": \"multiple\",\r\n    \"includeWheelsInFilename\": true,\r\n    \"models\": {\r\n      \"i6\": {\r\n        \"name\": \"i6\",\r\n        \"variantFolder\": \"\u7406\u60f3i6\",\r\n        \"price\": 17900000,\r\n        \"specs\": \"Extended Range Electric Vehicle<br>Premium Interior<br>Advanced Driver Assistance<br>Intelligent Cockpit System\"\r\n      }\r\n    },\r\n    \"exteriorColors\": {\r\n      \"white-pearl\": { \"name\": \"White Pearl\", \"chinese\": \"\u73cd\u73e0\u767d\", \"price\": 0 },\r\n      \"alien-silver\": { \"name\": \"Alien Silver\", \"chinese\": \"\u5916\u661f\u94f6\", \"price\": 0 },\r\n      \"darth-vader-black\": { \"name\": \"Darth Vader Black\", \"chinese\": \"\u9ed1\u6b66\u58eb\", \"price\": 0 },\r\n      \"shark-gray\": { \"name\": \"Shark Gray\", \"chinese\": \"\u5c0f\u7070\u9ca8\", \"price\": 420000 },\r\n      \"clouds-yellow\": { \"name\": \"Clouds Yellow\", \"chinese\": \"\u4e91\u6735\u9ec4\", \"price\": 420000 }\r\n    },\r\n    \"wheels\": {\r\n      \"20-low-drag\": { \"name\": \"20\u2033 Low-drag Wheels\", \"desc\": \"255\/50 R20 Silent Tires\", \"chinese\": \"20\u82f1\u5bf8\u4f4e\u98ce\u963b\u8f6e\u6bc2\", \"price\": 0 },\r\n      \"21-7-spoke\": { \"name\": \"21\u2033 7-Spoke Sport Wheels\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"21\u82f1\u5bf8\u4e03\u8f90\u8fd0\u52a8\u8f6e\u6bc2\", \"price\": 700000, \"bundledWith\": \"awd-system\" }\r\n    },\r\n    \"interiorColors\": {\r\n      \"white\": { \"name\": \"White\", \"chinese\": \"\u767d\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"brown\": { \"name\": \"Brown\", \"chinese\": \"\u7070\u68d5\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"orange\": { \"name\": \"Orange\", \"chinese\": \"\u6a59\u9ec4\u8272\u5185\u9970\", \"price\": 0 }\r\n    },\r\n    \"options\": {\r\n      \"awd-system\": {\r\n        \"name\": \"Dual Motor AWD System\",\r\n        \"chinese\": \"\u53cc\u7535\u673a\u56db\u9a71\",\r\n        \"chineseBase\": \"\u540e\u9a71\",\r\n        \"price\": 1400000,\r\n        \"affectsExterior\": false,\r\n        \"affectsInterior\": true,\r\n        \"category\": \"drivetrain\"\r\n      },\r\n      \"platinum-audio\": {\r\n        \"name\": \"Platinum Audio\",\r\n        \"chinese\": \"\u94c2\u91d1\u97f3\u54cd\",\r\n        \"chineseBase\": \"\u9ad8\u7ea7\u97f3\u54cd\",\r\n        \"price\": 350000,\r\n        \"affectsExterior\": false,\r\n        \"affectsInterior\": true,\r\n        \"category\": \"audio\"\r\n      },\r\n      \"rear-screen\": {\r\n        \"name\": \"Rear Entertainment Screen\",\r\n        \"chinese\": \"\u540e\u8231\u5a31\u4e50\u5c4f+\u6d41\u5a92\u4f53\u540e\u89c6\u955c\",\r\n        \"chineseBase\": \"\u65e0\u540e\u8231\u5a31\u4e50\u5c4f\",\r\n        \"price\": 700000,\r\n        \"affectsExterior\": true,\r\n        \"affectsInterior\": true,\r\n        \"category\": \"screen\"\r\n      },\r\n      \"soft-close\": {\r\n        \"name\": \"Soft Close Doors\",\r\n        \"price\": 350000,\r\n        \"affectsExterior\": false,\r\n        \"affectsInterior\": false,\r\n        \"category\": \"comfort\"\r\n      },\r\n      \"refrigerator\": {\r\n        \"name\": \"Smart Refrigerator\",\r\n        \"price\": 350000,\r\n        \"affectsExterior\": false,\r\n        \"affectsInterior\": false,\r\n        \"category\": \"comfort\"\r\n      },\r\n      \"air-suspension\": {\r\n        \"name\": \"Magic Carpet Air Suspension\",\r\n        \"price\": 1100000,\r\n        \"affectsExterior\": false,\r\n        \"affectsInterior\": false,\r\n        \"category\": \"performance\"\r\n      },\r\n      \"trailer-hitch\": {\r\n        \"name\": \"Trailer Hitch\",\r\n        \"price\": 210000,\r\n        \"affectsExterior\": false,\r\n        \"affectsInterior\": false,\r\n        \"category\": \"utility\"\r\n      }\r\n    },\r\n    \"defaultConfig\": {\r\n      \"model\": \"i6\",\r\n      \"wheels\": \"20-low-drag\",\r\n      \"exterior\": \"white-pearl\",\r\n      \"interior\": \"white\",\r\n      \"options\": []\r\n    }\r\n  },\r\n  \"l6\": {\r\n    \"displayName\": \"Li L6\",\r\n    \"subtitle\": \"Premium Electric Vehicle\",\r\n    \"chineseFolder\": \"\u7406\u60f3L6\",\r\n    \"optionType\": \"audio\",\r\n    \"includeWheelsInFilename\": true,\r\n    \"models\": {\r\n      \"pro\": { \"name\": \"L6 Pro\", \"variantFolder\": \"\u7406\u60f3L6 Pro\", \"price\": 17790000,\r\n                \"specs\": \"Range: 212km<br>Intelligent Driving: High-speed<br>Cockpit: Quad-screen<br>Audio: 19-speaker\"\r\n\r\n       },\r\n      \"max\": { \"name\": \"L6 Max\", \"variantFolder\": \"\u7406\u60f3L6 Max\", \"price\": 19630000, \"specs\": \"Range: 212km<br>Intelligent Driving: City+Highway<br>Audio: Platinum<br>Features: Smart refrigerator\" }\r\n    },\r\n    \"exteriorColors\": {\r\n      \"white-pearl\": { \"name\": \"White Pearl\", \"chinese\": \"\u767d\u8272\u73cd\u73e0\u6f06\", \"price\": 0 },\r\n      \"silver-metallic\": { \"name\": \"Silver Metallic\", \"chinese\": \"\u94f6\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"gray-metallic\": { \"name\": \"Gray Metallic\", \"chinese\": \"\u7070\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"black-metallic\": { \"name\": \"Black Metallic\", \"chinese\": \"\u9ed1\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"elephant-grey\": { \"name\": \"Elephant Grey\", \"chinese\": \"\u5c0f\u8c61\u7070\u7279\u522b\u7248\u51b7\u5149\u6f06\", \"price\": 350000 },\r\n      \"sky-cyan\": { \"name\": \"Mint Blue\", \"chinese\": \"\u5929\u9752\u8272\u7279\u522b\u7248\u73cd\u73e0\u6f06\", \"price\": 350000 },\r\n      \"deep-green\": { \"name\": \"Deep Green\", \"chinese\": \"\u7eff\u8272\u7279\u522b\u7248\u73cd\u73e0\u6f06\", \"price\": 350000 }\r\n    },\r\n    \"wheels\": {\r\n      \"20-silver-grey\": { \"name\": \"20\u2033 Silver-Grey\", \"desc\": \"255\/50 R20 Silent Tires\", \"chinese\": \"\u5168\u65b020\u82f1\u5bf8\u94f6\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 0 },\r\n      \"20-black-grey\": { \"name\": \"20\u2033 Black-Grey\", \"desc\": \"255\/50 R20 Silent Tires\", \"chinese\": \"\u5168\u65b020\u82f1\u5bf8\u9ed1\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 0 },\r\n      \"21-silver-grey\": { \"name\": \"21\u2033 Silver-Grey\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"\u5168\u65b021\u82f1\u5bf8\u94f6\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 350000 },\r\n      \"21-black-grey\": { \"name\": \"21\u2033 Black-Grey\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"\u5168\u65b021\u82f1\u5bf8\u9ed1\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 350000 }\r\n    },\r\n    \"interiorColors\": {\r\n      \"black-brown\": { \"name\": \"Black-Brown\", \"chinese\": \"\u9ed1\u68d5\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-orange\": { \"name\": \"Black-Orange\", \"chinese\": \"\u9ed1\u6a59\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-white\": { \"name\": \"Black-White\", \"chinese\": \"\u9ed1\u767d\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-sport\": { \"name\": \"Black Sport\", \"chinese\": \"\u9ed1\u8272\u8fd0\u52a8\u5185\u9970\", \"price\": 0 }\r\n    },\r\n    \"options\": {\r\n      \"platinum\": { \"name\": \"Platinum 19-speaker\", \"chinese\": \"19\u626c\u58f0\u5668\u94c2\u91d1\u97f3\u54cd\", \"price\": { \"pro\": 350000, \"max\": 0 }, \"disabledFor\": [\"max\", \"pro\"], \"affectsExterior\": false, \"affectsInterior\": true }\r\n    },\r\n    \"defaultConfig\": {\r\n      \"model\": \"pro\",\r\n      \"wheels\": \"20-silver-grey\",\r\n      \"exterior\": \"white-pearl\",\r\n      \"interior\": \"black-brown\",\r\n      \"option\": \"none\"\r\n    }\r\n  },\r\n  \"l7\": {\r\n    \"displayName\": \"Li L7\",\r\n    \"subtitle\": \"Premium Electric Vehicle\",\r\n    \"chineseFolder\": \"\u7406\u60f3L7\",\r\n    \"optionType\": \"footboards\",\r\n    \"includeWheelsInFilename\": true,\r\n    \"interiorPattern\": \"exterior-first\",\r\n    \"models\": {\r\n      \"pro\": { \"name\": \"L7 Pro\", \"variantFolder\": \"\u7406\u60f3L7 Pro\", \"price\": 20540000, \"specs\" : \"CLTC Range: 225 kilometers<br>Cockpit: Quad-screen interactive<br>Intelligent Driving: High-speed<br>Audio: 19-speaker premium\" },\r\n      \"max\": { \"name\": \"L7 Max\", \"variantFolder\": \"\u7406\u60f3L7 Max\", \"price\": 22870000, \"specs\" : \"CLTC Range: 225 kilometers<br>Cockpit: Quad-screen interactive<br>Intelligent Driving: City+Highway<br>Audio: Platinum 19-speaker<br>Refrigerator: Intelligent cold and warm dual-purpose\" },\r\n      \"ultra\": { \"name\": \"L7 Ultra\", \"variantFolder\": \"\u7406\u60f3L7 Ultra\", \"price\": 24510000, \"specs\" : \"CLTC Range: 286 kilometers<br>Cockpit: Five-screen interactive<br>Intelligent Driving: City+Highway<br>Audio: 21-speaker platinum<br>Refrigerator: Intelligent cold and warm dual-purpose\" }\r\n    },\r\n    \"exteriorColors\": {\r\n      \"white-pearl\": { \"name\": \"White Pearl\", \"chinese\": \"\u767d\u8272\u73cd\u73e0\u6f06\", \"price\": 0 },\r\n      \"silver-metallic\": { \"name\": \"Silver Metallic\", \"chinese\": \"\u94f6\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"gray-metallic\": { \"name\": \"Gray Metallic\", \"chinese\": \"\u7070\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"black-metallic\": { \"name\": \"Black Metallic\", \"chinese\": \"\u9ed1\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"deep-green\": { \"name\": \"Deep Green\", \"chinese\": \"\u7eff\u8272\u7279\u522b\u7248\u73cd\u73e0\u6f06\", \"price\": 350000 },\r\n      \"blue-gray\": { \"name\": \"Blue Gray\", \"chinese\": \"\u84dd\u7070\u7279\u522b\u7248\u51b7\u5149\u6f06\", \"price\": 350000 },\r\n      \"baby-blue\": { \"name\": \"Baby Blue\", \"chinese\": \"Baby Blue\u200b\u7279\u522b\u7248\u73cd\u73e0\u6f06\", \"price\": 350000 }\r\n    },\r\n    \"wheels\": {\r\n      \"20-silver-grey\": { \"name\": \"20\u2033 Silver-Grey\", \"desc\": \"255\/50 R20 Silent Tires\", \"chinese\": \"\u5168\u65b020\u82f1\u5bf8\u94f6\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 0, \"disabledFor\": [\"ultra\"] },\r\n      \"20-black-grey\": { \"name\": \"20\u2033 Black-Grey\", \"desc\": \"255\/50 R20 Silent Tires\", \"chinese\": \"\u5168\u65b020\u82f1\u5bf8\u9ed1\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 0, \"disabledFor\": [\"ultra\"] },\r\n      \"21-silver-grey\": { \"name\": \"21\u2033 Silver-Grey\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"\u5168\u65b021\u82f1\u5bf8\u94f6\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": { \"pro\": 350000, \"max\": 350000, \"ultra\": 0 } },\r\n      \"21-black-grey\": { \"name\": \"21\u2033 Black-Grey\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"\u5168\u65b021\u82f1\u5bf8\u9ed1\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": { \"pro\": 350000, \"max\": 350000, \"ultra\": 0 } }\r\n    },\r\n    \"interiorColors\": {\r\n      \"black-brown\": { \"name\": \"Black-Brown\", \"chinese\": \"\u9ed1\u68d5\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-orange\": { \"name\": \"Black-Orange\", \"chinese\": \"\u9ed1\u6a59\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-white\": { \"name\": \"Black-White\", \"chinese\": \"\u9ed1\u767d\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-sport\": { \"name\": \"Black Sport\", \"chinese\": \"\u9ed1\u8272\u8fd0\u52a8\u5185\u9970\", \"price\": 0 }\r\n    },\r\n    \"options\": {\r\n      \"footboards\": { \"name\": \"Electric Running Boards\", \"chinese\": \"\u7535\u52a8\u8e0f\u677f\", \"price\": 350000, \"affectsExterior\": false, \"affectsInterior\": false }\r\n    },\r\n    \"defaultConfig\": {\r\n      \"model\": \"pro\",\r\n      \"wheels\": \"20-silver-grey\",\r\n      \"exterior\": \"white-pearl\",\r\n      \"interior\": \"black-brown\",\r\n      \"option\": \"none\"\r\n    }\r\n  },\r\n  \"l9\": {\r\n    \"displayName\": \"Li L9\",\r\n    \"subtitle\": \"Premium Electric Vehicle\",\r\n    \"chineseFolder\": \"\u7406\u60f3L9\",\r\n    \"optionType\": \"footboards\",\r\n    \"includeWheelsInFilename\": true,\r\n    \"exteriorPattern\": \"interior-before-wheels\",\r\n    \"interiorPattern\": \"exterior-first\",\r\n    \"models\": {\r\n      \"pro\": { \"name\": \"L9 Pro\", \"variantFolder\": \"\u7406\u60f3L9 Pro\", \"price\": 27620000, \"specs\" : \"CLTC Range: 280 kilometers<br>Cockpit: Five-screen interactive<br>Intelligent Driving: High-speed<br>Audio: 21-speaker platinum<br>Seating: Zero-gravity queen seat\"},\r\n      \"ultra\": { \"name\": \"L9 Ultra\", \"variantFolder\": \"\u7406\u60f3L9 Ultra\", \"price\": 29350000, \"specs\" : \"CLTC Range: 280 kilometers<br>Cockpit: Five-screen interactive<br>Intelligent Driving: City + highway<br>Audio: 21-speaker platinum<br>Seating: Zero-gravity queen seat\" }\r\n    },\r\n    \"exteriorColors\": {\r\n      \"white-pearl\": { \"name\": \"White Pearl\", \"chinese\": \"\u767d\u8272\u73cd\u73e0\u6f06\", \"price\": 0 },\r\n      \"silver-metallic\": { \"name\": \"Silver Metallic\", \"chinese\": \"\u94f6\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"gray-metallic\": { \"name\": \"Gray Metallic\", \"chinese\": \"\u7070\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"black-metallic\": { \"name\": \"Black Metallic\", \"chinese\": \"\u9ed1\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"elegant-gray\": { \"name\": \"Elegant Gray\", \"chinese\": \"\u96c5\u7070\u7279\u522b\u7248\u51b7\u5149\u6f06\", \"price\": 350000 },\r\n      \"deep-green\": { \"name\": \"Deep Green\", \"chinese\": \"\u7eff\u8272\u7279\u522b\u7248\u73cd\u73e0\u6f06\", \"price\": 350000 },\r\n      \"purple\": { \"name\": \"Purple\", \"chinese\": \"\u7d2b\u8272\u7279\u522b\u7248\u73cd\u73e0\u6f06\", \"price\": 350000 }\r\n    },\r\n    \"wheels\": {\r\n      \"21-silver-grey\": { \"name\": \"21\u2033 Silver-Gray Two-tone\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"\u5168\u65b021\u82f1\u5bf8\u94f6\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 0 },\r\n      \"21-black-grey\": { \"name\": \"21\u2033 Black-Gray Two-tone\", \"desc\": \"265\/45 R21 Silent Tires\", \"chinese\": \"\u5168\u65b021\u82f1\u5bf8\u9ed1\u7070\u53cc\u8272\u8f6e\u6bc2\", \"price\": 0 }\r\n    },\r\n    \"interiorColors\": {\r\n      \"black-brown\": { \"name\": \"Black-Brown\", \"chinese\": \"\u9ed1\u68d5\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-orange\": { \"name\": \"Black-Orange\", \"chinese\": \"\u9ed1\u6a59\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-white\": { \"name\": \"Black-White\", \"chinese\": \"\u9ed1\u767d\u53cc\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"black-sport\": { \"name\": \"Black Sport\", \"chinese\": \"\u9ed1\u8272\u8fd0\u52a8\u5185\u9970\", \"price\": 0 }\r\n    },\r\n    \"options\": {\r\n      \"footboards\": { \"name\": \"Electric Running Boards\", \"chinese\": \"\u7535\u52a8\u8e0f\u677f\", \"price\": { \"pro\": 350000, \"ultra\": 0 }, \"disabledFor\": [\"ultra\"], \"affectsExterior\": false, \"affectsInterior\": false }\r\n    },\r\n    \"defaultConfig\": {\r\n      \"model\": \"pro\",\r\n      \"wheels\": \"21-silver-grey\",\r\n      \"exterior\": \"white-pearl\",\r\n      \"interior\": \"black-brown\",\r\n      \"option\": \"none\"\r\n    }\r\n  },\r\n  \"mega\": {\r\n    \"displayName\": \"Li MEGA\",\r\n    \"subtitle\": \"Premium Electric Vehicle\",\r\n    \"chineseFolder\": \"\u7406\u60f3MEGA\",\r\n    \"optionType\": \"footboards\",\r\n    \"includeWheelsInFilename\": false,\r\n    \"interiorPattern\": \"exterior-first\",\r\n    \"models\": {\r\n      \"ultra\": { \"name\": \"Mega Ultra\", \"variantFolder\": \"\u7406\u60f3MEGA Ultra\", \"price\": 36070000, \"specs\" : \"5C Fast Charging: 500km in 10min<br>Battery Capacity: 102.7kWh<br>CLTC Range: 710km<br>Domain Controller: NVIDIA DRIVE Thor-U (700 TOPS)<br>Massage: Spa-grade 16-point (10 back + 6 cushion)\" },\r\n      \"home\": { \"name\": \"Mega Home\", \"variantFolder\": \"\u7406\u60f3MEGA Home\", \"price\": 38150000, \"specs\" : \"5C Fast Charging: 500km in 10min<br>Battery Capacity: 102.7kWh<br>CLTC Range: 710km<br>Domain Controller: NVIDIA DRIVE Thor-U (700 TOPS)<br>Massage: Hot Stone 18-point kneading (12 back + 6 cushion)\" }\r\n    },\r\n    \"exteriorColors\": {\r\n      \"panda-pearl\": { \"name\": \"Panda Pearl\", \"chinese\": \"\u718a\u732b\u767d\u73cd\u73e0\u6f06\", \"price\": 0 },\r\n      \"silver-metallic\": { \"name\": \"Silver Metallic\", \"chinese\": \"\u94f6\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"gray-metallic\": { \"name\": \"Gray Metallic\", \"chinese\": \"\u7070\u8272\u91d1\u5c5e\u6f06\", \"price\": 0 },\r\n      \"elephant-gray\": { \"name\": \"Elephant Gray\", \"chinese\": \"\u5927\u8c61\u7070\u7279\u522b\u7248\u73cd\u73e0\u6f06\", \"price\": 350000 }\r\n    },\r\n    \"wheels\": {\r\n      \"18-black-gray\": { \"name\": \"18\u2033 Black-gray Low-drag\", \"desc\": \"245\/60 R18 Silent Tires\", \"chinese\": \"18\u82f1\u5bf8\u9ed1\u7070\u4f4e\u98ce\u963b\", \"price\": 0 }\r\n    },\r\n    \"interiorColors\": {\r\n      \"cream\": { \"name\": \"Cream\", \"chinese\": \"\u767d\u8272\u5185\u9970\", \"price\": 0 },\r\n      \"brown\": { \"name\": \"Brown\", \"chinese\": \"\u68d5\u8272\u5185\u9970\", \"price\": 0 }\r\n    },\r\n    \"options\": {\r\n      \/\/\"footboards\": { \"name\": \"Electric Running Boards\", \"chinese\": \"\u7535\u52a8\u8e0f\u677f\", \"price\": 0, \"disabledFor\": [\"ultra\", \"home\"], \"alwaysIncluded\": true, \"affectsExterior\": false, \"affectsInterior\": false }\r\n    },\r\n    \"defaultConfig\": {\r\n      \"model\": \"ultra\",\r\n      \"wheels\": \"18-black-gray\",\r\n      \"exterior\": \"panda-pearl\",\r\n      \"interior\": \"cream\",\r\n      \"option\": \"none\"\r\n    }\r\n  }\r\n\r\n\r\n\t\t};\r\n        \/\/ Load configuration from URL path or query parameter\r\n        \/\/ Tries path first (e.g., \/en\/configurator-l7\/), then query (?model=l7)\r\n        function getModelFromURL() {\r\n            const pathname = window.location.pathname;\r\n            const match = pathname.match(\/configurator-([^\\\/]+)\/);\r\n            if (match) return match[1];\r\n\r\n            const params = new URLSearchParams(window.location.search);\r\n            return params.get('model') || 'i8'; \/\/ Default to i8\r\n        }\r\n\r\n        \/\/ Load model config from embedded data\r\n        async function loadModelConfig() {\r\n            try {\r\n                const allConfigs = ALL_MODEL_CONFIGS;\r\n\r\n                currentModelKey = getModelFromURL();\r\n                MODEL_CONFIG = allConfigs[currentModelKey];\r\n\r\n                if (!MODEL_CONFIG) {\r\n                    console.error(`Model ${currentModelKey} not found in config`);\r\n                    currentModelKey = 'i8';\r\n                    MODEL_CONFIG = allConfigs['i8'];\r\n                }\r\n\r\n                \/\/ Build chinese names lookup\r\n                chineseNames = {\r\n                    exteriorColors: {},\r\n                    wheels: {},\r\n                    interiorColors: {},\r\n                    options: {}\r\n                };\r\n\r\n                Object.keys(MODEL_CONFIG.exteriorColors).forEach(key => {\r\n                    chineseNames.exteriorColors[key] = MODEL_CONFIG.exteriorColors[key].chinese;\r\n                });\r\n\r\n                Object.keys(MODEL_CONFIG.wheels).forEach(key => {\r\n                    chineseNames.wheels[key] = MODEL_CONFIG.wheels[key].chinese;\r\n                });\r\n\r\n                Object.keys(MODEL_CONFIG.interiorColors).forEach(key => {\r\n                    chineseNames.interiorColors[key] = MODEL_CONFIG.interiorColors[key].chinese;\r\n                });\r\n\r\n                Object.keys(MODEL_CONFIG.options).forEach(key => {\r\n                    chineseNames.options[key] = MODEL_CONFIG.options[key].chinese;\r\n                });\r\n\r\n                \/\/ Set initial configuration from defaults\r\n                const defaultCfg = MODEL_CONFIG.defaultConfig;\r\n                const defaultModel = MODEL_CONFIG.models[defaultCfg.model];\r\n                selectedConfig.model = {\r\n                    id: defaultCfg.model,\r\n                    name: defaultModel.name,\r\n                    price: defaultModel.price\r\n                };\r\n\r\n                const defaultWheel = MODEL_CONFIG.wheels[defaultCfg.wheels];\r\n                let wheelPrice = defaultWheel.price;\r\n                if (typeof wheelPrice === 'object') {\r\n                    wheelPrice = wheelPrice[defaultCfg.model] || 0;\r\n                }\r\n\r\n                \/\/ Check if default wheel is disabled for default model, use first available wheel\r\n                let finalWheelId = defaultCfg.wheels;\r\n                let finalWheelData = defaultWheel;\r\n                let finalWheelPrice = wheelPrice;\r\n\r\n                if (defaultWheel.disabledFor && defaultWheel.disabledFor.includes(defaultCfg.model)) {\r\n                    const availableWheelId = Object.keys(MODEL_CONFIG.wheels).find(wheelId => {\r\n                        const wheelData = MODEL_CONFIG.wheels[wheelId];\r\n                        return !wheelData.disabledFor || !wheelData.disabledFor.includes(defaultCfg.model);\r\n                    });\r\n                    if (availableWheelId) {\r\n                        finalWheelId = availableWheelId;\r\n                        finalWheelData = MODEL_CONFIG.wheels[availableWheelId];\r\n                        finalWheelPrice = finalWheelData.price;\r\n                        if (typeof finalWheelPrice === 'object') {\r\n                            finalWheelPrice = finalWheelPrice[defaultCfg.model] || 0;\r\n                        }\r\n                    }\r\n                }\r\n\r\n                selectedConfig.wheels = {\r\n                    id: finalWheelId,\r\n                    name: finalWheelData.name,\r\n                    desc: finalWheelData.desc,\r\n                    price: finalWheelPrice\r\n                };\r\n\r\n                selectedConfig.exterior = {\r\n                    id: defaultCfg.exterior,\r\n                    name: MODEL_CONFIG.exteriorColors[defaultCfg.exterior].name,\r\n                    price: MODEL_CONFIG.exteriorColors[defaultCfg.exterior].price\r\n                };\r\n\r\n                selectedConfig.interior = {\r\n                    id: defaultCfg.interior,\r\n                    name: MODEL_CONFIG.interiorColors[defaultCfg.interior].name,\r\n                    price: MODEL_CONFIG.interiorColors[defaultCfg.interior].price\r\n                };\r\n\r\n                \/\/ Initialize options based on model mode\r\n                if (MODEL_CONFIG.optionMode === 'multiple') {\r\n                    \/\/ Multi-option mode: use options array from defaultConfig\r\n                    selectedConfig.options = defaultCfg.options || [];\r\n                    selectedConfig.option = { id: 'none', name: 'N\/A', price: 0 }; \/\/ Keep for compatibility\r\n                } else {\r\n                    \/\/ Single-option mode: use option field\r\n                    selectedConfig.option = { id: 'none', name: 'N\/A', price: 0 };\r\n                    selectedConfig.options = []; \/\/ Keep empty for compatibility\r\n                }\r\n\r\n                \/\/ Update page titles\r\n                document.title = `2026 ${MODEL_CONFIG.displayName} Configurator`;\r\n                document.getElementById('carTitle').textContent = `${MODEL_CONFIG.displayName} 2026`;\r\n                document.getElementById('carSubtitle').textContent = MODEL_CONFIG.subtitle;\r\n                document.getElementById('formSubtitle').textContent = `The wait is over. The ${MODEL_CONFIG.displayName} is now available near you.`;\r\n\r\n                \/\/ Render UI\r\n                renderConfigUI();\r\n\r\n            } catch (error) {\r\n                console.error('Error loading model config:', error);\r\n                document.getElementById('configContent').innerHTML = '<p style=\"padding: 20px; text-align: center; color: red;\">Error loading configuration. Please refresh the page.<\/p>';\r\n            }\r\n        }\r\n\r\n        \/\/ Helper function to generate picture element with AVIF and WebP sources\r\n        function generatePictureElement(basePath, alt, cssClass = '') {\r\n            \/\/ Generate AVIF and WebP sources for preview images\r\n            const avifSrc = basePath.replace('\/webp\/', '\/avif\/').replace('.webp', '.avif');\r\n            const webpSrc = basePath;\r\n\r\n            return `\r\n                <picture>\r\n                    <source srcset=\"${avifSrc}\" type=\"image\/avif\">\r\n                    <source srcset=\"${webpSrc}\" type=\"image\/webp\">\r\n                    <img decoding=\"async\" src=\"${webpSrc}\" alt=\"${alt}\" ${cssClass ? `class=\"${cssClass}\"` : ''} onerror=\"this.parentElement.style.display='none'\">\r\n                <\/picture>\r\n            `;\r\n        }\r\n\r\n        \/\/ Helper function to style spec labels (text before colons)\r\n        function formatSpecs(specs) {\r\n            if (!specs) return '';\r\n            \/\/ Replace \"Label:\" with \"<span class='spec-label'>Label:<\/span>\"\r\n            return specs.replace(\/([^<>\\n]+?):\/g, '<span class=\"spec-label\">$1:<\/span>');\r\n        }\r\n\r\n        \/\/ Render configuration UI dynamically\r\n        function renderConfigUI() {\r\n            const container = document.getElementById('configContent');\r\n            let html = '';\r\n\r\n            \/\/ Models section\r\n            html += '<div class=\"config-section\"><h3 class=\"section-title\">Model<\/h3>';\r\n            html += '<div style=\"display: grid; grid-template-columns: 1fr; gap: 16px;\">';\r\n            Object.keys(MODEL_CONFIG.models).forEach(modelId => {\r\n                const model = MODEL_CONFIG.models[modelId];\r\n                const selected = modelId === selectedConfig.model.id ? 'selected' : '';\r\n                const specs = model.specs || '';\r\n                const formattedSpecs = formatSpecs(specs);\r\n                html += `\r\n                    <div class=\"wheel-option ${selected}\" onclick=\"selectModel('${modelId}', '${model.name}', ${model.price})\">\r\n                        <div class=\"wheel-name\">${model.name}<\/div>\r\n                        ${formattedSpecs ? `<div class=\"wheel-desc\">${formattedSpecs}<\/div>` : ''}\r\n                        <div class=\"price-tag\">${formatPrice(model.price)}<\/div>\r\n                    <\/div>\r\n                `;\r\n            });\r\n            html += '<\/div><\/div>';\r\n\r\n            \/\/ Exterior colors\r\n            html += '<div class=\"config-section\"><h3 class=\"section-title\">Exterior Color<\/h3>';\r\n            html += '<div class=\"color-grid\">';\r\n            Object.keys(MODEL_CONFIG.exteriorColors).forEach(colorId => {\r\n                const color = MODEL_CONFIG.exteriorColors[colorId];\r\n                const selected = colorId === selectedConfig.exterior.id ? 'selected' : '';\r\n                const priceText = color.price === 0 ? '0 AMD' : `<span style=\"color: #fbbf24;\">+${formatPrice(color.price)}<\/span>`;\r\n                html += `\r\n                    <div class=\"color-option ext-${colorId} ${selected}\" onclick=\"selectExteriorColor('${colorId}', '${color.name}', ${color.price})\">\r\n                        <div class=\"color-label\">${color.name}<br><small>${priceText}<\/small><\/div>\r\n                    <\/div>\r\n                `;\r\n            });\r\n            html += '<\/div><\/div>';\r\n\r\n            \/\/ Interior colors\r\n            html += '<div class=\"config-section\"><h3 class=\"section-title\">Interior Color<\/h3>';\r\n            html += '<div class=\"interior-color-grid\">';\r\n            Object.keys(MODEL_CONFIG.interiorColors).forEach(colorId => {\r\n                const color = MODEL_CONFIG.interiorColors[colorId];\r\n                const selected = colorId === selectedConfig.interior.id ? 'selected' : '';\r\n                html += `\r\n                    <div class=\"color-option int-${colorId} ${selected}\" onclick=\"selectInteriorColor('${colorId}', '${color.name}', ${color.price})\">\r\n                        <div class=\"color-label\">${color.name}<\/div>\r\n                    <\/div>\r\n                `;\r\n            });\r\n            html += '<\/div><\/div>';\r\n\r\n            \/\/ Wheels\r\n            html += '<div class=\"config-section\" id=\"wheelsSection\"><h3 class=\"section-title\">Wheels<\/h3>';\r\n            html += '<div class=\"wheel-grid\">';\r\n            Object.keys(MODEL_CONFIG.wheels).forEach(wheelId => {\r\n                const wheel = MODEL_CONFIG.wheels[wheelId];\r\n                const selected = wheelId === selectedConfig.wheels.id ? 'selected' : '';\r\n                let wheelPrice = wheel.price;\r\n                if (typeof wheelPrice === 'object') {\r\n                    wheelPrice = wheelPrice[selectedConfig.model.id] || 0;\r\n                }\r\n\r\n                \/\/ Check for i6 AWD + 21\" wheels bundle\r\n                if (currentModelKey === 'i6' && wheelId === '21-7-spoke') {\r\n                    const hasAWD = selectedConfig.options.some(opt => opt.id === 'awd-system');\r\n                    if (hasAWD) {\r\n                        wheelPrice = 0; \/\/ Free with AWD\r\n                    }\r\n                }\r\n\r\n                const disabled = wheel.disabledFor && wheel.disabledFor.includes(selectedConfig.model.id);\r\n                const disabledStyle = disabled ? 'opacity: 0.5; cursor: not-allowed; pointer-events: none;' : '';\r\n                const disabledAttr = disabled ? '' : `onclick=\"selectWheel('${wheelId}', '${wheel.name}', '${wheel.desc}', ${wheelPrice})\"`;\r\n                const priceText = wheelPrice === 0 ? '0 AMD' : `<span style=\"color: #fbbf24;\">+${formatPrice(wheelPrice)}<\/span>`;\r\n                const wheelImagePath = `https:\/\/liautoyerevan.am\/preview-images\/webp\/${currentModelKey}-${wheelId}.webp`;\r\n                if (!disabled) {\r\n                    html += `\r\n                        <div class=\"wheel-option ${selected}\" ${disabledAttr}>\r\n                            <div class=\"wheel-image\">\r\n                                ${generatePictureElement(wheelImagePath, wheel.name)}\r\n                            <\/div>\r\n                            <div class=\"wheel-name\">${wheel.name}<\/div>\r\n                            <div class=\"wheel-desc\">${wheel.desc}<\/div>\r\n                            <div class=\"price-tag\">${priceText}<\/div>\r\n                        <\/div>\r\n                    `;\r\n                }\r\n            });\r\n            html += '<\/div><\/div>';\r\n\r\n            \/\/ Options - only show section if there are available options for current model\r\n            const optionType = MODEL_CONFIG.optionType;\r\n            const availableOptions = Object.keys(MODEL_CONFIG.options).filter(optionId => {\r\n                const option = MODEL_CONFIG.options[optionId];\r\n                return !option.disabledFor || !option.disabledFor.includes(selectedConfig.model.id);\r\n            });\r\n\r\n            if (availableOptions.length > 0) {\r\n                html += '<div class=\"config-section\"><h3 class=\"section-title\">Options<\/h3>';\r\n                html += '<div style=\"display: grid; grid-template-columns: 1fr; gap: 16px;\">';\r\n                Object.keys(MODEL_CONFIG.options).forEach(optionId => {\r\n                    const option = MODEL_CONFIG.options[optionId];\r\n                    let optionPrice = option.price;\r\n                    if (typeof optionPrice === 'object') {\r\n                        optionPrice = optionPrice[selectedConfig.model.id] || 0;\r\n                    }\r\n                    const disabled = option.disabledFor && option.disabledFor.includes(selectedConfig.model.id);\r\n                    const disabledStyle = disabled ? 'opacity: 0.5; cursor: not-allowed;' : '';\r\n                    const disabledAttr = disabled ? 'onclick=\"return false;\"' : `onclick=\"selectOption('${optionId}', '${option.name}')\"`;\r\n\r\n                    \/\/ Handle free wheels when bundled with AWD (i6 specific)\r\n                    let effectivePrice = optionPrice;\r\n                    if (currentModelKey === 'i6' && optionId === 'awd-system') {\r\n                        \/\/ Check if 21\" wheels are selected - if so, they become free with AWD\r\n                        if (selectedConfig.wheels.id === '21-7-spoke') {\r\n                            const wheelData = MODEL_CONFIG.wheels['21-7-spoke'];\r\n                            const wheelBasePrice = wheelData.price || 0;\r\n                            \/\/ Show AWD price includes free wheels\r\n                            effectivePrice = optionPrice; \/\/ AWD price stays same, but wheels become free\r\n                        }\r\n                    }\r\n\r\n                    const priceText = effectivePrice === 0 ? (option.alwaysIncluded ? 'Included' : '0 AMD') : `+${formatPrice(effectivePrice)}`;\r\n                    const optionImagePath = `https:\/\/liautoyerevan.am\/preview-images\/webp\/${currentModelKey}-${optionId}.webp`;\r\n\r\n                    \/\/ Check if option is selected (multi-option or single-option mode)\r\n                    let isSelected = false;\r\n                    if (MODEL_CONFIG.optionMode === 'multiple') {\r\n                        isSelected = selectedConfig.options.some(opt => opt.id === optionId);\r\n                    } else {\r\n                        isSelected = selectedConfig.option.id === optionId;\r\n                    }\r\n                    const selectedClass = isSelected ? ' selected' : '';\r\n\r\n                    \/\/ Add bundle note for AWD option on i6\r\n                    let bundleNote = '';\r\n                    if (currentModelKey === 'i6' && optionId === 'awd-system') {\r\n                        bundleNote = '<div class=\"note-text\">Includes 21-inch wheels at no extra cost<\/div>';\r\n                    }\r\n\r\n                    html += `\r\n                        <div class=\"audio-option${selectedClass}\" data-option-id=\"${optionId}\" style=\"${disabledStyle}\" ${disabledAttr}>\r\n                            <div class=\"wheel-image\">\r\n                                ${generatePictureElement(optionImagePath, option.name)}\r\n                            <\/div>\r\n                            <div class=\"option-text-content\">\r\n                                <div class=\"audio-name\">${option.name}<\/div>\r\n                                <div class=\"price-tag\">${priceText}<\/div>\r\n                                ${disabled ? '<div class=\"note-text\">Included with this model<\/div>' : bundleNote}\r\n                            <\/div>\r\n                        <\/div>\r\n                    `;\r\n                });\r\n                html += '<\/div><\/div>';\r\n            }\r\n\r\n            container.innerHTML = html;\r\n\r\n            \/\/ Generate CSS for color previews\r\n            generateColorPreviewCSS();\r\n        }\r\n\r\n        \/\/ Generate CSS for color preview backgrounds\r\n        function generateColorPreviewCSS() {\r\n            let css = '';\r\n            const chineseFolder = MODEL_CONFIG.chineseFolder;\r\n\r\n            \/\/ Get current variant folder (for multi-variant models like L6 Pro\/Max)\r\n            const currentModel = MODEL_CONFIG.models[selectedConfig.model.id];\r\n            const variantFolder = currentModel.variantFolder;\r\n\r\n            \/\/ Exterior colors - use full car images\r\n            Object.keys(MODEL_CONFIG.exteriorColors).forEach(colorId => {\r\n                const colorChinese = chineseNames.exteriorColors[colorId];\r\n                const defaultInterior = Object.keys(MODEL_CONFIG.interiorColors)[0];\r\n                const interiorChinese = chineseNames.interiorColors[defaultInterior];\r\n\r\n                let filename;\r\n                const includeWheels = MODEL_CONFIG.includeWheelsInFilename !== false;\r\n                const exteriorPattern = MODEL_CONFIG.exteriorPattern || 'default';\r\n\r\n                if (!includeWheels) {\r\n                    \/\/ MEGA: no wheels in filename\r\n                    filename = `${colorChinese}-${interiorChinese}.webp`;\r\n                } else if (exteriorPattern === 'interior-before-wheels') {\r\n                    \/\/ L9: color -> interior -> wheel\r\n                    \/\/ Get first available wheel (not disabled for current model)\r\n                    const defaultWheel = Object.keys(MODEL_CONFIG.wheels).find(wheelId => {\r\n                        const wheelData = MODEL_CONFIG.wheels[wheelId];\r\n                        return !wheelData.disabledFor || !wheelData.disabledFor.includes(selectedConfig.model.id);\r\n                    }) || Object.keys(MODEL_CONFIG.wheels)[0];\r\n                    const wheelChinese = chineseNames.wheels[defaultWheel];\r\n                    filename = `${colorChinese}-${interiorChinese}-${wheelChinese}.webp`;\r\n                } else {\r\n                    \/\/ Default (i8, L6, L7, i6): color -> wheel -> interior\r\n                    \/\/ Get first available wheel (not disabled for current model)\r\n                    const defaultWheel = Object.keys(MODEL_CONFIG.wheels).find(wheelId => {\r\n                        const wheelData = MODEL_CONFIG.wheels[wheelId];\r\n                        return !wheelData.disabledFor || !wheelData.disabledFor.includes(selectedConfig.model.id);\r\n                    }) || Object.keys(MODEL_CONFIG.wheels)[0];\r\n                    const wheelChinese = chineseNames.wheels[defaultWheel];\r\n                    filename = `${colorChinese}-${wheelChinese}-${interiorChinese}.webp`;\r\n\r\n                    \/\/ i6 multi-option: exterior includes rear screen option\r\n                    if (MODEL_CONFIG.optionMode === 'multiple') {\r\n                        \/\/ Get rear screen base value (when not selected)\r\n                        const rearScreenOption = MODEL_CONFIG.options['rear-screen'];\r\n                        if (rearScreenOption && rearScreenOption.chineseBase) {\r\n                            filename = `${colorChinese}-${wheelChinese}-${interiorChinese}-${rearScreenOption.chineseBase}.webp`;\r\n                        }\r\n                    }\r\n                }\r\n\r\n                const imagePath = `https:\/\/liautoyerevan.am\/configurator_images\/downloaded-images-webp\/${chineseFolder}\/${variantFolder}\/variant-attribute\/exterior\/angle-0\/${filename}`;\r\n                css += `.ext-${colorId} { background-image: url('${imagePath}'); }\\n`;\r\n            });\r\n\r\n            \/\/ Interior colors - use full car images\r\n            Object.keys(MODEL_CONFIG.interiorColors).forEach(colorId => {\r\n                const interiorChinese = chineseNames.interiorColors[colorId];\r\n                const defaultExterior = Object.keys(MODEL_CONFIG.exteriorColors)[0];\r\n                const exteriorChinese = chineseNames.exteriorColors[defaultExterior];\r\n\r\n                \/\/ Use correct pattern based on model config\r\n                const interiorPattern = MODEL_CONFIG.interiorPattern || 'default';\r\n                let filename;\r\n                if (interiorPattern === 'exterior-first') {\r\n                    \/\/ L7\/L9\/MEGA pattern\r\n                    filename = `${exteriorChinese}-${interiorChinese}.webp`;\r\n\r\n                    \/\/ L7 Ultra Baby Blue has special pattern: exterior-interior-exterior\r\n                    if (variantFolder === '\u7406\u60f3L7 Ultra' && exteriorChinese === 'Baby Blue\u200b\u7279\u522b\u7248\u73cd\u73e0\u6f06') {\r\n                        filename = `${exteriorChinese}-${interiorChinese}-${exteriorChinese}.webp`;\r\n                    }\r\n                } else {\r\n                    \/\/ Default (i8\/L6\/i6) pattern\r\n                    filename = `${interiorChinese}-${exteriorChinese}.webp`;\r\n\r\n                    \/\/ i6 multi-option: interior includes audio, rear screen, and drivetrain options\r\n                    if (MODEL_CONFIG.optionMode === 'multiple') {\r\n                        \/\/ Pattern with base options: {interior}-{color}-{audio}-{rearScreen}-{drivetrain}\r\n                        const rearScreenOption = MODEL_CONFIG.options['rear-screen'];\r\n                        const audioOption = MODEL_CONFIG.options['platinum-audio'];\r\n                        const awdOption = MODEL_CONFIG.options['awd-system'];\r\n\r\n                        const rearScreenBase = rearScreenOption ? rearScreenOption.chineseBase : '';\r\n                        const audioBase = audioOption ? audioOption.chineseBase : '';\r\n                        const drivetrainBase = awdOption ? awdOption.chineseBase : '';\r\n\r\n                        filename = `${interiorChinese}-${exteriorChinese}-${audioBase}-${rearScreenBase}-${drivetrainBase}.webp`;\r\n                    }\r\n                }\r\n\r\n                const imagePath = `https:\/\/liautoyerevan.am\/configurator_images\/downloaded-images-webp\/${chineseFolder}\/${variantFolder}\/variant-attribute\/interior\/angle-0\/${filename}`;\r\n                css += `.int-${colorId} { background-image: url('${imagePath}'); }\\n`;\r\n            });\r\n\r\n            \/\/ Inject CSS\r\n            const styleEl = document.createElement('style');\r\n            styleEl.textContent = css;\r\n            document.head.appendChild(styleEl);\r\n        }\r\n\r\n        async function initConfigurator() {\r\n            await loadModelConfig();\r\n            updateConfigDetails();\r\n            updatePricing();\r\n            updateImage('exterior', true); \/\/ Load initial image without crossfade\r\n            preloadAdjacentOptions(); \/\/ Preload adjacent options on init\r\n\r\n            if ('ontouchstart' in window) {\r\n                addTouchSupport();\r\n            }\r\n\r\n            \/\/ Add zoom and pan event listeners\r\n            const carDisplay = document.querySelector('.car-display');\r\n            if (carDisplay) {\r\n                \/\/ Mouse events\r\n                carDisplay.addEventListener('wheel', handleWheel, { passive: false });\r\n                carDisplay.addEventListener('mousedown', handleMouseDown);\r\n                document.addEventListener('mousemove', handleMouseMove);\r\n                document.addEventListener('mouseup', handleMouseUp);\r\n\r\n                \/\/ Touch events\r\n                carDisplay.addEventListener('touchstart', handleTouchStart, { passive: false });\r\n                carDisplay.addEventListener('touchmove', handleTouchMove, { passive: false });\r\n                carDisplay.addEventListener('touchend', handleTouchEnd);\r\n            }\r\n\r\n            \/\/ Initialize tab indicator position after DOM is fully rendered\r\n            setTimeout(updateTabIndicator, 0);\r\n\r\n            \/\/ Hide zoom controls on mobile initially (at base scale)\r\n            if (isMobile()) {\r\n                const zoomControls = document.querySelector('.zoom-controls');\r\n                if (zoomControls) {\r\n                    zoomControls.classList.add('hide-on-mobile');\r\n                }\r\n            }\r\n\r\n            \/\/ Prevent page-level pinch-to-zoom globally (for Elementor compatibility)\r\n            \/\/ This works even when viewport meta tags are overridden\r\n            document.addEventListener('touchstart', function(e) {\r\n                if (e.touches.length > 1) {\r\n                    \/\/ Allow pinch on car display (handled by our custom zoom)\r\n                    const target = e.target;\r\n                    const carDisplay = target.closest('.car-display');\r\n                    if (!carDisplay) {\r\n                        \/\/ Prevent pinch-to-zoom on the rest of the page\r\n                        e.preventDefault();\r\n                    }\r\n                }\r\n            }, { passive: false });\r\n\r\n            document.addEventListener('touchmove', function(e) {\r\n                if (e.touches.length > 1) {\r\n                    \/\/ Allow pinch on car display (handled by our custom zoom)\r\n                    const target = e.target;\r\n                    const carDisplay = target.closest('.car-display');\r\n                    if (!carDisplay) {\r\n                        \/\/ Prevent pinch-to-zoom on the rest of the page\r\n                        e.preventDefault();\r\n                    }\r\n                }\r\n            }, { passive: false });\r\n        }\r\n\r\n        function addTouchSupport() {\r\n            document.querySelectorAll('.wheel-option, .color-option, .audio-option, .view-tab, .cta-button, .cancel-btn, .submit-btn').forEach(element => {\r\n                element.addEventListener('touchstart', function () {\r\n                    this.style.opacity = '0.8';\r\n                }, { passive: true });\r\n\r\n                element.addEventListener('touchend', function () {\r\n                    this.style.opacity = '';\r\n                }, { passive: true });\r\n\r\n                element.addEventListener('touchcancel', function () {\r\n                    this.style.opacity = '';\r\n                }, { passive: true });\r\n            });\r\n        }\r\n\r\n        function updateTabIndicator() {\r\n            const studioControls = document.querySelector('.studio-controls');\r\n            const activeTab = document.querySelector('.view-tab.active');\r\n\r\n            if (!studioControls || !activeTab) return;\r\n\r\n            \/\/ Get the position and size of the active tab relative to the container\r\n            const containerRect = studioControls.getBoundingClientRect();\r\n            const tabRect = activeTab.getBoundingClientRect();\r\n\r\n            \/\/ Calculate the left position and width for the indicator\r\n            const left = tabRect.left - containerRect.left;\r\n            const width = tabRect.width;\r\n\r\n            \/\/ Update the ::before pseudo-element via CSS custom properties\r\n            studioControls.style.setProperty('--indicator-left', left + 'px');\r\n            studioControls.style.setProperty('--indicator-width', width + 'px');\r\n        }\r\n\r\n        function switchView(view, clickEvent) {\r\n\r\n            currentView = view;\r\n\r\n            \/\/ Update tab highlighting\r\n            document.querySelectorAll('.view-tab').forEach(tab => tab.classList.remove('active'));\r\n\r\n            \/\/ If called from tab click, use the clicked element\r\n            if (clickEvent && clickEvent.target && clickEvent.target.classList.contains('view-tab')) {\r\n                clickEvent.target.classList.add('active');\r\n            } else {\r\n                \/\/ Programmatic call - find and highlight the correct tab by data-view attribute\r\n                const targetTab = document.querySelector(`.view-tab[data-view=\"${view}\"]`);\r\n                if (targetTab) {\r\n                    targetTab.classList.add('active');\r\n                }\r\n            }\r\n\r\n            \/\/ Update sliding indicator position\r\n            updateTabIndicator();\r\n\r\n            document.querySelectorAll('.car-view').forEach(view => view.classList.remove('active'));\r\n            document.getElementById(view + 'View').classList.add('active');\r\n\r\n            const overlay = document.querySelector('.car-info-overlay');\r\n            if (isMobile() && (view === 'interior')) {\r\n                overlay.classList.add('interior-hidden');\r\n            } else {\r\n                overlay.classList.remove('interior-hidden');\r\n            }\r\n\r\n            updateImage(view); \/\/ Load correct image for the view\r\n            resetZoom();\r\n            updateConfigDetails();\r\n        }\r\n\r\n        function selectWheel(id, name, desc, price) {\r\n            \/\/ Handle AWD + 21\" wheels bundle for i6\r\n            if (currentModelKey === 'i6' && id === '21-7-spoke') {\r\n                const hasAWD = selectedConfig.options.some(opt => opt.id === 'awd-system');\r\n                if (hasAWD) {\r\n                    \/\/ AWD bundles with 21\" wheels - make them free\r\n                    price = 0;\r\n                }\r\n            }\r\n\r\n            selectedConfig.wheels = { id, name, desc, price };\r\n\r\n            document.querySelectorAll('#wheelsSection .wheel-option').forEach(option => {\r\n                option.classList.remove('selected');\r\n            });\r\n            event.currentTarget.classList.add('selected');\r\n\r\n            if (currentView !== 'exterior') switchView('exterior');\r\n            updatePricing();\r\n            updateConfigDetails();\r\n            updateImage('exterior'); \/\/ Update car image when wheel changes\r\n            preloadAdjacentOptions(); \/\/ Preload adjacent options\r\n        }\r\n\r\n        function selectExteriorColor(id, name, price) {\r\n            selectedConfig.exterior = { id, name, price };\r\n\r\n            document.querySelectorAll('.color-grid .color-option').forEach(option => {\r\n                option.classList.remove('selected');\r\n            });\r\n            event.currentTarget.classList.add('selected');\r\n\r\n            if (currentView !== 'exterior') switchView('exterior');\r\n            updatePricing();\r\n            updateConfigDetails();\r\n            updateImage('exterior'); \/\/ Crossfade to new image\r\n            preloadAdjacentOptions(); \/\/ Preload adjacent options\r\n        }\r\n\r\n        function selectInteriorColor(id, name, price) {\r\n            selectedConfig.interior = { id, name, price };\r\n\r\n            document.querySelectorAll('.interior-color-grid .color-option').forEach(option => {\r\n                option.classList.remove('selected');\r\n            });\r\n            event.currentTarget.classList.add('selected');\r\n\r\n            if (currentView !== 'interior') switchView('interior');\r\n            updatePricing();\r\n            updateConfigDetails();\r\n            updateImage('interior'); \/\/ Update interior view image when interior color changes\r\n            preloadAdjacentOptions(); \/\/ Preload adjacent options\r\n        }\r\n\r\n        function updateConfigDetails() {\r\n            const details = document.getElementById('configDetails');\r\n            const formattedPrice = formatPrice(calculateTotalPrice());\r\n\r\n            \/\/ Build options string (single or multiple)\r\n            let optionsText = '';\r\n            if (MODEL_CONFIG && MODEL_CONFIG.optionMode === 'multiple') {\r\n                \/\/ Multi-option mode: show count instead of names (more compact)\r\n                if (selectedConfig.options.length > 0) {\r\n                    const count = selectedConfig.options.length;\r\n                    optionsText = `${count} option${count > 1 ? 's' : ''} selected`;\r\n                }\r\n            } else {\r\n                \/\/ Single-option mode: show single option if selected\r\n                if (selectedConfig.option.id !== 'none') {\r\n                    optionsText = selectedConfig.option.name;\r\n                }\r\n            }\r\n\r\n            let newContent;\r\n            if (currentView === 'exterior') {\r\n                newContent = `${selectedConfig.model.name} - ${selectedConfig.exterior.name} &bull; ${selectedConfig.interior.name}<br>`;\r\n                if (optionsText) {\r\n                    newContent += `${selectedConfig.wheels.name} &bull; ${optionsText}<br>`;\r\n                } else {\r\n                    newContent += `${selectedConfig.wheels.name}<br>`;\r\n                }\r\n                newContent += `${formattedPrice}`;\r\n            } else if (currentView === 'interior') {\r\n                newContent = `${selectedConfig.model.name} - ${selectedConfig.interior.name} &bull; ${selectedConfig.exterior.name}<br>`;\r\n                if (optionsText) {\r\n                    newContent += `${selectedConfig.wheels.name} &bull; ${optionsText}<br>`;\r\n                } else {\r\n                    newContent += `${selectedConfig.wheels.name}<br>`;\r\n                }\r\n                newContent += `${formattedPrice}`;\r\n            }\r\n\r\n            \/\/ Fade out, update, fade in animation with height preservation\r\n            if (details.innerHTML !== newContent) {\r\n                \/\/ Capture current height to prevent card from shrinking during transition\r\n                const currentHeight = details.offsetHeight;\r\n                details.style.minHeight = currentHeight + 'px';\r\n\r\n                details.style.opacity = '0.4';\r\n                setTimeout(() => {\r\n                    details.innerHTML = newContent;\r\n                    details.style.opacity = '1';\r\n\r\n                    \/\/ Remove min-height after fade completes to allow natural sizing\r\n                    setTimeout(() => {\r\n                        details.style.minHeight = '';\r\n                    }, 300);\r\n                }, 150);\r\n            }\r\n        }\r\n\r\n        \/\/ Bounce animation for zoom limit feedback\r\n        function bounceZoom(amount) {\r\n            const originalZoom = currentZoom;\r\n            currentZoom += amount;\r\n            updateZoom();\r\n\r\n            \/\/ Bounce back after 100ms\r\n            setTimeout(() => {\r\n                currentZoom = originalZoom;\r\n                updateZoom();\r\n            }, 100);\r\n        }\r\n\r\n        function zoomIn() {\r\n            if (currentZoom < maxZoom) {\r\n                currentZoom += zoomStep;\r\n                currentZoom = Math.min(currentZoom, maxZoom);\r\n                updateZoom();\r\n            } else {\r\n                \/\/ Bounce feedback when hitting max zoom\r\n                bounceZoom(0.02);\r\n            }\r\n        }\r\n\r\n        function zoomOut() {\r\n            if (currentZoom > minZoom) {\r\n                currentZoom -= zoomStep;\r\n                currentZoom = Math.max(currentZoom, minZoom);\r\n\r\n                \/\/ Auto-center when zooming below base scale to prevent softlock\r\n                const baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n                if (currentZoom <= baseScale) {\r\n                    panX = 0;\r\n                    panY = 0;\r\n                }\r\n\r\n                updateZoom();\r\n            } else {\r\n                \/\/ Bounce feedback when hitting min zoom\r\n                bounceZoom(-0.015);\r\n            }\r\n        }\r\n\r\n        function resetZoom() {\r\n            const targetZoom = currentView === 'exterior' ? 1.2 : 1.3;\r\n            const startZoom = currentZoom;\r\n            const startPanX = panX;\r\n            const startPanY = panY;\r\n\r\n            \/\/ Set flag to prevent UI flicker during animation\r\n            isResettingZoom = true;\r\n\r\n            \/\/ Animate zoom reset over 300ms\r\n            const duration = 300;\r\n            const startTime = performance.now();\r\n\r\n            function animate(currentTime) {\r\n                const elapsed = currentTime - startTime;\r\n                const progress = Math.min(elapsed \/ duration, 1);\r\n\r\n                \/\/ Ease-out cubic for smooth deceleration\r\n                const easeProgress = 1 - Math.pow(1 - progress, 3);\r\n\r\n                \/\/ Interpolate values\r\n                currentZoom = startZoom + (targetZoom - startZoom) * easeProgress;\r\n                panX = startPanX + (0 - startPanX) * easeProgress;\r\n                panY = startPanY + (0 - startPanY) * easeProgress;\r\n\r\n                updateZoom();\r\n\r\n                if (progress < 1) {\r\n                    requestAnimationFrame(animate);\r\n                } else {\r\n                    \/\/ Ensure final values are exact\r\n                    currentZoom = targetZoom;\r\n                    panX = 0;\r\n                    panY = 0;\r\n                    updateZoom();\r\n\r\n                    \/\/ Clear flag after animation completes\r\n                    isResettingZoom = false;\r\n\r\n                    \/\/ Update mobile UI now that flag is cleared\r\n                    updateZoom();\r\n                }\r\n            }\r\n\r\n            requestAnimationFrame(animate);\r\n        }\r\n\r\n        function updateZoom() {\r\n            const activeImages = document.querySelectorAll('.car-view.active .car-image');\r\n            if (activeImages.length) {\r\n                \/\/ Apply pan boundaries to prevent image from being dragged completely outside viewport\r\n                const img = activeImages[0];\r\n                const container = img.closest('.car-display');\r\n\r\n                if (container) {\r\n                    const containerRect = container.getBoundingClientRect();\r\n                    const containerWidth = containerRect.width;\r\n                    const containerHeight = containerRect.height;\r\n\r\n                    \/\/ Get natural image dimensions (before any transform)\r\n                    const naturalWidth = img.naturalWidth || img.width;\r\n                    const naturalHeight = img.naturalHeight || img.height;\r\n\r\n                    \/\/ Calculate actual displayed dimensions considering object-fit: contain\r\n                    const imgAspect = naturalWidth \/ naturalHeight;\r\n                    const containerAspect = containerWidth \/ containerHeight;\r\n\r\n                    let baseWidth, baseHeight;\r\n                    if (imgAspect > containerAspect) {\r\n                        \/\/ Image is wider - width constrained\r\n                        baseWidth = containerWidth;\r\n                        baseHeight = containerWidth \/ imgAspect;\r\n                    } else {\r\n                        \/\/ Image is taller - height constrained\r\n                        baseHeight = containerHeight;\r\n                        baseWidth = containerHeight * imgAspect;\r\n                    }\r\n\r\n                    \/\/ Apply current zoom to get actual scaled dimensions\r\n                    const scaledWidth = baseWidth * currentZoom;\r\n                    const scaledHeight = baseHeight * currentZoom;\r\n\r\n                    \/\/ Calculate zoom-dependent minimum visible percentage\r\n                    \/\/ At base scale: 20% minimum, at max zoom (2x): 40% minimum\r\n                    const baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n                    const zoomRatio = (currentZoom - baseScale) \/ (maxZoom - baseScale);\r\n                    const minVisiblePercent = 0.2 + (zoomRatio * 0.2); \/\/ 20% to 40% based on zoom\r\n\r\n                    \/\/ Calculate how much the scaled image exceeds the viewport\r\n                    const excessWidth = Math.max(0, scaledWidth - containerWidth);\r\n                    const excessHeight = Math.max(0, scaledHeight - containerHeight);\r\n\r\n                    \/\/ Calculate max pan: half the excess, minus the minimum visible margin\r\n                    const minVisibleMarginX = scaledWidth * minVisiblePercent;\r\n                    const minVisibleMarginY = scaledHeight * minVisiblePercent;\r\n\r\n                    const maxPanX = Math.max(0, (excessWidth \/ 2) + (scaledWidth \/ 2) - minVisibleMarginX);\r\n                    const maxPanY = Math.max(0, (excessHeight \/ 2) + (scaledHeight \/ 2) - minVisibleMarginY);\r\n\r\n                    \/\/ Clamp pan values to boundaries\r\n                    panX = Math.max(-maxPanX, Math.min(maxPanX, panX));\r\n                    panY = Math.max(-maxPanY, Math.min(maxPanY, panY));\r\n                }\r\n\r\n                const baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n\r\n                activeImages.forEach(img => {\r\n                    img.style.transform = `translate(${panX}px, ${panY}px) scale(${currentZoom})`;\r\n                    \/\/ Show grab cursor only when zoom is above base scale (when panning is enabled)\r\n                    img.style.cursor = currentZoom > baseScale ? 'grab' : 'default';\r\n                });\r\n            }\r\n\r\n            \/\/ Hide info overlay and show reset button on mobile when zoomed away from default\r\n            \/\/ Skip this logic during reset animation to prevent flicker\r\n            if (isMobile() && !isResettingZoom) {\r\n                const overlay = document.querySelector('.car-info-overlay');\r\n                const zoomControls = document.querySelector('.zoom-controls');\r\n                let baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n\r\n                \/\/ Show reset button when zoom is not at base scale (either above or below)\r\n                const isAtBaseScale = Math.abs(currentZoom - baseScale) < 0.01;\r\n\r\n                if (!isAtBaseScale) {\r\n                    \/\/ Zoomed away from default (either in or out)\r\n                    overlay.classList.add('interior-hidden');\r\n                    zoomControls.classList.remove('hide-on-mobile');\r\n                } else {\r\n                    \/\/ At base scale\r\n                    \/\/ Only show overlay if not in interior view (which has its own hide logic)\r\n                    if (currentView !== 'interior') {\r\n                        overlay.classList.remove('interior-hidden');\r\n                    }\r\n                    zoomControls.classList.add('hide-on-mobile');\r\n                }\r\n            }\r\n        }\r\n\r\n        \/\/ Mouse wheel zoom\r\n        function handleWheel(e) {\r\n            \/\/ Allow zooming from anywhere in car-display, not just on the image\r\n            e.preventDefault();\r\n\r\n            if (e.deltaY < 0) {\r\n                zoomIn();\r\n            } else {\r\n                zoomOut();\r\n            }\r\n        }\r\n\r\n        \/\/ Mouse drag to pan\r\n        function handleMouseDown(e) {\r\n            \/\/ Allow dragging from anywhere in car-display, not just on the image\r\n            const carDisplay = e.target.closest('.car-display');\r\n            if (!carDisplay) return;\r\n\r\n            \/\/ Disable panning when at base scale (default zoom)\r\n            const baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n            if (currentZoom <= baseScale) return;\r\n\r\n            isDragging = true;\r\n            startX = e.clientX - panX;\r\n            startY = e.clientY - panY;\r\n\r\n            \/\/ Update cursor on all active images\r\n            const activeImages = document.querySelectorAll('.car-view.active .car-image');\r\n            activeImages.forEach(img => img.style.cursor = 'grabbing');\r\n        }\r\n\r\n        function handleMouseMove(e) {\r\n            if (!isDragging) return;\r\n            e.preventDefault();\r\n\r\n            panX = e.clientX - startX;\r\n            panY = e.clientY - startY;\r\n            updateZoom();\r\n        }\r\n\r\n        function handleMouseUp(e) {\r\n            if (isDragging) {\r\n                isDragging = false;\r\n                \/\/ Reset cursor on all active images\r\n                const activeImages = document.querySelectorAll('.car-view.active .car-image');\r\n                activeImages.forEach(img => img.style.cursor = 'grab');\r\n            }\r\n        }\r\n\r\n        \/\/ Touch pinch to zoom and drag to pan\r\n        function getTouchDistance(touches) {\r\n            const dx = touches[0].clientX - touches[1].clientX;\r\n            const dy = touches[0].clientY - touches[1].clientY;\r\n            return Math.sqrt(dx * dx + dy * dy);\r\n        }\r\n\r\n        function handleTouchStart(e) {\r\n            \/\/ Allow touch from anywhere in car-display, not just on the image\r\n            const carDisplay = e.target.closest('.car-display');\r\n            if (!carDisplay) return;\r\n\r\n            const baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n\r\n            if (e.touches.length === 2) {\r\n                e.preventDefault();\r\n                initialDistance = getTouchDistance(e.touches);\r\n                initialZoom = currentZoom;\r\n                \/\/ Disable dragging when entering pinch mode to prevent jump when one finger lifts\r\n                isDragging = false;\r\n            } else if (e.touches.length === 1) {\r\n                \/\/ Only enable dragging if we're not transitioning from a pinch gesture\r\n                \/\/ AND only if zoom is above base scale\r\n                if (initialDistance === 0 && currentZoom > baseScale) {\r\n                    isDragging = true;\r\n                    startX = e.touches[0].clientX - panX;\r\n                    startY = e.touches[0].clientY - panY;\r\n                }\r\n            }\r\n        }\r\n\r\n        function handleTouchMove(e) {\r\n            \/\/ No need to check for car-image since we're working in car-display\r\n            if (e.touches.length === 2) {\r\n                e.preventDefault();\r\n                const distance = getTouchDistance(e.touches);\r\n                const scale = distance \/ initialDistance;\r\n                let newZoom = initialZoom * scale;\r\n\r\n                \/\/ Check if hitting zoom limits and apply bounce\r\n                if (newZoom > maxZoom) {\r\n                    currentZoom = maxZoom;\r\n                    \/\/ Allow slight overshoot for tactile feedback\r\n                    if (newZoom > maxZoom * 1.05) {\r\n                        bounceZoom(0.02);\r\n                    }\r\n                } else if (newZoom < minZoom) {\r\n                    currentZoom = minZoom;\r\n                    \/\/ Allow slight undershoot for tactile feedback\r\n                    if (newZoom < minZoom * 0.95) {\r\n                        bounceZoom(-0.015);\r\n                    }\r\n                } else {\r\n                    currentZoom = newZoom;\r\n                }\r\n\r\n                \/\/ Auto-center when pinch-zooming below base scale to prevent softlock\r\n                const baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n                if (currentZoom <= baseScale) {\r\n                    panX = 0;\r\n                    panY = 0;\r\n                }\r\n\r\n                updateZoom();\r\n            } else if (e.touches.length === 1) {\r\n                const baseScale = currentView === 'exterior' ? 1.2 : 1.3;\r\n\r\n                \/\/ Transitioning from 2 fingers to 1 - reset pan start position\r\n                if (initialDistance > 0) {\r\n                    \/\/ We were just pinching, only enable pan if above base scale\r\n                    if (currentZoom > baseScale) {\r\n                        isDragging = true;\r\n                        startX = e.touches[0].clientX - panX;\r\n                        startY = e.touches[0].clientY - panY;\r\n                    }\r\n                    initialDistance = 0;\r\n                }\r\n\r\n                \/\/ Now pan if dragging is enabled and above base scale\r\n                if (isDragging && currentZoom > baseScale) {\r\n                    e.preventDefault();\r\n                    panX = e.touches[0].clientX - startX;\r\n                    panY = e.touches[0].clientY - startY;\r\n                    updateZoom();\r\n                }\r\n            }\r\n        }\r\n\r\n        function handleTouchEnd(e) {\r\n            if (e.touches.length === 0) {\r\n                isDragging = false;\r\n                initialDistance = 0;\r\n            }\r\n        }\r\n\r\n        function showContactForm() {\r\n            document.getElementById('contactForm').classList.add('show');\r\n            document.body.classList.add('form-open');\r\n            clearMessages();\r\n            resetForm();\r\n        }\r\n\r\n        function hideContactForm() {\r\n            document.getElementById('contactForm').classList.remove('show');\r\n            document.body.classList.remove('form-open');\r\n            clearMessages();\r\n            resetForm();\r\n        }\r\n\r\n        function resetForm() {\r\n            document.getElementById('notificationForm').reset();\r\n            clearFormErrors();\r\n            document.getElementById('submitButton').disabled = false;\r\n            document.getElementById('submitText').textContent = 'Submit a Request';\r\n        }\r\n\r\n        function clearMessages() {\r\n            document.getElementById('messageContainer').innerHTML = '';\r\n        }\r\n\r\n        function clearFormErrors() {\r\n            document.querySelectorAll('.form-input').forEach(input => {\r\n                input.classList.remove('error');\r\n            });\r\n            document.querySelectorAll('.form-error').forEach(error => {\r\n                error.textContent = '';\r\n            });\r\n        }\r\n\r\n        function showMessage(message, type) {\r\n            const container = document.getElementById('messageContainer');\r\n            const messageClass = type === 'success' ? 'success' : 'error';\r\n            container.innerHTML = `<div class=\"message ${messageClass}\">${message}<\/div>`;\r\n        }\r\n\r\n        function validateForm() {\r\n            let isValid = true;\r\n            clearFormErrors();\r\n\r\n            const firstName = document.getElementById('firstName');\r\n            if (!firstName.value.trim()) {\r\n                showFieldError('firstName', 'First name is required');\r\n                isValid = false;\r\n            }\r\n\r\n            const lastName = document.getElementById('lastName');\r\n            if (!lastName.value.trim()) {\r\n                showFieldError('lastName', 'Last name is required');\r\n                isValid = false;\r\n            }\r\n\r\n            const email = document.getElementById('email');\r\n            const emailRegex = \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/;\r\n            if (email.value.trim() && !emailRegex.test(email.value.trim())) {\r\n                showFieldError('email', 'Please enter a valid email address');\r\n                isValid = false;\r\n            }\r\n\r\n            const phone = document.getElementById('phone');\r\n            if (!phone.value.trim()) {\r\n                showFieldError('phone', 'Phone number is required');\r\n                isValid = false;\r\n            }\r\n\r\n            return isValid;\r\n        }\r\n\r\n        function showFieldError(fieldId, message) {\r\n            const field = document.getElementById(fieldId);\r\n            const errorEl = document.getElementById(fieldId + 'Error');\r\n            field.classList.add('error');\r\n            errorEl.textContent = message;\r\n        }\r\n\r\n        document.getElementById('notificationForm').addEventListener('submit', async function (e) {\r\n            e.preventDefault();\r\n\r\n            if (!validateForm()) return;\r\n\r\n            const submitButton = document.getElementById('submitButton');\r\n            const submitText = document.getElementById('submitText');\r\n\r\n            submitButton.disabled = true;\r\n            submitText.textContent = 'Sending...';\r\n            clearMessages();\r\n\r\n            try {\r\n                const payload = {\r\n                    firstName: document.getElementById('firstName').value.trim(),\r\n                    lastName: document.getElementById('lastName').value.trim(),\r\n                    email: document.getElementById('email').value.trim() || 'Not provided',\r\n                    phone: document.getElementById('phone').value.trim(),\r\n\r\n                    configuration: {\r\n                        model: selectedConfig.model.name,\r\n                        wheels: selectedConfig.wheels.name,\r\n                        exterior: selectedConfig.exterior.name,\r\n                        interior: selectedConfig.interior.name,\r\n                        option: (() => {\r\n                            if (selectedConfig.options && selectedConfig.options.length > 0) {\r\n                                return selectedConfig.options.map(opt => opt.name).join(', ');\r\n                            } else if (selectedConfig.option && selectedConfig.option.id && selectedConfig.option.id !== 'none') {\r\n                                return selectedConfig.option.name;\r\n                            } else {\r\n                                return 'None';\r\n                            }\r\n                        })(),\r\n                        totalPrice: formatPrice(calculateTotalPrice())\r\n                    },\r\n\r\n                    timestamp: new Date().toISOString(),\r\n                    source: `${MODEL_CONFIG ? MODEL_CONFIG.displayName : 'Li Auto'} Configurator - Submit a Request`\r\n                };\r\n\r\n                const response = await fetch('https:\/\/liautoyerevan.am\/wp-json\/telegram-notifier\/v2\/2', {\r\n                    method: 'POST',\r\n                    headers: { 'Content-Type': 'application\/json' },\r\n                    body: JSON.stringify(payload)\r\n                });\r\n\r\n                if (response.ok) {\r\n                    showMessage('Thank you! You will be notified as soon as the Li i8 becomes available.', 'success');\r\n                    setTimeout(() => hideContactForm(), 3000);\r\n                } else {\r\n                    throw new Error(`Server responded with status: ${response.status}`);\r\n                }\r\n\r\n            } catch (error) {\r\n                console.error('Error sending notification request:', error);\r\n                showMessage('Sorry, there was an error processing your request. Please try again or contact us directly.', 'error');\r\n            } finally {\r\n                submitButton.disabled = false;\r\n                submitText.textContent = 'Submit a Request';\r\n            }\r\n        });\r\n\r\n        document.addEventListener('keydown', function (e) {\r\n            if (e.key === 'Escape' && document.body.classList.contains('form-open')) {\r\n                hideContactForm();\r\n            }\r\n        });\r\n\r\n        window.addEventListener('resize', function () {\r\n            \/\/ Update tab indicator on resize for responsive behavior\r\n            updateTabIndicator();\r\n        });\r\n\r\n        document.addEventListener('DOMContentLoaded', initConfigurator);\r\n    <\/script>\r\n<\/body>\r\n<script>\r\n\/\/ Frontend Form Handler - Collects data and sends to generatepdf.php\r\n(function() {\r\n    const originalForm = document.getElementById('notificationForm');\r\n    \r\n    \/\/ Create modal HTML\r\n    const modalHTML = `\r\n        <div id=\"pdfDownloadModal\" style=\"\r\n            position: fixed;\r\n            top: 0;\r\n            left: 0;\r\n            width: 100%;\r\n            height: 100%;\r\n            z-index: 10000;\r\n            display: none;\r\n            align-items: center;\r\n            justify-content: center;\r\n            backdrop-filter: blur(8px);\r\n            background: rgba(0, 0, 0, 0.4);\r\n        \">\r\n            <div style=\"\r\n                background: white;\r\n                border-radius: 16px;\r\n                padding: 40px;\r\n                max-width: 500px;\r\n                width: 90%;\r\n                box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\r\n                text-align: center;\r\n            \">\r\n                <div style=\"\r\n                    width: 64px;\r\n                    height: 64px;\r\n                    margin: 0 auto 24px;\r\n                    background: #10b981;\r\n                    border-radius: 50%;\r\n                    display: flex;\r\n                    align-items: center;\r\n                    justify-content: center;\r\n                \">\r\n                    <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n                        <polyline points=\"20 6 9 17 4 12\"><\/polyline>\r\n                    <\/svg>\r\n                <\/div>\r\n                <h2 style=\"\r\n                    font-size: 24px;\r\n                    font-weight: 600;\r\n                    color: #1a1a1a;\r\n                    margin: 0 0 12px 0;\r\n                    font-family: 'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n                \">Information Submitted Successfully<\/h2>\r\n                <p style=\"\r\n                    font-size: 16px;\r\n                    color: #6b7280;\r\n                    margin: 0 0 32px 0;\r\n                    line-height: 1.5;\r\n                    font-family: 'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n                \">Your configuration has been saved. Click below to download your PDF.<\/p>\r\n                <button id=\"downloadPdfBtn\" style=\"\r\n                    background: #1a1a1a;\r\n                    color: white;\r\n                    border: none;\r\n                    padding: 14px 32px;\r\n                    font-size: 16px;\r\n                    font-weight: 600;\r\n                    border-radius: 8px;\r\n                    cursor: pointer;\r\n                    font-family: 'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n                    transition: background 0.2s;\r\n                \" onmouseover=\"this.style.background='#374151'\" onmouseout=\"this.style.background='#1a1a1a'\">Download PDF<\/button>\r\n            <\/div>\r\n        <\/div>\r\n    `;\r\n    \r\n    \/\/ Inject modal\r\n    document.body.insertAdjacentHTML('beforeend', modalHTML);\r\n    const modal = document.getElementById('pdfDownloadModal');\r\n    const downloadBtn = document.getElementById('downloadPdfBtn');\r\n    \r\n    let formData = null;\r\n    \r\n    originalForm.addEventListener('submit', function(e) {\r\n        e.preventDefault();\r\n        \r\n        \/\/ Get form data\r\n        const firstName = document.getElementById('firstName').value.trim();\r\n        const lastName = document.getElementById('lastName').value.trim();\r\n        const email = document.getElementById('email').value.trim() || 'Not provided';\r\n        const phone = document.getElementById('phone').value.trim();\r\n        \r\n        \/\/ Get device info synchronously\r\n        const deviceInfo = {\r\n            userAgent: navigator.userAgent,\r\n            platform: navigator.platform,\r\n            language: navigator.language,\r\n            screenResolution: `${screen.width}x${screen.height}`,\r\n            timestamp: new Date().toISOString()\r\n        };\r\n        \r\n        \/\/ Get configuration\r\n        const config = selectedConfig;\r\n        const totalPrice = formatPrice(calculateTotalPrice());\r\n        \r\n        \/\/ Fetch IP in background\r\n        let userIP = 'Unknown';\r\n        fetch('https:\/\/api.ipify.org?format=json')\r\n            .then(r => r.json())\r\n            .then(data => { userIP = data.ip; })\r\n            .catch(e => console.error('Failed to fetch IP:', e));\r\n        \r\n        \/\/ Store data\r\n        formData = {\r\n            firstName: firstName,\r\n            lastName: lastName,\r\n            email: email,\r\n            phone: phone,\r\n            userIP: userIP,\r\n            deviceInfo: deviceInfo,\r\n            config: config,\r\n            totalPrice: totalPrice\r\n        };\r\n        \r\n        \/\/ Show modal\r\n        modal.style.display = 'flex';\r\n    }, true);\r\n    \r\n    \/\/ Download button handler\r\n    downloadBtn.addEventListener('click', function() {\r\n        if (!formData) return;\r\n        \r\n        \/\/ Open window FIRST (synchronously) - critical for iOS Safari\r\n        const windowName = 'pdfWindow_' + Date.now();\r\n        const newWindow = window.open('', windowName);\r\n        if (!newWindow) {\r\n            alert('Please allow popups for this site');\r\n            return;\r\n        }\r\n        \r\n        \/\/ Submit form to the opened window\r\n        const form = document.createElement('form');\r\n        form.method = 'POST';\r\n        form.action = '\/generatepdf.php';\r\n        form.target = windowName;\r\n        form.style.display = 'none';\r\n        \r\n        const input = document.createElement('input');\r\n        input.type = 'hidden';\r\n        input.name = 'data';\r\n        input.value = JSON.stringify(formData);\r\n        \r\n        form.appendChild(input);\r\n        document.body.appendChild(form);\r\n        form.submit();\r\n        document.body.removeChild(form);\r\n        \r\n        \/\/ Hide modal\r\n        modal.style.display = 'none';\r\n        \r\n        console.log('Data sent to generatepdf.php');\r\n    });\r\n})();\r\n<\/script>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>2026 Li Auto Configurator Loading&#8230; 2026 Premium Electric Vehicle Loading configuration&#8230; Exterior Interior + \u2212 \u21ba Base Price: 22,750,000 AMD Options: 0 AMD Total Price: 22,750,000 AMD Get Special Price Get Special Price Configure your perfect car and get a special price. First Name * Last Name * Email Address Phone Number * Cancel Submit [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-2279","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Configurator MEGA - Li Auto Yerevan<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/liautoyerevan.am\/am\/configurator-mega\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Configurator MEGA - Li Auto Yerevan\" \/>\n<meta property=\"og:description\" content=\"2026 Li Auto Configurator Loading&#8230; 2026 Premium Electric Vehicle Loading configuration&#8230; Exterior Interior + \u2212 \u21ba Base Price: 22,750,000 AMD Options: 0 AMD Total Price: 22,750,000 AMD Get Special Price Get Special Price Configure your perfect car and get a special price. First Name * Last Name * Email Address Phone Number * Cancel Submit [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/liautoyerevan.am\/am\/configurator-mega\/\" \/>\n<meta property=\"og:site_name\" content=\"Li Auto Yerevan\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-13T06:06:26+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/liautoyerevan.am\/am\/configurator-mega\/\",\"url\":\"https:\/\/liautoyerevan.am\/am\/configurator-mega\/\",\"name\":\"Configurator MEGA - Li Auto Yerevan\",\"isPartOf\":{\"@id\":\"http:\/\/liautoyerevan.am\/am\/#website\"},\"datePublished\":\"2025-10-22T07:25:23+00:00\",\"dateModified\":\"2026-04-13T06:06:26+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/liautoyerevan.am\/am\/configurator-mega\/#breadcrumb\"},\"inLanguage\":\"hy-AM\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/liautoyerevan.am\/am\/configurator-mega\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/liautoyerevan.am\/am\/configurator-mega\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"http:\/\/liautoyerevan.am\/am\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Configurator MEGA\"}]},{\"@type\":\"WebSite\",\"@id\":\"http:\/\/liautoyerevan.am\/am\/#website\",\"url\":\"http:\/\/liautoyerevan.am\/am\/\",\"name\":\"Li Auto Yerevan\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\/\/liautoyerevan.am\/am\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"hy-AM\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Configurator MEGA - Li Auto Yerevan","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/liautoyerevan.am\/am\/configurator-mega\/","og_locale":"en_US","og_type":"article","og_title":"Configurator MEGA - Li Auto Yerevan","og_description":"2026 Li Auto Configurator Loading&#8230; 2026 Premium Electric Vehicle Loading configuration&#8230; Exterior Interior + \u2212 \u21ba Base Price: 22,750,000 AMD Options: 0 AMD Total Price: 22,750,000 AMD Get Special Price Get Special Price Configure your perfect car and get a special price. First Name * Last Name * Email Address Phone Number * Cancel Submit [&hellip;]","og_url":"https:\/\/liautoyerevan.am\/am\/configurator-mega\/","og_site_name":"Li Auto Yerevan","article_modified_time":"2026-04-13T06:06:26+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/liautoyerevan.am\/am\/configurator-mega\/","url":"https:\/\/liautoyerevan.am\/am\/configurator-mega\/","name":"Configurator MEGA - Li Auto Yerevan","isPartOf":{"@id":"http:\/\/liautoyerevan.am\/am\/#website"},"datePublished":"2025-10-22T07:25:23+00:00","dateModified":"2026-04-13T06:06:26+00:00","breadcrumb":{"@id":"https:\/\/liautoyerevan.am\/am\/configurator-mega\/#breadcrumb"},"inLanguage":"hy-AM","potentialAction":[{"@type":"ReadAction","target":["https:\/\/liautoyerevan.am\/am\/configurator-mega\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/liautoyerevan.am\/am\/configurator-mega\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/liautoyerevan.am\/am\/"},{"@type":"ListItem","position":2,"name":"Configurator MEGA"}]},{"@type":"WebSite","@id":"http:\/\/liautoyerevan.am\/am\/#website","url":"http:\/\/liautoyerevan.am\/am\/","name":"Li Auto Yerevan","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/liautoyerevan.am\/am\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"hy-AM"}]}},"_links":{"self":[{"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/pages\/2279","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/comments?post=2279"}],"version-history":[{"count":86,"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/pages\/2279\/revisions"}],"predecessor-version":[{"id":4639,"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/pages\/2279\/revisions\/4639"}],"wp:attachment":[{"href":"https:\/\/liautoyerevan.am\/am\/wp-json\/wp\/v2\/media?parent=2279"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}