{"product_id":"sgp-phantom","title":"SGP phantom","description":"\u003cbody\u003e\n\n\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n    \u003ctitle\u003eSGP PHANTOM - Advanced Hub\u003c\/title\u003e\n    \n    \u003c!-- Google Fonts: Space Grotesk (Headers) and Inter (Body) --\u003e\n    \u003clink rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\"\u003e\n    \u003clink rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin\u003e\n    \u003clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600\u0026amp;family=Space+Grotesk:wght@700;800\u0026amp;display=swap\" rel=\"stylesheet\"\u003e\n\n    \u003cstyle\u003e\n        :root {\n            \/* Neumorphic Color Palette *\/\n            --bg-color: #e0e5ec;\n            --text-main: #2d3748;\n            --text-muted: #718096;\n            --accent: #eab308; \/* Premium Amber\/Gold *\/\n            --success: #38a169;\n            --danger: #e53e3e;\n            \n            \/* Shadows (Extrusion\/Sunken Effects) *\/\n            --shadow-light: rgba(255, 255, 255, 0.8);\n            --shadow-dark: rgba(163, 177, 198, 0.6);\n            --neu-out: 9px 9px 16px var(--shadow-dark), -9px -9px 16px var(--shadow-light);\n            --neu-out-sm: 5px 5px 10px var(--shadow-dark), -5px -5px 10px var(--shadow-light);\n            --neu-in: inset 6px 6px 10px var(--shadow-dark), inset -6px -6px 10px var(--shadow-light);\n            \n            \/* Border Radii *\/\n            --radius-xl: 40px;\n            --radius-lg: 30px;\n            --radius-pill: 100px;\n            --transition: all 0.25s ease-in-out;\n        }\n\n        * { box-sizing: border-box; margin: 0; padding: 0; }\n\n        body {\n            background-color: var(--bg-color);\n            color: var(--text-main);\n            font-family: 'Inter', sans-serif;\n            line-height: 1.6;\n            -webkit-font-smoothing: antialiased;\n            padding: 20px;\n            overflow-x: hidden;\n        }\n\n        h1, h2, h3, h4 {\n            font-family: 'Space Grotesk', sans-serif;\n            font-weight: 800;\n            color: var(--text-main);\n            margin-bottom: 15px;\n            letter-spacing: -0.5px;\n        }\n\n        .product-container { max-width: 1000px; margin: 0 auto; padding-bottom: 60px; }\n        \n        .neu-card { background: var(--bg-color); border-radius: var(--radius-xl); box-shadow: var(--neu-out); padding: 40px; margin-bottom: 40px; }\n        .neu-card-sm { background: var(--bg-color); border-radius: var(--radius-lg); box-shadow: var(--neu-out); padding: 25px; display: flex; flex-direction: column; gap: 15px; }\n        .neu-sunken { background: var(--bg-color); border-radius: var(--radius-lg); box-shadow: var(--neu-in); padding: 20px; }\n\n        .neu-icon { width: 60px; height: 60px; border-radius: 50%; background: var(--bg-color); box-shadow: var(--neu-out); display: flex; align-items: center; justify-content: center; color: var(--accent); font-size: 24px; margin-bottom: 10px; }\n        .svg-icon { width: 28px; height: 28px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }\n\n        \/* Header *\/\n        .header-section { text-align: center; margin-bottom: 50px; padding-top: 20px; }\n        .badge { display: inline-block; background: var(--bg-color); box-shadow: var(--neu-in); padding: 8px 20px; border-radius: var(--radius-pill); font-size: 13px; font-weight: 600; color: var(--accent); text-transform: uppercase; letter-spacing: 2px; margin-bottom: 20px; }\n        .main-title { font-size: clamp(32px, 5vw, 56px); background: linear-gradient(135deg, #2d3748 0%, #718096 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 10px; }\n        .subtitle { font-size: clamp(16px, 2vw, 20px); color: var(--text-muted); font-weight: 500; max-width: 700px; margin: 0 auto 30px auto; }\n\n        \/* Media Grid (Videos) *\/\n        .media-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; margin-bottom: 50px; }\n        .video-container { border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--neu-out); position: relative; background: var(--bg-color); padding: 10px; }\n        .video-container video { width: 100%; aspect-ratio: 16\/9; object-fit: cover; border-radius: 20px; display: block; }\n        .video-label { text-align: center; font-size: 12px; font-weight: 600; color: var(--text-muted); margin-top: 15px; margin-bottom: 5px; text-transform: uppercase; letter-spacing: 1px; }\n\n        \/* Features Grid *\/\n        .features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 30px; margin-bottom: 50px; }\n        .feature-title { font-size: 18px; margin-bottom: 5px; }\n        .feature-desc { color: var(--text-muted); font-size: 15px; }\n\n        \/* Gallery (Grid Mosaico) *\/\n        .gallery-wrapper { margin-top: 50px; margin-bottom: 50px; }\n        .gallery-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; padding: 20px; }\n        .gallery-item { border-radius: var(--radius-lg); padding: 8px; box-shadow: var(--neu-out); background: var(--bg-color); transition: var(--transition); }\n        .gallery-item:hover { transform: translateY(-5px); box-shadow: 12px 12px 20px var(--shadow-dark), -12px -12px 20px var(--shadow-light); }\n        \n        \/* Contenedor CRT para el efecto de TV Antigua *\/\n        .crt-wrapper { position: relative; border-radius: 22px; overflow: hidden; }\n        .gallery-item img { width: 100%; aspect-ratio: 4\/3; object-fit: cover; display: block; filter: contrast(125%) saturate(70%) sepia(30%) hue-rotate(10deg); }\n        \n        \/* Scanlines y Viñeta *\/\n        .crt-wrapper::after {\n            content: \"\";\n            position: absolute;\n            top: 0; left: 0; right: 0; bottom: 0;\n            background: linear-gradient(rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.15) 50%);\n            background-size: 100% 4px;\n            box-shadow: inset 0 0 30px rgba(0,0,0,0.6);\n            pointer-events: none;\n            z-index: 2;\n        }\n\n        \/* Interactive 3D Viewer *\/\n        .viewer-3d-container { width: 100%; height: 500px; border-radius: var(--radius-xl); box-shadow: var(--neu-in); overflow: hidden; position: relative; cursor: grab; display: flex; flex-direction: column; }\n        .viewer-3d-container:active { cursor: grabbing; }\n        .viewer-instructions { position: absolute; bottom: 20px; left: 0; right: 0; text-align: center; color: var(--text-muted); font-size: 13px; font-weight: 500; pointer-events: none; z-index: 10; }\n        \n        #three-canvas-container { flex: 1; width: 100%; height: 100%; outline: none; }\n\n        \/* Disclaimer *\/\n        .disclaimer { margin-top: 60px; text-align: center; }\n        .disclaimer p { font-size: 12px; color: var(--text-muted); margin-top: 10px; }\n\n        \/* Animación Fade *\/\n        @keyframes fadeUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } }\n        .reveal { animation: fadeUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards; }\n\n        @media (max-width: 768px) { .neu-card { padding: 25px; } .main-title { font-size: 32px; } .viewer-3d-container { height: 450px; } }\n    \u003c\/style\u003e\n\n\n\n\u003cdiv class=\"product-container reveal\"\u003e\n\n    \u003cheader class=\"header-section\"\u003e\n        \u003cdiv class=\"badge\"\u003eProfessional Hardware\u003c\/div\u003e\n        \u003ch1 class=\"main-title\"\u003eSGP PHANTOM\u003c\/h1\u003e\n        \u003cp class=\"subtitle\"\u003eThe ultimate IT diagnostic and environmental monitoring hub. Designed for network administrators and security researchers.\u003c\/p\u003e\n        \n        \u003cdiv class=\"neu-sunken\" style=\"display: inline-block; max-width: 800px; margin: 0 auto;\"\u003e\n            \u003cp style=\"color: var(--text-main); font-size: 16px; font-weight: 500;\"\u003e\n                Driven by the high-performance \u003cstrong\u003eESP32-S3\u003c\/strong\u003e architecture, the Phantom is more than a learning platform—it’s a field-ready asset for digital and physical diagnostics.\n            \u003c\/p\u003e\n        \u003c\/div\u003e\n    \u003c\/header\u003e\n\n    \u003c!-- Video Showcase --\u003e\n    \u003cdiv class=\"media-grid\"\u003e\n        \u003cdiv\u003e\n            \u003cdiv class=\"video-container\"\u003e\n                \u003cvideo preload=\"metadata\" controls aria-label=\"SGP Phantom Hardware Overview\" poster=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/03\/photo_2026-03-05_19-06-26.jpg\"\u003e\n                    \u003csource src=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/03\/The_SGP_Phantom-1.mp4\" type=\"video\/mp4\"\u003e\n                    Your browser does not support HTML5 video.\n                \u003c\/source\u003e\u003c\/video\u003e\n            \u003c\/div\u003e\n            \u003cdiv class=\"video-label\"\u003eHardware Overview\u003c\/div\u003e\n        \u003c\/div\u003e\n        \u003cdiv\u003e\n            \u003cdiv class=\"video-container\"\u003e\n                \u003cvideo preload=\"metadata\" controls aria-label=\"SGP Phantom Diagnostic Interface\" poster=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/03\/photo_2026-03-05_19-06-10.jpg\"\u003e\n                    \u003csource src=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/02\/VID_20260220_162621_335_bsl.mp4\" type=\"video\/mp4\"\u003e\n                    Your browser does not support HTML5 video.\n                \u003c\/source\u003e\u003c\/video\u003e\n            \u003c\/div\u003e\n            \u003cdiv class=\"video-label\"\u003eDiagnostic Interface\u003c\/div\u003e\n        \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003ch2 style=\"text-align: center; margin-bottom: 40px; font-size: 28px;\"\u003eCore Operational Capabilities\u003c\/h2\u003e\n    \n    \u003cdiv class=\"features-grid\"\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003crect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" ry=\"2\"\u003e\u003c\/rect\u003e\u003crect x=\"9\" y=\"9\" width=\"6\" height=\"6\"\u003e\u003c\/rect\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eESP32-S3 Command Center\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eFully programmable silicon. Deploy diagnostic scripts, automate IT routines, and audit system infrastructure with raw S3 power.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003crect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\"\u003e\u003c\/rect\u003e\u003cline x1=\"8\" y1=\"21\" x2=\"16\" y2=\"21\"\u003e\u003c\/line\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eProfessional LCD Interface\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eHigh-definition screen paired with 3 programmable physical buttons for rapid tool deployment in field testing scenarios.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003cpath d=\"M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eEnvironmental Sensing\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eIntegrated BME680 multi-sensor. Monitor Air Quality (VOCs), Temperature, Humidity, Barometric Pressure, and Altitude in real-time.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003cpath d=\"M5 12.55a11 11 0 0 1 14.08 0\"\u003e\u003c\/path\u003e\u003cpath d=\"M1.42 9a16 16 0 0 1 21.16 0\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eSignal Analysis\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eNative Wi-Fi \u0026amp; Bluetooth stacks for comprehensive wireless auditing and protocol analysis.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003cpolygon points=\"12 2 2 7 12 12 22 7 12 2\"\u003e\u003c\/polygon\u003e\u003cpolyline points=\"2 17 12 22 22 17\"\u003e\u003c\/polyline\u003e\u003cpolyline points=\"2 12 12 17 22 12\"\u003e\u003c\/polyline\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eLimitless Expansion\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eOpen architecture allows you to bridge external hardware and sensors, scaling your capabilities as the mission evolves.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003cpath d=\"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eHigh-Fidelity Visuals\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eOptimized UI rendering with over 263,000 colors for clear data visualization under any lighting condition.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003crect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"\u003e\u003c\/rect\u003e\u003cpath d=\"M7 11V7a5 5 0 0 1 10 0v4\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eRFID\/NFC RC522 Reader\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eIntegrated 13.56MHz module. Read, write, and clone smart cards, tags, and access credentials natively from the device.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003cpath d=\"M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16z\"\u003e\u003c\/path\u003e\u003cpath d=\"M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4z\"\u003e\u003c\/path\u003e\u003cpath d=\"M12 2v2\"\u003e\u003c\/path\u003e\u003cpath d=\"M12 20v2\"\u003e\u003c\/path\u003e\u003cpath d=\"M2 12h2\"\u003e\u003c\/path\u003e\u003cpath d=\"M20 12h2\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eRadar \u0026amp; IoT Connectivity\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eDeploy spatial radar mapping applications and connect to the global internet network for remote data exfiltration and updates.\u003c\/p\u003e\n        \u003c\/div\u003e\n        \u003cdiv class=\"neu-card-sm\"\u003e\n            \u003cdiv class=\"neu-icon\"\u003e\u003csvg class=\"svg-icon\" viewbox=\"0 0 24 24\"\u003e\u003crect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\" ry=\"1\"\u003e\u003c\/rect\u003e\u003crect x=\"4\" y=\"6\" width=\"16\" height=\"16\" rx=\"2\" ry=\"2\"\u003e\u003c\/rect\u003e\u003cline x1=\"12\" y1=\"11\" x2=\"12\" y2=\"17\"\u003e\u003c\/line\u003e\u003cline x1=\"9\" y1=\"14\" x2=\"15\" y2=\"14\"\u003e\u003c\/line\u003e\u003c\/svg\u003e\u003c\/div\u003e\n            \u003ch3 class=\"feature-title\"\u003eExtended Power \u0026amp; USB OTG\u003c\/h3\u003e\n            \u003cp class=\"feature-desc\"\u003eHigh-capacity \u003cstrong\u003e\u0026gt;500 mAh battery\u003c\/strong\u003e for extended field ops, plus USB OTG port to interface with external peripheral devices directly.\u003c\/p\u003e\n        \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Hardware Gallery --\u003e\n    \u003cdiv class=\"gallery-wrapper\"\u003e\n        \u003ch2 style=\"text-align: center; margin-bottom: 10px; font-size: 28px;\"\u003eHardware Gallery\u003c\/h2\u003e\n        \u003cp style=\"text-align: center; color: var(--text-muted); font-size: 14px; margin-bottom: 20px;\"\u003eExplore the premium build quality\u003c\/p\u003e\n        \n        \u003cdiv class=\"gallery-grid neu-sunken\"\u003e\n            \u003cdiv class=\"gallery-item\"\u003e\n                \u003cdiv class=\"crt-wrapper\"\u003e\n                    \u003cimg src=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/03\/photo_2026-03-05_19-06-26.jpg\" alt=\"Sensor BME680\" loading=\"lazy\"\u003e\n                \u003c\/div\u003e\n            \u003c\/div\u003e\n            \u003cdiv class=\"gallery-item\"\u003e\n                \u003cdiv class=\"crt-wrapper\"\u003e\n                    \u003cimg src=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/03\/photo_2026-03-05_19-06-38.jpg\" alt=\"Motherboard\" loading=\"lazy\"\u003e\n                \u003c\/div\u003e\n            \u003c\/div\u003e\n            \u003cdiv class=\"gallery-item\"\u003e\n                \u003cdiv class=\"crt-wrapper\"\u003e\n                    \u003cimg src=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/03\/photo_2026-03-05_19-06-10.jpg\" alt=\"LCD Interface Detail\" loading=\"lazy\"\u003e\n                \u003c\/div\u003e\n            \u003c\/div\u003e\n            \u003cdiv class=\"gallery-item\"\u003e\n                \u003cdiv class=\"crt-wrapper\"\u003e\n                    \u003cimg src=\"https:\/\/sgpcard.com\/wp-content\/uploads\/2026\/03\/photo_2026-03-05_19-05-49.jpg\" alt=\"Connectivity Ports\" loading=\"lazy\"\u003e\n                \u003c\/div\u003e\n            \u003c\/div\u003e\n        \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Interactive 3D Model --\u003e\n    \u003ch2 style=\"text-align: center; margin-bottom: 10px; font-size: 28px;\"\u003eInteractive 3D Preview\u003c\/h2\u003e\n    \u003cdiv class=\"viewer-3d-container\"\u003e\n        \u003cdiv id=\"three-canvas-container\"\u003e\u003c\/div\u003e\n        \u003cdiv class=\"viewer-instructions\"\u003eClick and drag to rotate. Tap side buttons to interact.\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Legal Disclaimer --\u003e\n    \u003cdiv class=\"disclaimer neu-sunken\"\u003e\n        \u003ch4 style=\"color: var(--danger); font-size: 14px; margin-bottom: 5px; text-transform: uppercase;\"\u003eResponsibility Protocol\u003c\/h4\u003e\n        \u003cp\u003eProfessional engineering tool designed strictly for STEM education, IT research, and authorized network diagnostics. The user is solely responsible for compliance with all local laws and regulations. This is not a surveillance device.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js\"\u003e\u003c\/script\u003e\n\u003cscript\u003e\n    window.addEventListener('load', function() {\n        const container = document.getElementById('three-canvas-container');\n        if (!container) return;\n        \n        const scene = new THREE.Scene();\n        const camera = new THREE.PerspectiveCamera(45, container.clientWidth \/ container.clientHeight, 0.1, 100);\n        camera.position.z = 5; \n\n        const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });\n        renderer.setSize(container.clientWidth, container.clientHeight);\n        renderer.setPixelRatio(window.devicePixelRatio);\n        container.appendChild(renderer.domElement);\n\n        const deviceGroup = new THREE.Group();\n        scene.add(deviceGroup);\n\n        const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);\n        scene.add(ambientLight);\n        const dirLight = new THREE.DirectionalLight(0xffffff, 0.9);\n        dirLight.position.set(5, 5, 5);\n        scene.add(dirLight);\n\n        \/\/ 1. Cuerpo del SGP Phantom (Bloque vertical)\n        const bodyWidth = 1.2;\n        const bodyHeight = 2.4;\n        const bodyDepth = 0.22; \/\/ Grosor reducido (antes 0.4) para un perfil delgado\n        \n        const shape = new THREE.Shape();\n        shape.moveTo(-bodyWidth\/2, bodyHeight\/2);\n        shape.lineTo(bodyWidth\/2, bodyHeight\/2);\n        shape.lineTo(bodyWidth\/2, -bodyHeight\/2);\n        shape.lineTo(-bodyWidth\/2, -bodyHeight\/2);\n        shape.lineTo(-bodyWidth\/2, bodyHeight\/2);\n\n        \/\/ Agujero cuadrado abajo a la derecha\n        const hole = new THREE.Path();\n        hole.moveTo(0.38, -0.92);\n        hole.lineTo(0.52, -0.92);\n        hole.lineTo(0.52, -1.06);\n        hole.lineTo(0.38, -1.06);\n        hole.lineTo(0.38, -0.92);\n        shape.holes.push(hole);\n\n        const extrudeSettings = {\n            depth: bodyDepth,\n            bevelEnabled: true,\n            bevelThickness: 0.02,\n            bevelSize: 0.02,\n            bevelSegments: 3\n        };\n        const bodyGeo = new THREE.ExtrudeGeometry(shape, extrudeSettings);\n        bodyGeo.translate(0, 0, -bodyDepth\/2); \/\/ Centrar extrusión\n\n        const bodyMat = new THREE.MeshStandardMaterial({ \n            color: 0x111111,\n            roughness: 0.85, \n            metalness: 0.2 \n        });\n        const body = new THREE.Mesh(bodyGeo, bodyMat);\n        deviceGroup.add(body);\n\n        \/\/ 2. Pantalla LCD (Moved to TOP half)\n        const screenCanvas = document.createElement('canvas');\n        screenCanvas.width = 256;\n        screenCanvas.height = 256;\n        const ctx = screenCanvas.getContext('2d');\n        const screenTex = new THREE.CanvasTexture(screenCanvas);\n        \n        const screenWidth = 1.05;\n        const screenHeight = 1.05;\n        const screenGeo = new THREE.PlaneGeometry(screenWidth, screenHeight);\n        const screenMat = new THREE.MeshBasicMaterial({ map: screenTex });\n        const screen = new THREE.Mesh(screenGeo, screenMat);\n        \n        \/\/ Postion screen on TOP half of the device face (Ajustado por el bisel de la extrusión)\n        screen.position.set(0, 0.5, (bodyDepth \/ 2) + 0.025); \n        deviceGroup.add(screen);\n\n        const glassGeo = new THREE.PlaneGeometry(screenWidth, screenHeight);\n        const glassMat = new THREE.MeshStandardMaterial({ \n            color: 0x000000, \n            transparent: true, \n            opacity: 0.2, \n            roughness: 0.1, \n            metalness: 0.9 \n        });\n        const glass = new THREE.Mesh(glassGeo, glassMat);\n        glass.position.set(0, 0.5, (bodyDepth \/ 2) + 0.035);\n        deviceGroup.add(glass);\n\n        \/\/ 3. Botones Laterales (Borde Derecho, alineados con la pantalla arriba)\n        const btnGeo = new THREE.BoxGeometry(0.15, 0.3, 0.08); \/\/ Botones adaptados al nuevo grosor\n        const btnMat = new THREE.MeshStandardMaterial({ color: 0x050505, roughness: 0.9 });\n        const interactiveButtons = [];\n\n        for(let i=0; i\u003c3; i++) {\n            const btn = new THREE.Mesh(btnGeo, btnMat);\n            \/\/ Posicionar a la derecha (eje X positivo), mitad superior (eje Y positivo)\n            const startX = (bodyWidth \/ 2) + 0.05;\n            btn.position.set(startX, 0.8 - (i * 0.35), 0);\n            \n            btn.userData = { \n                id: i, \n                originalX: startX,\n                programName: i === 0 ? 'MENU' : (i === 1 ? 'RADAR' : 'SENSORS')\n            };\n            \n            deviceGroup.add(btn);\n            interactiveButtons.push(btn);\n        }\n\n        \/\/ 4. Interacciones de Ratón y Táctil\n        let isDragging = false;\n        let previousMousePosition = { x: 0, y: 0 };\n        let clickStartPos = { x: 0, y: 0 };\n        const raycaster = new THREE.Raycaster();\n        const mouse = new THREE.Vector2();\n\n        let currentProgram = 'MENU'; \n        let time = 0;\n\n        const getCoords = (e) =\u003e {\n            const rect = container.getBoundingClientRect();\n            let clientX, clientY;\n\n            if (e.changedTouches \u0026\u0026 e.changedTouches.length \u003e 0) {\n                clientX = e.changedTouches[0].clientX;\n                clientY = e.changedTouches[0].clientY;\n            } else {\n                clientX = e.clientX;\n                clientY = e.clientY;\n            }\n\n            return {\n                x: clientX - rect.left,\n                y: clientY - rect.top,\n                normX: ((clientX - rect.left) \/ container.clientWidth) * 2 - 1,\n                normY: -((clientY - rect.top) \/ container.clientHeight) * 2 + 1\n            };\n        };\n\n        const startInteraction = (e) =\u003e {\n            isDragging = true;\n            const coords = getCoords(e);\n            previousMousePosition = { x: coords.x, y: coords.y };\n            clickStartPos = { x: coords.x, y: coords.y };\n        };\n        \n        const doInteraction = (e) =\u003e {\n            if (isDragging) {\n                const coords = getCoords(e);\n                const deltaMove = { \n                    x: coords.x - previousMousePosition.x, \n                    y: coords.y - previousMousePosition.y \n                };\n                deviceGroup.rotation.y += deltaMove.x * 0.01;\n                deviceGroup.rotation.x += deltaMove.y * 0.01;\n                previousMousePosition = { x: coords.x, y: coords.y };\n            }\n        };\n        \n        const endInteraction = (e) =\u003e {\n            isDragging = false;\n            const coords = getCoords(e);\n            const dist = Math.sqrt(Math.pow(coords.x - clickStartPos.x, 2) + Math.pow(coords.y - clickStartPos.y, 2));\n            \n            \/\/ Si no hubo apenas arrastre, es un clic (pulsación de botón)\n            if (dist \u003c 5) { \n                mouse.x = coords.normX;\n                mouse.y = coords.normY;\n                raycaster.setFromCamera(mouse, camera);\n\n                const intersects = raycaster.intersectObjects(interactiveButtons);\n                if (intersects.length \u003e 0) {\n                    const btn = intersects[0].object;\n                    currentProgram = btn.userData.programName; \n                    \n                    \/\/ Animar botón hundiéndose\n                    btn.position.x = btn.userData.originalX - 0.08;\n                    setTimeout(() =\u003e {\n                        btn.position.x = btn.userData.originalX;\n                    }, 150);\n                }\n            }\n        };\n\n        container.addEventListener('mousedown', startInteraction);\n        document.addEventListener('mousemove', doInteraction);\n        document.addEventListener('mouseup', endInteraction);\n        \n        container.addEventListener('touchstart', startInteraction, {passive: true});\n        document.addEventListener('touchmove', doInteraction, {passive: true});\n        document.addEventListener('touchend', endInteraction);\n\n        window.addEventListener('resize', () =\u003e {\n            camera.aspect = container.clientWidth \/ container.clientHeight;\n            camera.updateProjectionMatrix();\n            renderer.setSize(container.clientWidth, container.clientHeight);\n        });\n\n        \/\/ 5. Funciones de Dibujo (Programas)\n        const drawMenu = () =\u003e {\n            ctx.fillStyle = '#39ff14';\n            ctx.font = 'bold 20px monospace';\n            ctx.fillText('HACKER OS', 75, 40);\n            ctx.fillRect(15, 55, 226, 2);\n            \n            ctx.font = '16px monospace';\n            const items = ['\u003e MATCH FACES', '\u003e WIFI MOTION', '\u003e GPIO CLONER', '\u003e BIOHAZARD', '\u003e GAS MONITOR'];\n            items.forEach((item, i) =\u003e {\n                if (Math.floor(time * 1.5) % items.length === i) {\n                    ctx.fillStyle = '#1a401a';\n                    ctx.fillRect(15, 75 + i * 30 - 16, 226, 22);\n                    ctx.fillStyle = '#39ff14';\n                }\n                ctx.fillText(item, 20, 75 + i * 30);\n            });\n        };\n\n        const drawSensors = () =\u003e {\n            ctx.fillStyle = '#39ff14';\n            ctx.font = 'bold 20px monospace';\n            ctx.fillText('BME680 SENSOR', 50, 40);\n            ctx.fillRect(15, 55, 226, 2);\n            \n            ctx.font = '18px monospace';\n            const t = (24.1 + Math.sin(time)*0.5).toFixed(1);\n            const h = (42.5 + Math.cos(time)*1.2).toFixed(1);\n            \n            ctx.fillText(`TEMP : ${t} C`, 20, 100);\n            ctx.fillText(`HUM  : ${h} %`, 20, 140);\n            ctx.fillText(`PRES : 1013 hPa`, 20, 180);\n            \n            ctx.fillStyle = Math.sin(time*5) \u003e 0 ? '#39ff14' : '#1a401a';\n            ctx.fillText(`VOC  : DETECTING...`, 20, 220);\n        };\n\n        const drawRadar = () =\u003e {\n            const centerX = 128, centerY = 128, maxRadius = 115;\n            ctx.strokeStyle = '#1a401a'; \n            ctx.lineWidth = 1;\n            ctx.beginPath();\n            for(let r = 30; r \u003c maxRadius; r += 30) ctx.arc(centerX, centerY, r, 0, Math.PI * 2);\n            ctx.moveTo(centerX - maxRadius, centerY); ctx.lineTo(centerX + maxRadius, centerY);\n            ctx.moveTo(centerX, centerY - maxRadius); ctx.lineTo(centerX, centerY + maxRadius);\n            ctx.stroke();\n\n            const sweepAngle = (time * 3) % (Math.PI * 2);\n            const gradient = ctx.createConicGradient(sweepAngle + Math.PI\/2, centerX, centerY);\n            gradient.addColorStop(0, 'rgba(57, 255, 20, 0)');\n            gradient.addColorStop(0.7, 'rgba(57, 255, 20, 0.05)');\n            gradient.addColorStop(1, 'rgba(57, 255, 20, 0.5)');\n            ctx.fillStyle = gradient;\n            ctx.beginPath(); ctx.moveTo(centerX, centerY);\n            ctx.arc(centerX, centerY, maxRadius, sweepAngle - 0.7, sweepAngle);\n            ctx.lineTo(centerX, centerY); ctx.fill();\n\n            ctx.strokeStyle = '#39ff14'; ctx.lineWidth = 2;\n            ctx.beginPath(); ctx.moveTo(centerX, centerY);\n            ctx.lineTo(centerX + Math.cos(sweepAngle)*maxRadius, centerY + Math.sin(sweepAngle)*maxRadius);\n            ctx.stroke();\n\n            ctx.fillStyle = '#39ff14';\n            ctx.beginPath(); ctx.arc(centerX, centerY, 3 + Math.sin(time*8)*1.5, 0, Math.PI*2); ctx.fill();\n            ctx.beginPath(); ctx.arc(centerX + 60, centerY - 40, 4, 0, Math.PI*2); ctx.fill();\n            ctx.beginPath(); ctx.arc(centerX - 50, centerY + 70, 4, 0, Math.PI*2); ctx.fill();\n            \n            ctx.font = 'bold 14px monospace';\n            ctx.fillText('RF SCAN: ACTIVE', 10, 25);\n            ctx.font = '12px monospace';\n            ctx.fillText('TARGETS: 2', 10, 245);\n        };\n\n        \/\/ 6. Bucle Principal\n        function animate() {\n            requestAnimationFrame(animate);\n            time += 0.02;\n\n            ctx.fillStyle = '#020502';\n            ctx.fillRect(0, 0, 256, 256);\n\n            if (currentProgram === 'MENU') drawMenu();\n            else if (currentProgram === 'RADAR') drawRadar();\n            else if (currentProgram === 'SENSORS') drawSensors();\n\n            screenTex.needsUpdate = true;\n\n            if (!isDragging) {\n                deviceGroup.rotation.y += 0.005;\n                deviceGroup.position.y = Math.sin(time) * 0.05; \/\/ Hovering muy sutil\n            }\n\n            renderer.render(scene, camera);\n        }\n        \n        animate();\n    });\n\u003c\/script\u003e\n\n\u003c\/body\u003e","brand":"sgpstore","offers":[{"title":"Default Title","offer_id":57533564780876,"sku":null,"price":230.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1057\/9807\/4700\/files\/rn-image_picker_lib_temp_334f85ee-291c-4675-ac13-ea52b37cb46e.png?v=1778887517","url":"https:\/\/sgpstore.net\/products\/sgp-phantom","provider":"sgpstore","version":"1.0","type":"link"}