{"asset_map": {"arena_stadium": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/arena_stadium_8c554fa4-b989-4114-ae06-38fbe30c1560.webp", "type": "image", "prompt": "Generate a top-down view of a circular Beyblade-style battle arena stadium. Diameter 500px, featuring a raised 30px thick metallic silver chrome rim with visible panel lines and bolts. Smooth light gray inner surface with a subtle radial gradient. Include a faint futuristic circular logo in the center. Clean, modern, anime-inspired aesthetic with bold outlines, professional game asset, transparent background outside the rim.", "description": "Top-down view of a circular battle arena with a metallic rim and anime-inspired detailing.", "subtype": "background", "aspect_ratio": [906, 904], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_balanced": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_balanced_31621314-87ab-41b7-89eb-db4bd6ad913a.webp", "type": "image", "prompt": "Generate a top-down view of a balanced-type spinning top, Beyblade style. Symmetrical circular base with 4-6 evenly spaced attack points. Primary blue body with yellow and gold metallic accents. Central axis tip visible. Metallic sheen, anime-style bold outlines, highly detailed mechanical panel lines. Professional game-ready character asset, transparent background.", "description": "A balanced-type spinning top character with a blue and gold color scheme.", "subtype": "character", "aspect_ratio": [865, 887], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_attack": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_attack_4bbe9a05-4c1e-425d-b89d-b3414721d99e.webp", "type": "image", "prompt": "Generate a top-down view of an aggressive attack-type spinning top, Beyblade style. Angular design with 3-4 sharp, blade-like protrusions. Primary red body with black and silver accents. Flame and lightning motifs. Metallic sheen, high contrast, anime-style bold outlines. Fast and dangerous look, professional game-ready character asset, transparent background.", "description": "An aggressive, red-themed attack-type spinning top with sharp blades.", "subtype": "character", "aspect_ratio": [852, 855], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_defense": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_defense_ed815a81-008f-403e-8631-4c93be5edebb.webp", "type": "image", "prompt": "Generate a top-down view of a heavy defense-type spinning top, Beyblade style. Rounded, thick design with a wide circular defensive ring and minimal protrusions. Primary green body with silver and white metallic accents. Shield and armor motifs suggesting durability. Metallic sheen, anime-style bold outlines, professional game-ready character asset, transparent background.", "description": "A heavy, rounded green-themed defense-type spinning top.", "subtype": "character", "aspect_ratio": [967, 955], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "energy_trail_blue": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/energy_trail_blue_e0ea360c-b9d6-4bb8-890c-8234c9ba34ca.webp", "type": "image", "prompt": "Generate an anime-style glowing energy trail particle, 60x20px, tapering to a point. Bright electric blue color with a luminous core and soft semi-transparent edges. Slight curve to suggest spinning motion. High-quality visual effect, transparent background.", "description": "A luminous blue energy trail for the balanced top.", "subtype": "effect", "aspect_ratio": [1023, 433], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "energy_trail_red": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/energy_trail_red_55da8f6d-fff5-4b89-873f-caaabd2c0f49.webp", "type": "image", "prompt": "Generate an anime-style glowing energy trail particle, 60x20px, tapering to a point. Bright fiery red and orange color with a luminous core and soft semi-transparent edges. Slight curve to suggest circular motion. High-quality visual effect, transparent background.", "description": "A fiery red energy trail for the attack top.", "subtype": "effect", "aspect_ratio": [1158, 435], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "energy_trail_green": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/energy_trail_green_1d2940a9-888b-4c8f-a4ab-544f638f2f5a.webp", "type": "image", "prompt": "Generate an anime-style glowing energy trail particle, 60x20px, tapering to a point. Bright emerald green color with a luminous core and soft semi-transparent edges. Slight curve to suggest circular motion. High-quality visual effect, transparent background.", "description": "A bright green energy trail for the defense top.", "subtype": "effect", "aspect_ratio": [650, 238], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "collision_spark": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/collision_spark_c1e880d0-4cf4-42e5-a761-16c7b4fcbeb7.webp", "type": "image", "prompt": "Generate a bright anime-style impact spark effect, starburst pattern with sharp radiating points. Yellow-white core fading to orange. Bold lines, high contrast, conveying explosive energy. Semi-transparent edges, high resolution, transparent background.", "description": "A starburst spark effect for collisions.", "subtype": "effect", "aspect_ratio": [929, 958], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "background_arena": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/background_arena_ec94cfe6-6778-4058-a4f1-e235c654b188.webp", "type": "image", "prompt": "Generate a 9:16 tall image of a dramatic Beyblade battle arena environment. Cinematic stadium lighting, blurred crowd silhouettes in the background, futuristic high-tech aesthetic. Color palette of dark blues and purples with neon accent lighting. Darker upper 60%, subtle gradient to deeper tones in the bottom 40%. High detail, anime-style artistic treatment, professional quality.", "description": "Dramatic 9:16 background featuring stadium lights and a futuristic anime aesthetic.", "subtype": "background", "aspect_ratio": [1024, 1536], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "launch_button": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/launch_button_dba9d0d9-a2c0-4f18-96a9-6e5771824374.webp", "type": "image", "prompt": "Generate a circular UI button for game launch, 120px. Bright orange and red gradient, metallic rim, anime-style bold outlines. Features a prominent white arrow icon in the center. Glossy highlights and shine effects, clean game asset, transparent background.", "description": "Exciting red/orange 'GO' launch button.", "subtype": "ui", "aspect_ratio": [929, 942], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "retry_button": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/retry_button_77c54d44-5747-414e-bdce-ac59dd99324a.webp", "type": "image", "prompt": "Generate a circular UI button for retry, 100px. Yellow and gold metallic color scheme with a circular arrow icon in the center. Anime-style bold outlines, glossy finish with subtle shine. Energetic and polished appearance, transparent background.", "description": "Energetic yellow/gold retry button.", "subtype": "ui", "aspect_ratio": [879, 881], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "launch_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/launch_sound_a5ff69b4-ffe2-44a3-9db6-a3a9682d9223.mp3", "type": "audio", "prompt": "A powerful, high-velocity 'whoosh' sound effect transition into a fast mechanical whirring. Sharp release, aerodynamic air displacement, followed by a metallic spinning resonance. Clean, punchy, and satisfying for a physics-based battle game.", "description": "High-energy whoosh and whirring sound for the initial top launch", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.2, "loop": false, "animation": null}, "collision_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/collision_sound_c2d12264-067f-4451-b49c-f29ab5382c12.mp3", "type": "audio", "prompt": "High-impact metallic 'clang' sound effect, heavy steel hitting steel, sharp transient with a short ringing resonance. Vibrant and anime-style, clear and punchy without being muddy. Suitable for repeated collision hits.", "description": "Sharp metallic impact sound for top-on-top collisions", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 0.8, "loop": false, "animation": null}, "spinning_loop": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/spinning_loop_5fd13a6d-9ca6-445c-a0fb-33ac746c2a61.mp3", "type": "audio", "prompt": "Continuous mechanical spinning sound, a steady whirring hum with a subtle metallic resonance and airy whooshing. Seamless loop, constant energy, medium pitch, clean and non-intrusive background texture.", "description": "Seamless mechanical hum representing the top's rotation", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3, "loop": true, "animation": null}, "knockout_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/knockout_sound_b29bb43d-5bd3-4376-93a3-d95a1d1eb655.mp3", "type": "audio", "prompt": "Dramatic knockout sound effect: a sharp metallic crash followed by a descending pitch 'falling' whoosh and a final heavy clatter. Conveys a sense of being thrown out of a stadium, high energy, slightly exaggerated anime style.", "description": "Dramatic crash and falling sound when a top leaves the arena", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3, "loop": false, "animation": null}, "victory_fanfare": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/victory_fanfare_7f316d3b-845d-42fe-9265-41e96b04aa8d.mp3", "type": "audio", "prompt": "Short, triumphant 4-second anime victory fanfare. Bright brass section, energetic orchestral percussion, fast-paced major key melody, ends on a powerful and satisfying final chord. High energy and celebratory.", "description": "Short, triumphant anime-style theme for the winner", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 5, "loop": false, "animation": null}, "battle_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/battle_music_22ccbb69-50f6-4eb9-b890-fe675e4dedbc.mp3", "type": "audio", "prompt": "Intense fast-paced anime action background music. Features driving rock drums, aggressive electric guitar riffs, and bright energetic synths. 150 BPM, high tension, competitive spirit, driving rhythm. Seamless loop for continuous gameplay.", "description": "Intense, high-tempo background music for the battle phase", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30, "loop": true, "animation": null}, "countdown_beep": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/countdown_beep_9cf0a568-1679-42ee-8729-daa88533135d.mp3", "type": "audio", "prompt": "Clean digital electronic beep, short attack and decay, arcade style. Minimalist and attention-grabbing. Clear sine or square wave with a soft pop, suitable for a 3-2-1 countdown sequence.", "description": "Short digital beep for the pre-battle countdown", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2, "loop": false, "animation": null}, "top_valtryek": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_valtryek_ba58258d-5ee4-433f-b6d4-8f4b3449d8af.webp", "type": "image", "prompt": "Generate a high-energy anime style spinning top from a top-down view. The design features a sleek metallic blue base with three prominent, sharp golden wings or blades. A bold red and yellow 'V' emblem is centered on the top. Professional quality game asset with sharp lines, metallic textures, and a clean transparent background. Consistent with the aesthetic of a high-stakes battle arena.", "description": "A high-performance blue and gold Valtryek-style spinning top for combat.", "subtype": "character", "aspect_ratio": [950, 948], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_victory_valtryek": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_victory_valtryek_b78f1761-664b-4cda-8ba5-60f7ed280b09.webp", "type": "image", "prompt": "Generate a high-quality top-down view of an evolved 'Victory Valtryek' spinning top. It should feature sharp, translucent blue blades with polished silver metallic edges, showing more complexity than image 1. The central emblem should be intricate with a detailed 'V' and yellow lightning motifs. Professional anime game art style, sharp lines, metallic and crystalline textures, top-down perspective, front-facing, transparent background.", "description": "An evolved, more powerful version of the Valtryek spinning top with translucent blades and lightning motifs.", "subtype": "character", "aspect_ratio": [1004, 1002], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_genesis_valtryek": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_genesis_valtryek_909ee345-ee25-4f1e-be20-cbab9e8f6e7f.webp", "type": "image", "prompt": "Generate a top-down view of the 'Genesis Valtryek' spinning top, an ultimate evolution of image 1 and image 2. Features large, clear-blue crystalline wings and a heavy metallic core with a complex god-like motif in the center. High-energy anime art style, sharp lines, metallic and translucent textures, powerful and futuristic look, transparent background, professional game asset quality.", "description": "The ultimate evolution of the Valtryek spinning top with crystalline wings and a futuristic metallic core.", "subtype": "character", "aspect_ratio": [1011, 992], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "top_storm_pegasus": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_storm_pegasus_4fce9d2f-99a9-4cf1-a5ce-3905b6375e06.webp", "type": "image", "prompt": "Generate a top-down view of a 'Storm Pegasus' style spinning top, professional game asset. It features a circular silver metallic outer ring with curved blue wing-like accents. In the very center is a small red face bolt with a stylized pegasus icon. High-energy classic anime art style, sharp lines, metallic textures, polished finish, transparent background.", "description": "A top-down view of a Storm Pegasus style spinning top for the battle arena.", "subtype": "character", "aspect_ratio": [979, 977], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "spring_attack_fx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/spring_attack_fx_713b4ed7-4477-4079-b2e9-02ac196d7bf9.webp", "type": "image", "prompt": "Generate a high-energy visual effect representing a 'Spring Attack'. A bright yellow and white spiraling energy burst, stylized as a compressed spring-like shockwave. The design should be circular and viewed from a top-down perspective to match the game arena. High-energy anime aesthetic with glowing light trails, sharp energy particles, and semi-transparency. High resolution, professional game asset, transparent background.", "description": "A high-energy yellow and white spiraling energy shockwave for a special attack move.", "subtype": "effect", "aspect_ratio": [949, 904], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "top_ultimate_valtryek": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_ultimate_valtryek_626845cd-fec3-4303-83b5-2d4dfef821fa.webp", "type": "image", "prompt": "Generate a top-down view of a high-performance 'Ultimate Valtryek' spinning top. The design must be highly aggressive and complex, featuring deep blue, gold, and vibrant red accents. The outer perimeter should have sharp, wing-like protrusions with crystalline textures and a polished metallic finish. Professional anime game asset style, consistent with the aesthetic of image 1 and image 2, high resolution, detailed lighting, transparent background.", "description": "The ultimate evolution of the Valtryek spinning top with a complex, aggressive design for top-down battle gameplay.", "subtype": "character", "aspect_ratio": [1016, 1007], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_galaxy_pegasus": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_galaxy_pegasus_650d84ea-ed6d-48aa-bedd-a4ab535eb941.webp", "type": "image", "prompt": "Generate a top-down view of a Galaxy Pegasus spinning top for an anime-style battle game. The design features a celestial blue and silver color scheme with intricate cosmic patterns. The outer rim has three distinct, sharp metallic wings, and the center core features a prominent stylized horse head motif. Shiny metallic textures, polished finish, high resolution, detailed game asset, transparent background, matching the art style of top_storm_pegasus.", "description": "Top-down view of a celestial blue and silver Galaxy Pegasus spinning top with metallic wings and horse motif.", "subtype": "character", "aspect_ratio": [1017, 1009], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_stamina": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_stamina_3e62e032-6365-4f1c-affa-ebcf195b436c.webp", "type": "image", "prompt": "Generate a top-down view of a sleek, aerodynamic stamina-type spinning top for a combat game. The design should be perfectly circular with a smooth yellow and gold metallic finish, minimal friction blades, and a polished center core. Professional anime game asset style, consistent with the futuristic aesthetic of image 1, clean lines, high resolution, transparent background.", "description": "A sleek yellow and gold stamina-type spinning top designed for long-duration spinning.", "subtype": "character", "aspect_ratio": [879, 881], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "voice_let_it_rip": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/voice_let_it_rip_c470098e-8e9e-441d-be5a-acb38127228d.mp3", "type": "audio", "prompt": "High-energy, enthusiastic male anime protagonist voice shouting 'Three, two, one... LET IT RIP!'. The delivery is dramatic, powerful, and iconic of a shonen battle series. Vocal performance has a slight raspy grit on the final 'RIP' for emphasis. Recorded in a clean studio environment with professional presence, suitable for a Beyblade-inspired battle intro. Clear articulation with a fast-paced, hype-building cadence.", "description": "Dramatic anime-style male voice performing the iconic battle countdown and launch catchphrase.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 4.08, "loop": false, "animation": null}, "top_world_spryzen": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_world_spryzen_3a798b0e-ab51-42a9-b8cc-5150599583a2.webp", "type": "image", "prompt": "Generate a top-down view of a World Spryzen spinning top, featuring a fierce and aggressive mechanical design. The color palette is primarily deep red and black with ornate gold highlights. The central core depicts a stylized axe or bird motif. The art style is vibrant, polished anime-inspired mechanical art with high-quality metallic textures and sharp edges, consistent with high-performance battle tops. High resolution, detailed, professional quality game asset, transparent background.", "description": "A fierce red and black World Spryzen spinning top with an aggressive axe motif for top-down combat.", "subtype": "character", "aspect_ratio": [1011, 1020], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "top_roktavor": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_roktavor_e5d279ec-99b5-4210-94b2-53a28af50a3f.webp", "type": "image", "prompt": "Generate a top-down view of a Roktavor (Ragnaruk) spinning top for a battle arena game. The design should be sturdy and stamina-focused with a primarily orange and yellow/gold color scheme. Include flaming and wing-like patterns on the perimeter with a central mechanical core. Use a vibrant anime-inspired mechanical art style, matching the aesthetic of image 1. Professional game asset, high resolution, detailed metallic textures, transparent background.", "description": "Top-down view of an orange and gold stamina-type Roktavor spinning top with flame patterns.", "subtype": "character", "aspect_ratio": [983, 1005], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "top_dread_phoenix": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_dread_phoenix_5867e925-1ac0-4da6-9e15-232df776b57b.webp", "type": "image", "prompt": "Generate a high-resolution, top-down view of a 'Dread Phoenix' spinning top. The design is anime-inspired and futuristic, featuring a heavy metallic circular frame. The center core showcases a detailed phoenix motif. Color palette: dark purple, sleek silver, and deep crimson. It should look like a high-end defensive-type combat top with polished surfaces and intricate mechanical details. Professional game asset, transparent background, top-down perspective.", "description": "A high-end, defensive spinning top with a dark purple and crimson phoenix motif.", "subtype": "character", "aspect_ratio": [1005, 1016], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "top_xcalius": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_xcalius_0e78cf77-0ee4-4df9-8e11-8e8ade30d6ed.webp", "type": "image", "prompt": "Generate a top-down view of an aggressive spinning top named Xcalius. Anime-inspired, metallic, and futuristic style. The design features a prominent integrated large sword-like blade that looks sharp and lethal. Color scheme: deep blue, silver, and gold. High resolution, detailed metallic textures, clean polished game asset, transparent background.", "description": "An aggressive, sword-themed spinning top character named Xcalius for top-down combat.", "subtype": "character", "aspect_ratio": [906, 1102], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "top_fafnir": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_fafnir_68732f93-21e1-4118-8606-2e2492fde04a.webp", "type": "image", "prompt": "Generate a top-down view of a high-performance spinning top named Drain Fafnir. The design features a primarily gold and dark blue color scheme with specialized rubber-like triangular blades around the perimeter. In the center, there is a detailed high-tech dragon motif. The art style is polished, metallic, and vibrant anime-inspired, matching the aesthetic of top_valtryek and top_world_spryzen. High resolution, professional game asset, transparent background.", "description": "A gold and dark blue dragon-themed stamina-type spinning top for top-down combat.", "subtype": "character", "aspect_ratio": [1015, 1022], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "top_turbo_achilles": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/top_turbo_achilles_bf6eb837-f344-4630-b00c-dbf286f4c62d.webp", "type": "image", "prompt": "Generate a top-down view of a Turbo Achilles-style spinning top, designed for a high-energy anime battle game. The top features a dominant crimson red and metallic gold color scheme with sharp silver blades on the sides. It has a central golden core and intricate mechanical detailing. Polished metallic finish, vibrant colors, clean lines, professional game asset, transparent background.", "description": "A high-energy, crimson and gold Turbo Achilles spinning top for top-down combat.", "subtype": "character", "aspect_ratio": [998, 1003], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}}, "game_code": "<!DOCTYPE html>\n<html>\n<head>\n    <title>Beyblade</title>\n    <link href=\"https://fonts.googleapis.com/css2?family=Orbitron:wght@700;900&family=Poppins:wght@400;600;700&display=swap\" rel=\"stylesheet\">\n    <style>\n        :root {\n            --primary-color: #ff6600;\n            --secondary-color: #00ccff;\n            --bg-dark: #1a1a2e;\n            --bg-darker: #0f0f1a;\n            --text-light: #ffffff;\n            --text-dim: #aaaacc;\n            --transition-fast: 150ms;\n            --transition-normal: 300ms;\n            --ease-out: cubic-bezier(0.0, 0, 0.2, 1);\n            --ease-bounce: cubic-bezier(0.68, -0.6, 0.32, 1.6);\n        }\n\n        body, html {\n            margin: 0;\n            padding: 0;\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n            touch-action: none;\n            -ms-touch-action: none;\n            font-family: 'Poppins', sans-serif;\n            background: var(--bg-darker);\n        }\n\n        #game-world {\n            position: relative;\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n        }\n\n        #background {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            object-fit: cover;\n            z-index: 0;\n        }\n\n        #game-canvas {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            z-index: 1;\n        }\n\n        /* UI Overlay */\n        .ui-overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            pointer-events: none;\n            z-index: 10;\n        }\n\n        .ui-overlay > * {\n            pointer-events: auto;\n        }\n\n        /* Top Stats Display */\n        .stats-container {\n            position: absolute;\n            top: 16px;\n            left: 16px;\n            right: 16px;\n            display: flex;\n            justify-content: space-between;\n            gap: 8px;\n        }\n\n        .top-stat {\n            background: rgba(0, 0, 0, 0.75);\n            border-radius: 16px;\n            padding: 12px 16px;\n            flex: 1;\n            max-width: 220px;\n            backdrop-filter: blur(8px);\n            border: 1px solid rgba(255, 255, 255, 0.1);\n        }\n\n        .top-stat-name {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 18px;\n            font-weight: 700;\n            color: var(--text-light);\n            margin-bottom: 6px;\n            white-space: nowrap;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);\n        }\n\n        .spin-bar-container {\n            height: 12px;\n            background: rgba(255, 255, 255, 0.15);\n            border-radius: 6px;\n            overflow: hidden;\n            box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);\n        }\n\n        .spin-bar {\n            height: 100%;\n            border-radius: 4px;\n            transition: width 0.1s ease-out;\n        }\n\n        /* Control Area */\n        .control-area {\n            position: absolute;\n            bottom: 0;\n            left: 0;\n            right: 0;\n            height: 40%;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            padding: 20px;\n            box-sizing: border-box;\n        }\n\n        .power-meter-container {\n            width: 280px;\n            height: 32px;\n            background: rgba(0, 0, 0, 0.75);\n            border-radius: 16px;\n            overflow: hidden;\n            margin-bottom: 20px;\n            border: 3px solid rgba(255, 255, 255, 0.3);\n            box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4), inset 0 2px 4px rgba(0, 0, 0, 0.3);\n        }\n\n        .power-meter {\n            height: 100%;\n            width: 0%;\n            background: linear-gradient(90deg, #00ff88, #ffcc00, #ff4444);\n            transition: width 0.05s ease-out;\n        }\n\n        .launch-instruction {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 28px;\n            color: var(--text-light);\n            text-align: center;\n            text-shadow: 0 2px 12px rgba(0, 0, 0, 0.9), 0 0 20px rgba(255, 102, 0, 0.3);\n            margin-bottom: 20px;\n            letter-spacing: 1px;\n        }\n\n        /* Countdown Overlay */\n        .countdown-overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            background: rgba(0, 0, 0, 0.6);\n            z-index: 100;\n            opacity: 0;\n            pointer-events: none;\n            transition: opacity 0.3s ease;\n        }\n\n        .countdown-overlay.active {\n            opacity: 1;\n            pointer-events: auto;\n        }\n\n        .countdown-text {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 120px;\n            font-weight: 900;\n            color: var(--primary-color);\n            text-shadow: 0 0 40px rgba(255, 102, 0, 0.8);\n            animation: countdownPulse 0.5s ease-out;\n        }\n\n        @keyframes countdownPulse {\n            0% { transform: scale(1.5); opacity: 0; }\n            50% { transform: scale(1); opacity: 1; }\n            100% { transform: scale(0.95); opacity: 1; }\n        }\n\n        /* Result Screen */\n        .result-overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: flex-end;\n            padding-bottom: 120px;\n            box-sizing: border-box;\n            background: rgba(0, 0, 0, 0.85);\n            z-index: 100;\n            opacity: 0;\n            pointer-events: none;\n            transition: opacity 0.5s ease;\n        }\n\n        .result-overlay.active {\n            opacity: 1;\n            pointer-events: auto;\n        }\n\n        .result-title {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 56px;\n            font-weight: 900;\n            margin-bottom: 48px;\n            text-shadow: 0 0 40px currentColor, 0 4px 12px rgba(0, 0, 0, 0.5);\n            text-align: center;\n        }\n\n        .result-title.victory {\n            color: #00ff88;\n        }\n\n        .result-title.defeat {\n            color: #ff4444;\n        }\n\n        .result-buttons {\n            display: flex;\n            flex-direction: column;\n            gap: 16px;\n            width: 100%;\n            padding: 0 32px;\n            box-sizing: border-box;\n        }\n\n        .result-button {\n            width: 100%;\n            min-height: 72px;\n            padding: 20px 32px;\n            font-family: 'Orbitron', sans-serif;\n            font-size: 22px;\n            font-weight: 700;\n            color: white;\n            background: linear-gradient(135deg, var(--primary-color), #ff3300);\n            border: none;\n            border-radius: 36px;\n            cursor: pointer;\n            transition: transform var(--transition-fast) var(--ease-out), box-shadow var(--transition-fast);\n            box-shadow: 0 6px 20px rgba(255, 102, 0, 0.4);\n        }\n\n        .result-button:active {\n            transform: scale(0.96);\n            box-shadow: 0 3px 10px rgba(255, 102, 0, 0.3);\n        }\n\n        .result-button.secondary {\n            background: linear-gradient(135deg, #445566, #334455);\n            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);\n        }\n\n        /* Edit Mode */\n        .edit-panel {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            display: flex;\n            flex-direction: column;\n            background: linear-gradient(180deg, var(--bg-dark) 0%, var(--bg-darker) 100%);\n            z-index: 50;\n            opacity: 0;\n            pointer-events: none;\n            transition: opacity 0.3s ease;\n            overflow-y: auto;\n        }\n\n        .edit-panel.active {\n            opacity: 1;\n            pointer-events: auto;\n        }\n\n        .edit-title {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 36px;\n            font-weight: 900;\n            color: var(--primary-color);\n            text-align: center;\n            padding: 32px 16px 16px;\n            text-shadow: 0 0 30px rgba(255, 102, 0, 0.6), 0 4px 8px rgba(0, 0, 0, 0.4);\n            letter-spacing: 1px;\n        }\n\n        .top-preview-container {\n            flex: 0 0 auto;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            padding: 20px;\n        }\n\n        .top-preview {\n            width: 150px;\n            height: 150px;\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            animation: previewSpin 2s linear infinite;\n            box-shadow: 0 0 40px rgba(255, 102, 0, 0.4);\n        }\n\n        .top-preview img {\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n        }\n\n        @keyframes previewSpin {\n            from { transform: rotate(0deg); }\n            to { transform: rotate(360deg); }\n        }\n\n        .edit-section {\n            padding: 16px 24px;\n        }\n\n        .edit-section-title {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 20px;\n            font-weight: 700;\n            color: var(--secondary-color);\n            margin-bottom: 16px;\n            text-shadow: 0 0 12px rgba(0, 204, 255, 0.4);\n        }\n\n        .top-type-buttons {\n            display: flex;\n            flex-direction: column;\n            gap: 12px;\n            align-items: stretch;\n        }\n\n        .top-type-btn {\n            flex: 1;\n            min-width: 200px;\n            min-height: 110px;\n            padding: 16px 12px;\n            background: rgba(255, 255, 255, 0.08);\n            border: 2px solid rgba(255, 255, 255, 0.2);\n            border-radius: 16px;\n            color: var(--text-light);\n            font-family: 'Orbitron', sans-serif;\n            font-size: 18px;\n            font-weight: 700;\n            cursor: pointer;\n            transition: all var(--transition-fast) var(--ease-out);\n        }\n\n        .top-type-btn.selected {\n            background: rgba(255, 102, 0, 0.25);\n            border-color: var(--primary-color);\n            box-shadow: 0 0 24px rgba(255, 102, 0, 0.5), inset 0 0 20px rgba(255, 102, 0, 0.1);\n        }\n\n        .top-type-btn:active {\n            transform: scale(0.97);\n        }\n\n        .stat-bars {\n            margin-top: 10px;\n        }\n\n        .stat-row {\n            display: flex;\n            align-items: center;\n            margin-bottom: 6px;\n            font-size: 14px;\n            font-family: 'Poppins', sans-serif;\n            font-weight: 500;\n            color: var(--text-dim);\n        }\n\n        .stat-label {\n            width: 48px;\n        }\n\n        .stat-bar-bg {\n            flex: 1;\n            height: 10px;\n            background: rgba(255, 255, 255, 0.15);\n            border-radius: 5px;\n            overflow: hidden;\n        }\n\n        .stat-bar-fill {\n            height: 100%;\n            border-radius: 5px;\n        }\n\n        .color-inputs {\n            display: flex;\n            gap: 16px;\n            align-items: center;\n        }\n\n        .color-input-group {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n        }\n\n        .color-input-group label {\n            font-size: 14px;\n            color: var(--text-dim);\n        }\n\n        .color-input-group input[type=\"color\"] {\n            width: 48px;\n            height: 48px;\n            border: 2px solid rgba(255, 255, 255, 0.3);\n            border-radius: 8px;\n            cursor: pointer;\n            background: transparent;\n            padding: 2px;\n        }\n\n        .name-input {\n            width: 100%;\n            padding: 16px 20px;\n            font-family: 'Poppins', sans-serif;\n            font-size: 20px;\n            color: var(--text-light);\n            background: rgba(255, 255, 255, 0.1);\n            border: 2px solid rgba(255, 255, 255, 0.2);\n            border-radius: 16px;\n            box-sizing: border-box;\n            min-height: 60px;\n            transition: border-color var(--transition-fast), box-shadow var(--transition-fast);\n        }\n\n        .name-input:focus {\n            outline: none;\n            border-color: var(--primary-color);\n            box-shadow: 0 0 16px rgba(255, 102, 0, 0.3);\n        }\n\n        .name-input::placeholder {\n            color: rgba(255, 255, 255, 0.4);\n        }\n\n        .ready-button {\n            width: calc(100% - 48px);\n            margin: 24px;\n            margin-top: auto;\n            padding: 24px;\n            min-height: 80px;\n            font-family: 'Orbitron', sans-serif;\n            font-size: 26px;\n            font-weight: 900;\n            color: white;\n            background: linear-gradient(135deg, var(--primary-color), #ff3300);\n            border: none;\n            border-radius: 40px;\n            cursor: pointer;\n            transition: transform var(--transition-fast) var(--ease-out), box-shadow var(--transition-fast);\n            box-shadow: 0 8px 32px rgba(255, 102, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3);\n            letter-spacing: 1px;\n        }\n\n        .ready-button:active {\n            transform: scale(0.96);\n            box-shadow: 0 4px 16px rgba(255, 102, 0, 0.4);\n        }\n\n        /* Retry Button */\n        .retry-button {\n            position: absolute;\n            bottom: 40px;\n            left: 50%;\n            transform: translateX(-50%);\n            width: 100px;\n            height: 100px;\n            border-radius: 50%;\n            border: none;\n            cursor: pointer;\n            opacity: 0;\n            pointer-events: none;\n            transition: opacity 0.3s ease, transform var(--transition-fast) var(--ease-out);\n            background: transparent;\n            padding: 0;\n        }\n\n        /* Menu Button */\n        .menu-btn-container {\n            position: absolute;\n            top: 16px;\n            right: 16px;\n            z-index: 20;\n            display: none;\n        }\n\n        .menu-btn-container.active {\n        }\n\n        .icon-button {\n            background: rgba(0, 0, 0, 0.6);\n            border: 1px solid rgba(255, 255, 255, 0.3);\n            border-radius: 12px;\n            width: 56px;\n            height: 56px;\n            color: white;\n            font-size: 32px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            cursor: pointer;\n            backdrop-filter: blur(8px);\n            font-family: 'Poppins', sans-serif;\n            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n            transition: transform 0.1s;\n        }\n\n        .icon-button:active {\n            transform: scale(0.9);\n        }\n\n        /* Pause Overlay */\n        .pause-overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.85);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            z-index: 150;\n            opacity: 0;\n            pointer-events: none;\n            transition: opacity 0.3s ease;\n        }\n\n        .pause-overlay.active {\n            opacity: 1;\n            pointer-events: auto;\n        }\n\n        .pause-menu-title {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 48px;\n            font-weight: 900;\n            color: white;\n            margin-bottom: 60px;\n            text-shadow: 0 0 20px rgba(255, 255, 255, 0.3);\n        }\n\n        .retry-button.active {\n            opacity: 1;\n            pointer-events: auto;\n        }\n\n        .retry-button:active {\n            transform: translateX(-50%) scale(0.9);\n        }\n\n        .retry-button img {\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n        }\n\n        /* Screen shake animation */\n        @keyframes screenShake {\n            0%, 100% { transform: translate(0, 0); }\n            10% { transform: translate(-5px, -5px); }\n            20% { transform: translate(5px, 5px); }\n            30% { transform: translate(-5px, 5px); }\n            40% { transform: translate(5px, -5px); }\n            50% { transform: translate(-3px, -3px); }\n            60% { transform: translate(3px, 3px); }\n            70% { transform: translate(-2px, 2px); }\n            80% { transform: translate(2px, -2px); }\n            90% { transform: translate(-1px, 1px); }\n        }\n\n        .shake {\n            animation: screenShake 0.3s ease-out;\n        }\n\n        /* Voice Button */\n        .voice-btn-container {\n            position: absolute;\n            top: 16px;\n            left: 16px;\n            z-index: 20;\n            display: flex;\n            align-items: center;\n            gap: 12px;\n        }\n\n        .voice-btn {\n            background: rgba(0, 0, 0, 0.6);\n            border: 2px solid rgba(255, 255, 255, 0.3);\n            border-radius: 50%;\n            width: 56px;\n            height: 56px;\n            color: white;\n            font-size: 24px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            cursor: pointer;\n            backdrop-filter: blur(8px);\n            transition: all 0.3s ease;\n        }\n\n        .voice-btn.active {\n            border-color: #00ff88;\n            box-shadow: 0 0 15px rgba(0, 255, 136, 0.5);\n            animation: pulse-green 1.5s infinite;\n        }\n\n        .voice-status {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 14px;\n            color: white;\n            text-shadow: 0 2px 4px rgba(0,0,0,0.5);\n            opacity: 0;\n            transition: opacity 0.3s;\n        }\n\n        .voice-status.active {\n            opacity: 1;\n        }\n\n        @keyframes pulse-green {\n            0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(0, 255, 136, 0.7); }\n            70% { transform: scale(1.1); box-shadow: 0 0 0 10px rgba(0, 255, 136, 0); }\n            100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(0, 255, 136, 0); }\n        }\n\n        #attack-btn-container {\n            position: absolute;\n            bottom: 40px;\n            right: 20px;\n            z-index: 20;\n            display: none;\n            grid-template-columns: repeat(2, 1fr);\n            align-items: center;\n            gap: 10px;\n            pointer-events: none;\n        }\n\n        #attack-btn-container.active {\n            display: grid;\n        }\n\n        .attack-btn-wrapper {\n            pointer-events: auto;\n            transition: transform 0.2s;\n        }\n\n        .attack-btn-wrapper:active {\n            transform: scale(0.9);\n        }\n\n        .attack-btn-dynamic {\n            width: 100px;\n            height: 100px;\n            border-radius: 50%;\n            border: 4px solid rgba(255, 255, 255, 0.4);\n            color: white;\n            font-family: 'Orbitron', sans-serif;\n            font-size: 14px;\n            font-weight: 900;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            cursor: pointer;\n            box-shadow: 0 0 20px rgba(255, 255, 255, 0.2);\n            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);\n            position: relative;\n            overflow: hidden;\n            padding: 5px;\n            text-align: center;\n        }\n\n        .attack-label {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 11px;\n            color: white;\n            text-shadow: 0 2px 4px rgba(0,0,0,0.5);\n            text-align: center;\n            background: rgba(0,0,0,0.5);\n            padding: 2px 8px;\n            border-radius: 10px;\n            margin-bottom: 2px;\n        }\n\n        .special-banner {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%) scale(0);\n            width: 100%;\n            background: rgba(0, 0, 0, 0.85);\n            border-top: 4px solid var(--primary-color);\n            border-bottom: 4px solid var(--primary-color);\n            color: white;\n            font-family: 'Orbitron', sans-serif;\n            font-size: 42px;\n            font-weight: 900;\n            text-align: center;\n            padding: 30px 0;\n            z-index: 200;\n            pointer-events: none;\n            transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.3s;\n            text-shadow: 0 0 20px var(--primary-color);\n            opacity: 0;\n            letter-spacing: 2px;\n        }\n\n        .special-banner.active {\n            transform: translate(-50%, -50%) scale(1);\n            opacity: 1;\n        }\n\n        .special-banner-type {\n            font-size: 18px;\n            color: var(--secondary-color);\n            margin-bottom: 10px;\n            letter-spacing: 4px;\n        }\n\n        .cooldown-fill {\n            position: absolute;\n            bottom: 0;\n            left: 0;\n            width: 100%;\n            height: 0%;\n            background: rgba(0, 0, 0, 0.6);\n            pointer-events: none;\n        }\n\n        .weight-type-btn.selected, .height-type-btn.selected {\n            background: rgba(255, 200, 0, 0.25);\n            border-color: #ffcc00;\n            box-shadow: 0 0 24px rgba(255, 200, 0, 0.5);\n        }\n\n        .opponent-type-btn.selected {\n            background: rgba(0, 204, 255, 0.25);\n            border-color: var(--secondary-color);\n            box-shadow: 0 0 24px rgba(0, 204, 255, 0.5), inset 0 0 20px rgba(0, 204, 255, 0.1);\n        }\n\n        /* Hidden class */\n        .hidden {\n            display: none !important;\n        }\n    </style>\n</head>\n<body>\n    <div id=\"game-world\">\n        <img id=\"background\" src=\"\" alt=\"background\">\n        <canvas id=\"game-canvas\"></canvas>\n        \n        <div class=\"ui-overlay\">\n            <!-- Top Stats -->\n            <div class=\"stats-container\" id=\"stats-container\">\n            </div>\n\n            <div class=\"voice-btn-container\" id=\"voice-btn-container\" style=\"display: none;\">\n                <button class=\"voice-btn\" id=\"voice-toggle-btn\">\ud83c\udfa4</button>\n                <div class=\"voice-status\" id=\"voice-status\">LISTENING...</div>\n            </div>\n\n            <div id=\"attack-btn-container\">\n            </div>\n\n            <div id=\"special-banner\" class=\"special-banner\">\n                <div class=\"special-banner-type\" id=\"special-banner-type\">SPECIAL MOVE</div>\n                <div id=\"special-banner-name\">ULTRA FLASH</div>\n            </div>\n\n            <div class=\"menu-btn-container\" id=\"menu-btn-container\">\n                <button class=\"icon-button\" id=\"open-menu-btn\">\u2630</button>\n            </div>\n\n            <!-- Control Area -->\n            <div class=\"control-area\" id=\"control-area\">\n                <div class=\"launch-instruction\" id=\"launch-instruction\">TAP & DRAG TO AIM</div>\n                <div class=\"power-meter-container\">\n                    <div class=\"power-meter\" id=\"power-meter\"></div>\n                </div>\n                <div id=\"tap-to-launch\" style=\"font-family: 'Orbitron', sans-serif; font-size: 14px; color: #aaa; margin-top: 10px;\">OR TAP HERE TO LAUNCH INSTANTLY</div>\n            </div>\n\n            <!-- Retry Button -->\n            <button class=\"retry-button\" id=\"retry-button\">\n                <img src=\"\" alt=\"Retry\" id=\"retry-img\">\n            </button>\n        </div>\n\n        <!-- Countdown Overlay -->\n        <div class=\"countdown-overlay\" id=\"countdown-overlay\">\n            <div class=\"countdown-text\" id=\"countdown-text\">3</div>\n        </div>\n\n        <!-- Result Overlay -->\n        <div class=\"result-overlay\" id=\"result-overlay\">\n            <div class=\"result-title\" id=\"result-title\">VICTORY!</div>\n            <div class=\"result-buttons\">\n                <button class=\"result-button\" id=\"play-again-btn\">PLAY AGAIN</button>\n                <button class=\"result-button secondary\" id=\"customize-btn\">CUSTOMIZE</button>\n            </div>\n        </div>\n\n        <div class=\"pause-overlay\" id=\"pause-overlay\">\n            <div class=\"pause-menu-title\">PAUSED</div>\n            <div class=\"result-buttons\">\n                <button class=\"result-button\" id=\"resume-btn\">RESUME</button>\n                <button class=\"result-button\" id=\"restart-btn\" style=\"background: linear-gradient(135deg, #ffcc00, #ff9900);\">RESTART</button>\n                <button class=\"result-button secondary\" id=\"quit-btn\">MAIN MENU</button>\n            </div>\n        </div>\n\n        <!-- Edit Panel -->\n        <div class=\"edit-panel\" id=\"edit-panel\">\n            <div class=\"edit-title\">CUSTOMIZE YOUR TOP</div>\n            \n            <div class=\"top-preview-container\">\n                <div class=\"top-preview\" id=\"top-preview\">\n                    <img src=\"\" alt=\"Top Preview\" id=\"preview-img\">\n                </div>\n                <div class=\"stat-bars\" id=\"edit-stat-bars\" style=\"width: 200px; margin-left: 20px;\">\n                    <div class=\"stat-row\">\n                        <div class=\"stat-label\">SPD</div>\n                        <div class=\"stat-bar-bg\"><div id=\"bar-speed\" class=\"stat-bar-fill\" style=\"background: #00ccff; width: 50%;\"></div></div>\n                    </div>\n                    <div class=\"stat-row\">\n                        <div class=\"stat-label\">ATK</div>\n                        <div class=\"stat-bar-bg\"><div id=\"bar-power\" class=\"stat-bar-fill\" style=\"background: #ff4444; width: 50%;\"></div></div>\n                    </div>\n                    <div class=\"stat-row\">\n                        <div class=\"stat-label\">DEF</div>\n                        <div class=\"stat-bar-bg\"><div id=\"bar-defense\" class=\"stat-bar-fill\" style=\"background: #44cc44; width: 50%;\"></div></div>\n                    </div>\n                </div>\n            </div>\n\n            <div class=\"edit-section\">\n                <div class=\"edit-section-title\">FORGE DISC (WEIGHT)</div>\n                <div class=\"top-type-buttons\" style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 10px;\">\n                    <button class=\"top-type-btn weight-type-btn\" data-weight=\"heavy\">\n                        <div>HEAVY</div>\n                        <div style=\"font-size: 10px; color: #ff4444;\">MASS++, SPEED-</div>\n                    </button>\n                    <button class=\"top-type-btn weight-type-btn\" data-weight=\"standard\">\n                        <div>STANDARD</div>\n                        <div style=\"font-size: 10px; color: #aaa;\">BALANCED</div>\n                    </button>\n                </div>\n            </div>\n\n            <div class=\"edit-section\">\n                <div class=\"edit-section-title\">PERFORMANCE TIP (HEIGHT)</div>\n                <div class=\"top-type-buttons\" style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 10px;\">\n                    <button class=\"top-type-btn height-type-btn\" data-height=\"low\">\n                        <div>LOW</div>\n                        <div style=\"font-size: 10px; color: #44cc44;\">STABILITY++, DEF+</div>\n                    </button>\n                    <button class=\"top-type-btn height-type-btn\" data-height=\"high\">\n                        <div>HIGH</div>\n                        <div style=\"font-size: 10px; color: #00ccff;\">SPEED+, ATK+</div>\n                    </button>\n                </div>\n            </div>\n\n            <div class=\"edit-section\">\n                <div class=\"edit-section-title\">SELECT TOP (LAYER)</div>\n                <div class=\"top-type-buttons\" style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 10px;\">\n                    <button class=\"top-type-btn\" data-type=\"world_spryzen\" style=\"min-height: 80px;\">\n                        <div>WORLD SPRYZEN</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: COUNTER, AXE, DUAL SPIN, LEGEND BLAST</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"roktavor\" style=\"min-height: 80px;\">\n                        <div>ROKTAVOR</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: ZONE, GRAVITY, FIRE WALL, VOLCANO</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"valtryek\" style=\"min-height: 80px;\">\n                        <div>VALTRYEK</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: RUSH, WING, VALKYRIE DASH, FLASH</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"victory_valtryek\" style=\"min-height: 80px;\">\n                        <div>VICTORY VALTRYEK</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: SLASH, SABER, ULTRA DASH, BLAST</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"genesis_valtryek\" style=\"min-height: 80px;\">\n                        <div>GENESIS VALTRYEK</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: WHIP, REBOOT, SPRING, DIVINE SPEED</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"ultimate_valtryek\" style=\"min-height: 80px;\">\n                        <div>ULTIMATE VALTRYEK</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: FLASH, BOUND, ULTRA SLASH, FINAL REBOOT</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"storm_pegasus\" style=\"min-height: 80px;\">\n                        <div>STORM PEGASUS</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: METEOR, WING, GUST BOOST, STAR PULSE</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"galaxy_pegasus\" style=\"min-height: 80px;\">\n                        <div>GALAXY PEGASUS</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: STARBLAST, NOVA, COSMIC, NEBULA</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"fafnir\" style=\"min-height: 80px;\">\n                        <div>FAFNIR</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: DRAIN, NOTHING, MIRAGE, SENSE DESTROY</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"turbo_achilles\" style=\"min-height: 80px;\">\n                        <div>TURBO ACHILLES</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: Z-SHIELD, TURBO WING, Z-BUSTER, AWAKENING</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"dread_phoenix\" style=\"min-height: 80px;\">\n                        <div>DREAD PHOENIX</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: ARMOR, CANNON, GRAVITY, REBIRTH</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"xcalius\" style=\"min-height: 80px;\">\n                        <div>XCALIUS</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: SABER, IMPACT, SWORD PULSE, GRAND IMPACT</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"stamina\" style=\"min-height: 80px;\">\n                        <div>STAMINA</div>\n                        <div style=\"font-size: 10px; color: #ffcc00;\">SPECIALS: CYCLONE LOOP, WIND SHIELD</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"balanced\" style=\"min-height: 80px;\">\n                        <div>BALANCED</div>\n                    </button>\n                    <button class=\"top-type-btn\" data-type=\"defense\" style=\"min-height: 80px;\">\n                        <div>DEFENSE</div>\n                    </button>\n                </div>\n            </div>\n\n            <div class=\"edit-section\">\n                <div class=\"edit-section-title\">SELECT OPPONENT</div>\n                <div class=\"top-type-buttons\" style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 10px;\">\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"world_spryzen\">WORLD SPRYZEN</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"roktavor\">ROKTAVOR</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"valtryek\">VALTRYEK</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"storm_pegasus\">STORM PEGASUS</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"fafnir\">FAFNIR</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"turbo_achilles\">TURBO ACHILLES</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"dread_phoenix\">DREAD PHOENIX</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"xcalius\">XCALIUS</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"attack\">ATTACK</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"defense\">DEFENSE</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"stamina\">STAMINA</button>\n                    <button class=\"top-type-btn opponent-type-btn\" data-otype=\"balanced\">BALANCED</button>\n                </div>\n            </div>\n\n            <div class=\"edit-section\">\n                <div class=\"edit-section-title\">TOP NAME</div>\n                <input type=\"text\" class=\"name-input\" id=\"name-input\" maxlength=\"15\" placeholder=\"Enter name...\">\n            </div>\n\n            <button class=\"ready-button\" id=\"ready-button\">READY TO BATTLE!</button>\n        </div>\n    </div>\n\n    <script>\n        /*\n         * BEYBLADE - Battle Game\n         * \n         * A physics-based spinning top battle game where players launch their tops\n         * into an arena to compete against AI opponents. The goal is to knock out\n         * all opponents or be the last top spinning.\n         * \n         * Features:\n         * - Touch/mouse drag launch mechanic\n         * - Physics-based collision and spinning\n         * - 3 top types with different stats\n         * - AI opponents\n         * - Edit mode for customization\n         */\n\n        async function run(mode) {\n            const gameWorld = document.getElementById('game-world');\n            const canvas = document.getElementById('game-canvas');\n            const ctx = canvas.getContext('2d');\n\n            // Constants\n            const ARENA_RADIUS = 550;\n            const ARENA_CENTER_X = 360;\n            const ARENA_CENTER_Y = 600;\n            const TOP_RADIUS = 40;\n            const RIM_WIDTH = 30;\n            const FRICTION = 0.999;\n            const SPIN_DECAY = 0.003;\n            const COLLISION_ENERGY_LOSS = 0.4;\n            const MIN_POWER = 5;\n            const MAX_SPEED = 45;\n            const KNOCKOUT_DISTANCE = ARENA_RADIUS + 80; // Distance from center to be considered out\n            const MIN_KNOCKOUT_SPEED = 15; // Minimum speed to be knocked out when hitting rim\n\n            // Top type stats\n            const TOP_STATS = {\n                world_spryzen: { \n                    speed: 18, power: 28, defense: 18, mass: 2.2, color: '#ff0000', trailId: 'energy_trail_red',\n                    specials: [\n                        { name: 'WORLD COUNTER', type: 'world_counter', cooldown: 6 },\n                        { name: 'AXE CRASH', type: 'axe_crash', cooldown: 5 },\n                        { name: 'DUAL SPIN', type: 'drain_spin', cooldown: 7 },\n                        { name: 'LEGEND BLAST', type: 'shockwave', cooldown: 8 }\n                    ]\n                },\n                roktavor: { \n                    speed: 14, power: 22, defense: 22, mass: 2.6, color: '#ff9900', trailId: 'energy_trail_red', behavior: 'center',\n                    specials: [\n                        { name: 'ROKTAVOR ZONE', type: 'roktavor_zone', cooldown: 7 },\n                        { name: 'GRAVITY FIRE', type: 'gravity_fire', cooldown: 5 },\n                        { name: 'FIRE WALL', type: 'guard', cooldown: 6 },\n                        { name: 'VOLCANO DRIVE', type: 'overdrive', cooldown: 8 }\n                    ]\n                },\n                balanced: { \n                    speed: 15, power: 20, defense: 18, mass: 1.5, color: '#4488ff', trailId: 'energy_trail_blue',\n                    specials: [\n                        { name: 'BALANCE BREAK', type: 'attack', cooldown: 4 },\n                        { name: 'SPIRAL SHOT', type: 'speed', cooldown: 4 },\n                        { name: 'IRON CORE', type: 'guard', cooldown: 6 },\n                        { name: 'PULSE WAVE', type: 'shockwave', cooldown: 7 }\n                    ]\n                },\n                attack: { \n                    speed: 22, power: 26, defense: 12, mass: 1.2, color: '#ff4444', trailId: 'energy_trail_red',\n                    specials: [\n                        { name: 'GIGA CRASH', type: 'attack', cooldown: 4 },\n                        { name: 'FLAME DRIVE', type: 'speed', cooldown: 3 },\n                        { name: 'METEOR DASH', type: 'rush_launch', cooldown: 5 },\n                        { name: 'FINAL IMPACT', type: 'impact_slash', cooldown: 7 }\n                    ]\n                },\n                defense: { \n                    speed: 12, power: 18, defense: 26, mass: 2.2, color: '#44cc44', trailId: 'energy_trail_green',\n                    specials: [\n                        { name: 'IRON GUARD', type: 'guard', cooldown: 5 },\n                        { name: 'SHIELD BASH', type: 'attack', cooldown: 6 },\n                        { name: 'GRAVITY PULL', type: 'dread_gravity', cooldown: 8 },\n                        { name: 'FORTRESS', type: 'overdrive', cooldown: 9 }\n                    ]\n                },\n                stamina: { \n                    speed: 13, power: 16, defense: 24, mass: 1.6, color: '#ffcc00', trailId: 'energy_trail_blue', behavior: 'center',\n                    specials: [\n                        { name: 'CYCLONE LOOP', type: 'stamina', cooldown: 5 },\n                        { name: 'WIND SHIELD', type: 'guard', cooldown: 6 },\n                        { name: 'ENERGY STEAL', type: 'drain_spin', cooldown: 7 },\n                        { name: 'ETERNAL SPIN', type: 'stamina_boost', cooldown: 10 }\n                    ]\n                },\n                valtryek: { \n                    speed: 22, power: 24, defense: 12, mass: 1.3, color: '#0066ff', trailId: 'energy_trail_blue', ability: 'spring',\n                    specials: [\n                        { name: 'RUSH LAUNCH', type: 'rush_launch', cooldown: 4 },\n                        { name: 'WING ATTACK', type: 'attack', cooldown: 5 },\n                        { name: 'VALKYRIE DASH', type: 'speed', cooldown: 4 },\n                        { name: 'FLASH BURST', type: 'flash', cooldown: 6 }\n                    ]\n                },\n                victory_valtryek: { \n                    speed: 23, power: 25, defense: 12, mass: 1.35, color: '#00ccff', trailId: 'energy_trail_blue', ability: 'spring',\n                    specials: [\n                        { name: 'VICTORY SLASH', type: 'victory_slash', cooldown: 5 },\n                        { name: 'SABER DRIVE', type: 'speed', cooldown: 3 },\n                        { name: 'ULTRA DASH', type: 'overdrive', cooldown: 7 },\n                        { name: 'VALKYRIE BLAST', type: 'shockwave', cooldown: 8 }\n                    ]\n                },\n                genesis_valtryek: { \n                    speed: 24, power: 26, defense: 14, mass: 1.4, color: '#00ffff', trailId: 'energy_trail_blue', ability: 'spring',\n                    specials: [\n                        { name: 'GENESIS WHIP', type: 'flash', cooldown: 4 },\n                        { name: 'GOD REBOOT', type: 'god_reboot', cooldown: 6 },\n                        { name: 'SPRING BLAST', type: 'impact_slash', cooldown: 7 },\n                        { name: 'DIVINE SPEED', type: 'overdrive', cooldown: 8 }\n                    ]\n                },\n                ultimate_valtryek: { \n                    speed: 26, power: 28, defense: 15, mass: 1.5, color: '#0033ff', trailId: 'energy_trail_blue', ability: 'spring',\n                    specials: [\n                        { name: 'ULTIMATE FLASH', type: 'flash', cooldown: 4 },\n                        { name: 'BOUND ATTACK', type: 'bound_attack', cooldown: 6 },\n                        { name: 'ULTRA SLASH', type: 'victory_slash', cooldown: 5 },\n                        { name: 'FINAL REBOOT', type: 'overdrive', cooldown: 10 }\n                    ]\n                },\n                storm_pegasus: { \n                    speed: 22, power: 24, defense: 14, mass: 1.3, color: '#ffffff', trailId: 'energy_trail_blue',\n                    specials: [\n                        { name: 'METEOR SHOWER', type: 'meteor_shower', cooldown: 7 },\n                        { name: 'STORM WING', type: 'attack', cooldown: 4 },\n                        { name: 'GUST BOOST', type: 'speed', cooldown: 4 },\n                        { name: 'STAR PULSE', type: 'shockwave', cooldown: 8 }\n                    ]\n                },\n                galaxy_pegasus: { \n                    speed: 25, power: 26, defense: 16, mass: 1.4, color: '#3399ff', trailId: 'energy_trail_blue',\n                    specials: [\n                        { name: 'STARBLAST ATTACK', type: 'starblast_attack', cooldown: 7 },\n                        { name: 'GALAXY NOVA', type: 'galaxy_nova', cooldown: 5 },\n                        { name: 'COSMIC DRIVE', type: 'overdrive', cooldown: 8 },\n                        { name: 'NEBULA BLAST', type: 'shockwave', cooldown: 9 }\n                    ]\n                },\n                dread_phoenix: { \n                    speed: 12, power: 22, defense: 30, mass: 3.2, color: '#990033', trailId: 'energy_trail_red',\n                    specials: [\n                        { name: 'DREAD ARMOR', type: 'dread_armor', cooldown: 8 },\n                        { name: 'DREAD CANNON', type: 'dread_cannon', cooldown: 6 },\n                        { name: 'DREAD GRAVITY', type: 'dread_gravity', cooldown: 7 },\n                        { name: 'PHOENIX REBIRTH', type: 'stamina_boost', cooldown: 12 }\n                    ]\n                },\n                fafnir: { \n                    speed: 18, power: 20, defense: 22, mass: 1.7, color: '#ffcc00', trailId: 'energy_trail_green', behavior: 'center',\n                    specials: [\n                        { name: 'DRAIN SPIN', type: 'drain_spin', cooldown: 6 },\n                        { name: 'NOTHING BREAK', type: 'nothing_break', cooldown: 4 },\n                        { name: 'MIRAGE CLAW', type: 'attack', cooldown: 5 },\n                        { name: 'SENSE DESTROY', type: 'shockwave', cooldown: 9 }\n                    ]\n                },\n                turbo_achilles: { \n                    speed: 20, power: 32, defense: 22, mass: 2.0, color: '#cc0000', trailId: 'energy_trail_red',\n                    specials: [\n                        { name: 'Z-SHIELD', type: 'guard', cooldown: 5 },\n                        { name: 'TURBO WING', type: 'speed', cooldown: 4 },\n                        { name: 'Z-BUSTER', type: 'impact_slash', cooldown: 7 },\n                        { name: 'TURBO AWAKENING', type: 'overdrive', cooldown: 10 }\n                    ]\n                },\n                xcalius: { \n                    speed: 26, power: 42, defense: 12, mass: 1.6, color: '#0044cc', trailId: 'energy_trail_blue',\n                    specials: [\n                        { name: 'TRIPLE SABER', type: 'triple_saber', cooldown: 5 },\n                        { name: 'IMPACT SLASH', type: 'impact_slash', cooldown: 6 },\n                        { name: 'SWORD PULSE', type: 'shockwave', cooldown: 7 },\n                        { name: 'GRAND IMPACT', type: 'overdrive', cooldown: 9 }\n                    ]\n                }\n            };\n\n            // Asset cache\n            const assetCache = {\n                images: {},\n                audio: {}\n            };\n\n            // Audio context\n            let audioContext = null;\n            const audioBuffers = {};\n\n            // Game state\n            let gameState = 'edit'; // 'edit', 'countdown', 'launch', 'battle', 'result'\n            let isPaused = false;\n            let tops = [];\n            let particles = [];\n            let trails = [];\n            let armorPieces = []; // Detached armor pieces for Dread Phoenix\n            let playerLaunched = false;\n            let playerRetryUsed = false;\n            let lastTime = 0;\n            let gameEndTimestamp = 0;\n            let battleMusicSource = null;\n            \n            // Voice control state\n            let voiceRecognition = null;\n            let isVoiceActive = false;\n            let voiceAvailable = false;\n\n            // Launch state\n            let isAiming = false;\n            let aimStartX = 0;\n            let aimStartY = 0;\n            let aimCurrentX = 0;\n            let aimCurrentY = 0;\n            let launchAngle = -Math.PI / 2;\n            let launchPower = 0;\n\n            // Armor Piece Class for Dread Phoenix\n            class ArmorPiece {\n                constructor(x, y, vx, vy, target, owner) {\n                    this.x = x;\n                    this.y = y;\n                    this.vx = vx;\n                    this.vy = vy;\n                    this.target = target;\n                    this.owner = owner;\n                    this.rotation = 0;\n                    this.life = 300.0; // Stay for the duration of the battle\n                    this.active = true;\n                    this.isHoming = true;\n                    this.isReturning = false;\n                }\n\n                update(deltaTime) {\n                    if (!this.active) return;\n\n                    // Returning logic\n                    if (this.isReturning) {\n                        const dx = this.owner.x - this.x;\n                        const dy = this.owner.y - this.y;\n                        const dist = Math.sqrt(dx * dx + dy * dy);\n                        if (dist > 10) {\n                            const returnSpeed = 35;\n                            this.vx = (dx / dist) * returnSpeed;\n                            this.vy = (dy / dist) * returnSpeed;\n                        } else {\n                            this.active = false;\n                            this.owner.hasArmor = true;\n                            return;\n                        }\n                    } else {\n                        // Homing logic towards target\n                        if (this.isHoming && this.target && this.target.isActive && !this.target.isKnockedOut) {\n                            const dx = this.target.x - this.x;\n                            const dy = this.target.y - this.y;\n                            const dist = Math.sqrt(dx*dx + dy*dy);\n                            if (dist > 0) {\n                                const homingForce = 45;\n                                this.vx += (dx / dist) * homingForce * deltaTime * 60;\n                                this.vy += (dy / dist) * homingForce * deltaTime * 60;\n                            }\n                            \n                            // Collision with target during homing phase\n                            if (dist < TOP_RADIUS * 1.5) {\n                                this.hitTarget();\n                            }\n                        } else if (this.isHoming) {\n                            // If target is gone, find a new one or stop homing\n                            const newTarget = tops.find(t => t !== this.owner && t.isActive && !t.isKnockedOut);\n                            if (newTarget) this.target = newTarget;\n                            else this.isHoming = false;\n                        }\n                    }\n                    \n                    this.x += this.vx * deltaTime * 60;\n                    this.y += this.vy * deltaTime * 60;\n                    \n                    // Friction logic\n                    const friction = (this.isHoming || this.isReturning) ? 0.985 : 0.975;\n                    const frictionFactor = Math.pow(friction, deltaTime * 60);\n                    this.vx *= frictionFactor;\n                    this.vy *= frictionFactor;\n                    this.rotation += 0.3;\n\n                    // Boundary collision (don't bounce out if returning)\n                    const distFromCenter = Math.sqrt(Math.pow(this.x - ARENA_CENTER_X, 2) + Math.pow(this.y - ARENA_CENTER_Y, 2));\n                    const boundaryRadius = ARENA_RADIUS - TOP_RADIUS;\n                    if (distFromCenter > boundaryRadius && !this.isReturning) {\n                        const nx = (this.x - ARENA_CENTER_X) / distFromCenter;\n                        const ny = (this.y - ARENA_CENTER_Y) / distFromCenter;\n                        const dot = this.vx * nx + this.vy * ny;\n                        this.vx -= 2 * dot * nx * 0.8;\n                        this.vy -= 2 * dot * ny * 0.8;\n                        this.x = ARENA_CENTER_X + nx * boundaryRadius;\n                        this.y = ARENA_CENTER_Y + ny * boundaryRadius;\n                        // Stop homing if it hits the wall hard\n                        if (Math.abs(dot) > 5) this.isHoming = false;\n                    }\n\n                    if (!this.isReturning) {\n                        this.life -= deltaTime;\n                        if (this.life <= 0) this.active = false;\n                    }\n                }\n\n                hitTarget() {\n                    if (!this.active || !this.isHoming) return;\n                    \n                    const dx = this.target.x - this.x;\n                    const dy = this.target.y - this.y;\n                    const dist = Math.sqrt(dx*dx + dy*dy);\n                    \n                    if (dist > 0) {\n                        const force = 40;\n                        this.target.vx += (dx / dist) * force;\n                        this.target.vy += (dy / dist) * force;\n                        \n                        // Bounce back armor piece\n                        this.vx = -(dx / dist) * force * 0.4;\n                        this.vy = -(dy / dist) * force * 0.4;\n                    }\n                    \n                    this.target.spinEnergy -= 25;\n                    this.isHoming = false; // Stop chasing after hit\n                    \n                    createCollisionEffect(this.x, this.y, 30);\n                    playSound('collision_sound', 1.0);\n                    createFloatingText(this.target.x, this.target.y - 40, \"DREAD ARMOR HIT!\", '#ff3300');\n                    \n                    gameWorld.classList.add('shake');\n                    setTimeout(() => gameWorld.classList.remove('shake'), 400);\n                }\n\n                draw(ctx) {\n                    if (!this.active) return;\n                    ctx.save();\n                    ctx.translate(this.x, this.y);\n                    ctx.rotate(this.rotation);\n                    ctx.beginPath();\n                    ctx.arc(0, 0, TOP_RADIUS * 1.15, 0, Math.PI * 2);\n                    ctx.strokeStyle = '#990033';\n                    ctx.lineWidth = 8;\n                    ctx.shadowColor = '#ff0000';\n                    ctx.shadowBlur = 20;\n                    ctx.stroke();\n                    // Add some inner details\n                    ctx.beginPath();\n                    ctx.arc(0, 0, TOP_RADIUS * 0.85, 0, Math.PI * 2);\n                    ctx.strokeStyle = '#660022';\n                    ctx.lineWidth = 4;\n                    ctx.stroke();\n                    ctx.restore();\n                }\n            }\n\n            // Initialize canvas\n            function resizeCanvas() {\n                canvas.width = gameWorld.clientWidth;\n                canvas.height = gameWorld.clientHeight;\n            }\n            resizeCanvas();\n            window.addEventListener('resize', resizeCanvas);\n\n            // Audio functions\n            function initAudio() {\n                if (!audioContext) {\n                    audioContext = new (window.AudioContext || window.webkitAudioContext)();\n                }\n            }\n\n            async function loadAudio(id) {\n                const assetInfo = lib.getAsset(id);\n                if (!assetInfo || assetInfo.type !== 'audio') return null;\n\n                try {\n                    const response = await fetch(assetInfo.url);\n                    const arrayBuffer = await response.arrayBuffer();\n                    const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n                    audioBuffers[id] = { buffer: audioBuffer, loop: assetInfo.loop === 'true' };\n                    return audioBuffer;\n                } catch (e) {\n                    lib.log('Failed to load audio: ' + id);\n                    return null;\n                }\n            }\n\n            // Voice functions\n            function speak(text) {\n                if (!window.gameConfig.settings.voiceEnabled || !('speechSynthesis' in window)) return;\n                const utterance = new SpeechSynthesisUtterance(text);\n                utterance.rate = 1.1;\n                utterance.pitch = 1.0;\n                window.speechSynthesis.speak(utterance);\n            }\n\n            function initVoiceRecognition() {\n                const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;\n                if (!SpeechRecognition) {\n                    lib.log('Speech Recognition not supported in this browser.');\n                    return;\n                }\n                \n                voiceAvailable = true;\n                voiceRecognition = new SpeechRecognition();\n                voiceRecognition.continuous = true;\n                voiceRecognition.interimResults = true;\n                voiceRecognition.lang = 'en-US';\n\n                voiceRecognition.onresult = (event) => {\n                    if (!isVoiceActive || gameState !== 'launch' || playerLaunched) return;\n                    \n                    for (let i = event.resultIndex; i < event.results.length; i++) {\n                        const transcript = event.results[i][0].transcript.toLowerCase();\n                        lib.log('Voice heard: ' + transcript);\n                        \n                        if (transcript.includes('rip') || transcript.includes('launch') || transcript.includes('go') || transcript.includes('let')) {\n                            triggerVoiceLaunch();\n                            break;\n                        }\n                    }\n                };\n\n                voiceRecognition.onerror = (event) => {\n                    lib.log('Voice recognition error: ' + event.error);\n                    if (event.error === 'not-allowed') {\n                        isVoiceActive = false;\n                        updateVoiceUI();\n                    }\n                };\n\n                voiceRecognition.onend = () => {\n                    if (isVoiceActive && gameState === 'launch' && !playerLaunched) {\n                        try { voiceRecognition.start(); } catch(e) {}\n                    }\n                };\n            }\n\n            function toggleVoice() {\n                if (!voiceAvailable) {\n                    speak(\"Voice recognition is not supported in your browser.\");\n                    return;\n                }\n\n                initAudio();\n                isVoiceActive = !isVoiceActive;\n                \n                if (isVoiceActive) {\n                    try {\n                        voiceRecognition.start();\n                        speak(\"Voice control activated. Say let it rip to launch!\");\n                    } catch (e) {\n                        lib.log('Voice start error: ' + e);\n                    }\n                } else {\n                    voiceRecognition.stop();\n                    speak(\"Voice control deactivated.\");\n                }\n                \n                updateVoiceUI();\n            }\n\n            function updateVoiceUI() {\n                const btn = document.getElementById('voice-toggle-btn');\n                const status = document.getElementById('voice-status');\n                const container = document.getElementById('voice-btn-container');\n                \n                if (window.gameConfig.settings.voiceEnabled) {\n                    container.style.display = 'flex';\n                } else {\n                    container.style.display = 'none';\n                    if (isVoiceActive) toggleVoice();\n                    return;\n                }\n\n                if (isVoiceActive) {\n                    btn.classList.add('active');\n                    status.classList.add('active');\n                } else {\n                    btn.classList.remove('active');\n                    status.classList.remove('active');\n                }\n            }\n\n            function triggerVoiceLaunch() {\n                if (gameState !== 'launch' || playerLaunched) return;\n                \n                // Trigger launch with high power at current angle or default\n                const playerTop = tops.find(t => t.isPlayer);\n                if (playerTop) {\n                    launchAngle = launchAngle || -Math.PI / 2;\n                    launchPower = 100; // Voice launch is powerful!\n                    \n                    playerTop.x = ARENA_CENTER_X + Math.cos(launchAngle) * (ARENA_RADIUS - TOP_RADIUS - 40);\n                    playerTop.y = ARENA_CENTER_Y + Math.sin(launchAngle) * (ARENA_RADIUS - TOP_RADIUS - 40);\n                    \n                    playerTop.launch(launchAngle + Math.PI, launchPower);\n                    playerLaunched = true;\n                    playSound('launch_sound', 0.8);\n                    \n                    const firstSpecial = playerTop.stats.specials ? playerTop.stats.specials[0] : null;\n                    if (firstSpecial && firstSpecial.type === 'flash') {\n                        document.getElementById('launch-instruction').textContent = 'ULTRA CIRCLE ATTACK!';\n                        document.getElementById('launch-instruction').style.color = '#00ffff';\n                        setTimeout(() => {\n                            document.getElementById('launch-instruction').style.color = '';\n                        }, 2000);\n                    } else {\n                        document.getElementById('launch-instruction').textContent = 'BATTLE!';\n                    }\n                    launchAI();\n                    gameState = 'battle';\n                    \n                    // Stop listening after launch\n                    if (isVoiceActive) {\n                        voiceRecognition.stop();\n                        isVoiceActive = false;\n                        updateVoiceUI();\n                    }\n                }\n            }\n\n            function playSound(id, volume = 1.0, loop = false) {\n                if (!audioContext || !audioBuffers[id]) return null;\n                \n                const source = audioContext.createBufferSource();\n                const gainNode = audioContext.createGain();\n                \n                source.buffer = audioBuffers[id].buffer;\n                source.loop = loop || audioBuffers[id].loop;\n                gainNode.gain.value = volume;\n                \n                source.connect(gainNode);\n                gainNode.connect(audioContext.destination);\n                source.start(0);\n                \n                if (id === 'battle_music') {\n                    battleMusicSource = { source, gainNode };\n                }\n                \n                return { source, gainNode };\n            }\n\n            function stopSound(soundObj) {\n                if (soundObj && soundObj.source) {\n                    try {\n                        soundObj.source.stop();\n                    } catch (e) {}\n                }\n            }\n\n            // Preload assets\n            async function preloadAssets() {\n                const imageIds = [\n                    'top_world_spryzen', 'top_roktavor',\n                    'arena_stadium', 'top_balanced', 'top_attack', 'top_defense', 'top_stamina',\n                    'top_valtryek', 'top_victory_valtryek', 'top_genesis_valtryek', 'top_ultimate_valtryek', \n                    'top_storm_pegasus', 'top_galaxy_pegasus',\n                    'top_dread_phoenix', 'top_xcalius', 'top_fafnir', 'top_turbo_achilles',\n                    'spring_attack_fx',\n                    'energy_trail_blue', 'energy_trail_red', 'energy_trail_green',\n                    'collision_spark', 'background_arena', 'launch_button', 'retry_button'\n                ];\n\n                const audioIds = [\n                    'launch_sound', 'collision_sound', 'spinning_loop',\n                    'knockout_sound', 'victory_fanfare', 'battle_music', 'countdown_beep',\n                    'voice_let_it_rip'\n                ];\n\n                // Load images\n                const imagePromises = imageIds.map(id => {\n                    return new Promise((resolve) => {\n                        const assetInfo = lib.getAsset(id);\n                        if (assetInfo && assetInfo.type === 'image') {\n                            const img = new Image();\n                            img.onload = () => {\n                                assetCache.images[id] = img;\n                                resolve();\n                            };\n                            img.onerror = () => {\n                                lib.log('Failed to load image: ' + id);\n                                resolve();\n                            };\n                            img.src = assetInfo.url;\n                        } else {\n                            resolve();\n                        }\n                    });\n                });\n\n                await Promise.all(imagePromises);\n\n                // Initialize audio context on user interaction\n                initAudio();\n\n                // Load audio\n                for (const id of audioIds) {\n                    await loadAudio(id);\n                }\n\n                // Set background\n                const bgAsset = lib.getAsset('background_arena');\n                if (bgAsset) {\n                    document.getElementById('background').src = bgAsset.url;\n                }\n\n                // Set retry button image\n                const retryAsset = lib.getAsset('retry_button');\n                if (retryAsset) {\n                    document.getElementById('retry-img').src = retryAsset.url;\n                }\n            }\n\n            // Initialize game parameters\n            function setupGameParameters() {\n                lib.showGameParameters({\n                    name: 'Beyblade',\n                    params: {\n                        'Voice Features': {\n                            key: 'settings.voiceEnabled',\n                            type: 'checkbox',\n                            onChange: (val) => {\n                                window.gameConfig.settings.voiceEnabled = val;\n                                updateVoiceUI();\n                                if (val) speak(\"Voice features enabled.\");\n                            }\n                        },\n                        'AI Difficulty': {\n                            key: 'settings.difficulty',\n                            type: 'dropdown',\n                            options: [\n                                { label: 'Easy', value: 'easy' },\n                                { label: 'Medium', value: 'medium' },\n                                { label: 'Hard', value: 'hard' }\n                            ]\n                        }\n                    }\n                });\n            }\n\n            // Top class\n            class Top {\n                constructor(type, name, x, y, isPlayer = false, primaryColor = null) {\n                    this.type = type;\n                    this.name = name;\n                    this.stats = { ...TOP_STATS[type] };\n                    \n                    // Apply part modifiers if player\n                    if (isPlayer) {\n                        const weight = window.gameConfig.playerTop.weightType || 'standard';\n                        const height = window.gameConfig.playerTop.heightType || 'standard';\n                        \n                        if (weight === 'heavy') {\n                            this.stats.mass *= 1.4;\n                            this.stats.defense += 3;\n                            this.stats.speed -= 2;\n                        }\n                        \n                        if (height === 'low') {\n                            this.stats.defense += 2;\n                            this.stats.speed -= 1;\n                            this.isLowProfile = true;\n                        } else if (height === 'high') {\n                            this.stats.speed += 2;\n                            this.stats.power += 2;\n                            this.isHighProfile = true;\n                        }\n                    }\n\n                    this.x = x;\n                    this.y = y;\n                    this.vx = 0;\n                    this.vy = 0;\n                    this.spinEnergy = 100;\n                    this.rotation = 0;\n                    this.isPlayer = isPlayer;\n                    this.isActive = false;\n                    this.isKnockedOut = false;\n                    this.isBurst = false;\n                    this.burstPieces = [];\n                    this.primaryColor = primaryColor || this.stats.color;\n                    this.trailTimer = 0;\n                    this.abilityCooldown = 0;\n                    this.specialCooldowns = this.stats.specials ? this.stats.specials.map(() => 0) : [];\n                    this.isSpringing = false;\n                    this.rushLaunchTimer = 0;\n                    this.ultraFlashTimer = 0;\n                    this.counterTimer = 0;\n                    this.zoneTimer = 0;\n                    this.jumpTimer = 0;\n                    this.guardTimer = 0;\n                    this.scale = (type === 'xcalius' || type === 'dread_phoenix') ? 1.15 : 1.0;\n                    this.lastBoundaryHitTime = 0;\n                    this.aiAttackTimer = 3 + Math.random() * 4;\n                    this.aiSpecialTimer = 8 + Math.random() * 10;\n                    this.hasArmor = (type === 'dread_phoenix');\n                }\n\n                launch(angle, power) {\n                    const speed = (power / 100) * MAX_SPEED * (this.stats.speed / 5);\n                    this.vx = Math.cos(angle) * speed;\n                    this.vy = Math.sin(angle) * speed;\n                    this.isActive = true;\n                    this.isBurst = false;\n                    this.isKnockedOut = false;\n                    this.burstPieces = [];\n                    \n                    const firstSpecial = this.stats.specials ? this.stats.specials[0] : null;\n                    if (firstSpecial && firstSpecial.type === 'flash' && power > 70) {\n                        this.ultraFlashTimer = 3.0;\n                        this.vx *= 1.4;\n                        this.vy *= 1.4;\n                    }\n                }\n\n                burst() {\n                    if (this.isBurst) return;\n                    this.isBurst = true;\n                    this.isActive = false;\n                    this.isKnockedOut = true;\n                    this.spinEnergy = 0;\n                    \n                    // Create burst fragments\n                    for (let i = 0; i < 3; i++) {\n                        const angle = (Math.PI * 2 / 3) * i;\n                        this.burstPieces.push({\n                            x: 0,\n                            y: 0,\n                            vx: Math.cos(angle) * 8 + (Math.random() - 0.5) * 4,\n                            vy: Math.sin(angle) * 8 + (Math.random() - 0.5) * 4,\n                            rotation: angle,\n                            rv: (Math.random() - 0.5) * 0.4\n                        });\n                    }\n                    \n                    playSound('knockout_sound', 1.0);\n                    createCollisionEffect(this.x, this.y, 15);\n                    createFloatingText(this.x, this.y - 60, \"BURST FINISH!\", '#ff3300');\n                    \n                    // Banner effect for player or AI burst\n                    const banner = document.getElementById('special-banner');\n                    const bannerName = document.getElementById('special-banner-name');\n                    const bannerType = document.getElementById('special-banner-type');\n                    bannerName.textContent = \"BURST FINISH!\";\n                    bannerType.textContent = this.name.toUpperCase();\n                    banner.classList.add('active');\n                    setTimeout(() => banner.classList.remove('active'), 2000);\n\n                    gameWorld.classList.add('shake');\n                    setTimeout(() => gameWorld.classList.remove('shake'), 500);\n                }\n\n                update(deltaTime) {\n                    if (this.isBurst) {\n                        this.burstPieces.forEach(p => {\n                            p.x += p.vx * deltaTime * 60;\n                            p.y += p.vy * deltaTime * 60;\n                            p.rotation += p.rv * deltaTime * 60;\n                            p.vx *= 0.97;\n                            p.vy *= 0.97;\n                        });\n                        return;\n                    }\n\n                    if (!this.isActive || this.isKnockedOut) return;\n\n                    if (this.abilityCooldown > 0) this.abilityCooldown -= deltaTime;\n                    \n                    if (this.specialCooldowns) {\n                        for (let i = 0; i < this.specialCooldowns.length; i++) {\n                            if (this.specialCooldowns[i] > 0) this.specialCooldowns[i] -= deltaTime;\n                        }\n                    }\n                    \n                    // AI Logic\n                    if (!this.isPlayer && this.isActive && !this.isKnockedOut && gameState === 'battle') {\n                        if (this.aiAttackTimer > 0) {\n                            this.aiAttackTimer -= deltaTime;\n                        } else {\n                            const playerTop = tops.find(t => t.isPlayer && t.isActive && !t.isKnockedOut);\n                            if (playerTop) {\n                                const dx = playerTop.x - this.x;\n                                const dy = playerTop.y - this.y;\n                                const dist = Math.sqrt(dx * dx + dy * dy);\n                                if (dist > 0) {\n                                    const difficulty = window.gameConfig.settings.difficulty || 'medium';\n                                    const boost = { easy: 10, medium: 16, hard: 22 }[difficulty];\n                                    this.vx += (dx / dist) * boost * 0.4;\n                                    this.vy += (dy / dist) * boost * 0.4;\n                                    this.aiAttackTimer = 3 + Math.random() * 4;\n                                }\n                            }\n                        }\n\n                        if (this.aiSpecialTimer > 0) {\n                            this.aiSpecialTimer -= deltaTime;\n                        } else {\n                            const moveCount = this.stats.specials ? this.stats.specials.length : 0;\n                            if (moveCount > 0) {\n                                triggerSpecialMove(this, Math.floor(Math.random() * moveCount));\n                            }\n                            const difficulty = window.gameConfig.settings.difficulty || 'medium';\n                            this.aiSpecialTimer = { easy: 15, medium: 10, hard: 7 }[difficulty] + Math.random() * 5;\n                        }\n                    }\n                    \n                    // Update special timers\n                    if (this.counterTimer > 0) this.counterTimer -= deltaTime;\n                    if (this.zoneTimer > 0) {\n                        this.zoneTimer -= deltaTime;\n                        this.spinEnergy = Math.min(100, this.spinEnergy + 5 * deltaTime);\n                    }\n                    if (this.guardTimer > 0) this.guardTimer -= deltaTime;\n                    if (this.jumpTimer > 0) {\n                        this.jumpTimer -= deltaTime;\n                        this.scale = 1.0 + Math.sin(Math.PI * (this.jumpTimer / 1.2)) * 1.5;\n                        if (this.jumpTimer <= 0) {\n                            this.scale = 1.0;\n                            createCollisionEffect(this.x, this.y, 10);\n                            playSound('collision_sound', 1.0);\n                            gameWorld.classList.add('shake');\n                            setTimeout(() => gameWorld.classList.remove('shake'), 400);\n                            createFloatingText(this.x, this.y - 50, \"METEOR!\", this.primaryColor);\n                        }\n                    }\n\n                    // Ultra Flash Logic\n                    if (this.ultraFlashTimer > 0) {\n                        this.ultraFlashTimer -= deltaTime;\n                        const speed = Math.sqrt(this.vx * this.vx + this.vy * this.vy);\n                        let target = null;\n                        let minDist = Infinity;\n                        tops.forEach(t => {\n                            if (t !== this && t.isActive && !t.isKnockedOut) {\n                                const d = Math.sqrt((t.x - this.x)**2 + (t.y - this.y)**2);\n                                if (d < minDist) { minDist = d; target = t; }\n                            }\n                        });\n\n                        if (speed > 1) {\n                            const perpX = -this.vy / speed;\n                            const perpY = this.vx / speed;\n                            const circleForce = 45; \n                            const timeScale = Date.now() / 100;\n                            this.vx += (perpX * Math.sin(timeScale) * circleForce) * deltaTime * 60;\n                            this.vy += (perpY * Math.sin(timeScale) * circleForce) * deltaTime * 60;\n                            \n                            if (target) {\n                                const tdx = target.x - this.x;\n                                const tdy = target.y - this.y;\n                                const tdist = Math.sqrt(tdx * tdx + tdy * tdy);\n                                if (tdist > 0) {\n                                    const homingPower = 18;\n                                    this.vx += (tdx / tdist) * homingPower * deltaTime * 60;\n                                    this.vy += (tdy / tdist) * homingPower * deltaTime * 60;\n                                }\n                            }\n                        }\n                        if (Math.random() < 0.3) createCollisionEffect(this.x, this.y, 2);\n                    }\n\n                    // Stamina Center seeking\n                    if ((this.stats.behavior === 'center' || this.zoneTimer > 0) && !this.isSpringing && this.jumpTimer <= 0) {\n                        const dx = ARENA_CENTER_X - this.x;\n                        const dy = ARENA_CENTER_Y - this.y;\n                        const dist = Math.sqrt(dx * dx + dy * dy);\n                        if (dist > 10) {\n                            const pull = (this.zoneTimer > 0) ? 0.35 : 0.12;\n                            this.vx += (dx / dist) * pull * deltaTime * 60;\n                            this.vy += (dy / dist) * pull * deltaTime * 60;\n                        } else {\n                            const damp = Math.pow(0.9, deltaTime * 60);\n                            this.vx *= damp;\n                            this.vy *= damp;\n                        }\n                    }\n\n                    // Movement and Rotation\n                    const speed = Math.sqrt(this.vx * this.vx + this.vy * this.vy);\n                    this.rotation += speed * 0.1 + (this.spinEnergy / 100) * 0.25;\n\n                    let currentFriction = FRICTION;\n                    if (this.zoneTimer > 0 || this.guardTimer > 0) currentFriction = 0.985;\n                    const frictionFactor = Math.pow(currentFriction, deltaTime * 60);\n                    this.vx *= frictionFactor;\n                    this.vy *= frictionFactor;\n\n                    const maxS = (this.ultraFlashTimer > 0 || this.jumpTimer > 0) ? MAX_SPEED * 1.6 : MAX_SPEED * 1.3;\n                    const currentS = Math.sqrt(this.vx * this.vx + this.vy * this.vy);\n                    if (currentS > maxS) {\n                        this.vx = (this.vx / currentS) * maxS;\n                        this.vy = (this.vy / currentS) * maxS;\n                    }\n\n                    if (this.jumpTimer <= 0) {\n                        this.x += this.vx * deltaTime * 60;\n                        this.y += this.vy * deltaTime * 60;\n                    }\n\n                    // Spin decay\n                    let decayRate = SPIN_DECAY;\n                    if (this.type === 'stamina' || this.type === 'roktavor') decayRate *= 0.6;\n                    \n                    // Height modifier for stamina\n                    if (this.isLowProfile) decayRate *= 0.85;\n                    if (this.isHighProfile) decayRate *= 1.1;\n\n                    if (this.ultraFlashTimer > 0) decayRate *= 1.6;\n                    this.spinEnergy -= decayRate * deltaTime * 60;\n                    if (this.spinEnergy <= 0) {\n                        this.spinEnergy = 0;\n                        this.burst();\n                    }\n\n                    // Boundary collision\n                    const distFromCenter = Math.sqrt(Math.pow(this.x - ARENA_CENTER_X, 2) + Math.pow(this.y - ARENA_CENTER_Y, 2));\n                    const boundaryRadius = ARENA_RADIUS - TOP_RADIUS;\n                    if (distFromCenter > boundaryRadius && this.jumpTimer <= 0) {\n                        const currentTopSpeed = Math.sqrt(this.vx * this.vx + this.vy * this.vy);\n                        if (currentTopSpeed > (this.isPlayer ? MIN_KNOCKOUT_SPEED : MIN_KNOCKOUT_SPEED * 1.6) && distFromCenter > KNOCKOUT_DISTANCE) {\n                            this.isKnockedOut = true; this.isActive = false;\n                            playSound('knockout_sound', 0.8); return;\n                        }\n                        const nx = (this.x - ARENA_CENTER_X) / distFromCenter;\n                        const ny = (this.y - ARENA_CENTER_Y) / distFromCenter;\n                        if (this.stats.ability === 'spring' && this.abilityCooldown <= 0 && this.spinEnergy > 20) {\n                            this.isSpringing = true; this.abilityCooldown = 1.5;\n                            const b = 15; this.vx = -nx * b; this.vy = -ny * b;\n                            playSound('launch_sound', 0.8); createCollisionEffect(this.x, this.y, 6);\n                            setTimeout(() => { this.isSpringing = false; }, 400);\n                        } else {\n                            const dot = this.vx * nx + this.vy * ny;\n                            this.vx -= 2 * dot * nx * 0.8; this.vy -= 2 * dot * ny * 0.8;\n                        }\n                        this.x = ARENA_CENTER_X + nx * boundaryRadius;\n                        this.y = ARENA_CENTER_Y + ny * boundaryRadius;\n                        this.spinEnergy -= 0.5;\n                    }\n\n                    this.trailTimer += deltaTime;\n                    if (this.trailTimer > 0.03 && speed > 1 && this.spinEnergy > 10) {\n                        this.trailTimer = 0;\n                        trails.push({\n                            x: this.x, y: this.y,\n                            rotation: Math.atan2(this.vy, this.vx) + Math.PI,\n                            alpha: 0.6 * (this.spinEnergy / 100), life: 0.3,\n                            trailId: this.stats.trailId\n                        });\n                    }\n                }\n\n                draw(ctx) {\n                    if (this.isBurst) {\n                        const imgId = 'top_' + this.type;\n                        const img = assetCache.images[imgId];\n                        if (!img) return;\n\n                        this.burstPieces.forEach((p, i) => {\n                            ctx.save();\n                            ctx.translate(this.x + p.x, this.y + p.y);\n                            ctx.rotate(p.rotation);\n                            \n                            const size = TOP_RADIUS * 2.2;\n                            \n                            // Clip the image into pieces\n                            ctx.beginPath();\n                            ctx.moveTo(0, 0);\n                            const startAngle = (Math.PI * 2 / 3) * i;\n                            const endAngle = (Math.PI * 2 / 3) * (i + 1);\n                            ctx.arc(0, 0, size, startAngle, endAngle);\n                            ctx.closePath();\n                            ctx.clip();\n                            \n                            ctx.drawImage(img, -size/2, -size/2, size, size);\n                            ctx.restore();\n                        });\n                        return;\n                    }\n\n                    if (this.isKnockedOut) return;\n\n                    ctx.save();\n                    ctx.translate(this.x, this.y);\n                    if (this.scale !== undefined) ctx.scale(this.scale, this.scale);\n                    ctx.rotate(this.rotation);\n\n                    const imgId = 'top_' + this.type;\n                    const img = assetCache.images[imgId];\n                    \n                    if (img) {\n                        const assetInfo = lib.getAsset(imgId);\n                        let drawWidth = TOP_RADIUS * 2.2;\n                        let drawHeight = TOP_RADIUS * 2.2;\n                        \n                        if (assetInfo && assetInfo.aspect_ratio) {\n                            const aspectRatio = assetInfo.aspect_ratio[0] / assetInfo.aspect_ratio[1];\n                            if (aspectRatio > 1) drawHeight = drawWidth / aspectRatio;\n                            else drawWidth = drawHeight * aspectRatio;\n                        }\n\n                        const glowIntensity = this.spinEnergy / 100;\n                        ctx.shadowColor = this.primaryColor;\n                        ctx.shadowBlur = (this.isSpringing || this.ultraFlashTimer > 0 || this.counterTimer > 0 ? 50 : 25) * glowIntensity;\n                        \n                        // Draw Armor if present\n                        if (this.hasArmor) {\n                            ctx.save();\n                            ctx.beginPath();\n                            ctx.arc(0, 0, TOP_RADIUS * 1.1, 0, Math.PI * 2);\n                            ctx.strokeStyle = '#660022';\n                            ctx.lineWidth = 8;\n                            ctx.stroke();\n                            ctx.restore();\n                        }\n\n                        ctx.drawImage(img, -drawWidth/2, -drawHeight/2, drawWidth, drawHeight);\n\n                        // Enhance Xcalius Shape with a sword-like aura\n                        if (this.type === 'xcalius') {\n                            ctx.save();\n                            ctx.globalCompositeOperation = 'lighter';\n                            ctx.strokeStyle = '#00ccff';\n                            ctx.lineWidth = 6;\n                            ctx.shadowColor = '#00ffff';\n                            ctx.shadowBlur = 25;\n                            \n                            // Draw a sharp sword shape overlay\n                            ctx.beginPath();\n                            ctx.moveTo(0, -TOP_RADIUS * 2.2); // Point of the sword\n                            ctx.lineTo(TOP_RADIUS * 0.5, -TOP_RADIUS * 0.6);\n                            ctx.lineTo(TOP_RADIUS * 1.0, -TOP_RADIUS * 0.6);\n                            ctx.lineTo(0, TOP_RADIUS * 1.5); // Pommel\n                            ctx.lineTo(-TOP_RADIUS * 1.0, -TOP_RADIUS * 0.6);\n                            ctx.lineTo(-TOP_RADIUS * 0.5, -TOP_RADIUS * 0.6);\n                            ctx.closePath();\n                            \n                            ctx.globalAlpha = 0.5 + Math.sin(Date.now() / 150) * 0.3;\n                            if (this.ultraFlashTimer > 0 || this.isSpringing) {\n                                ctx.globalAlpha = 1.0;\n                                ctx.scale(1.3, 1.3);\n                            }\n                            \n                            ctx.fillStyle = 'rgba(0, 204, 255, 0.5)';\n                            ctx.fill();\n                            ctx.stroke();\n                            \n                            // Add extra blade light\n                            ctx.beginPath();\n                            ctx.moveTo(0, -TOP_RADIUS * 2.2);\n                            ctx.lineTo(0, TOP_RADIUS * 1.5);\n                            ctx.strokeStyle = '#ffffff';\n                            ctx.lineWidth = 2;\n                            ctx.stroke();\n                            ctx.restore();\n                        }\n\n                        if (this.isSpringing || this.ultraFlashTimer > 0 || this.jumpTimer > 0) {\n                            const springImg = assetCache.images['spring_attack_fx'];\n                            if (springImg) {\n                                ctx.save();\n                                ctx.rotate(Date.now() / 80);\n                                ctx.globalAlpha = 0.7;\n                                ctx.drawImage(springImg, -drawWidth, -drawHeight, drawWidth * 2, drawHeight * 2);\n                                ctx.restore();\n                            }\n                        }\n                        \n                        if (this.guardTimer > 0) {\n                            ctx.beginPath();\n                            ctx.arc(0, 0, TOP_RADIUS * 1.5, 0, Math.PI * 2);\n                            ctx.strokeStyle = this.primaryColor;\n                            ctx.lineWidth = 4;\n                            ctx.globalAlpha = 0.5 + Math.sin(Date.now() / 100) * 0.2;\n                            ctx.stroke();\n                        }\n                        \n                        if (this.zoneTimer > 0) {\n                            ctx.beginPath();\n                            ctx.arc(0, 0, 150, 0, Math.PI * 2);\n                            ctx.fillStyle = this.primaryColor + '22';\n                            ctx.fill();\n                            ctx.strokeStyle = this.primaryColor;\n                            ctx.lineWidth = 2;\n                            ctx.setLineDash([10, 10]);\n                            ctx.stroke();\n                        }\n                    } else {\n                        ctx.beginPath();\n                        ctx.arc(0, 0, TOP_RADIUS, 0, Math.PI * 2);\n                        ctx.fillStyle = this.primaryColor;\n                        ctx.fill();\n                    }\n                    ctx.restore();\n                }\n            }\n\n            // Collision detection and response\n            function handleCollisions() {\n                for (let i = 0; i < tops.length; i++) {\n                    for (let j = i + 1; j < tops.length; j++) {\n                        const t1 = tops[i];\n                        const t2 = tops[j];\n\n                        if (!t1.isActive || !t2.isActive || t1.isKnockedOut || t2.isKnockedOut) continue;\n\n                        const dx = t2.x - t1.x;\n                        const dy = t2.y - t1.y;\n                        const dist = Math.sqrt(dx * dx + dy * dy);\n                        const minDist = TOP_RADIUS * 2;\n\n                        if (dist < minDist && dist > 0) {\n                            // Collision!\n                            const nx = dx / dist;\n                            const ny = dy / dist;\n\n                            // Relative velocity\n                            const dvx = t1.vx - t2.vx;\n                            const dvy = t1.vy - t2.vy;\n                            const dvn = dvx * nx + dvy * ny;\n                            const impactSpeed = Math.abs(dvn);\n\n                            // Only resolve if approaching\n                            if (dvn > 0) {\n                                // Mass-based collision response\n                                const m1 = t1.stats.mass;\n                                const m2 = t2.stats.mass;\n                                const restitution = 0.8;\n\n                                const j = (-(1 + restitution) * dvn) / (1/m1 + 1/m2);\n\n                                t1.vx += (j / m1) * nx;\n                                t1.vy += (j / m1) * ny;\n                                t2.vx -= (j / m2) * nx;\n                                t2.vy -= (j / m2) * ny;\n\n                                // Energy loss based on defense stat\n                                const t1Loss = COLLISION_ENERGY_LOSS * (1 - t1.stats.defense / 20);\n                                const t2Loss = COLLISION_ENERGY_LOSS * (1 - t2.stats.defense / 20);\n                                \n                                // Counter Logic\n                                if (t1.counterTimer > 0) {\n                                    t2.vx -= (j / m2) * nx * 7.5;\n                                    t2.vy -= (j / m2) * ny * 7.5;\n                                    t2.spinEnergy -= 40;\n                                    createFloatingText(t1.x, t1.y - 40, \"WORLD COUNTER!\", t1.primaryColor);\n                                    createCollisionEffect(t1.x, t1.y, 35);\n                                    gameWorld.classList.add('shake');\n                                    setTimeout(() => gameWorld.classList.remove('shake'), 400);\n                                }\n                                if (t2.counterTimer > 0) {\n                                    t1.vx += (j / m1) * nx * 7.5;\n                                    t1.vy += (j / m1) * ny * 7.5;\n                                    t1.spinEnergy -= 40;\n                                    createFloatingText(t2.x, t2.y - 40, \"WORLD COUNTER!\", t2.primaryColor);\n                                    createCollisionEffect(t2.x, t2.y, 35);\n                                    gameWorld.classList.add('shake');\n                                    setTimeout(() => gameWorld.classList.remove('shake'), 400);\n                                }\n\n                                t1.spinEnergy -= t1Loss;\n                                t2.spinEnergy -= t2Loss;\n\n                                // Dread Armor Detachment Logic\n                                if (t1.type === 'dread_phoenix' && t1.hasArmor && impactSpeed > 8) {\n                                    t1.hasArmor = false;\n                                    createFloatingText(t1.x, t1.y - 60, \"ARMOR DETACH!\", t1.primaryColor);\n                                    const armorPiece = new ArmorPiece(t1.x, t1.y, -nx * 10, -ny * 10, t2, t1);\n                                    armorPieces.push(armorPiece);\n                                    playSound('launch_sound', 1.0);\n                                }\n                                if (t2.type === 'dread_phoenix' && t2.hasArmor && impactSpeed > 8) {\n                                    t2.hasArmor = false;\n                                    createFloatingText(t2.x, t2.y - 60, \"ARMOR DETACH!\", t2.primaryColor);\n                                    const armorPiece = new ArmorPiece(t2.x, t2.y, nx * 10, ny * 10, t1, t2);\n                                    armorPieces.push(armorPiece);\n                                    playSound('launch_sound', 1.0);\n                                }\n\n                                // Burst Chance logic\n                                if (t1.spinEnergy <= 0) t1.burst();\n                                else if (impactSpeed > 20 && t1.spinEnergy < 20 && Math.random() < 0.3) t1.burst();\n                                \n                                if (t2.spinEnergy <= 0) t2.burst();\n                                else if (impactSpeed > 20 && t2.spinEnergy < 20 && Math.random() < 0.3) t2.burst();\n\n                                // Separate tops\n                                const overlap = minDist - dist;\n                                const separateX = (overlap / 2) * nx;\n                                const separateY = (overlap / 2) * ny;\n                                t1.x -= separateX;\n                                t1.y -= separateY;\n                                t2.x += separateX;\n                                t2.y += separateY;\n\n                                // Create collision effect\n                                if (impactSpeed > 2) {\n                                    createCollisionEffect((t1.x + t2.x) / 2, (t1.y + t2.y) / 2, impactSpeed);\n                                    playSound('collision_sound', Math.min(impactSpeed / 10, 0.8));\n                                    \n                                    if (impactSpeed > 10) {\n                                        const words = ['K-POW!', 'SLAM!', 'CRASH!', 'BOOM!'];\n                                        const word = words[Math.floor(Math.random() * words.length)];\n                                        createFloatingText((t1.x + t2.x) / 2, (t1.y + t2.y) / 2 - 40, word, '#ffcc00');\n                                    }\n\n                                    // Screen shake\n                                    if (impactSpeed > 5) {\n                                        gameWorld.classList.add('shake');\n                                        setTimeout(() => gameWorld.classList.remove('shake'), 300);\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // Top to Armor Piece Collisions\n                for (let i = 0; i < tops.length; i++) {\n                    const top = tops[i];\n                    if (!top.isActive || top.isKnockedOut) continue;\n\n                    for (let j = 0; j < armorPieces.length; j++) {\n                        const armor = armorPieces[j];\n                        if (!armor.active) continue;\n\n                        const dx = armor.x - top.x;\n                        const dy = armor.y - top.y;\n                        const dist = Math.sqrt(dx * dx + dy * dy);\n                        const minDist = TOP_RADIUS + (TOP_RADIUS * 1.1);\n\n                        if (dist < minDist && dist > 0) {\n                            const nx = dx / dist;\n                            const ny = dy / dist;\n                            const dvx = top.vx - armor.vx;\n                            const dvy = top.vy - armor.vy;\n                            const dvn = dvx * nx + dvy * ny;\n\n                            if (dvn > 0) {\n                                const m1 = top.stats.mass;\n                                const m2 = 4.0; \n                                const restitution = 0.6;\n                                const j = (-(1 + restitution) * dvn) / (1/m1 + 1/m2);\n\n                                top.vx += (j / m1) * nx;\n                                top.vy += (j / m1) * ny;\n                                armor.vx -= (j / m2) * nx;\n                                armor.vy -= (j / m2) * ny;\n\n                                top.spinEnergy -= 2;\n                                \n                                // Armor Kicking Mechanic\n                                if (top.isPlayer || top.isActive) {\n                                    // Find target for armor to hit (other beyblade)\n                                    const otherTarget = tops.find(t => t !== top && t.isActive && !t.isKnockedOut);\n                                    if (otherTarget) {\n                                        armor.target = otherTarget;\n                                        armor.isHoming = true;\n                                        // Give armor extra speed towards the target\n                                        const boost = 25;\n                                        const tx = otherTarget.x - armor.x;\n                                        const ty = otherTarget.y - armor.y;\n                                        const tdist = Math.sqrt(tx*tx + ty*ty);\n                                        if (tdist > 0) {\n                                            armor.vx += (tx / tdist) * boost;\n                                            armor.vy += (ty / tdist) * boost;\n                                        }\n                                        createFloatingText(armor.x, armor.y - 40, \"ARMOR KICK!\", top.primaryColor);\n                                    }\n                                }\n\n                                createCollisionEffect(armor.x, armor.y, 10);\n                                playSound('collision_sound', 0.4);\n                            }\n                            \n                            const overlap = minDist - dist;\n                            top.x -= (overlap / 2) * nx;\n                            top.y -= (overlap / 2) * ny;\n                            armor.x += (overlap / 2) * nx;\n                            armor.y += (overlap / 2) * ny;\n                        }\n                    }\n                }\n            }\n\n            // Particle effects\n            function createCollisionEffect(x, y, intensity) {\n                particles.push({\n                    x: x,\n                    y: y,\n                    scale: 0.5 + intensity * 0.1,\n                    alpha: 1,\n                    life: 0.3\n                });\n            }\n\n            let floatingTexts = [];\n\n            // ... (rest of the vars)\n\n            function createFloatingText(x, y, text, color = '#ffffff') {\n                floatingTexts.push({\n                    x, y, text, color,\n                    life: 1.0,\n                    vy: -1.5\n                });\n            }\n\n            function updateParticles(deltaTime) {\n                particles = particles.filter(p => {\n                    p.life -= deltaTime;\n                    p.alpha = p.life / 0.3;\n                    return p.life > 0;\n                });\n\n                trails = trails.filter(t => {\n                    t.life -= deltaTime;\n                    t.alpha *= 0.9;\n                    return t.life > 0;\n                });\n\n                floatingTexts = floatingTexts.filter(ft => {\n                    ft.life -= deltaTime;\n                    ft.y += ft.vy;\n                    return ft.life > 0;\n                });\n\n                armorPieces.forEach(ap => ap.update(deltaTime));\n                armorPieces = armorPieces.filter(ap => ap.active);\n            }\n\n            function drawParticles(ctx) {\n                // Draw trails\n                trails.forEach(t => {\n                    const img = assetCache.images[t.trailId];\n                    if (img) {\n                        ctx.save();\n                        ctx.translate(t.x, t.y);\n                        ctx.rotate(t.rotation);\n                        ctx.globalAlpha = t.alpha;\n                        ctx.drawImage(img, -TOP_RADIUS, -TOP_RADIUS/2, TOP_RADIUS*2, TOP_RADIUS);\n                        ctx.restore();\n                    }\n                });\n\n                // Draw armor pieces\n                armorPieces.forEach(ap => ap.draw(ctx));\n\n                // Draw sparks\n                particles.forEach(p => {\n                    const img = assetCache.images['collision_spark'];\n                    if (img) {\n                        ctx.save();\n                        ctx.translate(p.x, p.y);\n                        ctx.globalAlpha = p.alpha;\n                        ctx.scale(p.scale, p.scale);\n                        ctx.drawImage(img, -TOP_RADIUS, -TOP_RADIUS, TOP_RADIUS * 2, TOP_RADIUS * 2);\n                        ctx.restore();\n                    }\n                });\n                \n                // Draw floating texts\n                floatingTexts.forEach(ft => {\n                    ctx.save();\n                    ctx.font = '900 28px Orbitron';\n                    ctx.fillStyle = ft.color;\n                    ctx.textAlign = 'center';\n                    ctx.globalAlpha = ft.life;\n                    ctx.shadowColor = '#000000';\n                    ctx.shadowBlur = 4;\n                    ctx.fillText(ft.text, ft.x, ft.y);\n                    ctx.restore();\n                });\n            }\n\n            // UI Updates\n            function updateStatsUI() {\n                const container = document.getElementById('stats-container');\n                container.innerHTML = '';\n\n                tops.forEach(top => {\n                    const statDiv = document.createElement('div');\n                    statDiv.className = 'top-stat';\n                    \n                    const nameDiv = document.createElement('div');\n                    nameDiv.className = 'top-stat-name';\n                    nameDiv.textContent = top.name;\n                    nameDiv.style.color = top.primaryColor;\n                    \n                    const barContainer = document.createElement('div');\n                    barContainer.className = 'spin-bar-container';\n                    \n                    const bar = document.createElement('div');\n                    bar.className = 'spin-bar';\n                    bar.style.width = (top.isKnockedOut ? 0 : top.spinEnergy) + '%';\n                    bar.style.background = top.isKnockedOut ? '#666' : \n                        `linear-gradient(90deg, ${top.primaryColor}, ${top.primaryColor}88)`;\n                    \n                    barContainer.appendChild(bar);\n                    statDiv.appendChild(nameDiv);\n                    statDiv.appendChild(barContainer);\n                    container.appendChild(statDiv);\n                });\n            }\n\n            // Launch trajectory drawing\n            function drawLaunchTrajectory(ctx) {\n                if (!isAiming || gameState !== 'launch') return;\n\n                const startX = ARENA_CENTER_X + Math.cos(launchAngle) * (ARENA_RADIUS - TOP_RADIUS - 20);\n                const startY = ARENA_CENTER_Y + Math.sin(launchAngle) * (ARENA_RADIUS - TOP_RADIUS - 20);\n\n                // Draw trajectory line\n                const lineLength = 100 + launchPower;\n                const endX = startX + Math.cos(launchAngle + Math.PI) * lineLength;\n                const endY = startY + Math.sin(launchAngle + Math.PI) * lineLength;\n\n                ctx.save();\n                ctx.strokeStyle = `rgba(255, 255, 255, ${0.5 + (launchPower / 200)})`;\n                ctx.lineWidth = 4;\n                ctx.setLineDash([10, 5]);\n                ctx.lineDashOffset = -Date.now() / 50;\n                \n                ctx.beginPath();\n                ctx.moveTo(startX, startY);\n                ctx.lineTo(endX, endY);\n                ctx.stroke();\n\n                // Arrow head\n                ctx.setLineDash([]);\n                ctx.fillStyle = '#ffffff';\n                const arrowSize = 15;\n                const arrowAngle = launchAngle + Math.PI;\n                ctx.beginPath();\n                ctx.moveTo(endX, endY);\n                ctx.lineTo(\n                    endX - arrowSize * Math.cos(arrowAngle - 0.4),\n                    endY - arrowSize * Math.sin(arrowAngle - 0.4)\n                );\n                ctx.lineTo(\n                    endX - arrowSize * Math.cos(arrowAngle + 0.4),\n                    endY - arrowSize * Math.sin(arrowAngle + 0.4)\n                );\n                ctx.closePath();\n                ctx.fill();\n\n                // Draw launch position indicator\n                ctx.beginPath();\n                ctx.arc(startX, startY, 15, 0, Math.PI * 2);\n                ctx.strokeStyle = '#ffffff';\n                ctx.lineWidth = 3;\n                ctx.stroke();\n                ctx.fillStyle = 'rgba(255, 102, 0, 0.5)';\n                ctx.fill();\n\n                ctx.restore();\n            }\n\n            // Game initialization\n            function initGame() {\n                tops = [];\n                particles = [];\n                trails = [];\n                armorPieces = []; // Clear armor pieces\n                playerLaunched = false;\n                playerRetryUsed = false;\n                gameEndTimestamp = 0;\n\n                const config = window.gameConfig;\n\n                // Create player top\n                const playerStartX = ARENA_CENTER_X;\n                const playerStartY = ARENA_CENTER_Y + ARENA_RADIUS - TOP_RADIUS - 40;\n                const playerTop = new Top(\n                    config.playerTop.type,\n                    config.playerTop.name,\n                    playerStartX,\n                    playerStartY,\n                    true,\n                    config.playerTop.primaryColor\n                );\n                tops.push(playerTop);\n\n                // Create AI opponent\n                const opponentType = config.opponentTop ? config.opponentTop.type : 'attack';\n                const opponentName = config.opponentTop ? config.opponentTop.name : 'Rival';\n                const opponentColor = config.opponentTop ? config.opponentTop.primaryColor : '#ff4444';\n                \n                const pos = { x: ARENA_CENTER_X, y: ARENA_CENTER_Y - 300 };\n                const aiTop = new Top(\n                    opponentType,\n                    opponentName,\n                    pos.x,\n                    pos.y,\n                    false,\n                    opponentColor\n                );\n\n                // Boost AI stats for challenge\n                aiTop.stats.mass *= 1.6;\n                aiTop.stats.power *= 1.4;\n                aiTop.stats.speed *= 1.1;\n                aiTop.spinEnergy = 140;\n                tops.push(aiTop);\n\n                updateStatsUI();\n            }\n\n            // AI launch logic\n            function launchAI() {\n                const difficulty = window.gameConfig.settings.difficulty || 'medium';\n                const powerRange = {\n                    easy: { min: 65, max: 85 },\n                    medium: { min: 85, max: 105 },\n                    hard: { min: 105, max: 130 }\n                };\n\n                tops.forEach((top, index) => {\n                    if (!top.isPlayer && !top.isActive && !top.isKnockedOut) {\n                        setTimeout(() => {\n                            const angle = Math.PI / 2 + (Math.random() - 0.5) * Math.PI * 0.8;\n                            const range = powerRange[difficulty];\n                            const power = range.min + Math.random() * (range.max - range.min);\n                            top.launch(angle, power);\n                            playSound('launch_sound', 0.5);\n                        }, 500 + index * 300);\n                    }\n                });\n            }\n\n            // Countdown sequence\n            async function startCountdown() {\n                gameState = 'countdown';\n                isPaused = false;\n                \n                // Stop any existing battle music\n                stopSound(battleMusicSource);\n                \n                const overlay = document.getElementById('countdown-overlay');\n                const text = document.getElementById('countdown-text');\n                overlay.classList.add('active');\n                document.getElementById('control-area').classList.add('hidden');\n                document.getElementById('menu-btn-container').classList.add('active');\n                document.getElementById('pause-overlay').classList.remove('active');\n                updateVoiceUI();\n\n                if (window.gameConfig.settings.voiceEnabled && audioBuffers['voice_let_it_rip']) {\n                    playSound('voice_let_it_rip', 1.0);\n                }\n\n                const countdownSteps = ['3', '2', '1', 'LET IT RIP!'];\n                \n                for (const step of countdownSteps) {\n                    text.textContent = step;\n                    text.style.animation = 'none';\n                    text.offsetHeight; // Trigger reflow\n                    text.style.animation = 'countdownPulse 0.5s ease-out';\n                    \n                    if (step === 'LET IT RIP!') {\n                        text.style.fontSize = '60px';\n                        if (!window.gameConfig.settings.voiceEnabled) playSound('countdown_beep', 0.8);\n                    } else {\n                        if (!window.gameConfig.settings.voiceEnabled) {\n                            playSound('countdown_beep', 0.6);\n                            speak(step);\n                        }\n                    }\n                    \n                    await new Promise(resolve => { setTimeout(resolve, 800); });\n                }\n\n                overlay.classList.remove('active');\n                text.style.fontSize = '120px';\n                document.getElementById('control-area').classList.remove('hidden');\n                \n                gameState = 'launch';\n                playSound('battle_music', 0.4, true);\n            }\n\n            // Check win/lose conditions\n            function checkGameEnd() {\n                const playerTop = tops.find(t => t.isPlayer);\n                if (!playerTop) return;\n\n                const opponents = tops.filter(t => !t.isPlayer);\n                const playerLost = playerTop.isKnockedOut || (!playerTop.isActive && playerLaunched);\n                const allOpponentsDefeated = opponents.every(t => t.isKnockedOut || (t.spinEnergy <= 0));\n\n                if (playerLost || (allOpponentsDefeated && playerLaunched)) {\n                    if (gameEndTimestamp === 0) gameEndTimestamp = Date.now();\n                    if (Date.now() - gameEndTimestamp < 1500) return;\n\n                    if (playerLost) {\n                        if (!playerRetryUsed) {\n                            document.getElementById('retry-button').classList.add('active');\n                            return;\n                        }\n                        endGame(false);\n                    } else {\n                        endGame(true);\n                    }\n                } else {\n                    gameEndTimestamp = 0;\n                }\n            }\n\n            // End game\n            function endGame(victory) {\n                gameState = 'result';\n                isPaused = false;\n\n                // Make armor return to owners\n                armorPieces.forEach(ap => {\n                    ap.isReturning = true;\n                    ap.isHoming = false;\n                });\n                \n                const overlay = document.getElementById('result-overlay');\n                const title = document.getElementById('result-title');\n                \n                if (victory) {\n                    title.textContent = 'VICTORY!';\n                    title.className = 'result-title victory';\n                    playSound('victory_fanfare', 0.7);\n                    speak(\"Victory! You are the champion!\");\n                } else {\n                    title.textContent = 'DEFEAT';\n                    title.className = 'result-title defeat';\n                    speak(\"Defeat. Try again!\");\n                }\n\n                overlay.classList.add('active');\n                document.getElementById('retry-button').classList.remove('active');\n                document.getElementById('control-area').classList.add('hidden');\n                document.getElementById('menu-btn-container').classList.remove('active');\n                document.getElementById('pause-overlay').classList.remove('active');\n            }\n\n            // Player retry\n            function retryLaunch() {\n                if (playerRetryUsed) return;\n                playerRetryUsed = true;\n                \n                armorPieces = []; // Clear detached armor\n                \n                // Reset all tops for a fresh round start\n                tops.forEach((top, index) => {\n                    if (top.isPlayer) {\n                        top.x = ARENA_CENTER_X;\n                        top.y = ARENA_CENTER_Y + ARENA_RADIUS - TOP_RADIUS - 40;\n                        top.spinEnergy = 100; // Reset player spin\n                    } else {\n                        // Reset AI to starting positions\n                        top.x = ARENA_CENTER_X;\n                        top.y = ARENA_CENTER_Y - 300;\n                        top.spinEnergy = 140; // Restore AI spin\n                    }\n                    top.vx = 0;\n                    top.vy = 0;\n                    top.isActive = false;\n                    top.isKnockedOut = false;\n                    top.isBurst = false;\n                    top.burstPieces = [];\n                    // Reset all special timers and states\n                    top.abilityCooldown = 0;\n                    top.isSpringing = false;\n                    top.rushLaunchTimer = 0;\n                    top.ultraFlashTimer = 0;\n                    top.counterTimer = 0;\n                    top.zoneTimer = 0;\n                    top.jumpTimer = 0;\n                    top.guardTimer = 0;\n                    top.scale = 1.0;\n                    if (top.specialCooldowns) {\n                        top.specialCooldowns = top.specialCooldowns.map(() => 0);\n                    }\n                });\n\n                playerLaunched = false;\n                gameState = 'launch';\n                gameEndTimestamp = 0;\n\n                document.getElementById('retry-button').classList.remove('active');\n                document.getElementById('launch-instruction').textContent = 'LAST CHANCE! AIM CAREFULLY!';\n            }\n\n            // Edit mode functions\n            function showEditPanel() {\n                document.getElementById('edit-panel').classList.add('active');\n                document.getElementById('menu-btn-container').classList.remove('active');\n                document.getElementById('pause-overlay').classList.remove('active');\n                isPaused = false;\n                gameState = 'edit';\n                stopSound(battleMusicSource);\n                updateEditPreview();\n                updateTypeButtons();\n            }\n\n            function hideEditPanel() {\n                document.getElementById('edit-panel').classList.remove('active');\n            }\n\n            function updateEditPreview() {\n                const config = window.gameConfig;\n                const topType = config.playerTop.type;\n                const stats = { ...TOP_STATS[topType] };\n\n                // Apply part modifiers for preview\n                const weight = config.playerTop.weightType || 'standard';\n                const height = config.playerTop.heightType || 'standard';\n                if (weight === 'heavy') {\n                    stats.defense += 3;\n                    stats.speed -= 2;\n                }\n                if (height === 'low') {\n                    stats.defense += 2;\n                    stats.speed -= 1;\n                } else if (height === 'high') {\n                    stats.speed += 2;\n                    stats.power += 2;\n                }\n\n                const imgId = 'top_' + topType;\n                const img = assetCache.images[imgId];\n                const previewImg = document.getElementById('preview-img');\n                \n                if (img) {\n                    previewImg.src = img.src;\n                }\n\n                // Update stats bars\n                if (stats) {\n                    document.getElementById('bar-speed').style.width = (stats.speed * 8) + '%';\n                    document.getElementById('bar-power').style.width = (stats.power * 8) + '%';\n                    document.getElementById('bar-defense').style.width = (stats.defense * 8) + '%';\n                }\n            }\n\n            function updateTypeButtons() {\n                const config = window.gameConfig;\n                document.querySelectorAll('.top-type-btn:not(.opponent-type-btn):not(.weight-type-btn):not(.height-type-btn)').forEach(btn => {\n                    btn.classList.toggle('selected', btn.dataset.type === config.playerTop.type);\n                });\n                document.querySelectorAll('.weight-type-btn').forEach(btn => {\n                    btn.classList.toggle('selected', btn.dataset.weight === (config.playerTop.weightType || 'standard'));\n                });\n                document.querySelectorAll('.height-type-btn').forEach(btn => {\n                    btn.classList.toggle('selected', btn.dataset.height === (config.playerTop.heightType || 'standard'));\n                });\n                document.querySelectorAll('.opponent-type-btn').forEach(btn => {\n                    btn.classList.toggle('selected', btn.dataset.otype === (config.opponentTop ? config.opponentTop.type : 'attack'));\n                });\n            }\n\n            // Trigger Special Move Function\n            function triggerSpecialMove(top, moveIndex = 0) {\n                if (top.isKnockedOut || !top.isActive) return;\n                \n                const move = top.stats.specials ? top.stats.specials[moveIndex] : null;\n                if (!move) return;\n\n                const specialName = move.name;\n                const banner = document.getElementById('special-banner');\n                const bannerName = document.getElementById('special-banner-name');\n                const bannerType = document.getElementById('special-banner-type');\n                \n                bannerName.textContent = specialName;\n                bannerType.textContent = top.name.toUpperCase();\n                banner.style.borderColor = top.primaryColor;\n                bannerName.style.textShadow = `0 0 20px ${top.primaryColor}`;\n                banner.classList.add('active');\n                \n                setTimeout(() => banner.classList.remove('active'), 1200);\n\n                const boost = 60;\n                \n                // Logic based on move type\n                switch(move.type) {\n                    case 'world_counter':\n                        top.counterTimer = 4.0;\n                        top.guardTimer = 4.0;\n                        const originalMass = top.stats.mass;\n                        top.stats.mass *= 15; // Even more immovable\n                        createFloatingText(top.x, top.y - 60, \"WORLD GUARD!\", top.primaryColor);\n                        setTimeout(() => { if (top.stats) top.stats.mass = originalMass; }, 4000);\n                        break;\n                    case 'axe_crash':\n                        let axeTarget = tops.find(t => t !== top && t.isActive && !t.isKnockedOut);\n                        if (axeTarget) {\n                            const dx = axeTarget.x - top.x;\n                            const dy = axeTarget.y - top.y;\n                            const dist = Math.sqrt(dx * dx + dy * dy);\n                            top.vx = (dx / dist) * boost * 3.5;\n                            top.vy = (dy / dist) * boost * 3.5;\n                            top.ultraFlashTimer = 2.0; \n                        }\n                        createCollisionEffect(top.x, top.y, 40);\n                        gameWorld.classList.add('shake');\n                        setTimeout(() => gameWorld.classList.remove('shake'), 600);\n                        break;\n                    case 'roktavor_zone':\n                        top.zoneTimer = 5.0;\n                        top.spinEnergy = Math.min(100, top.spinEnergy + 30);\n                        top.stats.defense += 5;\n                        setTimeout(() => { if (top.stats) top.stats.defense -= 5; }, 5000);\n                        break;\n                    case 'gravity_fire':\n                        top.vx *= 0.2; top.vy *= 0.2;\n                        top.spinEnergy = Math.min(120, top.spinEnergy + 50); // Overcharge\n                        createCollisionEffect(top.x, top.y, 20);\n                        break;\n                    case 'rush_launch':\n                        top.ultraFlashTimer = 2.0;\n                        top.vx *= 1.5; top.vy *= 1.5;\n                        break;\n                    case 'victory_slash':\n                        for(let i=0; i<3; i++) {\n                            setTimeout(() => {\n                                if(!top.isActive) return;\n                                let t = tops.find(ot => ot !== top && ot.isActive && !ot.isKnockedOut);\n                                if(t) {\n                                    const dx = t.x - top.x; const dy = t.y - top.y;\n                                    const d = Math.sqrt(dx*dx + dy*dy);\n                                    top.vx = (dx/d) * 45; top.vy = (dy/d) * 45;\n                                    createCollisionEffect(top.x, top.y, 10);\n                                }\n                            }, i * 350);\n                        }\n                        break;\n                    case 'god_reboot':\n                        top.spinEnergy = Math.min(100, top.spinEnergy + 25);\n                        top.vx *= 2.0; top.vy *= 2.0;\n                        createFloatingText(top.x, top.y - 40, \"REBOOT!\", '#00ffff');\n                        break;\n                    case 'bound_attack':\n                        top.abilityCooldown = 0; // Reset spring ability\n                        top.vx *= 2.5; top.vy *= 2.5;\n                        top.ultraFlashTimer = 1.5;\n                        break;\n                    case 'meteor_shower':\n                    case 'starblast_attack':\n                        top.jumpTimer = 1.5;\n                        top.scale = 1.0;\n                        let jumpTarget = tops.find(t => t !== top && t.isActive && !t.isKnockedOut);\n                        if (jumpTarget) {\n                            const dx = jumpTarget.x - top.x;\n                            const dy = jumpTarget.y - top.y;\n                            const dist = Math.sqrt(dx * dx + dy * dy);\n                            top.vx = (dx / dist) * 15;\n                            top.vy = (dy / dist) * 15;\n                            // Teleport slightly towards target during jump\n                            setTimeout(() => {\n                                if (top.isActive && jumpTarget.isActive) {\n                                    top.x = jumpTarget.x + (Math.random() - 0.5) * 60;\n                                    top.y = jumpTarget.y + (Math.random() - 0.5) * 60;\n                                }\n                            }, 750);\n                        }\n                        break;\n                    case 'galaxy_nova':\n                        top.spinEnergy = Math.min(100, top.spinEnergy + 15);\n                        top.ultraFlashTimer = 3.0;\n                        gameWorld.classList.add('shake');\n                        setTimeout(() => gameWorld.classList.remove('shake'), 800);\n                        break;\n                    case 'dread_armor':\n                        top.hasArmor = true; // Regenerate armor if used\n                        top.guardTimer = 5.0;\n                        top.zoneTimer = 5.0; \n                        const oldMass = top.stats.mass;\n                        top.stats.mass *= 3;\n                        createFloatingText(top.x, top.y - 60, \"DREAD ARMOR!\", top.primaryColor);\n                        // Armor repulsion pulse\n                        const armorInterval = setInterval(() => {\n                            if (!top.isActive || top.guardTimer <= 0) {\n                                clearInterval(armorInterval);\n                                top.stats.mass = oldMass;\n                                return;\n                            }\n                            tops.forEach(t => {\n                                if (t !== top && t.isActive && !t.isKnockedOut) {\n                                    const dx = t.x - top.x;\n                                    const dy = t.y - top.y;\n                                    const dist = Math.sqrt(dx*dx + dy*dy);\n                                    if (dist < 180) {\n                                        t.vx += (dx / dist) * 2.5;\n                                        t.vy += (dy / dist) * 2.5;\n                                        t.spinEnergy -= 0.5;\n                                    }\n                                }\n                            });\n                        }, 50);\n                        break;\n                    case 'dread_cannon':\n                        let cannonTarget = tops.find(t => t !== top && t.isActive && !t.isKnockedOut);\n                        if (cannonTarget) {\n                            const dx = cannonTarget.x - top.x;\n                            const dy = cannonTarget.y - top.y;\n                            const dist = Math.sqrt(dx * dx + dy * dy);\n                            top.vx = (dx / dist) * 50;\n                            top.vy = (dy / dist) * 50;\n                            top.stats.mass *= 2;\n                            setTimeout(() => { if(top.stats) top.stats.mass /= 2; }, 1000);\n                        }\n                        createCollisionEffect(top.x, top.y, 30);\n                        break;\n                    case 'drain_spin':\n                        top.zoneTimer = 5.0;\n                        top.spinEnergy = Math.min(110, top.spinEnergy + 15);\n                        createFloatingText(top.x, top.y - 60, \"DRAIN SPIN!\", top.primaryColor);\n                        const drainInterval = setInterval(() => {\n                            if (!top.isActive || top.zoneTimer <= 0) {\n                                clearInterval(drainInterval);\n                                return;\n                            }\n                            tops.forEach(t => {\n                                if (t !== top && t.isActive && !t.isKnockedOut) {\n                                    const dx = t.x - top.x;\n                                    const dy = t.y - top.y;\n                                    const dist = Math.sqrt(dx*dx + dy*dy);\n                                    if (dist < 180) {\n                                        // Steal energy\n                                        const stealAmount = 0.4;\n                                        t.spinEnergy -= stealAmount;\n                                        top.spinEnergy = Math.min(110, top.spinEnergy + stealAmount * 0.8);\n                                        // Slight pull\n                                        t.vx -= (dx / dist) * 0.5;\n                                        t.vy -= (dy / dist) * 0.5;\n                                    }\n                                }\n                            });\n                        }, 100);\n                        break;\n                    case 'nothing_break':\n                        top.ultraFlashTimer = 2.0;\n                        const nbSpeed = Math.sqrt(top.vx * top.vx + top.vy * top.vy);\n                        if (nbSpeed > 0) {\n                            top.vx *= 2.2;\n                            top.vy *= 2.2;\n                        } else {\n                            top.vx = (Math.random() - 0.5) * 40;\n                            top.vy = (Math.random() - 0.5) * 40;\n                        }\n                        createFloatingText(top.x, top.y - 60, \"NOTHING BREAK!\", top.primaryColor);\n                        break;\n                    case 'dread_gravity':\n                        top.zoneTimer = 4.0;\n                        const gravityInterval = setInterval(() => {\n                            if (!top.isActive || top.zoneTimer <= 0) {\n                                clearInterval(gravityInterval);\n                                return;\n                            }\n                            tops.forEach(t => {\n                                if (t !== top && t.isActive && !t.isKnockedOut) {\n                                    const dx = top.x - t.x;\n                                    const dy = top.y - t.y;\n                                    const dist = Math.sqrt(dx*dx + dy*dy);\n                                    if (dist < 400) {\n                                        t.vx += (dx / dist) * 1.5;\n                                        t.vy += (dy / dist) * 1.5;\n                                    }\n                                }\n                            });\n                        }, 50);\n                        createFloatingText(top.x, top.y - 60, \"DREAD GRAVITY\", top.primaryColor);\n                        break;\n                    case 'triple_saber':\n                        for(let i=0; i<3; i++) {\n                            setTimeout(() => {\n                                if(!top.isActive) return;\n                                let t = tops.find(ot => ot !== top && ot.isActive && !ot.isKnockedOut);\n                                if(t) {\n                                    const dx = t.x - top.x; const dy = t.y - top.y;\n                                    const d = Math.sqrt(dx*dx + dy*dy);\n                                    top.vx = (dx/d) * 55; top.vy = (dy/d) * 55;\n                                    createCollisionEffect(top.x, top.y, 15);\n                                    playSound('collision_sound', 0.6);\n                                }\n                            }, i * 250);\n                        }\n                        break;\n                    case 'impact_slash':\n                        let impactTarget = tops.find(t => t !== top && t.isActive && !t.isKnockedOut);\n                        if (impactTarget) {\n                            const dx = impactTarget.x - top.x;\n                            const dy = impactTarget.y - top.y;\n                            const dist = Math.sqrt(dx * dx + dy * dy);\n                            top.vx = (dx / dist) * 110;\n                            top.vy = (dy / dist) * 110;\n                            top.spinEnergy -= 15;\n                            createFloatingText(top.x, top.y - 60, \"ULTRA IMPACT!\", top.primaryColor);\n                        }\n                        gameWorld.classList.add('shake');\n                        setTimeout(() => gameWorld.classList.remove('shake'), 500);\n                        break;\n                    case 'shockwave':\n                        createCollisionEffect(top.x, top.y, 50);\n                        tops.forEach(t => {\n                            if (t !== top && t.isActive && !t.isKnockedOut) {\n                                const dx = t.x - top.x;\n                                const dy = t.y - top.y;\n                                const dist = Math.sqrt(dx*dx + dy*dy);\n                                if (dist < 300 && dist > 0) {\n                                    const force = (1 - dist/300) * 45;\n                                    t.vx += (dx/dist) * force;\n                                    t.vy += (dy/dist) * force;\n                                    t.spinEnergy -= 8;\n                                }\n                            }\n                        });\n                        createFloatingText(top.x, top.y - 60, \"SHOCKWAVE!\", top.primaryColor);\n                        gameWorld.classList.add('shake');\n                        setTimeout(() => gameWorld.classList.remove('shake'), 400);\n                        break;\n                    case 'overdrive':\n                        top.ultraFlashTimer = 3.5;\n                        top.vx *= 1.8;\n                        top.vy *= 1.8;\n                        top.spinEnergy = Math.min(120, top.spinEnergy + 30);\n                        createFloatingText(top.x, top.y - 60, \"OVERDRIVE!\", top.primaryColor);\n                        break;\n                    case 'counter':\n                        top.counterTimer = 2.0;\n                        top.guardTimer = 2.0;\n                        const m = top.stats.mass;\n                        top.stats.mass *= 2;\n                        setTimeout(() => { if (top.stats) top.stats.mass = m; }, 2000);\n                        break;\n                    case 'stamina':\n                        top.zoneTimer = 3.0;\n                        top.spinEnergy = Math.min(100, top.spinEnergy + 20);\n                        break;\n                    case 'stamina_boost':\n                        top.zoneTimer = 1.5;\n                        top.spinEnergy = Math.min(100, top.spinEnergy + 40);\n                        top.vx *= 0.5; top.vy *= 0.5;\n                        break;\n                    case 'jump':\n                        top.jumpTimer = 1.2;\n                        // ... existing generic jump logic if any ...\n                        break;\n                    case 'flash':\n                        top.ultraFlashTimer = 2.5;\n                        break;\n                    case 'guard':\n                        top.guardTimer = 3.0;\n                        const gMass = top.stats.mass;\n                        top.stats.mass *= 3;\n                        setTimeout(() => { if (top.stats) top.stats.mass = gMass; }, 3000);\n                        break;\n                    case 'speed':\n                        const s = Math.sqrt(top.vx * top.vx + top.vy * top.vy);\n                        if (s > 0) {\n                            top.vx = (top.vx / s) * MAX_SPEED * 1.5;\n                            top.vy = (top.vy / s) * MAX_SPEED * 1.5;\n                        }\n                        break;\n                    case 'attack':\n                    default:\n                        let target = tops.find(t => t !== top && t.isActive && !t.isKnockedOut);\n                        if (target) {\n                            const dx = target.x - top.x;\n                            const dy = target.y - top.y;\n                            const dist = Math.sqrt(dx * dx + dy * dy);\n                            if (dist > 0) {\n                                top.vx = (dx / dist) * boost;\n                                top.vy = (dy / dist) * boost;\n                            }\n                        } else {\n                            top.vy = -boost;\n                        }\n                        break;\n                }\n\n                top.spinEnergy -= 8;\n                if (top.specialCooldowns) {\n                    top.specialCooldowns[moveIndex] = move.cooldown || 5;\n                }\n                \n                playSound('launch_sound', 1.0);\n                createCollisionEffect(top.x, top.y, 8);\n            }\n\n            // Input handling\n            function setupInputHandlers() {\n                const controlArea = document.getElementById('control-area');\n\n                // Touch/mouse start\n                function handleStart(e) {\n                    if (gameState !== 'launch' || playerLaunched) return;\n                    \n                    initAudio();\n                    \n                    const rect = gameWorld.getBoundingClientRect();\n                    const clientX = e.touches ? e.touches[0].clientX : e.clientX;\n                    const clientY = e.touches ? e.touches[0].clientY : e.clientY;\n                    \n                    aimStartX = clientX - rect.left;\n                    aimStartY = clientY - rect.top;\n                    aimCurrentX = aimStartX;\n                    aimCurrentY = aimStartY;\n                    isAiming = true;\n                    \n                    e.preventDefault();\n                }\n\n                // Touch/mouse move\n                function handleMove(e) {\n                    if (!isAiming) return;\n                    \n                    const rect = gameWorld.getBoundingClientRect();\n                    const clientX = e.touches ? e.touches[0].clientX : e.clientX;\n                    const clientY = e.touches ? e.touches[0].clientY : e.clientY;\n                    \n                    aimCurrentX = clientX - rect.left;\n                    aimCurrentY = clientY - rect.top;\n\n                    // Calculate angle from arena center to touch point\n                    const dx = aimCurrentX - ARENA_CENTER_X;\n                    const dy = aimCurrentY - ARENA_CENTER_Y;\n                    launchAngle = Math.atan2(dy, dx);\n                    \n                    // Clamp to bottom half (facing up into arena)\n                    if (launchAngle < 0.2) launchAngle = 0.2;\n                    if (launchAngle > Math.PI - 0.2) launchAngle = Math.PI - 0.2;\n\n                    // Calculate power based on drag distance\n                    const dragDist = Math.sqrt(\n                        Math.pow(aimCurrentX - aimStartX, 2) + \n                        Math.pow(aimCurrentY - aimStartY, 2)\n                    );\n                    launchPower = Math.min(100, Math.max(MIN_POWER, dragDist / 2));\n\n                    // Update power meter\n                    document.getElementById('power-meter').style.width = launchPower + '%';\n                    \n                    e.preventDefault();\n                }\n\n                // Touch/mouse end\n                function handleEnd(e) {\n                    if (!isAiming) return;\n                    isAiming = false;\n\n                    if (launchPower >= MIN_POWER && gameState === 'launch' && !playerLaunched) {\n                        // Launch player top\n                        const playerTop = tops.find(t => t.isPlayer);\n                        if (playerTop) {\n                            // Set start position based on launch angle\n                            playerTop.x = ARENA_CENTER_X + Math.cos(launchAngle) * (ARENA_RADIUS - TOP_RADIUS - 40);\n                            playerTop.y = ARENA_CENTER_Y + Math.sin(launchAngle) * (ARENA_RADIUS - TOP_RADIUS - 40);\n                            \n                            playerTop.launch(launchAngle + Math.PI, launchPower);\n                            playerLaunched = true;\n                            playSound('launch_sound', 0.7);\n                            \n                            const firstSpecial = playerTop.stats.specials ? playerTop.stats.specials[0] : null;\n                            if (firstSpecial && firstSpecial.type === 'flash' && launchPower > 70) {\n                                document.getElementById('launch-instruction').textContent = 'ULTRA CIRCLE ATTACK!';\n                                document.getElementById('launch-instruction').style.color = '#00ffff';\n                                setTimeout(() => {\n                                    document.getElementById('launch-instruction').style.color = '';\n                                }, 2000);\n                            } else {\n                                document.getElementById('launch-instruction').textContent = 'BATTLE!';\n                            }\n                            \n                            // Launch AI after player\n                            launchAI();\n                            \n                            gameState = 'battle';\n                        }\n                    }\n\n                    // Reset power meter\n                    document.getElementById('power-meter').style.width = '0%';\n                    \n                    e.preventDefault();\n                }\n\n                // Tap to launch support\n                document.getElementById('tap-to-launch').addEventListener('click', (e) => {\n                    if (gameState === 'launch' && !playerLaunched) {\n                        launchAngle = -Math.PI / 2;\n                        launchPower = 80;\n                        handleEnd(e);\n                    }\n                });\n\n                // Add event listeners\n                controlArea.addEventListener('mousedown', handleStart);\n                controlArea.addEventListener('touchstart', handleStart, { passive: false });\n                \n                window.addEventListener('mousemove', handleMove);\n                window.addEventListener('touchmove', handleMove, { passive: false });\n                \n                window.addEventListener('mouseup', handleEnd);\n                window.addEventListener('touchend', handleEnd, { passive: false });\n\n                // Retry button\n                document.getElementById('retry-button').addEventListener('click', () => {\n                    initAudio();\n                    retryLaunch();\n                });\n\n                // Result buttons\n                document.getElementById('play-again-btn').addEventListener('click', () => {\n                    document.getElementById('result-overlay').classList.remove('active');\n                    document.getElementById('control-area').classList.remove('hidden');\n                    document.getElementById('launch-instruction').textContent = 'TAP & DRAG TO AIM';\n                    initGame();\n                    startCountdown();\n                });\n\n                document.getElementById('customize-btn').addEventListener('click', () => {\n                    document.getElementById('result-overlay').classList.remove('active');\n                    showEditPanel();\n                });\n\n                // Edit mode handlers\n                document.querySelectorAll('.top-type-btn:not(.opponent-type-btn):not(.weight-type-btn):not(.height-type-btn)').forEach(btn => {\n                    btn.addEventListener('click', () => {\n                        window.gameConfig.playerTop.type = btn.dataset.type;\n                        updateTypeButtons();\n                        updateEditPreview();\n                    });\n                });\n\n                document.querySelectorAll('.weight-type-btn').forEach(btn => {\n                    btn.addEventListener('click', () => {\n                        window.gameConfig.playerTop.weightType = btn.dataset.weight;\n                        updateTypeButtons();\n                        updateEditPreview();\n                    });\n                });\n\n                document.querySelectorAll('.height-type-btn').forEach(btn => {\n                    btn.addEventListener('click', () => {\n                        window.gameConfig.playerTop.heightType = btn.dataset.height;\n                        updateTypeButtons();\n                        updateEditPreview();\n                    });\n                });\n\n                document.querySelectorAll('.opponent-type-btn').forEach(btn => {\n                    btn.addEventListener('click', () => {\n                        const type = btn.dataset.otype;\n                        const nameMap = {\n                            fafnir: 'Wizard Fafnir',\n                            turbo_achilles: 'Turbo Achilles',\n                            world_spryzen: 'Dark Spryzen',\n                            roktavor: 'Blaze Roktavor',\n                            valtryek: 'Rival Valtryek',\n                            storm_pegasus: 'Rival Pegasus',\n                            dread_phoenix: 'Dread Phoenix',\n                            xcalius: 'Xcalius Master',\n                            attack: 'Red Fury',\n                            defense: 'Iron Guard',\n                            stamina: 'Golden Spin',\n                            balanced: 'Shadow Blade'\n                        };\n                        const colorMap = {\n                            fafnir: '#ffcc00',\n                            turbo_achilles: '#cc0000',\n                            world_spryzen: '#ff0000',\n                            roktavor: '#ff9900',\n                            valtryek: '#0066ff',\n                            storm_pegasus: '#ffffff',\n                            dread_phoenix: '#990033',\n                            xcalius: '#0044cc',\n                            attack: '#ff4444',\n                            defense: '#44cc44',\n                            stamina: '#ffcc00',\n                            balanced: '#aa88ff'\n                        };\n                        window.gameConfig.opponentTop = {\n                            type: type,\n                            name: nameMap[type] || 'Rival',\n                            primaryColor: colorMap[type] || '#ff4444'\n                        };\n                        updateTypeButtons();\n                    });\n                });\n\n                document.getElementById('name-input').addEventListener('input', (e) => {\n                    window.gameConfig.playerTop.name = e.target.value || 'My Top';\n                });\n\n                document.getElementById('ready-button').addEventListener('click', () => {\n                    initAudio();\n                    hideEditPanel();\n                    document.getElementById('control-area').classList.remove('hidden');\n                    initGame();\n                    startCountdown();\n                });\n\n                // Keyboard support\n                window.addEventListener('keydown', (e) => {\n                    if (e.code === 'Space') {\n                        if (document.getElementById('retry-button').classList.contains('active')) {\n                            retryLaunch();\n                        }\n                    }\n                    if (e.code === 'Escape') {\n                        if (gameState === 'battle' || gameState === 'launch' || gameState === 'countdown') {\n                            togglePause();\n                        }\n                    }\n                });\n\n                // Menu handlers\n                document.getElementById('open-menu-btn').addEventListener('click', togglePause);\n                document.getElementById('resume-btn').addEventListener('click', togglePause);\n                \n                document.getElementById('restart-btn').addEventListener('click', () => {\n                    togglePause();\n                    initGame();\n                    startCountdown();\n                });\n\n                document.getElementById('quit-btn').addEventListener('click', () => {\n                    togglePause();\n                    showEditPanel();\n                });\n\n                // Voice button\n                document.getElementById('voice-toggle-btn').addEventListener('click', () => {\n                    toggleVoice();\n                });\n            }\n\n            function togglePause() {\n                if (gameState === 'edit' || gameState === 'result') return;\n                \n                isPaused = !isPaused;\n                const pauseOverlay = document.getElementById('pause-overlay');\n                \n                if (isPaused) {\n                    pauseOverlay.classList.add('active');\n                } else {\n                    pauseOverlay.classList.remove('active');\n                }\n            }\n\n            // Draw arena\n            function drawArena(ctx) {\n                const img = assetCache.images['arena_stadium'];\n                if (img) {\n                    // Calculate dimensions maintaining aspect ratio\n                    const assetInfo = lib.getAsset('arena_stadium');\n                    let drawWidth = ARENA_RADIUS * 2 + RIM_WIDTH * 2;\n                    let drawHeight = drawWidth;\n                    \n                    if (assetInfo && assetInfo.aspect_ratio) {\n                        const aspectRatio = assetInfo.aspect_ratio[0] / assetInfo.aspect_ratio[1];\n                        if (aspectRatio > 1) {\n                            drawHeight = drawWidth / aspectRatio;\n                        } else {\n                            drawWidth = drawHeight * aspectRatio;\n                        }\n                    }\n\n                    ctx.drawImage(\n                        img,\n                        ARENA_CENTER_X - drawWidth / 2,\n                        ARENA_CENTER_Y - drawHeight / 2,\n                        drawWidth,\n                        drawHeight\n                    );\n                } else {\n                    // Fallback: draw simple arena\n                    ctx.save();\n                    \n                    // Outer rim\n                    ctx.beginPath();\n                    ctx.arc(ARENA_CENTER_X, ARENA_CENTER_Y, ARENA_RADIUS + RIM_WIDTH, 0, Math.PI * 2);\n                    ctx.fillStyle = '#556677';\n                    ctx.fill();\n                    \n                    // Inner surface\n                    const gradient = ctx.createRadialGradient(\n                        ARENA_CENTER_X, ARENA_CENTER_Y, 0,\n                        ARENA_CENTER_X, ARENA_CENTER_Y, ARENA_RADIUS\n                    );\n                    gradient.addColorStop(0, '#445566');\n                    gradient.addColorStop(1, '#334455');\n                    \n                    ctx.beginPath();\n                    ctx.arc(ARENA_CENTER_X, ARENA_CENTER_Y, ARENA_RADIUS, 0, Math.PI * 2);\n                    ctx.fillStyle = gradient;\n                    ctx.fill();\n                    \n                    ctx.restore();\n                }\n            }\n\n            // Main game loop\n            function gameLoop(timestamp) {\n                const deltaTime = Math.min((timestamp - lastTime) / 1000, 0.11);\n                lastTime = timestamp;\n\n                // Clear canvas\n                ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n                if (mode === 'edit') {\n                    // Edit mode - just show arena preview\n                    drawArena(ctx);\n                    \n                    // Draw preview top in center\n                    const config = window.gameConfig;\n                    const imgId = 'top_' + config.playerTop.type;\n                    const img = assetCache.images[imgId];\n                    \n                    if (img) {\n                        ctx.save();\n                        ctx.translate(ARENA_CENTER_X, ARENA_CENTER_Y);\n                        ctx.rotate(timestamp / 500);\n                        ctx.shadowColor = config.playerTop.primaryColor;\n                        ctx.shadowBlur = 25;\n                        ctx.drawImage(img, -TOP_RADIUS, -TOP_RADIUS, TOP_RADIUS * 2, TOP_RADIUS * 2);\n                        ctx.restore();\n                    }\n                } else {\n                    // Play mode\n                    drawArena(ctx);\n\n                    if (!isPaused && (gameState === 'battle' || gameState === 'launch' || gameState === 'result')) {\n                        // Update tops (only rotation/movement in result)\n                        tops.forEach(top => top.update(deltaTime));\n\n                        if (gameState !== 'result') {\n                            // Handle collisions\n                            handleCollisions();\n                        }\n\n                        // Update particles & armor\n                        updateParticles(deltaTime);\n\n                        // Check win/lose\n                        if (gameState === 'battle') {\n                            checkGameEnd();\n                        }\n\n                        // Update stats UI\n                        updateStatsUI();\n                    }\n\n                    // Draw particles (behind tops)\n                    drawParticles(ctx);\n\n                    // Draw tops\n                    tops.forEach(top => top.draw(ctx));\n\n                    // Update Attack Buttons UI\n                    const attackBtnContainer = document.getElementById('attack-btn-container');\n                    if (gameState === 'battle' && playerLaunched) {\n                        const playerTop = tops.find(t => t.isPlayer);\n                        if (playerTop && playerTop.isActive) {\n                            attackBtnContainer.classList.add('active');\n                            \n                            // Check if buttons need to be created/refreshed\n                            const existingButtons = attackBtnContainer.querySelectorAll('.attack-btn-wrapper');\n                            if (existingButtons.length !== (playerTop.stats.specials ? playerTop.stats.specials.length : 0)) {\n                                attackBtnContainer.innerHTML = '';\n                                playerTop.stats.specials.forEach((special, idx) => {\n                                    const wrapper = document.createElement('div');\n                                    wrapper.className = 'attack-btn-wrapper';\n                                    wrapper.style.display = 'flex';\n                                    wrapper.style.flexDirection = 'column';\n                                    wrapper.style.alignItems = 'center';\n                                    wrapper.style.gap = '4px';\n\n                                    const label = document.createElement('div');\n                                    label.className = 'attack-label';\n                                    label.textContent = special.name;\n                                    label.style.color = playerTop.primaryColor;\n                                    \n                                    const btn = document.createElement('button');\n                                    btn.id = `attack-btn-${idx}`;\n                                    btn.className = 'attack-btn-dynamic';\n                                    btn.style.width = '90px';\n                                    btn.style.height = '90px';\n                                    btn.style.borderRadius = '50%';\n                                    btn.style.border = '4px solid rgba(255, 255, 255, 0.4)';\n                                    btn.style.background = `radial-gradient(circle, ${playerTop.primaryColor} 0%, #000 100%)`;\n                                    btn.style.color = 'white';\n                                    btn.style.fontFamily = 'Orbitron, sans-serif';\n                                    btn.style.fontSize = '12px';\n                                    btn.style.fontWeight = '900';\n                                    btn.style.cursor = 'pointer';\n                                    btn.style.position = 'relative';\n                                    btn.style.overflow = 'hidden';\n                                    btn.style.boxShadow = `0 0 15px ${playerTop.primaryColor}`;\n                                    btn.textContent = 'ATTACK';\n                                    \n                                    const cooldown = document.createElement('div');\n                                    cooldown.className = 'cooldown-fill';\n                                    cooldown.id = `cooldown-fill-${idx}`;\n                                    btn.appendChild(cooldown);\n\n                                    btn.addEventListener('click', () => {\n                                        if (playerTop.specialCooldowns[idx] <= 0) {\n                                            triggerSpecialMove(playerTop, idx);\n                                        }\n                                    });\n\n                                    wrapper.appendChild(label);\n                                    wrapper.appendChild(btn);\n                                    attackBtnContainer.appendChild(wrapper);\n                                });\n                            }\n\n                            // Update cooldowns\n                            playerTop.specialCooldowns.forEach((cd, idx) => {\n                                const btn = document.getElementById(`attack-btn-${idx}`);\n                                const fill = document.getElementById(`cooldown-fill-${idx}`);\n                                if (btn && fill) {\n                                    if (cd > 0) {\n                                        btn.style.filter = 'grayscale(0.8)';\n                                        const move = playerTop.stats.specials[idx];\n                                        fill.style.height = (cd / (move.cooldown || 5) * 100) + '%';\n                                    } else {\n                                        btn.style.filter = 'none';\n                                        fill.style.height = '0%';\n                                    }\n                                }\n                            });\n                        } else {\n                            attackBtnContainer.classList.remove('active');\n                        }\n                    } else {\n                        attackBtnContainer.classList.remove('active');\n                        attackBtnContainer.innerHTML = ''; // Clear for next time\n                    }\n\n                    // Draw launch trajectory\n                    drawLaunchTrajectory(ctx);\n                }\n\n                requestAnimationFrame(gameLoop);\n            }\n\n            // Initialize\n            await preloadAssets();\n            setupGameParameters();\n            setupInputHandlers();\n            initVoiceRecognition();\n\n            // Set initial name input value\n            document.getElementById('name-input').value = window.gameConfig.playerTop.name;\n\n            if (mode === 'edit') {\n                // Edit mode - show customization panel\n                showEditPanel();\n            } else {\n                // Play mode - start game\n                initGame();\n                // Instead of full panel, just start the countdown\n                // But wait, they want to choose Valtryek. \n                // Let's keep it but make it very clear how to start.\n                showEditPanel(); \n            }\n\n            // Start game loop\n            lastTime = performance.now();\n            requestAnimationFrame(gameLoop);\n        }\n    </script>\n</body>\n</html>", "game_config": "{\n  \"playerTop\": {\n    \"type\": \"balanced\",\n    \"primaryColor\": \"#4488ff\",\n    \"secondaryColor\": \"#ffcc00\",\n    \"name\": \"Blue Storm\",\n    \"weightType\": \"standard\",\n    \"heightType\": \"standard\"\n  },\n  \"settings\": {\n    \"difficulty\": \"medium\",\n    \"voiceEnabled\": false\n  },\n  \"opponentTop\": {\n    \"name\": \"Red Fury\",\n    \"type\": \"attack\",\n    \"primaryColor\": \"#ff4444\"\n  }\n}", "game_design_document": "## Core Game Loop and Mechanics\n\n**Spin Masters** is a physics-based battle game where players launch spinning tops into an arena to compete against AI opponents. The core experience centers around:\n\n1. **Launch Phase**: Players tap and drag to set launch power and angle, then release to send their top spinning into the arena\n2. **Battle Phase**: Tops collide and interact based on physics - stronger spins and better positioning lead to knockouts\n3. **Victory Conditions**: \n   - Knock all opponent tops out of the arena, OR\n   - Be the last top spinning when all others have stopped\n4. **Progression**: Win battles to earn coins, unlock new top parts, and customize your spinner\n\nThe gameplay is compelling because:\n- Each launch feels impactful with satisfying physics and collision feedback\n- Strategic depth comes from choosing launch position, power, and timing\n- Customization allows players to build tops that match their playstyle\n- Quick rounds (30-60 seconds) make it perfect for mobile sessions\n\n## Starting Scope\n\n**First Iteration - Core Battle Experience:**\n- Single arena (circular stadium with raised edges)\n- Player's customizable top vs 2 AI opponents\n- Basic launch mechanic (tap, drag, release)\n- Physics-based spinning, collision, and arena boundaries\n- Simple part system: 3 pre-made tops with different stats (Balanced, Attack, Defense)\n- Win/lose screen with replay option\n- Touch and keyboard/mouse controls\n\n**Future Iterations:**\n- Multiple arena types with different hazards\n- More top parts and deeper customization\n- Tournament mode with multiple rounds\n- Special moves/abilities\n- Multiplayer battles\n- Achievement system\n\n## Game Perspective\n\n**Top-down perspective** - Bird's eye view of the circular arena, allowing players to see all tops and plan their launch strategy. The camera is fixed, showing the entire arena at all times.\n\n## Game World and Level Design\n\n**The Arena:**\n- Circular stadium approximately 500px diameter (scaled to fit the 720px width)\n- Raised outer rim that prevents easy knockouts - tops must have enough momentum to escape\n- Smooth inner surface where tops spin and collide\n- Stadium positioned in the upper 60% of screen (leaving bottom 40% for controls)\n\n**Visual Layout:**\n- Arena centered horizontally at approximately y=400px from top\n- Launch zone indicator shows where player will launch from (bottom edge of arena)\n- Top stats/health bars displayed at top of screen\n- Launch power meter and angle indicator in bottom control area\n\n**Physics Design:**\n- Tops lose spin energy over time (friction)\n- Collisions transfer momentum based on relative speeds and angles\n- Heavier tops (Defense type) are harder to knock out but spin slower\n- Lighter tops (Attack type) move faster but are easier to knock out\n- Arena boundaries provide bounce-back with energy loss\n\n## Edit Mode Design\n\nPlayers can customize their spinning top before battle:\n\n**Customizable Properties:**\n- **Top Selection**: Choose from 3 pre-made top types:\n  - **Balanced**: Medium weight, medium speed, medium defense (all stats = 5/10)\n  - **Attack**: Light weight, high speed, low defense (speed=8, power=7, defense=3)\n  - **Defense**: Heavy weight, low speed, high defense (speed=3, power=5, defense=9)\n- **Color Scheme**: Primary and secondary colors for the top (color pickers)\n- **Name**: Custom name for your top (text input, max 15 characters)\n\n**Edit Mode UI:**\n- Top preview showing selected configuration spinning in center\n- Part selection buttons with stat bars\n- Color pickers for customization\n- \"Ready to Battle\" button to start game\n\n**Constraints:**\n- Must select one of the 3 top types (no mixing parts in first iteration)\n- Colors must have sufficient contrast for visibility\n- Name must be family-friendly (basic filter for common inappropriate words)\n\n## Control Design\n\n**Mobile (Touch) Controls:**\n\n*Launch Phase:*\n- Tap and hold anywhere in the bottom control area to begin aiming\n- Drag finger to adjust launch angle (left/right arc around arena edge)\n- Drag distance from initial touch determines launch power (visual meter fills)\n- Release to launch the top\n- Launch position is fixed at bottom of arena, only angle and power are adjustable\n\n*Battle Phase:*\n- No direct control - watch the battle unfold\n- Tap \"Launch Again\" button if your top stops spinning (costs one retry, max 1 per battle)\n\n**Desktop (Keyboard/Mouse) Controls:**\n\n*Launch Phase:*\n- Click and hold in bottom control area to begin aiming\n- Move mouse left/right to adjust launch angle\n- Mouse distance from click point determines power\n- Release mouse button to launch\n\n*Battle Phase:*\n- Click \"Launch Again\" button for retry\n- Space bar as alternative for retry button\n\n**Control Implementation Details:**\n- Launch angle visualized with an arrow/trajectory line from launch point\n- Power meter shows as a filling bar (0-100%)\n- Minimum power threshold (20%) to prevent accidental weak launches\n- Maximum power capped at 100%\n- Clear visual feedback during drag (arrow pulses, meter color changes)\n- Haptic feedback on mobile for launch moment\n\n## Art Style and Visual Theme\n\n**Art Style: Vibrant Anime-Inspired 3D**\n- Clean, colorful aesthetic inspired by the Beyblade anime\n- Tops rendered with metallic sheen and energy effects\n- Dynamic motion blur and particle effects during spins and collisions\n- Bold outlines and high contrast for readability\n\n**Color Palette:**\n- Arena: Cool grays and blues with metallic rim\n- Tops: Bright, saturated colors (reds, blues, yellows, greens) with metallic accents\n- Effects: Glowing energy trails, spark particles on collision\n- UI: Dark background with neon accents for buttons and meters\n\n**Visual Elements:**\n- Tops: ~80-100px diameter when viewed from above, with visible spinning motion\n- Spin trails: Colored energy trails that fade behind moving tops\n- Collision effects: Bright spark bursts and screen shake on impact\n- Arena surface: Subtle radial gradient, slight texture for depth\n- Speed lines: Radiating from fast-moving tops\n\n**Asset vs Code Rendering:**\n- **Generated Assets**: \n  - Top designs (3 distinct types with different shapes)\n  - Arena stadium (top-down view)\n  - UI elements (buttons, meters, icons)\n  - Particle effects (sparks, energy trails)\n  - Background elements\n- **Code Rendering**:\n  - Launch trajectory line (canvas)\n  - Power meter fill (CSS/canvas)\n  - Spin rotation animation (CSS transform)\n  - Health/spin energy bars (CSS)\n  - Collision detection visualization (canvas)\n\n## Additional Game-Specific Elements\n\n**AI Opponent Behavior:**\n- AI tops launch automatically 0.5-1 second after player launches\n- AI chooses random launch angles (avoiding direct collision with player initially)\n- AI launch power varies by difficulty: 60-80% power\n- 2 AI opponents with different top types (ensures variety)\n\n**Spin Energy System:**\n- Each top starts with 100% spin energy\n- Energy depletes over time (loses ~2% per second)\n- Collisions drain energy from both tops (more from lighter top)\n- Top stops spinning at 0% energy\n- Visual indicator: Glow intensity and trail length decrease with energy\n\n**Battle Flow:**\n1. Edit mode: Customize top\n2. Pre-battle: \"3, 2, 1, Let it rip!\" countdown with dramatic zoom\n3. Launch phase: Player launches (5 second window)\n4. AI launches follow\n5. Battle phase: Physics simulation until win/lose condition\n6. Results screen: Winner announced, coins earned, replay/customize options\n\n**Audio Design:**\n- Intense background music during battle\n- Satisfying \"whoosh\" sound on launch\n- Metallic collision sounds with pitch variation\n- Spinning hum that changes with speed\n- Victory/defeat fanfares", "persistent_storage_config": null, "game_metadata": {"game_id": "01KSC4K8WCFVF5Z3A6TADXRJ7T", "title": "Beyblade burst", "description": "Battle spinning tops in an intense arena showdown! Launch your Beyblade-style spinner, knock out opponents, and be the last top standing to win.", "thumbnail_url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/thumbnail_2d1bcbc1-5ec0-4b12-97f0-c682bd906f3a.webp", "created_at": 1779608520, "updated_at": 1780037395163.653, "art_style": null}}