{"product_id":"sin-titulo-7jun_15-01-42","title":"SGP Spectre","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 Spectre - Product Description\u003c\/title\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=Orbitron:wght@500;600;700;800\u0026amp;family=Inter:wght@400;500;600\u0026amp;display=swap\" rel=\"stylesheet\"\u003e\n    \u003cscript src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js\"\u003e\u003c\/script\u003e\n    \u003cscript src=\"https:\/\/d3js.org\/d3.v7.min.js\"\u003e\u003c\/script\u003e\n    \u003cscript src=\"https:\/\/unpkg.com\/topojson-client@3\"\u003e\u003c\/script\u003e\n\n\n\n\u003cstyle\u003e\n  .spectre-desc {\n    font-family: 'Inter', sans-serif;\n    background: transparent;\n    padding: clamp(30px, 5vw, 60px) 16px;\n    color: #4a5568;\n    max-width: 1100px;\n    margin: 0 auto;\n  }\n\n  \/* Cabecera \/ Intro *\/\n  .spectre-hero {\n    text-align: center;\n    margin-bottom: 40px;\n    opacity: 0;\n    transform: translateY(20px);\n    animation: fadeUp 0.8s ease forwards;\n  }\n\n  .spectre-title {\n    font-family: 'Orbitron', sans-serif;\n    font-weight: 800;\n    font-size: clamp(32px, 5vw, 56px);\n    color: #2d3748;\n    margin: 0 0 10px 0;\n    letter-spacing: 2px;\n    text-transform: uppercase;\n    text-shadow: 2px 2px 4px rgba(255,255,255,0.8);\n  }\n\n  .spectre-subtitle {\n    font-size: clamp(16px, 2vw, 20px);\n    font-weight: 600;\n    color: #eab308;\n    text-transform: uppercase;\n    letter-spacing: 3px;\n    margin: 0 0 20px 0;\n  }\n\n  .spectre-intro {\n    max-width: 700px;\n    margin: 0 auto;\n    font-size: 16px;\n    line-height: 1.6;\n  }\n\n  \/* PANTALLA TÁCTIL SIMULADA *\/\n  .spectre-device-wrapper {\n    display: flex;\n    justify-content: center;\n    margin: 0 auto 60px auto;\n    opacity: 0;\n    transform: translateY(20px);\n  }\n\n  .spectre-device-wrapper.is-visible {\n    animation: fadeUp 0.8s ease forwards;\n    animation-delay: 0.3s;\n  }\n\n  .spectre-device-casing {\n    background: #e0e5ec;\n    padding: 16px;\n    border-radius: 40px;\n    box-shadow: \n      12px 12px 24px rgba(163, 177, 198, 0.6), \n      -12px -12px 24px rgba(255, 255, 255, 0.8);\n    border: 1px solid rgba(255,255,255,0.4);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n  }\n\n  .spectre-device-bezel {\n    background: #1e293b;\n    padding: 10px;\n    border-radius: 28px;\n    box-shadow: inset 2px 2px 6px rgba(0,0,0,0.8), inset -2px -2px 6px rgba(255,255,255,0.1);\n  }\n\n  .spectre-screen {\n    background: #0f172a;\n    width: 280px;\n    height: 450px;\n    border-radius: 20px;\n    position: relative;\n    overflow: hidden;\n    display: flex;\n    flex-direction: column;\n    border: 2px solid #000;\n    box-shadow: inset 0 0 20px rgba(0,0,0,0.9);\n    color: #e2e8f0;\n    font-family: 'Orbitron', sans-serif;\n  }\n\n  .spectre-screen::before {\n    content: \" \";\n    display: block;\n    position: absolute;\n    top: 0; left: 0; bottom: 0; right: 0;\n    background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));\n    z-index: 50;\n    background-size: 100% 3px, 3px 100%;\n    pointer-events: none;\n  }\n\n  .spectre-screen-glare {\n    position: absolute;\n    top: 0; left: -50%; width: 200%; height: 100%;\n    background: linear-gradient(to bottom right, rgba(255,255,255,0.08) 0%, rgba(255,255,255,0) 40%);\n    pointer-events: none;\n    transform: rotate(-15deg);\n    z-index: 55;\n  }\n\n  .spectre-status-bar {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 8px 16px;\n    font-size: 11px;\n    color: #94a3b8;\n    background: #0f172a;\n    border-bottom: 1px solid rgba(255,255,255,0.05);\n    z-index: 40;\n    position: relative;\n  }\n\n  .spectre-status-icons { display: flex; gap: 8px; color: #eab308; }\n\n  .spectre-view-container {\n    flex: 1;\n    position: relative;\n    overflow: hidden;\n    z-index: 30;\n  }\n\n  .spectre-view {\n    position: absolute;\n    top: 0; left: 0; width: 100%; height: 100%;\n    background: #0f172a;\n    display: none;\n    flex-direction: column;\n    padding: 16px;\n    box-sizing: border-box;\n    overflow-y: auto;\n    scrollbar-width: none;\n  }\n  .spectre-view::-webkit-scrollbar { display: none; }\n  \n  .spectre-view.active {\n    display: flex;\n    animation: fadeInApp 0.3s ease;\n  }\n\n  @keyframes fadeInApp {\n    from { opacity: 0; transform: scale(0.95); }\n    to { opacity: 1; transform: scale(1); }\n  }\n\n  \/* HOME GRID *\/\n  #view-home {\n    grid-template-columns: repeat(3, 1fr);\n    grid-auto-rows: 80px;\n    gap: 16px 10px;\n    padding: 24px 16px;\n    align-content: start;\n  }\n  #view-home.active { display: grid; }\n\n  .spectre-app {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: start;\n    gap: 8px;\n    cursor: pointer;\n    transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n    position: relative;\n    z-index: 40;\n  }\n\n  .spectre-app:active { transform: scale(0.9); }\n\n  .app-icon {\n    width: 54px;\n    height: 54px;\n    background: linear-gradient(135deg, #1e293b, #0f172a);\n    border-radius: 14px;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    font-size: 26px;\n    box-shadow: 4px 4px 10px rgba(0,0,0,0.8), -1px -1px 6px rgba(255,255,255,0.05);\n    border: 1px solid rgba(255,255,255,0.08);\n    position: relative;\n  }\n\n  .app-icon.has-badge::after {\n    content: ''; position: absolute; top: -2px; right: -2px; width: 12px; height: 12px;\n    background: #ef4444; border-radius: 50%; border: 2px solid #0f172a;\n    animation: pulseBadge 2s infinite;\n  }\n\n  @keyframes pulseBadge {\n    0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); }\n    70% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }\n    100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }\n  }\n\n  .app-name {\n    color: #cbd5e1; font-size: 10px; font-family: 'Inter', sans-serif;\n    font-weight: 600; text-align: center; text-transform: uppercase; letter-spacing: 0.5px;\n  }\n\n  .spectre-home-bar {\n    height: 30px; background: #0f172a; display: flex; justify-content: center;\n    align-items: center; z-index: 40; position: relative; cursor: pointer;\n    border-top: 1px solid rgba(255,255,255,0.05);\n  }\n\n  .spectre-home-indicator {\n    width: 80px; height: 4px; background: #cbd5e1; border-radius: 4px;\n    transition: background 0.2s, transform 0.2s;\n  }\n  .spectre-home-bar:hover .spectre-home-indicator { background: #eab308; transform: scaleY(1.5); }\n\n  .app-header {\n    text-align: center; color: #eab308; font-size: 14px; letter-spacing: 2px;\n    margin-bottom: 20px; border-bottom: 1px solid rgba(234, 179, 8, 0.3); padding-bottom: 8px;\n  }\n\n  \/* APPS STYLES *\/\n  .radar-container {\n    position: relative; width: 200px; height: 200px; margin: 0 auto 20px auto;\n    border-radius: 50%; border: 2px solid #22c55e;\n    background: radial-gradient(circle, rgba(34,197,94,0.1) 0%, rgba(15,23,42,1) 70%); overflow: hidden;\n  }\n  .radar-grid {\n    position: absolute; top:0; left:0; width:100%; height:100%;\n    background-image: linear-gradient(#22c55e 1px, transparent 1px), linear-gradient(90deg, #22c55e 1px, transparent 1px);\n    background-size: 40px 40px; opacity: 0.2; border-radius: 50%;\n  }\n  .radar-sweep {\n    position: absolute; top: 50%; left: 50%; width: 100px; height: 100px;\n    background: conic-gradient(from 0deg, transparent 70%, rgba(34,197,94,0.8) 100%);\n    transform-origin: 0% 0%; animation: radarSpin 2s linear infinite;\n  }\n  .sat-dot { position: absolute; width: 6px; height: 6px; background: #fff; border-radius: 50%; box-shadow: 0 0 8px #fff; }\n  @keyframes radarSpin { 100% { transform: rotate(360deg); } }\n  .gnss-data { font-family: 'Inter', monospace; font-size: 12px; color: #22c55e; line-height: 1.8; }\n\n  .lora-console {\n    flex: 1; background: #000; border: 1px solid #334155; border-radius: 8px;\n    padding: 10px; font-family: monospace; font-size: 11px; color: #38bdf8;\n    overflow-y: hidden; display: flex; flex-direction: column; justify-content: flex-end;\n  }\n  .lora-line { margin: 2px 0; opacity: 0.8; }\n  .lora-line.tx { color: #eab308; }\n\n  #wifi-canvas { width: 100%; height: 150px; background: #000; border: 1px solid #334155; border-radius: 8px; margin-bottom: 16px; }\n  .wifi-networks { font-family: 'Inter', sans-serif; font-size: 11px; }\n  .wifi-net { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid #1e293b; }\n  .wifi-net strong { color: #e2e8f0; } .wifi-net span { color: #22c55e; }\n\n  #cellular-globe-container { width: 100%; height: 180px; margin: 0 auto 16px auto; position: relative; border-radius: 50%; overflow: hidden; background: #000; box-shadow: 0 0 30px rgba(234, 179, 8, 0.2); }\n  .cell-info { text-align: center; font-family: 'Inter', monospace; font-size: 12px; color: #eab308; background: rgba(0,0,0,0.5); padding: 10px; border-radius: 8px; border: 1px solid #334155; }\n\n  .terminal-view { font-family: monospace; font-size: 12px; color: #4ade80; flex: 1; overflow-y: hidden; display: flex; flex-direction: column; justify-content: flex-end; }\n  .term-line { margin: 2px 0; text-shadow: 0 0 5px rgba(74, 222, 128, 0.5); }\n  .term-cursor { display: inline-block; width: 8px; height: 12px; background: #4ade80; animation: blink 1s step-end infinite; }\n  @keyframes blink { 50% { opacity: 0; } }\n\n  .settings-list { display: flex; flex-direction: column; gap: 16px; }\n  .setting-item { display: flex; justify-content: space-between; align-items: center; font-family: 'Inter', sans-serif; font-size: 14px; color: #cbd5e1; }\n  .toggle { width: 40px; height: 20px; background: #334155; border-radius: 20px; position: relative; cursor: pointer; }\n  .toggle.on { background: #22c55e; }\n  .toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; background: #fff; border-radius: 50%; transition: 0.2s; }\n  .toggle.on::after { left: 22px; }\n\n  .chat-msg { margin-bottom: 8px; font-family: 'Inter', sans-serif; font-size: 11px; max-width: 85%; padding: 6px 10px; border-radius: 12px; clear: both; word-wrap: break-word;}\n  .chat-msg.rx { background: #1e293b; color: #cbd5e1; float: left; border-bottom-left-radius: 2px; }\n  .chat-msg.tx { background: #22c55e; color: #000; float: right; border-bottom-right-radius: 2px; }\n  \n  .cyber-console { flex: 1; background: #000; border: 1px solid #7f1d1d; border-radius: 8px; padding: 10px; font-family: monospace; font-size: 10px; color: #ef4444; overflow-y: hidden; display: flex; flex-direction: column; justify-content: flex-end; }\n  \n  .d-pad { display: grid; grid-template-columns: 35px 35px 35px; gap: 6px; justify-content: center; margin-top: 12px; }\n  .d-pad button { background: #1e293b; border: 1px solid #334155; color: #a855f7; border-radius: 6px; padding: 8px; font-weight: bold; cursor: pointer; transition: 0.1s; display: flex; justify-content: center; align-items: center;}\n  .d-pad button:active { background: #a855f7; color: #000; transform: scale(0.9); }\n\n  .rf-radar-container {\n    position: relative; width: 200px; height: 200px; margin: 0 auto 20px auto;\n    border-radius: 50%; border: 2px solid #f97316;\n    background: radial-gradient(circle, rgba(249,115,22,0.1) 0%, rgba(15,23,42,1) 70%); overflow: hidden;\n  }\n  .rf-sweep {\n    position: absolute; top: 50%; left: 50%; width: 100px; height: 100px;\n    background: conic-gradient(from 0deg, transparent 70%, rgba(249,115,22,0.8) 100%);\n    transform-origin: 0% 0%; animation: rfSpin 1.5s linear infinite;\n  }\n  .rf-dot { position: absolute; width: 8px; height: 8px; background: #ef4444; border-radius: 50%; box-shadow: 0 0 10px #ef4444; }\n  @keyframes rfSpin { 100% { transform: rotate(-360deg); } }\n\n  .music-player { text-align: center; }\n  .music-cover { width: 120px; height: 120px; background: #1e293b; border-radius: 12px; margin: 0 auto 16px auto; display:flex; justify-content:center; align-items:center; font-size:40px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); }\n  .music-title { font-size: 14px; color: #f8fafc; font-weight:bold; margin-bottom: 4px; }\n  .music-artist { font-family: 'Inter', sans-serif; font-size: 11px; color: #94a3b8; margin-bottom: 16px; }\n  .music-controls { display: flex; justify-content: center; gap: 16px; align-items: center; }\n  .music-btn { background: #334155; color: #fff; border:none; border-radius:50%; width:40px; height:40px; cursor:pointer; font-size:16px; display:flex; justify-content:center; align-items:center;}\n  #eq-canvas { width: 100%; height: 50px; margin-top: 20px; border-radius:8px; background: #000; }\n\n  .sd-explorer { font-family: 'Inter', sans-serif; font-size: 12px; }\n  .sd-item { display: flex; align-items: center; gap: 10px; padding: 10px 8px; border-bottom: 1px solid #1e293b; color: #cbd5e1; }\n  .sd-icon { font-size: 16px; }\n\n  .usb-console {\n    flex: 1; background: #000; border: 1px solid #0ea5e9; border-radius: 8px;\n    padding: 10px; font-family: monospace; font-size: 11px; color: #bae6fd;\n    overflow-y: auto; display: flex; flex-direction: column;\n  }\n  .usb-line { margin: 3px 0; }\n  .usb-success { color: #38bdf8; font-weight: bold; }\n\n  \/* Banners y Grid *\/\n  .spectre-features { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; margin-bottom: 50px; }\n  .spectre-card { background: #e0e5ec; border-radius: 30px; padding: 32px 24px; border: 1px solid rgba(255,255,255,0.2); box-shadow: 10px 10px 20px rgba(163, 177, 198, 0.5), -10px -10px 20px rgba(255, 255, 255, 0.8); transition: all 0.3s ease; opacity: 0; transform: translateY(20px); }\n  .spectre-card.is-visible { animation: fadeUp 0.6s ease forwards; }\n  .spectre-card:hover { box-shadow: inset 8px 8px 16px rgba(163, 177, 198, 0.6), inset -8px -8px 16px rgba(255, 255, 255, 0.9); transform: translateY(-5px); }\n  .spectre-icon { font-size: 32px; margin-bottom: 20px; display: inline-flex; width: 64px; height: 64px; align-items: center; justify-content: center; border-radius: 50%; background: #e0e5ec; box-shadow: 4px 4px 8px rgba(163, 177, 198, 0.5), -4px -4px 8px rgba(255, 255, 255, 0.8); }\n  .spectre-card-title { font-family: 'Orbitron', sans-serif; font-size: 18px; font-weight: 700; color: #2d3748; margin: 0 0 12px 0; }\n  .spectre-card-text { font-size: 14px; line-height: 1.5; margin: 0; }\n\n  .spectre-banner { background: #e0e5ec; border-radius: 40px; padding: 40px; text-align: center; box-shadow: inset 10px 10px 20px rgba(163, 177, 198, 0.5), inset -10px -10px 20px rgba(255, 255, 255, 0.8); border: 1px solid rgba(255,255,255,0.4); opacity: 0; transform: translateY(20px); }\n  .spectre-banner.is-visible { animation: fadeUp 0.8s ease forwards; }\n  .spectre-banner-title { font-family: 'Orbitron', sans-serif; font-size: 24px; font-weight: 800; color: #2d3748; margin: 0 0 16px 0; }\n\n  .spectre-prep { background: #e0e5ec; border-radius: 40px; padding: 50px 30px; margin-bottom: 50px; text-align: center; border: 1px solid rgba(255,255,255,0.4); box-shadow: 10px 10px 20px rgba(163, 177, 198, 0.5), -10px -10px 20px rgba(255, 255, 255, 0.8); opacity: 0; transform: translateY(20px); }\n  .spectre-prep.is-visible { animation: fadeUp 0.8s ease forwards; }\n  .spectre-prep-title { font-family: 'Orbitron', sans-serif; font-size: clamp(22px, 4vw, 32px); font-weight: 800; color: #eab308; margin: 0 0 20px 0; text-transform: uppercase; letter-spacing: 2px; }\n  .spectre-prep-text { font-size: 16px; line-height: 1.7; max-width: 800px; margin: 0 auto; color: #4a5568; }\n\n  .spectre-grid-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px; margin-top: 30px; }\n  .spectre-tag { background: #e0e5ec; padding: 12px 16px; border-radius: 12px; font-family: 'Orbitron', sans-serif; font-size: 13px; font-weight: 600; color: #2d3748; box-shadow: 4px 4px 8px rgba(163, 177, 198, 0.5), -4px -4px 8px rgba(255, 255, 255, 0.8); }\n\n  @keyframes fadeUp { to { opacity: 1; transform: translateY(0); } }\n\n  @media (max-width: 768px) {\n    .spectre-banner { padding: 30px 20px; border-radius: 24px; }\n    .spectre-prep { padding: 40px 20px; border-radius: 24px; }\n  }\n\u003c\/style\u003e\n\n\u003cdiv class=\"spectre-desc\"\u003e\n  \n  \u003c!-- HERO INTRO --\u003e\n  \u003cdiv class=\"spectre-hero\"\u003e\n    \u003cp class=\"spectre-subtitle\"\u003eThe Ultimate Tactical Device\u003c\/p\u003e\n    \u003ch1 class=\"spectre-title\"\u003eSGP Spectre\u003c\/h1\u003e\n    \u003cp class=\"spectre-intro\"\u003e\n      Engineered for extreme environments and advanced operations, the SGP Spectre is a true 007-style multi-tool designed to go with you to the end of the world. Whether you are deeply off-grid or in the heart of the city, this device provides unparalleled connectivity, tracking, and signal analysis in the palm of your hand.\n    \u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- PANTALLA TÁCTIL SIMULADA --\u003e\n  \u003cdiv class=\"spectre-device-wrapper\" id=\"spectre-screen\"\u003e\n    \u003cdiv class=\"spectre-device-casing\"\u003e\n      \u003cdiv class=\"spectre-device-bezel\"\u003e\n        \u003cdiv class=\"spectre-screen\"\u003e\n          \n          \u003c!-- Barra de estado --\u003e\n          \u003cdiv class=\"spectre-status-bar\"\u003e\n            \u003cspan class=\"time\"\u003e14:00\u003c\/span\u003e\n            \u003cdiv class=\"spectre-status-icons\"\u003e\n              \u003cspan style=\"color: #cbd5e1;\"\u003e⚲\u003c\/span\u003e\n              \u003cspan\u003e📶\u003c\/span\u003e\n              \u003cspan\u003e🔋98%\u003c\/span\u003e\n            \u003c\/div\u003e\n          \u003c\/div\u003e\n\n          \u003c!-- Contenedor Principal de Vistas --\u003e\n          \u003cdiv class=\"spectre-view-container\"\u003e\n            \n            \u003c!-- VISTA: HOME (Apps Grid) --\u003e\n            \u003cdiv id=\"view-home\" class=\"spectre-view active\"\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('gnss')\"\u003e\n                \u003cdiv class=\"app-icon has-badge\"\u003e🛰️\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eGNSS\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('lora')\"\u003e\n                \u003cdiv class=\"app-icon\"\u003e📡\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eLoRa\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('wifi')\"\u003e\n                \u003cdiv class=\"app-icon\"\u003e🛜\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eWi-Fi CSI\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('cellular')\"\u003e\n                \u003cdiv class=\"app-icon\"\u003e🌍\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eCellular\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('terminal')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #4ade80;\"\u003e\u0026gt;_\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eTerminal\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('chat')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #38bdf8;\"\u003e💬\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eP2P Chat\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('cyber')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #ef4444;\"\u003e💀\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eCyberSec\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('game')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #a855f7;\"\u003e👾\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eSnake\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('settings')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #cbd5e1;\"\u003e⚙️\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eSettings\u003c\/span\u003e\n              \u003c\/div\u003e\n              \n              \u003c!-- NUEVAS APPS --\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('rfradar')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #f97316;\"\u003e🎯\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eRF Radar\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('music')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #fb7185;\"\u003e🎵\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eMedia\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('sdcard')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #fbbf24;\"\u003e💾\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eSD Card\u003c\/span\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"spectre-app\" onclick=\"openApp('usbotg')\"\u003e\n                \u003cdiv class=\"app-icon\" style=\"color: #0ea5e9;\"\u003e🔌\u003c\/div\u003e\n                \u003cspan class=\"app-name\"\u003eUSB OTG\u003c\/span\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: GNSS --\u003e\n            \u003cdiv id=\"view-gnss\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\"\u003eGNSS TRACKER\u003c\/div\u003e\n              \u003cdiv class=\"radar-container\" id=\"radar-box\"\u003e\n                \u003cdiv class=\"radar-grid\"\u003e\u003c\/div\u003e\n                \u003cdiv class=\"radar-sweep\"\u003e\u003c\/div\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"gnss-data\" id=\"gnss-coords\"\u003e\n                STATUS: SEARCHING...\u003cbr\u003e\n                LAT: --.----\u003cbr\u003e\n                LON: --.----\u003cbr\u003e\n                SATS: 0\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: LoRa --\u003e\n            \u003cdiv id=\"view-lora\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\"\u003eLORA COMMS\u003c\/div\u003e\n              \u003cdiv class=\"lora-console\" id=\"lora-log\"\u003e\n                \u003cdiv class=\"lora-line\"\u003eInit LoRa Module... OK\u003c\/div\u003e\n                \u003cdiv class=\"lora-line\"\u003eBand: 868 MHz \/ 915 MHz\u003c\/div\u003e\n                \u003cdiv class=\"lora-line\"\u003eListening for beacons...\u003c\/div\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: Wi-Fi CSI --\u003e\n            \u003cdiv id=\"view-wifi\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\"\u003eWI-FI CSI ANALYSIS\u003c\/div\u003e\n              \u003ccanvas id=\"wifi-canvas\"\u003e\u003c\/canvas\u003e\n              \u003cdiv class=\"wifi-networks\"\u003e\n                \u003cdiv class=\"wifi-net\"\u003e\n\u003cstrong\u003eSGP_SECURE_5G\u003c\/strong\u003e \u003cspan\u003e-42 dBm\u003c\/span\u003e\n\u003c\/div\u003e\n                \u003cdiv class=\"wifi-net\"\u003e\n\u003cstrong\u003eHidden_Network\u003c\/strong\u003e \u003cspan\u003e-68 dBm\u003c\/span\u003e\n\u003c\/div\u003e\n                \u003cdiv class=\"wifi-net\"\u003e\n\u003cstrong\u003eGUEST_WIFI\u003c\/strong\u003e \u003cspan\u003e-85 dBm\u003c\/span\u003e\n\u003c\/div\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: Cellular --\u003e\n            \u003cdiv id=\"view-cellular\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\"\u003eGLOBAL CELLULAR\u003c\/div\u003e\n              \u003cdiv id=\"cellular-globe-container\"\u003e\u003c\/div\u003e\n              \u003cdiv class=\"cell-info\"\u003e\n                \u003cdiv\u003eNETWORK: \u003cspan style=\"color:#fff;\"\u003eSGP TACTICAL\u003c\/span\u003e\n\u003c\/div\u003e\n                \u003cdiv\u003eBAND: \u003cspan style=\"color:#fff;\"\u003eLTE-B7 (2600MHz)\u003c\/span\u003e\n\u003c\/div\u003e\n                \u003cdiv\u003eSECURE TUNNEL: \u003cspan style=\"color:#22c55e;\"\u003eESTABLISHED\u003c\/span\u003e\n\u003c\/div\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: Terminal --\u003e\n            \u003cdiv id=\"view-terminal\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\"\u003eROOT TERMINAL\u003c\/div\u003e\n              \u003cdiv class=\"terminal-view\" id=\"terminal-log\"\u003e\n                \u003cdiv class=\"term-line\"\u003e\u003cspan class=\"term-cursor\"\u003e\u003c\/span\u003e\u003c\/div\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: Settings --\u003e\n            \u003cdiv id=\"view-settings\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\"\u003eSYSTEM CONFIG\u003c\/div\u003e\n              \u003cdiv class=\"settings-list\"\u003e\n                \u003cdiv class=\"setting-item\"\u003e\n                  \u003cspan\u003eBluetooth LE\u003c\/span\u003e\n                  \u003cdiv class=\"toggle on\" onclick=\"this.classList.toggle('on')\"\u003e\u003c\/div\u003e\n                \u003c\/div\u003e\n                \u003cdiv class=\"setting-item\"\u003e\n                  \u003cspan\u003eStealth Mode\u003c\/span\u003e\n                  \u003cdiv class=\"toggle\" onclick=\"this.classList.toggle('on')\"\u003e\u003c\/div\u003e\n                \u003c\/div\u003e\n                \u003cdiv class=\"setting-item\"\u003e\n                  \u003cspan\u003eBuzzer Audio\u003c\/span\u003e\n                  \u003cdiv class=\"toggle on\" onclick=\"this.classList.toggle('on')\"\u003e\u003c\/div\u003e\n                \u003c\/div\u003e\n                \u003cdiv class=\"setting-item\" style=\"margin-top: 20px; justify-content:center;\"\u003e\n                  \u003cbutton style=\"background:#eab308; border:none; padding:8px 16px; border-radius:8px; font-family:'Orbitron'; font-weight:bold; cursor:pointer;\"\u003eUPDATE FIRMWARE\u003c\/button\u003e\n                \u003c\/div\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: LoRa Chat --\u003e\n            \u003cdiv id=\"view-chat\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\" style=\"color: #38bdf8; border-color: rgba(56, 189, 248, 0.3);\"\u003eENCRYPTED P2P CHAT\u003c\/div\u003e\n              \u003cdiv id=\"chat-messages\" style=\"flex:1; overflow-y:auto; margin-bottom:10px; scrollbar-width: none;\"\u003e\n                \u003cdiv class=\"chat-msg rx\"\u003eConnection established. AES-256 enabled.\u003c\/div\u003e\n              \u003c\/div\u003e\n              \u003cdiv style=\"display:flex; gap:6px;\"\u003e\n                \u003cinput type=\"text\" id=\"chat-input\" style=\"flex:1; background:#1e293b; border:1px solid #334155; color:#fff; border-radius:6px; padding:6px 10px; font-size:12px; outline:none;\" placeholder=\"Type \/msg...\" onkeypress=\"if(event.key === 'Enter') sendChat()\"\u003e\n                \u003cbutton onclick=\"sendChat()\" style=\"background:#38bdf8; color:#000; border:none; border-radius:6px; padding:0 12px; font-weight:bold; cursor:pointer;\"\u003eTX\u003c\/button\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: CyberSec --\u003e\n            \u003cdiv id=\"view-cyber\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\" style=\"color: #ef4444; border-color: rgba(239, 68, 68, 0.3);\"\u003eTACTICAL SCANNER\u003c\/div\u003e\n              \u003cdiv class=\"cyber-console\" id=\"cyber-log\"\u003e\n                 \u003cdiv\u003eAwaiting command...\u003c\/div\u003e\n              \u003c\/div\u003e\n              \u003cdiv style=\"margin-top: 12px; display:flex; gap:8px;\"\u003e\n                \u003cbutton onclick=\"runCyberAction('scan')\" style=\"flex:1; background:#1e293b; color:#ef4444; border:1px solid #ef4444; padding:8px; border-radius:6px; font-family:'Orbitron'; font-size:10px; cursor:pointer;\"\u003eNET SCAN\u003c\/button\u003e\n                \u003cbutton onclick=\"runCyberAction('deauth')\" style=\"flex:1; background:#ef4444; color:#fff; border:none; padding:8px; border-radius:6px; font-family:'Orbitron'; font-weight:bold; font-size:10px; cursor:pointer;\"\u003eINJECT\u003c\/button\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: Game (Snake) --\u003e\n            \u003cdiv id=\"view-game\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\" style=\"color: #a855f7; border-color: rgba(168, 85, 247, 0.3);\"\u003eSNAKE.EXE\u003c\/div\u003e\n              \u003ccanvas id=\"snake-canvas\" width=\"220\" height=\"180\" style=\"background:#0f172a; border:2px solid #334155; border-radius:8px; margin:0 auto; display:block; box-shadow: inset 0 0 10px #000;\"\u003e\u003c\/canvas\u003e\n              \n              \u003cdiv class=\"d-pad\"\u003e\n                \u003cdiv\u003e\u003c\/div\u003e\n                \u003cbutton onclick=\"changeSnakeDir(0,-1)\"\u003e\u003csvg width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\u003e\u003cpath d=\"m18 15-6-6-6 6\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/button\u003e\n                \u003cdiv\u003e\u003c\/div\u003e\n                \u003cbutton onclick=\"changeSnakeDir(-1,0)\"\u003e\u003csvg width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\u003e\u003cpath d=\"m15 18-6-6 6-6\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/button\u003e\n                \u003cbutton onclick=\"initSnakeGame()\" style=\"background:#334155; color:#cbd5e1; font-size:10px;\"\u003eRST\u003c\/button\u003e\n                \u003cbutton onclick=\"changeSnakeDir(1,0)\"\u003e\u003csvg width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\u003e\u003cpath d=\"m9 18 6-6-6-6\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/button\u003e\n                \u003cdiv\u003e\u003c\/div\u003e\n                \u003cbutton onclick=\"changeSnakeDir(0,1)\"\u003e\u003csvg width=\"16\" height=\"16\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\u003e\u003cpath d=\"m6 9 6 6 6-6\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/button\u003e\n                \u003cdiv\u003e\u003c\/div\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: RF Radar --\u003e\n            \u003cdiv id=\"view-rfradar\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\" style=\"color:#f97316; border-color:rgba(249,115,22,0.3);\"\u003eRF SPECTRUM RADAR\u003c\/div\u003e\n              \u003cdiv class=\"rf-radar-container\" id=\"rf-radar-box\"\u003e\n                \u003cdiv class=\"radar-grid\" style=\"background-image: linear-gradient(#f97316 1px, transparent 1px), linear-gradient(90deg, #f97316 1px, transparent 1px);\"\u003e\u003c\/div\u003e\n                \u003cdiv class=\"rf-sweep\"\u003e\u003c\/div\u003e\n              \u003c\/div\u003e\n              \u003cdiv class=\"gnss-data\" style=\"color:#f97316; text-align:center;\"\u003e\n                FREQ: 2.4GHz \/ 5.8GHz\u003cbr\u003e\n                SCANNING FOR ANOMALIES...\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: Music Player --\u003e\n            \u003cdiv id=\"view-music\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\" style=\"color:#fb7185; border-color:rgba(251,113,133,0.3);\"\u003eMEDIA PLAYER\u003c\/div\u003e\n              \u003cdiv class=\"music-player\"\u003e\n                \u003cdiv class=\"music-cover\"\u003e🎧\u003c\/div\u003e\n                \u003cdiv class=\"music-title\"\u003eTactical_Vibes.mp3\u003c\/div\u003e\n                \u003cdiv class=\"music-artist\"\u003eSGP Internal Storage\u003c\/div\u003e\n                \n                \u003cdiv class=\"music-controls\"\u003e\n                  \u003cbutton class=\"music-btn\" onclick=\"toggleMusic(false)\"\u003e⏮\u003c\/button\u003e\n                  \u003cbutton class=\"music-btn\" id=\"music-play-btn\" onclick=\"toggleMusic(true)\" style=\"width:50px; height:50px; font-size:20px;\"\u003e▶\u003c\/button\u003e\n                  \u003cbutton class=\"music-btn\" onclick=\"toggleMusic(false)\"\u003e⏭\u003c\/button\u003e\n                \u003c\/div\u003e\n                \n                \u003ccanvas id=\"eq-canvas\"\u003e\u003c\/canvas\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: SD Card --\u003e\n            \u003cdiv id=\"view-sdcard\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\" style=\"color:#fbbf24; border-color:rgba(251,191,36,0.3);\"\u003eSD CARD BROWSER\u003c\/div\u003e\n              \u003cdiv class=\"sd-explorer\" id=\"sd-file-list\"\u003e\n                \u003c!-- Se inyecta por JS --\u003e\n              \u003c\/div\u003e\n              \u003cdiv style=\"margin-top:auto; font-size:10px; color:#94a3b8; text-align:center;\"\u003eCAPACITY: 58GB \/ 64GB\u003c\/div\u003e\n            \u003c\/div\u003e\n\n            \u003c!-- VISTA: USB OTG --\u003e\n            \u003cdiv id=\"view-usbotg\" class=\"spectre-view\"\u003e\n              \u003cdiv class=\"app-header\" style=\"color:#0ea5e9; border-color:rgba(14,165,233,0.3);\"\u003eUSB HOST (OTG)\u003c\/div\u003e\n              \u003cdiv class=\"usb-console\" id=\"usb-log\"\u003e\n                \u003c!-- Se inyecta por JS --\u003e\n              \u003c\/div\u003e\n            \u003c\/div\u003e\n\n          \u003c\/div\u003e \u003c!-- End View Container --\u003e\n\n          \u003c!-- Home Button Bar (siempre visible) --\u003e\n          \u003cdiv class=\"spectre-home-bar\" onclick=\"goHome()\"\u003e\n            \u003cdiv class=\"spectre-home-indicator\"\u003e\u003c\/div\u003e\n          \u003c\/div\u003e\n\n          \u003c!-- Efecto cristal --\u003e\n          \u003cdiv class=\"spectre-screen-glare\"\u003e\u003c\/div\u003e\n\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- FEATURES GRID --\u003e\n  \u003cdiv class=\"spectre-features\" id=\"spectre-features\"\u003e\n    \u003cdiv class=\"spectre-card\"\u003e\n      \u003cdiv class=\"spectre-icon\"\u003e🛰️\u003c\/div\u003e\n      \u003ch3 class=\"spectre-card-title\"\u003eHelical GNSS Tracking\u003c\/h3\u003e\n      \u003cp class=\"spectre-card-text\"\u003eEquipped with a high-precision helical antenna. Track your real-time location, detect overhead satellites, and identify their unique registration IDs instantly.\u003c\/p\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"spectre-card\"\u003e\n      \u003cdiv class=\"spectre-icon\"\u003e📡\u003c\/div\u003e\n      \u003ch3 class=\"spectre-card-title\"\u003eLong-Range Dual-Band LoRa\u003c\/h3\u003e\n      \u003cp class=\"spectre-card-text\"\u003eStay connected off the grid. Communicate with other devices miles away without needing cellular service or internet access.\u003c\/p\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"spectre-card\"\u003e\n      \u003cdiv class=\"spectre-icon\"\u003e📶\u003c\/div\u003e\n      \u003ch3 class=\"spectre-card-title\"\u003eWi-Fi CSI \u0026amp; Dedicated Antenna\u003c\/h3\u003e\n      \u003cp class=\"spectre-card-text\"\u003eAdvanced Channel State Information capabilities. Analyze Wi-Fi signals, map environments, and detect movement using dedicated hardware.\u003c\/p\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"spectre-card\"\u003e\n      \u003cdiv class=\"spectre-icon\"\u003e👆\u003c\/div\u003e\n      \u003ch3 class=\"spectre-card-title\"\u003eProgrammable Touch Screen\u003c\/h3\u003e\n      \u003cp class=\"spectre-card-text\"\u003eTotal control at your fingertips. An intuitive, highly responsive, and fully programmable display tailored for rapid tactical execution.\u003c\/p\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"spectre-card\"\u003e\n      \u003cdiv class=\"spectre-icon\"\u003e🌍\u003c\/div\u003e\n      \u003ch3 class=\"spectre-card-title\"\u003eSIM Card Slot \u0026amp; Connectivity\u003c\/h3\u003e\n      \u003cp class=\"spectre-card-text\"\u003eInsert a SIM card for independent internet access. Features integrated Bluetooth, Wi-Fi, and a versatile USB OTG port for endless expansions.\u003c\/p\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"spectre-card\"\u003e\n      \u003cdiv class=\"spectre-icon\"\u003e🔋\u003c\/div\u003e\n      \u003ch3 class=\"spectre-card-title\"\u003eEndurance \u0026amp; Power\u003c\/h3\u003e\n      \u003cp class=\"spectre-card-text\"\u003eFitted with a high-capacity battery built to outlast your missions, plus powerful built-in speakers for clear audio alerts and communications.\u003c\/p\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- PREPAREDNESS \/ ADVENTURER SECTION --\u003e\n  \u003cdiv class=\"spectre-prep\" id=\"spectre-prep\"\u003e\n    \u003cdiv class=\"spectre-icon\" style=\"margin-bottom: 20px;\"\u003e🏕️\u003c\/div\u003e\n    \u003ch2 class=\"spectre-prep-title\"\u003eBuilt for Adventurers \u0026amp; Enthusiasts\u003c\/h2\u003e\n    \u003cp class=\"spectre-prep-text\"\u003e\n      \u003cstrong\u003ePrepare for the real end of the world.\u003c\/strong\u003e Achieve true autonomy and off-grid readiness with our fully \u003cstrong\u003eprogrammable, open-source\u003c\/strong\u003e device. Whether you are prepping for worst-case scenarios or venturing into the unknown, the Spectre gives you the tools to survive and thrive without relying on conventional infrastructure.\n    \u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- BOTTOM BANNER --\u003e\n  \u003cdiv class=\"spectre-banner\" id=\"spectre-banner\"\u003e\n    \u003ch3 class=\"spectre-banner-title\"\u003eA 007 Gadget In Your Pocket\u003c\/h3\u003e\n    \u003cp style=\"margin:0; font-size: 15px; max-width: 600px; margin: 0 auto;\"\u003e\n      \u003cstrong\u003eThe ultimate tool for professionals.\u003c\/strong\u003e The SGP Spectre isn't just a gadget; it's a completely self-sufficient ecosystem. Scan, track, communicate, and analyze with an arsenal of built-in hardware tailored for advanced operations.\n    \u003c\/p\u003e\n    \u003cdiv class=\"spectre-grid-list\"\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eHelical Antenna\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eGPS \/ GNSS\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eDual-Band LoRa\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eWi-Fi CSI\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eIMU Sensor\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eTouch Screen\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eBuilt-in Speakers\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eUSB OTG\u003c\/div\u003e\n      \u003cdiv class=\"spectre-tag\"\u003eBluetooth\u003c\/div\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n  \/\/ --- VARIABLES GLOBALES DEL SIMULADOR TÁCTICO ---\n  let termInterval, gnssInterval, chatInterval, cyberInterval, snakeInterval, rfInterval, usbInterval, sdInterval;\n  let wifiAnimFrame, musicAnimFrame, musicTimeout;\n  let isMusicPlaying = false;\n  let phoneGlobeInitialized = false;\n\n  \/\/ IMPORTANTE: Función maestra para matar todos los procesos en 2º plano y evitar bloqueos.\n  function clearAllApps() {\n    if(termInterval) clearInterval(termInterval);\n    if(gnssInterval) clearInterval(gnssInterval);\n    if(chatInterval) clearInterval(chatInterval);\n    if(cyberInterval) clearInterval(cyberInterval);\n    if(snakeInterval) clearInterval(snakeInterval);\n    if(rfInterval) clearInterval(rfInterval);\n    if(usbInterval) clearInterval(usbInterval);\n    if(sdInterval) clearInterval(sdInterval);\n    \n    if(wifiAnimFrame) cancelAnimationFrame(wifiAnimFrame);\n    if(musicAnimFrame) cancelAnimationFrame(musicAnimFrame);\n    if(musicTimeout) clearTimeout(musicTimeout);\n  }\n\n  \/\/ --- NAVEGACIÓN DEL SISTEMA OPERATIVO SIMULADO ---\n  function openApp(appId) {\n    \/\/ 1. Matar procesos anteriores para no saturar CPU\n    clearAllApps();\n    \n    \/\/ 2. Ocultar todas las vistas\n    document.querySelectorAll('.spectre-view').forEach(view =\u003e {\n      view.classList.remove('active');\n    });\n    \n    \/\/ 3. Mostrar la solicitada y ejecutar lógica\n    const target = document.getElementById('view-' + appId);\n    if(target) {\n      target.classList.add('active');\n      \n      if(appId === 'terminal') startTerminal();\n      if(appId === 'wifi') initWifiCanvas();\n      if(appId === 'cellular') initCellularGlobe();\n      if(appId === 'gnss') updateGNSS();\n      if(appId === 'chat') initChat();\n      if(appId === 'game') initSnakeGame();\n      if(appId === 'cyber') document.getElementById('cyber-log').innerHTML = '\u003cdiv\u003eAwaiting command...\u003c\/div\u003e';\n      \n      if(appId === 'rfradar') initRFRadar();\n      if(appId === 'music') initMusicUI();\n      if(appId === 'sdcard') initSDCard();\n      if(appId === 'usbotg') initUSBOTG();\n    }\n  }\n\n  function goHome() {\n    \/\/ Limpiar TODO para evitar que el navegador se bloquee\n    clearAllApps();\n    \n    document.querySelectorAll('.spectre-view').forEach(view =\u003e {\n      view.classList.remove('active');\n    });\n    document.getElementById('view-home').classList.add('active');\n  }\n\n  \/\/ --- LÓGICA DE APLICACIONES INDIVIDUALES ---\n\n  \/\/ 1. GNSS Radar\n  function updateGNSS() {\n    const coordsBox = document.getElementById('gnss-coords');\n    const radarBox = document.getElementById('radar-box');\n    \n    radarBox.querySelectorAll('.sat-dot').forEach(e =\u003e e.remove());\n\n    let lat = 40.0000;\n    let lon = -3.0000;\n    let sats = 0;\n\n    gnssInterval = setInterval(() =\u003e {\n      if(sats \u003c 12 \u0026\u0026 Math.random() \u003e 0.5) {\n        sats++;\n        lat += (Math.random() - 0.5) * 0.001;\n        lon += (Math.random() - 0.5) * 0.001;\n        \n        const dot = document.createElement('div');\n        dot.className = 'sat-dot';\n        dot.style.left = (20 + Math.random() * 150) + 'px';\n        dot.style.top = (20 + Math.random() * 150) + 'px';\n        dot.style.opacity = '1';\n        radarBox.appendChild(dot);\n      }\n      \n      coordsBox.innerHTML = `\n        STATUS: ${sats \u003e 3 ? '\u003cspan style=\"color:#fff;\"\u003e3D FIX OK\u003c\/span\u003e' : 'ACQUIRING...'} \u003cbr\u003e\n        LAT: ${lat.toFixed(5)} N \u003cbr\u003e\n        LON: ${Math.abs(lon).toFixed(5)} W \u003cbr\u003e\n        SATS: ${sats}\n      `;\n    }, 1000);\n  }\n\n  \/\/ 2. LoRa Logs (Global Interval solo si está activo)\n  setInterval(() =\u003e {\n    const log = document.getElementById('lora-log');\n    if(!log || !document.getElementById('view-lora').classList.contains('active')) return;\n    if(log.children.length \u003e 8) log.removeChild(log.firstChild);\n    \n    const line = document.createElement('div');\n    line.className = 'lora-line ' + (Math.random() \u003e 0.5 ? 'tx' : 'rx');\n    if(line.classList.contains('tx')) {\n      line.innerText = `[${new Date().getSeconds()}] TX -\u003e PING NODE_${Math.floor(Math.random()*100)}`;\n    } else {\n      line.innerText = `[${new Date().getSeconds()}] RX \u003c- ACK (-${90 + Math.floor(Math.random()*30)} dBm)`;\n    }\n    log.appendChild(line);\n  }, 2500);\n\n  \/\/ 3. Wi-Fi CSI Canvas\n  function initWifiCanvas() {\n    const canvas = document.getElementById('wifi-canvas');\n    if(!canvas) return;\n    const ctx = canvas.getContext('2d');\n    canvas.width = canvas.parentElement.clientWidth - 32;\n    canvas.height = 150;\n    \n    let time = 0;\n    function drawWave() {\n      if(!document.getElementById('view-wifi').classList.contains('active')) return;\n      \n      ctx.fillStyle = '#000';\n      ctx.fillRect(0, 0, canvas.width, canvas.height);\n      \n      ctx.beginPath();\n      ctx.lineWidth = 2;\n      ctx.strokeStyle = '#22c55e';\n      \n      for(let x = 0; x \u003c canvas.width; x++) {\n        const y = Math.sin(x * 0.05 + time) * 30 + \n                  Math.sin(x * 0.1 + time*1.5) * 15 + \n                  (Math.random() * 10 - 5) + \n                  canvas.height \/ 2;\n        \n        if(x === 0) ctx.moveTo(x, y);\n        else ctx.lineTo(x, y);\n      }\n      ctx.stroke();\n      \n      time += 0.1;\n      wifiAnimFrame = requestAnimationFrame(drawWave);\n    }\n    drawWave();\n  }\n\n  \/\/ 4. Cellular Globe\n  function initCellularGlobe() {\n    if(phoneGlobeInitialized) return;\n    const container = document.getElementById('cellular-globe-container');\n    if(!container || typeof THREE === 'undefined') return;\n    phoneGlobeInitialized = true;\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 = 2.2;\n\n    const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });\n    renderer.setSize(container.clientWidth, container.clientHeight);\n    container.appendChild(renderer.domElement);\n\n    const globeGroup = new THREE.Group();\n    scene.add(globeGroup);\n\n    fetch('https:\/\/unpkg.com\/world-atlas@2.0.2\/countries-110m.json')\n      .then(res =\u003e res.json())\n      .then(world =\u003e {\n          const w = 1024, h = 512;\n          const canvas = document.createElement('canvas');\n          canvas.width = w; canvas.height = h;\n          const ctx = canvas.getContext('2d');\n          \n          const countries = topojson.feature(world, world.objects.countries);\n          const projection = d3.geoEquirectangular().translate([w\/2, h\/2]).scale(w \/ (2 * Math.PI));\n          const path = d3.geoPath(projection, ctx);\n          \n          ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, w, h);\n          ctx.fillStyle = '#eab308'; ctx.strokeStyle = '#000'; ctx.lineWidth = 1;\n          ctx.beginPath(); path(countries); ctx.fill(); ctx.stroke();\n\n          ctx.fillStyle = '#fff';\n          for(let i=0; i\u003c30; i++) {\n            ctx.beginPath(); ctx.arc(Math.random() * w, Math.random() * h, 3, 0, Math.PI*2); ctx.fill();\n          }\n          \n          const texture = new THREE.CanvasTexture(canvas);\n          const sphereGeo = new THREE.SphereGeometry(1, 32, 32);\n          const sphereMat = new THREE.MeshBasicMaterial({ map: texture });\n          const globe = new THREE.Mesh(sphereGeo, sphereMat);\n          globeGroup.add(globe);\n          \n          const ringGeo = new THREE.RingGeometry(1.2, 1.22, 64);\n          const ringMat = new THREE.MeshBasicMaterial({ color: 0x22c55e, side: THREE.DoubleSide, transparent:true, opacity:0.5 });\n          const ring = new THREE.Mesh(ringGeo, ringMat);\n          ring.rotation.x = Math.PI \/ 2;\n          globeGroup.add(ring);\n      });\n\n    const animate = () =\u003e {\n      requestAnimationFrame(animate);\n      if(document.getElementById('view-cellular').classList.contains('active')) {\n        globeGroup.rotation.y += 0.005;\n        globeGroup.rotation.x = 0.2; \n        renderer.render(scene, camera);\n      }\n    };\n    animate();\n  }\n\n  \/\/ 5. Terminal Hack Simulator\n  const lines = [\n    \"root@spectre:~# init --tactical\",\n    \"[ OK ] Booting secure kernel...\",\n    \"[ OK ] Mounting encrypted volume...\",\n    \"[INFO] Scanning local networks...\",\n    \"Found 3 BSSIDs in range.\",\n    \"[WARN] Anomalous RF detected on 433MHz\",\n    \"root@spectre:~# run_exploit -t 192.168.1.1\",\n    \"Injecting payloads [||||||||||] 100%\",\n    \"Access GRANTED.\",\n    \"Bypassing firewall rules...\",\n    \"Establishing secure tunnel...\",\n    \"root@spectre:~# _\"\n  ];\n\n  function startTerminal() {\n    const term = document.getElementById('terminal-log');\n    term.innerHTML = '\u003cdiv class=\"term-line\"\u003e\u003cspan class=\"term-cursor\"\u003e\u003c\/span\u003e\u003c\/div\u003e';\n    let termLineIdx = 0;\n\n    termInterval = setInterval(() =\u003e {\n      if(termLineIdx \u003c lines.length) {\n        const cursor = term.querySelector('.term-cursor');\n        if(cursor) cursor.remove();\n\n        const newLine = document.createElement('div');\n        newLine.className = 'term-line';\n        newLine.innerText = lines[termLineIdx];\n        term.appendChild(newLine);\n        \n        const newCursor = document.createElement('span');\n        newCursor.className = 'term-cursor';\n        term.appendChild(newCursor);\n\n        termLineIdx++;\n      } else {\n        clearInterval(termInterval);\n      }\n    }, 800);\n  }\n\n  \/\/ 6. LoRa P2P Chat\n  function initChat() {\n    const box = document.getElementById('chat-messages');\n    const fakeReplies = [\n      \"Node_Beta: Sector 4 is clear.\",\n      \"Ghost_01: Acknowledged.\",\n      \"Base: Weather incoming, secure perimeter.\",\n      \"Node_Beta: RF interference detected on 433MHz.\",\n      \"Ghost_01: Moving to extraction point.\"\n    ];\n\n    chatInterval = setInterval(() =\u003e {\n      if(Math.random() \u003e 0.6) {\n        const msg = document.createElement('div');\n        msg.className = 'chat-msg rx';\n        msg.innerText = fakeReplies[Math.floor(Math.random() * fakeReplies.length)];\n        box.appendChild(msg);\n        box.scrollTop = box.scrollHeight;\n      }\n    }, 4000);\n  }\n\n  function sendChat() {\n    const input = document.getElementById('chat-input');\n    const box = document.getElementById('chat-messages');\n    if(input.value.trim() === '') return;\n    \n    const msg = document.createElement('div');\n    msg.className = 'chat-msg tx';\n    msg.innerText = input.value;\n    box.appendChild(msg);\n    box.scrollTop = box.scrollHeight;\n    input.value = '';\n    \n    setTimeout(() =\u003e {\n       const reply = document.createElement('div');\n       reply.className = 'chat-msg rx';\n       reply.innerText = \"Ghost_01: Copy that.\";\n       box.appendChild(reply);\n       box.scrollTop = box.scrollHeight;\n    }, 1500);\n  }\n\n  \/\/ 7. CyberSec Scanner\n  function runCyberAction(type) {\n    clearInterval(cyberInterval);\n    const log = document.getElementById('cyber-log');\n    log.innerHTML = '';\n    \n    let count = 0;\n    if(type === 'scan') {\n      cyberInterval = setInterval(() =\u003e {\n        const line = document.createElement('div');\n        const mac = \"00:\" + Math.floor(Math.random()*99) + \":XX:XX:XX:XX\";\n        line.innerText = `[+] Target found: ${mac} - RSSI: -${Math.floor(Math.random()*40 + 50)}dBm`;\n        log.appendChild(line);\n        if(log.children.length \u003e 8) log.removeChild(log.firstChild);\n        count++;\n        if(count \u003e 15) { clearInterval(cyberInterval); log.innerHTML += '\u003cdiv style=\"color:#22c55e\"\u003eScan Complete.\u003c\/div\u003e'; }\n      }, 300);\n    } else {\n      cyberInterval = setInterval(() =\u003e {\n        const line = document.createElement('div');\n        line.innerHTML = `[TX] Injecting Beacon Packets -\u003e \u003cspan style=\"color:#fff\"\u003eTarget_AP\u003c\/span\u003e [CH ${Math.floor(Math.random()*11 + 1)}]`;\n        log.appendChild(line);\n        if(log.children.length \u003e 8) log.removeChild(log.firstChild);\n      }, 100);\n    }\n  }\n\n  \/\/ 8. Snake Game\n  let snake = [{x: 10, y: 10}];\n  let dir = {x: 1, y: 0};\n  let food = {x: 5, y: 5};\n  \n  function initSnakeGame() {\n    const canvas = document.getElementById('snake-canvas');\n    if(!canvas) return;\n    const ctx = canvas.getContext('2d');\n    \n    snake = [{x: 10, y: 10}];\n    dir = {x: 1, y: 0};\n    placeFood();\n    \n    snakeInterval = setInterval(() =\u003e {\n      let head = {x: snake[0].x + dir.x, y: snake[0].y + dir.y};\n      \n      if(head.x \u003e= 22) head.x = 0; if(head.x \u003c 0) head.x = 21;\n      if(head.y \u003e= 18) head.y = 0; if(head.y \u003c 0) head.y = 17;\n      \n      snake.unshift(head);\n      \n      if(head.x === food.x \u0026\u0026 head.y === food.y) {\n        placeFood(); \n      } else {\n        snake.pop(); \n      }\n      \n      ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, canvas.width, canvas.height);\n      ctx.fillStyle = '#ef4444'; ctx.fillRect(food.x * 10, food.y * 10, 9, 9);\n      ctx.fillStyle = '#a855f7'; snake.forEach(s =\u003e ctx.fillRect(s.x * 10, s.y * 10, 9, 9));\n      \n    }, 120);\n  }\n\n  function placeFood() { food = {x: Math.floor(Math.random()*21), y: Math.floor(Math.random()*17)}; }\n  function changeSnakeDir(x, y) { \n    if(snake.length \u003e 1 \u0026\u0026 dir.x === -x \u0026\u0026 dir.y === -y) return;\n    dir = {x, y}; \n  }\n\n  \/\/ 9. RF Radar\n  function initRFRadar() {\n    const radarBox = document.getElementById('rf-radar-box');\n    radarBox.querySelectorAll('.rf-dot').forEach(e =\u003e e.remove());\n\n    rfInterval = setInterval(() =\u003e {\n      if(Math.random() \u003e 0.4) {\n        const dot = document.createElement('div');\n        dot.className = 'rf-dot';\n        dot.style.left = (20 + Math.random() * 150) + 'px';\n        dot.style.top = (20 + Math.random() * 150) + 'px';\n        radarBox.appendChild(dot);\n        setTimeout(() =\u003e { if(dot.parentElement) dot.remove(); }, 1500);\n      }\n    }, 800);\n  }\n\n  \/\/ 10. Music Player \/ EQ\n  function initMusicUI() {\n    drawEQ();\n  }\n\n  function toggleMusic(playClick) {\n    const btn = document.getElementById('music-play-btn');\n    if(playClick) {\n      isMusicPlaying = !isMusicPlaying;\n    }\n    btn.innerText = isMusicPlaying ? \"⏸\" : \"▶\";\n  }\n\n  function drawEQ() {\n    const canvas = document.getElementById('eq-canvas');\n    if(!canvas) return;\n    const ctx = canvas.getContext('2d');\n    canvas.width = canvas.parentElement.clientWidth;\n    canvas.height = 50;\n\n    function render() {\n      if(!document.getElementById('view-music').classList.contains('active')) return;\n\n      ctx.fillStyle = '#000';\n      ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n      const numBars = Math.floor(canvas.width \/ 8);\n      ctx.fillStyle = '#fb7185';\n\n      for(let i=0; i\u003cnumBars; i++) {\n        let h = 2; \/\/ Reposo\n        if(isMusicPlaying) {\n          h = Math.random() * 40 + 5; \/\/ Bailando\n        }\n        ctx.fillRect(i * 8 + 2, canvas.height - h, 4, h);\n      }\n\n      musicTimeout = setTimeout(() =\u003e { musicAnimFrame = requestAnimationFrame(render); }, 60);\n    }\n    render();\n  }\n\n  \/\/ 11. SD Card Reader\n  function initSDCard() {\n    const list = document.getElementById('sd-file-list');\n    list.innerHTML = '';\n    \n    const files = [\n      { icon: '📁', name: 'logs\/' },\n      { icon: '📁', name: 'payloads\/' },\n      { icon: '📁', name: 'music\/' },\n      { icon: '📄', name: 'sys_config.ini' },\n      { icon: '📄', name: 'capture_04.pcap' },\n      { icon: '📄', name: 'keys.txt' }\n    ];\n\n    let i = 0;\n    sdInterval = setInterval(() =\u003e {\n      if(i \u003c files.length) {\n        const row = document.createElement('div');\n        row.className = 'sd-item';\n        row.innerHTML = `\u003cspan class=\"sd-icon\"\u003e${files[i].icon}\u003c\/span\u003e \u003cspan\u003e${files[i].name}\u003c\/span\u003e`;\n        list.appendChild(row);\n        i++;\n      } else {\n        clearInterval(sdInterval);\n      }\n    }, 150);\n  }\n\n  \/\/ 12. USB OTG\n  function initUSBOTG() {\n    const log = document.getElementById('usb-log');\n    log.innerHTML = '';\n\n    const events = [\n      \"Initializing USB subsystem...\",\n      \"[ OK ] USB Core Loaded\",\n      \"Probing Port 1...\",\n      \"\u003cspan class='usb-success'\u003e[+] Device Found: RTL-SDR v3\u003c\/span\u003e\",\n      \"Probing Port 2...\",\n      \"Port 2 is empty.\",\n      \"Mounting external filesystem...\",\n      \"[ OK ] \/mnt\/usb mapped successfully.\"\n    ];\n\n    let i = 0;\n    usbInterval = setInterval(() =\u003e {\n      if(i \u003c events.length) {\n        const line = document.createElement('div');\n        line.className = 'usb-line';\n        line.innerHTML = events[i];\n        log.appendChild(line);\n        log.scrollTop = log.scrollHeight;\n        i++;\n      } else {\n        clearInterval(usbInterval);\n      }\n    }, 400);\n  }\n\n  \/\/ --- Animaciones Generales de Scroll ---\n  document.addEventListener(\"DOMContentLoaded\", () =\u003e {\n    const cards = document.querySelectorAll('.spectre-card');\n    const elements = [\n      document.getElementById('spectre-banner'),\n      document.getElementById('spectre-prep'),\n      document.getElementById('spectre-screen')\n    ];\n\n    const observer = new IntersectionObserver((entries) =\u003e {\n      entries.forEach((entry, index) =\u003e {\n        if (entry.isIntersecting) {\n          if(entry.target.classList.contains('spectre-card')) {\n             setTimeout(() =\u003e { entry.target.classList.add('is-visible'); }, index * 100); \n          } else {\n             entry.target.classList.add('is-visible');\n          }\n          observer.unobserve(entry.target);\n        }\n      });\n    }, { threshold: 0.1 });\n\n    cards.forEach(card =\u003e observer.observe(card));\n    elements.forEach(el =\u003e { if(el) observer.observe(el); });\n\n    const timeElement = document.querySelector('.spectre-status-bar .time');\n    if(timeElement) {\n      const updateTime = () =\u003e {\n        const now = new Date();\n        timeElement.textContent = now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0');\n      };\n      updateTime();\n      setInterval(updateTime, 60000);\n    }\n  });\n\u003c\/script\u003e\n\n\n\u003c\/body\u003e","brand":"sgpstore","offers":[{"title":"Default Title","offer_id":57731307831628,"sku":null,"price":750.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1057\/9807\/4700\/files\/rn-image_picker_lib_temp_5b755567-e932-4999-afc4-044b0eb8cb0c.png?v=1781652457","url":"https:\/\/sgpstore.net\/products\/sin-titulo-7jun_15-01-42","provider":"sgpstore","version":"1.0","type":"link"}