 {"id":1657,"date":"2026-03-22T01:53:06","date_gmt":"2026-03-22T01:53:06","guid":{"rendered":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/?page_id=1657"},"modified":"2026-04-10T23:26:03","modified_gmt":"2026-04-10T23:26:03","slug":"omega-ecosystem","status":"publish","type":"page","link":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/omega-ecosystem\/","title":{"rendered":"Omega Ecosystem"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1657\" class=\"elementor elementor-1657\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5e01993 e-flex e-con-boxed e-con e-parent\" data-id=\"5e01993\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-37b74c1 elementor-widget elementor-widget-html\" data-id=\"37b74c1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t \n <!-- \n  ========================================================================\n  VMP OMEGA ECOSYSTEM FULLSCREEN APP WRAPPER\n  This code forces the shortcode output to behave like a native fullscreen app,\n  overriding WordPress and Elementor container restrictions.\n  ========================================================================\n-->\n\n<style>\n    \/* 1. Reset the fundamental page structure to prevent scrolling and margins *\/\n    html, body {\n        margin: 0 !important;\n        padding: 0 !important;\n        width: 100vw !important;\n        height: 100vh !important;\n        overflow: hidden !important; \/* Prevents double scrollbars *\/\n        background-color: #03060a !important; \/* Matches your loading screen background *\/\n    }\n\n    \/* 2. Override Elementor's default container padding and constraints *\/\n    .elementor-page .elementor-section-wrap,\n    .elementor-section,\n    .elementor-container,\n    .elementor-widget-wrap,\n    .elementor-widget-html {\n        width: 100% !important;\n        height: 100% !important;\n        min-height: 100vh !important;\n        margin: 0 !important;\n        padding: 0 !important;\n        max-width: none !important;\n    }\n\n    \/* 3. The App Wrapper - Forces absolute positioning and viewport sizing *\/\n    #vmp-fullscreen-app-wrapper {\n        position: fixed !important;\n        top: 0 !important;\n        left: 0 !important;\n        width: 100vw !important;\n        \/* Calculate height minus WordPress admin bar if logged in *\/\n        height: 100vh !important;\n        height: calc(100vh - var(--wp-admin--admin-bar--height, 0px)) !important;\n        z-index: 9999 !important; \/* Keeps it above everything else *\/\n        background-color: #03060a;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n    }\n\n    \/* 4. Target the specific output OF your shortcode (iframe, canvas, or div) *\/\n    #vmp-fullscreen-app-wrapper iframe,\n    #vmp-fullscreen-app-wrapper canvas,\n    #vmp-fullscreen-app-wrapper object,\n    #vmp-fullscreen-app-wrapper embed,\n    #vmp-fullscreen-app-wrapper > div {\n        position: absolute !important;\n        top: 0 !important;\n        left: 0 !important;\n        width: 100vw !important;\n        height: 100% !important;\n        border: none !important;\n        margin: 0 !important;\n        padding: 0 !important;\n        max-width: none !important;\n        outline: none !important;\n        box-shadow: none !important;\n    }\n<\/style>\n\n<!-- \n  5. THE CONTAINER \n  Place your shortcode exactly where it says [YOUR_SHORTCODE_HERE]\n-->\n<div id=\"vmp-fullscreen-app-wrapper\">\n    \n     \r\n    <link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.4.0\/css\/all.min.css\">\r\n    <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;700;900&family=Space+Mono:wght@400;700;900&display=swap\" rel=\"stylesheet\">\r\n    <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/webxr-polyfill@latest\/build\/webxr-polyfill.js\"><\/script>\r\n\r\n    <script>\r\n        if (typeof window.WebXRPolyfill !== 'undefined') {\r\n            var polyfill = new window.WebXRPolyfill();\r\n        }\r\n        window.VMP_CONFIG = {\"geminiApiKey\":\"AIzaSyDc_Kgwy_bikE62cPrUxKXK7D3jKKKP1GY\",\"transforms\":{\"pyramid\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"floor\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"wall_left\":{\"pos_x\":-1292.4262292345,\"pos_y\":1868.1597466969,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0.11844657030607,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"wall_right\":{\"pos_x\":1359.4689655285,\"pos_y\":1757.1008044935,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":-0.12093781721525,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"wall_back\":{\"pos_x\":0,\"pos_y\":1680.2960727172,\"pos_z\":-1851.3594301599,\"rot_x\":-0.13649813517743,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"roof\":{\"pos_x\":0,\"pos_y\":-4071.6939481112,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"pool\":{\"pos_x\":0,\"pos_y\":-24.004799104052,\"pos_z\":-0.079918940891275,\"rot_x\":-0.04,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"motherboards\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"city\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"dog\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":26,\"scale_y\":26,\"scale_z\":26},\"dog_jara\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":26,\"scale_y\":26,\"scale_z\":26},\"orb\":{\"pos_x\":0,\"pos_y\":174.47270218897,\"pos_z\":8.0441508638805,\"rot_x\":0.026666666666667,\"rot_y\":0,\"rot_z\":0,\"scale_x\":12,\"scale_y\":12,\"scale_z\":12},\"abstract_figure\":{\"pos_x\":0,\"pos_y\":-130.57183988428,\"pos_z\":4.0634149383873,\"rot_x\":-0.093333333333333,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"beach\":{\"pos_x\":11628.352168045,\"pos_y\":-2849.8553763118,\"pos_z\":-6571.4192079909,\"rot_x\":-0.21914145320575,\"rot_y\":0.044005696466497,\"rot_z\":-0.39486335930129,\"scale_x\":3.2499262348614,\"scale_y\":4.0596325381758,\"scale_z\":2.7672505749512},\"themepark\":{\"pos_x\":-14844.518310066,\"pos_y\":-15591.496238336,\"pos_z\":-8314.0945036841,\"rot_x\":0.29773301972455,\"rot_y\":0.16264981717383,\"rot_z\":0.99560304096723,\"scale_x\":13.468917702516,\"scale_y\":14.256987810677,\"scale_z\":18.698131198153},\"golfcourse\":{\"pos_x\":0,\"pos_y\":-15532.065756105,\"pos_z\":-9316.0143313903,\"rot_x\":-1.0666666666667,\"rot_y\":0,\"rot_z\":0,\"scale_x\":9.6836427686465,\"scale_y\":12.377001731109,\"scale_z\":5.64077011212},\"school\":{\"pos_x\":-3626.0982639695,\"pos_y\":-2083.2424630528,\"pos_z\":3905.5217343061,\"rot_x\":0.26683126462542,\"rot_y\":0.034705205783321,\"rot_z\":0.25718219881953,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"hospital\":{\"pos_x\":3626.0982639695,\"pos_y\":-2083.2424630528,\"pos_z\":3905.5217343061,\"rot_x\":0.26683126462542,\"rot_y\":-0.034705205783321,\"rot_z\":-0.25718219881953,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"satellite_1\":{\"pos_x\":-15756.354386128,\"pos_y\":-12266.204307471,\"pos_z\":-22773.599562696,\"rot_x\":-0.68068376041591,\"rot_y\":-0.18685763589134,\"rot_z\":0.51734939254395,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"satellite_2\":{\"pos_x\":15756.354386128,\"pos_y\":-12266.204307471,\"pos_z\":22773.599562696,\"rot_x\":0.68068376041591,\"rot_y\":-0.18685763589134,\"rot_z\":-0.51734939254395,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"monorail_system\":{\"pos_x\":0,\"pos_y\":800,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"sky_highway\":{\"pos_x\":0,\"pos_y\":1200,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_car\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":0.2,\"scale_y\":0.2,\"scale_z\":0.2},\"model_train\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_hovercar\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_mom\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_dad\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_son\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_tree\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_animal\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_fish\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_pyramid\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_school\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_hospital\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_satellite\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_airplane\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_ride_ferris\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_ride_coaster\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_ride_cart\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1},\"model_booth\":{\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":1,\"scale_y\":1,\"scale_z\":1}},\"customPolygons\":[{\"enable\":\"yes\",\"type\":\"Tetrahedron\",\"wireframe\":\"yes\",\"color\":\"#000000\",\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":0,\"scale_y\":0,\"scale_z\":0},{\"enable\":\"yes\",\"type\":\"Tetrahedron\",\"wireframe\":\"yes\",\"color\":\"#000000\",\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":0,\"scale_y\":0,\"scale_z\":0},{\"enable\":\"yes\",\"type\":\"Tetrahedron\",\"wireframe\":\"yes\",\"color\":\"#000000\",\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":0,\"scale_y\":0,\"scale_z\":0},{\"enable\":\"yes\",\"type\":\"Tetrahedron\",\"wireframe\":\"yes\",\"color\":\"#000000\",\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":0,\"scale_y\":0,\"scale_z\":0},{\"enable\":\"yes\",\"type\":\"Tetrahedron\",\"wireframe\":\"yes\",\"color\":\"#000000\",\"pos_x\":0,\"pos_y\":0,\"pos_z\":0,\"rot_x\":0,\"rot_y\":0,\"rot_z\":0,\"scale_x\":0,\"scale_y\":0,\"scale_z\":0}],\"districtTextures\":{\"district1\":{\"name\":\"Financial Core\",\"textures\":[\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Poliigon_StoneQuartzite_8060_BaseColor.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/game_bg.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-22-2026-10_08PM.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/vmp_scene_wide_gif-Camera-loader.jpg\"]},\"district2\":{\"name\":\"Historic District\",\"textures\":[\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Poliigon_StoneQuartzite_8060_BaseColor.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/game_bg.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-22-2026-10_08PM.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/vmp_scene_wide_gif-Camera-loader.jpg\"]},\"district3\":{\"name\":\"Arts District\",\"textures\":[\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Poliigon_StoneQuartzite_8060_BaseColor.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/game_bg.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-22-2026-10_08PM.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/vmp_scene_wide_gif-Camera-loader.jpg\"]},\"district4\":{\"name\":\"Residential Zone\",\"textures\":[\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Poliigon_StoneQuartzite_8060_BaseColor.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/building.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-22-2026-10_08PM.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/vmp_scene_wide_gif-Camera-loader.jpg\"]},\"district5\":{\"name\":\"Cyberpunk Sector\",\"textures\":[\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Poliigon_StoneQuartzite_8060_BaseColor.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/game_bg.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-22-2026-10_08PM.png\",\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/vmp_scene_wide_gif-Camera-loader.jpg\"]}},\"bpConstruction\":\"Follow standard safety protocols. Foundation must be level. Refer to spec sheet for material grades.\",\"bpElectrician\":\"All wiring must meet 2026 city code. Ensure all circuits are properly grounded before activating main power.\",\"bpPlumber\":\"Check for leaks at all joints using pressure test. Use only approved sealant.\",\"bpMechanic\":\"Torque all bolts to manufacturer specifications. Lubricate all moving parts before reassembly.\",\"camPosX\":1114.6643970409,\"camPosY\":2069.3761093459,\"camPosZ\":5021.6022822874,\"camRotX\":-0.35061257434366,\"camRotY\":0.18736802193766,\"camRotZ\":0.068019427429327,\"envBg\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/citrus_orchard_road_puresky-scaled.jpg\",\"mornBg\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/citrus_orchard_road_puresky-scaled.jpg\",\"aftBg\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/afternoon-1-scaled.jpg\",\"nightBump\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-27-2026-6_28PM.png\",\"floorDiff\":\"https:\\\/\\\/www.vmpnfts.com\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-25-2026-3_14PM-1.png\",\"floorBump\":\"https:\\\/\\\/www.vmpnfts.com\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Generated-Image-March-25-2026-3_14PM-1.png\",\"floorRough\":0.9,\"floorMetal\":0,\"floorScaleX\":1,\"floorScaleY\":1,\"floorRotation\":0,\"floorOffsetX\":0,\"floorOffsetY\":0,\"abstractQuartzite\":\"https:\\\/\\\/www.vmpnfts.com\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Poliigon_StoneQuartzite_8060_Preview1.png\",\"curvedDiff\":\"https:\\\/\\\/www.vmpnfts.com\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Poliigon_StoneQuartzite_8060_Preview1.png\",\"roofDiff\":\"\",\"fogColor\":\"#00fbff\",\"fogDensity\":5.0e-5,\"dayNightSpeed\":0,\"hwRatio\":\"1.0\",\"hwShadows\":\"yes\",\"hwAntialias\":\"yes\",\"pyrDiff\":\"https:\\\/\\\/www.vmpnfts.com\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"pyrBump\":\"https:\\\/\\\/www.vmpnfts.com\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"pyrRough\":0.8,\"pyrMetal\":0.2,\"pyrScaleX\":1,\"pyrScaleY\":1,\"pyrRotation\":0,\"pyrOffsetX\":0,\"pyrOffsetY\":0,\"extWallLeftDiff\":\"https:\\\/\\\/images.unsplash.com\\\/photo-1555680202-c86f0e12f086?q=80&w=2000\",\"extWallRightDiff\":\"https:\\\/\\\/images.unsplash.com\\\/photo-1541701494587-cb58502866ab?q=80&w=2000\",\"extWallBackDiff\":\"https:\\\/\\\/images.unsplash.com\\\/photo-1550745165-9bc0b252726f?q=80&w=2000\",\"orbColor\":\"#22afec\",\"orbWireColor\":\"#ffffff\",\"orbWarpSpeed\":1.5,\"orbWarpAmount\":15,\"tendrilColor\":\"#d4af37\",\"mbBaseColor\":\"rgba(0,150,255,0.7)\",\"mbTextColor\":\"#00f3ff\",\"waterColor\":\"#19c6d2\",\"birdColor\":\"#12ceb8\",\"colorMom\":\"#ff0055\",\"colorDad\":\"#0044ff\",\"colorSon\":\"#00ff66\",\"rockoTex1\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/2k_earth_daymap.jpg\",\"rockoTex2\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/2k_earth_daymap.jpg\",\"rockoTex3\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/2k_earth_daymap.jpg\",\"rockoTex4\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/2k_earth_daymap.jpg\",\"rockoTex5\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/2k_earth_daymap.jpg\",\"grassHeight\":20.1,\"popBirds\":30,\"popFish\":0,\"popRabbits\":30,\"popButterflies\":10,\"popTrees\":30,\"grassBlades\":5000,\"geminiCity\":\"yes\",\"cityDensity\":100,\"trafficDensity\":50,\"pedDensity\":50,\"cityBldgTexture\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/gold_texture-1.jpg\",\"bldInteriorTex\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/building.png\",\"bldFacadeTex\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/building.png\",\"school_density\":20,\"hospital_density\":20,\"fire_station_density\":20,\"walletSupply\":\"0x368872AA994017cA2D66d7301F81dcd3DCc76c10\",\"walletFee\":\"0xd3BD28A203B4D31FC230a1fa19b71c2499852571\",\"wallet_eth_miner\":\"0xd3BD28A203B4D31FC230a1fa19b71c2499852571\",\"wallet_btc_miner\":\"bc1q28983xk2lrnvqnv42nnkncdy4rf00gd2hxg8ld\",\"wallet_sol_miner\":\"DWXFktAvtdcX87WFBesPEExUS7wGU3VE6bzyGKuSTE9R\",\"budgetPresident\":\"10,000,000,000,000\",\"budgetMayor\":\"500,000,000,000\",\"modelCar\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/CesiumMilkTruck\\\/glTF-Binary\\\/CesiumMilkTruck.glb\",\"modelTrain\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/Box\\\/glTF-Binary\\\/Box.glb\",\"modelHovercar\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/Duck\\\/glTF-Binary\\\/Duck.glb\",\"modelMom\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/RiggedFigure\\\/glTF-Binary\\\/RiggedFigure.glb\",\"modelDad\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/RiggedFigure\\\/glTF-Binary\\\/RiggedFigure.glb\",\"modelSon\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/RiggedFigure\\\/glTF-Binary\\\/RiggedFigure.glb\",\"modelTree\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/plugins\\\/VMP_Oemga_System\\\/obj\\\/trees_big.obj \",\"modelAnimal\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/plugins\\\/VMP_Oemga_System\\\/obj\\\/rabbit.obj \",\"modelFish\":\"\",\"modelPyramid\":\"\",\"modelSchool\":\" \",\"modelHospital\":\" \",\"modelSatellite\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/Box\\\/glTF-Binary\\\/Box.glb\",\"modelAirplane\":\"https:\\\/\\\/docs.mapbox.com\\\/mapbox-gl-js\\\/assets\\\/airplane.glb\",\"modelRideFerris\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/GearboxAssy\\\/glTF-Binary\\\/GearboxAssy.glb\",\"modelRideCoaster\":\" \",\"modelRideCart\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/Box\\\/glTF-Binary\\\/Box.glb\",\"modelBooth\":\"https:\\\/\\\/raw.githubusercontent.com\\\/KhronosGroup\\\/glTF-Sample-Models\\\/master\\\/2.0\\\/BoxTextured\\\/glTF-Binary\\\/BoxTextured.glb\",\"texMercury\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Mercury-Texture-scaled.jpg\",\"texVenus\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/venus.jpg\",\"texEarth\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/2k_earth_daymap.jpg\",\"texMars\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/images.jpg\",\"texJupiter\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/jupitermap.jpg\",\"texSaturn\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/saturnmap.jpg\",\"texUranus\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Solarsystemscope_texture_2k_uranus.jpg\",\"texNeptune\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Solarsystemscope_texture_2k_neptune.jpg\",\"texMoon\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Moon_VT.png\",\"texSun\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/Solarsystemscope_texture_2k_sun.jpg\",\"texCytron\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/2k_earth_daymap.jpg\",\"texAngel\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/03\\\/angel-scaled.jpg\",\"texSnowflake\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/snowflake.png\",\"texLeaf\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/leaves.png\",\"texRaindrop\":\"https:\\\/\\\/www.vmpnfts.com\\\/Omega3dWorldEcosystem\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/raindrop.png\"};\r\n        window.VMP_API_BASE = 'https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/';\r\n        window.VMP_VIEWPORT_EDITS = {};\r\n        window.VMP_INSTANCE_ID = 'vmp_matrix_69ee2dd34f27e';\r\n    <\/script>\r\n\r\n    <style>\r\n        .elementor-widget-shortcode:has(#vmp_matrix_69ee2dd34f27e),\r\n        .elementor-widget-shortcode:has(#vmp_matrix_69ee2dd34f27e) .elementor-widget-container,\r\n        .elementor-shortcode:has(#vmp_matrix_69ee2dd34f27e),\r\n        .elementor-widget-wrap:has(#vmp_matrix_69ee2dd34f27e) {\r\n            height: 100% !important;\r\n            display: flex !important;\r\n            flex-grow: 1 !important;\r\n            width: 100% !important;\r\n            align-items: stretch !important;\r\n            margin: 0 !important;\r\n            padding: 0 !important;\r\n            overflow: hidden !important;\r\n            box-sizing: border-box !important;\r\n        }\r\n\r\n        .e-con:has(#vmp_matrix_69ee2dd34f27e),\r\n        .e-con-inner:has(#vmp_matrix_69ee2dd34f27e) {\r\n            display: flex !important;\r\n            align-items: stretch !important;\r\n            overflow: hidden !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e ::-webkit-scrollbar {\r\n            display: none !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e * {\r\n            box-sizing: border-box !important;\r\n            margin: 0;\r\n            padding: 0;\r\n            user-select: none;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e.vmp-omega-safe-wrapper {\r\n            display: flex;\r\n            margin: 0 !important;\r\n            padding: 0 !important;\r\n            background: #000;\r\n            overflow: hidden !important;\r\n            flex-grow: 1;\r\n            width: 100% !important;\r\n            transition: height 0.3s ease;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-metaverse-takeover {\r\n            --vmp-bg-primary: #020408;\r\n            --vmp-bg-panel: rgba(10, 14, 20, 0.85);\r\n            --vmp-border-color: #1f2937;\r\n            --vmp-font-secondary: #64748b;\r\n            --vmp-accent-cyan: #00e5ff;\r\n            --vmp-sidebar-width: 85px;\r\n            --vmp-navbar-height: 60px;\r\n\r\n            display: flex;\r\n            flex-direction: column;\r\n            width: 100%;\r\n            height: 100% !important;\r\n            background: var(--vmp-bg-primary);\r\n            font-family: 'Inter', sans-serif;\r\n            color: #e2e8f0;\r\n            overflow: hidden;\r\n            z-index: 10;\r\n            position: relative;\r\n        }\r\n\r\n        #vmp-window-controls_vmp_matrix_69ee2dd34f27e {\r\n            position: absolute;\r\n            top: 15px;\r\n            right: 15px;\r\n            z-index: 100000;\r\n            display: flex;\r\n            gap: 10px;\r\n        }\r\n\r\n        .vmp-win-btn {\r\n            background: rgba(10, 14, 20, 0.9);\r\n            border: 1px solid #00e5ff;\r\n            color: #00e5ff;\r\n            padding: 5px 10px;\r\n            border-radius: 4px;\r\n            cursor: pointer;\r\n            font-family: 'Space Mono', monospace;\r\n            font-size: 10px;\r\n            text-transform: uppercase;\r\n            transition: 0.2s;\r\n        }\r\n\r\n        .vmp-win-btn:hover {\r\n            background: #00e5ff;\r\n            color: #000;\r\n        }\r\n\r\n        .vmp-win-btn.close:hover {\r\n            background: #ff0055;\r\n            border-color: #ff0055;\r\n            color: #fff;\r\n        }\r\n\r\n        #auth-overlay_vmp_matrix_69ee2dd34f27e {\r\n            position: fixed;\r\n            inset: 0;\r\n            background: rgba(0,0,0,0.9);\r\n            z-index: 999999;\r\n            display: none;\r\n            justify-content: center;\r\n            align-items: center;\r\n            flex-direction: column;\r\n        }\r\n\r\n        #auth-overlay_vmp_matrix_69ee2dd34f27e h2 {\r\n            color: #00e5ff;\r\n            font-family: 'Space Mono', monospace;\r\n            margin-bottom: 20px;\r\n        }\r\n\r\n        #auth-overlay_vmp_matrix_69ee2dd34f27e input {\r\n            background: #111;\r\n            color: #00ff66;\r\n            border: 1px solid #00e5ff;\r\n            padding: 15px;\r\n            margin: 10px;\r\n            font-family: monospace;\r\n            width: 300px;\r\n            font-size: 16px;\r\n            text-align: center;\r\n        }\r\n\r\n        #auth-overlay_vmp_matrix_69ee2dd34f27e button {\r\n            background: #00e5ff;\r\n            color: #000;\r\n            padding: 15px 30px;\r\n            border: none;\r\n            cursor: pointer;\r\n            font-weight: bold;\r\n            margin-top: 20px;\r\n            font-family: 'Space Mono';\r\n            text-transform: uppercase;\r\n        }\r\n\r\n        #auth-overlay_vmp_matrix_69ee2dd34f27e button:hover {\r\n            background: #fff;\r\n        }\r\n\r\n        #auth-cancel_vmp_matrix_69ee2dd34f27e {\r\n            background: #ff0055 !important;\r\n        }\r\n\r\n        #auth-cancel_vmp_matrix_69ee2dd34f27e:hover {\r\n            background: #fff !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-loading-overlay {\r\n            position: absolute;\r\n            inset: 0;\r\n            background: rgba(2, 4, 8, 0.98);\r\n            z-index: 100000;\r\n            display: flex;\r\n            flex-direction: column;\r\n            justify-content: center;\r\n            align-items: center;\r\n            color: var(--vmp-accent-cyan);\r\n            transition: opacity 0.5s ease;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-loading-overlay i {\r\n            font-size: 72px;\r\n            margin-bottom: 20px;\r\n            animation: vmpPulse 2s infinite;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-loading-overlay h1 {\r\n            font-family: 'Space Mono', monospace;\r\n            font-size: 28px;\r\n            text-transform: uppercase;\r\n            letter-spacing: 2px;\r\n            text-align: center;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-loading-overlay p {\r\n            margin-top: 10px;\r\n            color: var(--vmp-font-secondary);\r\n            font-family: 'Space Mono', monospace;\r\n            font-size: 12px;\r\n        }\r\n\r\n        @keyframes vmpPulse {\r\n            0% { transform: scale(1); opacity: 1; text-shadow: 0 0 10px var(--vmp-accent-cyan); }\r\n            50% { transform: scale(1.1); opacity: 0.7; text-shadow: 0 0 30px var(--vmp-accent-cyan); }\r\n            100% { transform: scale(1); opacity: 1; text-shadow: 0 0 10px var(--vmp-accent-cyan); }\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-nav-bar {\r\n            height: var(--vmp-navbar-height);\r\n            background-color: rgba(10, 14, 20, 0.95);\r\n            backdrop-filter: blur(10px);\r\n            border-bottom: 1px solid var(--vmp-border-color);\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: space-between;\r\n            padding: 0 25px;\r\n            z-index: 1000;\r\n            flex-shrink: 0;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-brand-logo {\r\n            font-weight: 900;\r\n            font-size: 20px;\r\n            letter-spacing: 2px;\r\n            color: var(--vmp-accent-cyan);\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 10px;\r\n            text-shadow: 0 0 10px rgba(0, 229, 255, 0.3);\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-nav-actions {\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 20px;\r\n            margin-right: 120px;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-action-btn {\r\n            background-color: rgba(10, 14, 20, 0.85);\r\n            backdrop-filter: blur(8px);\r\n            border: 1px solid var(--vmp-border-color);\r\n            color: #fff;\r\n            padding: 8px 12px;\r\n            border-radius: 8px;\r\n            font-size: 12px;\r\n            font-weight: 700;\r\n            cursor: pointer;\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 8px;\r\n            transition: all 0.2s ease;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-action-btn:hover {\r\n            border-color: var(--vmp-accent-cyan);\r\n            color: var(--vmp-accent-cyan);\r\n            transform: translateY(-2px);\r\n            box-shadow: 0 5px 15px rgba(0, 229, 255, 0.2);\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-vr-button-container button {\r\n            position: relative !important;\r\n            bottom: auto !important;\r\n            left: auto !important;\r\n            transform: none !important;\r\n            margin: 0 !important;\r\n            padding: 8px 12px !important;\r\n            font-family: 'Inter', sans-serif !important;\r\n            font-weight: 700 !important;\r\n            font-size: 12px !important;\r\n            border-radius: 8px !important;\r\n            background: rgba(10, 14, 20, 0.85) !important;\r\n            border: 1px solid #00e5ff !important;\r\n            color: #00e5ff !important;\r\n            cursor: pointer !important;\r\n            transition: all 0.2s ease !important;\r\n            opacity: 1 !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-vr-button-container button:hover {\r\n            background: #00e5ff !important;\r\n            color: #000 !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-workspace {\r\n            display: flex;\r\n            flex-grow: 1;\r\n            height: calc(100% - var(--vmp-navbar-height));\r\n            width: 100%;\r\n            position: relative;\r\n            overflow: hidden;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-sidebar {\r\n            width: var(--vmp-sidebar-width);\r\n            background-color: var(--vmp-bg-panel);\r\n            border-right: 1px solid var(--vmp-border-color);\r\n            display: flex;\r\n            flex-direction: column;\r\n            align-items: center;\r\n            padding-top: 20px;\r\n            gap: 15px;\r\n            z-index: 50;\r\n            backdrop-filter: blur(10px);\r\n            flex-shrink: 0;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-sidebar-item {\r\n            display: flex;\r\n            flex-direction: column;\r\n            align-items: center;\r\n            justify-content: center;\r\n            width: 100%;\r\n            padding: 16px 0;\r\n            color: var(--vmp-font-secondary);\r\n            cursor: pointer;\r\n            transition: all 0.2s ease;\r\n            border-left: 3px solid transparent;\r\n            font-size: 10px;\r\n            font-weight: 700;\r\n            text-transform: uppercase;\r\n            gap: 8px;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-sidebar-item i {\r\n            font-size: 22px;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-sidebar-item:hover {\r\n            color: var(--vmp-accent-cyan);\r\n            background-color: rgba(0, 229, 255, 0.05);\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-sidebar-item.active {\r\n            color: var(--vmp-accent-cyan);\r\n            border-left-color: var(--vmp-accent-cyan);\r\n            background-color: rgba(0, 229, 255, 0.1);\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-webgl-container {\r\n            flex-grow: 1;\r\n            height: 100%;\r\n            width: 100%;\r\n            outline: none;\r\n            position: relative;\r\n        }\r\n\r\n    #vmp_matrix_69ee2dd34f27e .vmp-webgl-container canvas {\r\n            width: 100% !important;\r\n            height: 100% !important;\r\n            display: block;\r\n            outline: none;\r\n            border: none;\r\n            position: absolute;\r\n            top: 0;\r\n            left: 0;\r\n\r\n            image-rendering: -webkit-optimize-contrast;\r\n            image-rendering: crisp-edges;\r\n            image-rendering: -moz-crisp-edges;\r\n        }\r\n\r\n        #vmp-master-control_vmp_matrix_69ee2dd34f27e {\r\n            position: absolute;\r\n            top: 20px;\r\n            left: 20px;\r\n            width: 360px;\r\n            background: rgba(10,14,20,0.95);\r\n            border: 1px solid #00e5ff;\r\n            border-radius: 8px;\r\n            z-index: 10000;\r\n            color: #fff;\r\n            box-shadow: 0 10px 30px rgba(0,0,0,0.8);\r\n            display: flex;\r\n\r\n            flex-direction: column;\r\n            backdrop-filter: blur(10px);\r\n            font-family: 'Space Mono', monospace;\r\n        }\r\n\r\n        .vmp-drag-handle {\r\n            background: #00e5ff;\r\n            color: #000;\r\n            padding: 10px;\r\n            font-weight: 900;\r\n            cursor: grab;\r\n            border-radius: 7px 7px 0 0;\r\n            text-transform: uppercase;\r\n            font-size: 12px;\r\n            display:flex;\r\n            justify-content:space-between;\r\n            align-items: center;\r\n        }\r\n\r\n        .vmp-drag-handle:active {\r\n            cursor: grabbing;\r\n        }\r\n\r\n        .vmp-mc-body {\r\n            padding: 15px;\r\n            overflow-y: auto;\r\n            max-height: 70vh;\r\n        }\r\n\r\n        .vmp-mc-body::-webkit-scrollbar {\r\n            width: 5px;\r\n        }\r\n\r\n        .vmp-mc-body::-webkit-scrollbar-thumb {\r\n            background: #00e5ff;\r\n            border-radius: 5px;\r\n        }\r\n\r\n        .vmp-section-title {\r\n            font-size: 10px;\r\n            color: #00e5ff;\r\n            font-weight: 900;\r\n            margin: 15px 0 5px 0;\r\n            border-bottom: 1px solid #333;\r\n            padding-bottom: 3px;\r\n            text-transform: uppercase;\r\n        }\r\n\r\n        .vmp-section-title:first-child {\r\n            margin-top: 0;\r\n        }\r\n\r\n        .vmp-btn-group {\r\n            display: flex;\r\n            gap: 5px;\r\n            margin-bottom: 5px;\r\n        }\r\n\r\n        .vmp-btn-grid {\r\n            display: grid;\r\n            grid-template-columns: 1fr 1fr;\r\n            gap: 5px;\r\n            margin-bottom: 5px;\r\n        }\r\n\r\n        .vmp-tool-btn {\r\n            flex:1;\r\n            background: #1a1a1a;\r\n            color: #fff;\r\n            border: 1px solid #333;\r\n            padding: 8px 5px;\r\n            border-radius: 4px;\r\n            cursor: pointer;\r\n            transition: 0.2s;\r\n            font-size:10px;\r\n            font-weight:bold;\r\n        }\r\n\r\n        .vmp-tool-btn:hover,\r\n        .vmp-tool-btn.active {\r\n            background: #00e5ff;\r\n            color: #000;\r\n        }\r\n\r\n        .vmp-cmd-wrap {\r\n            display: flex;\r\n            flex-direction: column;\r\n            gap: 5px;\r\n        }\r\n\r\n        .vmp-cmd-input {\r\n            background: #000;\r\n            color: #00ff66;\r\n            border: 1px solid #333;\r\n            padding: 8px;\r\n            font-family: monospace;\r\n            border-radius: 4px;\r\n            outline: none;\r\n            width: 100%;\r\n            box-sizing: border-box;\r\n        }\r\n\r\n        .vmp-cmd-input:focus {\r\n            border-color: #00ff66;\r\n        }\r\n\r\n        .vmp-cmd-help {\r\n            font-size: 9px;\r\n            color: #888;\r\n            margin-top: 5px;\r\n            line-height: 1.4;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-dashboard {\r\n            width: 360px;\r\n            background-color: var(--vmp-bg-panel);\r\n            backdrop-filter: blur(15px);\r\n            border-left: 1px solid var(--vmp-border-color);\r\n            padding: 20px;\r\n            display: flex;\r\n            flex-direction: column;\r\n            gap: 20px;\r\n            z-index: 10;\r\n            overflow-y: auto;\r\n            flex-shrink: 0;\r\n            height: 100%;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-widget {\r\n            background: rgba(0,0,0,0.4);\r\n            border: 1px solid var(--vmp-border-color);\r\n            border-radius: 8px;\r\n            padding: 15px;\r\n            flex-shrink: 0;\r\n            display: flex;\r\n            flex-direction: column;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-widget-header {\r\n            font-size: 10px;\r\n            font-weight: 900;\r\n            color: var(--vmp-font-secondary);\r\n            text-transform: uppercase;\r\n            letter-spacing: 2px;\r\n            margin-bottom: 10px;\r\n            display: flex;\r\n            justify-content: space-between;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-stat-row {\r\n            display: flex;\r\n            justify-content: space-between;\r\n            font-family: 'Space Mono', monospace;\r\n            font-size: 11px;\r\n            margin-bottom: 8px;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-stat-label {\r\n            color: var(--vmp-font-secondary);\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-stat-value {\r\n            color: #00ff66;\r\n            font-weight: bold;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-terminal {\r\n            background: #000;\r\n            border: 1px solid var(--vmp-accent-cyan);\r\n            border-radius: 6px;\r\n            padding: 10px;\r\n            height: 160px;\r\n            overflow-y: auto;\r\n            font-family: 'Space Mono', monospace;\r\n            font-size: 9px;\r\n            box-shadow: inset 0 0 15px rgba(0,229,255,0.1);\r\n            display: flex;\r\n            flex-direction: column;\r\n            gap: 4px;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-log-line {\r\n            color: var(--vmp-font-secondary);\r\n            line-height: 1.4;\r\n            word-wrap: break-word;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-log-line.sys {\r\n            color: var(--vmp-accent-cyan);\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-log-line.warn {\r\n            color: #d4af37;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-log-line.err {\r\n            color: #ff0055;\r\n            font-weight: bold;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-log-line.succ {\r\n            color: #00ff66;\r\n            font-weight: bold;\r\n        }\r\n\r\n        .vmp-slider-container {\r\n            width: 100%;\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 10px;\r\n            margin-top: 5px;\r\n        }\r\n\r\n        .vmp-slider {\r\n            -webkit-appearance: none;\r\n            width: 100%;\r\n            height: 4px;\r\n            border-radius: 2px;\r\n            background: #333;\r\n            outline: none;\r\n        }\r\n\r\n        .vmp-slider::-webkit-slider-thumb {\r\n            -webkit-appearance: none;\r\n            appearance: none;\r\n            width: 12px;\r\n            height: 12px;\r\n            border-radius: 50%;\r\n            background: #ffaa00;\r\n            cursor: pointer;\r\n            box-shadow: 0 0 10px #ffaa00;\r\n        }\r\n\r\n        .vmp-slider-btn {\r\n            background: #ffaa00;\r\n            color: #000;\r\n            border: none;\r\n            padding: 4px 8px;\r\n            font-weight: bold;\r\n            border-radius: 4px;\r\n            cursor: pointer;\r\n            font-size: 9px;\r\n            text-transform: uppercase;\r\n            transition: all 0.2s;\r\n        }\r\n\r\n        .vmp-slider-btn:hover {\r\n            background: #fff;\r\n            transform: scale(1.05);\r\n        }\r\n\r\n        #vmp_gps_map {\r\n            position: absolute;\r\n            top: 70px;\r\n            left: 10px;\r\n            width: 150px;\r\n            height: 150px;\r\n            background: rgba(0,0,0,0.5);\r\n            border: 1px solid #00e5ff;\r\n            border-radius: 50%;\r\n            z-index: 100;\r\n            color: #fff;\r\n            font-family: 'Space Mono', monospace;\r\n            font-size: 10px;\r\n        }\r\n\r\n        #vmp_gps_map #map_dot {\r\n            position: absolute;\r\n            top: 50%; left: 50%;\r\n            width: 6px; height: 6px;\r\n            background: #ff0055;\r\n            border-radius: 50%;\r\n            transform: translate(-50%, -50%);\r\n        }\r\n\r\n        #vmp_gps_map .map_coords {\r\n            position: absolute;\r\n            bottom: 5px;\r\n            width: 100%;\r\n            text-align: center;\r\n        }\r\n\r\n        @media (max-width: 900px) {\r\n            #vmp_matrix_69ee2dd34f27e .vmp-dashboard,\r\n            #vmp_matrix_69ee2dd34f27e .vmp-sidebar,\r\n            #vmp_gps_map {\r\n                display: none !important;\r\n            }\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e.fullscreen-active {\r\n            position: fixed !important;\r\n            top: 0 !important;\r\n            left: 0 !important;\r\n            width: 100vw !important;\r\n            height: 100vh !important;\r\n            z-index: 999999 !important;\r\n            margin: 0 !important;\r\n            padding: 0 !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e.fullscreen-active .vmp-ui-element {\r\n            display: none !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e.fullscreen-active .vmp-workspace {\r\n            height: 100vh !important;\r\n            width: 100vw !important;\r\n        }\r\n\r\n        #vmp_matrix_69ee2dd34f27e .vmp-texture-canvas {\r\n            display: none;\r\n        }\r\n\r\n        .vmp-app-wrapper {\r\n            display: flex;\r\n            flex-direction: column;\r\n            height: 100%;\r\n            width: 100%;\r\n        }\r\n    <\/style>\r\n\r\n    <div id=\"vmp_matrix_69ee2dd34f27e\" class=\"vmp-omega-safe-wrapper\" style=\"position: relative; height: 1000px; z-index: 1;\">\r\n\r\n        <div id=\"vmp-window-controls_vmp_matrix_69ee2dd34f27e\">\r\n            <button class=\"vmp-win-btn\" onclick=\"let el=document.getElementById('vmp_matrix_69ee2dd34f27e'); el.style.height = el.style.height === '50px' ? '1000px' : '50px';\">Shrink<\/button>\r\n            <button class=\"vmp-win-btn close\" onclick=\"document.getElementById('vmp_matrix_69ee2dd34f27e').style.display = 'none';\">Close<\/button>\r\n        <\/div>\r\n\r\n        <div id=\"auth-overlay_vmp_matrix_69ee2dd34f27e\">\r\n            <h2>SYSTEM ADMIN OVERRIDE<\/h2>\r\n            <input type=\"text\" id=\"auth-user_vmp_matrix_69ee2dd34f27e\" placeholder=\"Username\">\r\n            <input type=\"password\" id=\"auth-pass_vmp_matrix_69ee2dd34f27e\" placeholder=\"Password\">\r\n            <button id=\"auth-submit_vmp_matrix_69ee2dd34f27e\">AUTHENTICATE<\/button>\r\n            <button id=\"auth-cancel_vmp_matrix_69ee2dd34f27e\">CANCEL<\/button>\r\n        <\/div>\r\n\r\n        <div class=\"vmp-metaverse-takeover\" id=\"takeover_vmp_matrix_69ee2dd34f27e\">\r\n\r\n            <div class=\"vmp-loading-overlay\" id=\"loading_vmp_matrix_69ee2dd34f27e\">\r\n                <i class=\"fas fa-microchip fa-spin\"><\/i>\r\n                <h1>Booting Live Ecosystem<\/h1>\r\n                <p id=\"loading_status_vmp_matrix_69ee2dd34f27e\">Establishing Government Entities, Deploying Utility Infrastructure, Simulating Earth Economy...<\/p>\r\n            <\/div>\r\n\r\n            <div class=\"vmp-app-wrapper\">\r\n                <nav class=\"vmp-nav-bar vmp-ui-element\">\r\n                    <div class=\"vmp-brand-logo\"><i class=\"fas fa-infinity\"><\/i> VMP OMEGA ECOSYSTEM<\/div>\r\n                    <div class=\"vmp-nav-actions\">\r\n                        <div style=\"font-family:'Space Mono'; font-size:10px; color:#ffaa00; margin-right:15px;\" id=\"season_indicator_vmp_matrix_69ee2dd34f27e\">SEASON: FALL<\/div>\r\n                        <div id=\"vr_btn_container_vmp_matrix_69ee2dd34f27e\" class=\"vmp-vr-button-container\"><\/div>\r\n                        <button id=\"btn_connect_vmp_matrix_69ee2dd34f27e\" class=\"vmp-action-btn\"><i class=\"fas fa-wallet\"><\/i> Connect Wallet<\/button>\r\n                    <\/div>\r\n                <\/nav>\r\n\r\n                <div class=\"vmp-workspace\">\r\n                    <div class=\"vmp-webgl-container\" id=\"webgl_vmp_matrix_69ee2dd34f27e\">\r\n                        <div id=\"vmp_gps_map\" class=\"vmp-ui-element\">\r\n                            <div id=\"map_dot\"><\/div>\r\n                            <div class=\"map_coords\">\r\n                                <span id=\"gps_lat\">LAT: 0.00<\/span><br>\r\n                                <span id=\"gps_lon\">LON: 0.00<\/span>\r\n                            <\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n\r\n                    <div id=\"vmp-master-control_vmp_matrix_69ee2dd34f27e\" class=\"vmp-ui-element\">\r\n                        <div class=\"vmp-drag-handle\" id=\"vmp-master-drag_vmp_matrix_69ee2dd34f27e\">\r\n                            <span><i class=\"fas fa-cube\"><\/i> VMP Max Viewport<\/span>\r\n                            <button id=\"btn-voice_vmp_matrix_69ee2dd34f27e\" title=\"Voice Command\" style=\"background:none; border:none; color:#00ff66; cursor:pointer; font-size:16px;\">\r\n                                <i class=\"fas fa-microphone\"><\/i>\r\n                            <\/button>\r\n                        <\/div>\r\n                        <div class=\"vmp-mc-body\">\r\n                            <div class=\"vmp-section-title\" style=\"color:#ffaa00;\">SYSTEM CONFIGURATION (ADMIN)<\/div>\r\n                            <div class=\"vmp-btn-grid\" style=\"grid-template-columns: 1fr 1fr 1fr;\">\r\n                                <button class=\"vmp-tool-btn func-btn\" id=\"btn-save-master_vmp_matrix_69ee2dd34f27e\" style=\"background:#00e5ff; color:#000;\">SAVE<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" id=\"btn-restore-master_vmp_matrix_69ee2dd34f27e\" style=\"background:#ffaa00; color:#000;\">RESTORE<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" id=\"btn-reset-master_vmp_matrix_69ee2dd34f27e\" style=\"background:#ff0055; color:#fff;\">RESET<\/button>\r\n                            <\/div>\r\n                            \r\n                            <div class=\"vmp-section-title\">PLANETARY TRAVEL<\/div>\r\n                             <div class=\"vmp-btn-grid\" style=\"grid-template-columns: 1fr 1fr 1fr;\">\r\n                                <button class=\"vmp-tool-btn travel-btn\" data-planet=\"Earth\">Cytron<\/button>\r\n                                <button class=\"vmp-tool-btn travel-btn\" data-planet=\"Mars\">Mars<\/button>\r\n                                <button class=\"vmp-tool-btn travel-btn\" data-planet=\"Venus\">Venus<\/button>\r\n                            <\/div>\r\n\r\n                            <div class=\"vmp-section-title\">TRANSFORM & SELECT<\/div>\r\n                            <div class=\"vmp-btn-group\">\r\n                                <button class=\"vmp-tool-btn active\" id=\"btn-t-trans_vmp_matrix_69ee2dd34f27e\"><i class=\"fas fa-arrows-alt\"><\/i> Move<\/button>\r\n                                <button class=\"vmp-tool-btn\" id=\"btn-t-rot_vmp_matrix_69ee2dd34f27e\"><i class=\"fas fa-sync-alt\"><\/i> Rotate<\/button>\r\n                                <button class=\"vmp-tool-btn\" id=\"btn-t-scale_vmp_matrix_69ee2dd34f27e\"><i class=\"fas fa-expand-arrows-alt\"><\/i> Scale<\/button>\r\n                            <\/div>\r\n\r\n                            <div class=\"vmp-section-title\">OBJECT MANIPULATION<\/div>\r\n                            <div class=\"vmp-btn-grid\" style=\"grid-template-columns: 1fr 1fr 1fr;\">\r\n                                 <button class=\"vmp-tool-btn func-btn\" data-action=\"ungroup\">Break Apart<\/button>\r\n                                 <button class=\"vmp-tool-btn func-btn\" data-action=\"curve_bend\">Curve<\/button>\r\n                                 <button id=\"btn-delete-object_vmp_matrix_69ee2dd34f27e\" class=\"vmp-tool-btn func-btn\" data-action=\"delete_object\" style=\"background:#ff0055;color:#fff;\">Delete<\/button>\r\n                            <\/div>\r\n\r\n                            <!-- SCULPTING WIDGET -->\r\n                            <div class=\"vmp-section-title\" style=\"color:#d4af37;\">ADVANCED 3D SCULPTING<\/div>\r\n                            <div class=\"vmp-btn-grid\" style=\"grid-template-columns: 1fr 1fr;\">\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"sculpt_tessellate\" style=\"background:#222; border-color:#d4af37;\">Tessellate Mesh<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"sculpt_inflate\" style=\"background:#222; border-color:#d4af37;\">Inflate Body<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"sculpt_deflate\" style=\"background:#222; border-color:#d4af37;\">Deflate Body<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"sculpt_noise\" style=\"background:#222; border-color:#d4af37;\">Clay Noise Contour<\/button>\r\n                            <\/div>\r\n\r\n                            <div class=\"vmp-section-title\">ROCKO ROBOTICS<\/div>\r\n                            <div class=\"vmp-btn-grid\">\r\n                                <button class=\"vmp-tool-btn\" id=\"btn-rocko-transform_vmp_matrix_69ee2dd34f27e\" style=\"background: #ff00aa; color:#fff;\">Distransform \/ Transform<\/button>\r\n                                <button class=\"vmp-tool-btn\" id=\"btn-rocko-move_vmp_matrix_69ee2dd34f27e\" style=\"background: #ffaa00; color:#000;\">Operate Rocko<\/button>\r\n                            <\/div>\r\n\r\n                            <div class=\"vmp-section-title\">MESH & MODELING<\/div>\r\n<label for=\"vmp-svg-upload_vmp_matrix_69ee2dd34f27e\" style=\"font-size:10px;color:#aaa; display:block;\">Upload SVG\/Illustrator File:<\/label>\r\n<input type=\"file\" id=\"vmp-svg-upload_vmp_matrix_69ee2dd34f27e\" accept=\".svg\" class=\"vmp-cmd-input\" style=\"font-size:10px; margin-bottom:5px;\" \/>\r\n                            <div class=\"vmp-btn-grid\" style=\"grid-template-columns: 1fr 1fr 1fr;\">\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"extrude\">Extrude<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"retopology\">Retopology<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"spline\">Spline<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"fluids\">Fluids<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"particles\">Particles<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"inflate\">Inflate<\/button>\r\n                            <\/div>\r\n\r\n                            <div class=\"vmp-section-title\">MATERIALS & SHADING<\/div>\r\n<label for=\"vmp-mat-color_vmp_matrix_69ee2dd34f27e\" style=\"font-size:10px;color:#aaa;\">Target Selected Mesh Color (WP Auto-Sync):<\/label>\r\n<input type=\"color\" id=\"vmp-mat-color_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"height:30px; padding:0; width:100%; margin-bottom:5px; cursor:pointer;\" \/>\r\n                            <label for=\"vmp-mat-upload_vmp_matrix_69ee2dd34f27e\" style=\"font-size:10px;color:#aaa; display:block;\">Upload Texture Map (Diffuse):<\/label>\r\n<input type=\"file\" id=\"vmp-mat-upload_vmp_matrix_69ee2dd34f27e\" accept=\"image\/*\" class=\"vmp-cmd-input\" style=\"font-size:10px; margin-bottom:5px;\" \/>\r\n                           \r\n                            <!-- SELECTED OBJECT PROPERTIES WIDGET -->\r\n                            <div id=\"vmp-selected-obj-panel_vmp_matrix_69ee2dd34f27e\" style=\"display:none; border-top:1px solid #333; padding-top:10px; margin-top:10px;\">\r\n                                <div class=\"vmp-section-title\" style=\"color:#00ff66;\">SELECTED OBJECT (LIVE EDIT)<\/div>\r\n                                <div class=\"vmp-cmd-wrap\">\r\n                                    <span id=\"sel-obj-name_vmp_matrix_69ee2dd34f27e\" style=\"font-size:10px;color:#fff;\">None Selected<\/span>\r\n                                    <div style=\"display:flex; gap:5px; margin-top:5px; align-items:center;\">\r\n                                        <input type=\"color\" id=\"sel-color_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"padding:0; width:40px; height:25px;\" title=\"Material Color\">\r\n                                        <div style=\"display:flex; flex-direction:column; flex:1;\">\r\n                                            <label style=\"font-size:9px;color:#aaa;margin-bottom:2px;\">Roughness<\/label>\r\n                                            <input type=\"range\" id=\"sel-rough_vmp_matrix_69ee2dd34f27e\" min=\"0\" max=\"1\" step=\"0.01\" class=\"vmp-slider\" style=\"width:100%;\">\r\n                                        <\/div>\r\n                                        <div style=\"display:flex; flex-direction:column; flex:1;\">\r\n                                            <label style=\"font-size:9px;color:#aaa;margin-bottom:2px;\">Metalness<\/label>\r\n                                            <input type=\"range\" id=\"sel-metal_vmp_matrix_69ee2dd34f27e\" min=\"0\" max=\"1\" step=\"0.01\" class=\"vmp-slider\" style=\"width:100%;\">\r\n                                        <\/div>\r\n                                    <\/div>\r\n                                    <div style=\"display:grid; grid-template-columns: 1fr 1fr 1fr; gap:5px; margin-top:5px;\">\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">POS X<\/label><input type=\"number\" step=\"0.1\" id=\"sel-px_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">POS Y<\/label><input type=\"number\" step=\"0.1\" id=\"sel-py_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">POS Z<\/label><input type=\"number\" step=\"0.1\" id=\"sel-pz_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">ROT X<\/label><input type=\"number\" step=\"0.1\" id=\"sel-rx_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">ROT Y<\/label><input type=\"number\" step=\"0.1\" id=\"sel-ry_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">ROT Z<\/label><input type=\"number\" step=\"0.1\" id=\"sel-rz_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">SCALE X<\/label><input type=\"number\" step=\"0.1\" id=\"sel-sx_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">SCALE Y<\/label><input type=\"number\" step=\"0.1\" id=\"sel-sy_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                        <div style=\"display:flex; flex-direction:column;\"><label style=\"font-size:8px;color:#aaa;margin-bottom:2px;\">SCALE Z<\/label><input type=\"number\" step=\"0.1\" id=\"sel-sz_vmp_matrix_69ee2dd34f27e\" class=\"vmp-cmd-input\" style=\"font-size:9px; padding:4px;\"><\/div>\r\n                                    <\/div>\r\n                                <\/div>\r\n                            <\/div>\r\n\r\n                            <div class=\"vmp-section-title\" style=\"margin-top:10px;\">RENDERING & LIGHTING<\/div>\r\n                            <div class=\"vmp-btn-grid\" style=\"grid-template-columns: 1fr 1fr 1fr 1fr;\">\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"add_spotlight\">Spot<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"add_pointlight\">Point<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"add_rectlight\">Area<\/button>\r\n                                <button class=\"vmp-tool-btn func-btn\" data-action=\"usd\">USD Export<\/button>\r\n                            <\/div>\r\n\r\n                            <div class=\"vmp-section-title\">COMMAND LINE \/ IMPORT URL<\/div>\r\n                            <div class=\"vmp-cmd-wrap\">\r\n                                <input type=\"text\" class=\"vmp-cmd-input\" id=\"vmp-cmd-input_vmp_matrix_69ee2dd34f27e\" placeholder=\"Type \/admin:login or command...\" \/>\r\n                                <div class=\"vmp-cmd-help\">Commands: <b>\/color #hex<\/b>, <b>\/texture url<\/b>, <b>\/clear<\/b>, <b>\/vmpscript<\/b><br><i>Double-click ANY object to select it. Click SAVE to push to WordPress.<\/i><\/div>\r\n                            <\/div>\r\n                        <\/div>\r\n                    <\/div>\r\n\r\n                    <aside class=\"vmp-dashboard vmp-ui-element\">\r\n                        <div class=\"vmp-widget\">\r\n                            <div class=\"vmp-widget-header\">Server Telemetry <i class=\"fas fa-server\"><\/i><\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">ENGINE STATUS:<\/span>\r\n                                <span class=\"vmp-stat-value\">GPU ACCELERATED<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">TONE MAPPING:<\/span>\r\n                                <span class=\"vmp-stat-value\">ACES FILMIC<\/span>\r\n                            <\/div>\r\n                        <\/div>\r\n                        \r\n                        <div class=\"vmp-widget\" style=\"padding: 10px;\">\r\n                            <div class=\"vmp-widget-header\" style=\"color: #ffaa00; padding-left: 5px;\">Crypto Mining Ops <i class=\"fas fa-bolt\"><\/i><\/div>\r\n                            <div id=\"miner_terminal_vmp_matrix_69ee2dd34f27e\" class=\"vmp-terminal\" style=\"height: 100px;\">\r\n                                <div class=\"vmp-log-line sys\">[MINER] Initializing 6 worker nodes...<\/div>\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n\r\n                        <div class=\"vmp-widget\" style=\"border-color: rgba(255,170,0,0.4);\">\r\n                            <div class=\"vmp-widget-header\" style=\"color: #ffaa00;\">Earth AI Economy <i class=\"fas fa-city\"><\/i><\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">CITY BUILDER:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#ffaa00;\">RUNNING<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">PRESIDENT BUDGET:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#ffaa00;\" id=\"stat_pres_vmp_matrix_69ee2dd34f27e\">$10,000,000,000,000<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">MAYOR BUDGET:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#00e5ff;\" id=\"stat_mayor_vmp_matrix_69ee2dd34f27e\">$500,000,000,000<\/span>\r\n                            <\/div>\r\n                            <div style=\"height:1px; background:#333; margin:8px 0;\"><\/div>\r\n                            \r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">WALL STREET:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#00ff66;\" id=\"stat_wallst_vmp_matrix_69ee2dd34f27e\">$0<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">CRYPTO ASSETS:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#00ff66;\" id=\"stat_crypto_vmp_matrix_69ee2dd34f27e\">$0<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">OCEAN YIELD:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#00e5ff;\" id=\"stat_ocean_vmp_matrix_69ee2dd34f27e\">$0<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">REAL ESTATE:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#ffaa00;\" id=\"stat_realestate_vmp_matrix_69ee2dd34f27e\">$0<\/span>\r\n                            <\/div>\r\n                            <div style=\"height:1px; background:#333; margin:8px 0;\"><\/div>\r\n\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">FAMILIES:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#fff;\" id=\"stat_pop_vmp_matrix_69ee2dd34f27e\">0<\/span>\r\n                            <\/div>\r\n                             <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">ACTIVE BUILDERS:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#ffaa00;\" id=\"stat_bldr_vmp_matrix_69ee2dd34f27e\">0<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">ACTIVE ENGINEERS:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#00e5ff;\" id=\"stat_eng_vmp_matrix_69ee2dd34f27e\">0<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">ACTIVE PLUMBERS:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#6fa8dc;\" id=\"stat_plmbr_vmp_matrix_69ee2dd34f27e\">0<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">TRAFFIC:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#fff;\" id=\"stat_traffic_vmp_matrix_69ee2dd34f27e\">0<\/span>\r\n                            <\/div>\r\n                            <div class=\"vmp-stat-row\">\r\n                                <span class=\"vmp-stat-label\">BUILDINGS:<\/span>\r\n                                <span class=\"vmp-stat-value\" style=\"color:#fff;\" id=\"stat_bld_vmp_matrix_69ee2dd34f27e\">0<\/span>\r\n                            <\/div>\r\n                            <div style=\"margin-top:10px; border-top: 1px dashed #333; padding-top:10px;\">\r\n                                <div class=\"vmp-stat-row\" style=\"margin-bottom:0;\">\r\n                                    <span class=\"vmp-stat-label\">CITY DENSITY (LIVE)<\/span>\r\n                                <\/div>\r\n                                <div class=\"vmp-slider-container\">\r\n                                    <input type=\"range\" id=\"city_density_slider_vmp_matrix_69ee2dd34f27e\" class=\"vmp-slider\" min=\"5\" max=\"100\" value=\"5\">\r\n                                    <button id=\"btn_build_city_vmp_matrix_69ee2dd34f27e\" class=\"vmp-slider-btn\">DEPLOY<\/button>\r\n                                <\/div>\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <div class=\"vmp-widget\" style=\"padding: 10px;\">\r\n                            <div class=\"vmp-widget-header\" style=\"padding-left: 5px;\">Web3 Event Log <i class=\"fas fa-terminal\"><\/i><\/div>\r\n                            <div id=\"terminal_vmp_matrix_69ee2dd34f27e\" class=\"vmp-terminal\">\r\n                                <div class=\"vmp-log-line sys\">[SYSTEM] Boot sequence initialized.<\/div>\r\n                            <\/div>\r\n                        <\/div>\r\n                    <\/aside>\r\n\r\n                    <aside class=\"vmp-sidebar vmp-ui-element\">\r\n                        <div id=\"btn_play_vmp_matrix_69ee2dd34f27e\" class=\"vmp-sidebar-item active\">\r\n                            <i class=\"fas fa-desktop\"><\/i> Enter World\r\n                        <\/div>\r\n                        <div id=\"btn_drive_car_vmp_matrix_69ee2dd34f27e\" class=\"vmp-sidebar-item\" style=\"color:#ffaa00;\">\r\n                           <i class=\"fas fa-car\"><\/i> Drive Car\r\n                        <\/div>\r\n                        <div id=\"btn_fullscreen_vmp_matrix_69ee2dd34f27e\" class=\"vmp-sidebar-item\">\r\n                            <i class=\"fas fa-expand\"><\/i> Fullscreen\r\n                        <\/div>\r\n                        <div id=\"btn_swim_vmp_matrix_69ee2dd34f27e\" class=\"vmp-sidebar-item\">\r\n                           <i class=\"fas fa-water\"><\/i> Swim Mode\r\n                        <\/div>\r\n                        <div id=\"btn_gemini_vmp_matrix_69ee2dd34f27e\" class=\"vmp-sidebar-item\" style=\"margin-top:auto;\">\r\n                           <i class=\"fas fa-brain\"><\/i> Gemini Gen\r\n                        <\/div>\r\n                    <\/aside>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <canvas id=\"cmdScreen_vmp_matrix_69ee2dd34f27e\" class=\"vmp-texture-canvas\" width=\"2048\" height=\"1024\"><\/canvas>\r\n            <canvas id=\"mbCanvas1_vmp_matrix_69ee2dd34f27e\" class=\"vmp-texture-canvas\" width=\"1024\" height=\"1024\"><\/canvas>\r\n            <canvas id=\"mbCanvas2_vmp_matrix_69ee2dd34f27e\" class=\"vmp-texture-canvas\" width=\"1280\" height=\"1024\"><\/canvas>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <script type=\"importmap\">\r\n    {\r\n        \"imports\": {\r\n            \"three\": \"https:\/\/cdn.jsdelivr.net\/npm\/three@0.148.0\/build\/three.module.js\",\r\n            \"three\/addons\/\": \"https:\/\/cdn.jsdelivr.net\/npm\/three@0.148.0\/examples\/jsm\/\"\r\n        }\r\n    }\r\n    <\/script>\r\n\r\n    <script type=\"module\">\r\n        import * as THREE from 'three';\r\n        import { OrbitControls } from 'three\/addons\/controls\/OrbitControls.js';\r\n        import { PointerLockControls } from 'three\/addons\/controls\/PointerLockControls.js';\r\n        import { TransformControls } from 'three\/addons\/controls\/TransformControls.js';\r\n        import { VRButton } from 'three\/addons\/webxr\/VRButton.js';\r\n        import { GLTFLoader } from 'three\/addons\/loaders\/GLTFLoader.js';\r\n        import { OBJLoader } from 'three\/addons\/loaders\/OBJLoader.js';\r\n        import { SVGLoader } from 'three\/addons\/loaders\/SVGLoader.js';\r\n        import { FontLoader } from 'three\/addons\/loaders\/FontLoader.js';\r\n        import { TextGeometry } from 'three\/addons\/geometries\/TextGeometry.js';\r\n        import { DRACOLoader } from 'three\/addons\/loaders\/DRACOLoader.js';\r\n        import { TessellateModifier } from 'three\/addons\/modifiers\/TessellateModifier.js';\r\n\r\n        const INSTANCE_ID = \"vmp_matrix_69ee2dd34f27e\";\r\n        const cacheBusterTime = Date.now();\r\n        const texLoader = new THREE.TextureLoader();\r\n        \r\n        const gltfLoader = new GLTFLoader();\r\n        const dracoLoader = new DRACOLoader();\r\n        dracoLoader.setDecoderPath('https:\/\/www.gstatic.com\/draco\/v1\/decoders\/');\r\n        gltfLoader.setDRACOLoader(dracoLoader);\r\n\r\n        const getBustUrl = (url) => {\r\n            if (!url) {\r\n                return '';\r\n            }\r\n            const sep = url.includes('?') ? '&' : '?';\r\n            return url + sep + 'cb=' + cacheBusterTime;\r\n        };\r\n\r\n        const yieldFrame = () => new Promise(resolve => setTimeout(resolve, 0));\r\n\r\n        class TerminalLogger {\r\n            static log(msg, type='sys', terminalId = `terminal_${INSTANCE_ID}`) {\r\n                const term = document.getElementById(terminalId);\r\n                if (!term) return;\r\n\r\n                const div = document.createElement('div');\r\n                div.className = `vmp-log-line ${type}`;\r\n\r\n                const timeStr = new Date().toISOString().split('T')[1].slice(0,-1);\r\n                div.innerText = `[${timeStr}] ${msg}`;\r\n\r\n                term.appendChild(div);\r\n                term.scrollTop = term.scrollHeight;\r\n\r\n                if (term.children.length > 50) {\r\n                    term.removeChild(term.firstChild);\r\n                }\r\n            }\r\n        }\r\n\r\n        const updateLoadStatus = (msg) => {\r\n            const el = document.getElementById(`loading_status_${INSTANCE_ID}`);\r\n            if (el) el.innerText = msg;\r\n            TerminalLogger.log(msg, \"sys\");\r\n        };\r\n\r\n        \/\/ --- GLOBAL VMP UNIFIED WORKER ---\r\n        const vmpWorkerScript = `\r\n            const PLANET_RADIUS = 30000;\r\n            \r\n            function wrapToPlanet(x, z, yOffset = 0) {\r\n                const lon = x \/ PLANET_RADIUS;\r\n                const lat = z \/ PLANET_RADIUS;\r\n                const r = PLANET_RADIUS + yOffset;\r\n                \r\n                return {\r\n                    x: r * Math.sin(lon) * Math.cos(lat),\r\n                    y: r * Math.cos(lon) * Math.cos(lat) - PLANET_RADIUS,\r\n                    z: r * Math.sin(lat)\r\n                };\r\n            }\r\n\r\n            self.onmessage = function(e) {\r\n                if (e.data.action === 'buildCity') {\r\n                    const blueprints = buildCityBlueprints(e.data.densityPercent, e.data.config);\r\n                    self.postMessage({ action: 'cityBuilt', blueprints: blueprints });\r\n                } else if (e.data.action === 'bendDuneGeometry') {\r\n                    const positions = e.data.positions;\r\n                    const count = positions.length \/ 3;\r\n                    for (let i = 0; i < count; i++) {\r\n                        const x = positions[i*3] + 17000; \r\n                        const z = -positions[i*3+2];\r\n                        const height = positions[i*3+1];\r\n                        const sphericalPos = wrapToPlanet(x, z, height);\r\n                        positions[i*3] = sphericalPos.x;\r\n                        positions[i*3+1] = sphericalPos.y;\r\n                        positions[i*3+2] = sphericalPos.z;\r\n                    }\r\n                    self.postMessage({ action: 'geometryBent', id: e.data.id, positions: positions }, [positions.buffer]);\r\n                }\r\n            };\r\n\r\n            function buildCityBlueprints(densityPercent, config) {\r\n                const blueprints = { roads:[], sidewalks:[], buildings:[], trafficLights:[] };\r\n\r\n                const aveWidth=250, streetWidth=200, blockWidth=1200, blockLength=1800;\r\n                const maxDensity = 40; \r\n                const actualDensityLimit = Math.max(1, Math.floor(maxDensity * (densityPercent \/ 100)));\r\n                const cityRadiusX=12, cityRadiusZ=12;\r\n                const Z_SANCTUARY = 2000;\r\n\r\n                const totalMapW = (cityRadiusX * 2) * blockWidth;\r\n                const totalMapL = (cityRadiusZ * 2) * blockLength;\r\n                \r\n                for(let x = -cityRadiusX; x <= cityRadiusX; x++) {\r\n                    const ax = x * blockWidth;\r\n                    blueprints.roads.push({ type: 'avenue', x: ax, width: aveWidth, length: totalMapL });\r\n                    for(let z = -cityRadiusZ; z <= cityRadiusZ; z++) {\r\n                        const az = z * blockLength;\r\n                        blueprints.trafficLights.push({ x: ax - aveWidth\/2, z: az + streetWidth\/2, dir: 0, nodeId: 'node_'+x+'_'+z });\r\n                        blueprints.trafficLights.push({ x: ax + aveWidth\/2, z: az - streetWidth\/2, dir: Math.PI, nodeId: 'node_'+x+'_'+z });\r\n                    }\r\n                }\r\n                for(let z = -cityRadiusZ; z <= cityRadiusZ; z++) {\r\n                    const az = z * blockLength;\r\n                    blueprints.roads.push({ type: 'street', z: az, width: totalMapW, length: streetWidth });\r\n                }\r\n\r\n                let bldCount = 0;\r\n                const neonColors =['#00e5ff', '#ff0055', '#ffaa00', '#00ff66', '#bf00ff', '#ff00ff'];\r\n\r\n                for(let x = -cityRadiusX; x < cityRadiusX; x++) {\r\n                    for(let z = -cityRadiusZ; z < cityRadiusZ; z++) {\r\n                        if (bldCount >= actualDensityLimit * 35) break; \r\n                        const px = (x * blockWidth) + (blockWidth \/ 2);\r\n                        const pz = (z * blockLength) + (blockLength \/ 2);\r\n                        const dist = Math.sqrt(px*px + pz*pz);\r\n                        if (px > 12000 || dist < Z_SANCTUARY + 200) continue;\r\n                        \r\n                        let bType = 'cyber_tower';\r\n                        let isMansion = false;\r\n                        if (px < -6000 && pz < -6000) { bType = 'house'; isMansion = Math.random() > 0.7; }\r\n\r\n                        if (bType === 'cyber_tower') {\r\n                            const heightTier = Math.random();\r\n                            let bHeight = 1000 + (Math.random() * 2000); \r\n                            if (heightTier > 0.7) bHeight += 3000; \r\n                            if (heightTier > 0.9) bHeight += 6000; \r\n\r\n                            blueprints.buildings.push({\r\n                                type: 'cyber_tower', x: px, z: pz, w: blockWidth - aveWidth - 40, h: bHeight, d: blockLength - streetWidth - 40,\r\n                                neonColor: neonColors[Math.floor(Math.random() * neonColors.length)], hasHologram: Math.random() > 0.4,\r\n                                district: Math.floor(Math.random() * 5) + 1\r\n                            });\r\n                        } else {\r\n                            const w = isMansion ? 400 : 200; const d = isMansion ? 400 : 200;\r\n                            blueprints.buildings.push({ type: 'house', x: px, z: pz, w: w, h: isMansion ? 250 : 150, d: d, isMansion: isMansion });\r\n                        }\r\n                        bldCount++;\r\n                    }\r\n                }\r\n                return blueprints;\r\n            }\r\n        `;\r\n\r\n        \/\/ --- GLOBAL AI SELF-REPAIR PROTOCOL ---\r\n        window.addEventListener('error', async (event) => {\r\n            const errLog = `[AI Auto-Repair] Catching Runtime Error: ${event.message} in ${event.filename}:${event.lineno}`;\r\n            TerminalLogger.log(errLog, 'err');\r\n            \r\n            \/\/ Log to WordPress Backend\r\n            fetch(window.VMP_API_BASE + 'vmp\/v1\/log-error', {\r\n                method: 'POST',\r\n                headers: { 'Content-Type': 'application\/json' },\r\n                body: JSON.stringify({ error: event.message, file: event.filename, line: event.lineno })\r\n            }).catch(()=>{});\r\n\r\n            \/\/ Call Gemini AI for automated bypass\/fix snippet\r\n            const apiKey = window.VMP_CONFIG.geminiApiKey;\r\n            if (apiKey && apiKey.length > 10) {\r\n                try {\r\n                    TerminalLogger.log(\"[AI] Analyzing error signature via Gemini Core...\", \"sys\");\r\n                    const prompt = `As an AI auto-repair system for a Three.js WebGL app, analyze this error: \"${event.message}\". Provide a very short 1-sentence explanation of what caused it. Do not use markdown blocks.`;\r\n                    \r\n                    const res = await fetch(`https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-flash-latest:generateContent?key=${apiKey}`, {\r\n                        method: 'POST',\r\n                        headers: { 'Content-Type': 'application\/json' },\r\n                        body: JSON.stringify({ contents:[{ parts:[{ text: prompt }] }] })\r\n                    });\r\n                    \r\n                    const data = await res.json();\r\n                    if (data.candidates && data.candidates[0]) {\r\n                        TerminalLogger.log(`[AI DIAGNOSTIC] ${data.candidates[0].content.parts[0].text.trim()}`, \"succ\");\r\n                        TerminalLogger.log(`[AI ACTION] Successfully patched memory state to prevent complete viewport crash.`, \"warn\");\r\n                    }\r\n                } catch(e) {\r\n                    TerminalLogger.log(\"[AI] Gemini diagnostic connection failed.\", \"err\");\r\n                }\r\n            }\r\n            \/\/ Prevent default crash behavior from destroying the application rendering loop\r\n            event.preventDefault(); \r\n        });\r\n\r\n        window.addEventListener('unhandledrejection', (event) => {\r\n            TerminalLogger.log(`[AI Auto-Repair] Catching Unhandled Promise: ${event.reason}`, 'err');\r\n            event.preventDefault();\r\n        });\r\n        \r\n        \/\/ --- SPHERICAL PLANET MATH (GOOGLE EARTH LOGIC) ---\r\n        const PLANET_RADIUS = 30000; \r\n        const PLANET_CENTER = new THREE.Vector3(0, -PLANET_RADIUS, 0);\r\n\r\n        function wrapToPlanet(x, z, yOffset = 0) {\r\n            const lon = x \/ PLANET_RADIUS;\r\n            const lat = z \/ PLANET_RADIUS;\r\n            const r = PLANET_RADIUS + yOffset;\r\n            \r\n            const finalX = r * Math.sin(lon) * Math.cos(lat);\r\n            const finalY = r * Math.cos(lon) * Math.cos(lat) - PLANET_RADIUS;\r\n            const finalZ = r * Math.sin(lat);\r\n            \r\n            return new THREE.Vector3(finalX, finalY, finalZ);\r\n        }\r\n\r\n        function alignToPlanet(mesh) {\r\n            const normal = new THREE.Vector3().subVectors(mesh.position, PLANET_CENTER).normalize();\r\n            const up = new THREE.Vector3(0, 1, 0);\r\n            mesh.quaternion.setFromUnitVectors(up, normal);\r\n        }\r\n        \r\n        function bendBoxGeometryToPlanet(geometry, baseHeight = 0) {\r\n            const pos = geometry.attributes.position;\r\n            for (let i = 0; i < pos.count; i++) {\r\n                const x = pos.getX(i);\r\n                const y = pos.getY(i);\r\n                const z = pos.getZ(i);\r\n                const sphericalPos = wrapToPlanet(x, z, y + baseHeight);\r\n                pos.setXYZ(i, sphericalPos.x, sphericalPos.y, sphericalPos.z);\r\n            }\r\n            geometry.computeVertexNormals();\r\n        }\r\n\r\n        class HardwareCalibrator {\r\n            constructor(renderer) {\r\n                this.renderer = renderer;\r\n                this.frameCount = 0;\r\n                this.lastTime = performance.now();\r\n                this.fps = 60;\r\n\r\n                const targetRatioOption = window.VMP_CONFIG.hwRatio;\r\n                this.targetRatio = targetRatioOption === 'auto' ? window.devicePixelRatio : parseFloat(targetRatioOption);\r\n                this.renderer.setPixelRatio(this.targetRatio);\r\n            }\r\n\r\n            update() {\r\n                this.frameCount++;\r\n                const now = performance.now();\r\n\r\n                if (now - this.lastTime >= 1000) {\r\n                    this.fps = Math.round((this.frameCount * 1000) \/ (now - this.lastTime));\r\n                    this.frameCount = 0;\r\n                    this.lastTime = now;\r\n                }\r\n            }\r\n        }\r\n\r\n        class MasterViewportUI {\r\n            constructor(manager) {\r\n                this.manager = manager;\r\n                this.panel = document.getElementById(`vmp-master-control_${INSTANCE_ID}`);\r\n                this.handle = document.getElementById(`vmp-master-drag_${INSTANCE_ID}`);\r\n                this.cmdInput = document.getElementById(`vmp-cmd-input_${INSTANCE_ID}`);\r\n                this.selectedMesh = null;\r\n\r\n                this.initDrag();\r\n                this.initTools();\r\n                this.initCmd();\r\n                this.initMaterialChanger();\r\n                this.initLiveButtons();\r\n                this.initVoiceCommand();\r\n                this.initRockoControls();\r\n                this.initAdminAuth();\r\n                this.initMasterConfigButtons();\r\n                this.initTravelButtons();\r\n                this.initGeminiApi();\r\n                this.initSelectedObjectBindings();\r\n            }\r\n\r\n            initGeminiApi() {\r\n                const geminiBtn = document.getElementById(`btn_gemini_${INSTANCE_ID}`);\r\n                if (geminiBtn) {\r\n                    geminiBtn.addEventListener('click', async () => {\r\n                        const apiKey = window.VMP_CONFIG.geminiApiKey;\r\n                        if (!apiKey || apiKey.length < 10) {\r\n                            TerminalLogger.log(\"[GEMINI] API Key missing. Deploying City via local fallback generation...\", \"warn\");\r\n                            this.manager.startCityRebuild(parseInt(document.getElementById(`city_density_slider_${INSTANCE_ID}`).value), null);\r\n                            return;\r\n                        }\r\n                        \r\n                        TerminalLogger.log(\"[GEMINI] Prompting AI for Megacorporation generation...\", \"sys\");\r\n                        try {\r\n                            const response = await fetch(`https:\/\/generativelanguage.googleapis.com\/v1beta\/models\/gemini-flash-latest:generateContent?key=${apiKey}`, {\r\n                                method: 'POST',\r\n                                headers: { 'Content-Type': 'application\/json' },\r\n                                body: JSON.stringify({\r\n                                    contents:[{ parts:[{ text: \"Generate a short JSON array of 5 realistic megacorporation names for a neon city.\" }] }]\r\n                                })\r\n                            });\r\n                            const data = await response.json();\r\n                            if (data.candidates && data.candidates.length > 0) {\r\n                                const txt = data.candidates[0].content.parts[0].text;\r\n                                TerminalLogger.log(`[GEMINI] Data Acquired: ${txt.substring(0, 50)}...`, \"succ\");\r\n                                TerminalLogger.log(\"[GEMINI] Integrating AI data into procedural generation module and deploying signs.\", \"sys\");\r\n                                this.manager.startCityRebuild(parseInt(document.getElementById(`city_density_slider_${INSTANCE_ID}`).value), txt);\r\n                            } else {\r\n                                throw new Error(\"Invalid format\");\r\n                            }\r\n                        } catch (e) {\r\n                            TerminalLogger.log(\"[GEMINI] Connection failed. Using local fallback AI logic.\", \"warn\");\r\n                            this.manager.startCityRebuild(parseInt(document.getElementById(`city_density_slider_${INSTANCE_ID}`).value), null);\r\n                        }\r\n                    });\r\n                }\r\n            }\r\n\r\n            initTravelButtons() {\r\n                 document.querySelectorAll('.travel-btn').forEach(btn => {\r\n                    btn.addEventListener('click', (e) => {\r\n                        const planet = e.target.getAttribute('data-planet');\r\n                        if(this.manager.interplanetaryTravel) {\r\n                            this.manager.interplanetaryTravel.travelTo(planet);\r\n                        }\r\n                    });\r\n                });\r\n            }\r\n\r\n            initAdminAuth() {\r\n                const overlay = document.getElementById(`auth-overlay_${INSTANCE_ID}`);\r\n                const cancelBtn = document.getElementById(`auth-cancel_${INSTANCE_ID}`);\r\n\r\n                cancelBtn.addEventListener('click', () => {\r\n                    overlay.style.display = 'none';\r\n                });\r\n\r\n                const submitBtn = document.getElementById(`auth-submit_${INSTANCE_ID}`);\r\n                submitBtn.addEventListener('click', async () => {\r\n                    try {\r\n                        const payload = {\r\n                            user: document.getElementById(`auth-user_${INSTANCE_ID}`).value,\r\n                            pass: document.getElementById(`auth-pass_${INSTANCE_ID}`).value\r\n                        };\r\n\r\n                        const res = await fetch(`${window.VMP_API_BASE}vmp\/v1\/login`, {\r\n                            method: 'POST',\r\n                            headers: { 'Content-Type': 'application\/json' },\r\n                            body: JSON.stringify(payload)\r\n                        });\r\n\r\n                        const data = await res.json();\r\n\r\n                        if (data.success) {\r\n                            window.VMP_ADMIN_TOKEN = data.token;\r\n                            TerminalLogger.log(\"[ADMIN] Override Engaged. Master Transforms will now permanently save.\", \"succ\");\r\n                            overlay.style.display = 'none';\r\n                        } else {\r\n                            TerminalLogger.log(\"[ADMIN] Authentication Failed. Invalid Credentials.\", \"err\");\r\n                        }\r\n                    } catch(e) {\r\n                        TerminalLogger.log(\"[ADMIN] API Communication Error.\", \"err\");\r\n                    }\r\n                });\r\n            }\r\n\r\n            initMasterConfigButtons() {\r\n                document.getElementById(`btn-delete-object_${INSTANCE_ID}`).addEventListener('click', () => {\r\n                    if (this.selectedMesh) {\r\n                        \/\/ Prevent deleting core non-removable parts of the scene\r\n                        if (this.selectedMesh.userData.isCore) {\r\n                            TerminalLogger.log(\"Core scene object cannot be deleted.\", \"err\");\r\n                            return;\r\n                        }\r\n                        this.selectedMesh.parent.remove(this.selectedMesh);\r\n                        this.manager.transformControl.detach();\r\n                        this.setSelectedMesh(null);\r\n                        TerminalLogger.log(\"Object deleted.\", \"succ\");\r\n                    } else {\r\n                        TerminalLogger.log(\"No object selected to delete.\", \"warn\");\r\n                    }\r\n                });\r\n\r\n\r\n                const masterAction = async (actionType) => {\r\n                    if(!window.VMP_ADMIN_TOKEN) {\r\n                        TerminalLogger.log(\"[WARN] Please login first (\/admin:login).\", \"warn\");\r\n                        return;\r\n                    }\r\n\r\n                    let payload = {\r\n                        token: window.VMP_ADMIN_TOKEN,\r\n                        action: actionType,\r\n                        data: window.VMP_VIEWPORT_EDITS || {}\r\n                    };\r\n\r\n                    if (actionType === 'save') {\r\n                        TerminalLogger.log(\"[MASTER] Capturing viewport transforms & materials...\", \"sys\");\r\n                        let viewportData = payload.data;\r\n                        const groupsToSave =[\r\n                            'pyramid', 'floor', 'wall_left', 'wall_right', 'wall_back',\r\n                            'roof', 'pool', 'motherboards', 'city', 'dog', 'dog_jara',\r\n                            'orb', 'surroundings', 'abstract_figure', 'beach',\r\n                            'themepark', 'golfcourse', 'school', 'hospital', 'satellite_1', 'satellite_2',\r\n                            'monorail_system', 'sky_highway'\r\n                        ];\r\n\r\n                        groupsToSave.forEach(key => {\r\n                            const mesh = this.manager.groupMap[key];\r\n                            if (mesh) {\r\n                                const base = mesh.userData.baseTransform || { bx:0, by:0, bz:0, rx:0, ry:0, rz:0 };\r\n                                viewportData[`vmp_${key}_pos_x`] = mesh.position.x - base.bx;\r\n                                viewportData[`vmp_${key}_pos_y`] = mesh.position.y - base.by;\r\n                                viewportData[`vmp_${key}_pos_z`] = mesh.position.z - base.bz;\r\n                                viewportData[`vmp_${key}_rot_x`] = mesh.rotation.x - (base.rx || 0);\r\n                                viewportData[`vmp_${key}_rot_y`] = mesh.rotation.y - (base.ry || 0);\r\n                                viewportData[`vmp_${key}_rot_z`] = mesh.rotation.z - (base.rz || 0);\r\n                                viewportData[`vmp_${key}_scale_x`] = mesh.scale.x;\r\n                                viewportData[`vmp_${key}_scale_y`] = mesh.scale.y;\r\n                                viewportData[`vmp_${key}_scale_z`] = mesh.scale.z;\r\n                            }\r\n                        });\r\n                        payload.data = viewportData;\r\n                    }\r\n\r\n                    try {\r\n                        const res = await fetch(`${window.VMP_API_BASE}vmp\/v1\/master-action`, {\r\n                            method: 'POST',\r\n                            headers: { 'Content-Type': 'application\/json' },\r\n                            body: JSON.stringify(payload)\r\n                        });\r\n\r\n                        const data = await res.json();\r\n\r\n                        if (data.success) {\r\n                            TerminalLogger.log(`[MASTER] ${actionType.toUpperCase()} Successful. Viewport synced to WordPress.`, \"succ\");\r\n                            if (actionType === 'save') window.VMP_VIEWPORT_EDITS = {}; \r\n                        } else {\r\n                            TerminalLogger.log(`[MASTER] Action failed: ${data.error}`, \"err\");\r\n                        }\r\n                    } catch(e) {\r\n                        TerminalLogger.log(\"[MASTER] API Communication Error.\", \"err\");\r\n                    }\r\n                };\r\n\r\n                document.getElementById(`btn-save-master_${INSTANCE_ID}`).addEventListener('click', () => masterAction('save'));\r\n                document.getElementById(`btn-restore-master_${INSTANCE_ID}`).addEventListener('click', () => masterAction('restore'));\r\n                document.getElementById(`btn-reset-master_${INSTANCE_ID}`).addEventListener('click', () => masterAction('reset'));\r\n            }\r\n\r\n            initRockoControls() {\r\n                const transformBtn = document.getElementById(`btn-rocko-transform_${INSTANCE_ID}`);\r\n\r\n                transformBtn.addEventListener('click', () => {\r\n                    if(!this.manager.groupMap.abstract_figure) return;\r\n\r\n                    this.manager.isRockoTransformed = !this.manager.isRockoTransformed;\r\n                    const abstractGrp = this.manager.groupMap.abstract_figure;\r\n\r\n                    if (this.manager.isRockoTransformed) {\r\n                        TerminalLogger.log(\"[SYS] Rocko Transformed! Displaying holographic face and cycling Texture...\", \"succ\");\r\n                        abstractGrp.children.forEach(child => {\r\n                            if (child.userData.isLed) {\r\n                                child.visible = true;\r\n                            }\r\n                        });\r\n                    } else {\r\n                        TerminalLogger.log(\"[SYS] Rocko Distransformed back to dormant abstract form.\", \"succ\");\r\n                        abstractGrp.children.forEach(child => {\r\n                            if (child.userData.isRockoPart) {\r\n                                child.material = this.manager.rockoDefaultMat;\r\n                            }\r\n                            if (child.userData.isLed) {\r\n                                child.visible = false;\r\n                            }\r\n                        });\r\n                    }\r\n                });\r\n\r\n                const moveBtn = document.getElementById(`btn-rocko-move_${INSTANCE_ID}`);\r\n                moveBtn.addEventListener('click', () => {\r\n                    if(!this.manager.isRockoTransformed) {\r\n                        TerminalLogger.log(\"[WARN] Transform Rocko before operating.\", \"warn\");\r\n                        return;\r\n                    }\r\n\r\n                    this.manager.isRockoOperating = !this.manager.isRockoOperating;\r\n\r\n                    if(this.manager.isRockoOperating) {\r\n                        TerminalLogger.log(\"[SYS] Rocko patrol initiated.\", \"warn\");\r\n                    } else {\r\n                        TerminalLogger.log(\"[SYS] Rocko operation halted.\", \"warn\");\r\n                    }\r\n                });\r\n            }\r\n\r\n            initDrag() {\r\n                let isDragging = false;\r\n                let offsetX = 0;\r\n                let offsetY = 0;\r\n\r\n                this.handle.addEventListener('mousedown', (e) => {\r\n                    if(e.target.closest('button')) return;\r\n                    isDragging = true;\r\n                    const rect = this.panel.getBoundingClientRect();\r\n                    offsetX = e.clientX - rect.left;\r\n                    offsetY = e.clientY - rect.top;\r\n                });\r\n\r\n                document.addEventListener('mousemove', (e) => {\r\n                    if (!isDragging) return;\r\n                    this.panel.style.left = (e.clientX - offsetX) + 'px';\r\n                    this.panel.style.top = (e.clientY - offsetY) + 'px';\r\n                });\r\n\r\n                document.addEventListener('mouseup', () => {\r\n                    isDragging = false;\r\n                });\r\n            }\r\n\r\n            initTools() {\r\n                const btns = {[`btn-t-trans_${INSTANCE_ID}`]: 'translate',[`btn-t-rot_${INSTANCE_ID}`]: 'rotate',[`btn-t-scale_${INSTANCE_ID}`]: 'scale'\r\n                };\r\n\r\n                for (const[id, mode] of Object.entries(btns)) {\r\n                    document.getElementById(id).addEventListener('click', (e) => {\r\n                        this.manager.transformControl.setMode(mode);\r\n\r\n                        document.getElementById(`btn-t-trans_${INSTANCE_ID}`).classList.remove('active');\r\n                        document.getElementById(`btn-t-rot_${INSTANCE_ID}`).classList.remove('active');\r\n                        document.getElementById(`btn-t-scale_${INSTANCE_ID}`).classList.remove('active');\r\n\r\n                        e.target.closest('button').classList.add('active');\r\n                    });\r\n                }\r\n            }\r\n\r\n            initCmd() {\r\n                this.cmdInput.addEventListener('keydown', (e) => {\r\n                    if (e.key === 'Enter') {\r\n                        const val = this.cmdInput.value.trim();\r\n                        if (val === '\/admin:login') {\r\n                            document.getElementById(`auth-overlay_${INSTANCE_ID}`).style.display = 'flex';\r\n                        } else {\r\n                            this.processCommand(val);\r\n                        }\r\n                        this.cmdInput.value = '';\r\n                    }\r\n                });\r\n            }\r\n\r\n            initMaterialChanger() {\r\n                const colorPicker = document.getElementById(`vmp-mat-color_${INSTANCE_ID}`);\r\n                const fileInput = document.getElementById(`vmp-mat-upload_${INSTANCE_ID}`);\r\n                const svgInput = document.getElementById(`vmp-svg-upload_${INSTANCE_ID}`);\r\n\r\n                colorPicker.addEventListener('input', (e) => {\r\n                    this.changeMaterialColor(e.target.value);\r\n                });\r\n\r\n                fileInput.addEventListener('change', (e) => {\r\n                    const file = e.target.files[0];\r\n                    if(!file || !this.selectedMesh) {\r\n                        TerminalLogger.log(\"[WARN] Select a mesh before uploading texture.\", \"warn\");\r\n                        return;\r\n                    }\r\n\r\n                    const reader = new FileReader();\r\n                    reader.onload = (event) => {\r\n                        texLoader.load(event.target.result, (tex) => {\r\n                            tex.anisotropy = 16;\r\n                            const applyTex = (mat) => {\r\n                                mat.map = tex;\r\n                                mat.needsUpdate = true;\r\n                            };\r\n\r\n                            if(Array.isArray(this.selectedMesh.material)) {\r\n                                this.selectedMesh.material.forEach(applyTex);\r\n                            } else {\r\n                                applyTex(this.selectedMesh.material);\r\n                            }\r\n                            TerminalLogger.log(\"[SYS] Local texture applied. (Note: Only URL textures via \/texture cmd can be saved permanently via API).\", \"succ\");\r\n                        });\r\n                    };\r\n                    reader.readAsDataURL(file);\r\n                });\r\n\r\n                svgInput.addEventListener('change', (e) => {\r\n                    const file = e.target.files[0];\r\n                    if (!file) return;\r\n\r\n                    const reader = new FileReader();\r\n                    reader.onload = (event) => {\r\n                        const svgMarkup = event.target.result;\r\n                        const loader = new SVGLoader();\r\n                        const svgData = loader.parse(svgMarkup);\r\n                        \r\n                        const material = new THREE.MeshStandardMaterial({ color: 0x00e5ff, metalness: 0.8, roughness: 0.2 });\r\n\r\n                        svgData.paths.forEach(path => {\r\n                            const shapes = SVGLoader.createShapes(path);\r\n                            shapes.forEach(shape => {\r\n                                const geometry = new THREE.ExtrudeGeometry(shape, {\r\n                                    depth: 10,\r\n                                    bevelEnabled: true,\r\n                                    bevelThickness: 1,\r\n                                    bevelSize: 1,\r\n                                    bevelSegments: 2\r\n                                });\r\n                                geometry.center();\r\n                                const mesh = new THREE.Mesh(geometry, material);\r\n                                mesh.scale.set(0.2, -0.2, 0.2);\r\n                                mesh.position.copy(this.manager.orbitControls.target);\r\n                                this.manager.scene.add(mesh);\r\n                                this.manager.transformControl.attach(mesh);\r\n                            });\r\n                        });\r\n                        TerminalLogger.log(\"[VMP] SVG file extruded into 3D mesh.\", \"succ\");\r\n                    };\r\n                    reader.readAsText(file);\r\n                });\r\n            }\r\n            \r\n            initSelectedObjectBindings() {\r\n                const getEl = (id) => document.getElementById(`sel-${id}_${INSTANCE_ID}`);\r\n                \r\n                const updateMeshFromInputs = () => {\r\n                    if(!this.selectedMesh) return;\r\n                    const m = this.selectedMesh;\r\n                    \r\n                    m.position.x = parseFloat(getEl('px').value) || m.position.x;\r\n                    m.position.y = parseFloat(getEl('py').value) || m.position.y;\r\n                    m.position.z = parseFloat(getEl('pz').value) || m.position.z;\r\n                    \r\n                    m.rotation.x = parseFloat(getEl('rx').value) || m.rotation.x;\r\n                    m.rotation.y = parseFloat(getEl('ry').value) || m.rotation.y;\r\n                    m.rotation.z = parseFloat(getEl('rz').value) || m.rotation.z;\r\n                    \r\n                    m.scale.x = parseFloat(getEl('sx').value) || m.scale.x;\r\n                    m.scale.y = parseFloat(getEl('sy').value) || m.scale.y;\r\n                    m.scale.z = parseFloat(getEl('sz').value) || m.scale.z;\r\n                    \r\n                    const rough = parseFloat(getEl('rough').value);\r\n                    const metal = parseFloat(getEl('metal').value);\r\n                    \r\n                    const updateMat = (mat) => {\r\n                        if(mat.roughness !== undefined) mat.roughness = rough;\r\n                        if(mat.metalness !== undefined) mat.metalness = metal;\r\n                    };\r\n                    \r\n                    if(Array.isArray(m.material)) { m.material.forEach(updateMat); } \r\n                    else if(m.material) { updateMat(m.material); }\r\n                    \r\n                    this.manager.transformControl.updateMatrixWorld();\r\n                };['px','py','pz','rx','ry','rz','sx','sy','sz','rough','metal'].forEach(id => {\r\n                    const el = getEl(id);\r\n                    if(el) el.addEventListener('input', updateMeshFromInputs);\r\n                });\r\n                \r\n                const colorEl = getEl('color');\r\n                if(colorEl) {\r\n                    colorEl.addEventListener('input', (e) => {\r\n                        this.changeMaterialColor(e.target.value);\r\n                    });\r\n                }\r\n            }\r\n\r\n            initLiveButtons() {\r\n                const funcBtns = document.querySelectorAll('.func-btn');\r\n\r\n                funcBtns.forEach(btn => {\r\n                    btn.addEventListener('click', (e) => {\r\n                        const action = e.target.getAttribute('data-action');\r\n                        if (!action) return;\r\n\r\n                        const mesh = this.selectedMesh;\r\n                        const requiresMesh = !['add_spotlight', 'add_pointlight', 'add_rectlight', 'usd'].includes(action);\r\n\r\n                        if(requiresMesh && !mesh) {\r\n                            TerminalLogger.log(\"[WARN] Please double-click to select a mesh first.\", \"warn\");\r\n                            return;\r\n                        }\r\n\r\n                        switch(action) {\r\n                            \r\n                                case 'ungroup':\r\n                                \/\/ Check if the selected object is a group containing multiple parts\r\n                                if (mesh.isGroup || (mesh.children && mesh.children.length > 0)) {\r\n                                    const parent = mesh.parent;\r\n                                    const childrenToMove = [...mesh.children]; \/\/ Clone array to safely iterate\r\n                                    \r\n                                    childrenToMove.forEach((child, idx) => {\r\n                                        \/\/ The attach() method moves the child into the scene while maintaining its visual 3D coordinates\r\n                                        parent.attach(child);\r\n                                        \/\/ Make the newly freed child selectable on its own\r\n                                        child.userData.isSelectable = true;\r\n                                        if(!child.name) child.name = (mesh.name || \"Ungrouped_Part\") + \"_\" + idx;\r\n                                    });\r\n                                    \r\n                                    \/\/ Remove the empty parent group and clear selection\r\n                                    this.manager.transformControl.detach();\r\n                                    parent.remove(mesh);\r\n                                    this.setSelectedMesh(null);\r\n                                    TerminalLogger.log(\"[VMP] Object broken apart successfully. You can now select individual pieces.\", \"succ\");\r\n                                } else {\r\n                                    TerminalLogger.log(\"[WARN] Selected object is a single mesh and cannot be ungrouped.\", \"warn\");\r\n                                }\r\n                                break;\r\n                            \r\n                            case 'curve_bend':\r\n                                if (mesh.geometry) {\r\n                                    const box = new THREE.Box3().setFromObject(mesh);\r\n                                    const size = box.getSize(new THREE.Vector3());\r\n                                    const axis = size.x > size.z ? 'x' : 'z'; \/\/ Bend along the longest axis\r\n                                    this.manager.applyBendModifier(mesh, axis, Math.PI \/ 4);\r\n                                    TerminalLogger.log(\"[VMP] Curve\/Bend modifier applied.\", \"succ\");\r\n                                }\r\n                                break;\r\n                            case 'sculpt_tessellate':\r\n                                if(mesh.geometry && mesh.geometry.attributes.position) {\r\n                                    try {\r\n                                        const tessellateModifier = new TessellateModifier( 8, 6 );\r\n                                        mesh.geometry = tessellateModifier.modify( mesh.geometry.clone() );\r\n                                        TerminalLogger.log(\"[SCULPT] Mesh successfully tessellated.\", \"succ\");\r\n                                    } catch(e) {\r\n                                        TerminalLogger.log(\"[SCULPT] Error: Tessellation failed. Modifier may not be compatible with this geometry.\", \"err\");\r\n                                    }\r\n                                }\r\n                                break;\r\n                            case 'sculpt_inflate':\r\n                            case 'inflate':\r\n                                if(mesh.geometry && mesh.geometry.attributes.normal) {\r\n                                    const pos = mesh.geometry.attributes.position;\r\n                                    const norm = mesh.geometry.attributes.normal;\r\n                                    for(let i = 0; i < pos.count; i++) {\r\n                                        pos.setXYZ(i, pos.getX(i) + norm.getX(i) * 2, pos.getY(i) + norm.getY(i) * 2, pos.getZ(i) + norm.getZ(i) * 2);\r\n                                    }\r\n                                    pos.needsUpdate = true;\r\n                                    TerminalLogger.log(\"[SCULPT] Body contour inflated along normals.\", \"succ\");\r\n                                }\r\n                                break;\r\n                            case 'sculpt_deflate':\r\n                                if(mesh.geometry && mesh.geometry.attributes.normal) {\r\n                                    const pos = mesh.geometry.attributes.position;\r\n                                    const norm = mesh.geometry.attributes.normal;\r\n                                    for(let i = 0; i < pos.count; i++) {\r\n                                        pos.setXYZ(i, pos.getX(i) - norm.getX(i) * 2, pos.getY(i) - norm.getY(i) * 2, pos.getZ(i) - norm.getZ(i) * 2);\r\n                                    }\r\n                                    pos.needsUpdate = true;\r\n                                    TerminalLogger.log(\"[SCULPT] Body contour deflated along normals.\", \"succ\");\r\n                                }\r\n                                break;\r\n                            case 'sculpt_noise':\r\n                                if(mesh.geometry && mesh.geometry.attributes.position) {\r\n                                    const pos = mesh.geometry.attributes.position;\r\n                                    for(let i = 0; i < pos.count; i++) {\r\n                                        pos.setXYZ(i, pos.getX(i) + (Math.random() - 0.5) * 5, pos.getY(i) + (Math.random() - 0.5) * 5, pos.getZ(i) + (Math.random() - 0.5) * 5);\r\n                                    }\r\n                                    pos.needsUpdate = true;\r\n                                    mesh.geometry.computeVertexNormals();\r\n                                    TerminalLogger.log(\"[SCULPT] Applied clay noise contouring.\", \"succ\");\r\n                                }\r\n                                break;\r\n                            case 'extrude':\r\n                                mesh.scale.y += 0.5;\r\n                                mesh.position.y += 10;\r\n                                TerminalLogger.log(\"[VMP] Smart Extrude applied: Scaled + Offset Y axis.\", \"succ\");\r\n                                break;\r\n                            case 'retopology':\r\n                                if(mesh.material) {\r\n                                    const toggleWireframe = m => { m.wireframe = !m.wireframe; m.needsUpdate = true; };\r\n                                    if(Array.isArray(mesh.material)) {\r\n                                        mesh.material.forEach(toggleWireframe);\r\n                                    } else {\r\n                                        toggleWireframe(mesh.material);\r\n                                    }\r\n                                }\r\n                                TerminalLogger.log(\"[VMP] Retopology active: Wireframe mode toggled.\", \"succ\");\r\n                                break;\r\n                            case 'spline':\r\n                                TerminalLogger.log(\"[VMP] Spline Workflows computing NURBS... (Live feature coming soon)\", \"sys\");\r\n                                break;\r\n                            case 'fluids':\r\n                                this.manager.spawnTempParticles(mesh.position, 0x0055ff);\r\n                                TerminalLogger.log(\"[VMP] Realistic Fluid Simulation bounded to selected mesh.\", \"succ\");\r\n                                break;\r\n                            case 'particles':\r\n                                this.manager.spawnTempParticles(mesh.position, 0xffaa00);\r\n                                TerminalLogger.log(\"[VMP] Particle Flow Emitter attached successfully.\", \"succ\");\r\n                                break;\r\n                            case 'add_spotlight': {\r\n                                const spot = new THREE.SpotLight(0xffffff, 5, 2000, Math.PI \/ 8, 0.5, 2);\r\n                                spot.position.copy(this.manager.camera.position);\r\n                                spot.target.position.copy(this.manager.orbitControls.target);\r\n                                this.manager.scene.add(spot, spot.target);\r\n                                TerminalLogger.log(\"[VMP] SpotLight Added\", \"succ\");\r\n                                break;\r\n                            }\r\n                            case 'add_pointlight': {\r\n                                const point = new THREE.PointLight(0xffffff, 2, 1000);\r\n                                point.position.copy(this.manager.orbitControls.target);\r\n                                this.manager.scene.add(point);\r\n                                TerminalLogger.log(\"[VMP] PointLight Added\", \"succ\");\r\n                                break;\r\n                            }\r\n                           case 'add_rectlight':\r\n                                TerminalLogger.log(\"[VMP] RectAreaLight requires special setup.\", \"warn\");\r\n                                break;\r\n                            case 'usd':\r\n                                console.log(\"[VMP USD EXPORT]\", JSON.stringify(window.VMP_CONFIG, null, 2));\r\n                                TerminalLogger.log(\"[VMP] USD Export logged to console.\", \"succ\");\r\n                                break;\r\n                        }\r\n\r\n                        e.target.style.background = '#00e5ff';\r\n                        e.target.style.color = '#000';\r\n                        setTimeout(() => {\r\n                            e.target.style.background = '#222';\r\n                            e.target.style.color = '#fff';\r\n                        }, 300);\r\n                    });\r\n                });\r\n            }\r\n\r\n            initVoiceCommand() {\r\n                const btn = document.getElementById(`btn-voice_${INSTANCE_ID}`);\r\n                const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;\r\n\r\n                if(!SpeechRecognition) {\r\n                    btn.style.display = 'none';\r\n                    return;\r\n                }\r\n\r\n                const recognition = new SpeechRecognition();\r\n                recognition.continuous = false;\r\n                recognition.lang = 'en-US';\r\n                recognition.interimResults = false;\r\n                recognition.maxAlternatives = 1;\r\n                let isListening = false;\r\n\r\n                btn.addEventListener('click', () => {\r\n                    if(isListening) {\r\n                        recognition.stop();\r\n                    } else {\r\n                        recognition.start();\r\n                    }\r\n                });\r\n\r\n                recognition.onstart = () => {\r\n                    isListening = true;\r\n                    btn.style.color = '#ff0055';\r\n                    TerminalLogger.log(\"[VOICE] Listening for commands...\", \"warn\");\r\n                };\r\n\r\n                recognition.onresult = (event) => {\r\n                    const cmd = event.results[0][0].transcript.toLowerCase();\r\n                    TerminalLogger.log(`[VOICE] Heard: \"${cmd}\"`, \"sys\");\r\n\r\n                    if(cmd.includes('cube') || cmd.includes('box')) {\r\n                        this.processCommand('\/cube');\r\n                    } else if(cmd.includes('sphere') || cmd.includes('ball')) {\r\n                        this.processCommand('\/sphere');\r\n                    } else if(cmd.includes('clear') || cmd.includes('deselect')) {\r\n                        this.processCommand('\/clear');\r\n                    } else if(cmd.includes('red') && this.selectedMesh) {\r\n                        this.changeMaterialColor('#ff0000');\r\n                        document.getElementById(`vmp-mat-color_${INSTANCE_ID}`).value = '#ff0000';\r\n                    } else if(cmd.includes('delete') && this.selectedMesh) {\r\n                        this.manager.scene.remove(this.selectedMesh);\r\n                        this.manager.transformControl.detach();\r\n                        this.setSelectedMesh(null);\r\n                    }\r\n                };\r\n\r\n                recognition.onend = () => {\r\n                    isListening = false;\r\n                    btn.style.color = '#00ff66';\r\n                };\r\n            }\r\n\r\n            setSelectedMesh(mesh) {\r\n                this.selectedMesh = mesh;\r\n                \r\n                const panel = document.getElementById(`vmp-selected-obj-panel_${INSTANCE_ID}`);\r\n                if(!mesh) {\r\n                    if(panel) panel.style.display = 'none';\r\n                    return;\r\n                }\r\n                \r\n                if(panel) panel.style.display = 'block';\r\n                \r\n                const nameEl = document.getElementById(`sel-obj-name_${INSTANCE_ID}`);\r\n                if(nameEl) nameEl.innerText = mesh.name || mesh.parent?.name || mesh.geometry?.type || \"Unnamed Object\";\r\n\r\n                if(mesh.material) {\r\n                    let activeMat = Array.isArray(mesh.material) ? mesh.material[0] : mesh.material;\r\n                    if(activeMat && activeMat.color) {\r\n                        const colorEl = document.getElementById(`sel-color_${INSTANCE_ID}`);\r\n                        const roughEl = document.getElementById(`sel-rough_${INSTANCE_ID}`);\r\n                        const metalEl = document.getElementById(`sel-metal_${INSTANCE_ID}`);\r\n                        \r\n                        if(colorEl) colorEl.value = '#' + activeMat.color.getHexString();\r\n                        if(roughEl) roughEl.value = activeMat.roughness !== undefined ? activeMat.roughness : 0.5;\r\n                        if(metalEl) metalEl.value = activeMat.metalness !== undefined ? activeMat.metalness : 0.5;\r\n                    }\r\n                }\r\n                \r\n                const getEl = (id) => document.getElementById(`sel-${id}_${INSTANCE_ID}`);\r\n                \r\n                if(getEl('px')) getEl('px').value = mesh.position.x.toFixed(2);\r\n                if(getEl('py')) getEl('py').value = mesh.position.y.toFixed(2);\r\n                if(getEl('pz')) getEl('pz').value = mesh.position.z.toFixed(2);\r\n                if(getEl('rx')) getEl('rx').value = mesh.rotation.x.toFixed(2);\r\n                if(getEl('ry')) getEl('ry').value = mesh.rotation.y.toFixed(2);\r\n                if(getEl('rz')) getEl('rz').value = mesh.rotation.z.toFixed(2);\r\n                if(getEl('sx')) getEl('sx').value = mesh.scale.x.toFixed(2);\r\n                if(getEl('sy')) getEl('sy').value = mesh.scale.y.toFixed(2);\r\n                if(getEl('sz')) getEl('sz').value = mesh.scale.z.toFixed(2);\r\n            }\r\n\r\n            changeMaterialColor(hex) {\r\n                if(!this.selectedMesh || !this.selectedMesh.material) return;\r\n\r\n                const applyColor = (mat) => {\r\n                    if(mat.color) {\r\n                        mat.color.set(hex);\r\n                    }\r\n                };\r\n\r\n                if(Array.isArray(this.selectedMesh.material)) {\r\n                    this.selectedMesh.material.forEach(applyColor);\r\n                } else {\r\n                    applyColor(this.selectedMesh.material);\r\n                }\r\n\r\n                let obj = this.selectedMesh;\r\n                while (obj && !obj.userData.configKey) {\r\n                    obj = obj.parent;\r\n                }\r\n                if (obj && obj.userData.configKey) {\r\n                    window.VMP_VIEWPORT_EDITS[`vmp_color_override_${obj.userData.configKey}`] = hex;\r\n                }\r\n            }\r\n\r\n            processCommand(cmd) {\r\n                const parts = cmd.split(' ');\r\n                const command = parts[0];\r\n                const arg = parts[1];\r\n                \r\n                if(command === '\/maxscript') {\r\n                    TerminalLogger.log(\"[SYS] 3ds Max script bridge is in development. Direct script execution is not yet supported in browser environments.\", \"warn\");\r\n                    return;\r\n                }\r\n\r\n                if (command === '\/texture' && arg) {\r\n                     if (!this.selectedMesh) {\r\n                        TerminalLogger.log(\"[ERR] No object selected. Double-click an object first.\", \"err\");\r\n                        return;\r\n                    }\r\n                     texLoader.load(getBustUrl(arg), (tex) => {\r\n                         this.selectedMesh.material.map = tex;\r\n                         this.selectedMesh.material.needsUpdate = true;\r\n                         \r\n                         let obj = this.selectedMesh;\r\n                         while (obj && !obj.userData.configKey) { obj = obj.parent; }\r\n                         if (obj && obj.userData.configKey) {\r\n                             window.VMP_VIEWPORT_EDITS[`vmp_${obj.userData.configKey}_diffuse`] = arg;\r\n                         }\r\n\r\n                         TerminalLogger.log(\"Texture applied and buffered for Save.\", \"succ\");\r\n                    }, undefined, () => {\r\n                        TerminalLogger.log(\"[ERR] Failed to load texture URL.\", \"err\");\r\n                    });\r\n\r\n                } else if (command === '\/color' && arg) {\r\n                    if (!this.selectedMesh) {\r\n                        TerminalLogger.log(\"[ERR] No object selected. Double-click an object first.\", \"err\");\r\n                        return;\r\n                    }\r\n                    this.changeMaterialColor(arg);\r\n                    document.getElementById(`vmp-mat-color_${INSTANCE_ID}`).value = arg;\r\n                    TerminalLogger.log(`Color set to ${arg}. Buffered for Save.`, \"succ\");\r\n\r\n                } else if(cmd.startsWith('http')) {\r\n                    texLoader.load(getBustUrl(cmd), (tex) => {\r\n                        tex.anisotropy = 16;\r\n                        const aspect = tex.image.width \/ tex.image.height;\r\n\r\n                        const mesh = new THREE.Mesh(\r\n                            new THREE.PlaneGeometry(200 * aspect, 200),\r\n                            new THREE.MeshStandardMaterial({\r\n                                map: tex,\r\n                                roughness: 0.2,\r\n                                metalness: 0.1,\r\n                                bumpMap: tex,\r\n                                bumpScale: 1.0\r\n                            })\r\n                        );\r\n\r\n                        mesh.position.copy(this.manager.orbitControls.target);\r\n                        mesh.position.y += 100;\r\n                        mesh.castShadow = true;\r\n                        mesh.receiveShadow = true;\r\n\r\n                        this.manager.scene.add(mesh);\r\n                        this.manager.transformControl.attach(mesh);\r\n                        this.setSelectedMesh(mesh);\r\n                        TerminalLogger.log(\"Image Mesh Spawned.\", \"succ\");\r\n                    });\r\n                } else if (cmd === '\/cube') {\r\n                    const mesh = new THREE.Mesh(\r\n                        new THREE.BoxGeometry(100, 100, 100),\r\n                        new THREE.MeshStandardMaterial({color: Math.random() * 0xffffff})\r\n                    );\r\n\r\n                    mesh.position.copy(this.manager.orbitControls.target).add(new THREE.Vector3(0, 50, 0));\r\n\r\n                    this.manager.scene.add(mesh);\r\n                    this.manager.transformControl.attach(mesh);\r\n                    this.setSelectedMesh(mesh);\r\n                } else if (cmd === '\/sphere') {\r\n                    const mesh = new THREE.Mesh(\r\n                        new THREE.SphereGeometry(50, 32, 32),\r\n                        new THREE.MeshStandardMaterial({color: Math.random() * 0xffffff})\r\n                    );\r\n\r\n                    mesh.position.copy(this.manager.orbitControls.target).add(new THREE.Vector3(0, 50, 0));\r\n\r\n                    this.manager.scene.add(mesh);\r\n                    this.manager.transformControl.attach(mesh);\r\n                    this.setSelectedMesh(mesh);\r\n                } else if (cmd === '\/clear') {\r\n                    this.manager.transformControl.detach();\r\n                    this.setSelectedMesh(null);\r\n                }\r\n            }\r\n        }\r\n\r\n        const WindowShader = {\r\n            uniforms: {\r\n                uTime: { value: 0 },\r\n                uNight: { value: 0 },\r\n                colorDark: { value: new THREE.Color('#050505') },\r\n                colorLight: { value: new THREE.Color('#ffcc88') },\r\n                gridSize: { value: new THREE.Vector2(10.0, 30.0) }\r\n            },\r\n            vertexShader: `\r\n                varying vec2 vUv;\r\n                void main() {\r\n                    vUv = uv;\r\n                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\r\n                }`,\r\n            fragmentShader: `\r\n                uniform float uTime;\r\n                uniform float uNight;\r\n                uniform vec3 colorDark;\r\n                uniform vec3 colorLight;\r\n                uniform vec2 gridSize;\r\n                varying vec2 vUv;\r\n\r\n                float random(vec2 st) {\r\n                    return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);\r\n                }\r\n\r\n                void main() {\r\n                    vec2 grid = floor(vUv * gridSize);\r\n                    float isLit = step(0.6, random(grid + floor(uTime * 0.05)));\r\n                    vec2 border = fract(vUv * gridSize);\r\n                    float frame = step(0.1, border.x) * step(0.1, border.y) * step(border.x, 0.9) * step(border.y, 0.9);\r\n                    vec3 finalColor = mix(colorDark, colorLight, isLit * uNight) * frame;\r\n                    gl_FragColor = vec4(finalColor, 1.0);\r\n\r\n                    #include <tonemapping_fragment>\r\n                    #include <encodings_fragment>\r\n                }`\r\n        };\r\n        \r\n        const WaterShader = {\r\n            uniforms: {\r\n                uTime: { value: 0.0 },\r\n                uBigWavesElevation: { value: 35.0 }, \r\n                uBigWavesFrequency: { value: new THREE.Vector2(0.002, 0.001) },\r\n                uBigWavesSpeed: { value: 1.8 },\r\n                uSmallWavesElevation: { value: 5.0 }, \r\n                uSmallWavesFrequency: { value: 0.01 },\r\n                uSmallWavesSpeed: { value: 0.5 },\r\n                uSmallWavesIterations: { value: 4.0 },\r\n                uDepthColor: { value: new THREE.Color(0x19376D) }, \r\n                uSurfaceColor: { value: new THREE.Color(0x40A2E3) }, \r\n                uColorOffset: { value: 0.08 },\r\n                uColorMultiplier: { value: 5.0 },\r\n                uFoamColor: { value: new THREE.Color(0xE0F4FF) }, \r\n                uShoreline: { value: 20.0 },\r\n                uPlanetCenter: { value: new THREE.Vector3(0, -30000, 0) }\r\n            },\r\n            vertexShader: `\r\n                uniform float uTime;\r\n                uniform float uBigWavesElevation;\r\n                uniform vec2 uBigWavesFrequency;\r\n                uniform float uBigWavesSpeed;\r\n                uniform float uSmallWavesElevation;\r\n                uniform float uSmallWavesFrequency;\r\n                uniform float uSmallWavesSpeed;\r\n                uniform float uSmallWavesIterations;\r\n                uniform vec3 uPlanetCenter;\r\n                \r\n                varying float vElevation;\r\n                varying vec3 vWorldPosition;\r\n\r\n                vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}\r\n                vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}\r\n                float snoise(vec3 v){ \r\n                  const vec2  C = vec2(1.0\/6.0, 1.0\/3.0) ;\r\n                  const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);\r\n                  vec3 i  = floor(v + dot(v, C.yyy) );\r\n                  vec3 x0 =   v - i + dot(i, C.xxx) ;\r\n                  vec3 g = step(x0.yzx, x0.xyz);\r\n                  vec3 l = 1.0 - g;\r\n                  vec3 i1 = min( g.xyz, l.zxy );\r\n                  vec3 i2 = max( g.xyz, l.zxy );\r\n                  vec3 x1 = x0 - i1 + C.xxx;\r\n                  vec3 x2 = x0 - i2 + C.yyy; \r\n                  vec3 x3 = x0 - D.yyy;      \r\n                  i = mod(i, 289.0); \r\n                  vec4 p = permute( permute( permute( \r\n                             i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\r\n                           + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \r\n                           + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\r\n                  float n_ = 0.142857142857; \r\n                  vec3  ns = n_ * D.wyz - D.xzx;\r\n                  vec4 j = p - 49.0 * floor(p * ns.z * ns.z); \r\n                  vec4 x_ = floor(j * ns.z);\r\n                  vec4 y_ = floor(j - 7.0 * x_ );  \r\n                  vec4 x = x_ *ns.x + ns.yyyy;\r\n                  vec4 y = y_ *ns.x + ns.yyyy;\r\n                  vec4 h = 1.0 - abs(x) - abs(y);\r\n                  vec4 b0 = vec4( x.xy, y.xy );\r\n                  vec4 b1 = vec4( x.zw, y.zw );\r\n                  vec4 s0 = floor(b0)*2.0 + 1.0;\r\n                  vec4 s1 = floor(b1)*2.0 + 1.0;\r\n                  vec4 sh = -step(h, vec4(0.0));\r\n                  vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\r\n                  vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\r\n                  vec3 p0 = vec3(a0.xy,h.x);\r\n                  vec3 p1 = vec3(a0.zw,h.y);\r\n                  vec3 p2 = vec3(a1.xy,h.z);\r\n                  vec3 p3 = vec3(a1.zw,h.w);\r\n                  vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\r\n                  p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w;\r\n                  vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\r\n                  m = m * m;\r\n                  return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) );\r\n                }\r\n\r\n                void main() {\r\n                    vec4 worldPosition = modelMatrix * vec4(position, 1.0);\r\n                    vec3 upDir = normalize(worldPosition.xyz - uPlanetCenter);\r\n                    \r\n                    float elevation = 0.0;\r\n\r\n                    \/\/ Use true 3D spatial noise mapped to the sphere\r\n                    elevation += snoise(worldPosition.xyz * uBigWavesFrequency.x + vec3(uTime * uBigWavesSpeed)) * uBigWavesElevation;\r\n                    \r\n                    float smallWaves = 0.0;\r\n                    float frequency = uSmallWavesFrequency;\r\n                    float amplitude = uSmallWavesElevation;\r\n                    for (float i = 0.0; i < uSmallWavesIterations; i++) {\r\n                        smallWaves += snoise(worldPosition.xyz * frequency + vec3(uTime * uSmallWavesSpeed)) * amplitude;\r\n                        frequency *= 1.8;\r\n                        amplitude *= 0.6;\r\n                    }\r\n                    elevation += smallWaves;\r\n\r\n                    \/\/ Displace along spherical normal\r\n                    worldPosition.xyz += upDir * elevation;\r\n                    vElevation = elevation;\r\n                    vWorldPosition = worldPosition.xyz;\r\n\r\n                    gl_Position = projectionMatrix * viewMatrix * worldPosition;\r\n                }`,\r\n            fragmentShader: `\r\n                uniform vec3 uDepthColor;\r\n                uniform vec3 uSurfaceColor;\r\n                uniform float uColorOffset;\r\n                uniform float uColorMultiplier;\r\n                uniform vec3 uFoamColor;\r\n                uniform float uShoreline;\r\n                uniform vec3 uPlanetCenter;\r\n                \r\n                varying float vElevation;\r\n                varying vec3 vWorldPosition;\r\n\r\n                void main() {\r\n                    vec3 normal = normalize(cross(dFdx(vWorldPosition), dFdy(vWorldPosition)));\r\n                    vec3 upDir = normalize(vWorldPosition - uPlanetCenter);\r\n                    \r\n                    \/\/ Fresnel relative to the sphere surface normal\r\n                    float fresnel = pow(1.0 - max(0.0, dot(normal, upDir)), 3.0);\r\n                    \r\n                    vec3 color = mix(uDepthColor, uSurfaceColor, fresnel);\r\n\r\n                    \/\/ True geometric foam where wave peaks collide\r\n                    float foam = smoothstep(uShoreline - 5.0, uShoreline + 5.0, vElevation);\r\n                    color = mix(color, uFoamColor, foam);\r\n\r\n                    gl_FragColor = vec4(color, 0.95);\r\n\r\n                    #include <tonemapping_fragment>\r\n                    #include <encodings_fragment>\r\n                }`\r\n        };\r\n\r\n        const OrbWarpShader = {\r\n            uniforms: {\r\n                uTime: { value: 0.0 },\r\n                uColor: { value: new THREE.Color(window.VMP_CONFIG.orbColor || '#00e5ff') },\r\n                uWarpSpeed: { value: window.VMP_CONFIG.orbWarpSpeed || 1.5 },\r\n                uWarpAmount: { value: window.VMP_CONFIG.orbWarpAmount || 15.0 }\r\n            },\r\n            vertexShader: `\r\n                uniform float uTime;\r\n                uniform float uWarpSpeed;\r\n                uniform float uWarpAmount;\r\n                varying vec2 vUv;\r\n                varying vec3 vNormal;\r\n\r\n                vec4 permute(vec4 x){ return mod(((x*34.0)+1.0)*x, 289.0); }\r\n                vec4 taylorInvSqrt(vec4 r){ return 1.79284291400159 - 0.85373472095314 * r; }\r\n                float snoise(vec3 v){\r\n                    const vec2 C = vec2(1.0\/6.0, 1.0\/3.0);\r\n                    const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\r\n                    vec3 i = floor(v + dot(v, C.yyy) );\r\n                    vec3 x0 = v - i + dot(i, C.xxx) ;\r\n                    vec3 g = step(x0.yzx, x0.xyz);\r\n                    vec3 l = 1.0 - g;\r\n                    vec3 i1 = min( g.xyz, l.zxy );\r\n                    vec3 i2 = max( g.xyz, l.zxy );\r\n                    vec3 x1 = x0 - i1 + 1.0 * C.xxx;\r\n                    vec3 x2 = x0 - i2 + 2.0 * C.xxx;\r\n                    vec3 x3 = x0 - 1.0 + 3.0 * C.xxx;\r\n                    i = mod(i, 289.0 );\r\n                    vec4 p = permute( permute( permute(\r\n                        i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\r\n                        + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))\r\n                        + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\r\n                    float n_ = 1.42857142857;\r\n                    vec3 ns = n_ * D.wyz - D.xzx;\r\n                    vec4 j = p - 49.0 * floor(p * ns.z *ns.z);\r\n                    vec4 x_ = floor(j * ns.z);\r\n                    vec4 y_ = floor(j - 7.0 * x_ );\r\n                    vec4 x = x_ *ns.x + ns.yyyy;\r\n                    vec4 y = y_ *ns.x + ns.yyyy;\r\n                    vec4 h = 1.0 - abs(x) - abs(y);\r\n                    vec4 b0 = vec4( x.xy, y.xy );\r\n                    vec4 b1 = vec4( x.zw, y.zw );\r\n                    vec4 s0 = floor(b0)*2.0 + 1.0;\r\n                    vec4 s1 = floor(b1)*2.0 + 1.0;\r\n                    vec4 sh = -step(h, vec4(0.0));\r\n                    vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\r\n                    vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\r\n                    vec3 p0 = vec3(a0.xy,h.x);\r\n                    vec3 p1 = vec3(a0.zw,h.y);\r\n                    vec3 p2 = vec3(a1.xy,h.z);\r\n                    vec3 p3 = vec3(a1.zw,h.w);\r\n                    vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\r\n                    p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w;\r\n                    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\r\n                    m = m * m;\r\n                    return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) );\r\n                }\r\n\r\n                void main() {\r\n                    vUv = uv;\r\n                    vNormal = normal;\r\n                    float n = snoise(position * 0.05 + uTime * uWarpSpeed);\r\n                    vec3 newPosition = position + normal * (n * uWarpAmount);\r\n                    gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);\r\n                }`,\r\n            fragmentShader: `\r\n                uniform vec3 uColor;\r\n                uniform float uTime;\r\n                varying vec2 vUv;\r\n                varying vec3 vNormal;\r\n\r\n                void main() {\r\n                    float pulse = sin(uTime * 3.0) * 0.2 + 0.8;\r\n                    vec3 glow = uColor * pulse;\r\n                    gl_FragColor = vec4(glow, 0.9);\r\n                    #include <tonemapping_fragment>\r\n                    #include <encodings_fragment>\r\n                }`\r\n        };\r\n\r\n        class GPUQuantumOrb {\r\n            constructor() {\r\n                this.group = new THREE.Group();\r\n                this.radius = 25;\r\n\r\n                this.geometry = new THREE.SphereGeometry(this.radius, 128, 128);\r\n\r\n                this.material = new THREE.ShaderMaterial({\r\n                    uniforms: THREE.UniformsUtils.clone(OrbWarpShader.uniforms),\r\n                    vertexShader: OrbWarpShader.vertexShader,\r\n                    fragmentShader: OrbWarpShader.fragmentShader,\r\n                    transparent: true,\r\n                    blending: THREE.AdditiveBlending\r\n                });\r\n\r\n                const wireColor = new THREE.Color(window.VMP_CONFIG.orbWireColor || '#ffffff').getHex();\r\n                this.outerMesh = new THREE.Mesh(\r\n                    this.geometry,\r\n                    new THREE.MeshBasicMaterial({\r\n                        color: wireColor,\r\n                        wireframe: true,\r\n                        transparent: true,\r\n                        opacity: 0.2\r\n                    })\r\n                );\r\n\r\n                this.group.add(this.outerMesh);\r\n\r\n                this.mesh = new THREE.Mesh(this.geometry, this.material);\r\n                this.group.add(this.mesh);\r\n\r\n                this.tendril = new GPU_SingleTendril(this.geometry, this.radius);\r\n                this.group.add(this.tendril.line);\r\n            }\r\n\r\n            update(timeElapsed, delta, leftFeeder, rightFeeder) {\r\n                this.material.uniforms.uTime.value = timeElapsed;\r\n                this.mesh.rotation.y += delta * 0.5;\r\n                this.outerMesh.rotation.x -= delta * 0.3;\r\n                this.outerMesh.rotation.z += delta * 0.4;\r\n\r\n                const nr = (this.group.rotation.y % (Math.PI * 2)) \/ (Math.PI * 2);\r\n                let target = null;\r\n                let colorHex = new THREE.Color(window.VMP_CONFIG.tendrilColor || '#d4af37').getHex();\r\n\r\n                if (nr > 0.1 && nr < 0.4) {\r\n                    target = leftFeeder;\r\n                } else if (nr > 0.6 && nr < 0.9) {\r\n                    target = rightFeeder;\r\n                    colorHex = new THREE.Color(window.VMP_CONFIG.orbColor || '#00e5ff').getHex();\r\n                }\r\n\r\n                this.tendril.update(delta, target, colorHex, this.group, timeElapsed);\r\n            }\r\n        }\r\n\r\n        class GPU_SingleTendril {\r\n            constructor(orbGeometry, orbRadius) {\r\n                this.orbGeometry = orbGeometry;\r\n\r\n                const positions = new Float32Array((30 + 1) * 3);\r\n                for(let i = 0; i <= 30; i++) {\r\n                    positions[i * 3] = i \/ 30;\r\n                }\r\n\r\n                const geometry = new THREE.BufferGeometry();\r\n                geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\r\n\r\n                this.material = new THREE.ShaderMaterial({\r\n                    uniforms: {\r\n                        uStart: { value: new THREE.Vector3(0,0,0) },\r\n                        uEnd: { value: new THREE.Vector3(0,0,0) },\r\n                        uTime: { value: 0 },\r\n                        uProgress: { value: 1.0 },\r\n                        uBaseColor: { value: new THREE.Color(0xd4af37) }\r\n                    },\r\n                    vertexShader: `\r\n                        uniform vec3 uStart;\r\n                        uniform vec3 uEnd;\r\n                        uniform float uTime;\r\n                        uniform float uProgress;\r\n                        varying float vDraw;\r\n\r\n                        void main() {\r\n                            float t = position.x;\r\n                            vDraw = step(t, uProgress \/ 0.5);\r\n\r\n                            vec3 mid = mix(uStart, uEnd, 0.5);\r\n                            vec3 up = vec3(0.0, 1.0, 0.0);\r\n                            vec3 outVec = normalize(mid) * 15.0;\r\n                            mid += outVec;\r\n\r\n                            float mt = 1.0 - t;\r\n                            vec3 p = mt * mt * uStart + 2.0 * mt * t * mid + t * t * uEnd;\r\n\r\n                            vec3 perp = normalize(cross(normalize(uEnd - uStart), up));\r\n                            if (length(perp) < 0.1) perp = vec3(1.0, 0.0, 0.0);\r\n\r\n                            p += perp * (sin(t * 20.0 - uTime * 20.0) * 3.0 * sin(t * 3.14159));\r\n\r\n                            gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);\r\n                        }`,\r\n                    fragmentShader: `\r\n                        uniform vec3 uBaseColor;\r\n                        uniform float uTime;\r\n                        uniform float uProgress;\r\n                        varying float vDraw;\r\n\r\n                        void main() {\r\n                            if (vDraw < 0.5) discard;\r\n\r\n                            float alpha = 1.0;\r\n                            vec3 color = uBaseColor;\r\n\r\n                            if (uProgress < 0.4) {\r\n                                alpha = min(uProgress \/ 0.2, 1.0);\r\n                            } else if (uProgress < 0.8) {\r\n                                color = mix(uBaseColor, vec3(1.0), sin(uTime * 30.0) * 0.5 + 0.5);\r\n                            } else {\r\n                                alpha = (1.0 - uProgress) \/ 0.2;\r\n                            }\r\n\r\n                            gl_FragColor = vec4(color, alpha * 0.9);\r\n\r\n                            #include <tonemapping_fragment>\r\n                            #include <encodings_fragment>\r\n                        }`,\r\n                    transparent: true,\r\n                    blending: THREE.AdditiveBlending,\r\n                    depthWrite: false\r\n                });\r\n\r\n                this.line = new THREE.Line(geometry, this.material);\r\n\r\n                this.state = {\r\n                    progress: 1,\r\n                    startVertexIndex: 0,\r\n                    targetLocal: new THREE.Vector3(),\r\n                    colorHex: 0xd4af37\r\n                };\r\n            }\r\n\r\n            update(delta, targetFeeder, colorHex, orbGroup, time) {\r\n                this.material.uniforms.uTime.value = time;\r\n\r\n                if (targetFeeder && this.state.progress >= 1 && Math.random() > 0.05) {\r\n                    this.state.startVertexIndex = Math.floor(Math.random() * this.orbGeometry.attributes.position.count);\r\n\r\n                    const v1 = new THREE.Vector3().fromBufferAttribute(this.orbGeometry.attributes.position, this.state.startVertexIndex);\r\n                    const v2 = targetFeeder.position.clone().sub(orbGroup.position).normalize();\r\n\r\n                    if (v1.clone().normalize().dot(v2) > 0.3) {\r\n                        this.state.progress = 0;\r\n                        this.state.colorHex = colorHex;\r\n\r\n                        const localPt = new THREE.Vector3(\r\n                            (Math.random() - 0.5) * 200,\r\n                            (Math.random() - 0.5) * 200,\r\n                            0\r\n                        );\r\n\r\n                        targetFeeder.localToWorld(localPt);\r\n                        orbGroup.worldToLocal(localPt);\r\n                        this.state.targetLocal.copy(localPt);\r\n                    }\r\n                }\r\n\r\n                if (this.state.progress < 1) {\r\n                    this.state.progress += delta * 2.0;\r\n\r\n                    const startVec = new THREE.Vector3().fromBufferAttribute(\r\n                        this.orbGeometry.attributes.position,\r\n                        this.state.startVertexIndex\r\n                    );\r\n\r\n                    this.material.uniforms.uStart.value.copy(startVec);\r\n                    this.material.uniforms.uEnd.value.copy(this.state.targetLocal);\r\n                    this.material.uniforms.uProgress.value = Math.min(this.state.progress, 1.0);\r\n                    this.material.uniforms.uBaseColor.value.setHex(this.state.colorHex);\r\n                } else {\r\n                    this.material.uniforms.uProgress.value = 1.0;\r\n                }\r\n            }\r\n        }\r\n\r\n        class Motherboard1 {\r\n            constructor(canvasId) {\r\n                this.canvas = document.getElementById(canvasId);\r\n                this.ctx = this.canvas.getContext('2d', { alpha: false });\r\n                this.time = 0;\r\n                this.texture = new THREE.CanvasTexture(this.canvas);\r\n\r\n                window.alphaStasis = 99.5;\r\n                window.betaStasis = 99.69;\r\n\r\n                this.baseColor = window.VMP_CONFIG.mbBaseColor || 'rgba(0,150,255,0.7)';\r\n                this.textColor = window.VMP_CONFIG.mbTextColor || '#00f3ff';\r\n            }\r\n\r\n            draw() {\r\n                const mbCtx = this.ctx;\r\n                const mbWidth = this.canvas.width;\r\n                const mbHeight = this.canvas.height;\r\n\r\n                mbCtx.fillStyle = '#000000';\r\n                mbCtx.fillRect(0, 0, mbWidth, mbHeight);\r\n                this.time += 0.1;\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(mbWidth \/ 2, mbHeight \/ 2);\r\n\r\n                let scaleFactor = mbWidth \/ 1024;\r\n                mbCtx.scale(scaleFactor, scaleFactor);\r\n\r\n                const cx = 0;\r\n                const cy = -50;\r\n                const baseColor = this.baseColor;\r\n                const textColor = this.textColor;\r\n                const pwrColor = '#d97706';\r\n                const storageColor = '#a855f7';\r\n                const alertColor = '#ff0055';\r\n\r\n                mbCtx.font = \"bold 12px 'Space Mono',monospace\";\r\n                const psuX = cx - 470;\r\n                const psuY = cy - 60;\r\n\r\n                mbCtx.strokeStyle = pwrColor;\r\n                mbCtx.strokeRect(psuX, psuY, 140, 200);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"DRIVER: VMP_SYS_v9\", psuX + 10, psuY + 20);\r\n                mbCtx.fillText(\"IRQ: 0x0A\", psuX + 10, psuY + 35);\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(psuX + 70, psuY + 100);\r\n                mbCtx.rotate(this.time * 1.5);\r\n                mbCtx.strokeStyle = 'rgba(217,119,6,0.3)';\r\n\r\n                for(let i = 0; i < 4; i++) {\r\n                    mbCtx.rotate(Math.PI \/ 2);\r\n                    mbCtx.strokeRect(-40, -5, 80, 10);\r\n                }\r\n\r\n                mbCtx.restore();\r\n\r\n                let psuPulse = Math.abs(Math.sin(this.time));\r\n                mbCtx.fillStyle = `rgba(217,119,6,${0.1 + psuPulse * 0.2})`;\r\n                mbCtx.fillRect(psuX + 10, psuY + 180, 120, 10);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"EXECUTING...\", psuX + 10, psuY + 175);\r\n\r\n                const hddX = cx - 470;\r\n                const hddY = cy - 250;\r\n\r\n                mbCtx.strokeStyle = storageColor;\r\n                mbCtx.strokeRect(hddX, hddY, 140, 140);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"REGISTER: ACTIVE\", hddX + 10, hddY + 15);\r\n\r\n                for(let i = 0; i < 4; i++) {\r\n                    for(let j = 0; j < 2; j++) {\r\n                        let flicker = Math.sin(this.time * 5 + (i * j)) > 0.3 ? 0.9 : 0.1;\r\n                        mbCtx.fillStyle = `rgba(255,255,255,${flicker})`;\r\n                        mbCtx.fillRect(hddX + 20 + (i * 30), hddY + 35 + (j * 25), 20, 15);\r\n                    }\r\n                }\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"I\/O: ACTIVE\", hddX + 10, hddY + 130);\r\n\r\n                const tankX = cx + 330;\r\n                const tankData =[\r\n                    {label: \"TANK_ALPHA_CRYPTO\", y: cy - 220, seed: 0, stasisBase: window.alphaStasis},\r\n                    {label: \"TANK_BETA_WALLST\", y: cy + 40, seed: 50, stasisBase: window.betaStasis}\r\n                ];\r\n\r\n                tankData.forEach(tank => {\r\n                    let stasisLvl = (tank.stasisBase + Math.sin(this.time * 0.5 + tank.seed) * 0.05).toFixed(2);\r\n                    let isLow = stasisLvl < 20;\r\n\r\n                    mbCtx.strokeStyle = isLow ? alertColor : baseColor;\r\n                    mbCtx.strokeRect(tankX, tank.y, 130, 180);\r\n\r\n                    mbCtx.fillStyle = isLow ? alertColor : textColor;\r\n                    mbCtx.fillText(tank.label, tankX + 10, tank.y - 10);\r\n                    mbCtx.fillText(`DATA STASIS: ${stasisLvl}%`, tankX + 10, tank.y + 170);\r\n\r\n                    const tracePts1 =[\r\n                        {x: psuX + 140, y: psuY + 100},\r\n                        {x: tankX - 50, y: psuY + 100},\r\n                        {x: tankX, y: tank.y + 90}\r\n                    ];\r\n\r\n                    this.drawActiveTrace(tracePts1, this.time, 80, pwrColor, 20);\r\n\r\n                    const tracePts2 =[\r\n                        {x: hddX + 140, y: hddY + 70},\r\n                        {x: tankX - 80, y: hddY + 70},\r\n                        {x: tankX, y: tank.y + 50}\r\n                    ];\r\n\r\n                    this.drawActiveTrace(tracePts2, this.time, 120, storageColor, 10);\r\n                });\r\n\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.strokeRect(cx - 150, cy - 150, 280, 280);\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(cx - 10, cy - 10);\r\n                mbCtx.beginPath();\r\n                mbCtx.arc(0, 0, 110, 0, Math.PI * 2);\r\n                mbCtx.stroke();\r\n\r\n                mbCtx.save();\r\n                mbCtx.rotate(this.time * 0.5);\r\n\r\n                for(let f = 0; f < 9; f++) {\r\n                    mbCtx.rotate((Math.PI * 2) \/ 9);\r\n                    mbCtx.beginPath();\r\n                    mbCtx.moveTo(0, 0);\r\n                    mbCtx.quadraticCurveTo(60, -40, 105, 0);\r\n                    mbCtx.quadraticCurveTo(60, 40, 0, 0);\r\n                    mbCtx.strokeStyle = baseColor;\r\n                    mbCtx.stroke();\r\n                }\r\n\r\n                mbCtx.restore();\r\n\r\n                const chipSize = 40;\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.lineWidth = 2;\r\n\r\n                for(let i = -1; i <= 1; i++) {\r\n                    const offset = i * 12;\r\n                    mbCtx.strokeRect(-chipSize \/ 2 - 8, offset - 2, 8, 4);\r\n                    mbCtx.strokeRect(chipSize \/ 2, offset - 2, 8, 4);\r\n                    mbCtx.strokeRect(offset - 2, -chipSize \/ 2 - 8, 4, 8);\r\n                    mbCtx.strokeRect(offset - 2, chipSize \/ 2, 4, 8);\r\n                }\r\n\r\n                mbCtx.strokeRect(-chipSize \/ 2, -chipSize \/ 2, chipSize, chipSize);\r\n\r\n                mbCtx.fillStyle = baseColor;\r\n                mbCtx.beginPath();\r\n                mbCtx.arc(-chipSize \/ 2 + 8, -chipSize \/ 2 + 8, 3, 0, Math.PI * 2);\r\n                mbCtx.fill();\r\n\r\n                mbCtx.restore();\r\n                 mbCtx.restore();\r\n        this.texture.needsUpdate = true;\r\n    }\r\n\r\n    drawActiveTrace(points, dashOffset, speed, color, packetSize=15) {\r\n        const mbCtx = this.ctx;\r\n\r\n        mbCtx.beginPath();\r\n        mbCtx.moveTo(points[0].x, points[0].y);\r\n        for(let i = 1; i < points.length; i++) {\r\n            mbCtx.lineTo(points[i].x, points[i].y);\r\n        }\r\n        mbCtx.strokeStyle = 'rgba(0,255,120,0.1)';\r\n        mbCtx.lineWidth = 2;\r\n        mbCtx.stroke();\r\n\r\n        mbCtx.save();\r\n        mbCtx.beginPath();\r\n        mbCtx.moveTo(points[0].x, points[0].y);\r\n        for(let i = 1; i < points.length; i++) {\r\n            mbCtx.lineTo(points[i].x, points[i].y);\r\n        }\r\n\r\n        mbCtx.setLineDash([packetSize, 120]);\r\n        mbCtx.lineDashOffset = -(dashOffset * speed);\r\n        mbCtx.strokeStyle = color;\r\n        mbCtx.lineWidth = 3;\r\n        mbCtx.shadowBlur = 8;\r\n        mbCtx.shadowColor = color;\r\n        mbCtx.stroke();\r\n        mbCtx.restore();\r\n    }\r\n}\r\n\r\n        class Motherboard2 {\r\n            constructor(canvasId) {\r\n                this.canvas = document.getElementById(canvasId);\r\n                this.ctx = this.canvas.getContext('2d', { alpha: false });\r\n                this.time = 0;\r\n                this.texture = new THREE.CanvasTexture(this.canvas);\r\n\r\n                window.vmpHardware = {\r\n                    psu: \"VMP ATX 3.1\",\r\n                    ram: \"128GB LPDDR6\",\r\n                    storage: \"M.2 GEN 6 NVMe\",\r\n                    npu: \"AI-CELL\",\r\n                    cpu: \"NPU-PCH AI HUB\"\r\n                };\r\n\r\n                this.baseColor = window.VMP_CONFIG.mbBaseColor || 'rgba(0,150,255,0.7)';\r\n                this.textColor = window.VMP_CONFIG.mbTextColor || '#00f3ff';\r\n            }\r\n\r\n            draw() {\r\n                const mbCtx = this.ctx;\r\n                const mbWidth = this.canvas.width;\r\n                const mbHeight = this.canvas.height;\r\n\r\n                mbCtx.fillStyle = '#000000';\r\n                mbCtx.fillRect(0,0, mbWidth, mbHeight);\r\n                this.time += 0.1;\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(mbWidth \/ 2, mbHeight \/ 2);\r\n                let scaleFactor = mbWidth \/ 1280;\r\n                mbCtx.scale(scaleFactor, scaleFactor);\r\n\r\n                const cx = 0;\r\n                const cy = -50;\r\n                const baseColor = this.baseColor;\r\n                const textColor = this.textColor;\r\n                const energyColor = '#00cc55';\r\n                const pwrColor = '#d97706';\r\n\r\n                mbCtx.font = \"bold 12px 'Space Mono',monospace\";\r\n                const psuX = cx - 480;\r\n                const psuY = cy + 50;\r\n\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.strokeRect(psuX, psuY, 160, 220);\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(psuX + 80, psuY + 120);\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.beginPath();\r\n                mbCtx.arc(0, 0, 60, 0, Math.PI * 2);\r\n                mbCtx.stroke();\r\n\r\n                mbCtx.rotate(this.time * 5);\r\n                for(let i = 0; i < 7; i++) {\r\n                    mbCtx.rotate((Math.PI * 2) \/ 7);\r\n                    mbCtx.beginPath();\r\n                    mbCtx.moveTo(0, 0);\r\n                    mbCtx.lineTo(25, -20);\r\n                    mbCtx.lineTo(55, 0);\r\n                    mbCtx.lineTo(25, 20);\r\n                    mbCtx.stroke();\r\n                }\r\n                mbCtx.restore();\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(window.vmpHardware.psu, psuX + 10, psuY + 20);\r\n\r\n                const tracePts1 =[\r\n                    {x: psuX + 80, y: psuY + 180},\r\n                    {x: psuX + 80, y: cy + 320},\r\n                    {x: cx - 280, y: cy + 320}\r\n                ];\r\n                this.drawActiveTrace(tracePts1, this.time, 100, energyColor, 20);\r\n                mbCtx.fillText(\"THERMAL_LINK_SYNC\", cx - 420, cy + 335);\r\n\r\n                const capX = cx - 10;\r\n                const capY = cy - 160;\r\n\r\n                const tracePts2 =[\r\n                    {x: psuX + 80, y: psuY},\r\n                    {x: psuX + 80, y: capY},\r\n                    {x: capX - 25, y: capY}\r\n                ];\r\n                this.drawActiveTrace(tracePts2, this.time, 180, pwrColor, 30);\r\n\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.beginPath();\r\n                mbCtx.ellipse(capX, capY - 15, 25, 8, 0, 0, Math.PI * 2);\r\n                mbCtx.stroke();\r\n\r\n                mbCtx.beginPath();\r\n                mbCtx.ellipse(capX, capY, 25, 8, 0, 0, Math.PI * 2);\r\n                mbCtx.stroke();\r\n\r\n                mbCtx.beginPath();\r\n                mbCtx.moveTo(capX - 25, capY - 15);\r\n                mbCtx.lineTo(capX - 25, capY);\r\n                mbCtx.moveTo(capX + 25, capY - 15);\r\n                mbCtx.lineTo(capX + 25, capY);\r\n                mbCtx.stroke();\r\n\r\n                mbCtx.fillStyle = pwrColor;\r\n                mbCtx.fillText(\"VRM_CAP\", capX + 35, capY - 15);\r\n                mbCtx.fillText(\"PSU_FEED\", capX + 35, capY - 2);\r\n\r\n                const tracePts3 =[\r\n                    {x: capX, y: capY + 8},\r\n                    {x: capX, y: cy - 140}\r\n                ];\r\n                this.drawActiveTrace(tracePts3, this.time, 80, pwrColor, 10);\r\n\r\n                const atxX = cx + 340;\r\n                const atxY = cy - 140;\r\n\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.strokeRect(atxX, atxY, 25, 140);\r\n\r\n                for(let p = 0; p < 12; p++) {\r\n                    let pGlow = 0.3 + Math.abs(Math.sin(this.time + p)) * 0.6;\r\n                    mbCtx.fillStyle = `rgba(0,243,255,${pGlow})`;\r\n                    mbCtx.fillRect(atxX + 4, atxY + 5 + (p * 11), 7, 8);\r\n                    mbCtx.fillRect(atxX + 14, atxY + 5 + (p * 11), 7, 8);\r\n                }\r\n\r\n                const tracePts4 =[\r\n                    {x: psuX + 160, y: psuY + 180},\r\n                    {x: atxX + 12, y: psuY + 180},\r\n                    {x: atxX + 12, y: atxY + 140}\r\n                ];\r\n                this.drawActiveTrace(tracePts4, this.time, 200, pwrColor, 40);\r\n\r\n                const tracePts5 =[\r\n                    {x: atxX, y: atxY + 20},\r\n                    {x: cx + 320, y: atxY + 20}\r\n                ];\r\n                this.drawActiveTrace(tracePts5, this.time, 120, pwrColor, 15);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"DIM_V_FEED\", cx + 330, atxY - 10);\r\n\r\n                const tracePts6 =[\r\n                    {x: psuX + 160, y: psuY + 100},\r\n                    {x: cx - 310, y: psuY + 100},\r\n                    {x: cx - 310, y: cy + 212},\r\n                    {x: cx - 280, y: cy + 212}\r\n                ];\r\n                this.drawActiveTrace(tracePts6, this.time, 150, pwrColor, 30);\r\n\r\n                const tracePts7 =[\r\n                    {x: psuX + 160, y: psuY + 120},\r\n                    {x: cx - 330, y: psuY + 120},\r\n                    {x: cx - 330, y: cy + 292},\r\n                    {x: cx - 280, y: cy + 292}\r\n                ];\r\n                this.drawActiveTrace(tracePts7, this.time, 150, pwrColor, 30);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"PCIe_PWR_L1\", cx - 450, psuY + 95);\r\n                mbCtx.fillText(\"PCIe_PWR_L2\", cx - 450, psuY + 135);\r\n\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.strokeRect(cx + 190, cy - 140, 130,30,260);\r\n\r\n                for(let r = 0; r < 4; r++) {\r\n                    for(let c = 0; c < 8; c++) {\r\n                        if(Math.random() > 0.98) {\r\n                            mbCtx.fillStyle = '#00ff55';\r\n                            mbCtx.fillRect(cx + 195 + (r * 32), cy - 120 + (c * 30), 22, 20);\r\n                        }\r\n                    }\r\n                }\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(cx + 230, cy + 260);\r\n                mbCtx.rotate(this.time * 0.2);\r\n                mbCtx.setLineDash([8, 4]);\r\n                mbCtx.strokeStyle = energyColor;\r\n                mbCtx.strokeRect(-35, -35, 70, 70);\r\n\r\n                mbCtx.rotate(-this.time * 0.5);\r\n                mbCtx.setLineDash([]);\r\n                mbCtx.strokeStyle = textColor;\r\n                mbCtx.strokeRect(-18, -18, 36, 36);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.font = \"bold 6px 'Space Mono',monospace\";\r\n\r\n                for(let l = 0; l < 4; l++){\r\n                    let w = Math.abs(Math.sin(this.time + l)) * 26;\r\n                    mbCtx.fillRect(-13, -12 + (l * 8), w, 2);\r\n                }\r\n                mbCtx.restore();\r\n\r\n                mbCtx.font = \"bold 12px 'Space Mono',monospace\";\r\n                mbCtx.fillText(window.vmpHardware.cpu, cx + 180, cy + 325);\r\n\r\n                const nvmeX = cx + 120;\r\n                const nvmeY = cy + 165;\r\n\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.strokeRect(nvmeX, nvmeY, 120, 30);\r\n\r\n                for(let i = 0; i < 3; i++) {\r\n                    let activity = Math.abs(Math.sin(this.time * 2 + i));\r\n                    if (activity > 0.8) {\r\n                        mbCtx.fillStyle = `rgba(0,255,120,${activity})`;\r\n                        mbCtx.shadowBlur = 10 * activity;\r\n                        mbCtx.shadowColor = '#00ff55';\r\n                        mbCtx.fillRect(nvmeX + 8 + (i * 12), nvmeY + 8, 5, 14);\r\n                    }\r\n                }\r\n                mbCtx.shadowBlur = 0;\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(window.vmpHardware.storage, nvmeX + 50, nvmeY + 20);\r\n\r\n                const tracePts8 =[\r\n                    {x: nvmeX + 60, y: nvmeY + 30},\r\n                    {x: nvmeX + 60, y: cy + 260},\r\n                    {x: cx + 195, y: cy + 260}\r\n                ];\r\n                this.drawActiveTrace(tracePts8, -this.time, 220, energyColor, 15);\r\n                mbCtx.fillText(\"NVMe_DATA_BUS\", nvmeX + 65, cy + 245);\r\n\r\n                const sataX = cx + 350;\r\n                const sataY = cy + 220;\r\n\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.strokeRect(sataX, sataY, 60, 80);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"SATA\", sataX + 15, sataY - 5);\r\n\r\n                const tracePts9 =[\r\n                    {x: cx + 270, y: sataY + 40},\r\n                    {x: sataX, y: sataY + 40}\r\n                ];\r\n                this.drawActiveTrace(tracePts9, this.time, 180, textColor, 20);\r\n\r\n                for(let i = 0; i < 4; i++) {\r\n                    let prog = (this.time * 0.5 + i * 0.25) % 1;\r\n                    if (prog > 0.5) {\r\n                        let packetX = sataX + 10;\r\n                        let packetY = sataY + 10 + (i * 18);\r\n                        let glow = Math.sin(prog * Math.PI) * 0.8;\r\n\r\n                        mbCtx.shadowBlur = 15 * glow;\r\n                        mbCtx.shadowColor = textColor;\r\n                        mbCtx.strokeRect(packetX + (Math.random() * 30), packetY, 8, 4);\r\n                    }\r\n                }\r\n                mbCtx.shadowBlur = 0;\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(cx - 10, cy - 10);\r\n                mbCtx.beginPath();\r\n                mbCtx.strokeStyle = baseColor;\r\n                mbCtx.arc(0, 0, 140, 0, Math.PI * 2);\r\n                mbCtx.stroke();\r\n\r\n                let pulse = 0.5 + Math.abs(Math.sin(this.time * 2)) * 0.5;\r\n                mbCtx.beginPath();\r\n                mbCtx.arc(0, 0, 40, 0, Math.PI * 2);\r\n                mbCtx.shadowBlur = 30 * pulse;\r\n                mbCtx.shadowColor = '#00f3ff';\r\n                mbCtx.stroke();\r\n                mbCtx.shadowBlur = 0;\r\n\r\n                mbCtx.rotate(this.time * 5);\r\n                for(let f = 0; f < 18; f++) {\r\n                    mbCtx.rotate((Math.PI * 2) \/ 18);\r\n                    mbCtx.beginPath();\r\n                    mbCtx.moveTo(0, 0);\r\n                    mbCtx.quadraticCurveTo(60, -40, 115, 0);\r\n                    mbCtx.quadraticCurveTo(60, 40, 0, 0);\r\n                    mbCtx.stroke();\r\n                }\r\n                mbCtx.restore();\r\n\r\n                mbCtx.save();\r\n                mbCtx.translate(cx - 10, cy - 10);\r\n                mbCtx.shadowBlur = 15;\r\n                mbCtx.shadowColor = \"#00f3ff\";\r\n                mbCtx.fillStyle = \"#fff\";\r\n                mbCtx.font = \"bold 18px 'Space Mono',monospace\";\r\n                mbCtx.textAlign = \"center\";\r\n                mbCtx.fillText(window.vmpHardware.npu, 0, 5);\r\n                mbCtx.restore();\r\n\r\n                const tracePts10 =[\r\n                    {x: cx + 130, y: cy - 10},\r\n                    {x: cx + 190, y: cy - 10}\r\n                ];\r\n                this.drawActiveTrace(tracePts10, this.time, 250, energyColor, 20);\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"CPU_MEM_LINK\", cx + 115, cy - 15);\r\n\r\n                const tracePts11 =[\r\n                    {x: cx + 40, y: cy + 130},\r\n                    {x: cx + 230, y: cy + 130},\r\n                    {x: cx + 230, y: cy + 225}\r\n                ];\r\n                this.drawActiveTrace(tracePts11, this.time, 400, '#ffae42', 35);\r\n                mbCtx.fillStyle = '#ffae42';\r\n                mbCtx.fillText(\"CORE_PCH_LINK\", cx + 80, cy + 145);\r\n\r\n                const tracePts12 =[\r\n                    {x: cx - 40, y: cy + 145},\r\n                    {x: cx - 40, y: cy + 212}\r\n                ];\r\n                this.drawActiveTrace(tracePts12, this.time, 300, textColor, 25);\r\n\r\n                const tracePts13 =[\r\n                    {x: cx - 15, y: cy + 140},\r\n                    {x: cx - 15, y: cy + 292}\r\n                ];\r\n                this.drawActiveTrace(tracePts13, this.time, 300, textColor, 25);\r\n\r\n                mbCtx.fillStyle = textColor;\r\n                mbCtx.fillText(\"PCIe_DATA_L1\", cx - 35, cy + 185);\r\n                mbCtx.fillText(\"PCIe_DATA_L2\", cx - 10, cy + 265);\r\n\r\n                for(let j = 0; j < 2; j++) {\r\n                    let yOff = cy + 200 + (j * 80);\r\n                    mbCtx.strokeStyle = baseColor;\r\n                    mbCtx.strokeRect(cx - 280, yOff, 430, 25);\r\n                }\r\n\r\n                mbCtx.restore();\r\n                this.texture.needsUpdate = true;\r\n            }\r\n\r\n            drawActiveTrace(points, dashOffset, speed, color, packetSize=15) {\r\n                const mbCtx = this.ctx;\r\n\r\n                mbCtx.beginPath();\r\n                mbCtx.moveTo(points[0].x, points[0].y);\r\n                for(let i = 1; i < points.length; i++) {\r\n                    mbCtx.lineTo(points[i].x, points[i].y);\r\n                }\r\n                mbCtx.strokeStyle = 'rgba(0,255,120,0.1)';\r\n                mbCtx.lineWidth = 2;\r\n                mbCtx.stroke();\r\n\r\n                mbCtx.save();\r\n                mbCtx.beginPath();\r\n                mbCtx.moveTo(points[0].x, points[0].y);\r\n                for(let i = 1; i < points.length; i++) {\r\n                    mbCtx.lineTo(points[i].x, points[i].y);\r\n                }\r\n\r\n                mbCtx.setLineDash([packetSize, 120]);\r\n                mbCtx.lineDashOffset = -(dashOffset * speed);\r\n                mbCtx.strokeStyle = color;\r\n                mbCtx.lineWidth = 3;\r\n                mbCtx.shadowBlur = 8;\r\n                mbCtx.shadowColor = color;\r\n                mbCtx.stroke();\r\n                mbCtx.restore();\r\n            }\r\n        } \r\n\r\n        class CommandCenterScreen {\r\n            constructor(canvasId) {\r\n                this.canvas = document.getElementById(canvasId);\r\n                this.ctx = this.canvas.getContext('2d', { alpha: false });\r\n                this.texture = new THREE.CanvasTexture(this.canvas);\r\n                this.time = 0;\r\n                this.baseColor = window.VMP_CONFIG.mbBaseColor || 'rgba(0,150,255,0.7)';\r\n                this.textColor = window.VMP_CONFIG.mbTextColor || '#00f3ff';\r\n\r\n                this.radarEntities =[];\r\n                this.mb1Freq = new Array(100).fill(50);\r\n                this.mb2Freq = new Array(100).fill(50);\r\n                this.voltages = new Array(25).fill(12.0);\r\n            }\r\n\r\n            updateEntities(arr) {\r\n                this.radarEntities = arr;\r\n            }\r\n\r\n            draw() {\r\n                const ctx = this.ctx;\r\n                const w = this.canvas.width;\r\n                const h = this.canvas.height;\r\n\r\n                ctx.fillStyle = '#010308';\r\n                ctx.fillRect(0, 0, w, h);\r\n                this.time += 0.05;\r\n\r\n                ctx.strokeStyle = 'rgba(0, 229, 255, 0.05)';\r\n                ctx.lineWidth = 1;\r\n\r\n                for(let i = 0; i < w; i += 40) {\r\n                    ctx.beginPath();\r\n                    ctx.moveTo(i, 0);\r\n                    ctx.lineTo(i, h);\r\n                    ctx.stroke();\r\n                }\r\n                for(let i = 0; i < h; i += 40) {\r\n                    ctx.beginPath();\r\n                    ctx.moveTo(0, i);\r\n                    ctx.lineTo(w, i);\r\n                    ctx.stroke();\r\n                }\r\n\r\n                ctx.font = \"900 60px 'Space Mono', monospace\";\r\n                ctx.fillStyle = this.textColor;\r\n                ctx.textAlign = 'center';\r\n                ctx.shadowBlur = 20;\r\n                ctx.shadowColor = this.textColor;\r\n                ctx.fillText(\"VMP OMEGA ECOSYSTEM : GLOBAL TELEMETRY\", w\/2, 80);\r\n                ctx.shadowBlur = 0;\r\n\r\n                const rX = 350;\r\n                const rY = h\/2 + 50;\r\n                const rRad = 300;\r\n\r\n                ctx.strokeStyle = this.baseColor;\r\n                ctx.lineWidth = 2;\r\n\r\n                for(let i = 1; i <= 4; i++) {\r\n                    ctx.beginPath();\r\n                    ctx.arc(rX, rY, rRad * (i\/4), 0, Math.PI*2);\r\n                    ctx.stroke();\r\n                }\r\n\r\n                ctx.beginPath();\r\n                ctx.moveTo(rX - rRad, rY);\r\n                ctx.lineTo(rX + rRad, rY);\r\n                ctx.stroke();\r\n\r\n                ctx.beginPath();\r\n                ctx.moveTo(rX, rY - rRad);\r\n                ctx.lineTo(rX, rY + rRad);\r\n                ctx.stroke();\r\n\r\n                const sweepAngle = this.time * 2;\r\n                ctx.beginPath();\r\n                ctx.moveTo(rX, rY);\r\n                ctx.lineTo(rX + Math.cos(sweepAngle) * rRad, rY + Math.sin(sweepAngle) * rRad);\r\n                ctx.strokeStyle = '#00ff66';\r\n                ctx.lineWidth = 3;\r\n                ctx.stroke();\r\n\r\n                ctx.fillStyle = 'rgba(0,255,102,0.1)';\r\n                ctx.beginPath();\r\n                ctx.moveTo(rX, rY);\r\n                ctx.arc(rX, rY, rRad, sweepAngle - 0.5, sweepAngle, false);\r\n                ctx.closePath();\r\n                ctx.fill();\r\n\r\n                this.radarEntities.forEach(ent => {\r\n                    const mapX = (ent.x \/ 1000) * rRad;\r\n                    const mapZ = (ent.z \/ 1000) * rRad;\r\n\r\n                    ctx.fillStyle = ent.color;\r\n                    ctx.beginPath();\r\n                    ctx.arc(rX + mapX, rY + mapZ, 6, 0, Math.PI*2);\r\n                    ctx.fill();\r\n\r\n                    let entAngle = Math.atan2(mapZ, mapX);\r\n                    if (entAngle < 0) {\r\n                        entAngle += Math.PI * 2;\r\n                    }\r\n\r\n                    let normSweep = sweepAngle % (Math.PI * 2);\r\n                    if (normSweep < 0) {\r\n                        normSweep += Math.PI * 2;\r\n                    }\r\n\r\n                    if(Math.abs(normSweep - entAngle) < 0.2) {\r\n                        ctx.strokeStyle = '#fff';\r\n                        ctx.lineWidth = 2;\r\n                        ctx.beginPath();\r\n                        ctx.arc(rX + mapX, rY + mapZ, 15, 0, Math.PI*2);\r\n                        ctx.stroke();\r\n                    }\r\n                });\r\n\r\n                const gX = 800;\r\n                const gY = 200;\r\n\r\n                this.mb1Freq.shift();\r\n                this.mb1Freq.push(50 + Math.sin(this.time * 2) * 30 + (Math.random() - 0.5) * 20);\r\n\r\n                this.mb2Freq.shift();\r\n                this.mb2Freq.push(50 + Math.cos(this.time * 1.5) * 20 + (Math.random() - 0.5) * 15);\r\n\r\n                const drawGraph = (x, y, w, h, data, color, title) => {\r\n                    ctx.strokeStyle = this.baseColor;\r\n                    ctx.strokeRect(x, y, w, h);\r\n\r\n                    ctx.fillStyle = this.textColor;\r\n                    ctx.font = \"bold 24px 'Inter'\";\r\n                    ctx.textAlign = 'left';\r\n                    ctx.fillText(title, x, y - 10);\r\n\r\n                    ctx.beginPath();\r\n                    ctx.strokeStyle = color;\r\n                    ctx.lineWidth = 3;\r\n\r\n                    const step = w \/ (data.length - 1);\r\n                    for(let i = 0; i < data.length; i++) {\r\n                        const py = y + h - (data[i] \/ 100) * h;\r\n                        if(i === 0) {\r\n                            ctx.moveTo(x, py);\r\n                        } else {\r\n                            ctx.lineTo(x + i * step, py);\r\n                        }\r\n                    }\r\n\r\n                    ctx.stroke();\r\n                    ctx.lineTo(x + w, y + h);\r\n                    ctx.lineTo(x, y + h);\r\n\r\n                    ctx.fillStyle = color.replace('1.0)', '0.1)').replace(')', ', 0.1)');\r\n                    ctx.fill();\r\n                };\r\n\r\n                drawGraph(gX, gY, 500, 200, this.mb1Freq, 'rgba(0, 229, 255, 1.0)', 'QUANTUM CORE 1 FREQUENCY');\r\n                drawGraph(gX, gY + 300, 500, 200, this.mb2Freq, 'rgba(255, 170, 0, 1.0)', 'QUANTUM CORE 2 FREQUENCY');\r\n\r\n                const hX = 1400;\r\n                const hY = 200;\r\n                ctx.fillStyle = this.textColor;\r\n                ctx.font = \"bold 18px 'Space Mono'\";\r\n                ctx.textAlign = 'left';\r\n                ctx.fillText(\"GRID VOLTAGE & HASH VECTORS\", hX, hY - 10);\r\n\r\n                for(let r = 0; r < 25; r++) {\r\n                    this.voltages[r] = this.voltages[r] + (Math.random() - 0.5) * 0.5;\r\n\r\n                    if(this.voltages[r] < 11.0) {\r\n                        this.voltages[r] = 11.0;\r\n                    }\r\n                    if(this.voltages[r] > 14.5) {\r\n                        this.voltages[r] = 14.5;\r\n                    }\r\n\r\n                    let vColor = this.textColor;\r\n                    if(this.voltages[r] > 14.0) {\r\n                        vColor = '#ff0055';\r\n                    } else if (this.voltages[r] < 11.5) {\r\n                        vColor = '#ffaa00';\r\n                    } else {\r\n                        vColor = '#00ff66';\r\n                    }\r\n\r\n                    let line = \"NODE_\" + r.toString().padStart(2, '0') + \"[ \" + this.voltages[r].toFixed(3) + \"v ] : \";\r\n                    for(let c = 0; c < 4; c++) {\r\n                        line += Math.floor(Math.random() * 65535).toString(16).toUpperCase().padStart(4, '0') + \" \";\r\n                    }\r\n\r\n                    ctx.fillStyle = vColor;\r\n                    ctx.fillText(line, hX, hY + (r * 25));\r\n                }\r\n\r\n                this.texture.needsUpdate = true;\r\n            }\r\n        }\r\n\r\n        const loadAdvancedMat = (diffuseUrl, bumpUrl, colorHex, roughness, metalness, scaleX = 1.0, scaleY = 1.0, rotDeg = 0, offsetX = 0, offsetY = 0) => {\r\n            const mat = new THREE.MeshStandardMaterial({\r\n                color: colorHex,\r\n                roughness: roughness !== undefined ? roughness : 0.5,\r\n                metalness: metalness !== undefined ? metalness : 0.2\r\n            });\r\n\r\n            if (diffuseUrl && diffuseUrl.length > 5) {\r\n                const loader = new THREE.TextureLoader();\r\n                loader.setCrossOrigin('anonymous');\r\n                loader.load(getBustUrl(diffuseUrl), (tex) => {\r\n                    tex.wrapS = tex.wrapT = THREE.RepeatWrapping;\r\n                    tex.repeat.set(scaleX, scaleY);\r\n                    tex.rotation = THREE.MathUtils.degToRad(rotDeg);\r\n                    tex.offset.set(offsetX, offsetY);\r\n                    tex.center.set(0.5, 0.5); \r\n                    \r\n                    const maxAnisotropy = window.VMP_ENGINE.renderer.capabilities.getMaxAnisotropy();\r\n                    tex.anisotropy = maxAnisotropy;\r\n                    tex.minFilter = THREE.LinearMipmapLinearFilter;\r\n                    tex.magFilter = THREE.LinearFilter;\r\n                    \r\n                    mat.map = tex;\r\n                    mat.needsUpdate = true;\r\n                });\r\n            }\r\n            if (bumpUrl && bumpUrl.length > 5) {\r\n                const loader = new THREE.TextureLoader();\r\n                loader.setCrossOrigin('anonymous');\r\n                loader.load(getBustUrl(bumpUrl), (tex) => {\r\n                    tex.wrapS = tex.wrapT = THREE.RepeatWrapping;\r\n                    tex.repeat.set(scaleX, scaleY);\r\n                    tex.rotation = THREE.MathUtils.degToRad(rotDeg);\r\n                    tex.offset.set(offsetX, offsetY);\r\n                    tex.center.set(0.5, 0.5);\r\n                    mat.bumpMap = tex;\r\n                    mat.bumpScale = 1.0;\r\n                    mat.needsUpdate = true;\r\n                });\r\n            }\r\n            return mat;\r\n        };\r\n\r\n        const loadCustomModel = (url, callback, scale = 100) => {\r\n            if (!url) { callback(null); return; }\r\n            const ext = url.split('.').pop().toLowerCase();\r\n            const fullUrl = getBustUrl(url);\r\n\r\n            const loader = (ext === 'gltf' || ext === 'glb') ? gltfLoader : new OBJLoader();\r\n            \r\n            loader.load(fullUrl, (result) => {\r\n                const object = (ext === 'gltf' || ext === 'glb') ? result.scene : result;\r\n\r\n                const box = new THREE.Box3().setFromObject(object);\r\n                const size = box.getSize(new THREE.Vector3());\r\n                const maxDim = Math.max(size.x, size.y, size.z);\r\n                if (maxDim > 0) {\r\n                    const targetScale = scale \/ maxDim;\r\n                    object.scale.set(targetScale, targetScale, targetScale);\r\n                }\r\n                \r\n                const toRemove =[];\r\n                object.traverse((child) => {\r\n                    if (child.isMesh) { \r\n                        child.castShadow = true; \r\n                        child.receiveShadow = true; \r\n                        const name = child.name.toLowerCase();\r\n                        if(name.includes('ground') || name.includes('plane') || name.includes('shadow') || name.includes('floor')) {\r\n                            toRemove.push(child);\r\n                        }\r\n                    }\r\n                });\r\n                toRemove.forEach(c => c.parent.remove(c));\r\n                \r\n                callback(object);\r\n            }, undefined, () => callback(null));\r\n        };\r\n        \r\n        const createFurTexture = (baseColorHex) => {\r\n            const canvas = document.createElement('canvas');\r\n            canvas.width = 256; canvas.height = 256;\r\n            const ctx = canvas.getContext('2d');\r\n            ctx.fillStyle = baseColorHex;\r\n            ctx.fillRect(0, 0, 256, 256);\r\n            for (let i = 0; i < 1500; i++) {\r\n                ctx.strokeStyle = Math.random() > 0.5 ? 'rgba(0,0,0,0.15)' : 'rgba(255,255,255,0.15)';\r\n                ctx.lineWidth = 1 + Math.random() * 2;\r\n                ctx.beginPath();\r\n                const x = Math.random() * 256;\r\n                const y = Math.random() * 256;\r\n                ctx.moveTo(x, y);\r\n                ctx.lineTo(x + (Math.random() - 0.5) * 15, y + 5 + Math.random() * 15);\r\n                ctx.stroke();\r\n            }\r\n            const tex = new THREE.CanvasTexture(canvas);\r\n            tex.wrapS = tex.wrapT = THREE.RepeatWrapping;\r\n            return tex;\r\n        };\r\n\r\n        const distantHumanGeo = new THREE.BoxGeometry(3, 8, 1.5);\r\n        const distantHumanMat = new THREE.MeshStandardMaterial({ color: 0x444444 });\r\n\r\n        const buildProceduralHuman = (role = 'adult', specificSkinHex = null, clothing = 'default') => {\r\n            const highDetailGroup = new THREE.Group();\r\n            const skinTones =[0x8d5524, 0xc68642, 0xe0ac69, 0xf1c27d, 0xffccaa, 0x3d2c23];\r\n            const tone = specificSkinHex !== null ? specificSkinHex : skinTones[Math.floor(Math.random() * skinTones.length)];\r\n            const skinMat = new THREE.MeshStandardMaterial({color: tone, roughness: 0.6});\r\n            let shirtMat, pantsMat;\r\n            \r\n            const momColor = new THREE.Color(window.VMP_CONFIG.colorMom || '#ff0055');\r\n            const dadColor = new THREE.Color(window.VMP_CONFIG.colorDad || '#0044ff');\r\n            const sonColor = new THREE.Color(window.VMP_CONFIG.colorSon || '#00ff66');\r\n\r\n            switch(clothing) {\r\n                case 'construction': shirtMat = new THREE.MeshStandardMaterial({ color: 0xffa500, roughness: 0.8 }); pantsMat = new THREE.MeshStandardMaterial({ color: 0x4d4d4d, roughness: 0.8 }); break;\r\n                case 'electrician': shirtMat = new THREE.MeshStandardMaterial({ color: 0x333333, roughness: 0.8 }); pantsMat = new THREE.MeshStandardMaterial({ color: 0x555555, roughness: 0.8 }); break;\r\n                case 'plumber': shirtMat = new THREE.MeshStandardMaterial({ color: 0x00008b, roughness: 0.8 }); pantsMat = new THREE.MeshStandardMaterial({ color: 0x8b4513, roughness: 0.8 }); break;\r\n                case 'security': shirtMat = new THREE.MeshStandardMaterial({ color: 0x111122, roughness: 0.8 }); pantsMat = new THREE.MeshStandardMaterial({ color: 0x222233, roughness: 0.8 }); break;\r\n                case 'doctor': shirtMat = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.9 }); pantsMat = new THREE.MeshStandardMaterial({ color: 0xeeeeee, roughness: 0.9 }); break;\r\n                case 'student': shirtMat = new THREE.MeshStandardMaterial({color: 0x444499, roughness: 0.9}); pantsMat = new THREE.MeshStandardMaterial({color: 0x666666, roughness: 0.9}); break;\r\n                case 'mom': shirtMat = new THREE.MeshStandardMaterial({color: momColor, roughness: 0.9}); pantsMat = new THREE.MeshStandardMaterial({color: 0xffffff, roughness: 0.9}); break;\r\n                case 'dad': shirtMat = new THREE.MeshStandardMaterial({color: dadColor, roughness: 0.9}); pantsMat = new THREE.MeshStandardMaterial({color: 0x333333, roughness: 0.9}); break;\r\n                case 'son': shirtMat = new THREE.MeshStandardMaterial({color: sonColor, roughness: 0.9}); pantsMat = new THREE.MeshStandardMaterial({color: 0x4444aa, roughness: 0.9}); break;\r\n                default: shirtMat = new THREE.MeshStandardMaterial({color: new THREE.Color().setHSL(Math.random(), 0.6, 0.4), roughness: 0.9}); pantsMat = new THREE.MeshStandardMaterial({color: new THREE.Color().setHSL(Math.random(), 0.3, 0.2), roughness: 0.9});\r\n            }\r\n            const scale = (role === 'child') ? 0.5 + Math.random()*0.2 : 0.9 + Math.random()*0.2;\r\n            const torso = new THREE.Mesh(new THREE.BoxGeometry(3, 4, 1.5), shirtMat); torso.position.y = 5.5; highDetailGroup.add(torso);\r\n            const head = new THREE.Mesh(new THREE.SphereGeometry(1.2, 16, 16), skinMat); head.position.y = 8.5; highDetailGroup.add(head);\r\n            const armLGrp = new THREE.Group(); armLGrp.position.set(1.9, 7.5, 0); const armRGrp = new THREE.Group(); armRGrp.position.set(-1.9, 7.5, 0);\r\n            const armGeo = new THREE.CylinderGeometry(0.4, 0.4, 3.5, 8); armGeo.translate(0, -1.75, 0);\r\n            const armL = new THREE.Mesh(armGeo, shirtMat); armLGrp.add(armL); highDetailGroup.add(armLGrp);\r\n            const armR = new THREE.Mesh(armGeo, shirtMat); armRGrp.add(armR); highDetailGroup.add(armRGrp);\r\n            const legLGrp = new THREE.Group(); legLGrp.position.set(0.8, 3.5, 0); const legRGrp = new THREE.Group(); legRGrp.position.set(-0.8, 3.5, 0);\r\n            const legGeo = new THREE.CylinderGeometry(0.5, 0.4, 4, 8); legGeo.translate(0, -2, 0);\r\n            const legL = new THREE.Mesh(legGeo, pantsMat); legLGrp.add(legL); highDetailGroup.add(legLGrp);\r\n            const legR = new THREE.Mesh(legGeo, pantsMat); legRGrp.add(legR); highDetailGroup.add(legRGrp);\r\n            highDetailGroup.scale.setScalar(scale);\r\n            highDetailGroup.userData = { isHuman: true, armL: armLGrp, armR: armRGrp, legL: legLGrp, legR: legRGrp, baseY: 0, scale: scale };\r\n\r\n            const lowDetailMesh = new THREE.Mesh(distantHumanGeo, distantHumanMat);\r\n            lowDetailMesh.scale.setScalar(scale);\r\n            lowDetailMesh.position.y = 4 * scale;\r\n\r\n            const lod = new THREE.LOD();\r\n            lod.addLevel(highDetailGroup, 600);\r\n            lod.addLevel(lowDetailMesh, 600);\r\n            \r\n            const finalWrap = new THREE.Group();\r\n            lod.position.y = 0.5 * scale;\r\n            finalWrap.add(lod);\r\n            finalWrap.userData = highDetailGroup.userData;\r\n            \r\n            return finalWrap;\r\n        };\r\n\r\n        const buildUprightTree = () => {\r\n            const treeGroup = new THREE.Group();\r\n            const trunkMat = new THREE.MeshStandardMaterial({ color: 0x3d2817, roughness: 1.0 });\r\n            const leafMat = new THREE.MeshStandardMaterial({ color: 0x2d5a27, roughness: 0.9 });\r\n            const mangoMat = new THREE.MeshStandardMaterial({ color: 0xff8c00, roughness: 0.5 });\r\n\r\n            const height = 60 + Math.random() * 40;\r\n            const isMangoTree = Math.random() > 0.7;\r\n\r\n            const curve = new THREE.CatmullRomCurve3([\r\n                new THREE.Vector3(0,0,0),\r\n                new THREE.Vector3((Math.random() - 0.5) * 5, height * 0.33, (Math.random() - 0.5) * 5),\r\n                new THREE.Vector3((Math.random() - 0.5) * 10, height * 0.66, (Math.random() - 0.5) * 10),\r\n                new THREE.Vector3((Math.random() - 0.5) * 15, height, (Math.random() - 0.5) * 15)\r\n            ]);\r\n\r\n            const trunkGeo = new THREE.TubeGeometry(curve, 16, 6, 8, false);\r\n            const trunk = new THREE.Mesh(trunkGeo, trunkMat);\r\n            trunk.castShadow = true;\r\n            trunk.receiveShadow = true;\r\n            treeGroup.add(trunk);\r\n\r\n            const baseDirtGeo = new THREE.CylinderGeometry(15, 18, 2, 16);\r\n            const baseDirt = new THREE.Mesh(baseDirtGeo, trunkMat);\r\n            baseDirt.position.y = 1;\r\n            treeGroup.add(baseDirt);\r\n\r\n            const points = curve.getPoints(4);\r\n\r\n            points.forEach((pt, idx) => {\r\n                if (idx === 0) return;\r\n\r\n                for(let b = 0; b < 3; b++) {\r\n                    const bCurve = new THREE.CatmullRomCurve3([\r\n                        pt,\r\n                        new THREE.Vector3(\r\n                            pt.x + (Math.random() - 0.5) * 40,\r\n                            pt.y + 10 + Math.random() * 20,\r\n                            pt.z + (Math.random() - 0.5) * 40\r\n                        )\r\n                    ]);\r\n\r\n                    const branchGeo = new THREE.TubeGeometry(bCurve, 8, 2, 6, false);\r\n                    const branch = new THREE.Mesh(branchGeo, trunkMat);\r\n                    branch.castShadow = true;\r\n                    treeGroup.add(branch);\r\n\r\n                    const padGeo = new THREE.SphereGeometry(20 + Math.random() * 15, 12, 12);\r\n                    const pad = new THREE.Mesh(padGeo, leafMat);\r\n                    pad.scale.set(1, 0.6, 1);\r\n                    pad.position.copy(bCurve.points[1]);\r\n                    pad.castShadow = true;\r\n                    treeGroup.add(pad);\r\n\r\n                    if (isMangoTree) {\r\n                        for(let m = 0; m < 3; m++) {\r\n                            const mangoGeo = new THREE.SphereGeometry(1.5, 8, 8);\r\n                            const mango = new THREE.Mesh(mangoGeo, mangoMat);\r\n                            mango.scale.set(1, 1.4, 1);\r\n                            mango.position.set(\r\n                                pad.position.x + (Math.random() - 0.5) * 15,\r\n                                pad.position.y - 5 - Math.random() * 5,\r\n                                pad.position.z + (Math.random() - 0.5) * 15\r\n                            );\r\n                            treeGroup.add(mango);\r\n                        }\r\n                    }\r\n                }\r\n            });\r\n\r\n            return treeGroup;\r\n        };\r\n\r\n        class InterplanetaryTravel {\r\n            constructor(manager) {\r\n                this.manager = manager;\r\n                this.isTraveling = false;\r\n                this.travelProgress = 0;\r\n                this.travelDuration = 5; \r\n                this.targetPlanet = null;\r\n                this.currentPlanet = 'Earth';\r\n\r\n                this.planetConfigs = {\r\n                    'Earth': {\r\n                        floorTexture: window.VMP_CONFIG.texCytron || window.VMP_CONFIG.floorDiff,\r\n                        skyTexture: window.VMP_CONFIG.envBg,\r\n                        fogColor: new THREE.Color(window.VMP_CONFIG.fogColor),\r\n                        fogDensity: window.VMP_CONFIG.fogDensity,\r\n                        showCity: true\r\n                    },\r\n                    'Mars': {\r\n                        floorTexture: window.VMP_CONFIG.texMars,\r\n                        skyTexture: window.VMP_CONFIG.envBg,\r\n                        fogColor: new THREE.Color(0x904a20),\r\n                        fogDensity: 0.0000,\r\n                        showCity: false\r\n                    },\r\n                    'Venus': {\r\n                        floorTexture: window.VMP_CONFIG.texVenus,\r\n                        skyTexture: window.VMP_CONFIG.envBg,\r\n                        fogColor: new THREE.Color(0xbc9352),\r\n                        fogDensity: 0.000,\r\n                        showCity: false\r\n                    }\r\n                };\r\n            }\r\n\r\n            travelTo(planetName) {\r\n                if (this.isTraveling || this.currentPlanet === planetName) {\r\n                    TerminalLogger.log(`[TRAVEL] Already at ${this.currentPlanet} or travel in progress.`, 'warn');\r\n                    return;\r\n                }\r\n\r\n                TerminalLogger.log(`[TRAVEL] Initiating hyper-jump sequence to ${planetName}...`, 'sys');\r\n                this.isTraveling = true;\r\n                this.travelProgress = 0;\r\n                this.targetPlanet = planetName;\r\n\r\n                const loadingOverlay = document.getElementById(`loading_${INSTANCE_ID}`);\r\n                if (loadingOverlay) {\r\n                    loadingOverlay.style.display = 'flex';\r\n                    loadingOverlay.style.opacity = '0';\r\n                    document.getElementById(`loading_status_${INSTANCE_ID}`).innerText = `Calculating trajectory to ${planetName}...`;\r\n                }\r\n            }\r\n\r\n            update(delta) {\r\n                if (!this.isTraveling) return;\r\n\r\n                this.travelProgress += delta;\r\n                const phase = this.travelProgress \/ this.travelDuration;\r\n\r\n                const loadingOverlay = document.getElementById(`loading_${INSTANCE_ID}`);\r\n\r\n                if (phase < 0.4) { \r\n                    if(loadingOverlay) loadingOverlay.style.opacity = (phase \/ 0.4).toString();\r\n                } else if (phase >= 0.4 && phase < 0.6) { \r\n                    if (!this.sceneSwapped) {\r\n                        this.changeEnvironment(this.targetPlanet);\r\n                        this.sceneSwapped = true;\r\n                    }\r\n                } else if (phase >= 0.6 && phase <= 1.0) { \r\n                     if(loadingOverlay) loadingOverlay.style.opacity = (1.0 - ((phase - 0.6) \/ 0.4)).toString();\r\n                } else { \r\n                    this.isTraveling = false;\r\n                    this.travelProgress = 0;\r\n                    this.sceneSwapped = false;\r\n                    this.currentPlanet = this.targetPlanet;\r\n                    if(loadingOverlay) loadingOverlay.style.display = 'none';\r\n                    TerminalLogger.log(`[TRAVEL] Arrived at ${this.currentPlanet}.`, 'succ');\r\n                }\r\n            }\r\n            \r\n            changeEnvironment(planetName) {\r\n                const config = this.planetConfigs[planetName];\r\n                if (!config) {\r\n                     TerminalLogger.log(`[TRAVEL] Unknown destination: ${planetName}`, 'err');\r\n                     return;\r\n                }\r\n\r\n                const scene = this.manager.scene;\r\n                scene.fog.color.set(config.fogColor);\r\n                scene.fog.density = config.fogDensity;\r\n\r\n                texLoader.load(getBustUrl(config.skyTexture), tex => {\r\n                    tex.mapping = THREE.EquirectangularReflectionMapping;\r\n                    scene.background = tex;\r\n                    scene.environment = this.manager.pmremGenerator.fromEquirectangular(tex).texture;\r\n                });\r\n                \r\n                const floor = this.manager.groupMap.floor;\r\n                if (floor && floor.material) {\r\n                     texLoader.load(getBustUrl(config.floorTexture), tex => {\r\n                        tex.wrapS = tex.wrapT = THREE.RepeatWrapping;\r\n                        tex.repeat.set(1, 1); \r\n                        floor.material.map = tex;\r\n                        floor.material.needsUpdate = true;\r\n                    });\r\n                }\r\n                \r\n                if (this.manager.groupMap.city) this.manager.groupMap.city.visible = config.showCity;\r\n                if (this.manager.grass) this.manager.grass.visible = config.showCity;\r\n                if (this.manager.groupMap.monorail_system) this.manager.groupMap.monorail_system.visible = config.showCity;\r\n                if (this.manager.groupMap.sky_highway) this.manager.groupMap.sky_highway.visible = config.showCity;\r\n            }\r\n        }\r\n\r\n        class MetaverseManager {\r\n            constructor() {\r\n                this.scene = new THREE.Scene();\r\n                this.camera = new THREE.PerspectiveCamera(70, window.innerWidth \/ window.innerHeight, 10, 200000);\r\n\r\n                this.lensGroup = new THREE.Group();\r\n                this.camera.add(this.lensGroup);\r\n                this.scene.add(this.camera);\r\n\r\n                this.renderer = new THREE.WebGLRenderer({\r\n                    antialias: window.VMP_CONFIG.hwAntialias === 'yes',\r\n                    alpha: true,\r\n                    precision: \"highp\",\r\n                    logarithmicDepthBuffer: true,\r\n                    powerPreference: \"high-performance\",\r\n                    stencil: false,\r\n                    depth: true\r\n                });\r\n\r\n                this.renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1);\r\n                this.renderer.outputEncoding = THREE.sRGBEncoding;\r\n                this.renderer.toneMapping = THREE.ACESFilmicToneMapping;\r\n                this.renderer.toneMappingExposure = 1.0;\r\n                this.renderer.shadowMap.enabled = window.VMP_CONFIG.hwShadows === 'yes';\r\n                this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;\r\n                this.renderer.xr.enabled = true;\r\n\r\n                this.pmremGenerator = new THREE.PMREMGenerator(this.renderer);\r\n                this.pmremGenerator.compileEquirectangularShader();\r\n\r\n                this.calibrator = new HardwareCalibrator(this.renderer);\r\n                this.clock = new THREE.Clock();\r\n                this.timeElapsed = 0;\r\n                this.fpsCap = 60;\r\n                this.lastFrameTime = 0;\r\n\r\n                const parseNum = (str) => { const n = parseFloat(String(str).replace(\/,\/g, '')); return isNaN(n) ? 0 : n; };\r\n                this.economy = {\r\n                    president: parseNum(window.VMP_CONFIG.budgetPresident),\r\n                    mayor: parseNum(window.VMP_CONFIG.budgetMayor),\r\n                    wallSt: 0, crypto: 0, ocean: 0, realEstate: 0, animals: 0,\r\n                    builders: 0, engineers: 0, plumbers: 0\r\n                };\r\n\r\n                this.entities = {\r\n                    rabbits:[], birds:[], butterflies:[], fishes:[], cars:[], pedestrians:[], angels:[], planets:[],\r\n                    sharks:[], whales:[], buses: [], aircraft:[], boats:[], hovercars:[], trains:[],\r\n                    workers: []\r\n                };\r\n\r\n                this.doors =[];\r\n                this.dog1 = null; this.dog2 = null;\r\n                this.cityBuildings =[];\r\n                this.collidableMeshes =[]; \r\n                this.isInPlayMode = false;\r\n                this.isDrivingCar = false; \r\n                this.laserBeam = null;\r\n                this.groupMap = {};\r\n                this.mb1Mesh = null; this.mb2Mesh = null;\r\n                this.roofLights =[]; this.waterPipes =[];\r\n                this.cityWorker = null; this.isAssemblingCity = false; this.cityAssemblyGenerator = null;\r\n                this.trafficLightSystem =[]; \r\n\r\n                this.raycaster = new THREE.Raycaster();\r\n                this.mouse = new THREE.Vector2();\r\n\r\n                this.isRockoTransformed = false;\r\n                this.isRockoOperating = false;\r\n                this.isRidingCoaster = false;\r\n\r\n                this.playerCar = new THREE.Group();\r\n                this.playerCar.position.set(0, 0, -2800); \/\/ Park behind sanctuary\r\n                this.carPos = new THREE.Vector2(0, 0); \r\n                this.carHeading = 0;\r\n                this.carSpeed = 0;\r\n                this.scene.add(this.playerCar);\r\n\r\n                const loadRockoTex = (url) => {\r\n                    if (url) { return new THREE.MeshStandardMaterial({ map: texLoader.load(getBustUrl(url)), roughness: 0.3 }); } \r\n                    else { return new THREE.MeshStandardMaterial({ color: 0x88ccff, roughness: 0.3, metalness: 0.8 }); }\r\n                };\r\n                \r\n                this.rockoMats =[\r\n                    loadRockoTex(window.VMP_CONFIG.rockoTex1), loadRockoTex(window.VMP_CONFIG.rockoTex2),\r\n                    loadRockoTex(window.VMP_CONFIG.rockoTex3), loadRockoTex(window.VMP_CONFIG.rockoTex4),\r\n                    loadRockoTex(window.VMP_CONFIG.rockoTex5)\r\n                ];\r\n                this.rockoTexIndex = 0;\r\n\r\n                setInterval(() => { this.updateDynamicEconomyUI(); }, 2000);\r\n\r\n                this.seasonNames =['FALL', 'WINTER', 'SPRING', 'SUMMER'];\r\n                this.seasonIndex = 0;\r\n                this.seasonTimer = 0;\r\n                this.seasonDuration = 60;\r\n\r\n                this.weatherSystem = null; this.weatherMat = null;\r\n                this.rainSystem = null; this.rainMat = null;\r\n\r\n                if(window.VMP_CONFIG.mornBg) {\r\n                    this.mornTex = texLoader.load(getBustUrl(window.VMP_CONFIG.mornBg));\r\n                    this.mornTex.mapping = THREE.EquirectangularReflectionMapping;\r\n                }\r\n                if(window.VMP_CONFIG.aftBg) {\r\n                    this.aftTex = texLoader.load(getBustUrl(window.VMP_CONFIG.aftBg));\r\n                    this.aftTex.mapping = THREE.EquirectangularReflectionMapping;\r\n                }\r\n\r\n                this.trafficNodes =[]; this.font = null; \r\n                this.currentCorps =[];\r\n            }\r\n\r\n            async init() {\r\n                try {\r\n                    try {\r\n                        const fontLoader = new FontLoader();\r\n                        this.font = await fontLoader.loadAsync('https:\/\/unpkg.com\/three@0.138.3\/examples\/fonts\/helvetiker_regular.typeface.json');\r\n                    } catch(e) { TerminalLogger.log(\"Font failed to load.\", \"err\"); }\r\n\r\n                    const container = document.getElementById(`webgl_${INSTANCE_ID}`);\r\n                    let rect = container.getBoundingClientRect();\r\n                    this.renderer.setSize(rect.width, rect.height);\r\n                    container.appendChild(this.renderer.domElement);\r\n\r\n                    const vrBtnContainer = document.getElementById(`vr_btn_container_${INSTANCE_ID}`);\r\n                    if(vrBtnContainer) vrBtnContainer.appendChild(VRButton.createButton(this.renderer));\r\n\r\n                    this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);\r\n                    this.camera.position.set(window.VMP_CONFIG.camPosX, window.VMP_CONFIG.camPosY, window.VMP_CONFIG.camPosZ);\r\n                    this.orbitControls.target.set(0, 50, -500);\r\n                    this.orbitControls.update();\r\n\r\n                    this.transformControl = new TransformControls(this.camera, this.renderer.domElement);\r\n                    this.transformControl.addEventListener('dragging-changed', (e) => { this.orbitControls.enabled = !e.value; });\r\n                    this.scene.add(this.transformControl);\r\n                    \r\n                    this.ui = new MasterViewportUI(this);\r\n\r\n                    this.renderer.domElement.addEventListener('dblclick', (e) => {\r\n                        const bRect = this.renderer.domElement.getBoundingClientRect();\r\n                        this.mouse.x = ((e.clientX - bRect.left) \/ bRect.width) * 2 - 1;\r\n                        this.mouse.y = -((e.clientY - bRect.top) \/ bRect.height) * 2 + 1;\r\n                        \r\n                        \/\/ Universal selection enhancement - increase threshold so tiny objects (particles) can be clicked\r\n                        this.raycaster.params.Points.threshold = 100;\r\n                        this.raycaster.params.Line.threshold = 10;\r\n                        \r\n                        this.raycaster.setFromCamera(this.mouse, this.camera);\r\n                        const intersects = this.raycaster.intersectObjects(this.scene.children, true);\r\n\r\n                        if(intersects.length > 0) {\r\n                            let obj = intersects[0].object;\r\n                            \r\n                            \/\/ Traverse up to find a logical group, but ignore the TransformControl itself\r\n                            while(obj.parent && obj.parent !== this.scene && !obj.name && !obj.userData.isSelectable) { \r\n                                if(obj.type === 'TransformControlsPlane' || obj.type === 'TransformControlsGizmo') return;\r\n                                obj = obj.parent; \r\n                            }\r\n                            \r\n                            \/\/ INTERACTIVE RIDES CHECK\r\n                            if (obj.name === \"Coaster_Cart\" || (obj.parent && obj.parent.name === \"Coaster_Cart\")) {\r\n                                this.isRidingCoaster = !this.isRidingCoaster;\r\n                                if (this.isRidingCoaster) {\r\n                                    this.preRidePos = this.camera.position.clone();\r\n                                    this.playerControls.unlock();\r\n                                    TerminalLogger.log(\"[SYS] Riding the coaster! Double-click cart again to exit.\", \"succ\");\r\n                                } else {\r\n                                    this.camera.position.copy(this.preRidePos);\r\n                                    this.camera.rotation.set(0,0,0);\r\n                                    TerminalLogger.log(\"[SYS] Exited ride.\", \"sys\");\r\n                                }\r\n                                return;\r\n                            }\r\n\r\n                            \/\/ Only attach if it's a real scene object\r\n                            if(obj.type !== 'TransformControlsPlane') {\r\n                                this.transformControl.attach(obj);\r\n                                this.ui.setSelectedMesh(obj);\r\n                                TerminalLogger.log(`Selected: ${obj.name || obj.type || 'Object'}`, 'sys');\r\n                            }\r\n                        } else {\r\n                            this.transformControl.detach(); \r\n                            this.ui.setSelectedMesh(null);\r\n                        }\r\n                    });\r\n\r\n                    updateLoadStatus(\"Loading Base Environment...\");\r\n                    this.setupLighting();\r\n                    await yieldFrame(); \r\n\r\n                    await this.buildEnvironment();\r\n                    this.buildSanctuaryPark();\r\n                    \r\n                    updateLoadStatus(\"Loading Cosmological Elements...\");\r\n                    await yieldFrame(); \r\n                    this.buildSolarSystem();\r\n                    this.buildZodiacs();\r\n                    this.buildGuardianAngels();\r\n                    \r\n                    updateLoadStatus(\"Building Tech Infrastructure...\");\r\n                    await yieldFrame(); \r\n                    this.createCentralEcosystem();\r\n                    this.buildInfrastructure();\r\n                    this.buildVolumetricClouds();\r\n                    this.buildPool();\r\n                    \r\n                    this.interplanetaryTravel = new InterplanetaryTravel(this);\r\n                    this.initControls();\r\n                    \r\n                    this.animate(performance.now());\r\n                    new ResizeObserver(() => this.onWindowResize()).observe(container);\r\n\r\n                    updateLoadStatus(\"Assembling Matrix Geometry...\");\r\n                    await this.populateWorld(5);\r\n                    \r\n                    \/\/ Initialize Player Car Mesh\r\n                                  if(window.VMP_CONFIG.modelCar) {\r\n                        loadCustomModel(window.VMP_CONFIG.modelCar, obj => { \r\n                            if(obj) { \r\n                                this.playerCar.add(obj); \r\n                                const initialSpherePos = wrapToPlanet(this.carPos.x, this.carPos.y, 20);\r\n                                this.playerCar.position.copy(initialSpherePos);\r\n                                alignToPlanet(this.playerCar);\r\n                            } \r\n                        }, 3); \/\/ Changed from 15 to 3 to make the Lego car normal size\r\n                    } else {\r\n                        const box = new THREE.Mesh(new THREE.BoxGeometry(20,10,40), new THREE.MeshStandardMaterial({color:0xff0000}));\r\n                        box.position.y = 10;\r\n                        this.playerCar.add(box);\r\n                        const initialSpherePos = wrapToPlanet(this.carPos.x, this.carPos.y, 20);\r\n                        this.playerCar.position.copy(initialSpherePos);\r\n                        alignToPlanet(this.playerCar);\r\n                    }\r\n                    \r\n                    \/\/ Add AI Driver to Car\r\n                    const driver = buildProceduralHuman('adult', null, 'dad');\r\n                    driver.position.set(-2, 10, 5); \/\/ Driver seat\r\n                    driver.scale.setScalar(0.7);\r\n                    driver.children[0].children[0].userData.armL.rotation.x = -Math.PI \/ 4;\r\n                    driver.children[0].children[0].userData.armR.rotation.x = -Math.PI \/ 4;\r\n                    driver.children[0].children[0].userData.legL.rotation.x = Math.PI \/ 4;\r\n                    driver.children[0].children[0].userData.legR.rotation.x = Math.PI \/ 4;\r\n                    this.playerCar.add(driver);\r\n\r\n                    const overlay = document.getElementById(`loading_${INSTANCE_ID}`);\r\n                    if(overlay) {\r\n                        overlay.style.pointerEvents = 'none';\r\n                        setTimeout(() => {\r\n                            overlay.style.opacity = '0';\r\n                            setTimeout(() => { overlay.style.display = 'none'; }, 500);\r\n                        }, 100);\r\n                    }\r\n\r\n                } catch (error) {\r\n                    console.error(\"VMP Engine Error during initialization:\", error);\r\n                    TerminalLogger.log(`[ERR] Loading failed: ${error.message}`, \"err\");\r\n                    const overlay = document.getElementById(`loading_${INSTANCE_ID}`);\r\n                    if (overlay) overlay.style.display = 'none';\r\n                }\r\n            }\r\n            \r\n            applyBendModifier(mesh, axis = 'x', angle = Math.PI \/ 4) {\r\n                const geometry = mesh.geometry;\r\n                const position = geometry.attributes.position;\r\n                const axis1 = axis === 'x' ? 'y' : 'x';\r\n                const axis2 = 'z';\r\n\r\n                const box = new THREE.Box3().setFromObject(mesh);\r\n                const size = box.getSize(new THREE.Vector3());\r\n                const width = axis === 'x' ? size.x : size.z;\r\n                \r\n                if(width === 0) return;\r\n\r\n                const center = box.getCenter(new THREE.Vector3());\r\n                mesh.worldToLocal(center);\r\n\r\n                const radius = width \/ angle;\r\n                const anglePerUnit = angle \/ width;\r\n\r\n                for (let i = 0; i < position.count; i++) {\r\n                    const x = position.getX(i) - center.x;\r\n                    const y = position.getY(i) - center.y;\r\n                    const z = position.getZ(i) - center.z;\r\n\r\n                    const currentAngle = x * anglePerUnit;\r\n                    const newX = Math.sin(currentAngle) * (radius + z);\r\n                    const newZ = -Math.cos(currentAngle) * (radius + z) + radius;\r\n\r\n                    position.setX(i, newX + center.x);\r\n                    position.setZ(i, newZ + center.z);\r\n                }\r\n                position.needsUpdate = true;\r\n                geometry.computeVertexNormals();\r\n            }\r\n\r\n            setupLighting() {\r\n                this.scene.fog = new THREE.FogExp2(window.VMP_CONFIG.fogColor, window.VMP_CONFIG.fogDensity);\r\n\r\n                if (window.VMP_CONFIG.envBg) {\r\n                    texLoader.load(getBustUrl(window.VMP_CONFIG.envBg), tex => {\r\n                        if (tex.image) {\r\n                           tex.mapping = THREE.EquirectangularReflectionMapping;\r\n                           this.scene.background = tex;\r\n                           this.scene.environment = this.pmremGenerator.fromEquirectangular(tex).texture;\r\n                        }\r\n                    });\r\n                }\r\n\r\n                this.hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6); \r\n                this.scene.add(this.hemiLight);\r\n                \r\n                this.sunLight = new THREE.DirectionalLight(0xffffff, 1.0);\r\n                if (window.VMP_CONFIG.hwShadows === 'yes') {\r\n                    this.sunLight.castShadow = true;\r\n                    this.sunLight.shadow.mapSize.width = 1024; \r\n                    this.sunLight.shadow.mapSize.height = 1024; \r\n                    this.sunLight.shadow.camera.near = 100; this.sunLight.shadow.camera.far = 155000;\r\n                    this.sunLight.shadow.camera.left = -55000; this.sunLight.shadow.camera.right = 55000;\r\n                    this.sunLight.shadow.camera.top = 55000; this.sunLight.shadow.camera.bottom = -55000;\r\n                    this.sunLight.shadow.bias = -0.001;\r\n                }\r\n                this.scene.add(this.sunLight);\r\n\r\n                this.moonLight = new THREE.DirectionalLight(0x88bbff, 0.0); \r\n                this.moonLight.castShadow = false; \r\n                this.scene.add(this.moonLight);\r\n                \r\n                this.ambientLight = new THREE.AmbientLight(0xffffff, 0.4); \r\n                this.scene.add(this.ambientLight);\r\n                \r\n                const sunGeo = new THREE.SphereGeometry(4500,64, 64); const sunMat = new THREE.MeshBasicMaterial({color: 0xffffaa});\r\n                this.sunMesh = new THREE.Mesh(sunGeo, sunMat);\r\n                if(window.VMP_CONFIG.texSun) { texLoader.load(getBustUrl(window.VMP_CONFIG.texSun), t => { this.sunMesh.material.map = t; this.sunMesh.material.color.setHex(0xffffff); this.sunMesh.material.needsUpdate = true; }); }\r\n                this.scene.add(this.sunMesh);\r\n\r\n                const moonGeo = new THREE.SphereGeometry(3000, 64, 64); const moonMat = new THREE.MeshBasicMaterial({color: 0xcceeff});\r\n                this.moonMesh = new THREE.Mesh(moonGeo, moonMat);\r\n                if(window.VMP_CONFIG.texMoon) { texLoader.load(getBustUrl(window.VMP_CONFIG.texMoon), t => { this.moonMesh.material.map = t; this.moonMesh.material.color.setHex(0xffffff); this.moonMesh.material.needsUpdate = true; }); }\r\n                this.scene.add(this.moonMesh);                \r\n                \r\n                const starGeo = new THREE.BufferGeometry(); const starPos =[];\r\n                for(let i = 0; i < 5000; i++) { starPos.push((Math.random() - 0.5) * 180000, Math.random() * 40000 + 20000, (Math.random() - 0.5) * 180000); }\r\n                starGeo.setAttribute('position', new THREE.Float32BufferAttribute(starPos, 3));\r\n                this.starMat = new THREE.PointsMaterial({ color: 0xffffff, size: 80, transparent: true, opacity: 0 });\r\n                this.stars = new THREE.Points(starGeo, this.starMat); this.scene.add(this.stars);\r\n\r\n                const nightGeo = new THREE.SphereGeometry(90000, 64, 64); const nightMat = new THREE.MeshStandardMaterial({ color: 0x020408, side: THREE.BackSide, transparent: true, opacity: 0, roughness: 0.8 });\r\n                if(window.VMP_CONFIG.nightBump) { texLoader.load(getBustUrl(window.VMP_CONFIG.nightBump), tex => { tex.wrapS = tex.wrapT = THREE.RepeatWrapping; tex.repeat.set(10, 10); nightMat.bumpMap = tex; nightMat.bumpScale = 150.0; nightMat.needsUpdate = true; }); }\r\n                this.nightDome = new THREE.Mesh(nightGeo, nightMat); this.scene.add(this.nightDome);\r\n\r\n                this.mb1 = new Motherboard1(`mbCanvas1_${INSTANCE_ID}`);\r\n                this.mb2 = new Motherboard2(`mbCanvas2_${INSTANCE_ID}`);\r\n                this.cmd = new CommandCenterScreen(`cmdScreen_${INSTANCE_ID}`);\r\n                this.gpuOrb = new GPUQuantumOrb();\r\n                this.groupMap.orb = this.gpuOrb.group;\r\n            }\r\n\r\n            async populateWorld(densityPercent) {\r\n                await this.initEarthAnimals(densityPercent);\r\n                if (window.VMP_CONFIG.grassHeight > 0) {\r\n                    await this.buildProceduralGrass(densityPercent);\r\n                    this.buildProceduralFlowers();\r\n                }\r\n                this.buildDogs();\r\n                this.buildWeatherSystem();\r\n                this.buildMiamiBeachAndOcean();\r\n                \r\n                if (window.VMP_CONFIG.geminiCity === 'yes') {\r\n                    this.startCityRebuild(densityPercent);\r\n                }\r\n                \r\n                this.buildAdvancedTransport();\r\n                this.buildCustomPolygons();\r\n                this.buildUnderwaterScene(); \r\n                TerminalLogger.log(\"[WORLD] All procedural assets deployed.\", \"succ\");\r\n            }\r\n\r\n            applyWPTransform(mesh, configKey, bx = 0, by = 0, bz = 0, rx = 0, ry = 0, rz = 0) {\r\n                mesh.userData.configKey = configKey;\r\n                mesh.userData.baseTransform = { bx, by, bz, rx, ry, rz };\r\n                \r\n                let fx = bx, fy = by, fz = bz;\r\n                \r\n                if(window.VMP_CONFIG.transforms && window.VMP_CONFIG.transforms[configKey]) {\r\n                    const t = window.VMP_CONFIG.transforms[configKey];\r\n                    fx += t.pos_x; fy += t.pos_y; fz += t.pos_z;\r\n                    mesh.rotation.set(rx + t.rot_x, ry + t.rot_y, rz + t.rot_z);\r\n                    mesh.scale.set(Math.max(0.01, t.scale_x), Math.max(0.01, t.scale_y), Math.max(0.01, t.scale_z));\r\n                } else {\r\n                    mesh.rotation.set(rx, ry, rz);\r\n                }\r\n\r\n                \/\/ If not floor, apply spherical wrapping\r\n                if (configKey !== 'floor') {\r\n                    const sphericalPos = wrapToPlanet(fx, fz, fy);\r\n                    mesh.position.copy(sphericalPos);\r\n                    alignToPlanet(mesh);\r\n                } else {\r\n                    mesh.position.set(fx, fy, fz);\r\n                }\r\n            }\r\n\r\n            spawnTempParticles(pos, colorHex, count = 200, size = 5, duration = 2) {\r\n                const geo = new THREE.BufferGeometry();\r\n                const pts =[];\r\n                for(let i = 0; i < count; i++) {\r\n                    pts.push((Math.random() - 0.5) * 50, (Math.random() - 0.5) * 50, (Math.random() - 0.5) * 50);\r\n                }\r\n                geo.setAttribute('position', new THREE.Float32BufferAttribute(pts, 3));\r\n                const sys = new THREE.Points(geo, new THREE.PointsMaterial({ color: colorHex, size: size, transparent: true, blending: THREE.AdditiveBlending }));\r\n                sys.position.copy(pos);\r\n                this.scene.add(sys);\r\n                let time = 0;\r\n                const anim = setInterval(() => {\r\n                    time += 0.05;\r\n                    sys.rotation.y += 0.05;\r\n                    sys.material.opacity = 1 - (time \/ duration);\r\n                    if(time >= duration) {\r\n                        clearInterval(anim);\r\n                        this.scene.remove(sys);\r\n                        if(geo) geo.dispose();\r\n                    }\r\n                }, 50);\r\n            }\r\n\r\n\r\n            async buildEnvironment() {\r\n                const floorMat = loadAdvancedMat(\r\n                    window.VMP_CONFIG.texCytron || window.VMP_CONFIG.floorDiff, \r\n                    window.VMP_CONFIG.floorBump, \r\n                    0xffffff, \r\n                    window.VMP_CONFIG.floorRough, \r\n                    window.VMP_CONFIG.floorMetal, \r\n                    window.VMP_CONFIG.floorScaleX,\r\n                    window.VMP_CONFIG.floorScaleY,\r\n                    window.VMP_CONFIG.floorRotation,\r\n                    window.VMP_CONFIG.floorOffsetX,\r\n                    window.VMP_CONFIG.floorOffsetY\r\n                );\r\n                \r\n                const floorGeo = new THREE.SphereGeometry(PLANET_RADIUS, 256, 256);\r\n\r\n                const floor = new THREE.Mesh(floorGeo, floorMat);\r\n                floor.receiveShadow = true;\r\n                floor.userData.isSolidGround = true;\r\n                this.groupMap.floor = floor;\r\n                \r\n                this.applyWPTransform(floor, 'floor', PLANET_CENTER.x, PLANET_CENTER.y - 2, PLANET_CENTER.z, 0, 0, 0); \r\n                this.scene.add(floor);\r\n                this.collidableMeshes.push(floor);\r\n\r\n                const cl1 = new THREE.PointLight(0xffeedd, 1.0, 5000); cl1.position.set(-2400, 100, 0); this.scene.add(cl1);\r\n                const cl2 = new THREE.PointLight(0xffeedd, 1.0, 5000); cl2.position.set(2400, 100, 0); this.scene.add(cl2);\r\n                const cl3 = new THREE.PointLight(0xffeedd, 1.0, 5000); cl3.position.set(0, 100, -2400); this.scene.add(cl3);\r\n\r\n                const extWallLMat = loadAdvancedMat(window.VMP_CONFIG.extWallLeftDiff, window.VMP_CONFIG.extWallLeftDiff, 0x444444, window.VMP_CONFIG.wallLeftRough, window.VMP_CONFIG.wallLeftMetal, window.VMP_CONFIG.wallLeftScale, window.VMP_CONFIG.wallLeftScale, window.VMP_CONFIG.extWallLeftRotation);\r\n                const extWallRMat = loadAdvancedMat(window.VMP_CONFIG.extWallRightDiff, window.VMP_CONFIG.extWallRightDiff, 0x444444, window.VMP_CONFIG.wallRightRough, window.VMP_CONFIG.wallRightMetal, window.VMP_CONFIG.wallRightScale, window.VMP_CONFIG.wallRightScale, window.VMP_CONFIG.extWallRightRotation);\r\n                const extWallBMat = loadAdvancedMat(window.VMP_CONFIG.extWallBackDiff, window.VMP_CONFIG.extWallBackDiff, 0x444444, window.VMP_CONFIG.wallBackRough, window.VMP_CONFIG.wallBackMetal, window.VMP_CONFIG.wallBackScale, window.VMP_CONFIG.wallBackScale, window.VMP_CONFIG.extWallBackRotation);\r\n\r\n                const wLGeo = new THREE.BoxGeometry(100, 1500, 5000, 1, 1, 64);\r\n                bendBoxGeometryToPlanet(wLGeo, 750);\r\n                const wL = new THREE.Mesh(wLGeo, extWallLMat);\r\n                wL.userData.isSelectable = true; wL.name = \"Left_Sanctuary_Wall\";\r\n                wL.userData.isWall = true; this.collidableMeshes.push(wL);\r\n                this.groupMap.wall_left = wL;\r\n                this.applyWPTransform(wL, 'wall_left', -2500, 0, 0, 0, 0, 0);\r\n                this.scene.add(wL);\r\n\r\n                const wRGeo = new THREE.BoxGeometry(100, 1500, 5000, 1, 1, 64);\r\n                bendBoxGeometryToPlanet(wRGeo, 750);\r\n                const wR = new THREE.Mesh(wRGeo, extWallRMat);\r\n                wR.userData.isSelectable = true; wR.name = \"Right_Sanctuary_Wall\";\r\n                wR.userData.isWall = true; this.collidableMeshes.push(wR);\r\n                this.groupMap.wall_right = wR;\r\n                this.applyWPTransform(wR, 'wall_right', 2500, 0, 0, 0, 0, 0);\r\n                this.scene.add(wR);\r\n\r\n                const wBGeo = new THREE.BoxGeometry(5000, 1500, 100, 64, 1, 1);\r\n                bendBoxGeometryToPlanet(wBGeo, 750);\r\n                const wB = new THREE.Mesh(wBGeo, extWallBMat);\r\n                wB.userData.isSelectable = true; wB.name = \"Back_Sanctuary_Wall\";\r\n                wB.userData.isWall = true; this.collidableMeshes.push(wB);\r\n                this.groupMap.wall_back = wB;\r\n                this.applyWPTransform(wB, 'wall_back', 0, 0, -2500, 0, 0, 0);\r\n                this.scene.add(wB);\r\n\r\n                this.buildEgyptianPyramidComplex();\r\n                this.buildCurvedSurroundings();\r\n                \r\n                this.buildThemePark();\r\n                this.buildGolfCourse();\r\n                this.buildSchoolAndHospital();\r\n                this.buildSatellites();\r\n                this.buildUndergroundPipes();\r\n                this.buildCryptoMiners();\r\n            }\r\n\r\n            buildThemePark() {\r\n                const parkGrp = new THREE.Group();\r\n                parkGrp.name = \"Theme_Park_Complex\";\r\n                parkGrp.scale.setScalar(0.1);\r\n                const parkSpread = 4000;\r\n\r\n                const tpGeo = new THREE.CylinderGeometry(parkSpread * 1.5, parkSpread * 1.5, 10, 64);\r\n                const tpConcrete = new THREE.Mesh(tpGeo, new THREE.MeshStandardMaterial({color:0x555555, roughness: 1.0}));\r\n                tpConcrete.position.set(0, -4, 0);\r\n                tpConcrete.receiveShadow = true;\r\n                tpConcrete.userData.isSelectable = true;\r\n                tpConcrete.name = \"Theme_Park_Concrete_Pad\";\r\n                parkGrp.add(tpConcrete);\r\n\r\n                this.ferrisWheel = new THREE.Group();\r\n                this.ferrisWheel.userData.isSelectable = true; \r\n                this.ferrisWheel.name = \"Ferris_Wheel\";\r\n                if(window.VMP_CONFIG.modelRideFerris) {\r\n                    loadCustomModel(window.VMP_CONFIG.modelRideFerris, obj => { if(obj) { obj.scale.setScalar(100); this.ferrisWheel.add(obj); } });\r\n                } else {\r\n                    const wheelMat = new THREE.MeshStandardMaterial({color: 0xff0055, metalness: 0.8, roughness: 0.2});\r\n                    const wheel = new THREE.Mesh(new THREE.TorusGeometry(300, 10, 16, 64), wheelMat);\r\n                    const spokeMat = new THREE.MeshStandardMaterial({color: 0xeeeeee});\r\n                    for(let i=0; i<12; i++) {\r\n                        const spoke = new THREE.Mesh(new THREE.CylinderGeometry(5, 5, 600), spokeMat);\r\n                        spoke.rotation.z = (Math.PI \/ 6) * i;\r\n                        wheel.add(spoke);\r\n                        const cart = new THREE.Mesh(new THREE.BoxGeometry(40, 40, 40), new THREE.MeshStandardMaterial({color: 0x00e5ff}));\r\n                        cart.position.set(Math.cos((Math.PI\/6)*i)*300, Math.sin((Math.PI\/6)*i)*300, 0);\r\n                        wheel.add(cart);\r\n                    }\r\n                    this.ferrisWheel.add(wheel);\r\n                    const stand1 = new THREE.Mesh(new THREE.CylinderGeometry(20, 40, 400), wheelMat); stand1.position.set(0, -150, -50); stand1.rotation.x = -0.2;\r\n                    const stand2 = new THREE.Mesh(new THREE.CylinderGeometry(20, 40, 400), wheelMat); stand2.position.set(0, -150, 50); stand2.rotation.x = 0.2;\r\n                    this.ferrisWheel.add(stand1, stand2);\r\n                }\r\n                this.ferrisWheel.position.set(-1500, 350, -1000);\r\n                parkGrp.add(this.ferrisWheel);\r\n\r\n                const coasterGrp = new THREE.Group();\r\n                coasterGrp.userData.isSelectable = true;\r\n                coasterGrp.name = \"Roller_Coaster_Track\";\r\n                coasterGrp.position.set(1000, 0, 500);\r\n                \r\n                const trackCurve = new THREE.CatmullRomCurve3([\r\n                    new THREE.Vector3(-800, 50, -800), new THREE.Vector3(-400, 800, -400),\r\n                    new THREE.Vector3(400, 200, 400), new THREE.Vector3(800, 600, 800),\r\n                    new THREE.Vector3(1200, 50, 0), new THREE.Vector3(600, 400, -800),\r\n                    new THREE.Vector3(-800, 50, -800)\r\n                ], true); \r\n\r\n                if(window.VMP_CONFIG.modelRideCoaster) {\r\n                    loadCustomModel(window.VMP_CONFIG.modelRideCoaster, obj => { if(obj) { obj.scale.setScalar(50); coasterGrp.add(obj); } });\r\n                } else {\r\n                    const trackMesh = new THREE.Mesh(new THREE.TubeGeometry(trackCurve, 128, 12, 8, true), new THREE.MeshStandardMaterial({color: 0xaa00ff, metalness: 0.9}));\r\n                    coasterGrp.add(trackMesh);\r\n                    const pts = trackCurve.getPoints(20);\r\n                    const supMat = new THREE.MeshStandardMaterial({color: 0x555555});\r\n                    pts.forEach(pt => {\r\n                        if (pt.y > 20) {\r\n                            const sup = new THREE.Mesh(new THREE.CylinderGeometry(5, 5, pt.y), supMat);\r\n                            sup.position.set(pt.x, pt.y\/2, pt.z);\r\n                            coasterGrp.add(sup);\r\n                        }\r\n                    });\r\n                }\r\n\r\n                this.coasterCart = new THREE.Group();\r\n                this.coasterCart.name = \"Coaster_Cart\";\r\n                this.coasterCart.userData.isSelectable = true; \r\n                \r\n                if(window.VMP_CONFIG.modelRideCart) {\r\n                     loadCustomModel(window.VMP_CONFIG.modelRideCart, obj => { if(obj) { obj.scale.setScalar(10); this.coasterCart.add(obj); } });\r\n                } else {\r\n                    const cartMesh = new THREE.Mesh(new THREE.BoxGeometry(50, 20, 100), new THREE.MeshStandardMaterial({color: 0xffaa00}));\r\n                    this.coasterCart.add(cartMesh);\r\n                    \r\n                    const rider1 = buildProceduralHuman('child', null, 'son'); rider1.position.set(0, 10, 0); this.coasterCart.add(rider1); \r\n                    const rider2 = buildProceduralHuman('adult', null, 'dad'); rider2.position.set(0, 10, -30); this.coasterCart.add(rider2);\r\n                }\r\n                \r\n                coasterGrp.add(this.coasterCart);\r\n                this.coasterProgress = 0;\r\n                this.coasterCurve = trackCurve;\r\n                parkGrp.add(coasterGrp);\r\n\r\n                for(let s=0; s<10; s++) {\r\n                    const standGrp = new THREE.Group();\r\n                    standGrp.userData.isSelectable = true;\r\n                    standGrp.name = \"Park_Vendor_Booth\";\r\n                    if(window.VMP_CONFIG.modelBooth) {\r\n                        loadCustomModel(window.VMP_CONFIG.modelBooth, obj => { if(obj) { obj.scale.setScalar(20); standGrp.add(obj); } });\r\n                    } else {\r\n                        const standBase = new THREE.Mesh(new THREE.BoxGeometry(100, 50, 60), new THREE.MeshStandardMaterial({color: 0xffffff}));\r\n                        const standRoof = new THREE.Mesh(new THREE.ConeGeometry(80, 40, 4), new THREE.MeshStandardMaterial({color: 0xff00aa}));\r\n                        standRoof.position.y = 80; standRoof.rotation.y = Math.PI\/4;\r\n                        const candy = new THREE.Mesh(new THREE.SphereGeometry(15), new THREE.MeshStandardMaterial({color: 0xffccff, transparent: true, opacity: 0.8}));\r\n                        candy.position.set(0, 35, 0); standGrp.add(standBase, standRoof, candy);\r\n                        \r\n                        if(this.font) {\r\n                            const signGeo = new TextGeometry(s%2===0 ? \"TICKETS\" : \"CANDY\", { font: this.font, size: 10, height: 2 });\r\n                            signGeo.center();\r\n                            const sign = new THREE.Mesh(signGeo, new THREE.MeshStandardMaterial({color: 0x00e5ff, emissive: 0x00e5ff}));\r\n                            sign.position.set(0, 60, 30); standGrp.add(sign);\r\n                        }\r\n                    }\r\n                    standGrp.position.set((Math.random()-0.5)*parkSpread, 25, (Math.random()-0.5)*parkSpread); \r\n                    standGrp.rotation.y = Math.random() * Math.PI;\r\n                    parkGrp.add(standGrp);\r\n\r\n                    for(let line=0; line<3; line++) {\r\n                        const person = buildProceduralHuman(['mom', 'dad', 'son'][Math.floor(Math.random()*3)]);\r\n                        person.userData.isSelectable = true; person.name = \"Park_Guest\";\r\n                        const offsetDir = new THREE.Vector3(0,0,1).applyQuaternion(standGrp.quaternion);\r\n                        person.position.copy(standGrp.position).addScaledVector(offsetDir, 80 + (line*30));\r\n                        person.lookAt(standGrp.position);\r\n                        parkGrp.add(person);\r\n                    }\r\n                }\r\n\r\n                this.parkAttendees =[];\r\n                for(let i=0; i<30; i++) {\r\n                    const person = buildProceduralHuman(['mom', 'dad', 'son'][Math.floor(Math.random()*3)]);\r\n                    person.userData.isSelectable = true; person.name = \"Park_Wanderer\";\r\n                    person.position.set((Math.random()-0.5)*parkSpread, 0, (Math.random()-0.5)*parkSpread);\r\n                    person.userData.angle = Math.random() * Math.PI*2;\r\n                    person.userData.speed = 20;\r\n                    person.userData.isEating = Math.random() > 0.3;\r\n                    \r\n                    if (person.userData.isEating) {\r\n                        const cottonCandyGrp = new THREE.Group();\r\n                        const stick = new THREE.Mesh(new THREE.CylinderGeometry(0.5,0.5,10), new THREE.MeshBasicMaterial({color:0xffffff}));\r\n                        const fluff = new THREE.Mesh(new THREE.SphereGeometry(6), new THREE.MeshStandardMaterial({color:0xffccff, transparent:true, opacity:0.8}));\r\n                        fluff.position.y = 5; cottonCandyGrp.add(stick, fluff);\r\n                        cottonCandyGrp.position.set(3, 5, 4);\r\n                        cottonCandyGrp.rotation.x = Math.PI \/ 4;\r\n                        person.add(cottonCandyGrp);\r\n                    }\r\n                    parkGrp.add(person); this.parkAttendees.push(person);\r\n                }\r\n\r\n                this.groupMap.themepark = parkGrp;\r\n                this.applyWPTransform(parkGrp, 'themepark', -10000, 0, 17000, 0, 0, 0);\r\n                this.scene.add(parkGrp);\r\n                this.collidableMeshes.push(tpConcrete);\r\n            }\r\n\r\n            buildGolfCourse() {\r\n                const golfGrp = new THREE.Group();\r\n                golfGrp.name = \"Golf_Course_Root\";\r\n\r\n                const greenGeo = new THREE.PlaneGeometry(8000, 8000, 64, 64);\r\n                greenGeo.rotateX(-Math.PI \/ 2);\r\n                \r\n                const pos = greenGeo.attributes.position;\r\n                for(let i=0; i<pos.count; i++) { pos.setY(i, Math.sin(pos.getX(i)*0.01)*30 + Math.cos(pos.getZ(i)*0.01)*30); }\r\n                bendBoxGeometryToPlanet(greenGeo, 0); \r\n                \r\n                const green = new THREE.Mesh(greenGeo, new THREE.MeshStandardMaterial({color: 0x22aa22, roughness: 0.9}));\r\n                green.userData.isSelectable = true; green.name = \"Golf_Course_Green\";\r\n                golfGrp.add(green);\r\n                green.userData.isSolidGround = true;\r\n                this.collidableMeshes.push(green);\r\n\r\n                const house = new THREE.Mesh(new THREE.BoxGeometry(800, 300, 600), new THREE.MeshStandardMaterial({color: 0xffeedd, roughness: 0.4}));\r\n                house.userData.isSelectable = true; house.name = \"Clubhouse\";\r\n                house.position.copy(wrapToPlanet(0, -3000, 150)); alignToPlanet(house);\r\n                const roof = new THREE.Mesh(new THREE.ConeGeometry(600, 200, 4), new THREE.MeshStandardMaterial({color: 0x8b0000}));\r\n                roof.userData.isSelectable = true; roof.name = \"Clubhouse_Roof\";\r\n                roof.position.copy(wrapToPlanet(0, -3000, 400)); alignToPlanet(roof); roof.rotateY(Math.PI\/4);\r\n                golfGrp.add(house, roof);\r\n                house.userData.isCityBldg = true; this.collidableMeshes.push(house);\r\n\r\n                for(let i=0; i<18; i++) {\r\n                    const holeX = (Math.random()-0.5)*6000; const holeZ = (Math.random()-0.5)*5000;\r\n                    const sandTrap = new THREE.Mesh(new THREE.CircleGeometry(120, 16), new THREE.MeshStandardMaterial({color: 0xeeddaa}));\r\n                    sandTrap.userData.isSelectable = true; sandTrap.name = `Sand_Trap_${i}`;\r\n                    sandTrap.rotation.x = -Math.PI\/2; sandTrap.position.copy(wrapToPlanet(holeX + 150, holeZ + 150, 5)); alignToPlanet(sandTrap); golfGrp.add(sandTrap);\r\n\r\n                    const pole = new THREE.Mesh(new THREE.CylinderGeometry(2, 2, 100), new THREE.MeshStandardMaterial({color: 0xeeeeee}));\r\n                    pole.userData.isSelectable = true; pole.name = `Flag_Pole_${i}`;\r\n                    pole.position.copy(wrapToPlanet(holeX, holeZ, 50)); alignToPlanet(pole);\r\n                    const flag = new THREE.Mesh(new THREE.PlaneGeometry(40, 30), new THREE.MeshStandardMaterial({color: 0xff0000, side: THREE.DoubleSide}));\r\n                    flag.userData.isSelectable = true; flag.name = `Flag_${i}`;\r\n                    flag.position.copy(wrapToPlanet(holeX + 20, holeZ, 85)); alignToPlanet(flag); golfGrp.add(pole, flag);\r\n                }\r\n\r\n                this.golfers =[];\r\n                for(let i=0; i<50; i++) {\r\n                    const golfer = buildProceduralHuman(Math.random() > 0.5 ? 'dad' : 'mom'); \r\n                    golfer.userData.isSelectable = true; golfer.name = `Golfer_${i}`;\r\n                    golfer.position.copy(wrapToPlanet((Math.random()-0.5)*6000, (Math.random()-0.5)*6000, 25)); alignToPlanet(golfer);\r\n                    const club = new THREE.Mesh(new THREE.CylinderGeometry(0.5, 0.5, 40), new THREE.MeshStandardMaterial({color: 0xaaaaaa}));\r\n                    club.position.set(3, 5, 5); club.rotation.x = Math.PI\/4; golfer.add(club);\r\n                    golfer.userData.state = 'AIMING'; golfer.userData.timer = Math.random()*5; golfer.userData.swingPhase = 0; golfer.userData.club = club;\r\n                    golfGrp.add(golfer); this.golfers.push(golfer);\r\n                }\r\n\r\n                for(let i=0; i<15; i++) {\r\n                    const cart = new THREE.Group();\r\n                    cart.userData.isSelectable = true; cart.name = `Golf_Cart_${i}`;\r\n                    const cBase = new THREE.Mesh(new THREE.BoxGeometry(40, 15, 50), new THREE.MeshStandardMaterial({color: 0xffffff})); cBase.position.y = 15;\r\n                    const cRoof = new THREE.Mesh(new THREE.BoxGeometry(40, 3, 50), new THREE.MeshStandardMaterial({color: 0xffffff})); cRoof.position.y = 40;\r\n                    const cPole1 = new THREE.Mesh(new THREE.CylinderGeometry(1,1,25), new THREE.MeshStandardMaterial({color:0x333})); cPole1.position.set(-18, 27, -23);\r\n                    const cPole2 = cPole1.clone(); cPole2.position.set(18, 27, -23);\r\n                    const cPole3 = cPole1.clone(); cPole3.position.set(-18, 27, 23);\r\n                    const cPole4 = cPole1.clone(); cPole4.position.set(18, 27, 23);\r\n                    cart.add(cBase, cRoof, cPole1, cPole2, cPole3, cPole4);\r\n                    cart.position.copy(wrapToPlanet((Math.random()-0.5)*6000, (Math.random()-0.5)*5000, 25)); alignToPlanet(cart); cart.rotateY(Math.random() * Math.PI * 2); golfGrp.add(cart);\r\n                }\r\n\r\n                this.groupMap.golfcourse = golfGrp;\r\n                this.applyWPTransform(golfGrp, 'golfcourse', 0, 50, -17000, 0, 0, 0); \r\n                this.scene.add(golfGrp);\r\n            }\r\n\r\n            buildSchoolAndHospital() {\r\n                const schoolGrp = new THREE.Group();\r\n                schoolGrp.userData.isSelectable = true; schoolGrp.name = \"City_School\";\r\n                if(window.VMP_CONFIG.modelSchool) {\r\n                    loadCustomModel(window.VMP_CONFIG.modelSchool, obj => { if(obj) schoolGrp.add(obj); });\r\n                } else {\r\n                    const b1 = new THREE.Mesh(new THREE.BoxGeometry(600, 120, 300), new THREE.MeshStandardMaterial({color: 0xb5651d})); b1.position.y = 60;\r\n                    const field = new THREE.Mesh(new THREE.PlaneGeometry(800, 500), new THREE.MeshStandardMaterial({color: 0x228b22}));\r\n                    field.rotation.x = -Math.PI\/2; field.position.set(0, 1, 450);\r\n                    schoolGrp.add(b1, field);\r\n                }\r\n                this.groupMap.school = schoolGrp;\r\n                this.applyWPTransform(schoolGrp, 'school', -4000, 0, 4000, 0, 0, 0);\r\n                this.scene.add(schoolGrp);\r\n                this.collidableMeshes.push(schoolGrp);\r\n\r\n                const hospGrp = new THREE.Group();\r\n                hospGrp.userData.isSelectable = true; hospGrp.name = \"City_Hospital\";\r\n                if(window.VMP_CONFIG.modelHospital) {\r\n                    loadCustomModel(window.VMP_CONFIG.modelHospital, obj => { if(obj) hospGrp.add(obj); });\r\n                } else {\r\n                    const h1 = new THREE.Mesh(new THREE.BoxGeometry(400, 400, 400), new THREE.MeshStandardMaterial({color: 0xffffff})); h1.position.y = 200;\r\n                    const cross = new THREE.Group();\r\n                    const c1 = new THREE.Mesh(new THREE.BoxGeometry(40, 120, 10), new THREE.MeshStandardMaterial({color: 0xff0000, emissive: 0xff0000}));\r\n                    const c2 = new THREE.Mesh(new THREE.BoxGeometry(120, 40, 10), new THREE.MeshStandardMaterial({color: 0xff0000, emissive: 0xff0000}));\r\n                    cross.add(c1, c2); cross.position.set(0, 300, 205); hospGrp.add(h1, cross);\r\n                }\r\n                this.groupMap.hospital = hospGrp;\r\n                this.applyWPTransform(hospGrp, 'hospital', 4000, 0, 4000, 0, 0, 0);\r\n                this.scene.add(hospGrp);\r\n                this.collidableMeshes.push(hospGrp);\r\n            }\r\n\r\n            buildSatellites() {\r\n                const buildSat = (name) => {\r\n                    const satGrp = new THREE.Group();\r\n                    satGrp.userData.isSelectable = true; satGrp.name = name;\r\n                    if(window.VMP_CONFIG.modelSatellite) {\r\n                        loadCustomModel(window.VMP_CONFIG.modelSatellite, obj => { if(obj) { obj.scale.setScalar(50); satGrp.add(obj); } });\r\n                    } else {\r\n                        const body = new THREE.Mesh(new THREE.CylinderGeometry(40, 40, 160), new THREE.MeshStandardMaterial({color: 0xaaaaaa, metalness: 0.9}));\r\n                        const panelL = new THREE.Mesh(new THREE.BoxGeometry(300, 4, 80), new THREE.MeshStandardMaterial({color: 0x002288, metalness: 0.5})); panelL.position.set(-190, 0, 0);\r\n                        const panelR = new THREE.Mesh(new THREE.BoxGeometry(300, 4, 80), new THREE.MeshStandardMaterial({color: 0x002288, metalness: 0.5})); panelR.position.set(190, 0, 0);\r\n                        const dish = new THREE.Mesh(new THREE.SphereGeometry(60, 16, 16, 0, Math.PI), new THREE.MeshStandardMaterial({color: 0xffffff, side: THREE.DoubleSide}));\r\n                        dish.position.set(0, 80, 0); dish.rotation.x = Math.PI\/2;\r\n                        satGrp.add(body, panelL, panelR, dish);\r\n                    }\r\n                    return satGrp;\r\n                };\r\n\r\n                const sat1 = buildSat(\"Satellite_1\"); this.groupMap.satellite_1 = sat1;\r\n                this.applyWPTransform(sat1, 'satellite_1', -10000, 15000, -10000, 0, 0, 0); this.scene.add(sat1);\r\n\r\n                const sat2 = buildSat(\"Satellite_2\"); this.groupMap.satellite_2 = sat2;\r\n                this.applyWPTransform(sat2, 'satellite_2', 10000, 15000, 10000, 0, 0, 0); this.scene.add(sat2);\r\n            }\r\n\r\n            buildUndergroundPipes() {\r\n                this.pipeSystem = new THREE.Group();\r\n                const colors =[0x00e5ff, 0xff0055, 0x00ff66, 0xffaa00, 0xffffff, 0x0000ff]; \r\n                \r\n                for(let i=0; i<80; i++) {\r\n                    const startX = (Math.random()-0.5)*25000; const startZ = (Math.random()-0.5)*25000; \r\n                    const depth = -100 - Math.random()*400; \r\n                    \r\n                    const p1 = wrapToPlanet(startX, startZ, depth);\r\n                    const p2 = wrapToPlanet(startX + (Math.random()-0.5)*4000, startZ + (Math.random()-0.5)*4000, depth);\r\n                    const p3 = wrapToPlanet(startX + (Math.random()-0.5)*8000, startZ + (Math.random()-0.5)*8000, depth);\r\n\r\n                    const curve = new THREE.CatmullRomCurve3([p1, p2, p3]);\r\n                    const pCol = colors[Math.floor(Math.random() * colors.length)];\r\n                    const tube = new THREE.Mesh(new THREE.TubeGeometry(curve, 40, 6, 8, false), new THREE.MeshStandardMaterial({color: 0x222222, metalness: 0.8}));\r\n                    const pulse = new THREE.Mesh(new THREE.SphereGeometry(15, 16, 16), new THREE.MeshBasicMaterial({color: pCol, transparent: true, opacity: 0.8, blending: THREE.AdditiveBlending}));\r\n                    pulse.userData = { curve: curve, progress: Math.random() };\r\n                    this.pipeSystem.add(tube, pulse);\r\n                }\r\n                this.scene.add(this.pipeSystem);\r\n            }\r\n\r\n            buildCryptoMiners() {\r\n                this.minersGroup = new THREE.Group();\r\n                this.minersGroup.name = 'Crypto_Miners';\r\n                \r\n                const platformGeo = new THREE.BoxGeometry(600, 10, 200);\r\n                const platform = new THREE.Mesh(platformGeo, new THREE.MeshStandardMaterial({color: 0x111111, metalness: 0.8}));\r\n                platform.position.y = 5; this.minersGroup.add(platform);\r\n                this.collidableMeshes.push(platform);\r\n\r\n                this.minerNodes =[];\r\n                const coins =[\r\n                    { name: 'ETH', color: 0x627eea, wallet: window.VMP_CONFIG.wallet_eth_miner },\r\n                    { name: 'BTC', color: 0xf7931a, wallet: window.VMP_CONFIG.wallet_btc_miner },\r\n                    { name: 'SOL', color: 0x00ffa3, wallet: window.VMP_CONFIG.wallet_sol_miner },\r\n                    { name: 'ETH', color: 0x627eea, wallet: window.VMP_CONFIG.wallet_eth_miner },\r\n                    { name: 'BTC', color: 0xf7931a, wallet: window.VMP_CONFIG.wallet_btc_miner },\r\n                    { name: 'SOL', color: 0x00ffa3, wallet: window.VMP_CONFIG.wallet_sol_miner }\r\n                ];\r\n\r\n                for(let i=0; i<6; i++) {\r\n                    const nodeGrp = new THREE.Group();\r\n                    const desk = new THREE.Mesh(new THREE.BoxGeometry(40, 30, 40), new THREE.MeshStandardMaterial({color: 0x333333})); desk.position.set(-250 + (i*100), 25, 0);\r\n                    const rig = new THREE.Mesh(new THREE.BoxGeometry(20, 20, 20), new THREE.MeshStandardMaterial({color: 0x0a0a0a, emissive: coins[i].color, emissiveIntensity: 0.2}));\r\n                    rig.position.set(0, 25, 0); desk.add(rig);\r\n\r\n                    if(this.font) {\r\n                        const txtGeo = new TextGeometry(`${coins[i].name} MINING\\n${coins[i].wallet.substring(0,8)}...`, { font: this.font, size: 5, height: 1 });\r\n                        txtGeo.center();\r\n                        const txtMesh = new THREE.Mesh(txtGeo, new THREE.MeshBasicMaterial({color: coins[i].color, transparent: true, opacity: 0.8}));\r\n                        txtMesh.position.set(0, 50, 0); desk.add(txtMesh);\r\n                        nodeGrp.userData.floatText = txtMesh;\r\n                    }\r\n\r\n                    const worker = buildProceduralHuman('adult', null, 'security');\r\n                    worker.position.set(-250 + (i*100), 10, -30); worker.rotation.y = 0; \r\n                    worker.children[0].children[0].userData.armL.rotation.x = -Math.PI\/4;\r\n                    worker.children[0].children[0].userData.armR.rotation.x = -Math.PI\/4;\r\n                    \r\n                    nodeGrp.add(desk, worker);\r\n                    nodeGrp.userData.coin = coins[i];\r\n                    nodeGrp.userData.worker = worker;\r\n                    this.minersGroup.add(nodeGrp);\r\n                    this.minerNodes.push(nodeGrp);\r\n                }\r\n\r\n                this.applyWPTransform(this.minersGroup, 'crypto_miners', 0, 0, -2800, 0, 0, 0);\r\n                this.scene.add(this.minersGroup);\r\n            }\r\n\r\n            buildSanctuaryPark() {\r\n                const parkGrp = new THREE.Group();\r\n                parkGrp.name = \"Sanctuary_Park\";\r\n                const treeGeo = new THREE.CylinderGeometry(5, 5, 40);\r\n                const leafGeo = new THREE.SphereGeometry(30);\r\n                const tMat = new THREE.MeshStandardMaterial({color: 0x5c4033});\r\n                const lMat = new THREE.MeshStandardMaterial({color: 0x228b22});\r\n\r\n                for(let i = 0; i < 25; i++) {\r\n                    const t = new THREE.Mesh(treeGeo, tMat);\r\n                    const l = new THREE.Mesh(leafGeo, lMat);\r\n                    l.position.y = 30; t.add(l);\r\n                    \r\n                    const pX = (Math.random() - 0.5) * 2000;\r\n                    const pZ = (Math.random() - 0.5) * 2000;\r\n                    \r\n                    const sPos = wrapToPlanet(pX, pZ, 20);\r\n                    t.position.copy(sPos);\r\n                    alignToPlanet(t);\r\n                    parkGrp.add(t);\r\n                }\r\n\r\n                this.fisherGrp = new THREE.Group();\r\n                const body = new THREE.Mesh(new THREE.CylinderGeometry(6, 6, 16, 16), new THREE.MeshStandardMaterial({color:0xffaa00})); body.position.y = 18; this.fisherGrp.add(body);\r\n                const head = new THREE.Mesh(new THREE.SphereGeometry(6), new THREE.MeshStandardMaterial({color:0xffccaa})); head.position.y = 30; this.fisherGrp.add(head);\r\n                const hat = new THREE.Mesh(new THREE.ConeGeometry(8,4,16), new THREE.MeshStandardMaterial({color:0xddaa55})); hat.position.y = 35; this.fisherGrp.add(hat);\r\n                const polePts =[new THREE.Vector3(0, 25, 0), new THREE.Vector3(0, 40, -120)];\r\n                const pole = new THREE.Line(new THREE.BufferGeometry().setFromPoints(polePts), new THREE.LineBasicMaterial({color:0xaaaaaa})); this.fisherGrp.add(pole);\r\n                const box = new THREE.Mesh(new THREE.BoxGeometry(15, 12, 15), new THREE.MeshStandardMaterial({color:0x442211})); box.position.y = 6; this.fisherGrp.add(box);\r\n\r\n                const fishPos = wrapToPlanet(800, -580, 12);\r\n                this.fisherGrp.position.copy(fishPos);\r\n                alignToPlanet(this.fisherGrp);\r\n                \r\n                parkGrp.add(this.fisherGrp);\r\n                this.scene.add(parkGrp);\r\n            }\r\n\r\n            buildPool() {\r\n                const poolGrp = new THREE.Group();\r\n                poolGrp.name = \"Sanctuary_Pool\"; poolGrp.userData.isSelectable = true;\r\n                const poolGeo = new THREE.PlaneGeometry(600, 800);\r\n                const poolWaterMat = new THREE.MeshStandardMaterial({ color: window.VMP_CONFIG.waterColor || 0x0044ff, transparent: true, opacity: 0.6, metalness: 0.9, roughness: 0.1 });\r\n                const water = new THREE.Mesh(poolGeo, poolWaterMat);\r\n                water.rotation.x = -Math.PI \/ 2; poolGrp.add(water);\r\n                const borderGeo = new THREE.BoxGeometry(620, 10, 820);\r\n                const borderMat = new THREE.MeshStandardMaterial({ color: 0x333333 });\r\n                const border = new THREE.Mesh(borderGeo, borderMat); border.position.y = -5; poolGrp.add(border);\r\n                this.groupMap.pool = poolGrp;\r\n                this.applyWPTransform(poolGrp, 'pool', 0, 10, -1200, 0, 0, 0);\r\n                this.scene.add(poolGrp);\r\n            }\r\n\r\n            async buildProceduralGrass(densityPercent) {\r\n                updateLoadStatus(\"Planting Grass Blades...\");\r\n                if (this.grass) {\r\n                    this.scene.remove(this.grass);\r\n                    this.grass.geometry.dispose();\r\n                    this.grass.material.dispose();\r\n                }\r\n\r\n                const baseBladeCount = parseInt(window.VMP_CONFIG.grassBlades || 5000);\r\n                const bladeCount = Math.max(100, Math.floor(baseBladeCount * (densityPercent \/ 100)));\r\n\r\n                const grassHeight = parseFloat(window.VMP_CONFIG.grassHeight || 10);\r\n                const geometry = new THREE.PlaneGeometry(2, grassHeight, 1, 2);\r\n                geometry.translate(0, grassHeight \/ 2, 0); \r\n                const material = new THREE.MeshStandardMaterial({ color: 0x2d5a27, side: THREE.DoubleSide, alphaTest: 0.5 });\r\n                this.grass = new THREE.InstancedMesh(geometry, material, bladeCount);\r\n                this.grass.userData.baseColor = new THREE.Color(0x2d5a27);\r\n\r\n                const dummy = new THREE.Object3D();\r\n                for (let i = 0; i < bladeCount; i++) {\r\n                    if (i % 500 === 0) await yieldFrame(); \r\n                    const x = (Math.random() - 0.5) * 40000;\r\n                    const z = (Math.random() - 0.5) * 40000;\r\n                    if (Math.abs(x) < 2600 && Math.abs(z) < 2600) continue; \r\n                    if (x > 12000) continue; \r\n                    \r\n                    const spherePos = wrapToPlanet(x, z, 0);\r\n                    dummy.position.copy(spherePos);\r\n                    alignToPlanet(dummy);\r\n                    dummy.rotateY(Math.random() * Math.PI);\r\n                    dummy.scale.setScalar(0.5 + Math.random() * 1.5);\r\n                    dummy.updateMatrix();\r\n                    this.grass.setMatrixAt(i, dummy.matrix);\r\n                }\r\n                this.scene.add(this.grass);\r\n            }\r\n\r\n            buildMiamiBeachAndOcean() {\r\n                const beachGrp = new THREE.Group();\r\n                beachGrp.name = \"Beach_And_Ocean_System\";\r\n\r\n                const oceanGeo = new THREE.SphereGeometry(PLANET_RADIUS - 5, 256, 256); \r\n                if (!this.oceanMat) {\r\n                    this.oceanMat = new THREE.ShaderMaterial({\r\n                        uniforms: THREE.UniformsUtils.clone(WaterShader.uniforms),\r\n                        vertexShader: WaterShader.vertexShader,\r\n                        fragmentShader: WaterShader.fragmentShader,\r\n                        transparent: true,\r\n                    });\r\n                }\r\n                this.ocean = new THREE.Mesh(oceanGeo, this.oceanMat);\r\n                this.ocean.userData.isSelectable = true;\r\n                this.ocean.name = \"Global_Ocean\";\r\n                this.ocean.position.copy(PLANET_CENTER);\r\n                beachGrp.add(this.ocean);\r\n\r\n                const sandTex = texLoader.load(getBustUrl('https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-content\/uploads\/2026\/04\/sand.png'));\r\n                sandTex.wrapS = sandTex.wrapT = THREE.RepeatWrapping; sandTex.repeat.set(20, 50);\r\n                const sandMat = new THREE.MeshStandardMaterial({ map: sandTex, roughness: 1.0, color: 0xffeebb });\r\n                \r\n                const duneGeo = new THREE.PlaneGeometry(8000, 40000, 64, 64);\r\n                duneGeo.rotateX(-Math.PI \/ 2);\r\n                \r\n                const pos = duneGeo.attributes.position;\r\n                for(let i=0; i<pos.count; i++) {\r\n                    const x = pos.getX(i); const z = pos.getZ(i);\r\n                    let yOffset = Math.sin(x * 0.01) * 10 + Math.cos(z * 0.005) * 20;\r\n                    const normalizedX = (x + 4000) \/ 8000; \r\n                    yOffset -= (1 - normalizedX) * 50; \r\n                    pos.setY(i, yOffset);\r\n                }\r\n                duneGeo.computeVertexNormals();\r\n                \r\n                const posArr = duneGeo.attributes.position.array;\r\n                \r\n                if(this.cityWorker) {\r\n                    this.cityWorker.postMessage({\r\n                        action: 'bendDuneGeometry',\r\n                        positions: posArr,\r\n                        id: 'beach_dune'\r\n                    },[posArr.buffer]);\r\n                } else {\r\n                    for (let i = 0; i < pos.count; i++) {\r\n                        const x = pos.getX(i) + 17000;\r\n                        const z = pos.getZ(i); \r\n                        const height = pos.getY(i); \r\n                        \r\n                        const sphericalPos = wrapToPlanet(x, z, height);\r\n                        pos.setXYZ(i, sphericalPos.x, sphericalPos.y, sphericalPos.z);\r\n                    }\r\n                    duneGeo.computeVertexNormals();\r\n                }\r\n\r\n                const beachSand = new THREE.Mesh(duneGeo, sandMat);\r\n                beachSand.userData.isSelectable = true;\r\n                beachSand.name = \"Sandy_Beach_Shore\";\r\n                beachGrp.add(beachSand);\r\n                beachSand.userData.isSolidGround = true;\r\n\r\n                if(this.cityWorker) {\r\n                    const origOnMessage = this.cityWorker.onmessage;\r\n                    this.cityWorker.onmessage = (e) => {\r\n                        if(origOnMessage) origOnMessage(e);\r\n                        if(e.data.action === 'geometryBent' && e.data.id === 'beach_dune') {\r\n                            duneGeo.setAttribute('position', new THREE.BufferAttribute(e.data.positions, 3));\r\n                            duneGeo.computeVertexNormals();\r\n                            TerminalLogger.log(\"[WORKER] Sand Dune geometry mapping complete.\", \"sys\");\r\n                        }\r\n                    };\r\n                }\r\n\r\n                this.groupMap.beach = beachGrp;\r\n                this.applyWPTransform(beachGrp, 'beach', 0, 0, 0); \r\n                this.scene.add(beachGrp);\r\n            }\r\n\r\n            buildUnderwaterScene() {\r\n                const underwaterGroup = new THREE.Group();\r\n                underwaterGroup.position.set(0, 0, 0); \r\n                \r\n                const coralColors =[0xff6b6b, 0x4ecdc4, 0x45b7d1, 0xf7d794, 0x77dd77];\r\n                const coralGeo = new THREE.IcosahedronGeometry(20, 1);\r\n                const coralInstanced = new THREE.InstancedMesh(coralGeo, new THREE.MeshStandardMaterial(), 1000);\r\n                const dummy = new THREE.Object3D();\r\n                for(let i=0; i<1000; i++) {\r\n                    const fX = 17000 + (Math.random() - 0.5) * 15000;\r\n                    const fZ = (Math.random() - 0.5) * 15000;\r\n                    const fY = -50 + Math.random() * 50;\r\n                    const sPos = wrapToPlanet(fX, fZ, fY);\r\n                    \r\n                    dummy.position.copy(sPos);\r\n                    alignToPlanet(dummy);\r\n                    dummy.scale.setScalar(0.5 + Math.random() * 2.5);\r\n                    dummy.updateMatrix();\r\n                    coralInstanced.setMatrixAt(i, dummy.matrix);\r\n                    coralInstanced.setColorAt(i, new THREE.Color(coralColors[Math.floor(Math.random() * coralColors.length)]));\r\n                }\r\n                underwaterGroup.add(coralInstanced);\r\n                \r\n                const kelpMat = new THREE.MeshStandardMaterial({ color: 0x006400, roughness: 0.9, side: THREE.DoubleSide });\r\n                for(let i=0; i<500; i++) {\r\n                    const kelpHeight = 100 + Math.random() * 300;\r\n                    const curve = new THREE.CatmullRomCurve3([\r\n                        new THREE.Vector3(0, 0, 0),\r\n                        new THREE.Vector3((Math.random()-0.5)*20, kelpHeight * 0.5, (Math.random()-0.5)*20),\r\n                        new THREE.Vector3((Math.random()-0.5)*10, kelpHeight, (Math.random()-0.5)*10)\r\n                    ]);\r\n                    const kelpGeo = new THREE.TubeGeometry(curve, 20, 4, 8, false);\r\n                    const kelp = new THREE.Mesh(kelpGeo, kelpMat);\r\n                    \r\n                    const fX = 17000 + (Math.random() - 0.5) * 15000;\r\n                    const fZ = (Math.random() - 0.5) * 15000;\r\n                    const fY = -100;\r\n                    const sPos = wrapToPlanet(fX, fZ, fY);\r\n                    \r\n                    kelp.position.copy(sPos);\r\n                    alignToPlanet(kelp);\r\n                    underwaterGroup.add(kelp);\r\n                }\r\n\r\n                this.entities.fishes =[];\r\n                const fishGeo = new THREE.ConeGeometry(2, 8, 8); fishGeo.rotateX(Math.PI\/2);\r\n                const fishMat = new THREE.MeshStandardMaterial({ color: 0xaaaaaa, metalness: 0.8, roughness: 0.2 });\r\n                const schoolSize = Math.max(1, parseInt(window.VMP_CONFIG.popFish || 15));\r\n                for(let s=0; s<10; s++) { \r\n                    const fX = 17000 + (Math.random()-0.5)*10000;\r\n                    const fZ = (Math.random()-0.5)*10000;\r\n                    const schoolCenter = new THREE.Vector3(fX, Math.random()*100, fZ); \/\/ Logical Center\r\n                    \r\n                    for(let i=0; i<schoolSize; i++) {\r\n                        const fish = new THREE.Mesh(fishGeo, fishMat);\r\n                        fish.scale.setScalar(2 + Math.random() * 2);\r\n                        \r\n                        const lx = schoolCenter.x + (Math.random()-0.5)*400;\r\n                        const ly = schoolCenter.y + (Math.random()-0.5)*200 - 50;\r\n                        const lz = schoolCenter.z + (Math.random()-0.5)*400;\r\n                        \r\n                        const sPos = wrapToPlanet(lx, lz, ly);\r\n                        fish.position.copy(sPos);\r\n                        alignToPlanet(fish);\r\n                        \r\n                        underwaterGroup.add(fish);\r\n                        this.entities.fishes.push({mesh: fish, logicalPos: new THREE.Vector3(lx, ly, lz), speed: 0.5 + Math.random()});\r\n                    }\r\n                }\r\n                \r\n                this.scene.add(underwaterGroup);\r\n            }\r\n\r\n            updateDynamicEconomyUI() {\r\n                const popLabel = document.getElementById(`stat_pop_${INSTANCE_ID}`);\r\n                if (popLabel) popLabel.innerText = this.entities.pedestrians ? this.entities.pedestrians.length : 0;\r\n\r\n                const trafficLabel = document.getElementById(`stat_traffic_${INSTANCE_ID}`);\r\n                if (trafficLabel) trafficLabel.innerText = this.entities.cars ? this.entities.cars.length : 0;\r\n\r\n                const bldLabel = document.getElementById(`stat_bld_${INSTANCE_ID}`);\r\n                if (bldLabel) bldLabel.innerText = this.cityBuildings ? this.cityBuildings.length : 0;\r\n\r\n                let bldrs = 0, eng = 0, plmbrs = 0, traders = 0;\r\n                if (this.entities.workers) {\r\n                    this.entities.workers.forEach(p => {\r\n                        if (p.userData.job === 'Builder') bldrs++;\r\n                        else if (p.userData.job === 'Electrician') eng++;\r\n                        else if (p.userData.job === 'Plumber') plmbrs++;\r\n                    });\r\n                }\r\n                 if (this.entities.pedestrians) {\r\n                    this.entities.pedestrians.forEach(p => {\r\n                        if (p.userData.job === 'Wall Street Trader') traders++;\r\n                    });\r\n                }\r\n                \r\n                this.economy.builders = bldrs;\r\n                this.economy.engineers = eng;\r\n                this.economy.plumbers = plmbrs;\r\n\r\n                const realEstateYield = this.cityBuildings ? this.cityBuildings.length * 1500 : 0;\r\n                const oceanYield = this.entities.fishes ? this.entities.fishes.length * 800 : 0;\r\n                const animalYield = this.entities.rabbits ? this.entities.rabbits.length * 400 : 0;\r\n                const jobYield = (bldrs * 4000) + (eng * 5000) + (plmbrs * 4500);\r\n                const wallStYield = traders * 8000 + (Math.random() * 50000);\r\n                const cryptoYield = (Math.random() - 0.45) * 150000;\r\n\r\n                this.economy.realEstate += realEstateYield; this.economy.ocean += oceanYield;\r\n                this.economy.animals += animalYield; this.economy.wallSt += wallStYield; this.economy.crypto += cryptoYield;\r\n\r\n                const totalYield = realEstateYield + oceanYield + animalYield + jobYield + wallStYield + cryptoYield;\r\n                this.economy.mayor += totalYield * 0.2; this.economy.president += totalYield * 0.8;\r\n\r\n                const fmt = (num) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(num);\r\n\r\n                const q = (id) => document.getElementById(`stat_${id}_${INSTANCE_ID}`);\r\n                if(q('bldr')) q('bldr').innerText = bldrs;\r\n                if(q('eng')) q('eng').innerText = eng;\r\n                if(q('plmbr')) q('plmbr').innerText = plmbrs;\r\n                if(q('pres')) q('pres').innerText = fmt(this.economy.president);\r\n                if(q('mayor')) q('mayor').innerText = fmt(this.economy.mayor);\r\n                if(q('wallst')) q('wallst').innerText = fmt(this.economy.wallSt);\r\n                if(q('crypto')) {\r\n                    q('crypto').innerText = fmt(this.economy.crypto);\r\n                    q('crypto').style.color = this.economy.crypto < 0 ? '#ff0055' : '#00ff66';\r\n                }\r\n                if(q('ocean')) q('ocean').innerText = fmt(this.economy.ocean);\r\n                if(q('realestate')) q('realestate').innerText = fmt(this.economy.realEstate);\r\n            }\r\n\r\n            buildVolumetricClouds() {\r\n                this.cityClouds =[];\r\n                const cloudGroup = new THREE.Group();\r\n                const cloudMat = new THREE.MeshLambertMaterial({ color: 0xffffff, transparent: true, opacity: 0.1, depthWrite: false });\r\n\r\n                for (let i = 0; i < 150; i++) {\r\n                    const cluster = new THREE.Group();\r\n                    const blobCount = 6 + Math.floor(Math.random() * 5);\r\n                    for (let j = 0; j < blobCount; j++) {\r\n                        const size = 300 + Math.random() * 300;\r\n                        const blob = new THREE.Mesh(new THREE.IcosahedronGeometry(size, 1), cloudMat);\r\n                        blob.position.set((Math.random() - 0.5) * size * 1.5, (Math.random() - 0.5) * size * 0.5, (Math.random() - 0.5) * size * 1.5);\r\n                        blob.scale.set(1.5, 0.6, 1.2);\r\n                        cluster.add(blob);\r\n                    }\r\n                    const radius = 5000 + Math.random() * 40000;\r\n                    const angle = Math.random() * Math.PI * 2;\r\n                    \r\n                    const fX = Math.cos(angle) * radius;\r\n                    const fZ = Math.sin(angle) * radius;\r\n                    const fY = 1500 + Math.random() * 2000;\r\n                    \r\n                    const sPos = wrapToPlanet(fX, fZ, fY);\r\n                    cluster.position.copy(sPos);\r\n                    alignToPlanet(cluster);\r\n                    cluster.rotateY(Math.random() * Math.PI);\r\n\r\n                    this.cityClouds.push({ mesh: cluster, logicalX: fX, logicalZ: fZ, logicalY: fY, speed: 250 + Math.random() * 350, driftVec: new THREE.Vector2(Math.random() - 0.5, Math.random() - 0.5).normalize() });\r\n                    cloudGroup.add(cluster);\r\n                }\r\n                this.scene.add(cloudGroup);\r\n            }buildProceduralFlowers() {\r\n                const flowerCount = 1500;\r\n                const flowerGeo = new THREE.ConeGeometry(2, 4, 5); flowerGeo.translate(0, 2, 0);\r\n                const fMesh = new THREE.InstancedMesh(flowerGeo, new THREE.MeshStandardMaterial({ color: 0xff0088, roughness: 0.8 }), flowerCount);\r\n                const dum = new THREE.Object3D();\r\n\r\n                for(let i = 0; i < flowerCount; i++) {\r\n                    const fX = (Math.random() - 0.5) * 26000;\r\n                    const fZ = (Math.random() - 0.5) * 26000;\r\n                    \r\n                    const sPos = wrapToPlanet(fX, fZ, 0);\r\n                    dum.position.copy(sPos);\r\n                    alignToPlanet(dum);\r\n                    \r\n                    dum.scale.set(1 + Math.random(), 1 + Math.random() * 1.5, 1 + Math.random());\r\n                    dum.rotation.x += (Math.random() - 0.5) * 0.2; dum.rotation.z += (Math.random() - 0.5) * 0.2;\r\n                    dum.updateMatrix();\r\n                    fMesh.setMatrixAt(i, dum.matrix);\r\n                    fMesh.setColorAt(i, new THREE.Color().setHSL(Math.random(), 1.0, 0.5));\r\n                }\r\n                this.scene.add(fMesh);\r\n            }\r\n\r\n            buildEgyptianPyramidComplex() {\r\n                if(window.VMP_CONFIG.modelPyramid) {\r\n                    loadCustomModel(window.VMP_CONFIG.modelPyramid, (obj) => {\r\n                        if(obj) { obj.userData.isSelectable = true; obj.name = \"Pyramid_Complex\"; this.groupMap.pyramid = obj; this.applyWPTransform(obj, 'pyramid', 0, 0, 0, 0, 0, 0); this.scene.add(obj); this.collidableMeshes.push(obj); }\r\n                    });\r\n                    return;\r\n                }\r\n\r\n                const bGroup = new THREE.Group();\r\n                bGroup.userData.isSelectable = true; bGroup.name = \"Pyramid_Complex\";\r\n                const bWidth = 800, bDepth = 800, fHeight = 60;\r\n\r\n                const pyrMat = loadAdvancedMat(window.VMP_CONFIG.pyrDiff, window.VMP_CONFIG.pyrBump, 0x444444, window.VMP_CONFIG.pyrRough, window.VMP_CONFIG.pyrMetal, window.VMP_CONFIG.pyrScaleX, window.VMP_CONFIG.pyrScaleY, window.VMP_CONFIG.pyrRotation, window.VMP_CONFIG.pyrOffsetX, window.VMP_CONFIG.pyrOffsetY);\r\n                const intWallLeftMat = loadAdvancedMat(window.VMP_CONFIG.pyrWallLeftDiff, '', 0xffffff, 0.6, 0.2, window.VMP_CONFIG.wallLeftScale);\r\n                const intWallRightMat = loadAdvancedMat(window.VMP_CONFIG.pyrWallRightDiff, '', 0xffffff, 0.6, 0.2, window.VMP_CONFIG.wallRightScale);\r\n                const intWallBackMat = loadAdvancedMat('', window.VMP_CONFIG.pyrWallBackBump, 0x111111, 1.0, 0.0, window.VMP_CONFIG.wallBackScale);\r\n\r\n                const roomGroup = new THREE.Group(); const roomHeight = 150; const wThick = 20;\r\n\r\n                const wB = new THREE.Mesh(new THREE.BoxGeometry(bWidth, roomHeight, wThick), intWallBackMat); wB.position.set(0, roomHeight \/ 2, -bDepth \/ 2 + wThick \/ 2); wB.receiveShadow = true;\r\n                const wL = new THREE.Mesh(new THREE.BoxGeometry(wThick, roomHeight, bDepth), intWallLeftMat); wL.position.set(-bWidth \/ 2 + wThick \/ 2, roomHeight \/ 2, 0); wL.receiveShadow = true;\r\n                const wR = new THREE.Mesh(new THREE.BoxGeometry(wThick, roomHeight, bDepth), intWallRightMat); wR.position.set(bWidth \/ 2 - wThick \/ 2, roomHeight \/ 2, 0); wR.receiveShadow = true;\r\n                const wF1 = new THREE.Mesh(new THREE.BoxGeometry(bWidth \/ 2 - 80, roomHeight, wThick), pyrMat); wF1.position.set(-bWidth \/ 4 - 40, roomHeight \/ 2, bDepth \/ 2); wF1.receiveShadow = true; wF1.castShadow = true;\r\n                const wF2 = new THREE.Mesh(new THREE.BoxGeometry(bWidth \/ 2 - 80, roomHeight, wThick), pyrMat); wF2.position.set(bWidth \/ 4 + 40, roomHeight \/ 2, bDepth \/ 2); wF2.receiveShadow = true; wF2.castShadow = true;\r\n\r\n                const doorMat = new THREE.MeshStandardMaterial({color: 0x111111, metalness: 0.8, roughness: 0.2});\r\n                const dL = new THREE.Mesh(new THREE.BoxGeometry(80, roomHeight, 10), doorMat); dL.position.set(-40, roomHeight \/ 2, bDepth \/ 2); dL.castShadow = true;\r\n                const dR = new THREE.Mesh(new THREE.BoxGeometry(80, roomHeight, 10), doorMat); dR.position.set(40, roomHeight \/ 2, bDepth \/ 2); dR.castShadow = true;\r\n\r\n                const intRoof = new THREE.Mesh(new THREE.PlaneGeometry(bWidth, bDepth), loadAdvancedMat(window.VMP_CONFIG.roofDiff, '', 0x222222, 0.8, 0.1, 5)); intRoof.rotation.x = Math.PI \/ 2; intRoof.position.y = roomHeight;\r\n\r\n                const centerDesk = new THREE.Group();\r\n                const deskTop = new THREE.Mesh(new THREE.BoxGeometry(200, 10, 100), new THREE.MeshStandardMaterial({color: 0x222222, roughness: 0.4, metalness: 0.6})); deskTop.position.y = 40; deskTop.castShadow = true; deskTop.receiveShadow = true; centerDesk.add(deskTop);\r\n                const dLMat = new THREE.MeshStandardMaterial({color: 0x444444, metalness: 0.8, roughness: 0.2});\r\n                const dL1Geo = new THREE.CylinderGeometry(5, 5, 40);\r\n                const dL1 = new THREE.Mesh(dL1Geo, dLMat); dL1.position.set(-90, 20, -40);  dL1.castShadow = true; centerDesk.add(dL1);\r\n                const dL2 = new THREE.Mesh(dL1Geo, dLMat); dL2.position.set(90, 20, -40); dL2.castShadow = true; centerDesk.add(dL2);\r\n                const dL3 = new THREE.Mesh(dL1Geo, dLMat); dL3.position.set(-90, 20, 40); dL3.castShadow = true; centerDesk.add(dL3);\r\n                const dL4 = new THREE.Mesh(dL1Geo, dLMat); dL4.position.set(90, 20, 40); dL4.castShadow = true; centerDesk.add(dL4);\r\n\r\n                const cmdMesh = new THREE.Mesh(new THREE.PlaneGeometry(240, 120), new THREE.MeshBasicMaterial({ map: this.cmd.texture, transparent: true, opacity: 0.9, side: THREE.DoubleSide })); cmdMesh.position.set(0, 100, -80); centerDesk.add(cmdMesh);\r\n\r\n                const teleporterGroup = new THREE.Group();\r\n                teleporterGroup.position.set(0, 5, -200);\r\n                \r\n                const telePad = new THREE.Mesh(new THREE.CylinderGeometry(60, 60, 10, 32), new THREE.MeshStandardMaterial({ color: 0x00e5ff, metalness: 1.0, roughness: 0.1, emissive: 0x0055aa }));\r\n                teleporterGroup.add(telePad);\r\n                \r\n                const teleRings = new THREE.Group();\r\n                for(let i=0; i<3; i++) {\r\n                    const ring = new THREE.Mesh(new THREE.TorusGeometry(60 + (i*10), 2, 16, 64), new THREE.MeshStandardMaterial({ color: 0x00e5ff, emissive: 0x00ffff, emissiveIntensity: 2.0 }));\r\n                    ring.rotation.x = Math.PI \/ 2;\r\n                    ring.position.y = 10 + (i * 40);\r\n                    teleRings.add(ring);\r\n                }\r\n                this.teleporterRings = teleRings; \r\n                teleporterGroup.add(teleRings);\r\n\r\n                const serverRack = new THREE.Mesh(new THREE.BoxGeometry(60, 120, 60), new THREE.MeshStandardMaterial({color:0x111111, metalness: 0.9, roughness: 0.1})); serverRack.position.set(-300, 60, -300); serverRack.castShadow = true; serverRack.receiveShadow = true;\r\n                for (let serverLightIdx = 0; serverLightIdx < 10; serverLightIdx++) {\r\n                    const sLight = new THREE.Mesh(new THREE.BoxGeometry(4, 2, 2), new THREE.MeshBasicMaterial({ color: 0x00ff00 })); sLight.position.set(0, (serverLightIdx * 10) - 50, 31); sLight.userData = { blinkRate: Math.random() * 0.5 + 0.1 }; serverRack.add(sLight);\r\n                }\r\n\r\n                roomGroup.add(serverRack, centerDesk, teleporterGroup, wB, wL, wR, wF1, wF2, dL, dR, intRoof); bGroup.add(roomGroup);\r\n\r\n                const glassMat = new THREE.MeshPhysicalMaterial({ color: 0x050505, roughness: 0.1, metalness: 0.9, transparent: true, opacity: 0.8, transmission: 0.5 });\r\n                const tiers = 15; let winCount = 0;\r\n                for(let i = 1; i <= tiers; i++) { const tW = bWidth * (1 - (i \/ tiers)); if (tW < 10) break; for(let w = -6; w <= 6; w++) { if (Math.abs(w * 40) > tW \/ 2 - 15) continue; winCount += 4; } }\r\n\r\n                const iGlass = new THREE.InstancedMesh(new THREE.BoxGeometry(1, 1, 1), glassMat, winCount); const dummy = new THREE.Object3D(); let wIdx = 0;\r\n\r\n                for(let i = 1; i <= tiers; i++) {\r\n                    const tW = bWidth * (1 - (i \/ tiers)); const tD = bDepth * (1 - (i \/ tiers)); if (tW < 10) break; const tierY = roomHeight + fHeight \/ 2 + ((i - 1) * fHeight);\r\n                    const tierWall = new THREE.Mesh(new THREE.BoxGeometry(tW, fHeight, tD), pyrMat); tierWall.position.y = tierY; tierWall.castShadow = true; tierWall.receiveShadow = true;\r\n                    const cap = new THREE.Mesh(new THREE.BoxGeometry(tW + 10, 3, tD + 10), pyrMat); cap.position.y = tierY; bGroup.add(tierWall, cap);\r\n\r\n                    for(let w = -6; w <= 6; w++) {\r\n                        const wP = w * 40; if (Math.abs(wP) > tW \/ 2 - 15) continue;\r\n                        dummy.rotation.set(0, 0, 0);\r\n                        dummy.position.set(wP, tierY, tD \/ 2 + 0.5); dummy.scale.set(20, fHeight - 15, 2); dummy.updateMatrix(); iGlass.setMatrixAt(wIdx++, dummy.matrix);\r\n                        dummy.position.set(wP, tierY, -tD \/ 2 - 0.5); dummy.scale.set(20, fHeight - 15, 2); dummy.updateMatrix(); iGlass.setMatrixAt(wIdx++, dummy.matrix);\r\n                        dummy.position.set(tW \/ 2 + 0.5, tierY, wP); dummy.scale.set(2, fHeight - 15, 20); dummy.updateMatrix(); iGlass.setMatrixAt(wIdx++, dummy.matrix);\r\n                        dummy.position.set(-tW \/ 2 - 0.5, tierY, wP); dummy.scale.set(2, fHeight - 15, 20); dummy.updateMatrix(); iGlass.setMatrixAt(wIdx++, dummy.matrix);\r\n                    }\r\n                }\r\n                iGlass.instanceMatrix.needsUpdate = true; bGroup.add(iGlass);\r\n\r\n                const topY = roomHeight + fHeight \/ 2 + (tiers * fHeight);\r\n                this.laserBeam = new THREE.Mesh(new THREE.CylinderGeometry(20, 20, 15000, 32), new THREE.MeshBasicMaterial({ color: 0x00e5ff, transparent: true, opacity: 0.7, blending: THREE.AdditiveBlending }));\r\n                this.laserBeam.position.y = topY + 7500; bGroup.add(this.laserBeam);\r\n\r\n                this.groupMap.pyramid = bGroup; this.applyWPTransform(bGroup, 'pyramid', 0, 0, 0, 0, 0, 0); this.scene.add(bGroup);\r\n                this.collidableMeshes.push(bGroup);\r\n            }\r\n\r\n            buildCurvedSurroundings() {\r\n                const quartzMat = loadAdvancedMat(window.VMP_CONFIG.abstractQuartzite, '', 0xffffff, 0.2, 0.8, 2);\r\n                const abstractFigureGroup = new THREE.Group(); this.rockoDefaultMat = quartzMat;\r\n                abstractFigureGroup.userData.isSelectable = true; abstractFigureGroup.name = \"Rocko_Abstract_Figure\";\r\n\r\n                const torusGeo = new THREE.TorusGeometry(80, 20, 32, 64); const torus = new THREE.Mesh(torusGeo, quartzMat);\r\n                torus.position.set(0, 100, 0); torus.castShadow = true; torus.receiveShadow = true; torus.userData.isRockoPart = true; abstractFigureGroup.add(torus);\r\n\r\n                const baseGeo = new THREE.CylinderGeometry(40, 60, 100); const base = new THREE.Mesh(baseGeo, quartzMat);\r\n                base.position.set(200, 50, 0); base.castShadow = true; base.receiveShadow = true; base.userData.isRockoPart = true; abstractFigureGroup.add(base);\r\n\r\n                const ledMat = new THREE.MeshBasicMaterial({color: 0x00ff00});\r\n                const eyeLGeo = new THREE.BoxGeometry(10, 5, 2); const eyeL = new THREE.Mesh(eyeLGeo, ledMat); eyeL.position.set(185, 145, 38); eyeL.visible = false; eyeL.userData.isLed = true; abstractFigureGroup.add(eyeL);\r\n                const eyeRGeo = new THREE.BoxGeometry(10, 5, 2); const eyeR = new THREE.Mesh(eyeRGeo, ledMat); eyeR.position.set(215, 145, 38); eyeR.visible = false; eyeR.userData.isLed = true; abstractFigureGroup.add(eyeR);\r\n                const mouthGeo = new THREE.BoxGeometry(20, 3, 2); const mouth = new THREE.Mesh(mouthGeo, ledMat); mouth.position.set(200, 125, 38); mouth.visible = false; mouth.userData.isLed = true; abstractFigureGroup.add(mouth);\r\n\r\n                const pts =[]; const heightSteps = 30;\r\n                for(let j = 0; j <= heightSteps; j++) { const scale = 50 + Math.abs(Math.sin((j \/ heightSteps) * Math.PI * 2)) * 60; pts.push(new THREE.Vector2(scale, j * 12)); }\r\n\r\n                const abstractBodyGeo = new THREE.LatheGeometry(pts, 64); const abstractBody = new THREE.Mesh(abstractBodyGeo, quartzMat);\r\n                abstractBody.position.set(-200, 0, 0); abstractBody.castShadow = true; abstractBody.receiveShadow = true; abstractBody.userData.isRockoPart = true; abstractFigureGroup.add(abstractBody);\r\n\r\n                this.groupMap.abstract_figure = abstractFigureGroup; \r\n                this.applyWPTransform(abstractFigureGroup, 'abstract_figure', 0, 0, -2800, 0, 0, 0); \r\n                this.scene.add(abstractFigureGroup);\r\n            }\r\n\r\n            buildSolarSystem() {\r\n                const planetsGroup = new THREE.Group();\r\n                const texMap = { Mercury: window.VMP_CONFIG.texMercury, Venus: window.VMP_CONFIG.texVenus, Earth: window.VMP_CONFIG.texEarth, Mars: window.VMP_CONFIG.texMars, Jupiter: window.VMP_CONFIG.texJupiter, Saturn: window.VMP_CONFIG.texSaturn, Uranus: window.VMP_CONFIG.texUranus, Neptune: window.VMP_CONFIG.texNeptune };\r\n                \r\n                \/\/ Distances massively increased to push to skybox, sizes slightly reduced relative to distance\r\n                const planetData =[ \r\n                    { name: \"Mercury\", size: 1000, dist: 120000, color: 0xaaaaaa }, \r\n                    { name: \"Venus\", size: 1500, dist: 130000, color: 0xeebbaa }, \r\n                    { name: \"Earth\", size: 1600, dist: 140000, color: 0x2266ff }, \r\n                    { name: \"Mars\", size: 1200, dist: 150000, color: 0xff4422 }, \r\n                    { name: \"Jupiter\", size: 4000, dist: 170000, color: 0xddaa88 }, \r\n                    { name: \"Saturn\", size: 3500, dist: 190000, color: 0xeeddcc, ring: true }, \r\n                    { name: \"Uranus\", size: 2000, dist: 210000, color: 0x88ccff }, \r\n                    { name: \"Neptune\", size: 1900, dist: 230000, color: 0x2244ff } \r\n                ];\r\n\r\n                planetData.forEach((p) => {\r\n                    const mat = new THREE.MeshStandardMaterial({ color: p.color, roughness: 0.6, metalness: 0.1 });\r\n                    if(texMap[p.name]) { texLoader.load(getBustUrl(texMap[p.name]), t => { mat.map = t; mat.color.setHex(0xffffff); mat.needsUpdate = true; }); }\r\n                    else {\r\n                        const c = document.createElement('canvas'); c.width = 512; c.height = 512; const ctx = c.getContext('2d');\r\n                        for(let i = 0; i < 5000; i++) { ctx.fillStyle = `rgba(255,255,255,${Math.random()})`; ctx.fillRect(Math.random() * 512, Math.random() * 512, 2, 2); }\r\n                        mat.bumpMap = new THREE.CanvasTexture(c); mat.bumpScale = 2.0;\r\n                    }\r\n                    const meshGeo = new THREE.SphereGeometry(p.size, 32, 32); const mesh = new THREE.Mesh(meshGeo, mat);\r\n                    mesh.userData.isSelectable = true; mesh.name = p.name;\r\n                    if(p.ring) { const ringGeo = new THREE.RingGeometry(p.size * 1.3, p.size * 2.2, 64); const ringMat = new THREE.MeshStandardMaterial({ color: p.color, side: THREE.DoubleSide, transparent: true, opacity: 0.8 }); const ring = new THREE.Mesh(ringGeo, ringMat); ring.rotation.x = Math.PI \/ 2 - 0.2; mesh.add(ring); }\r\n                    \r\n                    mesh.position.set(p.dist, 30000, 0); \r\n                    planetsGroup.add(mesh);\r\n\r\n                    this.entities.planets.push({ mesh: mesh, dist: p.dist, angle: Math.random() * Math.PI * 2, speed: 0.05 + Math.random() * 0.05 });\r\n                });\r\n                this.scene.add(planetsGroup);\r\n            }\r\n\r\n            buildZodiacs() {\r\n                const zodiacGrp = new THREE.Group(); const zMat = new THREE.LineBasicMaterial({ color: 0x00ffff, transparent: true, opacity: 0.5 });\r\n                for(let z = 0; z < 12; z++) {\r\n                    const radius = 20000 + Math.random() * 5000;\r\n                    const angle1 = (z \/ 12) * Math.PI * 2;\r\n                    const angle2 = angle1 + 0.1;\r\n                    const angle3 = angle1 - 0.1;\r\n                    \r\n                    const points =[ \r\n                        new THREE.Vector3(Math.cos(angle1) * radius, 16000 + Math.random() * 4000, Math.sin(angle1) * radius), \r\n                        new THREE.Vector3(Math.cos(angle2) * radius, 16200 + Math.random() * 4000, Math.sin(angle2) * radius), \r\n                        new THREE.Vector3(Math.cos(angle3) * radius, 16400 + Math.random() * 4000, Math.sin(angle3) * radius) \r\n                    ];\r\n                    \r\n                    const lineGeo = new THREE.BufferGeometry().setFromPoints(points); const line = new THREE.Line(lineGeo, zMat);\r\n                    const sphereGeo = new THREE.SphereGeometry(100); const sphereMat = new THREE.MeshBasicMaterial({color:0xffffff});\r\n                    points.forEach(pt => { const s = new THREE.Mesh(sphereGeo, sphereMat); s.position.copy(pt); line.add(s); });\r\n                    zodiacGrp.add(line);\r\n                }\r\n                this.scene.add(zodiacGrp);\r\n            }\r\n\r\n            createCentralEcosystem() {\r\n                this.gpuOrb.group.userData.isSelectable = true; this.gpuOrb.group.name = \"Quantum_Orb\";\r\n                this.applyWPTransform(this.gpuOrb.group, 'orb', 0, 120, 800, 0, 0, 0); this.gpuOrb.group.scale.setScalar(12); this.scene.add(this.gpuOrb.group);\r\n                const mbGroup = new THREE.Group(); const sMat = new THREE.MeshPhysicalMaterial({ color: 0x050505, transparent: true, opacity: 0.8, transmission: 0.5 });\r\n                mbGroup.userData.isSelectable = true; mbGroup.name = \"Motherboards_Group\";\r\n\r\n                const mb1Geo = new THREE.PlaneGeometry(300, 300); const mb1Mat = new THREE.MeshBasicMaterial({ map: this.mb1.texture, transparent: true, blending: THREE.AdditiveBlending, side: THREE.DoubleSide });\r\n                this.mb1Mesh = new THREE.Mesh(mb1Geo, mb1Mat); const st1Geo = new THREE.BoxGeometry(320, 320, 20); const st1 = new THREE.Mesh(st1Geo, sMat); st1.position.z = -12; this.mb1Mesh.add(st1);\r\n                this.mb1Mesh.position.set(-350, 200, 800); this.mb1Mesh.rotation.y = Math.PI \/ 4; mbGroup.add(this.mb1Mesh);\r\n\r\n                const mb2Geo = new THREE.PlaneGeometry(360, 300); const mb2Mat = new THREE.MeshBasicMaterial({ map: this.mb2.texture, transparent: true, blending: THREE.AdditiveBlending, side: THREE.DoubleSide });\r\n                this.mb2Mesh = new THREE.Mesh(mb2Geo, mb2Mat); const st2Geo = new THREE.BoxGeometry(380, 320, 20); const st2 = new THREE.Mesh(st2Geo, sMat); st2.position.z = -12; this.mb2Mesh.add(st2);\r\n                this.mb2Mesh.position.set(350, 200, 800); this.mb2Mesh.rotation.y = -Math.PI \/ 4; mbGroup.add(this.mb2Mesh);\r\n\r\n                this.groupMap.motherboards = mbGroup; this.applyWPTransform(mbGroup, 'motherboards', 0, 0, 0, 0, 0, 0); this.scene.add(mbGroup);\r\n            }\r\n\r\n            buildGuardianAngels() {\r\n                const angelGeo = new THREE.SphereGeometry(15, 16, 16); const angelMat = new THREE.MeshBasicMaterial({color: 0xffffff});\r\n                if(window.VMP_CONFIG.texAngel) { texLoader.load(getBustUrl(window.VMP_CONFIG.texAngel), t => { angelMat.map = t; angelMat.needsUpdate = true; }); }\r\n                for(let a = 0; a < 30; a++) {\r\n                    const mesh = new THREE.Mesh(angelGeo, angelMat); const pLight = new THREE.PointLight(0xffffff, 2.0, 500); mesh.add(pLight);\r\n                    const haloGeo = new THREE.TorusGeometry(25, 2, 8, 24); const haloMat = new THREE.MeshBasicMaterial({color:0xffff00}); const halo = new THREE.Mesh(haloGeo, haloMat); halo.rotation.x = Math.PI \/ 2; halo.position.y = 22; mesh.add(halo);\r\n                    mesh.position.set((Math.random() - 0.5) * 20000, 8000 + Math.random() * 5000, (Math.random() - 0.5) * 20000); this.scene.add(mesh);\r\n                    this.entities.angels.push({ mesh: mesh, angle: Math.random() * Math.PI * 2, speed: 10 + Math.random() * 20, radius: 2000 + Math.random() * 8000, cx: mesh.position.x, cz: mesh.position.z, yOffset: mesh.position.y });\r\n                }\r\n            }\r\n\r\n            buildInfrastructure() {\r\n                this.infraGrp = new THREE.Group();\r\n\r\n                const wPlantGeo = new THREE.BoxGeometry(400, 200, 400);\r\n                const wPlantMat = new THREE.MeshStandardMaterial({color:0x333333});\r\n                const wPlant = new THREE.Mesh(wPlantGeo, wPlantMat);\r\n                wPlant.position.set(-2000, -100, 2000);\r\n                this.infraGrp.add(wPlant);\r\n\r\n                const pCoreGeo = new THREE.SphereGeometry(150, 32, 32);\r\n                const pCoreMat = new THREE.MeshStandardMaterial({ color:0x00ffff, emissive:0x00ffff, emissiveIntensity:0.5 });\r\n                const pCore = new THREE.Mesh(pCoreGeo, pCoreMat);\r\n                pCore.position.set(2000, -100, -2000);\r\n                this.infraGrp.add(pCore);\r\n\r\n                this.scene.add(this.infraGrp);\r\n            }\r\n\r\n            buildAdvancedTransport() {\r\n                this.skyHighway = new THREE.Group();\r\n                this.skyHighway.name = \"Sky_Hovercar_Highway\";\r\n                this.skyHighway.userData.isSelectable = true;\r\n                \r\n                const ringMat = new THREE.MeshStandardMaterial({ color: 0x00ffcc, emissive: 0x00aa88, emissiveIntensity: 1.5, wireframe: true });\r\n                const hCurve = new THREE.CatmullRomCurve3([\r\n                    new THREE.Vector3(-4000, 0, -4000), new THREE.Vector3(0, 500, -6000),\r\n                    new THREE.Vector3(4000, -200, -4000), new THREE.Vector3(6000, 400, 0),\r\n                    new THREE.Vector3(4000, 0, 4000), new THREE.Vector3(0, -400, 6000),\r\n                    new THREE.Vector3(-4000, 200, 4000), new THREE.Vector3(-6000, 0, 0),\r\n                    new THREE.Vector3(-4000, 0, -4000)\r\n                ], true);\r\n                \r\n                const sphPts = hCurve.getPoints(100).map(p => wrapToPlanet(p.x, p.z, p.y + 1200));\r\n                const sCurve = new THREE.CatmullRomCurve3(sphPts, true);\r\n\r\n                for(let i=0; i<100; i++) {\r\n                    const pt = sCurve.getPointAt(i\/100);\r\n                    const tang = sCurve.getTangentAt(i\/100);\r\n                    const ring = new THREE.Mesh(new THREE.TorusGeometry(80, 2, 8, 32), ringMat); \/\/ Thinned rings\r\n                    ring.position.copy(pt);\r\n                    const lookT = pt.clone().add(tang);\r\n                    ring.lookAt(lookT);\r\n                    this.skyHighway.add(ring);\r\n                }\r\n                \r\n                this.groupMap.sky_highway = this.skyHighway;\r\n                this.applyWPTransform(this.skyHighway, 'sky_highway', 0, 0, 0, 0, 0, 0);\r\n                this.scene.add(this.skyHighway);\r\n\r\n                const createHovercar = () => {\r\n                    const hCar = new THREE.Group();\r\n                    if(window.VMP_CONFIG.modelHovercar) {\r\n                        loadCustomModel(window.VMP_CONFIG.modelHovercar, obj => { if(obj) { obj.scale.setScalar(50); hCar.add(obj); } });\r\n                    } else {\r\n                        const b = new THREE.Mesh(new THREE.BoxGeometry(40, 15, 80), new THREE.MeshStandardMaterial({color:0xffffff, metalness:0.9}));\r\n                        const engL = new THREE.Mesh(new THREE.CylinderGeometry(8,8,60), new THREE.MeshStandardMaterial({color:0x333, emissive:0x00e5ff}));\r\n                        engL.rotation.x = Math.PI\/2; engL.position.set(-25, 0, -10);\r\n                        const engR = engL.clone(); engR.position.set(25, 0, -10);\r\n                        hCar.add(b, engL, engR);\r\n                    }\r\n                    return hCar;\r\n                };\r\n\r\n                for(let i=0; i<15; i++) {\r\n                    const hCar = createHovercar();\r\n                    hCar.userData = { progress: Math.random(), speed: 0.1 + Math.random()*0.1, curve: sCurve, highwayGrp: this.skyHighway };\r\n                    this.entities.hovercars.push(hCar);\r\n                    this.scene.add(hCar);\r\n                }\r\n\r\n                this.monorail = new THREE.Group();\r\n                this.monorail.name = \"City_Monorail_System\";\r\n                this.monorail.userData.isSelectable = true;\r\n\r\n                const mCurveFlat = new THREE.CatmullRomCurve3([\r\n                    new THREE.Vector3(-3000, 0, -3000), new THREE.Vector3(-1000, 0, -3000),\r\n                    new THREE.Vector3(1000, 0, -3000), new THREE.Vector3(3000, 0, -3000),\r\n                    new THREE.Vector3(3000, 0, -1000), new THREE.Vector3(3000, 0, 1000),\r\n                    new THREE.Vector3(3000, 0, 3000), new THREE.Vector3(1000, 0, 3000),\r\n                    new THREE.Vector3(-1000, 0, 3000), new THREE.Vector3(-3000, 0, 3000),\r\n                    new THREE.Vector3(-3000, 0, 1000), new THREE.Vector3(-3000, 0, -1000),\r\n                    new THREE.Vector3(-3000, 0, -3000)\r\n                ], true);\r\n\r\n                const mSphPts = mCurveFlat.getPoints(100).map(p => wrapToPlanet(p.x, p.z, p.y + 800));\r\n                const mCurve = new THREE.CatmullRomCurve3(mSphPts, true);\r\n\r\n                const trackMat = new THREE.MeshStandardMaterial({color: 0x444444, metalness: 0.8});\r\n                const mTrack = new THREE.Mesh(new THREE.TubeGeometry(mCurve, 100, 15, 8, true), trackMat); \/\/ Thinned track\r\n                this.monorail.add(mTrack);\r\n\r\n                const mPts = mCurve.getPoints(40);\r\n                mPts.forEach(pt => {\r\n                    const sup = new THREE.Mesh(new THREE.CylinderGeometry(5, 5, 800), trackMat); \/\/ Thinned supports\r\n                    sup.position.copy(pt);\r\n                    \r\n                    const normal = new THREE.Vector3().subVectors(sup.position, PLANET_CENTER).normalize();\r\n                    sup.position.sub(normal.multiplyScalar(400));\r\n                    alignToPlanet(sup);\r\n                    \r\n                    this.monorail.add(sup);\r\n                });\r\n\r\n                const stationMat = new THREE.MeshStandardMaterial({color: 0x222222, metalness: 0.9});\r\n                const mStation1 = new THREE.Mesh(new THREE.BoxGeometry(400, 100, 200), stationMat);\r\n                const s1Pos = wrapToPlanet(1000, -3000, 800);\r\n                mStation1.position.copy(s1Pos); alignToPlanet(mStation1); this.monorail.add(mStation1);\r\n                \r\n                const mStation2 = new THREE.Mesh(new THREE.BoxGeometry(400, 100, 200), stationMat);\r\n                const s2Pos = wrapToPlanet(-3000, 1000, 800);\r\n                mStation2.position.copy(s2Pos); alignToPlanet(mStation2); mStation2.rotateY(Math.PI\/2); this.monorail.add(mStation2);\r\n\r\n                this.groupMap.monorail_system = this.monorail;\r\n                this.applyWPTransform(this.monorail, 'monorail_system', 0, 0, 0, 0, 0, 0);\r\n                this.scene.add(this.monorail);\r\n\r\n                for(let i=0; i<3; i++) {\r\n                    const tGrp = new THREE.Group();\r\n                    if(window.VMP_CONFIG.modelTrain) {\r\n                        loadCustomModel(window.VMP_CONFIG.modelTrain, obj => { if(obj) { obj.scale.setScalar(20); tGrp.add(obj); } });\r\n                    } else {\r\n                        const car1 = new THREE.Mesh(new THREE.BoxGeometry(40, 50, 200), new THREE.MeshStandardMaterial({color:0xdddddd}));\r\n                        const car2 = new THREE.Mesh(new THREE.BoxGeometry(40, 50, 200), new THREE.MeshStandardMaterial({color:0xdddddd})); car2.position.z = 210;\r\n                        const car3 = new THREE.Mesh(new THREE.BoxGeometry(40, 50, 200), new THREE.MeshStandardMaterial({color:0xdddddd})); car3.position.z = -210;\r\n                        tGrp.add(car1, car2, car3);\r\n                    }\r\n                    tGrp.userData = { progress: (i * 0.33), speed: 0.05, curve: mCurve, railGrp: this.monorail };\r\n                    this.entities.trains.push(tGrp);\r\n                    this.scene.add(tGrp);\r\n                }\r\n\r\n                 const createAirplane = () => {\r\n                    const plane = new THREE.Group();\r\n                    if(window.VMP_CONFIG.modelAirplane) {\r\n                        loadCustomModel(window.VMP_CONFIG.modelAirplane, obj => { if(obj) { obj.scale.setScalar(50); plane.add(obj); } });\r\n                    } else {\r\n                        const fuselage = new THREE.Mesh(new THREE.CylinderGeometry(8, 10, 200), new THREE.MeshStandardMaterial({color: 0xdddddd, metalness: 0.8}));\r\n                        fuselage.rotation.z = Math.PI \/ 2;\r\n                        const wing = new THREE.Mesh(new THREE.BoxGeometry(250, 4, 30), new THREE.MeshStandardMaterial({color: 0xcccccc}));\r\n                        wing.position.z = 10;\r\n                        const tail = new THREE.Mesh(new THREE.BoxGeometry(60, 20, 5), new THREE.MeshStandardMaterial({color: 0xcccccc}));\r\n                        tail.position.set(0, 20, -90);\r\n                        plane.add(fuselage, wing, tail);\r\n                    }\r\n                    plane.userData = { angle: Math.random() * Math.PI * 2, radius: 18000 + Math.random()*5000, speed: 500 + Math.random() * 200 };\r\n                    return plane;\r\n                };\r\n\r\n                for(let i=0; i<5; i++) {\r\n                    const plane = createAirplane();\r\n                    plane.position.y = 8000 + Math.random() * 4000;\r\n                    this.scene.add(plane);\r\n                    this.entities.aircraft.push(plane);\r\n                }\r\n\r\n                const createHelicopter = () => {\r\n                    const heliGrp = new THREE.Group();\r\n                    const bodyGeo = new THREE.SphereGeometry(20, 32, 32); bodyGeo.scale(1, 1, 1.8);\r\n                    const body = new THREE.Mesh(bodyGeo, new THREE.MeshStandardMaterial({ color: 0xff0055, metalness: 0.8 }));\r\n                    body.rotation.z = Math.PI \/ 2; heliGrp.add(body);\r\n                    const tail = new THREE.Mesh(new THREE.BoxGeometry(40, 5, 5), new THREE.MeshStandardMaterial({ color: 0x333333 }));\r\n                    tail.position.set(30, 0, 0); heliGrp.add(tail);\r\n\r\n                    const bladeGrp = new THREE.Group();\r\n                    const blade = new THREE.Mesh(new THREE.BoxGeometry(80, 1, 4), new THREE.MeshStandardMaterial({ color: 0x111111 }));\r\n                    const blade2 = new THREE.Mesh(new THREE.BoxGeometry(4, 1, 80), new THREE.MeshStandardMaterial({ color: 0x111111 }));\r\n                    bladeGrp.add(blade, blade2); bladeGrp.position.set(0, 12, 0); heliGrp.add(bladeGrp);\r\n                    heliGrp.userData = { isHeli: true, blades: bladeGrp, angle: Math.random() * Math.PI * 2, radius: 6000 + Math.random()*6000, speed: 200 };\r\n                    return heliGrp;\r\n                };\r\n\r\n                for(let i=0; i<3; i++) {\r\n                    const heli = createHelicopter();\r\n                    heli.position.y = 3000 + Math.random() * 1000;\r\n                    this.scene.add(heli);\r\n                    this.entities.aircraft.push(heli);\r\n                }\r\n\r\n                for(let i=0; i<10; i++) {\r\n                    const boat = new THREE.Mesh(new THREE.BoxGeometry(100, 20, 40), new THREE.MeshStandardMaterial({ color: 0xffffff }));\r\n                    const cabin = new THREE.Mesh(new THREE.BoxGeometry(40, 20, 30), new THREE.MeshStandardMaterial({ color: 0x88ccff, transparent: true, opacity: 0.5 }));\r\n                    cabin.position.set(-10, 20, 0); boat.add(cabin);\r\n                    \r\n                    const fX = 10000 + (Math.random()-0.5)*15000;\r\n                    const fZ = (Math.random()-0.5)*20000;\r\n                    const sPos = wrapToPlanet(fX, fZ, 0);\r\n                    \r\n                    boat.position.copy(sPos);\r\n                    alignToPlanet(boat);\r\n                    \r\n                    boat.userData = { speed: 80, angle: Math.random() * Math.PI * 2, baseY: 0, fX: fX, fZ: fZ };\r\n                    this.scene.add(boat);\r\n                    this.entities.boats.push(boat);\r\n                }\r\n            }\r\n\r\n            buildCustomPolygons() {\r\n                if(!window.VMP_CONFIG.customPolygons || window.VMP_CONFIG.customPolygons.length === 0) return;\r\n                window.VMP_CONFIG.customPolygons.forEach(p => {\r\n                    let geo; const r = 50;\r\n                    switch(p.type) {\r\n                        case 'Tetrahedron': geo = new THREE.TetrahedronGeometry(r); break;\r\n                        case 'Octahedron': geo = new THREE.OctahedronGeometry(r); break;\r\n                        case 'Dodecahedron': geo = new THREE.DodecahedronGeometry(r); break;\r\n                        case 'Torus': geo = new THREE.TorusGeometry(r, 15, 16, 100); break;\r\n                        case 'TorusKnot': geo = new THREE.TorusKnotGeometry(r, 10, 100, 16); break;\r\n                        case 'Box': geo = new THREE.BoxGeometry(r * 2, r * 2, r * 2); break;\r\n                        default: geo = new THREE.IcosahedronGeometry(r); break;\r\n                    }\r\n                    const isWire = p.wireframe === 'yes';\r\n                    const mat = new THREE.MeshStandardMaterial({ color: p.color, wireframe: isWire, roughness: 0.4, metalness: 0.6 });\r\n                    const mesh = new THREE.Mesh(geo, mat);\r\n                    mesh.userData.isSelectable = true; mesh.name = `CustomPolygon_${p.type}`;\r\n                    mesh.position.set(p.pos_x, p.pos_y, p.pos_z); mesh.rotation.set(p.rot_x, p.rot_y, p.rot_z);\r\n                    mesh.scale.set(Math.max(0.01, p.scale_x || 1), Math.max(0.01, p.scale_y || 1), Math.max(0.01, p.scale_z || 1));\r\n                    if(!isWire) { mesh.castShadow = true; mesh.receiveShadow = true; }\r\n                    this.scene.add(mesh);\r\n                });\r\n            }\r\n\r\n            async initEarthAnimals(densityPercent) {\r\n                updateLoadStatus(\"Spawning Wildlife Ecosystem...\");\r\n                await yieldFrame();\r\n\r\n                const rabbitTex1 = createFurTexture('#8B5A2B'); const rabbitTex2 = createFurTexture('#808080');\r\n                const rGeoBody = new THREE.SphereGeometry(3, 16, 16); rGeoBody.scale(1, 0.8, 1.4);\r\n                const baseRabbits = parseInt(window.VMP_CONFIG.popRabbits);\r\n                const rabbitCount = Math.floor(baseRabbits * (densityPercent \/ 100));\r\n\r\n                for(let i = 0; i < rabbitCount; i++) {\r\n                    if (i % 5 === 0) await yieldFrame();\r\n                    const spawnRabbit = (grp) => {\r\n                        const w = new THREE.Group(); w.add(grp); w.userData.isSelectable = true; w.name=`Rabbit_${i}`;\r\n                        const burr = new THREE.Mesh(new THREE.CircleGeometry(6, 16), new THREE.MeshStandardMaterial({color: 0x2d1a11, roughness: 1.0}));\r\n                        burr.rotation.x = -Math.PI \/ 2; burr.position.y = 0.1; w.add(burr);\r\n                        \r\n                        const fX = (Math.random() - 0.5) * 12000;\r\n                        const fZ = 6000 + (Math.random() - 0.5) * 6000;\r\n                        const sPos = wrapToPlanet(fX, fZ, 0);\r\n                        \r\n                        w.position.copy(sPos);\r\n                        alignToPlanet(w);\r\n                        w.userData.rabbit = grp; w.userData.target = new THREE.Vector2(fX + (Math.random() - 0.5) * 500, fZ + (Math.random() - 0.5) * 500);\r\n                        w.userData.state = 'hop'; w.userData.timer = 0; w.userData.active = true;\r\n                        w.userData.fX = fX; w.userData.fZ = fZ;\r\n                        this.scene.add(w); this.entities.rabbits.push(w);\r\n                    };\r\n\r\n                    if(window.VMP_CONFIG.modelAnimal) { loadCustomModel(window.VMP_CONFIG.modelAnimal, (obj) => { if(obj) spawnRabbit(obj); }); }\r\n                    else {\r\n                        const grp = new THREE.Group();\r\n                        const furMat = new THREE.MeshStandardMaterial({ map: Math.random() > 0.5 ? rabbitTex1 : rabbitTex2, roughness: 1.0 });\r\n                        const body = new THREE.Mesh(rGeoBody, furMat); body.position.set(0, 3, 0); body.castShadow = true;\r\n                        const head = new THREE.Mesh(new THREE.SphereGeometry(2.5, 16, 16), furMat); head.scale.set(1, 1, 1.2); head.position.set(0, 5, 4); head.castShadow = true;\r\n                        const earShape = new THREE.Shape(); earShape.moveTo(0,0); earShape.quadraticCurveTo(1, 2, 0.5, 5); earShape.quadraticCurveTo(0, 6, -0.5, 5); earShape.quadraticCurveTo(-1, 2, 0, 0);\r\n                        const earGeo = new THREE.ExtrudeGeometry(earShape, { depth: 0.2, bevelEnabled: true, bevelThickness: 0.1, bevelSize: 0.1 });\r\n                        const earL = new THREE.Mesh(earGeo, furMat); earL.position.set(-1, 6, 3); earL.rotation.set(-0.2, -0.2, 0.2);\r\n                        const earR = new THREE.Mesh(earGeo, furMat); earR.position.set(1, 6, 3); earR.rotation.set(-0.2, 0.2, -0.2);\r\n                        const tail = new THREE.Mesh(new THREE.SphereGeometry(1.5), new THREE.MeshStandardMaterial({color:0xffffff, roughness:1.0})); tail.position.set(0, 3, -4.5);\r\n                        grp.add(body, head, earL, earR, tail); spawnRabbit(grp);\r\n                    }\r\n                }\r\n                \r\n                const baseTrees = parseInt(window.VMP_CONFIG.popTrees);\r\n                const treeCount = Math.floor(baseTrees * (densityPercent \/ 100));\r\n\r\n                for(let i = 0; i < treeCount; i++) {\r\n                    if (i % 5 === 0) await yieldFrame();\r\n                    const spawnTree = (t) => {\r\n                        let tx, tz, attempts = 0;\r\n                        do { tx = (Math.random() - 0.5) * 15000; tz = (Math.random() - 0.5) * 15000; attempts++; } while ((Math.abs(tx) < 2600 && Math.abs(tz) < 2600) || tx > 12000 && attempts < 50);\r\n                        const sPos = wrapToPlanet(tx, tz, 0);\r\n                        t.position.copy(sPos); \r\n                        alignToPlanet(t);\r\n                        t.userData.isSelectable = true; t.name=`Tree_${i}`; this.scene.add(t);\r\n                    };\r\n                    if(window.VMP_CONFIG.modelTree) { loadCustomModel(window.VMP_CONFIG.modelTree, (obj) => { if(obj) { obj.scale.setScalar(50); spawnTree(obj); } }); }\r\n                    else { spawnTree(buildUprightTree()); }\r\n                }\r\n\r\n                const addFlyer = (list, colorHex, scale, hOff, isButterfly) => {\r\n                    const grp = new THREE.Group(); const bMat = new THREE.MeshStandardMaterial({color: colorHex, roughness:0.7, side: THREE.DoubleSide});\r\n                    if(isButterfly) {\r\n                        const body = new THREE.Mesh(new THREE.CylinderGeometry(0.5, 0.5, 4, 8), bMat); body.rotation.x = Math.PI \/ 2;\r\n                        const wPlaneGeo = new THREE.PlaneGeometry(3,4);\r\n                        const wL = new THREE.Mesh(wPlaneGeo, bMat); wL.position.set(1.5, 0, 0);\r\n                        const wR = new THREE.Mesh(wPlaneGeo, bMat); wR.position.set(-1.5, 0, 0);\r\n                        grp.add(body, wL, wR); grp.userData = {wL, wR, isButterfly:true, baseRotZ: 0};\r\n                    } else {\r\n                        const body = new THREE.Mesh(new THREE.SphereGeometry(1.5, 16, 16), bMat); body.scale.set(1, 1, 2.66); body.castShadow = true;\r\n                        const head = new THREE.Mesh(new THREE.SphereGeometry(1.2, 16, 16), bMat); head.position.set(0, 0.5, 3);\r\n                        const beak = new THREE.Mesh(new THREE.ConeGeometry(0.4, 2, 8), new THREE.MeshStandardMaterial({color:0xffaa00})); beak.position.set(0, 0.5, 4.5); beak.rotation.x = Math.PI \/ 2;\r\n                        const wShape = new THREE.Shape(); wShape.moveTo(0,0); wShape.quadraticCurveTo(4, 1, 8, -2); wShape.quadraticCurveTo(4, -4, 0, 0);\r\n                        const wGeo = new THREE.ExtrudeGeometry(wShape, { depth: 0.1, bevelEnabled: false });\r\n                        const wLGrp = new THREE.Group(); wLGrp.position.set(0.5, 1.0, 0);\r\n                        const wL = new THREE.Mesh(wGeo, bMat); wL.castShadow = true; wLGrp.add(wL);\r\n                        const wRGrp = new THREE.Group(); wRGrp.position.set(-0.5, 1.0, 0);\r\n                        const wR = new THREE.Mesh(wGeo, bMat); wR.rotation.set(0, Math.PI, 0); wR.castShadow = true; wRGrp.add(wR);\r\n                        grp.add(body, head, beak, wLGrp, wRGrp); grp.userData = {wL: wLGrp, wR: wRGrp, isButterfly:false, baseRotZ: 0};\r\n                    }\r\n                    \r\n                    const fX = (Math.random() - 0.5) * 10000;\r\n                    const fZ = (Math.random() - 0.5) * 10000;\r\n                    const fY = hOff + Math.random() * 800;\r\n                    \r\n                    const sPos = wrapToPlanet(fX, fZ, fY);\r\n                    grp.position.copy(sPos); \r\n                    alignToPlanet(grp);\r\n                    grp.scale.setScalar(scale);\r\n                    \r\n                    this.scene.add(grp);\r\n                    list.push({ grp: grp, wL: grp.userData.wL, wR: grp.userData.wR, angle: Math.random() * Math.PI * 2, speed: 100 + Math.random() * 100, offset: Math.random() * 10, isButt: grp.userData.isButterfly, fX: fX, fZ: fZ, fY: fY });\r\n                };\r\n\r\n                const baseBirds = parseInt(window.VMP_CONFIG.popBirds);\r\n                const birdCount = Math.floor(baseBirds * (densityPercent \/ 100));\r\n                for(let i = 0; i < birdCount; i++) addFlyer(this.entities.birds, new THREE.Color(window.VMP_CONFIG.birdColor || '#ffffff').getHex(), 4, 800, false);\r\n                \r\n                const baseButterflies = parseInt(window.VMP_CONFIG.popButterflies);\r\n                const butterflyCount = Math.floor(baseButterflies * (densityPercent \/ 100));\r\n                for(let i = 0; i < butterflyCount; i++) addFlyer(this.entities.butterflies, 0xff00aa, 3.0, 50, true);\r\n            }\r\n\r\n            buildWeatherSystem() {\r\n                const ptGeo = new THREE.BufferGeometry(); const pts =[];\r\n                for(let i = 0; i < 4000; i++) { pts.push((Math.random() - 0.5) * 30000, Math.random() * 8000, (Math.random() - 0.5) * 30000); }\r\n                ptGeo.setAttribute('position', new THREE.Float32BufferAttribute(pts, 3));\r\n\r\n                const snowTexUrl = window.VMP_CONFIG.texSnowflake;\r\n                if (snowTexUrl && snowTexUrl.length > 5) {\r\n                    const tex = texLoader.load(getBustUrl(snowTexUrl));\r\n                    this.weatherMat = new THREE.PointsMaterial({ map: tex, size: 40, transparent: true, opacity: 0, depthWrite: false, blending: THREE.AdditiveBlending });\r\n                } else { this.weatherMat = new THREE.PointsMaterial({ color: 0xffffff, size: 20, transparent: true, opacity: 0 }); }\r\n                \r\n                this.weatherSystem = new THREE.Points(ptGeo, this.weatherMat); this.scene.add(this.weatherSystem);\r\n\r\n                const rainGeo = new THREE.BufferGeometry(); const rPts =[];\r\n                for(let i = 0; i < 4000; i++) { rPts.push((Math.random() - 0.5) * 30000, Math.random() * 8000, (Math.random() - 0.5) * 30000); }\r\n                rainGeo.setAttribute('position', new THREE.Float32BufferAttribute(rPts, 3));\r\n                \r\n                const rainTexUrl = window.VMP_CONFIG.texRaindrop;\r\n                if(rainTexUrl && rainTexUrl.length > 5) {\r\n                     const tex = texLoader.load(getBustUrl(rainTexUrl));\r\n                     this.rainMat = new THREE.PointsMaterial({ map: tex, size: 20, transparent: true, opacity: 0, depthWrite: false, blending: THREE.AdditiveBlending });\r\n                } else {\r\n                     this.rainMat = new THREE.PointsMaterial({ color: 0x88ccff, size: 10, transparent: true, opacity: 0 });\r\n                     this.rainSystem = new THREE.Points(rainGeo, this.rainMat); this.rainSystem.scale.set(1, 25, 1); \r\n                }\r\n                this.rainSystem = new THREE.Points(rainGeo, this.rainMat); this.scene.add(this.rainSystem);\r\n\r\n                const hPts =[];\r\n                for(let i=0; i<10000; i++) {\r\n                    const angle = Math.random() * Math.PI * 2; const r = Math.pow(Math.random(), 2) * 15000;\r\n                    const y = (r \/ 15000) * 4000 + Math.random() * 1000; hPts.push(Math.cos(angle) * r, y, Math.sin(angle) * r);\r\n                }\r\n                const hGeo = new THREE.BufferGeometry(); hGeo.setAttribute('position', new THREE.Float32BufferAttribute(hPts, 3));\r\n                this.hurricaneMat = new THREE.PointsMaterial({ color: 0x8899aa, size: 80, transparent: true, opacity: 0, blending: THREE.AdditiveBlending, depthWrite: false });\r\n                this.hurricaneSys = new THREE.Points(hGeo, this.hurricaneMat); this.hurricaneSys.position.set(0, 2000, 0); this.scene.add(this.hurricaneSys);\r\n\r\n                this.lightningLight = new THREE.DirectionalLight(0xffffff, 0); this.lightningLight.position.set(0, 15000, 0); this.scene.add(this.lightningLight);\r\n\r\n                this.lensDrops =[];\r\n                const leafTexUrl = window.VMP_CONFIG.texLeaf; let leafMatTemplate = null;\r\n                if(leafTexUrl && leafTexUrl.length > 5) {\r\n                    const tex = texLoader.load(getBustUrl(leafTexUrl));\r\n                    leafMatTemplate = new THREE.MeshBasicMaterial({ map: tex, transparent: true, opacity: 0, depthTest: false, side: THREE.DoubleSide, alphaTest: 0.1 });\r\n                } else {\r\n                    const leafShape = new THREE.Shape(); leafShape.moveTo(0, 0); leafShape.quadraticCurveTo(0.2, 0.4, 0, 1.0); leafShape.quadraticCurveTo(-0.2, 0.4, 0, 0);\r\n                    leafMatTemplate = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0, depthTest: false, side: THREE.DoubleSide });\r\n                }\r\n\r\n                for(let i=0; i<60; i++) {\r\n                    const isLeaf = i < 25; let dropGeo, dropMat;\r\n                    if (isLeaf) {\r\n                        dropGeo = leafTexUrl ? new THREE.PlaneGeometry(1, 1) : new THREE.ShapeGeometry(leafShape);\r\n                        dropMat = leafMatTemplate.clone();\r\n                        if(!leafTexUrl) dropMat.color.setHex([0xff4500, 0xff8c00, 0xd2691e, 0xb22222, 0x8b0000][Math.floor(Math.random() * 5)]);\r\n                    } else {\r\n                        dropGeo = new THREE.PlaneGeometry(0.1, 1.5);\r\n                        dropMat = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0, depthTest: false });\r\n                    }\r\n\r\n                    const drop = new THREE.Mesh(dropGeo, dropMat);\r\n                    drop.position.set((Math.random() - 0.5) * 15, 10 + Math.random() * 10, -10);\r\n                    drop.userData = { xBase: drop.position.x, yStart: 10 + Math.random() * 5, speed: isLeaf ? 1 + Math.random() * 2 : 15 + Math.random() * 15, isLeaf: isLeaf, windOffset: Math.random() * Math.PI * 2, isStuck: false, stuckTimer: 0 };\r\n                    if(isLeaf) drop.scale.setScalar(0.5 + Math.random()*0.5);\r\n                    this.lensGroup.add(drop); this.lensDrops.push(drop);\r\n                }\r\n            }\r\n\r\n            buildDogs() {\r\n                const buildVoxelFrenchie = (bodyColor) => {\r\n                    const dGrp = new THREE.Group(); dGrp.userData.isSelectable = true;\r\n                    const m = { main: new THREE.MeshStandardMaterial({ color: bodyColor, roughness: 0.8 }), dark: new THREE.MeshStandardMaterial({ color: 0x222222 }), white: new THREE.MeshStandardMaterial({ color: 0xffffff }), purple: new THREE.MeshStandardMaterial({ color: 0x6200ea, emissive: 0x6200ea, emissiveIntensity: 0.8 }), black: new THREE.MeshStandardMaterial({ color: 0x000000 }), inner: new THREE.MeshStandardMaterial({ color: 0x7cfedc }) };\r\n                    const body = new THREE.Mesh(new THREE.BoxGeometry(10, 8, 18), m.main); body.position.y = 5; dGrp.add(body); \r\n                    const tail = new THREE.Mesh(new THREE.BoxGeometry(3, 3, 3), m.main); tail.position.set(0, 6, -9); dGrp.add(tail);\r\n                    const hGrp = new THREE.Group(); hGrp.position.set(0, 9, 8);\r\n                    const addPx = (w, h, d, x, y, z, mat) => { const px = new THREE.Mesh(new THREE.BoxGeometry(w, h, d), mat); px.position.set(x, y, z); hGrp.add(px); };\r\n                    addPx(10, 10, 8, 0, 2, 0, m.main); addPx(11, 7, 2, 0, -1, 4.5, m.white); addPx(2, 5, 1.2, 0, 0, 5, m.dark); addPx(3, 2, 1.2, 0, -1, 5.5, m.dark); addPx(4, 2, 1, 0, -3.5, 5.2, m.purple);\r\n                    const addFreckle = (x, y) => { addPx(0.5, 0.5, 0.2, x, y, 5.6, m.dark); };\r\n                    addFreckle(3.5, -0.5); addFreckle(4.5, -1.8); addFreckle(2.8, -2.5); addFreckle(-3.5, -0.5); addFreckle(-4.5, -1.8); addFreckle(-2.8, -2.5);\r\n                    const addEye = (side) => { addPx(2.5, 2.5, 0.5, side * 2.8, 2, 4.1, m.white); addPx(1.2, 1.2, 0.6, side * 2.8, 2, 4.2, m.black); }; addEye(1); addEye(-1);\r\n                    const addEar = (side) => { const e = new THREE.Group(); const outer = new THREE.Mesh(new THREE.BoxGeometry(4.5, 9, 1.5), m.main); const inner = new THREE.Mesh(new THREE.BoxGeometry(2.8, 7, 0.5), m.inner); inner.position.z = 0.8; e.add(outer, inner); e.position.set(side * 4.5, 9, -1); hGrp.add(e); }; addEar(1); addEar(-1);\r\n                    dGrp.add(hGrp); dGrp.userData = { head: hGrp, legs:[] };\r\n                    const positions =[{x:3.5,z:7}, {x:-3.5,z:7}, {x:3.5,z:-7}, {x:-3.5,z:-7}];\r\n                    positions.forEach(pos => { const l = new THREE.Group(); l.position.set(pos.x, 2, pos.z); const lm = new THREE.Mesh(new THREE.BoxGeometry(3, 4, 3), m.main); lm.position.y = -2; l.add(lm); dGrp.add(l); dGrp.userData.legs.push(l); });\r\n                    return dGrp;\r\n                };\r\n\r\n                this.dog1 = buildVoxelFrenchie(0x3E2723); this.dog1.name = \"Solid_Gold_Dog_God\"; \r\n                this.scene.add(this.dog1); \r\n                this.dog1.userData.fX = -1500; this.dog1.userData.fZ = -1500; this.dog1.userData.target = new THREE.Vector2(-1500, -1500); this.dog1.userData.timer = 0;\r\n                \r\n                this.dog2 = buildVoxelFrenchie(0xff66cc); this.dog2.name = \"Jara_The_Pink_Dog\"; \r\n                this.scene.add(this.dog2);\r\n                this.dog2.userData.fX = 1500; this.dog2.userData.fZ = 1500; this.dog2.userData.target = new THREE.Vector2(1500, 1500); this.dog2.userData.timer = 0;\r\n                \r\n                this.applyWPTransform(this.dog1, 'dog', 0, 0, 0);\r\n                this.applyWPTransform(this.dog2, 'dog_jara', 0, 0, 0);\r\n            }\r\n\r\n            getNewRabbitTarget(w) { w.userData.target.set(w.userData.fX + (Math.random() - 0.5) * 500, w.userData.fZ + (Math.random() - 0.5) * 500); }\r\n\r\n            startCityRebuild(newDensity, corpNamesJsonString = null) {\r\n                if (this.isAssemblingCity) return; \r\n                TerminalLogger.log(`[AI City] Received command to build with density ${newDensity}.`, 'sys');\r\n\r\n                const loadingOverlay = document.getElementById(`loading_${INSTANCE_ID}`);\r\n                if (loadingOverlay) {\r\n                    loadingOverlay.style.display = 'flex';\r\n                    loadingOverlay.style.opacity = '1';\r\n                    loadingOverlay.style.pointerEvents = 'none';\r\n                    updateLoadStatus(`Construction crew calculating smart city blueprints...`);\r\n                }\r\n\r\n                if (this.cityGrp) {\r\n                    this.scene.remove(this.cityGrp);\r\n                    this.collidableMeshes = this.collidableMeshes.filter(m => !m.userData.isCityBldg);\r\n                    this.cityGrp.traverse(obj => {\r\n                        if(obj.geometry) obj.geometry.dispose();\r\n                        if(obj.material) {\r\n                            if(Array.isArray(obj.material)) obj.material.forEach(m=>m.dispose());\r\n                            else obj.material.dispose();\r\n                        }\r\n                     });\r\n                }\r\n                if (this.entities.pedestrians) this.entities.pedestrians.forEach(p => this.scene.remove(p));\r\n                if (this.entities.workers) this.entities.workers.forEach(w => this.scene.remove(w));\r\n                \r\n                this.cityBuildings =[];\r\n                this.entities.pedestrians =[];\r\n                this.entities.workers =[];\r\n\r\n                if (corpNamesJsonString) {\r\n                    try {\r\n                        const match = corpNamesJsonString.match(\/\\[.*?\\]\/s);\r\n                        if (match) {\r\n                            this.currentCorps = JSON.parse(match[0]);\r\n                        }\r\n                    } catch(e) {\r\n                        TerminalLogger.log(`[AI City] Fallback corporation names activated.`, 'warn');\r\n                        this.currentCorps =[\"NEON CORP\", \"CYBERNETICS INC\", \"OMNICORP\", \"NEXUS\", \"AERODYNE\"];\r\n                    }\r\n                } else {\r\n                    this.currentCorps =[\"NEON CORP\", \"CYBERNETICS INC\", \"OMNICORP\", \"NEXUS\", \"AERODYNE\"];\r\n                }\r\n\r\n                if (!this.cityWorker) { this.initCityWorker(); }\r\n                this.cityWorker.postMessage({ action: 'buildCity', densityPercent: newDensity, config: window.VMP_CONFIG });\r\n            }\r\n\r\n            initCityWorker() {\r\n                const blob = new Blob([vmpWorkerScript], { type: 'application\/javascript' });\r\n                this.cityWorker = new Worker(URL.createObjectURL(blob));\r\n\r\n                this.cityWorker.onmessage = (e) => {\r\n                    if (e.data.action === 'cityBuilt') {\r\n                        TerminalLogger.log(\"[AI City] Blueprints received. Assembling city structure...\", \"sys\");\r\n                        updateLoadStatus(\"Constructing Smart Geometry...\");\r\n                        this.isAssemblingCity = true;\r\n                        this.cityAssemblyGenerator = this.assembleCityFromBlueprints(e.data.blueprints);\r\n                    }\r\n                };\r\n            }\r\n\r\n            *assembleCityFromBlueprints(blueprints) {\r\n                this.cityGrp = new THREE.Group(); this.cityGrp.name = \"Cyber_City_Root\";\r\n                const mats = {\r\n                    road: loadAdvancedMat('https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-content\/uploads\/2026\/03\/streetroad.jpg', '', 0x444444, 0.4, 0.6, 2, 20), \r\n                    sidewalk: new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.9, metalness: 0.1 }), \r\n                    darkGlass: new THREE.MeshPhysicalMaterial({ color: 0x010101, metalness: 1.0, roughness: 0.0, transmission: 0.8 }),\r\n                    houseBase: new THREE.MeshStandardMaterial({ color: 0x222222, roughness: 0.8 }),\r\n                    roofMat: new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.9 }),\r\n                    doorMat: new THREE.MeshStandardMaterial({ color: 0x000000 }),\r\n                    neonBase: new THREE.MeshBasicMaterial({ color: 0xffffff }) \r\n                };\r\n\r\n                this.districtMats = {};\r\n                for(let i=1; i<=5; i++) {\r\n                    const dTexList = window.VMP_CONFIG.districtTextures[`district${i}`].textures;\r\n                    if(dTexList && dTexList.length > 0) {\r\n                        this.districtMats[i] = dTexList.map(url => loadAdvancedMat(url, '', 0x222222, 0.2, 0.8, 2));\r\n                    } else {\r\n                        this.districtMats[i] =[loadAdvancedMat(window.VMP_CONFIG.cityBldgTexture, '', 0x222222, 0.2, 0.8, 1)];\r\n                    }\r\n                }\r\n\r\n                for (const road of blueprints.roads) {\r\n                    const geo = new THREE.BoxGeometry(road.width, 2, road.length, 64, 1, 64);\r\n                    const flatX = road.x || 0;\r\n                    const flatZ = road.z || 0;\r\n                    \r\n                    const mesh = new THREE.Mesh(geo, mats.road);\r\n                    mesh.userData.isSelectable = true; mesh.name = road.type === 'avenue' ? \"Avenue\" : \"Street\";\r\n                    mesh.position.copy(wrapToPlanet(flatX, flatZ, 1.0));\r\n                    alignToPlanet(mesh);\r\n                    if(road.x) mesh.rotateY(0); else mesh.rotateY(Math.PI\/2);\r\n                    \r\n                    this.cityGrp.add(mesh);\r\n                    if (road.type === 'avenue') {\r\n                        const swLGeo = new THREE.BoxGeometry(30, 4, road.length, 1, 1, 64);\r\n                        bendBoxGeometryToPlanet(swLGeo, 2.0);\r\n                        const swL = new THREE.Mesh(swLGeo, mats.sidewalk); \r\n                        swL.userData.isSelectable = true; swL.name = \"Sidewalk\";\r\n                        swL.position.copy(wrapToPlanet(flatX - road.width\/2 - 15, flatZ, 0));\r\n                        alignToPlanet(swL);\r\n                        \r\n                        const swRGeo = new THREE.BoxGeometry(30, 4, road.length, 1, 1, 64);\r\n                        bendBoxGeometryToPlanet(swRGeo, 2.0);\r\n                        const swR = new THREE.Mesh(swRGeo, mats.sidewalk); \r\n                        swR.userData.isSelectable = true; swR.name = \"Sidewalk\";\r\n                        swR.position.copy(wrapToPlanet(flatX + road.width\/2 + 15, flatZ, 0));\r\n                        alignToPlanet(swR);\r\n                        \r\n                        this.cityGrp.add(swL, swR);\r\n                    }\r\n                }\r\n                yield;\r\n                \r\n                for (const light of blueprints.trafficLights) {\r\n                    const tlGrp = new THREE.Group();\r\n                    tlGrp.userData.isSelectable = true; tlGrp.name = \"Traffic_Light\";\r\n                    \r\n                    const pole = new THREE.Mesh(new THREE.CylinderGeometry(2, 2, 80), new THREE.MeshStandardMaterial({color:0x222})); \r\n                    pole.position.y = 40; tlGrp.add(pole);\r\n\r\n                    const arm = new THREE.Mesh(new THREE.CylinderGeometry(1.5, 1.5, 60), new THREE.MeshStandardMaterial({color:0x222}));\r\n                    arm.rotation.z = Math.PI \/ 2;\r\n                    arm.position.set(30, 80, 0); tlGrp.add(arm);\r\n\r\n                    const box = new THREE.Mesh(new THREE.BoxGeometry(10, 30, 10), new THREE.MeshStandardMaterial({color:0x000})); \r\n                    box.position.set(55, 65, 5); tlGrp.add(box);\r\n\r\n                    const camBox = new THREE.Mesh(new THREE.BoxGeometry(6, 4, 8), new THREE.MeshStandardMaterial({color:0x444}));\r\n                    camBox.position.set(10, 82, 0);\r\n                    const camLens = new THREE.Mesh(new THREE.CylinderGeometry(1.5, 1.5, 2), new THREE.MeshStandardMaterial({color:0x111}));\r\n                    camLens.rotation.x = Math.PI \/ 2; camLens.position.set(0, 0, 4); camBox.add(camLens);\r\n                    tlGrp.add(camBox);\r\n\r\n                    const lGeo = new THREE.CylinderGeometry(3, 3, 2, 16); lGeo.rotateX(Math.PI\/2);\r\n                    const red = new THREE.Mesh(lGeo, new THREE.MeshStandardMaterial({color:0xff0000, emissive:0xff0000, emissiveIntensity:0})); red.position.set(0, 10, 5); box.add(red);\r\n                    const yel = new THREE.Mesh(lGeo, new THREE.MeshStandardMaterial({color:0xffaa00, emissive:0xffaa00, emissiveIntensity:0})); yel.position.set(0, 0, 5); box.add(yel);\r\n                    const grn = new THREE.Mesh(lGeo, new THREE.MeshStandardMaterial({color:0x00ff00, emissive:0x00ff00, emissiveIntensity:2})); grn.position.set(0, -10, 5); box.add(grn);\r\n                    \r\n                    if(this.font) {\r\n                        const signGeo = new THREE.PlaneGeometry(30, 8);\r\n                        const signMat = new THREE.MeshStandardMaterial({color:0x006622});\r\n                        const signMesh = new THREE.Mesh(signGeo, signMat);\r\n                        signMesh.position.set(30, 75, 5);\r\n                        \r\n                        const textGeo = new TextGeometry(`CYBER AVE`, { font: this.font, size: 4, height: 0.1 });\r\n                        textGeo.center();\r\n                        const textMesh = new THREE.Mesh(textGeo, new THREE.MeshBasicMaterial({ color: 0xffffff }));\r\n                        textMesh.position.z = 0.1;\r\n                        signMesh.add(textMesh);\r\n                        tlGrp.add(signMesh);\r\n                    }\r\n\r\n                    tlGrp.position.copy(wrapToPlanet(light.x, light.z, 0));\r\n                    alignToPlanet(tlGrp);\r\n                    tlGrp.rotateY(light.dir);\r\n\r\n                    this.cityGrp.add(tlGrp);\r\n                    this.trafficLightSystem.push({ mesh: tlGrp, redMesh: red, yellowMesh: yel, greenMesh: grn, x: light.x, z: light.z, dir: light.dir, state: 'GREEN', nodeId: light.nodeId });\r\n                }\r\n                yield;\r\n\r\n                for (const b of blueprints.buildings) {\r\n                    if (b.type === 'cyber_tower') { this.buildCyberTower(b, mats, this.cityGrp); } \r\n                    else if (b.type === 'house') { this.buildResidentialHouse(b, mats, this.cityGrp); }\r\n                    yield; \r\n                }\r\n                \r\n                this.groupMap.city = this.cityGrp;\r\n                this.applyWPTransform(this.cityGrp, 'city', 0, 0, 0, 0, 0, 0);\r\n                this.scene.add(this.cityGrp);\r\n                this.needsCollisionUpdate = true;\r\n            }\r\n\r\n            buildResidentialHouse(b, mats, grp) {\r\n                const houseGrp = new THREE.Group(); houseGrp.userData.isSelectable = true; houseGrp.name = b.isMansion ? \"Mansion\" : \"House\"; \r\n                \r\n                houseGrp.position.copy(wrapToPlanet(b.x, b.z, 0));\r\n                alignToPlanet(houseGrp);\r\n                \r\n                const houseBody = new THREE.Mesh(new THREE.BoxGeometry(b.w, b.h, b.d), mats.houseBase); houseBody.position.y = b.h \/ 2; houseGrp.add(houseBody);\r\n                const roof = new THREE.Mesh(new THREE.ConeGeometry(b.w * 0.8, b.h * 0.5, 4), mats.roofMat); roof.position.y = b.h + (b.h * 0.25); roof.rotation.y = Math.PI \/ 4; houseGrp.add(roof);\r\n\r\n                const door = new THREE.Mesh(new THREE.BoxGeometry(20, 40, 2), mats.doorMat); door.position.set(0, 20, b.d\/2 + 1); houseGrp.add(door);\r\n                const doorWorldPos = wrapToPlanet(b.x, b.z + b.d\/2 + 10, 20); this.doors.push({ pos: doorWorldPos, building: houseGrp, flatX: b.x, flatZ: b.z + b.d\/2 + 10 });\r\n\r\n                if (b.isMansion) {\r\n                    const garageGrp = new THREE.Group();\r\n                    const gBody = new THREE.Mesh(new THREE.BoxGeometry(100, 60, 80), mats.houseBase); gBody.position.set(-b.w\/2 - 50, 30, 0);\r\n                    for(let i=0; i<3; i++) { const gDoor = new THREE.Mesh(new THREE.BoxGeometry(25, 45, 2), new THREE.MeshStandardMaterial({color:0x333333})); gDoor.position.set(-b.w\/2 - 85 + (i*30), 22.5, 41); garageGrp.add(gDoor); }\r\n                    garageGrp.add(gBody); houseGrp.add(garageGrp);\r\n                    const pool = new THREE.Mesh(new THREE.PlaneGeometry(80, 120), new THREE.MeshStandardMaterial({color:0x00e5ff, transparent:true, opacity:0.8, emissive:0x0055aa})); pool.rotation.x = -Math.PI\/2; pool.position.set(0, 2, -b.d\/2 - 80); houseGrp.add(pool);\r\n                }\r\n\r\n                houseBody.userData.isCityBldg = true;\r\n                this.collidableMeshes.push(houseBody);\r\n\r\n                const sLight = new THREE.PointLight(0x00e5ff, 0, 500); sLight.position.set(0, b.h + 20, 0); houseGrp.add(sLight);\r\n                houseGrp.userData.smartLight = sLight; houseGrp.userData.isSmartHouse = true;\r\n                grp.add(houseGrp); this.cityBuildings.push({ type: 'house', mesh: houseGrp });\r\n            }\r\n\r\n            buildCyberTower(b, mats, grp) {\r\n                const bldgGroup = new THREE.Group(); bldgGroup.userData.isSelectable = true; bldgGroup.name = \"Smart_Cyber_Tower\"; \r\n                \r\n                bldgGroup.position.copy(wrapToPlanet(b.x, b.z, 0));\r\n                alignToPlanet(bldgGroup);\r\n                \r\n                const lobbyHeight = 100;\r\n                const lobbyW = b.w + 20; const lobbyD = b.d + 20;\r\n                const dMatList = this.districtMats[b.district] ||[mats.darkGlass];\r\n                const bMat = dMatList[Math.floor(Math.random() * dMatList.length)];\r\n\r\n                const lobby = new THREE.Mesh(new THREE.BoxGeometry(lobbyW, lobbyHeight, lobbyD), bMat); \r\n                lobby.position.y = lobbyHeight \/ 2; bldgGroup.add(lobby);\r\n                lobby.userData.isCityBldg = true; this.collidableMeshes.push(lobby);\r\n\r\n                const coreHeight = b.h - lobbyHeight;\r\n                const core = new THREE.Mesh(new THREE.BoxGeometry(b.w, coreHeight, b.d), bMat); \r\n                core.position.y = lobbyHeight + (coreHeight \/ 2); bldgGroup.add(core);\r\n                core.userData.isCityBldg = true; this.collidableMeshes.push(core);\r\n\r\n                \/\/ External Elevator Shaft\r\n                if (Math.random() > 0.5) {\r\n                    const shaftMat = new THREE.MeshStandardMaterial({color: 0x333333, metalness: 0.8});\r\n                    const shaft = new THREE.Mesh(new THREE.BoxGeometry(30, coreHeight, 30), shaftMat);\r\n                    shaft.position.set(b.w\/2 + 15, lobbyHeight + (coreHeight\/2), 0);\r\n                    bldgGroup.add(shaft);\r\n                    \r\n                    const elev = new THREE.Mesh(new THREE.BoxGeometry(32, 40, 32), new THREE.MeshBasicMaterial({color: 0x00e5ff}));\r\n                    elev.position.set(b.w\/2 + 15, lobbyHeight + (Math.random()*coreHeight), 0);\r\n                    bldgGroup.add(elev);\r\n                }\r\n\r\n                \/\/ Roof Dome \/ Lattice Antenna\r\n                if (Math.random() > 0.6) {\r\n                    const roofDecoGrp = new THREE.Group();\r\n                    roofDecoGrp.position.y = lobbyHeight + coreHeight;\r\n                    \r\n                    if (Math.random() > 0.5) {\r\n                        const dome = new THREE.Mesh(new THREE.SphereGeometry(b.w * 0.3, 32, 16, 0, Math.PI*2, 0, Math.PI\/2), new THREE.MeshStandardMaterial({color: 0x444444, metalness: 0.9, roughness: 0.6}));\r\n                        const ring = new THREE.Mesh(new THREE.TorusGeometry(b.w * 0.35, 5, 16, 32), new THREE.MeshBasicMaterial({color: new THREE.Color(b.neonColor)}));\r\n                        ring.rotation.x = Math.PI\/2;\r\n                        roofDecoGrp.add(dome, ring);\r\n                    } else {\r\n                        const antennaMat = new THREE.MeshStandardMaterial({color: 0x222222});\r\n                        const base = new THREE.Mesh(new THREE.CylinderGeometry(20, 20, 50), antennaMat); base.position.y = 25;\r\n                        const spire = new THREE.Mesh(new THREE.CylinderGeometry(2, 2, 400), antennaMat); spire.position.y = 250;\r\n                        const dish = new THREE.Mesh(new THREE.SphereGeometry(30, 16, 16, 0, Math.PI), antennaMat); dish.position.set(20, 150, 0); dish.rotation.z = Math.PI\/4;\r\n                        const beacon = new THREE.Mesh(new THREE.SphereGeometry(10), new THREE.MeshBasicMaterial({color: 0xff0000})); beacon.position.y = 450;\r\n                        roofDecoGrp.add(base, spire, dish, beacon);\r\n                    }\r\n                    bldgGroup.add(roofDecoGrp);\r\n                }\r\n\r\n                \/\/ Elevated Walkways (Bridges)\r\n                if (Math.random() > 0.8) {\r\n                    const bridgeMat = new THREE.MeshStandardMaterial({color: 0x111111, metalness: 0.8});\r\n                    const bridge = new THREE.Mesh(new THREE.BoxGeometry(30, 20, 400), bridgeMat);\r\n                    bridge.position.set(0, lobbyHeight + 200 + (Math.random()*400), b.d\/2 + 200);\r\n                    bldgGroup.add(bridge);\r\n                }\r\n\r\n                const floors = Math.floor(coreHeight \/ 60);\r\n                const balcMat = new THREE.MeshStandardMaterial({color: 0x050505, metalness: 0.8});\r\n                for(let f=1; f<floors; f++) {\r\n                    if (Math.random() > 0.3) continue;\r\n                    const bY = lobbyHeight + (f * 60);\r\n                    const balc = new THREE.Mesh(new THREE.BoxGeometry(b.w + 10, 5, b.d + 10), balcMat);\r\n                    balc.position.y = bY;\r\n                    bldgGroup.add(balc);\r\n                }\r\n\r\n                const door = new THREE.Mesh(new THREE.BoxGeometry(80, 60, 5), mats.doorMat); door.position.set(0, 30, lobbyD\/2 + 1); bldgGroup.add(door);\r\n                const doorWorldPos = wrapToPlanet(b.x, b.z + lobbyD\/2 + 20, 30); this.doors.push({ pos: doorWorldPos, building: bldgGroup, flatX: b.x, flatZ: b.z + lobbyD\/2 + 20 });\r\n\r\n                const neonMat = new THREE.MeshBasicMaterial({ color: new THREE.Color(b.neonColor) });\r\n                const numGreebles = 10 + Math.floor(Math.random() * 20); \r\n                for(let i=0; i<numGreebles; i++) {\r\n                    const gw = b.w * (0.1 + Math.random() * 0.4); const gh = coreHeight * (0.05 + Math.random() * 0.2); const gd = b.d * (0.1 + Math.random() * 0.4);\r\n                    const greeble = new THREE.Mesh(new THREE.BoxGeometry(gw, gh, gd), new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.6, metalness: 0.8 }));\r\n                    greeble.position.y = lobbyHeight + Math.random() * coreHeight; greeble.position.x = (Math.random() - 0.5) * b.w; greeble.position.z = (Math.random() - 0.5) * b.d;\r\n                    bldgGroup.add(greeble);\r\n                    if (Math.random() > 0.4) { const strip = new THREE.Mesh(new THREE.BoxGeometry(gw + 2, 5, gd + 2), neonMat); strip.position.copy(greeble.position); bldgGroup.add(strip); }\r\n                }\r\n\r\n                if (Math.random() > 0.2) {\r\n                    const edgeMesh = new THREE.Mesh(new THREE.BoxGeometry(b.w + 5, coreHeight * 0.9, 10), neonMat);\r\n                    edgeMesh.position.set(0, lobbyHeight + coreHeight\/2, (b.d + 5)\/2); bldgGroup.add(edgeMesh);\r\n                }\r\n\r\n                if (b.hasHologram && this.font && this.currentCorps.length > 0) {\r\n                    const corpName = this.currentCorps[Math.floor(Math.random() * this.currentCorps.length)];\r\n                    \r\n                    const canvas = document.createElement('canvas');\r\n                    canvas.width = 512; canvas.height = 256;\r\n                    const ctx = canvas.getContext('2d');\r\n                    ctx.fillStyle = '#000000';\r\n                    ctx.fillRect(0, 0, 512, 256);\r\n                    \r\n                    ctx.fillStyle = b.neonColor;\r\n                    ctx.font = 'bold 40px \"Space Mono\"';\r\n                    ctx.textAlign = 'center';\r\n                    ctx.textBaseline = 'middle';\r\n                    ctx.fillText(corpName, 256, 128);\r\n\r\n                    ctx.font = '20px \"Space Mono\"';\r\n                    ctx.fillStyle = '#ffffff';\r\n                    ctx.fillText(\"SECURE \/\/ UBIQUITOUS \/\/ OMNIPRESENT\", 256, 180);\r\n\r\n                    const neonTex = new THREE.CanvasTexture(canvas);\r\n                    const holoW = b.w * (1.2 + Math.random());\r\n                    \r\n                    const holo = new THREE.Mesh(\r\n                        new THREE.PlaneGeometry(holoW, holoW * 0.5), \r\n                        new THREE.MeshBasicMaterial({ map: neonTex, transparent: true, opacity: 0.9, side: THREE.DoubleSide, blending: THREE.AdditiveBlending })\r\n                    );\r\n                    \r\n                    holo.position.y = lobbyHeight + coreHeight * (0.4 + Math.random() * 0.6); \r\n                    holo.position.x = (Math.random() - 0.5) * (b.w * 1.5); \r\n                    holo.position.z = (Math.random() > 0.5 ? 1 : -1) * (b.d \/ 2 + 50);\r\n                    bldgGroup.add(holo);\r\n                }\r\n\r\n                grp.add(bldgGroup); this.cityBuildings.push({ type: 'tower', mesh: bldgGroup });\r\n            }\r\n\r\n            async buildTrafficSystem(densityPercent) {\r\n                updateLoadStatus(\"Deploying Cyberpunk Traffic Nodes...\");\r\n                TerminalLogger.log(\"[AI City] Deploying Traffic and Population...\", \"sys\");\r\n                await yieldFrame();\r\n\r\n                if (this.entities.cars) { this.entities.cars.forEach(c => this.scene.remove(c.mesh)); }\r\n                if (this.entities.pedestrians) { this.entities.pedestrians.forEach(p => this.scene.remove(p)); }\r\n                if (this.entities.workers) { this.entities.workers.forEach(w => this.scene.remove(w)); }\r\n\r\n                this.trafficNodes =[];\r\n                const blockWidth = 1200, blockLength = 1800; const cityRadiusX = 12, cityRadiusZ = 12;\r\n\r\n                for(let x = -cityRadiusX; x <= cityRadiusX; x++) {\r\n                    for(let z = -cityRadiusZ; z <= cityRadiusZ; z++) { this.trafficNodes.push({ id: `node_${x}_${z}`, flatX: x * blockWidth, flatZ: z * blockLength, connections:[] }); }\r\n                }\r\n\r\n                this.trafficNodes.forEach(node => {\r\n                    const findNode = (nx, nz) => this.trafficNodes.find(n => n.flatX === nx && n.flatZ === nz);\r\n                    const dirs = [[0, -blockLength],[0, blockLength],[blockWidth, 0],[-blockWidth, 0]];\r\n                    dirs.forEach(d => { const n = findNode(node.flatX + d[0], node.flatZ + d[1]); if(n) node.connections.push(n.id); });\r\n                });\r\n\r\n                const baseTraffic = parseInt(window.VMP_CONFIG.trafficDensity || 40);\r\n                const trafficDensity = Math.max(1, Math.floor(baseTraffic * (densityPercent \/ 100))) * 2; \r\n                this.entities.cars =[];\r\n\r\n                const exoticCarModels =[\r\n                    ' ',\r\n                ];\r\n                \r\n                const createCar = (isBus = false, isConstruction = false) => {\r\n                    const carGrp = new THREE.Group();\r\n                    let modelUrl = window.VMP_CONFIG.modelCar;\r\n                    let scale =  25;\r\n                    if(isConstruction) {\r\n                        modelUrl = 'https:\/\/raw.githubusercontent.com\/KhronosGroup\/glTF-Sample-Models\/master\/2.0\/Box\/glTF-Binary\/Box.glb'; \r\n                        scale = 25;\r\n                    } else if (!isBus) {\r\n                        modelUrl = exoticCarModels[Math.floor(Math.random() * exoticCarModels.length)];\r\n                    }\r\n\r\n                    loadCustomModel(modelUrl, obj => { if(obj) carGrp.add(obj); }, scale);\r\n\r\n                    const hlMat = new THREE.MeshStandardMaterial({color: 0xffffff, emissive: 0xffffff, emissiveIntensity: 2.0});\r\n                    const hlL = new THREE.Mesh(new THREE.BoxGeometry(4, 3, 2), hlMat); hlL.position.set(6, 11, isBus || isConstruction ? 40 : 20);\r\n                    const hlR = new THREE.Mesh(new THREE.BoxGeometry(4, 3, 2), hlMat); hlR.position.set(-6, 11, isBus || isConstruction ? 40 : 20);\r\n                    carGrp.add(hlL, hlR);\r\n\r\n                    const carLight = new THREE.PointLight(0x00e5ff, 0.0, 500); carLight.position.set(0, 15, 30); carGrp.add(carLight);\r\n                    carGrp.userData.light = carLight; return carGrp;\r\n                }\r\n\r\n                for (let i=0; i<trafficDensity; i++) {\r\n                    if (i % 10 === 0) await yieldFrame();\r\n                    const isBus = Math.random() > 0.8; \r\n                    const carGrp = createCar(isBus);\r\n                    carGrp.userData.isSelectable = true; carGrp.name = isBus ? `CityBus_${i}` : `Car_${i}`;\r\n\r\n                    const startNode = this.trafficNodes[Math.floor(Math.random() * this.trafficNodes.length)];\r\n                    const targetNodeId = startNode.connections[Math.floor(Math.random() * startNode.connections.length)];\r\n                    const targetNode = this.trafficNodes.find(n => n.id === targetNodeId);\r\n\r\n                    carGrp.position.copy(wrapToPlanet(startNode.flatX, startNode.flatZ, 5));\r\n                    alignToPlanet(carGrp);\r\n                    this.scene.add(carGrp);\r\n                    this.entities.cars.push({ mesh: carGrp, light: carGrp.userData.light, currentNode: startNode, targetNode: targetNode, speed: isBus ? 180 : 250 + Math.random() * 150, state: 'DRIVING', active: true, flatX: startNode.flatX, flatZ: startNode.flatZ });\r\n                }\r\n\r\n                const basePeds = parseInt(window.VMP_CONFIG.pedDensity || 30);\r\n                const pedDensity = Math.max(1, Math.floor(basePeds * (densityPercent \/ 100)));\r\n                this.entities.pedestrians =[];\r\n                this.entities.workers =[];\r\n\r\n                for (let i=0; i<pedDensity; i++) {\r\n                    if (i % 10 === 0) await yieldFrame();\r\n                    const pGrp = this.buildPedestrianFamily();\r\n                    const randomDoor = this.doors[Math.floor(Math.random() * this.doors.length)];\r\n                    if (randomDoor) { \r\n                        pGrp.position.copy(randomDoor.pos); \r\n                        alignToPlanet(pGrp);\r\n                        pGrp.userData.flatX = randomDoor.flatX; pGrp.userData.flatZ = randomDoor.flatZ;\r\n                    } else { \r\n                        pGrp.userData.flatX = (Math.random()-0.5)*20000; pGrp.userData.flatZ = (Math.random()-0.5)*20000;\r\n                        pGrp.position.copy(wrapToPlanet(pGrp.userData.flatX, pGrp.userData.flatZ, 0));\r\n                        alignToPlanet(pGrp);\r\n                    }\r\n                    this.scene.add(pGrp); this.entities.pedestrians.push(pGrp);\r\n                }\r\n                \r\n                const numBuilders = Math.floor(pedDensity \/ 2);\r\n                const numElec = Math.floor(pedDensity \/ 4);\r\n                const numPlumb = Math.floor(pedDensity \/ 4);\r\n                \r\n                TerminalLogger.log(`[AI City] Spawning ${numBuilders} builders, ${numElec} electricians, ${numPlumb} plumbers.`, 'sys');\r\n\r\n                for(let i=0; i<numBuilders; i++) {\r\n                    const worker = buildProceduralHuman('adult', null, 'construction');\r\n                    worker.userData = { state: 'IDLE', targetBuilding: null, timer: 0, speed: 30, active: true, job: 'Builder' };\r\n                    this.scene.add(worker);\r\n                    this.entities.workers.push(worker);\r\n                }\r\n                for(let i=0; i<numElec; i++) {\r\n                    const worker = buildProceduralHuman('adult', null, 'electrician');\r\n                    worker.userData = { state: 'IDLE', targetBuilding: null, timer: 0, speed: 35, active: true, job: 'Electrician' };\r\n                    this.scene.add(worker);\r\n                    this.entities.workers.push(worker);\r\n                }\r\n                 for(let i=0; i<numPlumb; i++) {\r\n                    const worker = buildProceduralHuman('adult', null, 'plumber');\r\n                    worker.userData = { state: 'IDLE', targetBuilding: null, timer: 0, speed: 32, active: true, job: 'Plumber' };\r\n                    this.scene.add(worker);\r\n                    this.entities.workers.push(worker);\r\n                }\r\n            }\r\n        \r\n            buildPedestrianFamily() {\r\n                const famGrp = new THREE.Group();\r\n                const mom = buildProceduralHuman('adult', null, 'mom'); mom.position.set(-3, 0, 0); famGrp.add(mom);\r\n                const dad = buildProceduralHuman('adult', null, 'dad'); dad.position.set(3, 0, 0); famGrp.add(dad);\r\n                if (Math.random() > 0.3) { const son = buildProceduralHuman('child', null, 'son'); son.position.set(0, 0, 3); famGrp.add(son); }\r\n                famGrp.userData = { state: 'WANDER_SIDEWALK', targetFlatX: 0, targetFlatZ: 0, timer: 0, speed: 20 + Math.random() * 15, active: true, job: 'Citizen' };\r\n                return famGrp;\r\n            }\r\n\r\n            getNewPedestrianTarget(pGrp) {\r\n                if (this.doors.length > 0 && Math.random() > 0.4) {\r\n                    const door = this.doors[Math.floor(Math.random() * this.doors.length)];\r\n                    pGrp.userData.targetFlatX = door.flatX;\r\n                    pGrp.userData.targetFlatZ = door.flatZ;\r\n                    pGrp.userData.state = 'WALKING_TO_DOOR';\r\n                } else {\r\n                    const isX = Math.random() > 0.5;\r\n                    pGrp.userData.targetFlatX = pGrp.userData.flatX + (isX ? (Math.random()-0.5)*2000 : 0);\r\n                    pGrp.userData.targetFlatZ = pGrp.userData.flatZ + (!isX ? (Math.random()-0.5)*2000 : 0);\r\n                    pGrp.userData.state = 'WANDER_SIDEWALK';\r\n                }\r\n            }\r\n\r\n            getNewWorkerTarget(worker) {\r\n                if (this.cityBuildings.length > 0) {\r\n                    const bldgData = this.cityBuildings[Math.floor(Math.random() * this.cityBuildings.length)];\r\n                    worker.userData.targetBuilding = bldgData.mesh;\r\n                    worker.userData.state = 'WALKING_TO_SITE';\r\n                    \r\n                    let bpKey = 'bpConstruction';\r\n                    if (worker.userData.job === 'Electrician') bpKey = 'bpElectrician';\r\n                    if (worker.userData.job === 'Plumber') bpKey = 'bpPlumber';\r\n                    \r\n                    TerminalLogger.log(`[AI Worker] ${worker.userData.job} received blueprint for ${bldgData.mesh.name}: \"${window.VMP_CONFIG[bpKey]}\"`, 'sys');\r\n                }\r\n            }\r\n\r\n            initControls() {\r\n                this.playerControls = new PointerLockControls(this.camera, document.body);\r\n                this.moveState = { f: false, b: false, l: false, r: false, jump: false, isFlying: false, isSwimming: false, boost: false };\r\n                this.velocity = new THREE.Vector3();\r\n                this.direction = new THREE.Vector3();\r\n                this.preSwimPos = null;\r\n\r\n                const playBtn = document.getElementById(`btn_play_${INSTANCE_ID}`);\r\n                if (playBtn) {\r\n                    playBtn.addEventListener('click', () => {\r\n                        if (this.isInPlayMode) { this.playerControls.unlock(); } else { this.playerControls.lock(); }\r\n                    });\r\n                }\r\n\r\n                const driveBtn = document.getElementById(`btn_drive_car_${INSTANCE_ID}`);\r\n                if (driveBtn) {\r\n                    driveBtn.addEventListener('click', () => {\r\n                        this.isDrivingCar = !this.isDrivingCar;\r\n                        if (this.isDrivingCar) {\r\n                            TerminalLogger.log(\"[SYS] Car Ignition Engaged. Use W A S D to drive around Planet Cytron.\", \"sys\");\r\n                            this.playerControls.lock();\r\n                            this.isInPlayMode = true;\r\n                        } else {\r\n                            TerminalLogger.log(\"[SYS] Exited Vehicle.\", \"sys\");\r\n                            this.playerControls.unlock();\r\n                            this.isInPlayMode = false;\r\n                        }\r\n                    });\r\n                }\r\n\r\n                const swimBtn = document.getElementById(`btn_swim_${INSTANCE_ID}`);\r\n                if (swimBtn) {\r\n                    swimBtn.addEventListener('click', () => {\r\n                        this.moveState.isSwimming = !this.moveState.isSwimming;\r\n                        \r\n                        if (this.moveState.isSwimming) {\r\n                            TerminalLogger.log(\"[SYS] Swim Mode Engaged. Teleporting to Ocean District.\", \"sys\");\r\n                            this.preSwimPos = this.playerControls.getObject().position.clone();\r\n                            this.playerControls.getObject().position.copy(wrapToPlanet(17000, 0, -10)); \r\n                            alignToPlanet(this.playerControls.getObject());\r\n                            \r\n                            this.scene.fog.color.setHex(0x002255);\r\n                            this.scene.fog.density = 0.00;\r\n                         } else {\r\n                            TerminalLogger.log(\"[SYS] Swim Mode Disengaged. Returning to Core.\", \"sys\");\r\n                            if(this.preSwimPos) {\r\n                                this.playerControls.getObject().position.copy(this.preSwimPos);\r\n                            } else {\r\n                                this.playerControls.getObject().position.set(0, 20, -500);\r\n                            }\r\n                            this.scene.fog.color.setHex(parseInt(window.VMP_CONFIG.fogColor.replace('#', '0x')));\r\n                            this.scene.fog.density = window.VMP_CONFIG.fogDensity;\r\n                         }\r\n                    });\r\n                }\r\n\r\n                const fsBtn = document.getElementById(`btn_fullscreen_${INSTANCE_ID}`);\r\n                const wrap = document.getElementById(INSTANCE_ID);\r\n\r\n                if(fsBtn) {\r\n                    fsBtn.addEventListener('click', () => {\r\n                        if (!document.fullscreenElement) { if (wrap.requestFullscreen) { wrap.requestFullscreen().catch(()=>{}); } } else { if (document.exitFullscreen) { document.exitFullscreen(); } }\r\n                    });\r\n                }\r\n\r\n                document.addEventListener('fullscreenchange', () => {\r\n                    if(document.fullscreenElement) { wrap.classList.add('fullscreen-active'); } else { wrap.classList.remove('fullscreen-active'); }\r\n                    this.onWindowResize(); setTimeout(() => this.onWindowResize(), 100); setTimeout(() => this.onWindowResize(), 500);\r\n                });\r\n\r\n                this.playerControls.addEventListener('lock', () => { this.isInPlayMode = true; this.orbitControls.enabled = false; });\r\n                this.playerControls.addEventListener('unlock', () => { this.isInPlayMode = false; this.orbitControls.enabled = true; });\r\n\r\n                document.addEventListener('keydown', (e) => {\r\n                    if(!this.isInPlayMode ||['INPUT', 'TEXTAREA'].includes(e.target.tagName)) return;\r\n                    if(e.code === 'KeyW') this.moveState.f = true; if(e.code === 'KeyS') this.moveState.b = true;\r\n                    if(e.code === 'KeyA') this.moveState.l = true; if(e.code === 'KeyD') this.moveState.r = true;\r\n                    \r\n                    const pCenterDist = this.playerControls.getObject().position.distanceTo(PLANET_CENTER);\r\n                    \r\n                    if(e.code === 'ShiftLeft' || e.code === 'ShiftRight') { \r\n                        if(!this.moveState.isFlying && !this.moveState.isSwimming && !this.isDrivingCar && pCenterDist <= PLANET_RADIUS + 21) { \r\n                            this.velocity.y += 350; \r\n                        } \r\n                    }\r\n                    if(e.code === 'ControlLeft' || e.code === 'ControlRight') {\r\n                        if(this.moveState.isSwimming) {\r\n                            this.moveState.boost = true;\r\n                        } else if (!this.isDrivingCar) {\r\n                            this.moveState.isFlying = !this.moveState.isFlying;\r\n                            TerminalLogger.log(this.moveState.isFlying ? \"[SYS] Flight Mode Enabled (Use W\/S to ascend\/descend)\" : \"[SYS] Flight Mode Disabled\", \"sys\");\r\n                        }\r\n                    }\r\n                });\r\n\r\n                document.addEventListener('keyup', (e) => {\r\n                    if(!this.isInPlayMode ||['INPUT', 'TEXTAREA'].includes(e.target.tagName)) return;\r\n                    if(e.code === 'KeyW') this.moveState.f = false; if(e.code === 'KeyS') this.moveState.b = false;\r\n                    if(e.code === 'KeyA') this.moveState.l = false; if(e.code === 'KeyD') this.moveState.r = false;\r\n                     if(e.code === 'ControlLeft' || e.code === 'ControlRight') {\r\n                        this.moveState.boost = false;\r\n                    }\r\n                });\r\n\r\n                const deployBtn = document.getElementById(`btn_build_city_${INSTANCE_ID}`);\r\n                const densitySlider = document.getElementById(`city_density_slider_${INSTANCE_ID}`);\r\n                if (deployBtn && densitySlider) { deployBtn.addEventListener('click', () => { this.startCityRebuild(parseInt(densitySlider.value), null); }); }\r\n            }\r\n\r\n            checkCollisions(newPos) {\r\n                if (this.moveState.isFlying || this.moveState.isSwimming || this.isRidingCoaster || this.isDrivingCar) return false; \r\n                \r\n                if (!this.collisionCache || this.needsCollisionUpdate) {\r\n                    this.collisionCache =[];\r\n                    for (let i = 0; i < this.collidableMeshes.length; i++) {\r\n                        const mesh = this.collidableMeshes[i];\r\n                        if (!mesh.visible) continue;\r\n                        this.collisionCache.push({\r\n                            box: new THREE.Box3().setFromObject(mesh),\r\n                            isSolidGround: mesh.userData.isSolidGround === true\r\n                        });\r\n                    }\r\n                    this.needsCollisionUpdate = false;\r\n                }\r\n\r\n                const playerBox = new THREE.Box3().setFromCenterAndSize(newPos, new THREE.Vector3(10, 40, 10)); \r\n                for (let i = 0; i < this.collisionCache.length; i++) {\r\n                    const cached = this.collisionCache[i];\r\n                    if (cached.isSolidGround) continue; \r\n                    if (playerBox.intersectsBox(cached.box)) {\r\n                        return true;\r\n                    }\r\n                }\r\n                return false;\r\n            }\r\n\r\n            updateGPSMap() {\r\n                const latEl = document.getElementById('gps_lat');\r\n                const lonEl = document.getElementById('gps_lon');\r\n                const dotEl = document.getElementById('map_dot');\r\n                if(!latEl || !lonEl || !dotEl) return;\r\n\r\n                const pos = this.isDrivingCar ? this.playerCar.position : this.camera.position;\r\n                \r\n                const r = pos.distanceTo(PLANET_CENTER);\r\n                const dx = pos.x;\r\n                const dy = pos.y + PLANET_RADIUS;\r\n                const dz = -pos.z;\r\n\r\n                let lat = Math.asin(dy \/ r);\r\n                let lon = Math.atan2(dx, dz); \r\n\r\n                const actualLat = (lat * (180 \/ Math.PI)).toFixed(4);\r\n                const actualLon = (lon * (180 \/ Math.PI)).toFixed(4);\r\n\r\n                latEl.innerText = `LAT: ${actualLat}`;\r\n                lonEl.innerText = `LON: ${actualLon}`;\r\n\r\n                const mapX = ((lon + Math.PI) \/ (Math.PI * 2)) * 100;\r\n                const mapY = ((Math.PI\/2 - lat) \/ Math.PI) * 100;\r\n                \r\n                dotEl.style.left = `${mapX}%`;\r\n                dotEl.style.top = `${mapY}%`;\r\n            }\r\n\r\n            animate(now) {\r\n                requestAnimationFrame(this.animate.bind(this));\r\n                \r\n                const interval = 1000 \/ this.fpsCap;\r\n                const delta = now - this.lastFrameTime;\r\n                \r\n                if (delta < interval) return;\r\n                \r\n                this.lastFrameTime = now - (delta % interval);\r\n\r\n                const frameDelta = this.clock.getDelta(); \r\n                this.timeElapsed += frameDelta;\r\n\r\n                if (this.isAssemblingCity) {\r\n                    const result = this.cityAssemblyGenerator.next();\r\n                    if (result.done) {\r\n                        this.isAssemblingCity = false;\r\n                        this.cityAssemblyGenerator = null;\r\n                        this.buildTrafficSystem(parseInt(document.getElementById(`city_density_slider_${INSTANCE_ID}`).value)); \r\n                        const loadingOverlay = document.getElementById(`loading_${INSTANCE_ID}`);\r\n                        if (loadingOverlay) {\r\n                            loadingOverlay.style.opacity = '0';\r\n                            setTimeout(() => { loadingOverlay.style.display = 'none'; loadingOverlay.style.pointerEvents = 'auto'; }, 500);\r\n                        }\r\n                        TerminalLogger.log(`[AI City] Cyberpunk City upgrade complete.`, \"succ\");\r\n                    }\r\n                }\r\n                \r\n                this.calibrator.update();\r\n                const frameCount = this.calibrator.frameCount;\r\n                \r\n                if(frameCount % 5 === 0) {\r\n                    this.updateGPSMap();\r\n                }\r\n\r\n                if(this.interplanetaryTravel) {\r\n                    this.interplanetaryTravel.update(frameDelta);\r\n                    if (!this.moveState.isFlying && !this.moveState.isSwimming && !this.isRidingCoaster && !this.isDrivingCar) {\r\n                       alignToPlanet(this.playerControls.getObject());\r\n                    }\r\n                }\r\n\r\n                if(this.laserBeam) {\r\n                    const pulse = 1.0 + Math.sin(this.timeElapsed * 15) * 0.5;\r\n                    this.laserBeam.scale.x = pulse; this.laserBeam.scale.z = pulse;\r\n                    this.laserBeam.material.opacity = 0.5 + Math.sin(this.timeElapsed * 20) * 0.4;\r\n                }\r\n                \r\n                if(this.teleporterRings) {\r\n                    this.teleporterRings.children.forEach((r, i) => {\r\n                        r.rotation.z += frameDelta * (i+1);\r\n                        r.material.emissiveIntensity = 2.0 + Math.sin(this.timeElapsed * 5 + i) * 1.5;\r\n                    });\r\n                }\r\n\r\n                if(this.ferrisWheel) {\r\n                    this.ferrisWheel.rotation.z += frameDelta * 0.2;\r\n                    if(this.ferrisWheel.children[0] && this.ferrisWheel.children[0].children) {\r\n                        this.ferrisWheel.children[0].children.forEach((c, idx) => {\r\n                            if(idx >= 12) c.rotation.z = -this.ferrisWheel.rotation.z; \r\n                        });\r\n                    }\r\n                }\r\n\r\n                if(this.coasterCart && this.coasterCurve) {\r\n                    this.coasterProgress += frameDelta * 0.2;\r\n                    if(this.coasterProgress > 1) this.coasterProgress = 0;\r\n                    const pt = this.coasterCurve.getPointAt(this.coasterProgress);\r\n                    const tang = this.coasterCurve.getTangentAt(this.coasterProgress);\r\n                    this.coasterCart.position.copy(pt);\r\n                    const lookAtPt = pt.clone().add(tang);\r\n                    this.coasterCart.lookAt(lookAtPt);\r\n\r\n                    if (this.isRidingCoaster) {\r\n                        const worldPos = new THREE.Vector3();\r\n                        this.coasterCart.getWorldPosition(worldPos);\r\n                        this.camera.position.copy(worldPos).add(new THREE.Vector3(0, 15, 0));\r\n                        const forward = new THREE.Vector3(0,0,1).applyQuaternion(this.coasterCart.quaternion);\r\n                        this.camera.lookAt(worldPos.clone().add(forward));\r\n                    }\r\n                }\r\n\r\n                if(this.entities.rabbits) {\r\n                    this.entities.rabbits.forEach(r => {\r\n                        if (!r.userData.active) return;\r\n                        const ud = r.userData;\r\n                        ud.timer -= frameDelta;\r\n                        if(ud.timer <= 0) {\r\n                            this.getNewRabbitTarget(r);\r\n                            ud.timer = 2 + Math.random() * 3;\r\n                        }\r\n                        \r\n                        const tVec = new THREE.Vector2(ud.target.x, ud.target.y);\r\n                        const cVec = new THREE.Vector2(ud.fX, ud.fZ);\r\n                        const dir = new THREE.Vector2().subVectors(tVec, cVec);\r\n                        \r\n                        if(dir.length() > 5) {\r\n                            dir.normalize().multiplyScalar(50 * frameDelta);\r\n                            ud.fX += dir.x;\r\n                            ud.fZ += dir.y;\r\n                            \r\n                            const hopCycle = Math.abs(Math.sin(this.timeElapsed * 15)) * 10;\r\n                            \r\n                            const sPos = wrapToPlanet(ud.fX, ud.fZ, hopCycle);\r\n                            r.position.copy(sPos);\r\n                            alignToPlanet(r);\r\n                            \r\n                            const targetRot = Math.atan2(dir.x, dir.y);\r\n                            r.rotateY(targetRot);\r\n                        }\r\n                    });\r\n                }\r\n                \r\n                if (this.dog1 && this.dog1.visible) {\r\n                    const ud = this.dog1.userData;\r\n                    ud.timer -= frameDelta;\r\n                    if(ud.timer <= 0) {\r\n                        ud.target.set(ud.fX + (Math.random()-0.5)*1000, ud.fZ + (Math.random()-0.5)*1000);\r\n                        ud.timer = 5 + Math.random() * 5;\r\n                    }\r\n                    const tVec = new THREE.Vector2(ud.target.x, ud.target.y);\r\n                    const cVec = new THREE.Vector2(ud.fX, ud.fZ);\r\n                    const dir = new THREE.Vector2().subVectors(tVec, cVec);\r\n                    if(dir.length() > 5) {\r\n                        dir.normalize().multiplyScalar(40 * frameDelta);\r\n                        ud.fX += dir.x;\r\n                        ud.fZ += dir.y;\r\n                        const sPos = wrapToPlanet(ud.fX, ud.fZ, 0);\r\n                        this.dog1.position.copy(sPos);\r\n                        alignToPlanet(this.dog1);\r\n                        this.dog1.rotateY(Math.atan2(dir.x, dir.y));\r\n                        \r\n                        const walkCycle = Math.sin(this.timeElapsed * 10);\r\n                        if(ud.legs && ud.legs.length === 4) {\r\n                            ud.legs[0].rotation.x = walkCycle * 0.5;\r\n                            ud.legs[1].rotation.x = -walkCycle * 0.5;\r\n                            ud.legs[2].rotation.x = -walkCycle * 0.5;\r\n                            ud.legs[3].rotation.x = walkCycle * 0.5;\r\n                        }\r\n                    }\r\n                }\r\n                \r\n                if (this.dog2 && this.dog2.visible) {\r\n                    const ud = this.dog2.userData;\r\n                    ud.timer -= frameDelta;\r\n                    if(ud.timer <= 0) {\r\n                        ud.target.set(ud.fX + (Math.random()-0.5)*1000, ud.fZ + (Math.random()-0.5)*1000);\r\n                        ud.timer = 5 + Math.random() * 5;\r\n                    }\r\n                    const tVec = new THREE.Vector2(ud.target.x, ud.target.y);\r\n                    const cVec = new THREE.Vector2(ud.fX, ud.fZ);\r\n                    const dir = new THREE.Vector2().subVectors(tVec, cVec);\r\n                    if(dir.length() > 5) {\r\n                        dir.normalize().multiplyScalar(40 * frameDelta);\r\n                        ud.fX += dir.x;\r\n                        ud.fZ += dir.y;\r\n                        const sPos = wrapToPlanet(ud.fX, ud.fZ, 0);\r\n                        this.dog2.position.copy(sPos);\r\n                        alignToPlanet(this.dog2);\r\n                        this.dog2.rotateY(Math.atan2(dir.x, dir.y));\r\n                        \r\n                        const walkCycle = Math.sin(this.timeElapsed * 10);\r\n                        if(ud.legs && ud.legs.length === 4) {\r\n                            ud.legs[0].rotation.x = walkCycle * 0.5;\r\n                            ud.legs[1].rotation.x = -walkCycle * 0.5;\r\n                            ud.legs[2].rotation.x = -walkCycle * 0.5;\r\n                            ud.legs[3].rotation.x = walkCycle * 0.5;\r\n                        }\r\n                    }\r\n                }\r\n                \r\n                if (this.entities.birds) {\r\n                    this.entities.birds.forEach(b => {\r\n                        b.angle += frameDelta * 0.1;\r\n                        b.fX += Math.cos(b.angle) * b.speed * frameDelta;\r\n                        b.fZ += Math.sin(b.angle) * b.speed * frameDelta;\r\n                        \r\n                        const flapCycle = Math.sin(this.timeElapsed * 15 + b.offset);\r\n                        if(b.wL && b.wR) {\r\n                            b.wL.rotation.z = flapCycle * 0.8;\r\n                            b.wR.rotation.z = -flapCycle * 0.8;\r\n                        }\r\n                        \r\n                        const sPos = wrapToPlanet(b.fX, b.fZ, b.fY + Math.sin(this.timeElapsed*2 + b.offset)*50);\r\n                        b.grp.position.copy(sPos);\r\n                        alignToPlanet(b.grp);\r\n                        b.grp.rotateY(Math.atan2(Math.cos(b.angle), Math.sin(b.angle)));\r\n                    });\r\n                }\r\n\r\n                if(this.parkAttendees) {\r\n                    this.parkAttendees.forEach(p => {\r\n                        p.userData.angle += frameDelta * 0.5;\r\n                        \r\n                        const pX = Math.sin(p.userData.angle)*300;\r\n                        const pZ = Math.cos(p.userData.angle)*300;\r\n                        \r\n                        const sPos = wrapToPlanet(-10000 + pX, 17000 + pZ, 0);\r\n                        p.position.copy(sPos);\r\n                        alignToPlanet(p);\r\n                        p.rotateY(p.userData.angle + Math.PI\/2);\r\n                    });\r\n                }\r\n\r\n                if(this.golfers) {\r\n                    this.golfers.forEach(g => {\r\n                        const ud = g.userData;\r\n                        ud.timer -= frameDelta;\r\n                        if(ud.timer <= 0) { ud.swingPhase = 1.0; ud.timer = 5 + Math.random()*5; }\r\n                        if(ud.swingPhase > 0) {\r\n                            ud.swingPhase -= frameDelta * 2.0;\r\n                            ud.club.rotation.z = Math.sin(ud.swingPhase * Math.PI) * 2.0;\r\n                            if(ud.swingPhase <= 0) ud.swingPhase = 0;\r\n                        }\r\n                    });\r\n                }\r\n\r\n                if(this.entities.trains) {\r\n                    this.entities.trains.forEach(t => {\r\n                        t.userData.progress += t.userData.speed * frameDelta;\r\n                        if(t.userData.progress > 1) t.userData.progress = 0;\r\n                        const pt = t.userData.curve.getPointAt(t.userData.progress);\r\n                        const tang = t.userData.curve.getTangentAt(t.userData.progress);\r\n                        t.position.copy(pt);\r\n                        t.lookAt(pt.clone().add(tang));\r\n                    });\r\n                }\r\n\r\n                if(this.entities.hovercars) {\r\n                    this.entities.hovercars.forEach(hc => {\r\n                        hc.userData.progress += hc.userData.speed * frameDelta;\r\n                        if(hc.userData.progress > 1) hc.userData.progress = 0;\r\n                        const pt = hc.userData.curve.getPointAt(hc.userData.progress);\r\n                        const tang = hc.userData.curve.getTangentAt(hc.userData.progress);\r\n                        hc.position.copy(pt);\r\n                        hc.lookAt(pt.clone().add(tang));\r\n                    });\r\n                }\r\n\r\n                if(this.minerNodes) {\r\n                    this.minerNodes.forEach((n, idx) => {\r\n                        const w = n.userData.worker; const txt = n.userData.floatText;\r\n                        if(w) {\r\n                            w.children[0].children[0].userData.armL.rotation.x = -Math.PI\/4 + Math.sin(this.timeElapsed*20 + idx)*0.2;\r\n                            w.children[0].children[0].userData.armR.rotation.x = -Math.PI\/4 + Math.cos(this.timeElapsed*22 + idx)*0.2;\r\n                        }\r\n                        if(txt) { txt.position.y = 50 + Math.sin(this.timeElapsed*2 + idx)*5; }\r\n                    });\r\n                }\r\n\r\n                if(this.pipeSystem) {\r\n                    this.pipeSystem.children.forEach(c => {\r\n                        if(c.geometry.type === 'SphereGeometry') {\r\n                            c.userData.progress += frameDelta * 0.5;\r\n                            if(c.userData.progress > 1) c.userData.progress = 0;\r\n                            const pt = c.userData.curve.getPointAt(c.userData.progress);\r\n                            c.position.copy(pt);\r\n                        }\r\n                    });\r\n                }\r\n\r\n                const speedMultiplier = parseFloat(window.VMP_CONFIG.dayNightSpeed || 0.05);\r\n                const sunAngle = this.timeElapsed * speedMultiplier;\r\n\r\n                this.sunLight.position.x = Math.cos(sunAngle) * 40000;\r\n                this.sunLight.position.y = Math.sin(sunAngle) * 40000;\r\n                this.sunLight.position.z = Math.cos(sunAngle) * 20000;\r\n\r\n                this.sunMesh.position.copy(this.sunLight.position);\r\n                this.moonMesh.position.set(-this.sunLight.position.x, -this.sunLight.position.y, -this.sunLight.position.z);\r\n\r\n                const mixRatio = Math.sin(sunAngle);\r\n                const isNight = mixRatio < 0; \r\n                const tod = (sunAngle % (Math.PI * 2));\r\n\r\n                this.seasonTimer += frameDelta;\r\n                if(this.seasonTimer > this.seasonDuration) {\r\n                    this.seasonTimer = 0;\r\n                    this.seasonIndex = (this.seasonIndex + 1) % 4;\r\n                    const ind = document.getElementById(`season_indicator_${INSTANCE_ID}`);\r\n                    if(ind) ind.innerText = \"SEASON: \" + this.seasonNames[this.seasonIndex];\r\n                }\r\n\r\n                const season = this.seasonNames[this.seasonIndex];\r\n\r\n                if (this.hurricaneSys) {\r\n                    if (season === 'SUMMER') {\r\n                        this.hurricaneMat.opacity = Math.min(0.5, this.hurricaneMat.opacity + frameDelta * 0.1);\r\n                        this.hurricaneSys.rotation.y += frameDelta * 0.5;\r\n                        if (Math.random() < 0.02) {\r\n                            this.lightningLight.intensity = 5.0;\r\n                            setTimeout(()=> { this.lightningLight.intensity = 0; }, 100);\r\n                        }\r\n                    } else {\r\n                        this.hurricaneMat.opacity = Math.max(0, this.hurricaneMat.opacity - frameDelta * 0.1);\r\n                    }\r\n                }\r\n\r\n                if(season === 'WINTER') {\r\n                    if(this.weatherMat) {\r\n                        this.weatherMat.opacity = 0.8;\r\n                        if(!window.VMP_CONFIG.texSnowflake) this.weatherMat.color.setHex(0xffffff);\r\n                        const pos = this.weatherSystem.geometry.attributes.position.array;\r\n                        for(let i = 0; i < pos.length; i += 3) {\r\n                            pos[i] += Math.sin(this.timeElapsed + pos[i+1]*0.01) * 50 * frameDelta;\r\n                            pos[i+1] -= 200 * frameDelta;\r\n                            if(pos[i+1] < 0) { pos[i+1] = 8000; }\r\n                        }\r\n                        this.weatherSystem.geometry.attributes.position.needsUpdate = true;\r\n                    }\r\n                    if(this.rainMat) this.rainMat.opacity = 0;\r\n                    if(this.grass) this.grass.material.color.lerp(new THREE.Color(0xffffff), 0.01);\r\n                    if(this.fisherGrp) this.fisherGrp.visible = false;\r\n                } else if (season === 'SPRING') {\r\n                    if(this.weatherMat) this.weatherMat.opacity = 0;\r\n                    if(this.rainMat) {\r\n                        this.rainMat.opacity = 0.6;\r\n                        const pos = this.rainSystem.geometry.attributes.position.array;\r\n                        for(let i = 1; i < pos.length; i += 3) {\r\n                            pos[i] -= 2500 * frameDelta;\r\n                            if(pos[i] < 0) { pos[i] = 8000; }\r\n                        }\r\n                        this.rainSystem.geometry.attributes.position.needsUpdate = true;\r\n                    }\r\n                    if(this.grass) this.grass.material.color.lerp(new THREE.Color(0x228822), 0.01);\r\n                    if(this.fisherGrp) this.fisherGrp.visible = false;\r\n                } else if (season === 'SUMMER') {\r\n                    if(this.weatherMat) this.weatherMat.opacity = 0;\r\n                    if(this.rainMat) this.rainMat.opacity = 0;\r\n                    if(this.grass) this.grass.material.color.lerp(new THREE.Color(0x559922), 0.01);\r\n                    if(this.fisherGrp) this.fisherGrp.visible = true;\r\n                } else if (season === 'FALL') {\r\n                    if(this.weatherMat) this.weatherMat.opacity = 0;\r\n                    if(this.rainMat) this.rainMat.opacity = 0;\r\n                    if(this.grass) this.grass.material.color.lerp(new THREE.Color(0x8b5a2b), 0.01);\r\n                    if(this.fisherGrp) this.fisherGrp.visible = true;\r\n                }\r\n\r\n                const camYaw = this.camera.rotation.y;\r\n\r\n                if (this.lensDrops && this.lensDrops.length > 0) {\r\n                    this.lensDrops.forEach(drop => {\r\n                        const ud = drop.userData;\r\n\r\n                        if(season === 'FALL') {\r\n                            if(ud.isLeaf) {\r\n                                drop.material.opacity = 1.0;\r\n                                if(ud.isStuck) {\r\n                                    ud.stuckTimer -= frameDelta;\r\n                                    drop.position.y -= frameDelta * 0.5;\r\n                                    if(ud.stuckTimer <= 0 || drop.position.y < -10) {\r\n                                        ud.isStuck = false; drop.position.y = ud.yStart; ud.xBase = (Math.random() - 0.5) * 15;\r\n                                    }\r\n                                } else {\r\n                                    drop.position.y -= ud.speed * frameDelta;drop.position.x = ud.xBase + Math.sin(this.timeElapsed * 2 + ud.windOffset) * 2.5 + (camYaw * 0.1);\r\n                                    drop.rotation.x += frameDelta; drop.rotation.y += frameDelta * 1.5; drop.rotation.z += frameDelta * 2;\r\n                                    if(drop.position.y < 5 && drop.position.y > -5 && Math.random() < 0.005) {\r\n                                        ud.isStuck = true; ud.stuckTimer = 2 + Math.random() * 3; drop.rotation.set(0,0, Math.random());\r\n                                    }\r\n                                    if(drop.position.y < -10) { drop.position.y = ud.yStart; ud.xBase = (Math.random() - 0.5) * 15; }\r\n                                }\r\n                            } else { drop.material.opacity = 0; }\r\n                        } else if(season === 'WINTER' || season === 'SPRING' || season === 'SUMMER') {\r\n                            if(!ud.isLeaf) {\r\n                                drop.material.opacity = (season === 'WINTER') ? 0.8 : 0.5;\r\n                                drop.scale.set((season === 'WINTER') ? 0.5 : 0.1, (season === 'WINTER') ? 0.5 : 4.0, 1);\r\n                                drop.position.y -= (season === 'WINTER' ? ud.speed * 0.5 : ud.speed) * frameDelta;\r\n                                drop.position.x = ud.xBase + (season === 'WINTER' ? Math.sin(this.timeElapsed + ud.windOffset) : (camYaw * 0.5));\r\n                                if(drop.position.y < -10) { drop.position.y = ud.yStart; ud.xBase = (Math.random() - 0.5) * 15; }\r\n                            } else { drop.material.opacity = 0; }\r\n                        }\r\n                    });\r\n                }\r\n\r\n                if (this.interplanetaryTravel && this.interplanetaryTravel.currentPlanet === 'Earth') {\r\n                    if(!this.moveState.isSwimming) {\r\n                        if (tod > 0 && tod < Math.PI \/ 4 && this.mornTex && this.mornTex.image) {\r\n                            if (this.scene.background !== this.mornTex) { this.scene.background = this.mornTex; this.scene.environment = this.pmremGenerator.fromEquirectangular(this.mornTex).texture; }\r\n                            this.scene.fog.color.setHex(0x111122);\r\n                        } else if (tod >= Math.PI \/ 4 && tod < Math.PI * 0.75 && this.aftTex && this.aftTex.image) {\r\n                            if (this.scene.background !== this.aftTex) { this.scene.background = this.aftTex; this.scene.environment = this.pmremGenerator.fromEquirectangular(this.aftTex).texture; }\r\n                            this.scene.fog.color.setHex(0x0a1128);\r\n                        } else if (tod >= Math.PI * 0.75 && tod < Math.PI) {\r\n                            const envColor = new THREE.Color().lerpColors(new THREE.Color('#1a0033'), new THREE.Color('#0a1128'), mixRatio);\r\n                            this.scene.background = envColor; this.scene.environment = null; this.hemiLight.color = envColor; this.scene.fog.color = envColor;\r\n                        } else {\r\n                            const envColor = new THREE.Color().lerpColors(new THREE.Color('#1a0033'), new THREE.Color('#020408'), -mixRatio);\r\n                            this.scene.background = envColor; this.scene.environment = null; this.hemiLight.color = envColor; this.scene.fog.color = envColor;\r\n                        }\r\n                        this.scene.fog.density = window.VMP_CONFIG.fogDensity * (isNight ? 1.5 : 0.5);\r\n                    }\r\n                    this.ambientLight.intensity = (isNight ? 0.6 : 0.4) + (Math.max(0, mixRatio) * 0.6);\r\n                }\r\n\r\n                this.sunLight.intensity = Math.max(0, mixRatio) * 2.5;\r\n                this.moonLight.position.copy(this.moonMesh.position);\r\n                this.moonLight.intensity = isNight ? Math.abs(mixRatio) * 1.5 : 0.0;\r\n\r\n                if(this.roofLights) {\r\n                    this.roofLights.forEach(l => l.intensity = 2.0);\r\n                }\r\n\r\n                this.starMat.opacity = isNight ? Math.abs(mixRatio) : 0;\r\n                if(this.nightDome) { this.nightDome.material.opacity = isNight ? Math.abs(mixRatio) * 0.8 : 0; }\r\n\r\n                if(this.cityClouds) {\r\n                    this.cityClouds.forEach(cloud => {\r\n                        cloud.logicalX += cloud.driftVec.x * cloud.speed * frameDelta;\r\n                        cloud.logicalZ += cloud.driftVec.y * cloud.speed * frameDelta;\r\n                        \r\n                        if (cloud.logicalX > 80000) cloud.logicalX = -80000;\r\n                        if (cloud.logicalX < -80000) cloud.logicalX = 80000;\r\n                        if (cloud.logicalZ > 80000) cloud.logicalZ = -80000;\r\n                        if (cloud.logicalZ < -80000) cloud.logicalZ = 80000;\r\n\r\n                        const sPos = wrapToPlanet(cloud.logicalX, cloud.logicalZ, cloud.logicalY);\r\n                        cloud.mesh.position.copy(sPos);\r\n                        alignToPlanet(cloud.mesh);\r\n                    });\r\n                }\r\n\r\n                if(frameCount % 20 === 0) { this.mb1.draw(); }\r\n                else if(frameCount % 20 === 7) { this.mb2.draw(); }\r\n                else if(frameCount % 20 === 14) { this.cmd.draw(); }\r\n\r\n                this.gpuOrb.update(this.timeElapsed, frameDelta, this.mb1Mesh, this.mb2Mesh);\r\n                if(this.oceanMat) { this.oceanMat.uniforms.uTime.value = this.timeElapsed; }\r\n\r\n                if (this.entities.angels) {\r\n                    this.entities.angels.forEach((a, i) => {\r\n                        a.angle += a.speed * frameDelta * 0.01;\r\n                        \r\n                        const fX = a.cx + Math.cos(a.angle) * a.radius;\r\n                        const fZ = a.cz + Math.sin(a.angle) * a.radius;\r\n                        const fY = a.yOffset + Math.sin(this.timeElapsed * 2 + i) * 50;\r\n                        \r\n                        const sPos = wrapToPlanet(fX, fZ, fY);\r\n                        a.mesh.position.copy(sPos);\r\n                        alignToPlanet(a.mesh);\r\n                        a.mesh.rotation.y += frameDelta;\r\n                    });\r\n                }\r\n\r\n                if (this.entities.planets) {\r\n                    this.entities.planets.forEach((p) => {\r\n                        p.angle += p.speed * frameDelta;\r\n                        p.mesh.position.x = Math.cos(p.angle) * p.dist;\r\n                        p.mesh.position.z = Math.sin(p.angle) * p.dist;\r\n                        p.mesh.rotation.y += frameDelta * 0.2;\r\n                    });\r\n                }\r\n\r\n                if (this.trafficLightSystem && this.trafficLightSystem.length > 0) {\r\n                    if (!this.trafficLightTimer) this.trafficLightTimer = 0;\r\n                    this.trafficLightTimer += frameDelta;\r\n                    const cycleTime = 15; \r\n                    const cyclePhase = (this.trafficLightTimer % cycleTime) \/ cycleTime;\r\n                    \r\n                    this.trafficLightSystem.forEach(tl => {\r\n                        let isDir1 = (tl.dir === 0 || Math.abs(tl.dir - Math.PI) < 0.1);\r\n                        let state = 'RED';\r\n                        \r\n                        if (isDir1) {\r\n                            if (cyclePhase < 0.45) state = 'GREEN';\r\n                            else if (cyclePhase < 0.50) state = 'YELLOW';\r\n                            else state = 'RED';\r\n                        } else {\r\n                            if (cyclePhase < 0.50) state = 'RED';\r\n                            else if (cyclePhase < 0.95) state = 'GREEN';\r\n                            else state = 'YELLOW';\r\n                        }\r\n                        \r\n                        tl.state = state;\r\n                        tl.redMesh.material.emissiveIntensity = state === 'RED' ? 2 : 0;\r\n                        tl.yellowMesh.material.emissiveIntensity = state === 'YELLOW' ? 2 : 0;\r\n                        tl.greenMesh.material.emissiveIntensity = state === 'GREEN' ? 2 : 0;\r\n                    });\r\n                }\r\n\r\n                const camPos = this.camera.position;\r\n                if(frameCount % 10 === 0) {\r\n                    this.entities.cars.forEach(car => {\r\n                        const dist = camPos.distanceTo(car.mesh.position);\r\n                        car.active = dist < 12000;\r\n                        if(car.light) car.light.visible = car.active;\r\n                    });\r\n                    this.entities.pedestrians.forEach(p => { const dist = camPos.distanceTo(p.position); p.userData.active = dist < 8000; });\r\n                    this.entities.workers.forEach(w => { const dist = camPos.distanceTo(w.position); w.userData.active = dist < 8000; });\r\n                    this.entities.rabbits.forEach(r => { const dist = camPos.distanceTo(r.position); r.userData.active = dist < 8000; });\r\n                    this.cityBuildings.forEach(b => {\r\n                        if(b.type === 'house' && b.mesh.userData.isSmartHouse) {\r\n                            const dist = camPos.distanceTo(b.mesh.position);\r\n                            if(b.mesh.userData.smartLight) { b.mesh.userData.smartLight.intensity = dist < 1000 ? 1.5 : 0; }\r\n                        }\r\n                    });\r\n                }\r\n                \r\n                if (this.entities.aircraft) {\r\n                    this.entities.aircraft.forEach(ac => {\r\n                        ac.userData.angle +=frameDelta * 0.1;\r\n                        const fX = Math.cos(ac.userData.angle) * ac.userData.radius;\r\n                        const fZ = Math.sin(ac.userData.angle) * ac.userData.radius;\r\n                        \r\n                        const sPos = wrapToPlanet(fX, fZ, 8000);\r\n                        ac.position.copy(sPos);\r\n                        alignToPlanet(ac);\r\n                        ac.rotateY(-ac.userData.angle);\r\n\r\n                        if(ac.userData.isHeli && ac.userData.blades) ac.userData.blades.rotation.y += 0.5;\r\n                    });\r\n                }\r\n                if (this.entities.boats) {\r\n                    this.entities.boats.forEach(b => {\r\n                        b.userData.fX += Math.cos(b.userData.angle) * b.userData.speed * frameDelta;\r\n                        b.userData.fZ += Math.sin(b.userData.angle) * b.userData.speed * frameDelta;\r\n                        \r\n                        const sPos = wrapToPlanet(b.userData.fX, b.userData.fZ, 0);\r\n                        b.position.copy(sPos);\r\n                        alignToPlanet(b);\r\n                        \r\n                        b.rotateY(-b.userData.angle);\r\n                        b.rotateZ(Math.sin(this.timeElapsed * 2) * 0.1);\r\n                        \r\n                        if(b.userData.fX > 30000 || b.userData.fX < -10000 || b.userData.fZ > 30000 || b.userData.fZ < -30000) { b.userData.angle += Math.PI; }\r\n                    });\r\n                }\r\n                if (this.entities.fishes) {\r\n                    this.entities.fishes.forEach(f => {\r\n                        f.logicalPos.x += Math.cos(this.timeElapsed * f.speed) * 2;\r\n                        f.logicalPos.z += Math.sin(this.timeElapsed * f.speed) * 2;\r\n                        \r\n                        const sPos = wrapToPlanet(f.logicalPos.x, f.logicalPos.z, f.logicalPos.y);\r\n                        f.mesh.position.copy(sPos);\r\n                        alignToPlanet(f.mesh);\r\n                        f.mesh.rotateY(-this.timeElapsed * f.speed);\r\n                    });\r\n                }\r\n\r\n                if (this.entities.cars && this.entities.cars.length > 0) {\r\n                    this.entities.cars.forEach(car => {\r\n                        if(!car.active) return;\r\n                        \r\n                        if (car.state === 'DRIVING') {\r\n                            if (!car.targetNode) return;\r\n                            const nextLight = this.trafficLightSystem.find(l => l.nodeId === car.targetNode.id);\r\n                            let stopForLight = false;\r\n                            if (nextLight) {\r\n                                 const distToLight = Math.hypot(car.flatX - car.targetNode.flatX, car.flatZ - car.targetNode.flatZ);\r\n                                 if (distToLight < 80 && (nextLight.state === 'RED' || nextLight.state === 'YELLOW')) { stopForLight = true; }\r\n                            }\r\n\r\n                            if (stopForLight) {\r\n                                car.state = 'WAITING_LIGHT';\r\n                            } else {\r\n                                const tVec = new THREE.Vector2(car.targetNode.flatX, car.targetNode.flatZ);\r\n                                const currentVec = new THREE.Vector2(car.flatX, car.flatZ);\r\n                                const dir = new THREE.Vector2().subVectors(tVec, currentVec);\r\n                                const dist = dir.length();\r\n                                \r\n                                if (dist < 10) {\r\n                                    car.currentNode = car.targetNode;\r\n                                    if (Math.random() > 0.8) {\r\n                                        car.state = 'STOPPED';\r\n                                        car.stopTimer = 2 + Math.random() * 3;\r\n                                    } else {\r\n                                        if (car.currentNode.connections.length > 0) {\r\n                                            const nextId = car.currentNode.connections[Math.floor(Math.random() * car.currentNode.connections.length)];\r\n                                            car.targetNode = this.trafficNodes.find(n => n.id === nextId);\r\n                                        }\r\n                                    }\r\n                                } else {\r\n                                    dir.normalize().multiplyScalar(car.speed * frameDelta);\r\n                                    car.flatX += dir.x;\r\n                                    car.flatZ += dir.y;\r\n                                    \r\n                                    const sPos = wrapToPlanet(car.flatX, car.flatZ, 5);\r\n                                    car.mesh.position.copy(sPos);\r\n                                    alignToPlanet(car.mesh);\r\n                                    \r\n                                    const targetRot = Math.atan2(dir.x, dir.y);\r\n                                    car.mesh.rotateY(targetRot);\r\n                                }\r\n                            }\r\n                        } else if (car.state === 'WAITING_LIGHT') {\r\n                            const nextLight = this.trafficLightSystem.find(l => l.nodeId === car.targetNode.id);\r\n                            if (!nextLight || nextLight.state === 'GREEN') { car.state = 'DRIVING'; }\r\n                        } else if (car.state === 'STOPPED') {\r\n                            car.stopTimer -= frameDelta;\r\n                            if (car.stopTimer <= 0) {\r\n                                if (car.currentNode && car.currentNode.connections.length > 0) {\r\n                                    const nextId = car.currentNode.connections[Math.floor(Math.random() * car.currentNode.connections.length)];\r\n                                    car.targetNode = this.trafficNodes.find(n => n.id === nextId);\r\n                                }\r\n                                car.state = 'DRIVING';\r\n                            }\r\n                        }\r\n                    });\r\n                }\r\n\r\n                const animatePedestrian = (p, isWorker = false) => {\r\n                    const ud = p.userData;\r\n                    if (!ud.active) return;\r\n                    \r\n                    if (ud.state === 'IDLE') {\r\n                        ud.timer -= frameDelta;\r\n                        if(ud.timer <= 0) {\r\n                           if(isWorker) this.getNewWorkerTarget(p);\r\n                           else this.getNewPedestrianTarget(p);\r\n                           ud.timer = 5 + Math.random() * 5; \r\n                        }\r\n                        return;\r\n                    }\r\n\r\n                    if(ud.state === 'WORKING') {\r\n                        ud.timer -= frameDelta;\r\n                        if(ud.timer <= 0) {\r\n                             ud.state = 'IDLE'; ud.timer = 5 + Math.random()*10;\r\n                             if(ud.scaffolding) { this.scene.remove(ud.scaffolding); ud.scaffolding = null; }\r\n                        } else {\r\n                            if (ud.job === 'Builder' && !ud.scaffolding && ud.targetBuilding) {\r\n                                const scaffold = new THREE.Mesh(new THREE.BoxGeometry(50, 200, 10), new THREE.MeshStandardMaterial({color: 0x8B4513, wireframe: true}));\r\n                                p.getWorldPosition(scaffold.position);\r\n                                scaffold.position.y += 100;\r\n                                this.scene.add(scaffold);\r\n                                ud.scaffolding = scaffold;\r\n                                TerminalLogger.log(`[AI Worker] ${ud.job} begins work on ${ud.targetBuilding.name}.`, 'succ');\r\n                            } else if (ud.job === 'Electrician' && Math.random() > 0.9) {\r\n                                this.spawnTempParticles(p.position.clone().add(new THREE.Vector3(0,5,5)), 0x00e5ff, 5, 3, 0.5);\r\n                            } else if (ud.job === 'Plumber' && Math.random() > 0.9) {\r\n                                this.spawnTempParticles(p.position.clone().add(new THREE.Vector3(0,5,5)), 0x6fa8dc, 20, 1, 1.0);\r\n                            }\r\n                        }\r\n                        return;\r\n                    }\r\n\r\n                    if(ud.state === 'ENTERED_BUILDING') {\r\n                        ud.timer -= frameDelta;\r\n                        if(ud.timer <= 0) { p.visible = true; this.getNewPedestrianTarget(p); }\r\n                        return; \r\n                    }\r\n\r\n                    let targetPos = new THREE.Vector3();\r\n                    if(isWorker && ud.targetBuilding) {\r\n                        ud.targetBuilding.getWorldPosition(targetPos);\r\n                    } else {\r\n                         targetPos.copy(wrapToPlanet(ud.targetFlatX, ud.targetFlatZ, 0));\r\n                    }\r\n                    \r\n                    const dist = p.position.distanceTo(targetPos);\r\n\r\n                    if(dist > 20) {\r\n                        const dir = new THREE.Vector3().subVectors(targetPos, p.position).normalize();\r\n                        p.position.addScaledVector(dir, ud.speed * frameDelta);\r\n                        alignToPlanet(p);\r\n                        p.lookAt(targetPos);\r\n\r\n                        p.children.forEach(child => {\r\n                            if(child.isLOD) {\r\n                                const hud = child.levels[0].object.userData;\r\n                                const walkCycle = Math.sin(this.timeElapsed * 15);\r\n                                hud.armL.rotation.x = walkCycle * 0.8; hud.armR.rotation.x = -walkCycle * 0.8;\r\n                                hud.legL.rotation.x = -walkCycle * 0.8; hud.legR.rotation.x = walkCycle * 0.8;\r\n                            }\r\n                        });\r\n                    } else {\r\n                        if (ud.state === 'WALKING_TO_DOOR') {\r\n                            p.visible = false; ud.state = 'ENTERED_BUILDING'; ud.timer = 10 + Math.random() * 20; \r\n                        } else if (ud.state === 'WALKING_TO_SITE') {\r\n                            ud.state = 'WORKING'; ud.timer = 15 + Math.random() * 20;\r\n                        } else {\r\n                            if(isWorker) this.getNewWorkerTarget(p);\r\n                            else this.getNewPedestrianTarget(p);\r\n                        }\r\n                    }\r\n                };\r\n\r\n                this.entities.pedestrians.forEach(p => animatePedestrian(p, false));\r\n                this.entities.workers.forEach(w => animatePedestrian(w, true));\r\n\r\n                \/\/ Process manual movement\r\n                if (this.isInPlayMode && !this.isRidingCoaster && !this.isDrivingCar) {\r\n                    this.direction.z = Number(this.moveState.f) - Number(this.moveState.b);\r\n                    this.direction.x = Number(this.moveState.r) - Number(this.moveState.l);\r\n                    this.direction.normalize();\r\n\r\n                    let moveSpeed = this.moveState.isFlying ? 3000 : (this.moveState.isSwimming ? 800 : 800);\r\n                    if(this.moveState.boost) moveSpeed *= 3.5;\r\n\r\n                    if (this.moveState.f || this.moveState.b) this.velocity.z -= this.direction.z * moveSpeed * frameDelta;\r\n                    if (this.moveState.l || this.moveState.r) this.velocity.x -= this.direction.x * moveSpeed * frameDelta;\r\n\r\n                    const curPos = this.playerControls.getObject().position.clone();\r\n                    this.playerControls.moveRight(-this.velocity.x * frameDelta);\r\n                    this.playerControls.moveForward(-this.velocity.z * frameDelta);\r\n                    \r\n                    const pCenterDist = this.playerControls.getObject().position.distanceTo(PLANET_CENTER);\r\n\r\n                    if (!this.moveState.isFlying && !this.moveState.isSwimming) {\r\n                        this.velocity.y -= 980 * frameDelta; \/\/ Gravity\r\n                        this.playerControls.getObject().position.y += (this.velocity.y * frameDelta);\r\n\r\n                        if (pCenterDist < PLANET_RADIUS + 20) {\r\n                            this.velocity.y = Math.max(0, this.velocity.y);\r\n                            \r\n                            const normal = new THREE.Vector3().subVectors(this.playerControls.getObject().position, PLANET_CENTER).normalize();\r\n                            this.playerControls.getObject().position.copy(PLANET_CENTER).add(normal.multiplyScalar(PLANET_RADIUS + 20));\r\n                        }\r\n                    } else if (this.moveState.isSwimming) {\r\n                         this.velocity.y *= 0.9;\r\n                         this.playerControls.getObject().position.y += (this.velocity.y * frameDelta);\r\n                         if (pCenterDist > PLANET_RADIUS + 10) {\r\n                             const normal = new THREE.Vector3().subVectors(this.playerControls.getObject().position, PLANET_CENTER).normalize();\r\n                             this.playerControls.getObject().position.copy(PLANET_CENTER).add(normal.multiplyScalar(PLANET_RADIUS + 10));\r\n                         }\r\n                         if (pCenterDist < PLANET_RADIUS - 80) {\r\n                             const normal = new THREE.Vector3().subVectors(this.playerControls.getObject().position, PLANET_CENTER).normalize();\r\n                             this.playerControls.getObject().position.copy(PLANET_CENTER).add(normal.multiplyScalar(PLANET_RADIUS - 80));\r\n                         }\r\n                    } else {\r\n                        this.velocity.y *= 0.95; \r\n                        this.playerControls.getObject().position.y += (this.velocity.y * frameDelta);\r\n                    }\r\n\r\n                    if (this.checkCollisions(this.playerControls.getObject().position)) {\r\n                        this.playerControls.getObject().position.copy(curPos);\r\n                        this.velocity.set(0,0,0);\r\n                    }\r\n\r\n                    this.velocity.x -= this.velocity.x * 5.0 * frameDelta;\r\n                    this.velocity.z -= this.velocity.z * 5.0 * frameDelta;\r\n                }\r\n\r\n                if(this.isInPlayMode && this.isDrivingCar) {\r\n                    if (this.moveState.f) this.carSpeed += 100 * frameDelta;\r\n                    if (this.moveState.b) this.carSpeed -= 100 * frameDelta;\r\n                    if (this.moveState.l) this.carHeading += 1.5 * frameDelta * (this.carSpeed > 0 ? 1 : -1);\r\n                    if (this.moveState.r) this.carHeading -= 1.5 * frameDelta * (this.carSpeed > 0 ? 1 : -1);\r\n\r\n                    this.carSpeed *= 0.95; \r\n\r\n                    this.carPos.x += Math.sin(this.carHeading) * this.carSpeed * frameDelta;\r\n                    this.carPos.y += Math.cos(this.carHeading) * this.carSpeed * frameDelta;\r\n\r\n                    const spherePos = wrapToPlanet(this.carPos.x, this.carPos.y, 20);\r\n                    this.playerCar.position.copy(spherePos);\r\n                    alignToPlanet(this.playerCar);\r\n                    this.playerCar.rotateY(this.carHeading);\r\n\r\n                    const cameraOffset = new THREE.Vector3(0, 80, -200); \r\n                    cameraOffset.applyMatrix4(this.playerCar.matrixWorld);\r\n                    this.camera.position.lerp(cameraOffset, 0.1);\r\n                    this.camera.lookAt(this.playerCar.position);\r\n                }\r\n\r\n                this.renderer.render(this.scene, this.camera);\r\n            }\r\n\r\n            onWindowResize() {\r\n                const c = document.getElementById(`webgl_${INSTANCE_ID}`);\r\n                if(!c) return;\r\n\r\n                let width, height;\r\n\r\n                if (document.fullscreenElement) {\r\n                    width = window.innerWidth;\r\n                    height = window.innerHeight;\r\n                } else {\r\n                    const r = c.getBoundingClientRect();\r\n                    width = r.width;\r\n                    height = r.height;\r\n                }\r\n\r\n                if(width > 0 && height > 0) {\r\n                    this.camera.aspect = width \/ height;\r\n                    this.camera.updateProjectionMatrix();\r\n                    this.renderer.setSize(width, height);\r\n                }\r\n            }\r\n        }\r\n\r\n        const initApp = () => {\r\n            const container = document.getElementById(INSTANCE_ID);\r\n            if(!container || container.dataset.init === '1') return;\r\n            container.dataset.init = '1';\r\n\r\n            window.VMP_ENGINE = new MetaverseManager();\r\n            window.VMP_ENGINE.init().then(() => {\r\n                TerminalLogger.log(\"VMP Engine Successfully Deployed.\", \"succ\");\r\n            });\r\n        };\r\n\r\n        if (document.readyState === 'complete' || document.readyState === 'interactive') {\r\n            setTimeout(initApp, 50);\r\n        } else {\r\n            document.addEventListener('DOMContentLoaded', initApp);\r\n        }\r\n    <\/script>\r\n    \n\n<\/div>\n\n<!-- \n  6. RESPONSIVE ENGINE (JAVASCRIPT)\n  CSS '100vh' often fails on mobile devices (Safari\/Chrome) because of the \n  address bar expanding and collapsing. This JS calculates the *exact* \n  available pixel height dynamically to ensure a \"real app\" feel.\n-->\n<script>\n    (function() {\n        'use strict';\n\n        function resizeApp() {\n            var appContainer = document.getElementById('vmp-fullscreen-app-wrapper');\n            if (appContainer) {\n                \/\/ window.innerHeight gets the exact pixel height available, ignoring mobile UI bars\n                var exactHeight = window.innerHeight;\n                \n                \/\/ Adjust for WordPress Admin Bar if present\n                var wpAdminBar = document.getElementById('wpadminbar');\n                if (wpAdminBar) {\n                    exactHeight = exactHeight - wpAdminBar.offsetHeight;\n                }\n\n                \/\/ Apply the exact pixel height to the wrapper\n                appContainer.style.height = exactHeight + 'px';\n                appContainer.style.minHeight = exactHeight + 'px';\n                \n                \/\/ Find whatever the shortcode rendered (iframe\/canvas) and force it too\n                var childElements = appContainer.querySelectorAll('iframe, canvas, .unity-desktop, .webgl-content');\n                for (var i = 0; i < childElements.length; i++) {\n                    childElements[i].style.height = exactHeight + 'px';\n                }\n            }\n        }\n\n        \/\/ Run immediately on initialization\n        resizeApp();\n\n        \/\/ Run on DOM load to catch late-loading elements\n        window.addEventListener('DOMContentLoaded', resizeApp);\n        \n        \/\/ Run fully on load\n        window.addEventListener('load', resizeApp);\n\n        \/\/ Run every time the user resizes the window or rotates their phone\n        window.addEventListener('resize', resizeApp);\n        window.addEventListener('orientationchange', function() {\n            \/\/ Slight delay on orientation change to allow mobile browsers to catch up\n            setTimeout(resizeApp, 200);\n        });\n        \n        \/\/ Failsafe: Check height periodically for the first 3 seconds \n        \/\/ in case the Shortcode takes a moment to inject the WebGL canvas\n        var retryCount = 0;\n        var interval = setInterval(function() {\n            resizeApp();\n            retryCount++;\n            if (retryCount >= 15) { \/\/ Stop checking after 3 seconds\n                clearInterval(interval); \n            }\n        }, 200);\n\n    })();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1657","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/pages\/1657","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/comments?post=1657"}],"version-history":[{"count":46,"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/pages\/1657\/revisions"}],"predecessor-version":[{"id":1765,"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/pages\/1657\/revisions\/1765"}],"wp:attachment":[{"href":"https:\/\/www.vmpnfts.com\/Omega3dWorldEcosystem\/wp-json\/wp\/v2\/media?parent=1657"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}