{"asset_map": {"bat_bai_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_idle_ffe01925-01eb-463b-91f5-23ada1435007.webp", "type": "image", "prompt": "Generate a full-body side view of a stocky, strong stick figure character in an idle stance, facing right. Features a simple circular head, thick blue lines (#4A90E2) for the body, and steel gray (#7B8D93) outlines. Modern, clean 2D game asset style, standing illustration on a transparent background.", "description": "Idle pose for the stocky blue stick figure character 'B\u1ea5t B\u1ea1i'", "subtype": "character", "aspect_ratio": [576, 1229], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_walk_81d91086-2c02-42f1-a974-0c86a3ec902a.webp", "type": "image", "prompt": "Generate the same stocky stick figure from image 1 in a walking pose, mid-stride with one leg forward and arms swinging, facing right. Maintain blue (#4A90E2) and steel gray colors, clean lines, side view, transparent background.", "description": "Walking animation frame for B\u1ea5t B\u1ea1i", "subtype": "character", "aspect_ratio": [677, 1243], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_jump_bcde1a30-234a-4904-aece-a9e964acca16.webp", "type": "image", "prompt": "Generate the same stocky stick figure from image 1 in a jumping pose, legs bent upward and arms raised slightly for momentum, facing right. Blue and steel gray colors, clean lines, side view, transparent background.", "description": "Jumping pose for B\u1ea5t B\u1ea1i", "subtype": "character", "aspect_ratio": [645, 939], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_ability1_c8cf1357-eb76-4929-8058-d95900244b61.webp", "type": "image", "prompt": "Generate the stocky blue stick figure from image 1 in a defensive stance with arms crossed and legs wide, facing right. Surround the character with a glowing blue energy aura. Transparent background, high resolution, professional game effect.", "description": "B\u1ea5t B\u1ea1i using Fortify Defense ability", "subtype": "character", "aspect_ratio": [662, 1213], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_ability2_9a1e5f4e-abce-4626-8c3b-5ce4fbc40b63.webp", "type": "image", "prompt": "Generate the stocky blue stick figure from image 1 facing right, holding a large translucent blue rectangular shield in front. The shield should look like energy/steel. Side view, transparent background, clean game asset.", "description": "B\u1ea5t B\u1ea1i using Steel Shield ability", "subtype": "character", "aspect_ratio": [652, 1230], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_ability3_2cb51e2c-76e6-4ff8-a192-098d491d699c.webp", "type": "image", "prompt": "Generate the stocky blue stick figure from image 1 in a powerful punching pose, leaning forward with a thrusting fist, facing right. Include white motion lines and a yellow impact effect burst at the fist. Side view, transparent background.", "description": "B\u1ea5t B\u1ea1i performing a Knockback Punch", "subtype": "character", "aspect_ratio": [807, 863], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_hit_e251d471-55ea-4d2d-8f70-af0bb782a124.webp", "type": "image", "prompt": "Generate the stocky blue stick figure from image 1 in a recoil pose, leaning back as if struck, arms up defensively, facing right. Side view, clean lines, transparent background.", "description": "B\u1ea5t B\u1ea1i in a hit/damage recoil pose", "subtype": "character", "aspect_ratio": [697, 1184], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_victory_85db2e70-fa08-464a-8719-44ff05b64f80.webp", "type": "image", "prompt": "Generate the stocky blue stick figure from image 1 in a victory pose, both arms raised triumphantly, facing forward. Maintain the thick blue lines and clean stick figure style. Transparent background.", "description": "Victory pose for B\u1ea5t B\u1ea1i", "subtype": "character", "aspect_ratio": [768, 1183], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_idle_c68a76e1-538a-4727-8920-e46d14c25580.webp", "type": "image", "prompt": "Generate a full-body side view of a lean, agile stick figure character in an idle stance, facing right. Features a circular head, thin purple lines (#9B59B6) for the body, and dark gray (#2C3E50) outlines. Modern 2D game asset style, transparent background.", "description": "Idle pose for the lean purple stick figure 'B\u00f3ng \u0110\u00eam'", "subtype": "character", "aspect_ratio": [437, 1354], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_walk_1ee855ab-9200-4338-8bf0-83a9501c9621.webp", "type": "image", "prompt": "Generate the lean purple stick figure from image 1 in a dynamic walking pose, mid-stride with thin lines suggesting speed, facing right. Side view, transparent background, clean lines.", "description": "Walking pose for B\u00f3ng \u0110\u00eam", "subtype": "character", "aspect_ratio": [640, 1229], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_jump_6d9f7750-c677-485d-8431-0fb83c99c82e.webp", "type": "image", "prompt": "Generate the lean purple stick figure from image 1 in a high jump pose, legs tucked up and arms spread for balance, facing right. Dynamic 2D action pose, transparent background.", "description": "High jumping pose for B\u00f3ng \u0110\u00eam", "subtype": "character", "aspect_ratio": [792, 686], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_ability1_8f9da187-70f7-4f43-a0c1-273595ddca36.webp", "type": "image", "prompt": "Generate the lean purple stick figure from image 1 in a throwing motion, arm extended forward releasing a projectile, body twisted, facing right. Side view, transparent background.", "description": "B\u00f3ng \u0110\u00eam throwing a projectile", "subtype": "character", "aspect_ratio": [769, 1178], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_ability2_0fd27e76-d7d4-42c8-a587-509d041fe535.webp", "type": "image", "prompt": "Generate the lean purple stick figure from image 1 in a horizontal dashing pose, body leaning forward dramatically with purple motion blur trails and afterimage effects, facing right. Transparent background.", "description": "B\u00f3ng \u0110\u00eam using Shadow Dash", "subtype": "character", "aspect_ratio": [770, 567], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_ability3_139aa56e-bfa2-428f-8d11-ae1068155ffd.webp", "type": "image", "prompt": "Generate the lean purple stick figure from image 1 in a rapid attack pose with multiple ghost-like arms suggesting fast strikes, facing right. Include purple slash marks and strike effects. Transparent background.", "description": "B\u00f3ng \u0110\u00eam using Assassination Combo", "subtype": "character", "aspect_ratio": [826, 1167], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_hit_5fe55204-cc13-4e4a-b368-d372d3cb606e.webp", "type": "image", "prompt": "Generate the lean purple stick figure from image 1 recoiling from damage, body bent backward, arms up, facing right. Side view, transparent background.", "description": "B\u00f3ng \u0110\u00eam in a hit recoil pose", "subtype": "character", "aspect_ratio": [607, 1209], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_victory_0ef858b1-135c-45e4-ab0d-5f01c42d31ea.webp", "type": "image", "prompt": "Generate the lean purple stick figure from image 1 in a confident victory pose, one arm raised and one on hip, facing forward. Transparent background.", "description": "Victory pose for B\u00f3ng \u0110\u00eam", "subtype": "character", "aspect_ratio": [497, 1173], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "shuriken_projectile": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shuriken_projectile_089084ca-a98a-40a4-a3b0-916b2a77859c.webp", "type": "image", "prompt": "Create a dark purple and black spinning shuriken throwing star with a subtle motion blur trail. Minimalist, clean 2D game asset, transparent background.", "description": "Spinning shadow shuriken projectile", "subtype": "effect", "aspect_ratio": [960, 781], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "impact_effect": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/impact_effect_5b227ee1-8fe0-4046-a471-7efc58402b83.webp", "type": "image", "prompt": "Generate a bright yellow and white radial impact burst. Explosive lines emanating from a central point, stylized action game effect, transparent background.", "description": "Hit impact visual effect", "subtype": "effect", "aspect_ratio": [1073, 951], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "arena_background": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/arena_background_278b1b6c-97d4-4b83-976d-a62e7a87e570.webp", "type": "image", "prompt": "Generate a 9:16 tall portrait image of a clean, minimalist 2D fighting arena. Neutral light gray gradient background with subtle geometric patterns. A clear dark gray ground platform occupies the bottom third. Professional, non-distracting background.", "description": "Minimalist fighting game arena background", "subtype": "background", "aspect_ratio": [1024, 1536], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "bat_bai_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bat_bai_portrait_438327b2-b0ba-485a-b8de-2c6feae9f8df.webp", "type": "image", "prompt": "Generate a high-quality character portrait of the blue stocky stick figure B\u1ea5t B\u1ea1i. Confident standing pose, facing forward, thick blue lines with steel gray accents. Clean background, suitable for a character select screen.", "description": "Selection portrait for B\u1ea5t B\u1ea1i", "subtype": "ui", "aspect_ratio": [585, 1247], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bong_dem_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bong_dem_portrait_f7216bda-2288-42fc-87a6-6e418188a476.webp", "type": "image", "prompt": "Generate a high-quality character portrait of the purple lean stick figure B\u00f3ng \u0110\u00eam. Confident standing pose, facing forward, thin purple lines with dark gray accents. Clean background, suitable for a character select screen.", "description": "Selection portrait for B\u00f3ng \u0110\u00eam", "subtype": "ui", "aspect_ratio": [399, 1247], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_bat_bai": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_bat_bai_1a3be47a-d855-4150-b4dd-dc5a16bd6c4b.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Fortify Defense' ability. Simple shield symbol with a blue glow. Clean vector style, blue color palette, transparent background.", "description": "Fortify Defense ability icon", "subtype": "ui", "aspect_ratio": [488, 579], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_bat_bai": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_bat_bai_66d3916d-9e40-4fb9-a0bf-7ead65b4e45e.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Steel Shield' ability. Simple solid steel shield symbol. Clean vector style, steel gray and blue colors, transparent background.", "description": "Steel Shield ability icon", "subtype": "ui", "aspect_ratio": [667, 832], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_bat_bai": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_bat_bai_1e319aa9-de76-4ae5-9080-dd0ab67e0718.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Knockback Punch' ability. Simple fist icon with impact lines. Clean vector style, blue and white colors, transparent background.", "description": "Knockback Punch ability icon", "subtype": "ui", "aspect_ratio": [849, 685], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_bong_dem": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_bong_dem_24f4f95e-c326-497c-92ba-08b6746e8293.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Shadow Shuriken' ability. Simple shuriken star symbol. Clean vector style, purple and dark gray color palette, transparent background.", "description": "Shadow Shuriken ability icon", "subtype": "ui", "aspect_ratio": [708, 722], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_bong_dem": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_bong_dem_521be2cc-8b37-45f4-9add-bacd8eb735f2.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Shadow Dash' ability. Simple motion lines and a dash symbol. Clean vector style, purple color palette, transparent background.", "description": "Shadow Dash ability icon", "subtype": "ui", "aspect_ratio": [760, 782], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_bong_dem": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_bong_dem_0981d5f4-2bc2-4ed2-b2e8-f4bfb21b7913.webp", "type": "image", "prompt": "Create a minimalist UI icon for an 'Assassination Combo' ability. Simple multiple slash marks symbol. Clean vector style, purple and dark gray, transparent background.", "description": "Assassination Combo ability icon", "subtype": "ui", "aspect_ratio": [841, 843], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "punch_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/punch_sfx_720939a5-c6e7-40a3-b6ab-f22028e4567a.mp3", "type": "audio", "prompt": "Sharp, punchy fist impact sound effect for a 2D fighting game. Immediate snappy attack with a solid low-mid thud. Clean, satisfying impact with a very short decay. High-quality foley, no reverb.", "description": "Short, punchy impact sound for basic melee strikes.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.45, "loop": false, "animation": null}, "shield_activate_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/shield_activate_sfx_1fbdcae7-78d3-4dc4-9826-023f1927be62.mp3", "type": "audio", "prompt": "Resonant metallic shield activation sound. A clean 'shing' or chime followed by a brief hum of energy protection. Suggests solid steel and magical reinforcement. High-fidelity, defensive tone.", "description": "Metallic defensive sound for the Steel Shield ability.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2, "loop": false, "animation": null}, "dash_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/dash_sfx_77bcda5e-a75d-4752-9ac6-ec349182ba16.mp3", "type": "audio", "prompt": "Fast, airy whoosh sound effect. High-speed wind displacement, quick burst of movement. Clean and sharp, suitable for a ninja-style character dash. Minimal low-end, high-frequency focus.", "description": "Quick airy whoosh for the Shadow Dash movement.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.04, "loop": false, "animation": null}, "shuriken_throw_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/shuriken_throw_sfx_c8dec325-f790-46c6-8bab-fde0e65d35d3.mp3", "type": "audio", "prompt": "Sharp cutting sound effect of a small metallic object being thrown. Quick 'zip' or 'swish' with a slight metallic ring. High-speed projectile release, concise and clean.", "description": "Sharp cutting sound for the Shadow Shuriken projectile.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 0.71, "loop": false, "animation": null}, "combo_attack_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/combo_attack_sfx_c3d8386d-8bec-4609-bc1f-fa882f6fcf10.mp3", "type": "audio", "prompt": "A rapid flurry of 4 distinct hit sounds in quick succession. Sharp, rhythmic slashing and impact sounds. High-speed martial arts combo effect with a final slightly heavier impact sound.", "description": "Rapid succession of strike sounds for the Assassination Combo.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 0.99, "loop": false, "animation": null}, "hit_damage_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/hit_damage_sfx_946a56b5-623f-4711-84dc-0926419883d5.mp3", "type": "audio", "prompt": "Solid body impact thud, slightly muffled, suggesting a hit to a person. A short 'ugh' or dry impact sound without being overly bloody. Clear feedback for player taking damage.", "description": "Impact thud sound for when a stick figure takes damage.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 0.86, "loop": false, "animation": null}, "victory_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/victory_sfx_f108d674-cda9-400f-8536-36888adaa4ed.mp3", "type": "audio", "prompt": "A short, triumphant orchestral or electronic fanfare. Bright major keys, rising melody, celebratory energy. Includes a final sustained chord with shimmering sparkle effects.", "description": "Triumphant fanfare for the win screen.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.06, "loop": false, "animation": null}, "defeat_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/defeat_sfx_b66537c5-45b9-4db5-b7b5-9fe6812bb687.mp3", "type": "audio", "prompt": "A descending musical phrase for a game-over screen. Muted brass or cello, negative but not harsh. A sense of failure or falling. Brief and clean resolution.", "description": "Somber, descending sound for the lose screen.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.15, "loop": false, "animation": null}, "menu_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/menu_music_36801bef-dabd-41dd-81da-a997d899d0bb.mp3", "type": "audio", "prompt": "Upbeat, energetic electronic background music for a game menu. Modern synth-pop style, 120 BPM, clean driving beat, optimistic and inviting. Polished production, seamless loopable structure.", "description": "Energetic electronic theme for the main menu.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30, "loop": true, "animation": null}, "combat_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/combat_music_7a10afc4-b488-48ad-9d58-63fd46250d35.mp3", "type": "audio", "prompt": "Intense fast-paced combat music, 145 BPM. Aggressive synth-rock or drum and bass. Driving percussion, heavy bassline, high-energy rhythmic textures. Exciting and immersive for a fighting game. Seamless loop.", "description": "Intense, high-tempo battle music for 1v1 fights.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30, "loop": true, "animation": null}, "itachi_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_portrait_8ff3ffc1-123e-4960-829f-1ad76943fa40.webp", "type": "image", "prompt": "Generate a character selection portrait for a stick figure character named ITACHI. The character is a lean black stick figure wearing a minimalist stylized black cloak with red cloud patterns. The stick figure has glowing red eyes. Minimalist 2D vector art style, dark and moody background, consistent with the clean aesthetic of existing character portraits. Professional game UI asset, centered composition.", "description": "A minimalist character selection portrait for the stick figure character ITACHI with glowing red eyes and Akatsuki cloak.", "subtype": "ui", "aspect_ratio": [1024, 1024], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_idle_bf1b007f-227c-4cb7-b0c2-1c06cd203db9.webp", "type": "image", "prompt": "Generate a full-body, front-facing illustration of a lean black stick figure character named ITACHI. The character wears a stylized black cloak decorated with red clouds. He has glowing red eyes and a calm, standing posture with the cloak slightly swaying. Minimalist 2D vector art style, clean lines, professional game-ready asset, transparent background, consistent with the style of image 1.", "description": "Idle pose for the ITACHI character, a lean black stick figure in a red-cloud cloak.", "subtype": "character", "aspect_ratio": [830, 802], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_walk_66f15be3-ef32-4603-a83f-8d8d41e835c2.webp", "type": "image", "prompt": "Generate a side-view, right-facing walking animation frame for a lean black stick figure character named ITACHI. The character is wearing a stylized Akatsuki-style black cloak with red clouds and has glowing red eyes. Minimalist 2D art style, clean lines, consistent with image 1 and image 2. Standing illustration on a transparent background, high resolution, game-ready asset.", "description": "Walking animation frame for the ITACHI stick figure character.", "subtype": "character", "aspect_ratio": [622, 918], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "itachi_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_jump_e73b02d8-8c60-4bd0-b61e-c44def461700.webp", "type": "image", "prompt": "Generate a full-body side view of a lean black stick figure character named ITACHI in a high jumping pose. The character is wearing a minimalist black cloak with red cloud patterns (Akatsuki style) that is trailing behind him in the air. He has glowing red eyes. Minimalist 2D art style, clean lines, professional quality, transparent background.", "description": "High jumping pose for the ITACHI stick figure character with a trailing Akatsuki cloak.", "subtype": "character", "aspect_ratio": [735, 727], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_ability1_8785b9b5-c3ee-454c-8d9c-c66490944c67.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of ITACHI performing a Fireball Jutsu. The character is a lean black stick figure wearing a black cloak decorated with red clouds, featuring glowing red eyes. Posed in a side view, right-facing, making hand signs with small orange and red flames emerging from the mouth area. Clean lines, game-ready asset, transparent background, matching the style of image 1.", "description": "Stick figure ITACHI performing a Fireball Jutsu with flames and hand signs", "subtype": "effect", "aspect_ratio": [532, 961], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "itachi_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_ability2_dfe8bcd3-30c1-4239-8bac-263a73212f58.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view stick figure illustration of ITACHI partially dissolving into a flock of small black crows. The character is a lean black stick figure wearing a black cloak with red cloud patterns and has glowing red eyes. Some crows are flying away from his body as he fades. Clean lines, stylized game asset, high resolution, transparent background.", "description": "The ITACHI stick figure character partially dissolving into black crows for the Crow Clone ability", "subtype": "effect", "aspect_ratio": [716, 905], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_ability3_d16641ae-3531-40e4-abcc-a75706b67d71.webp", "type": "image", "prompt": "Generate a full-body, side-view illustration of a lean black stick figure character named ITACHI. The character is wearing a stylized black cloak with red cloud patterns. He has intense, glowing red eyes with a swirling Mangekyo pattern. A dark purple and black energy aura surrounds the character. Minimalist 2D art style, clean lines, game-ready asset, transparent background.", "description": "ITACHI stick figure activating Mangekyo Sharingan with a dark aura", "subtype": "character", "aspect_ratio": [584, 962], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_hit_65f9cb73-11ff-4ff1-be73-1236d8d75f4c.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view illustration of a lean black stick figure character named ITACHI in a hit/damage recoil pose. The character is wearing a black cloak with red clouds (Akatsuki-style) and has glowing red eyes. The pose should show the character being pushed back or reeling from an impact, with the cloak flowing back. Match the artistic style and character design of image 1. Transparent background, high resolution, game-ready asset.", "description": "ITACHI stick figure in a hit/damage recoil pose", "subtype": "character", "aspect_ratio": [785, 818], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "itachi_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_victory_a6eaa05e-bd98-4398-9990-61ab574b6a7a.webp", "type": "image", "prompt": "Generate a full-body victory pose for a stick figure character named ITACHI. The character is a lean black stick figure wearing a stylized black cloak with red clouds (Akatsuki style). He is standing with his back partially turned to the camera, looking back over his shoulder with one glowing red eye. The cloak is blowing heroically in the wind. Minimalist 2D art style consistent with a fighting game, high resolution, clean lines, professional quality, transparent background.", "description": "Victory pose for the ITACHI stick figure character showing him looking over his shoulder.", "subtype": "character", "aspect_ratio": [774, 916], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_itachi": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_itachi_a30120fb-4c0d-49d5-8991-dc500dbdb7fc.webp", "type": "image", "prompt": "Generate a UI icon for an ability called 'Fireball Jutsu'. A bright orange and red stylized fireball centered on a dark circular background. Clean minimalist 2D vector style, high contrast, game-ready UI element, consistent with other ability icons.", "description": "Icon for ITACHI's 'Fireball Jutsu' ability featuring a stylized orange and red fireball.", "subtype": "ui", "aspect_ratio": [908, 907], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_itachi": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_itachi_4e5654d0-f62b-4556-8581-703f7034624e.webp", "type": "image", "prompt": "Generate a minimalist 2D vector icon for a 'Crow Clone' ability. The icon should feature a sharp silhouette of a black crow centered on a dark circular background. Maintain a clean, polished game UI style that matches the minimalist aesthetic of image 1. High resolution, professional quality, transparent background around the circular frame.", "description": "Icon for ITACHI's 'Crow Clone' ability featuring a black crow silhouette", "subtype": "ui", "aspect_ratio": [527, 530], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_itachi": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_itachi_be7babc8-45b4-40a9-881b-05c03dce3b37.webp", "type": "image", "prompt": "Generate a minimalist 2D vector icon for an ability called 'Tsukuyomi'. The icon features a stylized red eye with a black swirling comma pattern (Mangekyo Sharingan) centered on a dark circular background. Clean lines, professional game UI quality, high contrast, matching the minimalist style of image 1 and image 2.", "description": "Icon for ITACHI's 'Tsukuyomi' ultimate ability featuring a Mangekyo Sharingan eye", "subtype": "ui", "aspect_ratio": [1022, 1021], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "fireball_projectile": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/fireball_projectile_48488157-df8d-4967-ae84-53b461c5d476.webp", "type": "image", "prompt": "Generate a minimalist 2D game asset of a bright, glowing orange-red fireball with a wispy flame trail. Stylized vector art, side view, right-facing, vibrant colors, clean edges, professional quality, transparent background.", "description": "A bright orange-red fireball projectile with a trail, matching the minimalist stick figure style.", "subtype": "effect", "aspect_ratio": [770, 399], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "fireball_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/fireball_sfx_7197c6cb-5dac-4f98-ba88-407318f7ba65.mp3", "type": "audio", "prompt": "Powerful fire ignition and launch sound effect. Starts with a sharp 'foomph' of combustion followed by a sustained, roaring fiery whoosh as the projectile travels. Elements of crackling embers and high-pressure air displacement. Dynamic, cinematic, and magical, fitting for a ninja jutsu ability. Clean tail with a slight heat shimmer texture.", "description": "A powerful sound effect of fire igniting and a projectile launching, used for a fireball jutsu.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3.14, "loop": false, "animation": null}, "crow_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/crow_sfx_3417f80a-4830-4b7a-954d-70d82f13d998.mp3", "type": "audio", "prompt": "A quick, frantic fluttering sound of multiple bird wings flapping rapidly, followed by a singular, faint, high-pitched crow caw. The sound should feel supernatural and swift, with a ghostly reverb tail. Designed for a ninja-style ability where the character disappears into a cloud of crows. Clean, sharp attack, organic textures, suitable for frequent in-game use.", "description": "Sound effect of wings fluttering and a distant crow caw for a clone ability.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.48, "loop": false, "animation": null}, "luffy_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_portrait_bfcd7ea3-e146-4a4e-9f1a-5469bf9f3e44.webp", "type": "image", "prompt": "A minimalist character selection portrait of a stick figure character named Luffy. He features a simple black stick-man body wearing an iconic yellow straw hat with a red band and a simple open red vest. Professional clean lines, flat colors, minimalist game-ready aesthetic. Head and shoulders view. Match the art style and framing of itachi_portrait and bat_bai_portrait. Transparent background, high resolution.", "description": "Minimalist character selection portrait for Luffy in a stick figure style with a straw hat.", "subtype": "ui", "aspect_ratio": [465, 824], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_idle_a1f7c7e6-ec80-486d-a8de-30ed961b9c7e.webp", "type": "image", "prompt": "Generate a full-body, front-facing idle pose of a minimalist stick figure character named Luffy. The character is a lean red stick figure wearing a classic yellow straw hat with a red band and blue shorts. Simple, clean lines, side-view perspective suitable for a fighting game. Professional game asset style with a transparent background, matching the minimalist aesthetic of image 1.", "description": "Idle standing pose for the Luffy stick figure character with straw hat and red vest.", "subtype": "character", "aspect_ratio": [472, 1225], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_walk_40e912e4-ace1-49cd-a570-36559162636d.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for a minimalist red stick figure character named Luffy. The character is wearing a distinctive straw hat and blue shorts, captured mid-stride. Maintain the same minimalist, clean art style as in luffy_idle. High resolution, professional quality game asset, transparent background.", "description": "Walking animation frame for the Luffy stick figure character.", "subtype": "character", "aspect_ratio": [529, 1185], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_jump_0233d1fe-b1ef-4920-9b74-e0a98cd508f6.webp", "type": "image", "prompt": "Generate a side-view illustration of a lean red stick figure character representing Luffy, wearing a signature straw hat and blue shorts. The character is in a high jumping pose with legs tucked. Minimalist art style, clean lines, polished game-ready asset. Full body picture, transparent background.", "description": "A jumping pose for the Luffy stick figure character with tucked legs and a straw hat.", "subtype": "character", "aspect_ratio": [409, 913], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_ability1_65683852-b2a1-4aca-80ed-9d049ac31e09.webp", "type": "image", "prompt": "Generate a minimalist red stick figure character based on image 1, performing the 'Gomu Gomu no Pistol' attack. The character is wearing a straw hat and one arm is stretched out very long horizontally. Side view, right-facing, standing illustration, clean lines, polished game-ready asset, transparent background, high resolution.", "description": "Luffy stick figure character performing a Gomu Gomu no Pistol attack with a long stretched arm.", "subtype": "character", "aspect_ratio": [1147, 832], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_ability2_2b25c846-209e-4d92-a992-42e07a08a0b6.webp", "type": "image", "prompt": "Generate a side-view illustration of a lean red stick figure character named Luffy, wearing a straw hat and blue shorts, in a 'Gomu Gomu no Rocket' pose. He is crouched low, arms stretched far behind him as if preparing to slingshot forward. Minimalist stick figure art style consistent with luffy_idle and bat_bai_idle. High resolution, clean lines, professional game asset, transparent background.", "description": "Luffy stick figure in a 'Rocket' pose, preparing to dash", "subtype": "character", "aspect_ratio": [807, 765], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_ability3_b1613fc3-7195-4077-97ad-c33b5148a186.webp", "type": "image", "prompt": "Generate a high-energy, full-body illustration of a minimalist stick figure character in 'H\u00f3a Th\u1ea7n Nika' (Gear 5) form. The character is entirely white with stylized curly hair and a flowing white smoke aura around the shoulders. The character is in a dynamic, joyful laughing pose. Side view, right-facing. Minimalist stick figure art style consistent with luffy_idle. Transparent background, high resolution, game-ready asset.", "description": "Luffy stick figure in Gear 5 Nika form, laughing with white smoke aura", "subtype": "character", "aspect_ratio": [738, 1214], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_hit_02682856-30fe-497c-b896-dc43efe0d302.webp", "type": "image", "prompt": "Generate a minimalist stick figure character named Luffy in a hit or damage recoil pose. The character is a red stick figure wearing a straw hat and blue shorts, reeling back from an impact. Side view, right-facing. Clean lines, simple minimalist game art style, consistent with luffy_idle and bat_bai_hit. High resolution, professional quality, transparent background.", "description": "Luffy stick figure in a hit/damage recoil pose", "subtype": "character", "aspect_ratio": [638, 1092], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_victory_6cfdcdd0-5465-4fcd-aec1-b54c326e9b98.webp", "type": "image", "prompt": "Generate a full-body, front-view victory pose for the Luffy stick figure character. The character is a lean red stick figure wearing a straw hat and blue shorts, matching the style of image 1 and image 2. He is holding his straw hat and grinning widely. Minimalist stick figure style, clean lines, professional quality, transparent background.", "description": "Victory pose for the Luffy stick figure character holding his hat and grinning.", "subtype": "character", "aspect_ratio": [512, 1232], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_luffy": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_luffy_86b461a0-f6ac-4da9-b188-9e0e57ea90c3.webp", "type": "image", "prompt": "Generate a minimalist circular UI icon for a 'Gomu Gomu no Pistol' ability. The icon features a stylized fist flying forward with a long, stretching arm trail. Clean vector style, bold colors matching the character's red and yellow palette, set against a dark circular background, consistent with ability1_icon_itachi and ability1_icon_bat_bai. High resolution, professional game UI quality, transparent background.", "description": "Ability icon for Luffy's Gomu Gomu no Pistol featuring a stretching fist", "subtype": "ui", "aspect_ratio": [807, 787], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_luffy": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_luffy_86b191e1-dc41-46eb-9a15-4e98272351c1.webp", "type": "image", "prompt": "A minimalist, circular game ability icon for 'Gomu Gomu no Rocket'. Featuring a red and black stick figure silhouette flying through the air like a rocket with speed lines. Simple flat design, vibrant colors, game-ready UI element, transparent background, matching the style of ability1_icon_luffy.", "description": "Icon for Luffy's 'Gomu Gomu no Rocket' ability, showing a stick figure silhouette flying.", "subtype": "ui", "aspect_ratio": [999, 996], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_luffy": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_luffy_9f3b11a3-a464-4739-8ee2-dc21d60ab384.webp", "type": "image", "prompt": "A minimalist circular game ability icon for Luffy's 'H\u00f3a Th\u1ea7n Nika' form. The design should feature a stylized white silhouette of Gear 5 Luffy with curly hair/smoke aura or a sun symbol. Use a bright, high-energy color palette with whites and yellows. Clean, flat vector style, professional quality, transparent background, consistent with ability1_icon_luffy and ability2_icon_luffy.", "description": "Icon for Luffy's 'H\u00f3a Th\u1ea7n Nika' (Gear 5) ability featuring a minimalist sun symbol and white silhouette.", "subtype": "ui", "aspect_ratio": [1022, 1024], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "madara_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_portrait_b3afa29b-5166-4c33-8c21-a4c098459cb9.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for the stick figure character Madara Uchiha. Featuring long spiky black hair, glowing red sharingan eyes, and wearing red samurai-style chest armor. Clean, polished game-ready icon, flat design with bold outlines, consistent with the art style of image 1. Transparent background, high resolution.", "description": "Minimalist character selection portrait for Madara Uchiha in a stick figure style.", "subtype": "ui", "aspect_ratio": [321, 794], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "madara_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_idle_1eb3400a-7e28-48cf-a492-5b78ef92b26d.webp", "type": "image", "prompt": "Generate a full-body, side view right-facing minimalist stick figure character named Madara. The character is a lean black stick figure with long, messy spiky black hair, wearing iconic red samurai-style chest armor. He is standing in a confident idle pose with his arms crossed over his chest. Clean lines, professional game-ready asset, transparent background, matching the style of itachi_idle and bat_bai_idle.", "description": "Idle standing pose for the Madara stick figure character with red armor and crossed arms.", "subtype": "character", "aspect_ratio": [500, 1231], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "madara_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_walk_d8915dbb-333d-41e6-9a65-e5ceea9e5f6e.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for a minimalist stick figure character named Madara. The character should have long spiky black hair and red samurai-style armor. He is moving forward with a determined stride. Maintain a clean, minimalist 2D fighting game style consistent with image 1. High resolution, transparent background.", "description": "Walking animation frame for the Madara stick figure character.", "subtype": "character", "aspect_ratio": [561, 1222], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "madara_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_jump_f7ae1d16-1fe8-4171-9f41-d2b7de2865e1.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Madara Uchiha in a jumping pose. The character is a lean black stick figure with long, spiky black hair flowing upwards, wearing red samurai-style armor. High jumping action pose, side view, clean lines, professional game-ready asset, transparent background, matching the style of image 1.", "description": "Jumping animation pose for the Madara stick figure character with upward-flowing hair.", "subtype": "character", "aspect_ratio": [594, 1088], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "madara_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_ability1_10776f26-4e7e-4a72-8d6e-1c3243c4c1c2.webp", "type": "image", "prompt": "Generate a side view, right-facing minimalist stick figure of Madara Uchiha with long spiky hair and red armor, performing an attack. A large, translucent blue ethereal Susanoo arm holding a sword emerges from behind him, slashing forward. Clean lines, minimalist aesthetic, professional game asset quality, transparent background.", "description": "Madara stick figure performing an attack with a blue ethereal Susanoo arm and sword.", "subtype": "character", "aspect_ratio": [736, 1211], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "madara_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_ability2_f35c627b-1027-4b76-bc35-7b77cd817c49.webp", "type": "image", "prompt": "Generate a minimalist stick figure character named Madara with long spiky black hair and red samurai armor, surrounded by a semi-transparent, glowing blue ethereal Susanoo ribcage acting as a shield. Side view, right-facing. Clean vector style, professional game asset, transparent background, high resolution, matching the style of 'madara_idle'.", "description": "Madara stick figure surrounded by a blue ethereal Susanoo ribcage for defense.", "subtype": "effect", "aspect_ratio": [580, 1247], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "madara_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_ability3_d6f7692d-ace1-45e4-af56-edead6e2ab42.webp", "type": "image", "prompt": "Generate a minimalist side-view illustration of a black stick figure character with long spiky hair and red samurai armor, representing Madara. The character is in a dynamic throwing pose, launching several glowing blue ethereal Yasaka Magatama (comma-shaped energy projectiles) forward. Style must be clean, minimalist, and consistent with a 2D fighting game, featuring a transparent background and high-resolution details.", "description": "Madara stick figure performing his ultimate ability, throwing blue ethereal Yasaka Magatama projectiles.", "subtype": "character", "aspect_ratio": [663, 1031], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "madara_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_hit_9d4d7cdd-464d-4aef-ab48-f166510809c8.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Madara Uchiha in a hit/damage recoil pose. The character has long spiky black hair and red samurai-style armor. He is recoiling back from an impact. Maintain the exact same minimalist art style, line weight, and color palette as image 1. Side view, transparent background, high resolution.", "description": "Madara stick figure in a hit/damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [684, 1187], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "madara_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_victory_859e7ee9-e806-422a-a1e7-7db9684fdc15.webp", "type": "image", "prompt": "Generate a minimalist victory pose for the Madara stick figure character. A lean black stick figure with long spiky hair and red samurai armor, standing triumphantly atop a pile of gray rubble. He has a large circular Gunbai fan strapped to his back. Side view, right-facing character. Clean lines, flat colors, professional game-ready asset, transparent background, consistent with the style of image 1.", "description": "Victory pose for the Madara stick figure character standing on rubble with his signature fan.", "subtype": "character", "aspect_ratio": [715, 1204], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_madara": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_madara_ee56e7bb-49ec-4e8f-8dc3-56e31b258350.webp", "type": "image", "prompt": "Generate a minimalist game UI icon for an ability called 'Susanoo Slash'. The icon should feature a sharp, blue ethereal sword silhouette with a glowing energy effect. Clean, flat design, white or simple border, consistent with a fighting game interface. High contrast, professional quality, transparent background.", "description": "Icon for Madara's 'Susanoo Slash' ability featuring a blue ethereal sword silhouette.", "subtype": "ui", "aspect_ratio": [735, 745], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_madara": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_madara_b5cb5fb7-375c-482e-9204-f4513ecb6ace.webp", "type": "image", "prompt": "A minimalist game ability icon for 'Susanoo Ribcage'. Features a glowing blue ethereal ribcage silhouette centered in the frame. Clean, flat design, vector style, simple shapes, high contrast against a dark background, matching the style of ability1_icon_madara.", "description": "Ability icon for Madara's 'Susanoo Ribcage' defense ability.", "subtype": "ui", "aspect_ratio": [974, 1021], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_madara": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_madara_c5b9cb70-63d3-4ec4-ab39-7a48a5ff98bc.webp", "type": "image", "prompt": "Generate a minimalist game UI icon for an ability called 'Yasaka Magatama'. The icon should feature three blue glowing tomoe-shaped projectiles arranged in a circular pattern. Use a clean, flat design style with high contrast against a dark background, matching the minimalist aesthetic of existing ability icons like image 1 and image 2. Professional quality, centered composition, transparent background.", "description": "Icon for Madara's Yasaka Magatama ability featuring three blue tomoe-shaped projectiles in a minimalist style.", "subtype": "ui", "aspect_ratio": [466, 473], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "magatama_projectile": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/magatama_projectile_44430f5e-cc72-4fc1-a7d7-1404b7796984.webp", "type": "image", "prompt": "Generate a minimalist blue ethereal tomoe-shaped projectile (Yasaka Magatama) with a glowing energy trail. The design should be clean and stylized to match a stick figure fighting game aesthetic. The projectile should be glowing bright cyan and blue with a semi-transparent energy effect. Side view, right-facing orientation. High resolution, professional game asset, transparent background.", "description": "A blue ethereal Yasaka Magatama projectile for Madara's ability", "subtype": "effect", "aspect_ratio": [992, 701], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "susanoo_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/susanoo_sfx_fef8cf4d-aedc-4cac-99f4-92df62d7e33d.mp3", "type": "audio", "prompt": "Deep, booming ethereal activation sound effect for a massive energy avatar. The sound should begin with a low-frequency rumble and a sharp spiritual 'shimmer' attack, followed by a resonant, vibrating hum that feels divine and colossal. Incorporate elements of swirling wind, ghostly choir textures, and a heavy energy pulse. Cinematic, powerful, and supernatural, conveying immense scale and ancient power.", "description": "A powerful, ethereal activation sound for a giant energy avatar, featuring deep resonance and spiritual energy.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 4.25, "loop": false, "animation": null}, "sasuke_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_portrait_f6d1380d-3084-4c26-90ec-0634cb53e51e.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for Sasuke Uchiha in a clean stick figure style. The character should have spiky black hair and a cool, stoic expression. Use a purple background tint. Consistent with the style of image itachi_portrait and madara_portrait. High-quality, clean lines, game-ready UI asset.", "description": "Minimalist character selection portrait for Sasuke Uchiha in a stick figure style.", "subtype": "ui", "aspect_ratio": [903, 895], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_idle_9bdbe795-bc9d-49f8-a1b3-69ddd6ca2a23.webp", "type": "image", "prompt": "Generate a minimalist stick figure character named Sasuke in an idle standing pose. Lean frame, spiky black hair, wearing a high-collared blue and black outfit. Front-facing, side view, clean lines, professional game-ready asset, transparent background, matching the minimalist art style of image 1.", "description": "Idle standing pose for the Sasuke stick figure character in a minimalist style.", "subtype": "character", "aspect_ratio": [297, 877], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "sasuke_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_walk_dec387d7-0f0a-408c-b76f-bcef14f09aee.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for a minimalist Sasuke stick figure character. The character should have a lean frame, spiky black hair, and wear a high-collared blue and black outfit. Show a cool, purposeful stride. Match the minimalist art style and character design of sasuke_idle. Clean lines, flat colors, transparent background, professional game asset.", "description": "A walking animation frame for the Sasuke stick figure character with a cool, purposeful stride.", "subtype": "character", "aspect_ratio": [559, 1198], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_jump_5619ea19-f3c8-4141-a6e0-202d731e0187.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Sasuke Uchiha in a high jumping pose with one knee tucked. Side view, right-facing. The character should have lean black stick limbs, spiky black hair, and a high-collared blue and black outfit. Maintain a clean, polished, game-ready aesthetic consistent with a stick figure fighting game. High resolution, professional quality, transparent background.", "description": "A minimalist stick figure of Sasuke Uchiha in a high jumping pose with one knee tucked.", "subtype": "character", "aspect_ratio": [459, 1046], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_ability1_83640988-03ce-4207-8277-f5d830377630.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of the character Sasuke from image 1. He is in a dynamic side view combat pose, one hand charging a bright blue electrical lightning ball (Chidori). Minimalist style, clean lines, black spiky hair, high-collared outfit, transparent background, high resolution.", "description": "Sasuke stick figure character charging a bright blue Chidori lightning attack.", "subtype": "character", "aspect_ratio": [755, 941], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_ability2_821322b2-43bf-4b8c-8eb9-d8a418a8cefe.webp", "type": "image", "prompt": "Generate a minimalist side-view stick figure character of Sasuke from Naruto performing a Fireball Jutsu. The character should be in a crouching pose with hand signs near the mouth, exhaling a large, stylized orange and red fireball. Lean black stick figure frame, spiky black hair, high-collared outfit. Clean lines, minimalist aesthetic, transparent background, matching the style of sasuke_idle and fireball_projectile.", "description": "Sasuke stick figure character performing Fireball Jutsu with hand signs and orange fire.", "subtype": "character", "aspect_ratio": [947, 790], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_ability3_cac2e787-7add-4ef4-b766-9a9d640a2bb3.webp", "type": "image", "prompt": "Generate a minimalist stick figure character named Sasuke enveloped in a translucent purple ethereal Susanoo ribcage and a giant skeletal arm. The character is in a heroic, powerful pose. Match the clean, minimalist stick figure style of image 1 and image 2. Side view, right-facing, transparent background, high resolution.", "description": "Sasuke stick figure character using his Susanoo ultimate ability for defense and power.", "subtype": "effect", "aspect_ratio": [649, 1073], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_hit_85e0a432-9746-4347-8d70-e64188d2d20f.webp", "type": "image", "prompt": "Generate a minimalist stick figure character named Sasuke in a hit or damage recoil pose. The character has spiky black hair and a high-collared outfit. The pose should show the character being knocked back or reeling from an impact. Side view, right-facing, transparent background, clean lines, professional game-ready asset, matching the style of sasuke_idle.", "description": "Sasuke stick figure character in a hit/damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [541, 993], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "sasuke_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_victory_cdea9939-30f5-40d9-a5b7-51ae7bde8c6b.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Sasuke Uchiha in a victory pose. The character is shown from the back, looking over his shoulder with a cool, stoic gaze. He has spiky black hair and wears a high-collared blue and black outfit. Clean lines, minimalist aesthetic, side-view perspective, high resolution, transparent background. Match the character design and art style of sasuke_idle.", "description": "Victory pose for the Sasuke stick figure character looking over his shoulder.", "subtype": "character", "aspect_ratio": [467, 1231], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_sasuke": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_sasuke_690a49d8-c999-413b-90cf-b051e96f9375.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Chidori' ability, featuring a stylized bright blue lightning bolt and electric discharge, clean flat design, vector style, simple shapes, professional game quality, transparent background", "description": "Icon for Sasuke's Chidori ability featuring blue lightning electricity", "subtype": "ui", "aspect_ratio": [678, 725], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_sasuke": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_sasuke_a02eaaa5-7504-4462-a210-d7343f432b60.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Fireball Jutsu' ability. The icon should feature a stylized orange and red flame silhouette with clean, sharp lines. Maintain a consistent minimalist aesthetic matching the style of existing icons like ability1_icon_itachi. High contrast, simple shapes, professional game UI quality, transparent background.", "description": "A minimalist UI icon for Sasuke's Fireball Jutsu ability.", "subtype": "ui", "aspect_ratio": [735, 754], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_sasuke": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_sasuke_34e3945b-67bd-4364-a140-e2ad1e9a8769.webp", "type": "image", "prompt": "A minimalist game ability icon for a 'Susanoo' power, featuring a stylized purple ethereal helmet or ribcage silhouette. Use a clean, flat vector style with high contrast against a dark background, matching the minimalist aesthetic of image 1 and image 2. Purple glowing energy theme, professional game UI quality.", "description": "Icon for Sasuke's Susanoo ultimate ability featuring a purple ethereal silhouette", "subtype": "ui", "aspect_ratio": [606, 637], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "chidori_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/chidori_sfx_79f28490-3d19-449a-a99e-5d0a4657aedd.mp3", "type": "audio", "prompt": "High-pitched, aggressive electric crackling sound combined with the rapid, layered chirping of thousands of birds. The sound should begin with a sharp energy surge and transition into a powerful, high-velocity airy dash 'whoosh'. Convey intense electrical power, piercing resonance, and extreme speed. Cinematic quality, clean layers, no background music, suitable for a special ability activation in a combat game.", "description": "Powerful electric charging and dash sound effect inspired by the Chidori jutsu, featuring chirping and crackling elements.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3.52, "loop": false, "animation": null}, "sukuna_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_portrait_c974123a-6cdf-4632-be01-d34b299b3f85.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for a stick figure version of Sukuna from Jujutsu Kaisen. The character should have pinkish hair, signature black facial tattoos, and a menacing expression. Professional 2D stick figure art style, clean lines, high resolution, transparent background, centered composition.", "description": "Minimalist character selection portrait for Sukuna", "subtype": "character", "aspect_ratio": [680, 1450], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "sukuna_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_idle_c6a53c12-ee57-40e7-a083-5da6c44a095b.webp", "type": "image", "prompt": "Generate a 2D minimalist stick figure of Sukuna in an idle standing pose. Lean black stick figure body, distinctive pink hair, facial and body tattoos, wearing a simple white kimono. Side view, right-facing, clean lines, professional game-ready asset, transparent background, matching the minimalist style of existing stick figure characters.", "description": "Idle standing pose for the Sukuna stick figure character in a white kimono", "subtype": "character", "aspect_ratio": [583, 1245], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sukuna_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_walk_a67ca1ce-7f6f-43e6-9523-085b1860949e.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for a minimalist 2D stick figure character of Sukuna. The character has a lean black stick body, spiked pink hair, and black facial/body tattoos, wearing a simple white kimono. Clean lines, flat colors, professional game-ready asset, transparent background.", "description": "Walking animation frame for the Sukuna stick figure character with pink hair and tattoos.", "subtype": "character", "aspect_ratio": [509, 1238], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sukuna_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_jump_669b8c0b-8566-44d8-80d7-b65ddfd8665c.webp", "type": "image", "prompt": "Generate a dynamic mid-air jumping pose for a Sukuna-inspired stick figure character. Lean black stick figure with distinctive pink hair and black facial/body tattoos, wearing a simple white kimono. Side view, minimalist 2D style, clean lines, high resolution, professional game asset quality, transparent background.", "description": "Dynamic jumping pose for the Sukuna stick figure character", "subtype": "character", "aspect_ratio": [636, 852], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "sukuna_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_ability1_d6e9514b-315d-4af6-99b3-3925dbd28a2d.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Sukuna performing a 'Dismantle' slash attack. The character is a lean black stick figure with pink hair and facial tattoos, extending one arm forward. In front of the arm, include sharp, translucent white slash lines to represent the cutting effect. Side view, right-facing, clean lines, professional game-ready asset, transparent background.", "description": "Sukuna stick figure performing a Dismantle slash attack with translucent effect lines.", "subtype": "character", "aspect_ratio": [787, 1116], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "sukuna_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_ability2_676230e2-43fd-4baa-89cf-724a0f2ccba8.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of the character Sukuna from Jujutsu Kaisen in a side view. The character is a lean black stick figure with pink hair and facial tattoos, wearing a white kimono. He is in a dynamic pose with one hand pulled back, holding and aiming a bright, glowing orange-red ethereal 'Fire Arrow'. The style must be clean and minimalist to match image sukuna_idle. High resolution, professional quality game asset, transparent background.", "description": "Sukuna stick figure character shooting a fiery orange-red arrow.", "subtype": "character", "aspect_ratio": [754, 1048], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "sukuna_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_ability3_49960bb0-5962-403f-b3c7-31323aee1a39.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Sukuna from Jujutsu Kaisen performing his unique 'Domain Expansion' hand sign gesture. The character is a lean black stick figure with pink hair and facial tattoos, surrounded by a dark, swirling purple and black cursed energy aura. High-quality game asset, side view, standing illustration, transparent background.", "description": "Sukuna stick figure character performing his Domain Expansion hand sign with a cursed energy aura.", "subtype": "character", "aspect_ratio": [662, 1217], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sukuna_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_hit_75324b4f-4cff-4b68-bb5e-1f2286a5788a.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Sukuna in a hit/damage recoil pose. The character is a lean black stick figure with pink hair and visible facial tattoos, wearing a simple white kimono. Show the character leaning back as if struck by an impact. Professional game-ready asset, side view, clean lines, transparent background.", "description": "The Sukuna stick figure character in a hit or damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [796, 1021], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sukuna_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sukuna_victory_7d4d0ece-303b-4c72-acf4-a951b5ed043c.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Sukuna in a victory pose, sitting confidently on an invisible throne with a smug expression. The character is a lean black stick figure with short pink hair, distinctive facial and body tattoos, and wearing a simple white kimono. Side view, clean lines, professional game-ready asset, transparent background.", "description": "Victory pose for Sukuna sitting confidently with a smug expression", "subtype": "character", "aspect_ratio": [810, 1225], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_sukuna": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_sukuna_03856eb1-b8c7-4a16-80bc-053310cea171.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Dismantle' ability, featuring several sharp, intersecting diagonal slash marks in a clean white and red style on a dark circular background, professional game asset quality, flat design", "description": "Icon for Sukuna's 'Dismantle' ability featuring sharp slash marks", "subtype": "ui", "aspect_ratio": [866, 864], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_sukuna": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_sukuna_650ff8f6-40d8-4d5d-9bf1-dde31622d4e3.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Fire Arrow' ability. The icon should feature a stylized flaming arrow in vibrant orange and red colors. Clean, flat design, high contrast, suitable for a mobile game ability button. Professional quality, minimalist game asset on a dark background.", "description": "Icon for Sukuna's 'Fire Arrow' ability featuring a stylized flaming arrow.", "subtype": "ui", "aspect_ratio": [574, 718], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_sukuna": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_sukuna_2862b71c-0b2c-4280-810e-d5a0ab8c39ba.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Domain Expansion' ability. The icon features a stylized, simplified silhouette of an ancient Japanese temple shrine with menacing teeth and eyes integrated into the structure. Use a high-contrast dark red and black color palette. 2D flat vector style, clean lines, game-ready UI element, centered composition, transparent background.", "description": "Ability icon for Sukuna's 'Domain Expansion' (Malevolent Shrine) ultimate ability.", "subtype": "ui", "aspect_ratio": [1018, 1018], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "gojo_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_portrait_c3415297-ffaf-4299-b4d4-0371f0865f5f.webp", "type": "image", "prompt": "A minimalist character selection portrait for Gojo Satoru. Stick figure style illustration with clean lines. Features iconic white spiky hair, a black blindfold over his eyes, and a high-collar dark purple jacket. Front-facing, centered composition, high contrast, professional game UI quality, dark background.", "description": "Minimalist character selection portrait for Gojo Satoru in a stick figure style.", "subtype": "ui", "aspect_ratio": [504, 592], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "gojo_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_idle_7224a5c9-2260-4946-8d35-524ed15417a8.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view stick figure of Gojo Satoru in an idle standing pose. The character should have spiky white hair, a black blindfold, and a dark high-collar jacket. Clean lines, flat colors, professional game-ready asset on a transparent background, matching the minimalist stick figure style of other characters like itachi_idle and sasuke_idle.", "description": "Idle standing pose for the Gojo Satoru stick figure character", "subtype": "character", "aspect_ratio": [365, 1190], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "gojo_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_walk_cf5a6dda-67eb-460f-8c09-c371f746cb70.webp", "type": "image", "prompt": "Generate a 2D side-view walking animation frame for a Gojo Satoru stick figure character. The character has spiky white hair, a black blindfold, and a high-collar dark jacket. Show a smooth, confident stride. Minimalist stick figure style, clean lines, professional game asset, transparent background.", "description": "Walking animation frame for the Gojo Satoru stick figure character.", "subtype": "character", "aspect_ratio": [561, 1182], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "gojo_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_jump_a703beaa-9b00-4728-b1f6-5d61315967cf.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view stick figure of Gojo Satoru in a dynamic but poised jumping pose. The character should have iconic white spiky hair, a black blindfold, and a high-collar dark purple jacket. Clean lines, flat design, jumping high into the air with one leg slightly tucked. Transparent background, professional game-ready asset.", "description": "Dynamic jumping pose for the Gojo Satoru stick figure character.", "subtype": "character", "aspect_ratio": [491, 1001], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "gojo_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_ability1_b5cf62ed-3f50-42ab-8c34-6bca03cd2def.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view stick figure of Gojo Satoru with white spiky hair and black blindfold. He is in a dynamic combat pose, pointing forward with a small, intense blue glowing energy orb at his fingertip. The style should match the clean, simple lines of image 1. High-quality game asset on a transparent background.", "description": "Gojo Satoru stick figure character performing the 'Blue' (Cang) ability with a glowing orb.", "subtype": "character", "aspect_ratio": [767, 1121], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "gojo_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_ability2_ed68559d-f468-48eb-912e-eef0bca3fc08.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view stick figure of Gojo Satoru performing the 'Red' (H\u00e1ch) ability. The character has white spiky hair, a black blindfold, and a dark high-collar jacket. He is in a dynamic pose pointing forward with a small, intense red glowing energy orb at his fingertip. Match the style and character design of image 1. Transparent background, high resolution, clean lines, game-ready asset.", "description": "Gojo Satoru stick figure character performing the Red (H\u00e1ch) ability with a red energy orb.", "subtype": "character", "aspect_ratio": [657, 1202], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "gojo_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_ability3_709c785c-24cf-4c45-bd15-9d7fdba431db.webp", "type": "image", "prompt": "Generate a 2D side-view illustration of a Gojo Satoru stick figure character performing his Domain Expansion 'Infinite Void'. The character has white spiky hair and a black blindfold, wearing a high-collar dark jacket. He is making the specific 'Infinite Void' hand sign with fingers crossed. A swirling void of dark purple and space-like energy surrounds the character. Match the minimalist stick figure style of image 1. Transparent background.", "description": "Gojo Satoru stick figure performing his Domain Expansion 'Infinite Void' with the iconic hand sign.", "subtype": "character", "aspect_ratio": [832, 1239], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gojo_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_hit_6c4bf98a-4b69-4c2a-8b2c-133ace755e77.webp", "type": "image", "prompt": "Generate a 2D side-view stick figure of Gojo Satoru in a hit or damage recoil pose. The character has white spiky hair, a black blindfold, and a dark high-collar outfit. His poise is slightly broken as if struck by an attack, but he maintains an aura of power. Minimalist style with clean lines, matching the style of image 1. Transparent background.", "description": "Gojo Satoru stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [414, 1199], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "gojo_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gojo_victory_ce29223e-9de8-4ee7-b9b0-2b8404563ec7.webp", "type": "image", "prompt": "Generate a 2D side-view victory pose of a Gojo Satoru stick figure. He has white spiky hair and a high-collar black jacket. He is lifting his black blindfold slightly with one hand to reveal a single glowing blue eye. Minimalist stick figure art style, clean lines, transparent background, professional game asset quality.", "description": "Victory pose for Gojo Satoru revealing his eye, used for the win screen", "subtype": "character", "aspect_ratio": [512, 1238], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_gojo": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_gojo_90762c26-bb01-4a33-a0e2-a41618873158.webp", "type": "image", "prompt": "Generate a minimalist UI ability icon for a 'Blue' vortex ability. The icon should feature a stylized, glowing blue sphere or vortex centered on a dark background. Clean lines, simple shapes, professional game UI quality, matching the minimalist aesthetic of the existing character icons.", "description": "A minimalist UI icon for Gojo's 'Blue' ability featuring a stylized blue vortex.", "subtype": "ui", "aspect_ratio": [546, 571], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_gojo": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_gojo_2eee7d69-cef8-474a-83b2-1f9fa7deca7d.webp", "type": "image", "prompt": "A minimalist UI ability icon for Gojo Satoru's 'Red' (H\u00e1ch) technique. Centered on a dark background, featuring a stylized, high-contrast glowing red energy sphere with subtle outward blast ripples. Clean vector-like lines, professional game UI quality, matching the aesthetic of ability1_icon_gojo but with a red color palette.", "description": "Ability icon for Gojo's 'Red' ability featuring a stylized red glowing sphere.", "subtype": "ui", "aspect_ratio": [982, 1022], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_gojo": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_gojo_75ceef97-319b-41ca-8c31-71110228f75f.webp", "type": "image", "prompt": "A minimalist UI game icon for Gojo's ultimate ability 'Infinite Void'. The icon features a stylized illustration of a hand performing the specific hand sign with index and middle fingers crossed. Use a clean, flat design with a dark background and subtle purple or white glowing accents to represent cursed energy. High quality, professional game UI element.", "description": "Ability icon for Gojo's 'Infinite Void' featuring his signature crossed-finger hand sign.", "subtype": "ui", "aspect_ratio": [664, 645], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "saitama_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_portrait_5883c762-5f49-4485-97c5-243a680f3806.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for Saitama from One Punch Man. Use a clean stick figure art style consistent with luffy_portrait and gojo_portrait. Features include a bald head, simple deadpan facial expression, yellow jumpsuit, and white cape. Front-facing view, centered composition, high resolution, professional game UI quality, transparent background.", "description": "Minimalist character selection portrait for Saitama in stick figure style", "subtype": "ui", "aspect_ratio": [657, 1219], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "saitama_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_idle_0ccc7e79-d388-496a-96d6-360197d1b129.webp", "type": "image", "prompt": "Generate a full-body, front-view minimalist 2D stick figure character of Saitama. He is wearing a yellow suit, red gloves, and a white cape. He has a bald head and a simple, bored facial expression. Clean lines, polished game-ready asset, transparent background. Match the minimalist art style of 'luffy_idle' and 'gojo_idle'.", "description": "Idle standing pose for the Saitama stick figure character in a minimalist style", "subtype": "character", "aspect_ratio": [502, 1215], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "saitama_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_walk_0a1dd486-3557-44b3-942a-95311e737145.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for a minimalist stick figure character of Saitama. The character should have a bald head, a simple yellow suit with red gloves, and a white cape flowing slightly behind him. High-quality 2D vector style, clean lines, professional game asset, transparent background.", "description": "Walking animation frame for the Saitama stick figure character in a minimalist 2D style.", "subtype": "character", "aspect_ratio": [665, 1187], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "saitama_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_jump_6c4f8787-0b78-4d56-9df4-b6b6a3ffd46b.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Saitama jumping. The character has a bald head, a simple yellow suit with red gloves, and a white cape flowing upwards. Front-facing view, dynamic pose, high resolution, clean lines, professional game-ready asset, transparent background.", "description": "Jumping pose for the Saitama stick figure character with upward-flowing cape.", "subtype": "character", "aspect_ratio": [736, 829], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "saitama_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_ability1_705429a5-9806-4de2-bcbb-4ba84d46718b.webp", "type": "image", "prompt": "Generate a full-body, side view of a minimalist 2D stick figure character Saitama performing a 'Normal Punch'. One fist is extended forward in a simple but powerful punching pose. The character has a bald head, yellow suit, red gloves, and a white cape trailing behind. High-quality game asset, clean lines, transparent background, consistent with the style of luffy_ability1.", "description": "Saitama stick figure performing a powerful Normal Punch attack", "subtype": "character", "aspect_ratio": [1165, 824], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "saitama_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_ability2_3269ce86-7ebc-4b88-82b9-a94586354cfa.webp", "type": "image", "prompt": "Generate a full-body, side view of a minimalist Saitama stick figure character in a yellow suit and white cape performing 'Consecutive Normal Punches'. Show multiple blurred red fists and motion lines appearing rapidly in front of him to signify speed. Clean, polished 2D game asset style, transparent background, matching the art style of saitama_idle.", "description": "Saitama stick figure performing Consecutive Normal Punches with blurred fist effects", "subtype": "character", "aspect_ratio": [814, 1128], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "saitama_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_ability3_a4209db2-0d06-4690-ae8b-459a7f2e4e82.webp", "type": "image", "prompt": "Generate a full-body, side-view illustration of a minimalist stick figure Saitama performing a 'Serious Punch'. The character has a bald head, yellow suit, red gloves, and a white cape. One fist is extended forward in a powerful, dynamic pose with intense focus. A large, stylized white shockwave effect originates from the fist, spreading outward. Minimalist 2D game asset style, clean lines, professional quality, transparent background, matching the style of saitama_idle.", "description": "Saitama stick figure performing a Serious Punch with a massive shockwave effect", "subtype": "character", "aspect_ratio": [811, 735], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "saitama_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_hit_a1c76432-42a5-42de-9ee1-a841205a122d.webp", "type": "image", "prompt": "Generate a full-body, side-view minimalist 2D stick figure of Saitama in a hit or damage recoil pose. He has a bald head and is wearing his signature yellow suit with red gloves and a white cape. The pose should show him being pushed back or reeling from an impact. Clean, polished, game-ready game asset on a transparent background, matching the style of saitama_idle.", "description": "Saitama stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [721, 1085], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "saitama_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/saitama_victory_71015b9e-18df-4850-8f07-a7bf4af207f8.webp", "type": "image", "prompt": "Generate a full-body, front-facing victory pose of a minimalist 2D stick figure character Saitama. He is wearing his iconic yellow suit, red gloves, and a white cape, holding a brown paper grocery bag. He has a bald head and a bored, nonchalant facial expression. Clean, polished game-ready asset, minimalist 2D art style, transparent background, high resolution, matching the style of saitama_idle.", "description": "Victory pose for Saitama holding a grocery bag with a bored expression.", "subtype": "character", "aspect_ratio": [558, 1248], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_saitama": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_saitama_9fe565d4-f449-4a2e-9a6a-0561d841cc16.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Saitama's 'Normal Punch' ability. The icon should feature a simple, bold red fist silhouette. Clean, polished game-ready icon, minimalist vector style, transparent background, high resolution.", "description": "Ability icon for Saitama's 'Normal Punch' featuring a simple red fist.", "subtype": "ui", "aspect_ratio": [644, 769], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_saitama": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_saitama_f930e67d-dabf-4d62-b7d2-97f660010b0d.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Consecutive Normal Punches' ability. The icon features multiple overlapping red fist silhouettes to indicate rapid movement and speed. Use a clean, flat vector style consistent with ability1_icon_saitama. Transparent background, high resolution, professional game UI quality.", "description": "Ability icon for Saitama's Consecutive Normal Punches featuring multiple red fist silhouettes", "subtype": "ui", "aspect_ratio": [701, 492], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_saitama": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_saitama_e4394867-43ea-4dd0-8225-48c827cfca6c.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Serious Punch' ability. The icon features a large, bold red fist silhouette in the center with clean, white concentric shockwave lines radiating outwards. Flat 2D vector style, simple geometric shapes, high contrast, professional game UI quality, transparent background.", "description": "Ability icon for Saitama's Serious Punch featuring a red fist and shockwaves", "subtype": "ui", "aspect_ratio": [748, 727], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_portrait_e33a33e7-14d3-4924-8e9b-31e9c6741845.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for a stick figure character 'Vua Qu\u1ef7' (Demon King). The character is a clean black stick figure with glowing red eyes and sharp red horns, wearing a tattered dark red cloak. Style must strictly match the minimalist anime stick figure aesthetic of existing portraits like 'itachi_portrait' and 'sukuna_portrait'. High resolution, professional quality, centered composition on a simple background.", "description": "Minimalist character selection portrait for the Demon King stick figure character.", "subtype": "ui", "aspect_ratio": [1024, 1024], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_idle_08a3e615-b0f4-47b2-b4ff-73bc4ced86d3.webp", "type": "image", "prompt": "Generate a full-body, front-view idle standing illustration of a minimalist 2D stick figure character named 'Vua Qu\u1ef7'. The character has a sleek black stick body, intense glowing red eyes, and sharp red horns protruding from its head. It wears a tattered, weathered dark red cloak that drapes over its shoulders. Clean lines, professional game-ready asset, minimalist anime stick figure style, transparent background.", "description": "Idle pose for the Vua Qu\u1ef7 (Demon King) stick figure character", "subtype": "character", "aspect_ratio": [365, 894], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_walk_08353400-47b0-4472-92d1-6491411f21db.webp", "type": "image", "prompt": "Generate a side-view walking animation frame for the 'Vua Qu\u1ef7' stick figure character. The character is a lean black stick figure with glowing red eyes, sharp red horns, and a tattered dark red cloak that flows behind him. He is moving with a menacing, purposeful stride. Minimalist 2D vector-like style, clean lines, white background, transparent-ready.", "description": "Walking animation frame for the Vua Qu\u1ef7 (Demon King) stick figure character.", "subtype": "character", "aspect_ratio": [751, 894], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_jump_f9545c91-e149-4b6c-a426-a6e9fa5d6981.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character 'Vua Qu\u1ef7' in a dynamic jumping pose. The character is a black stick figure with glowing red eyes, sharp red horns, and a tattered dark red cloak flowing downwards. Side view, right-facing. Maintain consistency with the style of image 1. Clean lines, professional game-ready asset, transparent background.", "description": "Jumping pose for the Vua Qu\u1ef7 (Demon King) stick figure character with a flowing cloak.", "subtype": "character", "aspect_ratio": [693, 1214], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_ability1_02846080-9b85-4e05-9b66-f797cac50cb4.webp", "type": "image", "prompt": "Generate a full-body, side-view 2D minimalist stick figure character named 'Vua Qu\u1ef7'. The character is black with sharp red horns and a tattered dark red cloak. One arm is transformed into a large, oversized glowing red demonic claw swiping forward with motion trail effects. Clean vector style, transparent background, high resolution, matching the style of vua_quy_idle.", "description": "Vua Qu\u1ef7 stick figure performing a glowing red demonic claw swipe attack.", "subtype": "character", "aspect_ratio": [757, 1010], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_ability2_24402628-375a-4688-828a-86d24e2ef0c9.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character 'Vua Qu\u1ef7' performing a 'Hellfire' attack. The character is black with glowing red eyes and red horns, wearing a tattered dark red cloak. It is launching a dark red fireball from its hand. Side-view, right-facing, clean lines, professional game-ready asset, transparent background.", "description": "Stick figure Vua Qu\u1ef7 launching a dark red Hellfire projectile", "subtype": "character", "aspect_ratio": [748, 1088], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_ability3_2c7d6cab-d395-4b8b-b0c5-90ab8a0a142d.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character illustration of 'Vua Qu\u1ef7'. The character is a black stick figure with sharp red horns and a tattered dark red cloak. The character is in a 'Demon Roar' pose: head tilted back toward the sky, mouth open, with powerful glowing red energy waves erupting from its mouth. Maintain a clean, minimalist anime style consistent with a fighting game asset. Full body view, transparent background, high quality, side view.", "description": "Vua Qu\u1ef7 stick figure performing a Demon Roar ultimate ability with red energy waves", "subtype": "character", "aspect_ratio": [493, 981], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_hit_122027d6-a6aa-47ef-9e02-99d56b86a55d.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character 'Vua Qu\u1ef7' in a hit/damage recoil pose. The character is a black stick figure with glowing red eyes, sharp red horns, and a tattered dark red cloak, showing impact with a slight tilt and pained expression. Clean lines, side view, transparent background, high resolution, matching the style of vua_quy_idle.", "description": "The Vua Qu\u1ef7 stick figure character in a hit or damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [678, 1043], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_victory_959ce481-c593-43df-9039-2a1afd8c414a.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of 'Vua Qu\u1ef7' (Demon King) in a victory pose. The character is a black stick figure with sharp red horns and intensely glowing red eyes, wearing a tattered dark red cloak. He is standing triumphantly on a pile of dark shadows with his arms crossed. Side view, high-quality game asset, transparent background, clean lines, matching the minimalist anime stick figure style of the existing characters.", "description": "Victory pose for the Demon King stick figure standing triumphantly on shadows", "subtype": "character", "aspect_ratio": [778, 1202], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_vua_quy": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_vua_quy_f9e43af3-6c0d-46aa-8083-e3086ec52557.webp", "type": "image", "prompt": "A minimalist UI icon for a 'Demon Claw' ability, featuring three sharp, stylized red glowing claw marks or slashes. Clean vector-style art, high contrast against a dark background, professional game UI quality, matches the minimalist aesthetic of existing anime stick figure game icons.", "description": "Ability icon for Vua Qu\u1ef7's 'Demon Claw' featuring a stylized red sharp claw mark.", "subtype": "ui", "aspect_ratio": [701, 788], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_vua_quy": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_vua_quy_cd5c955a-bd46-4759-8bc3-54125d3f4cdf.webp", "type": "image", "prompt": "A minimalist UI ability icon for a 'Hellfire' skill, featuring a stylized dark red flame symbol. The design should be clean, flat, and professional, centered on a dark or neutral background suitable for a game HUD. Professional quality, game-ready UI element, minimalist vector style matching the existing game icons.", "description": "A minimalist UI icon for the Demon King's Hellfire ability featuring a dark red flame.", "subtype": "ui", "aspect_ratio": [458, 627], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_vua_quy": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_vua_quy_afdb2b71-1a5b-42f3-b00f-3115bec61489.webp", "type": "image", "prompt": "A minimalist game UI icon for an ultimate ability called 'Demon Roar'. Featuring a stylized red shockwave or a demonic mouth silhouette emitting energy. Use a clean, flat vector style with a dark background. The color palette should focus on intense red and black, matching the visual theme of the Vua Qu\u1ef7 character.", "description": "Minimalist UI icon for Vua Qu\u1ef7's Demon Roar ultimate ability", "subtype": "ui", "aspect_ratio": [906, 852], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "sasuke_adult_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_adult_idle_a16cbab5-b21b-4bee-99be-4cffd31df075.webp", "type": "image", "prompt": "Generate a full-body, side-view standing illustration of an Adult Sasuke Uchiha as a lean black stick figure. He wears a long grey and black traveling cloak that covers most of his body, with only one arm visible. Minimalist anime stick figure style, clean lines, professional game asset quality, transparent background. Match the artistic style, proportions, and minimalist aesthetic of image 1.", "description": "Idle standing pose for Adult Sasuke in a traveling cloak, minimalist stick figure style", "subtype": "character", "aspect_ratio": [385, 1232], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_adult_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_adult_walk_1f315040-0163-4f95-ba0d-cdf09a31888f.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for an Adult Sasuke Uchiha stick figure. The character is lean, wearing a signature long grey and black traveling cloak. Use a minimalist 2D stick figure style consistent with image 1. The movement should be a cool, purposeful stride on a transparent background.", "description": "Walking animation frame for Adult Sasuke Uchiha in his traveling cloak", "subtype": "character", "aspect_ratio": [683, 1204], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "sasuke_adult_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_adult_jump_21f70711-53b4-4402-b22f-0736d2542d0a.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Adult Sasuke Uchiha in a high jumping pose. The character should be a lean black stick figure wearing a long grey and black traveling cloak that flows dynamically behind him. Minimalist Naruto-inspired style. Ensure the pose is dynamic with one knee tucked, matching the composition and style of sasuke_jump. Full body, front-facing, transparent background, high quality.", "description": "A jumping pose for Adult Sasuke as a minimalist stick figure with a flowing cloak.", "subtype": "character", "aspect_ratio": [759, 1095], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "sasuke_adult_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sasuke_adult_portrait_5eef9ca0-306b-4dc0-9b9e-90ec52aee4c1.webp", "type": "image", "prompt": "A minimalist, clean character selection portrait of Adult Sasuke Uchiha from the Boruto era. Stick figure style character with long dark hair covering his right eye, while a purple Rinnegan eye is visible in the left. He is wearing a high-collared grey and black traveling cloak. Simple, professional game UI style with a plain background, matching the aesthetic of sasuke_portrait.", "description": "Minimalist character selection portrait for Adult Sasuke Uchiha in a stick figure style.", "subtype": "ui", "aspect_ratio": [1024, 1014], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "goku_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_portrait_0d8130b6-c9d2-46ec-8855-7ba13bb33a84.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait of Goku as a stick figure. He has iconic spiky black hair, wears an orange martial arts gi with a blue undershirt, and has a confident facial expression. Clean, flat vector style, centered composition, matching the minimalist aesthetic of image 1 and image 2.", "description": "Minimalist character selection portrait for Goku in stick figure style", "subtype": "ui", "aspect_ratio": [606, 1243], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "goku_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_idle_8bea0122-2121-4beb-88b1-6ea0dcdbae6b.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Goku in an idle standing pose. The character should have spiky black hair, wear a classic orange martial arts gi with a blue undershirt and belt. Side view, facing right. Clean lines, solid colors, professional game-ready asset with a transparent background. Maintain the same stick figure proportions and style as seen in 'bat_bai_idle' and 'luffy_idle'.", "description": "Idle standing pose for the Goku stick figure character in orange gi.", "subtype": "character", "aspect_ratio": [518, 1217], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "goku_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_walk_09e890e2-e658-4f7a-a195-1c4b56812a19.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Goku in a walking pose. The character has spiky black hair and wears a classic orange gi with a blue undershirt. Side view, right-facing, showing a smooth and purposeful stride. Match the clean, minimalist art style of 'goku_idle' and 'luffy_walk'. Transparent background, high resolution, game-ready asset.", "description": "Walking animation frame for the Goku stick figure character", "subtype": "character", "aspect_ratio": [534, 1160], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "goku_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_jump_c7d2eb9f-0646-4ceb-a0a3-9ae0d7c6546d.webp", "type": "image", "prompt": "Generate a high jumping pose for a Goku stick figure character. Minimalist 2D stick figure with spiky black hair and orange gi. High jumping pose with legs slightly bent, orange gi and blue belt flowing with the movement. Side view, right-facing, transparent background. Clean, polished, game-ready stick figure style consistent with goku_idle and bat_bai_jump.", "description": "Jumping pose for the Goku stick figure character", "subtype": "character", "aspect_ratio": [435, 840], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "goku_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_ability1_6948cd7b-c610-444b-a65f-292f593e99a5.webp", "type": "image", "prompt": "Generate a side-view, right-facing minimalist stick figure of Goku with spiky black hair and an orange gi. He is performing a rapid punch attack with one arm fully extended and a stylized motion blur effect to show high speed. Clean lines, 2D vector style, transparent background, high resolution, professional game asset.", "description": "Goku stick figure performing a rapid punch attack with speed blur", "subtype": "character", "aspect_ratio": [740, 868], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "goku_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_ability2_77f7bb59-e2f9-4a01-bdc9-b616dc53182f.webp", "type": "image", "prompt": "Generate a full-body, right-facing minimalist 2D stick figure of Goku in an Instant Transmission pose. He has spiky black hair and an orange gi, with two fingers pressed to his forehead in a focused stance. Clean lines, professional game-ready asset, transparent background, side view, matching the style of goku_idle.", "description": "Goku stick figure character performing Instant Transmission with fingers to forehead.", "subtype": "character", "aspect_ratio": [530, 1246], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "goku_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_ability3_23013bea-d6f5-4a72-b4f6-6ce0b9eb33c5.webp", "type": "image", "prompt": "Generate a side-view, right-facing minimalist 2D stick figure of Goku in a Kamehameha charging pose. The character has spiky black hair and an orange martial arts gi. Hands are cupped at his side with a small, glowing blue energy orb forming between them. Clean lines, professional game-ready asset, transparent background, matching the art style of 'goku_idle'.", "description": "Goku stick figure charging a Kamehameha energy attack", "subtype": "character", "aspect_ratio": [529, 1247], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "goku_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_hit_926c0a6a-f03d-4a93-b143-042f91707563.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Goku in a hit recoil pose, recoiling from a blow with eyes wide in pain. The character has spiky black hair and wears a classic orange gi with a blue undershirt. Side view, right-facing, transparent background. Maintain the same art style and proportions as 'goku_idle' and 'bat_bai_hit'. Professional game-ready asset.", "description": "Goku stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [617, 1122], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "goku_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_victory_17902d2a-40fc-47d5-8290-5d088695f755.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Goku from Dragon Ball Z in a victory pose. The character should have spiky black hair and his iconic orange gi with blue undershirt. He is standing facing the viewer with a wide grin and giving a confident thumbs-up gesture. Clean lines, simple colors, professional game-ready asset on a transparent background, matching the style of goku_idle.", "description": "Victory pose for Goku stick figure giving a thumbs up and grinning.", "subtype": "character", "aspect_ratio": [568, 1229], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_goku": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_goku_b1e40068-2ea0-46aa-94e4-bb91661c9633.webp", "type": "image", "prompt": "A minimalist UI icon for a game ability called 'Rapid Punches'. Features a stylized, bold orange fist with white speed lines to indicate fast motion. Clean vector style, flat design, high contrast, on a transparent background. Matches the minimalist aesthetic of 'ability1_icon_luffy' and 'ability1_icon_saitama'.", "description": "Ability icon for Goku's Rapid Punches featuring a stylized orange fist and speed lines.", "subtype": "ui", "aspect_ratio": [916, 355], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_goku": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_goku_14e8062c-008e-4e55-abe4-ccee056aabdc.webp", "type": "image", "prompt": "A minimalist UI icon for Goku's 'Instant Transmission' ability. The design should feature a stylized silhouette of two fingers pressed to the forehead with subtle blue sparkle or speed line effects to represent teleportation. Clean, high-contrast vector-style graphics on a transparent background, matching the minimalist aesthetic of 'ability1_icon_goku'.", "description": "Ability icon for Goku's Instant Transmission featuring his signature teleportation pose", "subtype": "ui", "aspect_ratio": [906, 453], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_goku": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_goku_442b1037-6512-4c08-9756-406034324d8e.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Goku's 'Kamehameha' ability. The icon should feature a stylized bright blue energy sphere or a powerful beam of light, using clean lines and a simple flat design style. The color palette should be dominated by cyan and electric blue on a dark or transparent-ready background to fit a fighting game HUD. High resolution, professional quality, matching the minimalist style of ability1_icon_goku.", "description": "A minimalist UI icon for Goku's Kamehameha ultimate ability.", "subtype": "ui", "aspect_ratio": [1191, 239], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "kamehameha_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/kamehameha_sfx_465c45e7-b117-4491-bac1-6ef1328005aa.mp3", "type": "audio", "prompt": "High-intensity anime energy attack sound effect. It begins with a 3-second rising pitch electronic hum and crackling static to simulate charging power, culminating in a massive, earth-shaking resonant energy blast with a deep bass boom and a long, fading white-noise sizzle. Cinematic, powerful, and iconic, similar to classic shonen battle climax sounds. Clean, high-fidelity audio.", "description": "Powerful anime-style energy charge and massive blast sound effect for a signature beam attack.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 5.59, "loop": false, "animation": null}, "shadow_garden_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_portrait_29832a44-5d40-4430-a633-9f93e4e92073.webp", "type": "image", "prompt": "Modify the shadow_garden_portrait to add intricate golden lines and trim along the edges of the black hooded coat. Enhance the prominence of the glowing purple eyes. Maintain the minimalist stick figure character style, clean lines, and professional game-ready portrait appearance.", "description": "Upgraded selection portrait for Lord Shadow featuring golden coat trim and glowing purple eyes.", "subtype": "ui", "aspect_ratio": [569, 1239], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_idle_43ea7c81-3af0-4648-bf0a-b7d71e2504a9.webp", "type": "image", "prompt": "Generate a full-body, front-side view of a minimalist 2D stick figure character representing Shadow (Cid Kagemou) in an idle standing pose. The character wears a long, flowing black trench coat with glowing violet trim and details. Clean lines, minimalist aesthetic matching the style of existing stick figure assets, on a transparent background.", "description": "Idle standing pose for Shadow from The Eminence in Shadow as a minimalist stick figure character.", "subtype": "character", "aspect_ratio": [536, 1202], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_walk_6806a2de-f172-4e1a-aa20-c68ab1a6df9d.webp", "type": "image", "prompt": "Generate a side-view walking animation frame of a minimalist 2D stick figure character named Shadow. He is wearing a long, flowing black slime suit trench coat with subtle glowing violet trim. Minimalist art style consistent with a stick figure fighting game. Right-facing character, transparent background, high resolution, clean lines.", "description": "Walking animation frame for Shadow (Cid Kagemou) in his black slime suit.", "subtype": "character", "aspect_ratio": [545, 1128], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_jump_0a04d9fd-7767-47c8-ad41-eabf9271d200.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character jumping pose for Shadow from The Eminence in Shadow. The character is wearing a long black slime suit trench coat with violet trim that flows dynamically behind him. Minimalist aesthetic, side view, right-facing. High resolution, clean lines, professional game asset. Transparent background.", "description": "Jumping pose for Shadow with a flowing black trench coat, stick figure style.", "subtype": "character", "aspect_ratio": [651, 701], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_ability1_c2e8f159-8a9c-485c-bc15-37300bd2f9c1.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of the character Shadow performing a dynamic sword slash. The character is wearing a long black trench coat with violet trim. The attack features a sharp, glowing violet energy trail following the blade. Side view, right-facing, full body. Clean lines, game-ready asset, transparent background, high resolution.", "description": "Shadow character performing a sword slash with a violet energy trail in a minimalist stick figure style.", "subtype": "character", "aspect_ratio": [662, 1095], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_ability2_8c60db89-4236-4e8c-80db-7541ba40b838.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character 'Shadow' in a dynamic dashing pose. The character is a lean black stick figure wearing a long trench coat with violet trim. Include a stylized violet motion blur effect trailing behind the character to represent speed. Side view, right-facing, full body illustration. Clean vector-like style, high resolution, transparent background.", "description": "Shadow stick figure performing a dashing maneuver with violet energy effects.", "subtype": "character", "aspect_ratio": [687, 609], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_ability3_76598116-86f8-4438-b55f-f705fce8048a.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character illustration of Shadow from The Eminence in Shadow in a powerful channeling pose. The character is a lean black stick figure wearing a long black trench coat with violet trim. He is channeling intense violet energy into his hands and sword, with glowing purple aura effects. Full body picture, standing illustration, front-side view, high resolution, professional game asset, transparent background.", "description": "Shadow character channeling violet energy for his ultimate ability", "subtype": "character", "aspect_ratio": [651, 998], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_hit_4a153405-f336-4a00-8436-938196d810b0.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Shadow from The Eminence in Shadow in a hit or damage recoil pose. He is wearing his signature long black slime suit trench coat with violet trim. The character should look like he just took an impact, with a slight backward lean. Side view, clean lines, professional game asset style, transparent background.", "description": "Shadow character in a damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [571, 1182], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "shadow_garden_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/shadow_garden_victory_222629f4-e9df-40d8-841b-5b26fe6c6d5b.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of the character Shadow from The Eminence in Shadow in a victory pose. The character is standing with his back to the viewer, looking over his shoulder so one glowing violet eye is visible. He wears a long black trench coat with violet trim that flows slightly. Minimalist style, clean lines, high resolution, transparent background, front-side view.", "description": "Victory pose for Shadow showing him looking over his shoulder with a glowing eye", "subtype": "character", "aspect_ratio": [816, 1155], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_shadow_garden": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_shadow_garden_24dab910-bbcb-458b-b73d-f9ae9653c884.webp", "type": "image", "prompt": "Generate a minimalist UI icon for the 'Slime Slash' ability. The icon features a sharp, diagonal violet-colored sword slash silhouette against a dark, solid background. Clean vector style, high contrast, professional game UI quality, matching the minimalist aesthetic of the existing character portraits.", "description": "Ability icon for Shadow's Slime Slash featuring a violet sword silhouette", "subtype": "ui", "aspect_ratio": [832, 1248], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_shadow_garden": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_shadow_garden_720dffd2-55e9-4642-a990-962ecec7cc35.webp", "type": "image", "prompt": "A minimalist UI icon for the 'Shadow Dash' ability, featuring a stylized violet silhouette of a character dashing through darkness with motion trails. Dark background, clean game-ready asset, professional quality, matching the aesthetic of Shadow from The Eminence in Shadow.", "description": "Ability icon for Shadow's 'Shadow Dash' featuring a violet silhouette dashing.", "subtype": "ui", "aspect_ratio": [832, 1248], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_shadow_garden": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_shadow_garden_f9d0694b-a5d7-47f8-81c2-4cd922948019.webp", "type": "image", "prompt": "A minimalist UI icon for a 'Violet Burst' ability, featuring a stylized circular violet energy explosion symbol, high contrast, dark background, clean vector style, professional game asset", "description": "Ability icon for Shadow's 'Violet Burst' ultimate ability", "subtype": "ui", "aspect_ratio": [1024, 1024], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "atomic_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/atomic_sfx_11e65775-f28f-46ed-9ab8-233bf8fd26d1.mp3", "type": "audio", "prompt": "A cinematic, ultra-powerful anime ultimate move sound effect. It begins with a hushed, breathy, cool male whisper saying 'I am Atomic', followed immediately by a brief moment of silence, then a massive, deep, resonating explosion. The explosion should have heavy low-end sub-bass, a wide stereo image, and a long decaying rumble. Epic, god-like power, high-fidelity, dramatic impact.", "description": "Massive explosion sound effect preceded by a whispery 'I am Atomic' vocal cue, for a signature ultimate move.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 5.56, "loop": false, "animation": null}, "naruto_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_portrait_81f8f793-8f33-4f44-943a-b6a257ed7b0d.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for Naruto Uzumaki. Stick figure style, clean lines, simple shapes. Focus on head and shoulders, featuring iconic yellow spiky hair and orange jumpsuit. High resolution, professional game asset, centered composition, transparent background.", "description": "Minimalist character selection portrait for Naruto Uzumaki in stick figure style", "subtype": "ui", "aspect_ratio": [638, 960], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_idle_ab195673-d643-4b25-a923-fefb92b61da2.webp", "type": "image", "prompt": "Generate a minimalist stick figure character of Naruto Uzumaki in an idle standing pose. The character should have yellow spiky hair, a head band, and wear a bright orange jumpsuit with black details. Clean, polished 2D game-ready asset, full body picture, front-facing, minimalist style consistent with other fighters, transparent background, high resolution.", "description": "Idle standing pose for the Naruto stick figure character in his signature orange jumpsuit.", "subtype": "character", "aspect_ratio": [483, 1216], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_walk_fa8815aa-3a9a-4425-884a-39e2ae3db0a5.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for a minimalist Naruto stick figure character. The character has bright yellow spiky hair, wearing an orange and black jumpsuit. Simple clean lines, professional game-ready asset, transparent background, matching the art style of image 1.", "description": "Walking animation frame for the Naruto stick figure character in orange jumpsuit.", "subtype": "character", "aspect_ratio": [499, 1197], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_jump_1a794e27-2322-4d96-83cb-fad629654270.webp", "type": "image", "prompt": "Generate a full-body, side-view illustration of a minimalist Naruto stick figure character in a high jumping pose. The character has spiky yellow hair and wears an iconic orange and black jumpsuit. One knee is tucked towards the chest while the other is extended, capturing a sense of upward motion. Clean, polished minimalist game asset style, high resolution, transparent background.", "description": "A dynamic jumping pose for the Naruto stick figure character in his signature orange jumpsuit.", "subtype": "character", "aspect_ratio": [433, 955], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_ability1_090b363d-07a2-469b-965c-feea65743678.webp", "type": "image", "prompt": "Generate a minimalist stick figure character of Naruto Uzumaki in his iconic orange jumpsuit charging a swirling blue energy Rasengan orb in his hand. Side view, right-facing, standing illustration, clean professional game-ready asset, high resolution, transparent background.", "description": "Naruto stick figure character charging a swirling blue Rasengan orb", "subtype": "character", "aspect_ratio": [693, 751], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_ability2_936e110c-3306-41b5-baac-e021e17bede0.webp", "type": "image", "prompt": "Generate a side-view, right-facing minimalist stick figure of Naruto Uzumaki accompanied by two identical shadow clones, all in a dynamic combat-ready pose preparing for a strike. The characters should feature the iconic orange jumpsuit and yellow spiky hair consistent with image 'naruto_idle'. Clean, polished 2D game asset style, professional quality, transparent background.", "description": "Naruto stick figure character with two shadow clones preparing to attack.", "subtype": "character", "aspect_ratio": [766, 658], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_ability3_2a86945a-3fde-49da-85aa-961783b6a6c9.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Naruto Uzumaki in an orange jumpsuit, side view, right-facing, throwing a large, glowing blue spinning Rasenshuriken. The Rasenshuriken should look like a bright blue shuriken made of wind energy with a swirling core. Match the minimalist art style of image 1 and image 2. High resolution, professional game asset, transparent background.", "description": "Naruto stick figure character throwing a large, glowing blue Rasenshuriken.", "subtype": "character", "aspect_ratio": [754, 1021], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_ability4_ee786039-31e6-49d1-b3ce-162ed8b8faea.webp", "type": "image", "prompt": "Generate a full-body, side-view illustration of a minimalist Naruto stick figure character transformed into Nine-Tails Chakra Mode (Kurama Mode). The character should be glowing intense golden-yellow with orange chakra whisker marks on the face and a vibrant, fiery yellow-orange energy aura surrounding the body. Clean lines, minimalist 2D fighting game style, transparent background, high resolution.", "description": "Naruto in Nine-Tails Chakra Mode with a golden fiery aura for his transformation state", "subtype": "character", "aspect_ratio": [652, 1201], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_hit_d67a68f2-21d2-4665-b37c-d901cf0be841.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Naruto Uzumaki in a hit recoil pose. The character should be recoiling from an impact, leaning back with a dynamic damage reaction. He wears his iconic orange jumpsuit and yellow spiky hair. Side-view, right-facing character, clean lines, professional game-ready asset, transparent background, matching the minimalist style of the naruto_idle asset.", "description": "Naruto stick figure character in a hit/damage recoil pose", "subtype": "character", "aspect_ratio": [582, 1148], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "naruto_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_victory_7a29a839-2b96-40c2-a624-b887adc0183c.webp", "type": "image", "prompt": "Generate a full-body, front-facing victory pose for the Naruto stick figure character. The character should be a minimalist lean stick figure in an orange jumpsuit with yellow spiky hair, grinning and giving a thumbs up to the camera. Maintain the same minimalist art style and character design as seen in naruto_idle and naruto_portrait. High resolution, clean lines, professional game asset, transparent background.", "description": "Victory pose for Naruto stick figure character, grinning and giving a thumbs up", "subtype": "character", "aspect_ratio": [693, 1218], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_naruto": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_naruto_1e91cccf-f7af-44e8-b59c-d96aa3b37f06.webp", "type": "image", "prompt": "Generate a minimalist UI ability icon for a Rasengan, featuring a glowing, swirling blue energy sphere with internal spiral patterns. Clean vector-style art, high contrast, centered on a dark background, game-ready quality, consistent with other minimalist anime ability icons.", "description": "UI icon for Naruto's Rasengan ability featuring a swirling blue energy sphere", "subtype": "ui", "aspect_ratio": [501, 517], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_naruto": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_naruto_58296a88-cc88-43ba-b230-72a37fc5b061.webp", "type": "image", "prompt": "A minimalist UI icon for Naruto's 'Shadow Clone Jutsu' ability. The design should feature multiple black stick figure silhouettes layered behind each other to represent clones, following the clean and simple game art style. Use a bright orange background consistent with Naruto's theme. High resolution, professional game UI quality, transparent background.", "description": "Ability icon for Naruto's Shadow Clone jutsu featuring multiple silhouettes.", "subtype": "ui", "aspect_ratio": [760, 765], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_naruto": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_naruto_570031e4-ba21-4e3b-96e9-79ced42b76ba.webp", "type": "image", "prompt": "Generate a minimalist UI ability icon for Naruto's 'Rasenshuriken'. The icon features a glowing blue swirling energy orb with four sharp wind-blade points resembling a shuriken. Clean white or light blue energy lines, centered composition, high contrast against a dark background, stylized game-ready vector art style.", "description": "A minimalist UI icon for Naruto's Rasenshuriken ability featuring a swirling blue shuriken.", "subtype": "ui", "aspect_ratio": [814, 891], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_naruto": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_naruto_3f24e1ff-731c-4dba-8b9f-f883e7a5c644.webp", "type": "image", "prompt": "A minimalist UI icon for Naruto's Nine-Tails Mode transformation, featuring a stylized orange fox silhouette surrounded by flickering orange chakra flames, clean lines, professional game-ready asset, matching the minimalist style of ability1_icon_naruto, vibrant orange and yellow colors, transparent background.", "description": "Ability icon for Naruto's Nine-Tails Chakra Mode transformation", "subtype": "ui", "aspect_ratio": [763, 769], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "rasenshuriken_projectile": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rasenshuriken_projectile_97db6480-435f-40f9-9f72-632c157de090.webp", "type": "image", "prompt": "Generate a glowing blue Rasenshuriken projectile, a large swirling energy sphere surrounded by four sharp rotating wind blades, minimalist 2D game asset style, clean lines, vibrant blue chakra effects, white core, transparent background, high resolution.", "description": "A spinning blue wind-based energy shuriken for Naruto's ultimate attack.", "subtype": "effect", "aspect_ratio": [746, 883], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rasengan_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/rasengan_sfx_c3589538-7531-4699-943b-9f079356d742.mp3", "type": "audio", "prompt": "High-pitched, swirling energy sound effect for a powerful spinning orb attack. The sound should feature a dense, rotating wind-like oscillation, electric humming, and a building high-frequency resonance. It should sound like compressed air and spiritual energy spinning at high speeds. Includes a quick, explosive energy release at the end. Cinematic anime style, powerful, sharp, and mystical.", "description": "A high-pitched, swirling energy sound effect for a Rasengan attack, featuring a sustained rotation sound and an impact release.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 4.32, "loop": false, "animation": null}, "naruto_transform_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/naruto_transform_sfx_35fdeab3-94d3-4dea-89d7-e95008e5174f.mp3", "type": "audio", "prompt": "Massive anime-style energy explosion sound effect. Begins with a low-frequency rumbling growl and a high-pitched spiritual hum, followed by a violent, roaring blast of red chakra energy. Features swirling wind textures, deep sub-bass impact, and a lingering crackle of intense power. Cinematic, aggressive, and supernatural, conveying a sense of overwhelming beastial strength. Clean tail, no background music.", "description": "A powerful roaring chakra explosion and energy surge for the Nine-Tails transformation.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 5, "loop": false, "animation": null}, "mahoraga_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_idle_503e6cf6-640c-4ff5-a778-da517abb4cbb.webp", "type": "image", "prompt": "Generate a full-body, side-view illustration of a large, muscular white stick figure character representing Mahoraga. The character features a large eight-spoked Dharma Wheel attached to its back and subtle black tattoo markings on its body. Imposing and powerful stature, minimalist 2D fighting game style consistent with a stick figure aesthetic, transparent background, high resolution.", "description": "Idle pose for the muscular white stick figure character Mahoraga with a Dharma Wheel", "subtype": "character", "aspect_ratio": [888, 1410], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_walk_49c0c56a-fe6c-4cb8-9c7e-6eb72f2c3a6f.webp", "type": "image", "prompt": "Generate a side-view walking animation frame of the Mahoraga character from image mahoraga_idle. It is a large, muscular white stick figure with a giant Dharma wheel attached to its back. The character is moving purposefully with a heavy, powerful stride. Minimalist stick figure style, clean lines, professional game asset quality, transparent background.", "description": "Walking animation frame for the Mahoraga stick figure character.", "subtype": "character", "aspect_ratio": [785, 1153], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_jump_50ad957b-7b8b-45eb-b120-88b46dfb3165.webp", "type": "image", "prompt": "Generate a dynamic jumping pose for the Mahoraga stick figure character from Jujutsu Kaisen. Large, muscular white stick figure with a large Dharma wheel attached to its back, minimalist 2D style. Side view, right-facing, mid-air leap with powerful legs. Match the style and character design of image 1. High resolution, clean lines, transparent background.", "description": "Dynamic jumping pose for the Mahoraga stick figure character with the Dharma wheel", "subtype": "character", "aspect_ratio": [757, 913], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_ability1_06bb7244-11a5-4722-a079-0d47bb84347d.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Mahoraga, a large white muscular figure with a Dharma wheel on its back, performing a powerful sword slash using the blade attached to its forearm. Dynamic action pose, side view, right-facing. Clean lines, professional game-ready asset, transparent background. Match the style and character design of mahoraga_idle.", "description": "Mahoraga stick figure performing a sword slash with its arm-blade", "subtype": "character", "aspect_ratio": [792, 957], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_ability2_4240a15f-287d-46f8-96e0-413b9dc08524.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Mahoraga, a large muscular white figure with a giant Dharma wheel attached to its back, performing a heavy ground smash attack. Side view, right-facing, striking the ground with both fists creating a powerful impact visual. Clean lines, minimalist style consistent with a 2D fighting game, transparent background, high resolution.", "description": "Mahoraga stick figure performing a heavy ground smash attack", "subtype": "character", "aspect_ratio": [795, 963], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_ability3_cba7b43b-d29e-4618-a9d3-af051a681179.webp", "type": "image", "prompt": "Generate a minimalist stick figure of Mahoraga performing a powerful, high-impact kick. The character is a large, muscular white stick figure with a giant Dharma wheel attached to its upper back. Side view, right-facing. Clean lines, minimalist 2D style consistent with image mahoraga_idle. Professional game asset with a transparent background.", "description": "Mahoraga stick figure performing a powerful kick attack", "subtype": "character", "aspect_ratio": [778, 1030], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_ability4_19341fd5-d04e-409c-85cf-5dcceadfe599.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Mahoraga, a large muscular white figure. The Dharma wheel on its back is spinning rapidly with motion blur, emitting bright glowing white energy. Side view, standing illustration, full body picture, high quality, professional game asset, transparent background.", "description": "Mahoraga stick figure performing an ability with its back wheel spinning rapidly and emitting white energy.", "subtype": "character", "aspect_ratio": [785, 1183], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_hit_b2d5ed6b-6d19-4bc6-8167-c3119f1ec6c6.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Mahoraga in a hit/damage recoil pose. The character is a large, muscular white stick figure with a giant Dharma wheel attached to its back. Side view, right-facing. The figure should appear staggered or recoiling from an impact. Clean, polished, game-ready game asset on a transparent background, high resolution.", "description": "Mahoraga stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [735, 1218], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_sukuna": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_sukuna_0d438b5d-f72d-4040-a6c7-34980e0d5546.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Summon Mahoraga' ability, featuring a clean silhouette of an 8-handled Dharma Wheel. High contrast black and white color scheme, professional game icon quality, clean lines, flat vector style, centered on a transparent background.", "description": "UI icon for Sukuna's Summon Mahoraga ability featuring a Dharma Wheel silhouette", "subtype": "ui", "aspect_ratio": [785, 1245], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "mahoraga_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/mahoraga_portrait_323fa735-554a-4d98-a356-17188730911d.webp", "type": "image", "prompt": "A minimalist, high-quality character selection portrait for Mahoraga. Show the upper torso and head of a muscular white stick figure character with a large eight-handled Dharma wheel positioned behind its head. Use dramatic lighting with high contrast, sharp edges, and a clean minimalist aesthetic. The style must match the existing stick figure character portraits. Transparent background.", "description": "Minimalist character selection portrait for Mahoraga featuring the Dharma Wheel", "subtype": "ui", "aspect_ratio": [784, 1247], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "enel_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_portrait_954c341a-9a5f-4d06-95be-7afa6a20d17f.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for a stick figure version of Enel. Features include long earlobes, bare chest, baggy orange pants, and a signature ring of drums attached to his back. The character has a smug facial expression. Clean 2D minimalist game art style, centered composition, high resolution, professional quality.", "description": "Minimalist character selection portrait for Enel with drums and smug expression", "subtype": "ui", "aspect_ratio": [688, 889], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "enel_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_idle_4035eb76-5104-4963-8341-97ba050eec3a.webp", "type": "image", "prompt": "Generate a minimalist stick figure character illustration of Enel from One Piece in an idle standing pose. The character is a lean black stick figure wearing baggy orange pants, bare chest, and distinctive long earlobes. He is holding a golden staff and has a circular ring of four drums (Taiko drums) attached to his back. Side view, right-facing character. Clean, polished, game-ready asset, minimalist 2D style, transparent background, high resolution.", "description": "Idle standing pose for the Enel stick figure character with gold staff and drums", "subtype": "character", "aspect_ratio": [579, 1031], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "enel_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_walk_d473aa7d-a06f-4754-b78c-7645f040b409.webp", "type": "image", "prompt": "A minimalist 2D stick figure character of Enel from One Piece in a walking pose. The character has long earlobes, a bare chest, baggy orange pants, and a ring of drums attached to his back. Side view, right-facing, clean lines, professional game asset style, transparent background. Matches the style of image 1.", "description": "Walking animation frame for the Enel stick figure character", "subtype": "character", "aspect_ratio": [648, 1163], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "enel_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_jump_4ebebff3-285a-47ea-b7de-009f22a76fb9.webp", "type": "image", "prompt": "Generate a minimalist stick figure of Enel from One Piece in a high jumping pose. The character should have long earlobes, a bare chest, baggy orange pants, and a ring of drums attached to his back. Side view, right-facing. Clean lines, minimalist 2D game asset style, transparent background, high resolution.", "description": "A dynamic jumping pose for the Enel stick figure character", "subtype": "character", "aspect_ratio": [511, 641], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "enel_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_ability1_85b2dcdf-1d7f-47a3-bb17-e213d0798aca.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Enel from One Piece performing a lightning attack. The character is a lean stick figure with long earlobes, baggy orange pants, and a ring of drums on his back. He is lunging forward with a gold staff, with bright blue electrical lightning bolts discharging from the staff. Clean 2D minimalist game art style, side view, right-facing, transparent background, high resolution.", "description": "Enel stick figure performing a lightning attack with his staff", "subtype": "character", "aspect_ratio": [740, 707], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "enel_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_ability2_cc43d767-523a-4d81-818b-bea63a723299.webp", "type": "image", "prompt": "Generate a full-body, minimalist stick figure of Enel from One Piece striking the drums on his back to generate bright blue lightning. The character has long earlobes and baggy orange pants. The style is clean, 2D minimalist vector art, with professional quality and high resolution. The background is transparent. Side-view, right-facing character.", "description": "Enel stick figure striking his drums to generate lightning, minimalist style.", "subtype": "character", "aspect_ratio": [769, 1248], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "enel_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_ability3_8c9281c5-d9d6-4146-8c0c-e870f312512c.webp", "type": "image", "prompt": "A minimalist stick figure of Enel transforming into a jagged, bright blue-white bolt of lightning. The figure should be partially dissolved into electricity, capturing a sense of high-speed movement. Keep the signature drums on the back visible within the electricity. Clean 2D minimalist style, transparent background, side view, right-facing.", "description": "Enel character transforming into a bolt of lightning for a dash or teleport ability", "subtype": "effect", "aspect_ratio": [688, 1242], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "enel_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_hit_31b0a5fe-3477-4a91-84cd-848e927e33b4.webp", "type": "image", "prompt": "Generate a minimalist stick figure of Enel from One Piece in a hit/damage recoil pose. The character should have long earlobes, a ring of drums on his back, and be reeling back from an impact. Maintain a clean, 2D minimalist style consistent with a fighting game asset. Full body illustration, front-facing, transparent background, high resolution.", "description": "Enel stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [710, 992], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "enel_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/enel_victory_bb16e0a4-1197-49e1-b944-b169a6ca8a5c.webp", "type": "image", "prompt": "Generate a victory pose for the Enel stick figure character from One Piece. He is sitting confidently and smugly, perhaps on a small stylized cloud. He is a lean stick figure with long earlobes, a bare chest, baggy orange pants, and a ring of drums attached to his back. Maintain the minimalist 2D art style consistent with existing characters. Standing/sitting illustration, transparent background, high quality.", "description": "Victory pose for Enel sitting confidently on a cloud throne", "subtype": "character", "aspect_ratio": [766, 929], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_enel": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_enel_8b1312d2-8c55-4db5-8c9a-f16150656cb1.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a special ability featuring a stylized electric bird made of blue lightning. Clean vector-style design, bold silhouettes, high contrast, vibrant blue electricity on a dark circular background, professional game asset quality, matching the minimalist style of other character icons.", "description": "Minimalist UI icon for Enel's Lightning Bird ability", "subtype": "ui", "aspect_ratio": [946, 942], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_enel": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_enel_09dad6ea-316e-40ad-994e-0ec3174bc72b.webp", "type": "image", "prompt": "A minimalist UI icon for a 'Lightning Teleport' ability. The icon features a stylized blue-white lightning bolt striking downward into a circle, suggesting high-speed movement or flashing away. Clean vector style, simple shapes, white silhouette on a dark circular background, consistent with a fighting game skill icon.", "description": "Minimalist UI icon for Enel's Lightning Teleport ability", "subtype": "ui", "aspect_ratio": [861, 850], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_enel": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_enel_8c699d3e-2bfe-480b-b4a7-311c47d580b9.webp", "type": "image", "prompt": "A minimalist UI icon for Enel's 'Lightning Dragon' ability. The icon should feature a stylized, sleek silhouette of a dragon made of jagged blue lightning bolts. Clean white or cyan lines on a dark background, high contrast, professional game UI quality, minimalist vector style to match the stick figure aesthetic.", "description": "Minimalist UI icon for Enel's Lightning Dragon ability", "subtype": "ui", "aspect_ratio": [689, 714], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_enel": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_enel_69c0e5a7-924c-45c0-974e-7697a2d809b5.webp", "type": "image", "prompt": "A minimalist UI icon for Enel's 'Raigo' ability, featuring a giant, ominous spherical ball of crackling electricity and dark clouds. Clean vector style, bold lines, high contrast, matching the existing minimalist game UI. The icon should be centered on a transparent background, professional quality.", "description": "Minimalist UI icon for Enel's Raigo (Giant Electric Sphere) ultimate ability.", "subtype": "ui", "aspect_ratio": [684, 651], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_portrait_f39f8fd3-90d9-4d73-ae28-d82982c209c2.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for Tanjiro Kamado in a stick figure style. Front-facing bust view, featuring his signature dark hair with red tips and hanafuda earrings. Simple clean lines, professional game UI quality, vibrant colors on a transparent background, matching the art style of existing character portraits like itachi_portrait and luffy_portrait.", "description": "Minimalist character selection portrait for Tanjiro Kamado in a stick figure style.", "subtype": "ui", "aspect_ratio": [729, 1248], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_idle_3ac0deb6-0989-4c15-a693-2a2708d21df6.webp", "type": "image", "prompt": "Generate a full-body, front-facing idle standing pose for a Tanjiro Kamado stick figure character. The character should have dark hair with red tips, wear a green and black checkered haori, and hold a katana at his side. Use a minimalist, clean 2D stick figure art style with thick lines and flat colors to match the aesthetic of 'bat_bai_idle' and 'goku_idle'. High resolution, professional game asset, transparent background.", "description": "Idle standing pose for the Tanjiro stick figure character in a minimalist style", "subtype": "character", "aspect_ratio": [490, 1136], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_walk_5f15b84b-af73-430e-be32-0d3960fb50df.webp", "type": "image", "prompt": "Generate a walking animation frame for the Tanjiro Kamado stick figure character. The character is a minimalist 2D stick figure with dark hair with red tips, wearing a green and black checkered haori. He is in a determined, purposeful stride, side view, right-facing, holding his demon slayer sword. Match the minimalist style and proportions of tanjiro_idle, transparent background.", "description": "Walking animation frame for the Tanjiro stick figure character", "subtype": "character", "aspect_ratio": [543, 1205], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_jump_4fcc8bbe-1d55-4615-b1c4-df5725d111ca.webp", "type": "image", "prompt": "Generate a dynamic jumping pose for the Tanjiro Kamado stick figure character. The character should be in mid-jump with an intense posture, holding his signature demon slayer sword ready for a strike. Maintain a minimalist 2D stick figure style consistent with image 1, featuring his dark hair with red tips and green-and-black checkered haori patterns. Side view, right-facing, transparent background, high resolution.", "description": "Dynamic jumping pose for the Tanjiro stick figure character for side-view combat.", "subtype": "character", "aspect_ratio": [606, 923], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_ability1_de9b6b91-78d6-427b-b370-c21cc87a2148.webp", "type": "image", "prompt": "Generate a full-body, side-view illustration of a minimalist stick figure Tanjiro Kamado in an attacking pose. He is performing a powerful sword slash that generates a fluid, stylized blue water wave effect (Mizunotenmon). The style should be clean and minimalist 2D, matching the existing stick figure characters. Include his green and black checkered haori and his katana. Transparent background, high resolution.", "description": "Tanjiro performing Water Breathing Form 2 - a water-based slash attack", "subtype": "character", "aspect_ratio": [714, 989], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_ability2_782f06c4-4b05-42be-af27-11f81da643fa.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Tanjiro Kamado performing a powerful Water Breathing thrust attack. The character is in a dynamic, low-profile forward lunging pose with his katana extended straight ahead in a piercing motion. Include flowing, stylized blue water current effects spiraling around the sword and arm to indicate the Water Breathing technique. Clean lines, minimalist detail, flat colors, side view, right-facing, transparent background, high resolution, matching the style of tanjiro_idle.", "description": "Tanjiro performing a powerful water-based piercing thrust attack", "subtype": "character", "aspect_ratio": [797, 608], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_ability3_a2b032f9-ab82-461d-b302-0bfc1eeae1c2.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Tanjiro Kamado performing Water Breathing Form 10 (Constant Flux). The character is in a dynamic circular motion with his black katana, surrounded by a large, flowing, spiraling dragon-like water current. Match the minimalist art style of image 1. Side view, right-facing character, transparent background, high resolution.", "description": "Tanjiro performing Water Breathing Form 10 (Constant Flux) with flowing water effects", "subtype": "character", "aspect_ratio": [811, 1184], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_hit_08dd32de-e473-46ef-935d-b1e2507ade33.webp", "type": "image", "prompt": "A minimalist 2D stick figure of Tanjiro Kamado in a hit/damage recoil pose. The character is staggered backward from an impact, with his body tilted and arms up defensively. He has dark hair with red tips and wears his signature checkered green and black haori over a demon slayer uniform. Clean lines, flat colors, side view, right-facing, transparent background, high resolution, professional game asset style matching the existing stick figure fighter aesthetic.", "description": "Tanjiro stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [567, 1235], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "tanjiro_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tanjiro_victory_e4f90407-2907-4d09-aab3-ead7af0a3f1d.webp", "type": "image", "prompt": "Generate a full-body, front-view victory pose for a Tanjiro Kamado stick figure character. The character is standing triumphantly, holding his black nichirin sword up confidently. Minimalist 2D stick figure style with dark hair, red tips, and a checkered haori pattern. High resolution, detailed, professional quality game asset on a transparent background.", "description": "Victory pose for Tanjiro Kamado stick figure standing triumphantly with his sword.", "subtype": "character", "aspect_ratio": [626, 1229], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_tanjiro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_tanjiro_abf6f69d-d936-48fd-b1e6-3b1e84594980.webp", "type": "image", "prompt": "A minimalist UI icon for a 'Water Breathing' ability, featuring a stylized blue and white water wave slash symbol. The design should be clean, high-contrast, and suitable for a game ability button, matching the minimalist aesthetic of the existing character icons. Transparent background.", "description": "Minimalist UI icon for Tanjiro's Water Breathing Form 2 ability", "subtype": "ui", "aspect_ratio": [781, 713], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_tanjiro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_tanjiro_0bc6862f-6180-4091-bbe0-215ee43a61b8.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a water breathing technique, featuring a stylized red water thrust or piercing motion symbol. The design should be clean, high-contrast, and professional quality, matching the minimalist aesthetic of existing ability icons. Use a red color palette as specified, on a transparent background.", "description": "Minimalist UI icon for Tanjiro's Water Breathing Form 6 ability", "subtype": "ui", "aspect_ratio": [816, 739], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_tanjiro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_tanjiro_1c6afcdc-7775-4973-98bc-676051008164.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Water Breathing Form 10' ability. The icon should feature a stylized, clean-edged flowing water or circular motion symbol in a vibrant red color. Maintain a simple, flat design style suitable for a fighting game HUD. The background must be transparent.", "description": "Minimalist UI icon for Tanjiro's Water Breathing Form 10 ability featuring a red flowing water symbol.", "subtype": "ui", "aspect_ratio": [1021, 926], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_tanjiro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_tanjiro_6d90ba33-d5be-4967-8642-b1585980ca16.webp", "type": "image", "prompt": "A minimalist UI icon for a fire breathing ultimate ability, featuring a stylized orange-red flame and sun symbol representing 'Hinokami Kagura'. Clean vector style, flat design, bold silhouette, vibrant orange and red colors, transparent background, high resolution game asset.", "description": "UI icon for Tanjiro's Hinokami Kagura fire breathing ultimate ability", "subtype": "ui", "aspect_ratio": [1018, 927], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_portrait_be165d0b-4f8b-455e-896b-d42b6a3c4b8c.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for Yuji Itadori. Stick figure style, spiky pink hair, dark blue school uniform with a prominent red hoodie collar. Front-facing view, clean lines, professional game UI quality, solid color background, match the minimalist aesthetic of gojo_portrait and sukuna_portrait.", "description": "Minimalist character selection portrait for Yuji Itadori in stick figure style.", "subtype": "ui", "aspect_ratio": [589, 1020], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_idle_b1942bca-de48-401b-b422-51d2f16888d4.webp", "type": "image", "prompt": "Generate a full-body, side-view standing illustration of a minimalist Yuji Itadori stick figure character. The character should have spiky pink hair, a dark blue school uniform, and a distinctive red hoodie collar. Clean lines, flat colors, professional game-ready asset, minimalist 2D art style, transparent background.", "description": "Idle standing pose for the Yuji Itadori stick figure character in a minimalist style", "subtype": "character", "aspect_ratio": [353, 1207], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_walk_a1f044c7-2ac2-409e-9052-8193d2d17256.webp", "type": "image", "prompt": "Generate a 2D side-view walking animation frame of a minimalist stick figure character representing Yuji Itadori. The character has spiky pink hair and wears a dark blue school uniform with a red hoodie collar. Maintain the clean, minimalist 2D art style consistent with image 1 and image 2. Transparent background.", "description": "Walking animation frame for the Yuji Itadori stick figure character", "subtype": "character", "aspect_ratio": [598, 1130], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_jump_670afbae-cec6-4e59-99cd-ac2d51b0ba18.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Yuji Itadori in a dynamic jumping pose, side view. The character has spiky pink hair, a dark blue school uniform, and a prominent red hoodie collar. Clean lines, high resolution, transparent background, matching the art style of image 1.", "description": "Jumping pose for the Yuji Itadori stick figure character", "subtype": "character", "aspect_ratio": [704, 975], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_ability1_d711d6bc-9069-4bf1-ae28-efefc6be1434.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Yuji Itadori performing a powerful punch. The character has spiky pink hair and wears a dark blue school uniform with a red hoodie collar. His fist is enveloped in glowing blue energy (Divergent Fist). Side view, right-facing, transparent background, high resolution, clean game-ready asset.", "description": "Yuji Itadori stick figure performing a Divergent Fist attack with blue cursed energy.", "subtype": "character", "aspect_ratio": [703, 1195], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_ability2_33cc92a7-ef94-407e-b007-64e139d69ed5.webp", "type": "image", "prompt": "Generate a 2D minimalist stick figure character of Yuji Itadori in a defensive bracing pose, arms crossed in front of his face to block. The character has spiky pink hair and wears a dark blue school uniform with a red hoodie collar. Side view, right-facing, clean lines, professional game-ready asset, transparent background, matching the style of image 1.", "description": "Yuji Itadori stick figure character in a defensive bracing pose", "subtype": "character", "aspect_ratio": [459, 1238], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "yuji_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_ability3_f25e8533-bb11-4bd4-b312-213943c53663.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Yuji Itadori performing a dynamic high kick. The character has spiky pink hair and wears a dark blue school uniform with a distinctive red hoodie collar. Side view, right-facing. Maintain the minimalist art style of image yuji_idle. Clean lines, transparent background, high resolution.", "description": "Yuji Itadori stick figure character performing a dynamic high kick", "subtype": "character", "aspect_ratio": [764, 1168], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_hit_1a41e63f-e324-4fdf-b681-1239704072a0.webp", "type": "image", "prompt": "Generate a 2D side-view minimalist stick figure character of Yuji Itadori in a hit or damage recoil pose. The character has spiky pink hair, a dark blue school uniform, and a red hoodie collar. The pose should show the character being pushed back or reeling from an impact, consistent with the art style of image 1.", "description": "Yuji Itadori stick figure character in a hit or damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [813, 745], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuji_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuji_victory_3e7d047b-16c5-4ff8-8187-979c937831c8.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Yuji Itadori in a victory pose. The character has spiky pink hair, wears a dark blue school uniform with a prominent red hoodie collar. He is wiping his nose with his thumb and grinning confidently. Side view, right-facing. High resolution, clean lines, professional game asset style, transparent background. Match the style and character design of yuji_idle.", "description": "Victory pose for Yuji Itadori stick figure character showing him wiping his nose with a confident grin", "subtype": "character", "aspect_ratio": [500, 1237], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_yuji": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_yuji_f28277af-1566-4f59-89d0-145cdf9fed67.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Divergent Fist' ability. The icon should feature a stylized fist silhouette surrounded by a double-layered blue cursed energy aura. Use a clean, flat design with high contrast, matching the minimalist stick figure game style. High resolution, white or simple blue tones, transparent background.", "description": "Minimalist UI icon for Yuji's Divergent Fist ability, featuring a fist with blue energy.", "subtype": "ui", "aspect_ratio": [681, 692], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_yuji": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_yuji_a5931374-5b3f-4807-8ba0-aae104a1c162.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a defensive ability, featuring a stylized shield or bracing silhouette in a clean, flat vector style. Use a color palette consistent with Yuji's character (red and dark blue), high contrast, professional game-ready quality on a transparent background.", "description": "Minimalist UI icon for Yuji's defensive ability", "subtype": "ui", "aspect_ratio": [645, 630], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_yuji": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_yuji_ea07c75e-6170-4011-8e4c-dd0a5d6be134.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Combo Punch' ability. The icon should feature stylized silhouettes of multiple punching fists to represent a rapid sequence of attacks. Use a clean, graphic style with high contrast, matching the minimalist aesthetic of the other ability icons. Dark background with a prominent, simple white or light-colored icon graphic.", "description": "Minimalist UI icon for Yuji's combo punch ability featuring multiple fist silhouettes.", "subtype": "ui", "aspect_ratio": [692, 692], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_yuji": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_yuji_88f2399d-1554-488b-8e12-dcfc4f11c69b.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a special ability called 'Black Flash'. The design features a stylized rock or fist silhouette at the center, surrounded by intense, jagged black and red lightning bolts and energy sparks. High-contrast, clean lines, game-ready UI element, professional quality, transparent background.", "description": "Minimalist UI icon for Yuji's Black Flash ultimate ability featuring black and red lightning", "subtype": "ui", "aspect_ratio": [807, 809], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "black_flash_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/black_flash_sfx_0cd4370c-e78f-4594-822a-2e6675119fcc.mp3", "type": "audio", "prompt": "A massive, supernatural combat impact sound effect. Begins with a heavy, distorted low-frequency 'boom' that vibrates with power, immediately followed by a sharp, aggressive electrical discharge crackle. The sound should conclude with a high-pitched, eerie metallic ringing resonance that fades out slowly. Inspired by the Black Flash from Jujutsu Kaisen. High energy, dark, forceful, and cinematic.", "description": "Powerful, supernatural distorted impact sound with deep bass and electrical crackle, used for a critical combat strike.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3.13, "loop": false, "animation": null}, "garp_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_portrait_3b5a98b3-dc55-4cf2-8f8d-a41b2dc62ac3.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait of Garp from One Piece. Stick figure style with high-quality clean lines. He has spiky white hair, a small scar under his left eye, and is wearing a white marine suit with a high collar. Determined expression, front-facing, professional game UI quality. Simple clean background, matching the style of existing character portraits.", "description": "Minimalist character selection portrait for Garp in a stick figure style.", "subtype": "ui", "aspect_ratio": [356, 947], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "garp_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_idle_579ea221-a45b-4e2e-9542-454edd08c8f4.webp", "type": "image", "prompt": "Generate a full-body, front-view illustration of a muscular stick figure character named Garp. He has spiky white hair and is wearing a white marine suit with a white marine cape draped over his shoulders. The style is minimalist 2D, consistent with other fighting game stick figure assets. Professional quality, clean lines, transparent background, standing idle pose.", "description": "Idle standing pose for the Garp stick figure character", "subtype": "character", "aspect_ratio": [693, 1208], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "garp_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_walk_154617e6-f054-4033-a424-08acb98c70cb.webp", "type": "image", "prompt": "Generate a walking animation frame for the Garp stick figure character. He is a muscular stick figure with spiky white hair, wearing a white marine suit with a flowing white cape. He has a powerful, confident stride. Side view, right-facing. Minimalist 2D stick figure style, clean lines, white marine aesthetic, transparent background. Match the character design of garp_idle.", "description": "Walking animation frame for the Garp stick figure character with a confident stride.", "subtype": "character", "aspect_ratio": [691, 1104], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "garp_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_jump_20b64a47-ae6f-4533-9a7f-4080390d0f78.webp", "type": "image", "prompt": "Generate a dynamic jumping pose of the Garp stick figure character from One Piece. The character is a muscular stick figure with spiky white hair, wearing a white marine suit and a flowing white marine cape. He should have his legs tucked in mid-air. Side view, right-facing. Minimalist 2D flat stick figure style, clean lines, professional quality, transparent background. Reference the character design from garp_idle.", "description": "Jumping pose for the Garp stick figure character with a flowing marine cape", "subtype": "character", "aspect_ratio": [600, 521], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "garp_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_hit_5ada5d30-04a3-4ae0-b77f-2c245141596e.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Garp in a hit or damage recoil pose. The character has spiky white hair and wears a white marine suit with a flowing cape. He should look like he just took an impact, with his body recoiling backwards. Side view, transparent background, clean lines, high resolution, professional game asset style.", "description": "Garp stick figure character in a hit or damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [682, 770], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "garp_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_victory_52f9b172-7678-4b11-b7fb-893dbb082fcf.webp", "type": "image", "prompt": "Generate a full-body, front-view minimalist 2D stick figure illustration of Monkey D. Garp in a victory pose. The character should be laughing heartily with hands on hips, featuring spiky white hair, a white marine suit, and a white marine cape flowing behind him. Maintain the minimalist aesthetic and style of garp_idle, transparent background, high resolution.", "description": "Victory pose for Garp stick figure character, laughing heartily", "subtype": "character", "aspect_ratio": [702, 1131], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_garp": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_garp_ad8fcd6c-2f30-4a26-a42b-e38f41d8db7f.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Fist of Love' ability, featuring a clean white fist silhouette against a dark background. Professional game-ready icon, flat design, vector-like quality, high contrast, simple and iconic shape to match the stick figure game style.", "description": "UI icon for Garp's 'Fist of Love' ability, featuring a simple white fist silhouette.", "subtype": "ui", "aspect_ratio": [321, 230], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_garp": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_garp_7a6b8501-57c1-4067-9856-b97d7f500490.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Cannonball' ability. The icon features a solid black cannonball silhouette with a small sparking fuse. Clean, sharp edges, flat design, suitable for a mobile game HUD. High resolution, white or transparent background, game-ready quality.", "description": "Minimalist UI icon for Garp's Cannonball ability", "subtype": "ui", "aspect_ratio": [701, 755], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_garp": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_garp_7efcdd1f-6a5f-48ce-bbd3-1f24f3f1730c.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a heavy punch ability. The icon should feature a stylized, powerful fist silhouette with impact lines to suggest great force, matching the clean and simple aesthetic of the existing game icons. Use a high-contrast color scheme suitable for a white marine-themed character, professional game-ready quality, transparent background.", "description": "Minimalist UI icon for Garp's heavy punch ability featuring a powerful fist silhouette", "subtype": "ui", "aspect_ratio": [986, 722], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_garp": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_garp_58e4c613-70fd-4710-bc62-9d20ade06428.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Garp's 'Galaxy Impact' ultimate ability. The design should feature a central fist silhouette emitting a massive, explosive energy shockwave in a striking red and black color palette. Clean vector-style graphics, high contrast, suitable for a fighting game HUD. Minimalist stick-figure aesthetic to match existing game UI.", "description": "Minimalist UI icon for Garp's Galaxy Impact ultimate ability featuring a fist and shockwave", "subtype": "ui", "aspect_ratio": [941, 927], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "garp_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_ability1_17bf8501-9945-4dd7-8654-46ebbe1644df.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Garp the Marine Hero from a side-view perspective. The character is leaning forward, delivering a massive, focused punch. He wears a white marine cape with the word 'Justice' on the back. Clean lines, minimalist style consistent with image 1. Transparent background, high resolution, game-ready asset.", "description": "Garp stick figure performing a powerful 'Fist of Love' punch attack", "subtype": "character", "aspect_ratio": [768, 635], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "garp_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_ability2_af19bdf8-881e-422a-91b8-7ecb0049297c.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view stick figure of Garp the Marine Hero in a dynamic throwing pose. He is holding a large, heavy iron cannonball, preparing to hurl it forward. He wears a white marine cape with 'Justice' kanji that flows behind him. Clean lines, minimalist aesthetic matching the style of garp_idle, high resolution, transparent background.", "description": "Garp stick figure in a throwing pose holding a large cannonball", "subtype": "character", "aspect_ratio": [738, 680], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "garp_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_ability3_5e1288f8-76ad-4833-b742-bad6d03b4323.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Garp the Marine Hero from a side view. He is performing 'Navy Strikes', shown as a flurry of powerful punches with multiple blurred arm effects and white speed lines to suggest rapid movement. He is wearing a white marine cape with 'Justice' written on the back. Clean lines, simple colors, transparent background, matching the style of garp_idle.", "description": "Garp performing a flurry of powerful punches with speed blur effects", "subtype": "character", "aspect_ratio": [724, 750], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "garp_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/garp_ability4_fc472188-64d3-4346-ab51-c3509cf8c03c.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Garp the Marine Hero in an epic mid-air downward punching pose for his 'Galaxy Impact'. The character features a white marine cape billowing upwards, leaning into a massive strike directed downwards. Side view, right-facing, clean minimalist lines, transparent background, high resolution, matching the style of garp_idle.", "description": "Garp performing his Galaxy Impact ultimate ability in a mid-air downward punch pose", "subtype": "character", "aspect_ratio": [817, 1248], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_portrait_e89602ca-b251-47a7-a23c-44632e5e3832.webp", "type": "image", "prompt": "Generate a high-quality, minimalist character selection portrait of Doraemon in a stick figure style. The character features a clear blue body, white belly, and the iconic red collar with a golden bell. Position the character centered, facing slightly towards the viewer. Use a clean, vibrant light blue background. Maintain visual consistency with existing minimalist stick figure portraits like 'luffy_portrait' and 'naruto_portrait'. Professional game UI quality, centered composition, front-facing.", "description": "Minimalist character selection portrait for Doraemon in a stick figure style.", "subtype": "ui", "aspect_ratio": [1024, 1024], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_idle_a8fdc487-8369-4d92-a7f4-f039918537f7.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Doraemon in a neutral idle standing pose. The character has a blue stick figure body, a white circular belly area, a red collar with a small yellow bell. Clean lines, flat colors, side view, right-facing. Transparent background, high-quality game asset, consistent with the existing stick figure art style.", "description": "Idle standing pose for the Doraemon stick figure character in a minimalist style", "subtype": "character", "aspect_ratio": [587, 1207], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_walk_039134ee-2fa9-4ad4-82a8-ae814894f536.webp", "type": "image", "prompt": "Generate a side-view walking animation frame for a Doraemon-inspired stick figure character. The character is a minimalist blue stick figure with a white circular belly area, a red collar, and a small yellow bell. Clean lines, minimalist 2D game asset style, right-facing, transparent background, matching the style of image 1.", "description": "Walking animation frame for the Doraemon stick figure character.", "subtype": "character", "aspect_ratio": [661, 1070], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_jump_3367a506-ec21-406f-8365-edf20cc97f53.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character based on image 1 in a dynamic jumping pose. The character is blue with a white belly area, a red collar, and a small yellow bell. Side view, right-facing, clean lines, professional game-ready asset on a transparent background.", "description": "Jumping pose for the Doraemon stick figure character", "subtype": "character", "aspect_ratio": [621, 940], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_hit_65acbb15-5755-4815-9015-58c5cf2f3bf5.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Doraemon in a hit or damage recoil pose. The character is a blue stick figure with a white belly area, a red collar, and a small yellow bell. The pose should show the character being pushed back or reeling from an impact, with a stunned expression. Side view, right-facing, transparent background, clean lines, high resolution, game-ready asset.", "description": "Doraemon stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [662, 1145], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_victory_a3f324f3-8033-4c7d-8512-1f5996652410.webp", "type": "image", "prompt": "Generate a victory pose for a Doraemon stick figure character. The character is a minimalist blue stick figure with a white belly, red collar, and yellow bell, holding a brown dorayaki pancake and smiling. Professional game-ready illustration, minimalist 2D style, side view, front-facing, transparent background.", "description": "Victory pose for Doraemon stick figure character holding a dorayaki", "subtype": "character", "aspect_ratio": [779, 874], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_ability1_08368c61-a5f6-4ad4-a44e-05e2ed6f1092.webp", "type": "image", "prompt": "Generate a minimalist blue stick figure character 'Doraemon' with a white belly, red collar, and yellow bell, reaching into a semi-circular white 4D pocket on its belly. Side view, right-facing. High contrast, clean lines, professional 2D game asset style on a transparent background.", "description": "Doraemon stick figure reaching into his 4D pocket for an item", "subtype": "character", "aspect_ratio": [607, 1246], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_ability2_4add31cf-1b23-49df-a324-b1c4116ad958.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Doraemon flying slightly. The character has a blue stick body, a white belly area, a red collar with a yellow bell, and a yellow bamboo-copter (Takecopter) spinning on top of his head. Side view, right-facing. Maintain consistency with the style of image 'doraemon_idle'. Transparent background, high quality, game-ready asset.", "description": "Doraemon stick figure character flying with a Takecopter on his head", "subtype": "character", "aspect_ratio": [503, 945], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "chaien_summon": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/chaien_summon_90296192-d3d2-4783-92dc-cf65ebb7ef27.webp", "type": "image", "prompt": "Generate a minimalist stick figure character of Chaien (Gian) from Doraemon. He is singing loudly with his mouth wide open, surrounded by jagged, chaotic musical notes indicating terrible singing. He wears his signature orange shirt with a dark zig-zag pattern. Clean stick figure style, side view, right-facing, transparent background, high resolution, game-ready illustration.", "description": "Stick figure of Chaien (Gian) singing loudly for a summon ability effect", "subtype": "effect", "aspect_ratio": [840, 1382], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "nobita_summon": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/nobita_summon_b000bcd3-5907-4c9a-9b69-2b8bdadf961f.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Nobita. He has a simple stick-man body wearing a yellow shirt and iconic round glasses. He is holding a futuristic 'Air Cannon' (tube-like gadget) on his hand, ready to fire. Clean lines, minimalist aesthetic, side view, right-facing, transparent background.", "description": "A minimalist stick figure of Nobita with an air cannon for the Doraemon summon ability.", "subtype": "effect", "aspect_ratio": [543, 769], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_doraemon": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_doraemon_99f9fa25-44d3-4652-adfb-095c470820c1.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Dorayaki' (Japanese pancake) ability. The icon should feature a stylized, clean silhouette of a dorayaki with a visible filling layer in the middle. Use a flat, vector art style with bold lines and a simple color palette of golden brown and dark red. High contrast, professional game-ready icon on a transparent background.", "description": "A minimalist UI icon for Doraemon's Dorayaki ability.", "subtype": "ui", "aspect_ratio": [768, 587], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_doraemon": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_doraemon_0f5b411c-2e85-47c1-b193-6baecf9117db.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Doraemon's '\u0110\u00e8n Pin Thu Nh\u1ecf' (Shrink Ray). The icon should feature a stylized, clean silhouette of a flashlight emitting a beam of light. Use a simple color palette, polished game-ready vector style, high resolution, professional quality, on a transparent background.", "description": "Minimalist UI icon for Doraemon's Shrink Ray ability featuring a flashlight silhouette.", "subtype": "ui", "aspect_ratio": [728, 731], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_doraemon": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_doraemon_24732d41-a1d6-4955-8ad2-0140d10ae28f.webp", "type": "image", "prompt": "A minimalist UI icon for a 'Chaien Summon' ability featuring a bold, stylized musical note symbol. Clean vector lines, high contrast, minimalist game interface style. Flat design with a simple color palette that matches the Doraemon theme (blue and white accents).", "description": "Ability icon for Doraemon's Chaien summon featuring a musical note", "subtype": "ui", "aspect_ratio": [771, 766], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_doraemon": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_doraemon_1654583e-d7bb-4086-b72f-a22a5ff04476.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Nobita Summon' ability. The icon should feature a clean, bold silhouette of an air cannon (\u0110\u1ea1i b\u00e1c kh\u00f4ng kh\u00ed) gadget. Maintain a flat design, high contrast, and a minimalist style consistent with other game icons. Professional game UI quality on a transparent background.", "description": "UI icon for Doraemon's Nobita summon ability featuring an air cannon silhouette", "subtype": "ui", "aspect_ratio": [715, 716], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_beach_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_beach_portrait_cfcf836c-87b7-4538-ad71-b9dacf420291.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for 'Beach Vua Qu\u1ef7'. A 2D stick figure character with a small gold crown, wearing a bright yellow short-sleeved shirt with a banana pattern and yellow shorts. The character has a relaxed expression and is holding a coconut with a straw. Use a clean, professional minimalist 2D style with a flat color background to match the style of vua_quy_portrait. High resolution, centered composition.", "description": "Minimalist character selection portrait for Beach Vua Qu\u1ef7 (Demon King) in summer attire", "subtype": "ui", "aspect_ratio": [235, 853], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_beach_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_beach_idle_57c43dae-5998-4ea2-b18a-b3d6611e041c.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character illustration in idle standing pose. The character is 'Beach Vua Qu\u1ef7', a stick figure wearing a bright yellow shirt with a banana pattern and matching yellow shorts. Minimalist art style, clean lines, side view, right-facing. Maintain consistent visual style and proportions with the existing 'vua_quy_idle' asset. Transparent background, high resolution.", "description": "Idle standing pose for the Beach version of the Demon King stick figure character", "subtype": "character", "aspect_ratio": [272, 1094], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_beach_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_beach_walk_673c463a-d9af-48e0-9b8a-b4fb4efd2114.webp", "type": "image", "prompt": "Generate a side-view walking animation frame for a stick figure character 'Beach Vua Qu\u1ef7'. The character should be a minimalist black stick figure wearing a bright yellow short-sleeved shirt with a green banana pattern and matching yellow shorts. One leg should be forward and arms in a mid-stride walking motion. Maintain the minimalist, clean 2D vector-like art style of the existing stick figure characters. Side-view, right-facing, transparent background.", "description": "Walking animation frame for the Beach skin version of the Demon King stick figure character", "subtype": "character", "aspect_ratio": [516, 1207], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_beach_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_beach_jump_ab884c36-c685-4f5e-b0a1-fab1e9ba0693.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character 'Beach Vua Qu\u1ef7' in a dynamic jumping pose. The character is wearing a bright yellow shirt with a small banana pattern and matching yellow shorts. Side view, right-facing. Maintain the same character proportions and minimalist style as image 1 and image 2. Transparent background, high resolution, game-ready illustration.", "description": "Jumping animation pose for the Beach Demon King stick figure character", "subtype": "character", "aspect_ratio": [489, 917], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_beach_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_beach_ability1_c7eee52a-2906-494d-9ba7-e759e854960e.webp", "type": "image", "prompt": "Generate a 2D minimalist side-view illustration of the 'Beach Vua Qu\u1ef7' stick figure character performing an attack. The character is wearing a bright yellow shirt with a banana pattern and yellow shorts. He is dynamically swinging a colorful surfboard like a weapon. The style must be a clean, minimalist stick figure illustration on a transparent background, matching the visual identity of existing characters like 'vua_quy_beach_idle'. High resolution, game-ready asset.", "description": "Attack pose for Beach Vua Qu\u1ef7 swinging a surfboard in a minimalist stick figure style", "subtype": "character", "aspect_ratio": [699, 964], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "vua_quy_beach_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/vua_quy_beach_victory_2265d4c1-f054-412e-8abb-4213b929f323.webp", "type": "image", "prompt": "Generate a victory pose illustration of a minimalist stick figure character known as 'Beach Vua Qu\u1ef7'. The character is wearing a bright yellow shirt with a small banana pattern and yellow shorts. He is reclining comfortably on a beach towel, holding a coconut with a straw and giving a confident thumbs up. 2D minimalist game art style, side view, clean lines, professional quality, transparent background.", "description": "Victory pose for Beach Vua Qu\u1ef7 wearing a banana shirt and shorts, relaxing with a coconut.", "subtype": "character", "aspect_ratio": [744, 678], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "coconut_tree": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/coconut_tree_963c5d41-4be6-4f7e-8d3b-91e9255f8bc0.webp", "type": "image", "prompt": "Generate a minimalist 2D coconut tree with a few coconuts hanging. Clean lines, simple flat colors, professional game-ready asset. Side view, 2D art style matching a minimalist stick-figure fighting game. High resolution, detailed but simple. Transparent background.", "description": "A minimalist 2D coconut tree with hanging coconuts for the arena background.", "subtype": "object", "aspect_ratio": [911, 1306], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "po_panda_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_portrait_fb37d782-c534-4932-ac05-1ec8b78c6226.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for Po from Kung Fu Panda. The style should be a clean, 2D stick figure illustration. The character is a rounder black and white stick figure wearing a conical straw hat and visible panda ears. Focus on the head and shoulders, using bold lines and a simple color palette against a transparent background. Professional game UI quality.", "description": "Minimalist character selection portrait for Po (Kung Fu Panda) in a stick figure style.", "subtype": "ui", "aspect_ratio": [788, 865], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "po_panda_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_idle_0dc18441-19a4-487a-a570-1beeb50e434e.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Po the Panda in an idle standing pose. The character should have a rounder body shape, black and white limbs, and be wearing brown shorts. Side view, right-facing, clean lines, professional game-ready asset, transparent background.", "description": "Idle standing pose for Po the Panda stick figure character in a minimalist style", "subtype": "character", "aspect_ratio": [440, 869], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "po_panda_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_walk_da2e2f29-6c99-4c46-b5dd-ea7611008e92.webp", "type": "image", "prompt": "Generate a side view, right-facing walking animation frame for a Po the Panda stick figure character. The character is a rounder black and white stick figure with panda ears, wearing brown kung fu shorts. Minimalist 2D flat style, clean lines, transparent background. The pose should show a bouncing, energetic walk matching the minimalist stick figure aesthetic of image 1.", "description": "Walking animation frame for the Po the Panda stick figure character", "subtype": "character", "aspect_ratio": [647, 1163], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "po_panda_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_jump_8b490e06-e3c8-4763-8e4e-2de32b1d99c1.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Po from Kung Fu Panda in a high jumping pose. The character should have a rounder body, black and white limbs, panda ears, and wear brown shorts. Both arms are out for balance. Full body picture, side view, right-facing, transparent background, clean game-ready vector style matching the aesthetic of po_panda_idle.", "description": "Jumping pose for the Po the Panda stick figure character", "subtype": "character", "aspect_ratio": [736, 974], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "po_panda_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_ability1_683534f9-fd1b-485f-a17c-2dfeacf92e4e.webp", "type": "image", "prompt": "A minimalist 2D stick figure of Po the Panda performing a powerful forward palm strike. The character is a rounder black and white stick figure wearing brown shorts. A vibrant, glowing golden chi energy effect radiates from the palm. Side view, right-facing, action pose, transparent background, clean lines, professional game asset style.", "description": "Po the Panda stick figure performing a golden chi palm strike", "subtype": "character", "aspect_ratio": [678, 860], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "po_panda_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_ability2_b8027933-4584-4ffe-ba9e-5d2a76b1ee42.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Po the Panda, depicted as a rounder black and white stick figure, curled tightly into a ball shape for a rolling attack. The character should have panda-like features (ears, black and white patterns) and be wearing brown shorts. Side-view perspective, action pose, clean lines, polished game-ready asset, transparent background, high resolution.", "description": "Po the Panda stick figure curled into a ball for a rolling attack", "subtype": "character", "aspect_ratio": [663, 555], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "po_panda_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_ability3_99180b39-735c-4b95-9ce6-b978c847d17e.webp", "type": "image", "prompt": "Generate a full-body side view of a rounder black and white stick figure character (Po from Kung Fu Panda) performing the Wuxi Finger Hold. The character is wearing brown shorts. A massive, radiant golden dragon chi aura swirls around him. Clean minimalist 2D game asset style, high resolution, detailed energy effects, transparent background.", "description": "Po the Panda performing his ultimate Wuxi Finger Hold with a golden dragon aura", "subtype": "effect", "aspect_ratio": [960, 1011], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "po_panda_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_hit_7936beb6-6b4c-4420-9f8b-25759abcaa4c.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Po from Kung Fu Panda in a hit/damage recoil pose. The character should have a rounder black and white body, wearing brown shorts, looking stunned or knocked back. Side view, right-facing. Maintain a clean, polished, game-ready aesthetic with a transparent background. Match the visual style and character design of po_panda_idle.", "description": "The Po the Panda stick figure character in a hit or damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [856, 1200], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "po_panda_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/po_panda_victory_c29631da-c14f-42aa-b98e-e970cbfc512e.webp", "type": "image", "prompt": "Generate a full-body, front-view victory pose for Po the Panda as a minimalist stick figure. The character is a rounder black and white stick figure with panda ears and brown shorts, shown happily eating a small dumpling with a wide smile. Use a clean 2D minimalist vector art style consistent with other game characters. High resolution, detailed character design, transparent background.", "description": "Victory pose for Po the Panda stick figure eating a dumpling and smiling.", "subtype": "character", "aspect_ratio": [743, 1101], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_po_panda": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_po_panda_e661e3ca-e9a3-47fe-b9e0-0005d47f8fd0.webp", "type": "image", "prompt": "A minimalist 2D UI game icon for a 'Panda Punch' ability. The icon features a stylized black and white fist silhouette surrounded by a radiant golden light aura. Clean lines, vector style, flat design, suitable for a fighting game mobile interface, high contrast, transparent background.", "description": "Ability icon for Po's Panda Punch featuring a black and white fist with golden light.", "subtype": "ui", "aspect_ratio": [471, 465], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_po_panda": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_po_panda_bcc96136-392c-47b9-9fe9-5d815029891f.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Po's 'Rolling Strike' ability. The icon should feature a stylized spinning circle silhouette with motion lines, representing a rolling panda. Use a clean, black and white color palette with subtle golden accents to match the kung fu theme. Vector style, flat design, centered on a transparent background, high resolution.", "description": "Ability icon for Po's Rolling Strike featuring a spinning circle silhouette", "subtype": "ui", "aspect_ratio": [574, 572], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_po_panda": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_po_panda_8e60bfea-7d16-4292-9c2f-effcbef01003.webp", "type": "image", "prompt": "A minimalist, professional quality UI icon for a special ability called 'Wuxi Finger Hold'. The design features a stylized, elegant golden dragon silhouette on a dark, circular background. The style should match the existing minimalist stick figure game aesthetic. High contrast, clean lines, and a focused composition suitable for a game button.", "description": "Ability icon for Po's Wuxi Finger Hold featuring a golden dragon silhouette", "subtype": "ui", "aspect_ratio": [893, 894], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_po_panda": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_po_panda_cf229e0a-4bb3-4488-91eb-eca04a139132.webp", "type": "image", "prompt": "A minimalist, clean game UI icon for a 'Long Th\u1ea7n B\u00e1t Qu\u00e1i' ultimate ability. The icon features a detailed golden dragon head silhouette with elegant horns and a glowing golden Bagua (octagonal) symbol positioned behind it. Style must match the minimalist, flat aesthetic of existing ability icons like ability3_icon_po_panda. Use a dark, slightly textured square background, high contrast, professional quality, transparent background.", "description": "Minimalist UI icon for Po's 'Long Th\u1ea7n B\u00e1t Qu\u00e1i' ultimate ability featuring a golden dragon and Bagua symbol.", "subtype": "ui", "aspect_ratio": [778, 779], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "map_one_piece": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/map_one_piece_10dd323b-7cbf-47a0-9e84-1a5794429650.webp", "type": "image", "prompt": "Generate a 9:16 tall background image of a lush tropical island beach for a 2D minimalist fighting game. The scene features white sand, clear blue ocean water, and a small stylized pirate ship with a sheep head figurehead (inspired by the Going Merry) anchored in the far distance. Bright, sunny, and vibrant atmosphere. The style is clean and minimalist to match stick figure characters. Ensure the lower half of the image is clear for game action. High resolution, professional quality, flat 2D vector-like aesthetic.", "description": "A lush tropical 'One Piece' themed beach background for a minimalist fighting game.", "subtype": "background", "aspect_ratio": [1024, 1536], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "map_naruto_village": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/map_naruto_village_e8acc303-0d78-42a4-954a-c0a2293b57ce.webp", "type": "image", "prompt": "Generate a 9:16 tall image of a 2D minimalist fighting game background depicting the entrance to the Hidden Leaf Village (Konoha). In the foreground, include the iconic large green village gate. In the background, show the Hokage Rock mountain with carved faces under a bright blue sky. Use clean lines and a vibrant, simplified anime style that matches a minimalist stick figure aesthetic. Design the composition for a portrait mobile game, ensuring the lower half is suitable for character combat.", "description": "Minimalist Konoha village background for Naruto-themed battles", "subtype": "background", "aspect_ratio": [1024, 1536], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "map_naruto_valley": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/map_naruto_valley_63f206af-2476-4bfc-bfe6-48e967a5f828.webp", "type": "image", "prompt": "Generate a 9:16 tall image for a 2D minimalist fighting game background. The scene depicts the 'Valley of the End' from Naruto, featuring two giant, stylized stone statues of ninjas facing each other across a massive central waterfall. The sky is a moody twilight with purple and orange hues. Clean, vibrant, and minimalist art style to match a stick figure game aesthetic. High resolution, professional quality, designed for mobile portrait orientation.", "description": "Minimalist 'Valley of the End' background featuring two giant ninja statues and a waterfall.", "subtype": "background", "aspect_ratio": [1024, 1536], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "obito_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_portrait_5be02e73-fc0a-4a4c-ae97-3f2efa655441.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for a stick figure version of Obito Uchiha. He is wearing his iconic white spiral mask with a single eye hole, through which a glowing red Sharingan eye is visible. He wears a high-collared dark blue cloak. Behind his shoulder, a large Gunbai fan is visible. Clean lines, 2D game-ready asset, professional minimalist style, transparent background, centered composition.", "description": "Minimalist character selection portrait for the stick figure character Obito Uchiha.", "subtype": "ui", "aspect_ratio": [725, 810], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "obito_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_idle_0b5e1855-d416-44b5-a278-b51dc8f1da53.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character 'Obito' in an idle standing pose. He is wearing a white mask with a spiral pattern and one eye hole, a dark blue high-collared robe, and has a large golden-brown Gunbai fan strapped to his back. Side view, right-facing, clean lines, professional game-ready asset, transparent background. Match the minimalist art style of the existing character portraits like image 1.", "description": "Idle standing pose for the Obito stick figure character with his mask and Gunbai fan", "subtype": "character", "aspect_ratio": [384, 941], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "obito_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_walk_ebe24024-b47e-4ac9-9a4c-a658347ecd7b.webp", "type": "image", "prompt": "Generate a walking animation frame for a minimalist 2D stick figure character of Obito Uchiha. He is wearing a white mask with a spiral pattern, a high-collared dark blue cloak, and carries a large golden-brown Gunbai fan on his back. Side view, right-facing, showing a determined and purposeful stride. Match the minimalist art style and character proportions of image 1.", "description": "Walking animation frame for the Obito stick figure character with a white mask and giant fan.", "subtype": "character", "aspect_ratio": [580, 1195], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "obito_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_jump_b900dfd9-6385-48c9-b58b-25dbf4008e29.webp", "type": "image", "prompt": "Generate a dynamic mid-air jumping pose for a minimalist 2D stick figure character of Obito Uchiha. The character should have a white spiral-patterned mask, a flowing dark blue high-collared cloak, and a large golden-brown Gunbai fan on his back. Side view, right-facing, transparent background, clean professional game art style consistent with a fighting game asset.", "description": "Dynamic jumping pose for the Obito stick figure character with a flowing cloak and giant fan.", "subtype": "character", "aspect_ratio": [708, 810], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "obito_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_ability1_5aba3628-0b24-4113-a8c4-45b89c4c2437.webp", "type": "image", "prompt": "Generate a side view, right-facing illustration of the Obito stick figure character performing Fire Style: Bomb Blast Dance. The character, featuring a white spiral mask and dark blue high-collared cloak, is blowing a large, intense swirling vortex of orange and red flames from his mouth. Maintain a minimalist 2D stick figure style consistent with image 1, with clean lines and a transparent background. High resolution, professional game asset.", "description": "Obito stick figure performing a Fire Style: Bomb Blast Dance with swirling flames", "subtype": "character", "aspect_ratio": [760, 887], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "obito_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_ability2_893b530c-23e6-4b2d-9b24-9a7e774b3a34.webp", "type": "image", "prompt": "Generate a side-view 2D minimalist stick figure of Obito Uchiha using his Kamui ability. The character, wearing a white spiral mask and dark blue high-collared cloak, is shown partially swirling into a spatial distortion vortex. Use translucent, warped circular effect lines to indicate the space-time suction. Match the minimalist art style of image 1 and image 2. High resolution, professional game asset, transparent background.", "description": "Obito stick figure using Kamui spatial distortion ability", "subtype": "effect", "aspect_ratio": [954, 814], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "obito_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_ability3_33760d52-a098-45e7-9d2b-9b0ff55f9658.webp", "type": "image", "prompt": "Generate a side-view, right-facing minimalist 2D stick figure character of Obito Uchiha swinging a giant golden-brown Gunbai fan forward in a powerful melee strike pose. Include sharp white wind effect lines to indicate motion. The character wears a white spiral mask and a high-collared dark blue cloak. Match the art style of image 1 and image 2. High resolution, professional game asset, transparent background.", "description": "Obito stick figure swinging the giant Gunbai fan for a powerful melee strike.", "subtype": "character", "aspect_ratio": [940, 867], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "obito_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_ability4_ed42efdd-9352-4ed6-ba43-abd9a13ac5d7.webp", "type": "image", "prompt": "Generate a professional 2D game asset of a minimalist stick figure character named Obito performing an ultimate ability. Obito is in the foreground with arms outstretched, wearing a white spiral mask and a dark blue high-collared cloak. Rising behind him is a massive, dark, ethereal silhouette of the Gedo Mazo (Demonic Statue of the Outer Path) with multiple closed eyes and a jagged stone texture. Minimalist stick figure art style, side-view, clean lines, high resolution, transparent background.", "description": "Obito stick figure performing his ultimate ability summoning the Gedo Mazo statue.", "subtype": "effect", "aspect_ratio": [733, 1237], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "obito_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_hit_f7d71329-381d-47f1-a8ec-a8969d330dbb.webp", "type": "image", "prompt": "Generate a side view of a minimalist 2D stick figure character named Obito in a hit/damage recoil pose. The character has a white spiral mask, a dark blue high-collared cloak, and a giant golden-brown Gunbai fan on his back. The pose should show him being knocked back with his head tilted and limbs reacting to an impact. Match the minimalist art style of existing character assets like `obito_idle` and `obito_walk`. Transparent background.", "description": "Obito stick figure in a hit/damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [769, 1033], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "obito_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_victory_44b6505d-58b1-48d7-81c4-d5363cccaaeb.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Obito Uchiha in a victory pose. He is standing triumphantly, holding his large golden-brown Gunbai fan in one hand. He wears a white spiral-pattern mask and a flowing dark blue high-collared cloak. Professional game-ready illustration, side-view for a fighting game, transparent background, high resolution.", "description": "Victory pose for Obito stick figure character holding his Gunbai fan", "subtype": "character", "aspect_ratio": [598, 1003], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_obito": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_obito_d636c97c-4c87-463c-ac88-c75306e98ee0.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a fire ability, featuring a stylized swirling flame vortex symbol. Use vibrant orange and red colors. Clean vector style, flat design, high resolution, professional quality, transparent background, suitable for a 2D fighting game HUD.", "description": "Minimalist UI icon for Obito's Fire Style ability featuring a swirling flame vortex", "subtype": "ui", "aspect_ratio": [707, 901], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_obito": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_obito_cf760b89-ba71-4492-9bf0-42798f32ac0c.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Kamui' ability, featuring a clean vector spatial spiral vortex symbol. Use a color palette of deep purple and black. The design should be centered, professional quality, and match a 2D fighting game aesthetic. Transparent background.", "description": "A minimalist UI icon for Obito's Kamui spatial distortion ability", "subtype": "ui", "aspect_ratio": [864, 863], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_obito": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_obito_895e1510-0466-4d73-b82b-bc2fef58f3da.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a Gunbai Uchiha fan, featuring a clean silhouette of a giant uchiwa fan with two circles on its surface. Use a color palette of gold and brown. Flat vector style, game-ready UI element, professional quality, high resolution, transparent background.", "description": "A minimalist UI icon for Obito's Gunbai Fan ability showing a silhouette of the fan.", "subtype": "ui", "aspect_ratio": [824, 911], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_obito": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_obito_03e8e747-8555-499b-a7f0-2765027bf87a.webp", "type": "image", "prompt": "A minimalist, clean vector UI icon for a Gedo Mazo ultimate ability, featuring the silhouette of a multi-eyed demonic statue face. The design should use a dark purple and black color palette, professional game asset quality, transparent background, centered composition.", "description": "Minimalist UI icon for Obito's Gedo Mazo ultimate ability", "subtype": "ui", "aspect_ratio": [638, 772], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "obito_ult_image": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_ult_image_b719913b-66e5-489d-8e3f-3d4aff04616f.webp", "type": "image", "prompt": "Remove the background, ground, rocks, and clouds from image 1. Extract and isolate only the central Gedo Mazo statue, which is a giant wooden humanoid figure with multiple eyes and protrusions on its back. Ensure the base of the statue is flat and clean for placement on game terrain. Maintain the original art style but provide it on a transparent background.", "description": "The Gedo Mazo (Ngo\u1ea1i \u0110\u1ea1o Ma T\u01b0\u1ee3ng) statue isolated for Obito's ultimate ability.", "subtype": "effect", "aspect_ratio": [683, 621], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "obito_god_tree": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/obito_god_tree_3064cb75-0a2e-482d-af81-5c683d64312c.webp", "type": "image", "prompt": "Remove the background, smoke, and sky from the image, leaving only the Ten-Tails (Th\u1ea7n Th\u1ee5) creature. The creature is a large, spiky, beige monster with a single massive Rinne-Sharingan eye at the center of its head. Ensure the output is the isolated creature on a clean transparent background, maintaining the minimalist stick-figure game aesthetic of image 1.", "description": "The Ten-Tails (Th\u1ea7n Th\u1ee5) creature on a transparent background for Obito's ultimate ability.", "subtype": "object", "aspect_ratio": [1177, 660], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "obito_fire_ring": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1783147416752_01KWNXWK5GJTGBQ2VK9N79XA0D.istockphoto-2148076081-612x612.jpg", "type": "image", "prompt": null, "description": "A fiery ring explosion effect for Obito's Tailed Beast Bomb.", "subtype": null, "aspect_ratio": [612, 433], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "po_dragon_skin": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1783150850331_01KWP15C8VC44Z0SCD5W9Y5N3H.(anhpng.com) r\u1ed3ng  (2).webp", "type": "image", "prompt": null, "description": "A golden dragon image for Po Panda's ultimate ability.", "subtype": null, "aspect_ratio": [400, 760], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "madara_susanoo_perfect": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/madara_susanoo_perfect_8d18b381-5835-48c8-9a07-9e3a7b5db3cc.webp", "type": "image", "prompt": "Extract and isolate the blue ethereal Perfect Susanoo from image 1. Keep only the giant winged samurai figure with its swords. Remove all environmental elements including mountains, rocks, soil, and the background sky. The final asset should be a high-resolution, detailed blue energy avatar on a transparent background, matching the minimalist stick figure fighting game aesthetic.", "description": "Madara's Perfect Susanoo blue ethereal samurai figure isolated on a transparent background", "subtype": "effect", "aspect_ratio": [536, 982], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gojo_infinite_void": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1783224125809_01KWR71JBHREZV9TGTR8ZP8HF7.woulf-professor-paradox-be-immune-to-gojos-infinite-void-v0-hlq9b8meylkc1.jpg", "type": "image", "prompt": null, "description": "Gojo Satoru's Infinite Void domain expansion background image.", "subtype": null, "aspect_ratio": [1280, 720], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "goku_ssj2": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1783314468327_01KWTX6KF7WR4APFEBNG896P5X.Screenshot_2026_0706_120629.jpg", "type": "image", "prompt": null, "description": "Goku SSJ2 stick figure character sprite with spiky golden hair and blue lightning sparks.", "subtype": null, "aspect_ratio": [481, 1069], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "goku_hair_ssj": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/goku_hair_ssj_7bb736ee-8f19-4cd0-9b98-9bd42545b94d.webp", "type": "image", "prompt": "Extract and isolate the golden spiky hair of Goku Super Saiyan from the image. Remove the background completely to make it transparent. Ensure the hair silhouette is sharp, clean, and centered, maintaining the iconic jagged spike shapes and vibrant yellow-gold color with highlights.", "description": "A clean cutout of Goku's golden spiky Super Saiyan hair for character customization.", "subtype": "other", "aspect_ratio": [769, 800], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_portrait_cbea9292-9826-47f9-8773-bc56869834b2.webp", "type": "image", "prompt": "Professional fighting game character selection portrait of Hashirama Senju. Stylized minimalist 2D stick figure character, long straight black hair, wearing iconic red samurai-style segmented armor plates over a dark suit. Front-facing, head and shoulders framing, clean and polished game-ready asset, transparent background, high resolution.", "description": "Minimalist character selection portrait for Hashirama Senju in a stick figure style.", "subtype": "ui", "aspect_ratio": [886, 992], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_idle_15d8e6e8-d9ca-4ba1-80c6-4e5e4c77bdb4.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Hashirama Senju in an idle standing pose. He has long straight black hair and wears red samurai-style armor plates over a dark suit. Professional fighting game character sprite, side view, right-facing, clean lines, simple colors, high resolution, transparent background.", "description": "Idle standing pose for the Hashirama Senju stick figure character in red armor.", "subtype": "character", "aspect_ratio": [256, 996], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_walk_9441411d-60af-437c-82fb-1e2ab16e1a0f.webp", "type": "image", "prompt": "Generate a walking animation frame for a Hashirama Senju stick figure. The character has long black hair and wears red samurai-style armor plates over a black suit. Minimalist 2D side-view fighting game sprite, right-facing, clean lines, professional game-ready asset, transparent background.", "description": "Walking animation frame for the Hashirama Senju stick figure character in red armor.", "subtype": "character", "aspect_ratio": [502, 1004], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_jump_fe915aeb-bb12-4078-ae15-c2729e9b13d9.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Hashirama Senju in a high jumping pose. The character has long black hair flowing upwards and wears red samurai-style armor plates over a black suit. Side view, right-facing, clean lines, professional fighting game sprite style, transparent background.", "description": "Jumping pose for the Hashirama Senju stick figure character in red samurai armor", "subtype": "character", "aspect_ratio": [601, 742], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_ability1_0923285c-7bd1-4c3c-869c-a0eff0460b97.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Hashirama Senju performing a Wood Style jutsu. The character has long black hair and red samurai-style armor plates, standing in a side-view combat pose with hands pressed together in a ninja hand sign. High-quality game asset style, clean lines, transparent background. Match the visual style of hashirama_idle.", "description": "Hashirama Senju stick figure performing a Wood Style jutsu with hand signs.", "subtype": "character", "aspect_ratio": [766, 1217], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_ability2_98b85fde-f878-4f4c-8102-82337b37d89c.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Hashirama Senju performing a powerful wood-style slam attack. He has long black hair and wears red samurai-style armor plates. The character is in a dynamic lunging or summoning pose with hands touching the ground, accompanied by stylized wooden roots or pillars emerging. Side view, right-facing, clean lines, professional fighting game asset style. Transparent background.", "description": "Hashirama Senju stick figure performing a wood-based slam attack pose", "subtype": "character", "aspect_ratio": [970, 842], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_ability3_f344711f-0bde-4221-8784-f6274edc56ab.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character illustration of Hashirama Senju in a calm meditative pose. He has long black hair and wears red samurai-style armor plates. A faint, glowing green life-energy aura surrounds him. Side view, high-quality game asset, transparent background.", "description": "Hashirama stick figure in a meditative pose for his ultimate Thousand-Hand Bodhisattva ability", "subtype": "character", "aspect_ratio": [554, 764], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "hashirama_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_hit_d9fa4726-e114-43c1-9b1f-68b8cf2750b6.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Hashirama Senju in a hit/damage recoil pose. The character should have long black hair and be wearing red samurai-style armor plates over a black suit. Side view, right-facing, showing impact reaction. Clean, professional game asset style with a transparent background.", "description": "Hashirama Senju stick figure in a hit/damage recoil pose for combat feedback.", "subtype": "character", "aspect_ratio": [620, 1014], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_victory_ffdcb974-96ff-49d9-8ff8-1f7a554cb248.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character illustration of Hashirama Senju in a victory pose, laughing heartily with eyes closed and mouth open. The character should have long straight black hair and wear red samurai-style plate armor over a black suit. Side-view perspective, professional game art style, clean lines, transparent background.", "description": "Victory pose for Hashirama Senju stick figure character laughing heartily.", "subtype": "character", "aspect_ratio": [454, 1150], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_hashirama": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_hashirama_73f5bf46-5d8a-448e-9a0c-ec8295986534.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Wood Dragon' ability. The icon should feature a stylized green dragon silhouette with bark-like textures and wooden branch aesthetics. Use a clean, professional game UI style with high contrast and a simple background, matching the minimalist fighting game aesthetic.", "description": "Minimalist UI icon for Hashirama's Wood Dragon ability", "subtype": "ui", "aspect_ratio": [803, 792], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_hashirama": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_hashirama_b33656ae-0690-45c7-aac2-ae8ed68327b3.webp", "type": "image", "prompt": "A minimalist UI game icon for a 'Wood Hand' ability. The icon features a stylized silhouette of a giant hand made of wood and bark emerging from the ground. Use a green and brown color palette consistent with Hashirama's wood style. Clean vector-like design, flat colors, professional quality, transparent background.", "description": "Minimalist UI icon for Hashirama's Wood Hand ability showing a wooden hand rising from the ground.", "subtype": "ui", "aspect_ratio": [580, 910], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_hashirama": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_hashirama_78c767a7-5600-442f-8e16-33b920993539.webp", "type": "image", "prompt": "A minimalist UI icon for a 'Thousand-Hand Bodhisattva' ultimate ability, featuring a clean silhouette of a multi-armed Buddhist statue. Professional game UI style, flat design, centered composition, high contrast, suitable for a fighting game interface, transparent background.", "description": "Minimalist UI icon for Hashirama's Thousand-Hand Bodhisattva ultimate ability.", "subtype": "ui", "aspect_ratio": [759, 749], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "wood_dragon_projectile": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wood_dragon_projectile_21886beb-6bfb-49fe-8580-1200aeccad13.webp", "type": "image", "prompt": "Generate a minimalist 2D game asset of a long, winding dragon made of textured wood and tree bark with glowing green eyes. Side view, facing right, designed for a horizontal projectile in a fighting game. Clean lines, stylized wooden texture, professional quality, transparent background.", "description": "A wooden dragon projectile for Hashirama's Wood Style ability", "subtype": "effect", "aspect_ratio": [971, 275], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_ult_statue": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_ult_statue_b12776d7-1723-4219-9760-fcedfae3dc7a.webp", "type": "image", "prompt": "Extract and isolate the golden Thousand-Hand Bodhisattva statue from image 1. Remove all background elements to make it a clean, standalone game asset. Ensure the many arms and intricate golden details are preserved against a transparent background. High resolution, minimalist stick-figure game style consistent with Hashirama's character.", "description": "The golden Thousand-Hand Bodhisattva statue for Hashirama's ultimate ability, isolated on a transparent background.", "subtype": "effect", "aspect_ratio": [942, 478], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "hashirama_ult_fists": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_ult_fists_f2689786-dbbf-4f57-8d4f-55f523315132.webp", "type": "image", "prompt": "Remove the background and everything except the golden wooden fists from image. The final image should have only the multiple golden wooden fists on a transparent background. Maintain the minimalist stick figure game art style, keeping all fists visible and highly detailed as a single combined asset.", "description": "Golden wooden fists from Hashirama's Thousand-Hand Bodhisattva ultimate ability, isolated on a transparent background.", "subtype": "effect", "aspect_ratio": [1244, 495], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "hashirama_tree_effect": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_tree_effect_e94abf91-442d-4f3f-94f4-734b7897b9c9.webp", "type": "image", "prompt": "Extract and isolate the large wooden tree trunk and the blooming pink flowers from the image. Remove all background elements, characters, and UI components. Ensure the final result is a clean game asset with a transparent background, maintaining the minimalist stick-figure game aesthetic of the existing environment.", "description": "A large wooden tree trunk with pink flowers for Hashirama's ultimate ability, isolated on a transparent background.", "subtype": "effect", "aspect_ratio": [1344, 549], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "hashirama_pillar_fist": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/hashirama_pillar_fist_67b59a1f-af3f-4cea-bc9b-ff4e74d21776.webp", "type": "image", "prompt": "Generate a 2D hand-drawn anime effect asset of a long, vertical wooden arm ending in a massive clenched fist extending downwards. The arm texture should resemble a giant weathered tree trunk with mossy greens and stone-like textures. Use a color palette of earthy browns and dull golden highlights. The fist is large and powerful. Style must match the minimalist stick figure game aesthetic while referencing the Thousand-Hand Bodhisattva from Naruto. High contrast, clean outlines, vertical orientation, transparent background.", "description": "A long vertical wooden pillar arm ending in a massive fist, designed as a falling projectile.", "subtype": "effect", "aspect_ratio": [692, 1231], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "zoro_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_portrait_fc1da9d6-91a6-4988-9fcd-97f15e747873.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for a stick figure version of Zoro from One Piece. Features include short green spiky hair, a black bandana tied around his left arm, and his signature scar over his left eye. He is seen from the chest up with a green background tint. Professional 2D minimalist game art style, clean lines, centered composition, high resolution. Match the art style, character proportions, and flat-shading of luffy_portrait and sasuke_portrait.", "description": "Minimalist character selection portrait for the Zoro stick figure character with green hair and three swords.", "subtype": "ui", "aspect_ratio": [1024, 1024], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_idle_bf47fcae-472e-487f-aabb-dddb80db3111.webp", "type": "image", "prompt": "Generate a full-body side view standing illustration of a minimalist stick figure character named Zoro in an idle stance, facing right. The character has short green hair and is holding three katanas: one held in his mouth and one in each hand. He wears a dark green robe and a green haramaki waistband. Clean 2D vector art style, minimalist stick figure aesthetic, professional game-ready asset, transparent background. Match the minimalist proportions and style of image 1 and image 2.", "description": "Idle standing pose for the Zoro stick figure character using Three Sword Style", "subtype": "character", "aspect_ratio": [627, 1241], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_walk_509803fd-6cfd-43ec-ba38-062cb126c9ae.webp", "type": "image", "prompt": "Generate a full-body side view walking animation frame for the Zoro stick figure character, facing right. He has short green hair and is carrying three swords: one in his mouth and one in each hand. He is captured mid-stride with a determined swordsman's walk. Minimalist 2D vector-art style, clean lines, professional game-ready asset, transparent background, matching the style and proportions of zoro_idle.", "description": "Walking animation frame for the Zoro stick figure character in Three Sword Style", "subtype": "character", "aspect_ratio": [627, 1159], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_jump_615e3585-eef0-4554-887c-2a364284ee8a.webp", "type": "image", "prompt": "Generate a full-body, side-view minimalist stick figure illustration of Zoro in a high jumping pose, facing right. The character is a lean black stick figure with short spiky green hair, holding three katanas: one in his mouth and one in each hand. Clean 2D vector art style, polished lines, professional game-ready asset, transparent background. Maintain visual consistency with the style and proportions of zoro_idle and luffy_idle.", "description": "High jumping pose for the Zoro stick figure character with green hair and three swords.", "subtype": "character", "aspect_ratio": [593, 940], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_ability1_efe89e79-02ac-4070-84b8-954f30e013a0.webp", "type": "image", "prompt": "Generate a full-body side view of a minimalist stick figure character named Zoro performing a powerful 'Onigiri' slash attack. The character is lunging forward to the right with three swords crossed (one in mouth, two in hands), accompanied by sharp, stylized white slash trail effects. Maintain a clean, professional 2D vector art style with minimalist lines, consistent with the style of luffy_idle and zoro_idle. High resolution, transparent background.", "description": "Zoro stick figure performing the 'Onigiri' three-sword slash attack", "subtype": "character", "aspect_ratio": [776, 1070], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "zoro_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_ability2_629aadcb-d60d-444f-a5ec-c987bd7f8837.webp", "type": "image", "prompt": "Generate a full-body side-view illustration of a minimalist stick figure character named Zoro performing the 'Sanjuuroku Pond Phoenix' attack. He is swinging his three swords to launch a powerful, vibrant green flying slash projectile. The character has short green hair and wears a dark green robe. Side view, right-facing. Clean lines, minimalist 2D vector art style, professional game-ready asset, transparent background, matching the style and proportions of zoro_idle and luffy_idle.", "description": "Zoro stick figure performing a green flying slash projectile attack", "subtype": "character", "aspect_ratio": [775, 988], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "zoro_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_ability3_fc1c5d2e-4fc6-4d4d-b097-8754573888b3.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of Zoro performing 'Tatsu Maki' (Dragon Twister). He is spinning rapidly with his three swords, creating a localized green energy whirlwind around him. Side view, right-facing. Maintain a clean, polished, 2D vector art style with clean lines. Professional game-ready asset, transparent background, matching the style and character design of zoro_idle and luffy_idle.", "description": "Zoro stick figure performing the Tatsu Maki whirlwind attack with his three swords", "subtype": "effect", "aspect_ratio": [832, 843], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_ability4_2476b541-fb23-4204-8e4a-3db1f028965b.webp", "type": "image", "prompt": "Generate a minimalist stick figure illustration of the character Zoro in his 'Ashura' form. The character features a unique silhouette appearing to have three heads and six arms, each hand holding a katana sword. The figure is surrounded by a swirling dark purple and green demonic aura. Full body, front-side view, standing powerful pose. Minimalist 2D vector art style, clean lines, professional game-ready asset, transparent background, matching the style and proportions of zoro_idle and luffy_idle.", "description": "Zoro in his legendary Ashura form with multiple arms and heads for his ultimate ability", "subtype": "character", "aspect_ratio": [740, 1068], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_hit_b4c210ac-c58b-4d9f-a61c-e9176edc0b72.webp", "type": "image", "prompt": "Generate a side-view minimalist 2D stick figure illustration of Zoro in a hit or damage recoil pose, reeling back from an impact. The character has short green hair and is wearing a dark green robe. Clean lines, polished, professional game-ready asset, high resolution, transparent background, matching the style and proportions of zoro_idle.", "description": "Zoro stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [686, 1052], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "zoro_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_victory_07c9fe33-95cf-4a6d-927e-104875a5642f.webp", "type": "image", "prompt": "Generate a full-body, right-facing victory pose for a minimalist Zoro stick figure character. The character is standing with his swords sheathed at his hip, looking coolly over his shoulder towards the viewer. He has short green hair and a visible eye scar. Clean 2D vector-like lines, professional game-ready asset, high resolution, transparent background. Match the minimalist art style and proportions of zoro_idle and luffy_victory.", "description": "Victory pose for the Zoro stick figure character looking over his shoulder", "subtype": "character", "aspect_ratio": [620, 1235], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_zoro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_zoro_f96837db-a8b6-4f09-85bf-7575b053e394.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Zoro's 'Onigiri' ability. The design features three crossed sword silhouettes in a clean vector style. High contrast, dark green background, professional game UI quality, square aspect ratio, centered composition.", "description": "A minimalist UI icon for Zoro's 'Onigiri' ability featuring crossed sword silhouettes.", "subtype": "ui", "aspect_ratio": [836, 833], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_zoro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_zoro_1e75b03b-3731-43ca-ba89-fc3b13de9ff4.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Phoenix Slash' ability. The icon features a sharp, curved green energy blade or slash silhouette in a clean vector style. High contrast, professional game UI quality, dark background to make the green energy pop, matching the aesthetic of existing ability icons.", "description": "A minimalist UI icon for Zoro's Phoenix Slash ability showing a curved green energy blade.", "subtype": "ui", "aspect_ratio": [1023, 1020], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_zoro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_zoro_91e1266d-2ccd-4b04-a679-59319cf86bca.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Zoro's 'Dragon Twister' ability. Featuring a stylized green whirlwind or tornado symbol. Clean vector style, high contrast, professional game UI quality, solid dark background, centered composition.", "description": "A minimalist UI icon for Zoro's Dragon Twister ability featuring a green whirlwind symbol.", "subtype": "ui", "aspect_ratio": [615, 648], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_zoro": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_zoro_e78ac84e-977a-43b3-8cc7-d8128b07f564.webp", "type": "image", "prompt": "Generate a minimalist UI icon for Zoro's 'Ashura' ultimate ability. The icon features a stylized silhouette of a three-headed demon holding many swords. Use a dark purple and green color palette with high contrast. Clean vector style, professional game UI quality, centered composition, transparent background.", "description": "Minimalist UI icon for Zoro's Ashura ultimate ability featuring a three-headed demon silhouette.", "subtype": "ui", "aspect_ratio": [713, 1025], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "sword_slash_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/sword_slash_sfx_c456832d-cd90-444c-90ea-dece8d015461.mp3", "type": "audio", "prompt": "Sharp, high-definition metallic sword slash sound effect. Features a clean 'shing' resonant metallic ring followed by a rapid, crisp air displacement 'whoosh'. High-quality, professional game audio with a snappy attack and a brief, natural tail. Suitable for a fast-paced action game, similar in clarity to high-tier anime combat sound design.", "description": "Sharp, metallic sword slash sound effect for melee combat.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.33, "loop": false, "animation": null}, "zoro_ashura_bg": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1783404043954_01KWXJM7NJ6D3VHF6A7V98D8BA.Screenshot_2026_0707_125907.jpg", "type": "image", "prompt": null, "description": "The Ashura spirit image for Zoro's ultimate ability, featuring multiple heads and arms in a purple/violet style.", "subtype": null, "aspect_ratio": [481, 447], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "main_menu_bg": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1783405992787_01KWXMFPTKMHHM9971QV5VJBY9.Screenshot_2026_0707_132349.jpg", "type": "image", "prompt": null, "description": "Main menu background featuring Saitama, Hashirama, and Zoro in a split-screen action style.", "subtype": null, "aspect_ratio": [481, 317], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "yuta_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_portrait_c2867045-3e0c-4553-a563-73a5ee7242ff.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait for Yuta Okkotsu from Jujutsu Kaisen. Use a clean stick figure style consistent with existing characters. The character should have messy black hair and a white sorcerer high-collar uniform. Dark blue background. High resolution, professional game UI asset.", "description": "Minimalist character selection portrait for Yuta Okkotsu in stick figure style", "subtype": "ui", "aspect_ratio": [1024, 1024], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuta_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_idle_2d1b5a20-8706-4f65-a54e-6158c3f4525d.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Yuta Okkotsu in an idle standing pose. He is wearing a white sorcerer uniform, has messy black hair, and is holding a katana sword. Side view, right-facing. Clean lines, flat colors, professional game-ready asset on a transparent background.", "description": "Idle standing pose for the Yuta Okkotsu stick figure character holding a katana", "subtype": "character", "aspect_ratio": [542, 919], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuta_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_walk_a744c563-4f84-4024-a625-40a6fb19c4cb.webp", "type": "image", "prompt": "Generate a minimalist 2D side view of a Yuta Okkotsu stick figure character in a walking pose. The character has messy black hair, wears a white sorcerer uniform, and carries a katana. Clean lines, flat design, side-scrolling fighting game style, transparent background, high resolution.", "description": "Walking animation frame for the Yuta Okkotsu stick figure character with a katana.", "subtype": "character", "aspect_ratio": [664, 1000], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuta_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_jump_d9635580-65f1-4b05-abcd-b3ce57dd77f9.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Yuta Okkotsu in a high jumping pose, swinging a katana. Side view, right-facing. He wears a white sorcerer uniform and has messy black hair. Clean lines, flat colors, white background for transparency. Professional game-ready asset in the style of existing stick figure fighters.", "description": "Dynamic jumping pose for the Yuta Okkotsu stick figure character swinging a katana.", "subtype": "character", "aspect_ratio": [656, 656], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "yuta_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_ability1_4d5677f1-990a-44db-9496-d949c67eff10.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Yuta Okkotsu performing a powerful sword slash. The character is in a side-view action pose, swinging a katana with vibrant blue cursed energy trails and effects. Stick figure style with a white sorcerer uniform and messy black hair. High resolution, professional game asset, transparent background.", "description": "Yuta Okkotsu performing a sword slash with blue cursed energy", "subtype": "effect", "aspect_ratio": [921, 801], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuta_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_ability2_013033b2-0816-41fe-a29c-daea48a4b0ff.webp", "type": "image", "prompt": "Generate a minimalist 2D side-view stick figure of Yuta Okkotsu from Jujutsu Kaisen. The character is wearing a white sorcerer uniform and has messy black hair. He is holding a small megaphone to his mouth, with stylized circular soundwave effects emitting from it. Match the minimalist art style of the existing game characters like yuta_idle. Transparent background, high resolution, clean lines, professional game asset.", "description": "Yuta Okkotsu stick figure using Cursed Speech with a megaphone and soundwaves", "subtype": "effect", "aspect_ratio": [442, 965], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuta_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_ability3_d3402c13-2026-485f-bcd2-2ba86cef8226.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character of Yuta Okkotsu from Jujutsu Kaisen in a side-view battle pose. He is wearing a white sorcerer uniform and firing a massive, powerful beam of bright blue cursed energy from his hands. High contrast, clean lines, game-ready asset, transparent background, matching the art style of yuta_idle and yuta_ability1.", "description": "Yuta Okkotsu stick figure character firing a massive blue cursed energy beam.", "subtype": "effect", "aspect_ratio": [1005, 649], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "yuta_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_ability4_7b8d0342-f44a-4a9e-a02f-c05b2f3ea07f.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure illustration of Yuta Okkotsu in a white sorcerer uniform, standing in a summoning pose. Behind him, a massive, terrifying cursed spirit named Rika emerges, featuring a white and black color scheme with multiple eyes and a monstrous, ethereal form. Maintain a clean, minimalist 2D fighting game style with a transparent background, side view, right-facing.", "description": "Yuta Okkotsu stick figure summoning the massive cursed spirit Rika behind him for his ultimate ability.", "subtype": "character", "aspect_ratio": [790, 1216], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "yuta_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_hit_978dbb1b-5040-4614-9f71-c49d50013e94.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure of Yuta Okkotsu in a hit and damage recoil pose. The character should have messy black hair and a white sorcerer uniform, showing a pained expression or physical reaction to an impact. Maintain the same minimalist art style and side-view perspective as the existing character sprites. High resolution, transparent background.", "description": "Yuta Okkotsu stick figure in a hit/damage recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [639, 960], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "yuta_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/yuta_victory_a116db9a-8133-41a6-b44d-3af5df9953c8.webp", "type": "image", "prompt": "Generate a minimalist 2D stick figure character illustration of Yuta Okkotsu in a victory pose. The character is sheathing his katana into a scabbard with a calm, serene expression. He wears a white sorcerer uniform and has messy black hair. Side-view, full body picture, standing illustration, clean lines, transparent background. Match the minimalist artistic style of yuta_idle.", "description": "Victory pose for Yuta Okkotsu stick figure character sheathing his katana", "subtype": "character", "aspect_ratio": [677, 1018], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "rika_spirit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rika_spirit_5d40cd95-2a28-46a2-8984-e305a57bebee.webp", "type": "image", "prompt": "Generate a full-body picture of the massive, terrifying cursed spirit Rika Okkotsu from Jujutsu Kaisen. Large white and grey muscular body, multiple unsettling eyes on its head, and sharp teeth. Minimalist 2D stick figure game art style, clean lines, flat colors. Side view, facing right. Transparent background, high resolution, game-ready asset.", "description": "The massive cursed spirit Rika Okkotsu for Yuta's ultimate ability", "subtype": "effect", "aspect_ratio": [787, 1195], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_yuta": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_yuta_7d12bca0-90ea-47f8-a912-6d883bee83a9.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Katana Slash' ability. The icon features a clean black silhouette of a katana sword slanted diagonally, surrounded by stylized glowing blue energy streaks and sparks. Clean vector style, game-ready UI asset, isolated on a transparent background, high contrast, simple and iconic design to match the stick figure game aesthetic.", "description": "Minimalist UI icon for Yuta's Katana Slash ability featuring a sword silhouette and blue energy.", "subtype": "ui", "aspect_ratio": [633, 686], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_yuta": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_yuta_a36cbab5-1411-4ea2-b62e-4066e06b0b02.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a Cursed Speech ability featuring a clean megaphone silhouette with stylized sound waves. Use a bold white graphic on a dark blue background to match the style of existing character portraits. Clean lines, high contrast, professional game UI quality, 2D vector style.", "description": "Minimalist UI icon for Yuta's Cursed Speech ability featuring a megaphone silhouette.", "subtype": "ui", "aspect_ratio": [853, 838], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_yuta": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_yuta_64b0d771-98ee-4795-aeb0-53efeeec6de5.webp", "type": "image", "prompt": "Generate a minimalist UI icon for a 'Cursed Energy Blast' ability. The icon features a stylized, glowing blue energy orb with subtle electrical or wispy cursed energy tendrils, clean flat vector design, solid dark blue background, professional game UI quality.", "description": "Minimalist UI icon for Yuta's Cursed Energy Blast ability featuring a blue energy orb.", "subtype": "ui", "aspect_ratio": [1024, 1024], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_yuta": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_yuta_28cd13df-034a-4d24-b57b-f1d7124ddce1.webp", "type": "image", "prompt": "A minimalist UI icon for a character's ultimate ability, featuring a stylized silhouette of a terrifying cursed spirit with multiple eyes and sharp features, inspired by Rika from Jujutsu Kaisen. The icon should use a dark blue and white color palette to match the game's UI style, presented as a clean vector-style graphic on a transparent background.", "description": "Minimalist UI icon for Yuta's Rika Summon ultimate ability featuring a silhouette of Rika.", "subtype": "ui", "aspect_ratio": [840, 847], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "rika_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/rika_sfx_5a3747a1-4a15-4582-b39a-b28760225428.mp3", "type": "audio", "prompt": "A bone-chilling, monstrous roar from a powerful cursed spirit, starting with a guttural, multi-layered screech and transitioning into a deep, vibrating energy surge. The sound should feature heavy sub-bass resonance, supernatural distortion, and a sense of immense spiritual pressure. Cinematic quality, dark and aggressive, with a lingering ethereal echo. No background music, clean isolated sound effect.", "description": "A terrifying monstrous roar and deep energy surge for a cursed spirit summon.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3.47, "loop": false, "animation": null}, "rika_v2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rika_v2_8af04ef4-72e4-4df8-8518-9f273a09d3af.webp", "type": "image", "prompt": "Generate a 2D pixel art game asset of Rika Okkotsu, the Queen of Curses. Features a white skeletal torso with a prominent ribcage, a long flexible neck, and a terrifying head with rows of sharp human-like teeth and no eyes. Long spindly white arms with sharp claws, with one arm reaching forward. The lower body is a dark, shadowy purple-black tail or cloud-like base. Side view, right-facing, transparent background. High resolution pixel art style matching the aesthetic of image 1.", "description": "A 2D pixel art representation of the cursed spirit Rika Okkotsu for Yuta's ultimate ability.", "subtype": "effect", "aspect_ratio": [1133, 773], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_portrait_49eed0e0-d8bf-4b49-85d0-3ff06072e301.webp", "type": "image", "prompt": "Modify the minimalist stick figure selection portrait of Zoro in his Wano outfit. Add green scalloped seigaiha (wave) patterns to the lower portions of his white kimono and across his green cloak, matching the exact pattern style from image 01KY90F634KG24RKWEZYK1FSWR. Maintain the clean, minimalist 2D style with a focused head-and-shoulders composition and transparent background.", "description": "Updated character selection portrait for Zoro in Wano outfit featuring traditional green wave patterns.", "subtype": "ui", "aspect_ratio": [1024, 1015], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_idle_05527520-081f-4c45-864e-529ef1b2b631.webp", "type": "image", "prompt": "Modify the minimalist stick figure character in image 1. Add green scalloped wave patterns (seigaiha pattern) to the lower portions of the white kimono and across the green cloak, matching the specific decorative style in image 2. The character should be in an idle standing pose with three swords, maintaining the clean, minimalist 2D game asset style on a transparent background.", "description": "Idle pose for the Zoro stick figure character in Wano outfit with detailed seigaiha wave patterns.", "subtype": "character", "aspect_ratio": [584, 1204], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_walk_6851a392-9eb5-422f-8aa7-4493b1b2bc7f.webp", "type": "image", "prompt": "Modify the minimalist stick figure character in image 1. Add green scalloped seigaiha wave patterns to the bottom of the white kimono and across the green cloak, matching the traditional pattern style seen in image 2. Maintain the side-view walking pose, three-sword style, and clean minimalist aesthetic with a transparent background.", "description": "Walking animation frame for Zoro in Wano outfit with traditional green wave patterns.", "subtype": "character", "aspect_ratio": [625, 1199], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_jump_b6350d67-d968-4067-ad35-30b26c586698.webp", "type": "image", "prompt": "Transform the stick figure character from image 1 by adding green scalloped seigaiha wave patterns to the bottom of the white kimono and across the green cloak. Match the specific pattern style and color from image 2. Maintain the minimalist stick figure style, side view, high jumping pose with three swords. Transparent background, high resolution, clean lines.", "description": "Zoro in Wano outfit jumping pose with green wave patterns on his kimono and cloak", "subtype": "character", "aspect_ratio": [657, 1242], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_ability1_e4b8fca6-7227-4a48-a296-2c4fdcb4ef74.webp", "type": "image", "prompt": "Modify the minimalist stick figure Zoro in Wano outfit to include green seigaiha (scalloped wave) patterns on the lower portions of his white kimono and across his green cloak, matching the pattern style from image 01KY90F634KG24RKWEZYK1FSWR. The character is in a dynamic sword-slashing attack pose using three swords. Maintain the clean, 2D minimalist stick figure style with a transparent background.", "description": "Zoro in Wano outfit performing a slash attack with detailed seigaiha patterns on his kimono and cloak.", "subtype": "character", "aspect_ratio": [728, 606], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_ability2_331f3a38-6865-4e53-ad0c-7c09920ebb2d.webp", "type": "image", "prompt": "Modify the minimalist stick figure character from zoro_wano_ability2. Add green seigaiha (scalloped wave) patterns to the lower portions of the white kimono and across the green cloak, matching the pattern style in image 01KY90F634KG24RKWEZYK1FSWR. Maintain the minimalist 2D stick figure aesthetic, side view, right-facing, performing a sword slash attack with three katanas. Transparent background.", "description": "Zoro in Wano outfit performing a projectile slash attack with traditional seigaiha patterns on his kimono and cloak.", "subtype": "character", "aspect_ratio": [672, 702], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_ability3_9d12d520-8112-4790-a406-0424a3436d69.webp", "type": "image", "prompt": "Modify the minimalist stick figure character from zoro_wano_ability3. Add traditional green seigaiha (scalloped wave) patterns to the lower portions of the white kimono and across the green cloak, matching the decorative style in image 01KY90F634KG24RKWEZYK1FSWR. Maintain the 2D minimalist stick figure aesthetic, side view, right-facing, three-sword style whirlwind pose with transparent background.", "description": "Zoro in Wano outfit performing a whirlwind attack with traditional seigaiha patterns on his clothing.", "subtype": "character", "aspect_ratio": [639, 1244], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_ability4_78c85aa7-f8e2-426e-9033-5196c05d8127.webp", "type": "image", "prompt": "Transform the stick figure character in image 1 by adding green 'seigaiha' scalloped wave patterns to the lower part of the white kimono and across the green cloak, matching the pattern style in image 2. The character is a minimalist stick figure in an Ashura ultimate attack pose with multiple arms and heads, holding three katanas. Maintain the clean, 2D minimalist game asset style with a transparent background.", "description": "Zoro in Wano outfit performing his Ashura ultimate ability with green scalloped wave patterns on his kimono and cloak.", "subtype": "character", "aspect_ratio": [672, 1091], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_hit_7e19bc1a-4f00-4423-9e15-20e9ea122c2f.webp", "type": "image", "prompt": "Modify the minimalist stick figure character in a hit recoil pose by adding green seigaiha (scalloped wave) patterns to the lower portions of the white kimono and across the green cloak. Match the specific pattern style from image 1. Keep the character design consistent with the existing minimalist style, side view, on a transparent background.", "description": "Zoro in Wano outfit in a damage recoil pose, updated with traditional green seigaiha patterns on his robes.", "subtype": "character", "aspect_ratio": [715, 1248], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "zoro_wano_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/zoro_wano_victory_01ee172a-a2ae-4713-b36e-cb8c758c4186.webp", "type": "image", "prompt": "Modify the minimalist stick figure character in image 1. Add green scalloped wave patterns (seigaiha pattern) to the lower portions of the white kimono and across the green cloak, matching the pattern style from image 2. Maintain the minimalist stick figure style, clean lines, and transparent background. Zoro is looking over his shoulder confidently with his swords.", "description": "Victory pose for Zoro in Wano outfit with traditional green seigaiha patterns on his kimono and cloak.", "subtype": "character", "aspect_ratio": [567, 1247], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "naruto_luc_dao_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_luc_dao_portrait_79ee00cc-7cd7-4ece-8486-6d31e1f44ca3.webp", "type": "image", "prompt": "Generate a minimalist 2D character selection portrait of the stick figure character in image 1. The character is in 'Six Paths Sage Mode' (Luc Dao), glowing with a vibrant yellow and orange chakra aura. Include black Truth-Seeker Orbs (Gudodama) floating in the background behind him. Maintain the lean stick figure anatomy, iconic orange-yellow color palette, and clean minimalist aesthetic of the existing game characters. Transparent background, high resolution, professional game UI quality.", "description": "Character selection portrait for Naruto in Six Paths Sage Mode (Luc Dao)", "subtype": "ui", "aspect_ratio": [497, 790], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_luc_dao_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_luc_dao_ability4_99f6cfb4-db8c-4bb1-b70a-a85776d0cb41.webp", "type": "image", "prompt": "Generate a 2D minimalist stick figure sprite of Naruto in Six Paths Sage Mode (Luc Dao). The character is a glowing vibrant yellow and orange stick figure wearing a high-collar chakra cloak. Behind his back, several black Truth-Seeker Orbs are floating in a perfect circular formation. The character is in a dynamic combat-ready pose, side view, right-facing. Style must match the stick figure aesthetic of image 1. Transparent background, high resolution, game-ready asset.", "description": "A 2D stick figure sprite of Naruto in Six Paths Sage Mode with Truth-Seeker Orbs.", "subtype": "character", "aspect_ratio": [528, 678], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "naruto_kurama_asura": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/naruto_kurama_asura_0c72bcd4-4825-4f86-ac3e-890597f48d4e.webp", "type": "image", "prompt": "Generate a large, majestic 2D chakra avatar of Kurama in Asura form, featuring three fox heads and six powerful arms. The style is clean, minimalist, and game-ready to match a stick-figure aesthetic. The entity is a glowing, semi-transparent pale-gold and yellow energy form with glowing orange chakra lines defining its silhouette. High-quality spectral energy effect, divine and powerful appearance, full body illustration, transparent background.", "description": "Large three-headed, six-armed Kurama Asura chakra avatar for Naruto's ultimate form.", "subtype": "effect", "aspect_ratio": [873, 599], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "luffy_nika_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_nika_portrait_56ebc334-860c-4a89-bfb8-c778057469b1.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait of Luffy in Gear 5 Nika form. Design it as a clean, 2D stick figure style portrait with white spiky hair, a joyful laughing expression, and white ethereal smoke or clouds swirling around the neck. Use a simple, clean background consistent with a character select screen. Maintain the artistic style of image 1 and image 2.", "description": "Minimalist character selection portrait for Luffy in his Gear 5 Nika form.", "subtype": "ui", "aspect_ratio": [603, 1007], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "luffy_gear2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_gear2_c0c4f8ff-cd3e-4f69-a261-859422e418c4.webp", "type": "image", "prompt": "Generate a full-body, side-view 2D minimalist stick figure sprite of Luffy in Gear 2. The character has a light pinkish skin tint, wearing a red vest and straw hat. Intense white steam and vapor clouds are emitting from the body. The pose is a dynamic classic Gear 2 crouching stance with one fist on the ground. Polished game-ready asset, transparent background, high resolution, matching the style of luffy_idle.", "description": "Luffy in Gear 2 state with pinkish skin and steam effects in a dynamic combat stance.", "subtype": "character", "aspect_ratio": [736, 760], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_gear4_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_gear4_portrait_5950fead-b4c6-4945-ad6e-599a7570f1ac.webp", "type": "image", "prompt": "Generate a minimalist character selection portrait of Luffy in Gear 4 Boundman form. He has an extremely bulky upper body and oversized muscular arms coated in dark red and black Haki with distinct spiral patterns. Include white steam clouds swirling around his torso. Maintain a clean stick figure style consistent with image 01KYBJ7SW71TJZ86WW5W7HP7X3, featuring his signature straw hat and a determined expression. High quality, centered composition, transparent background.", "description": "Minimalist character selection portrait for Luffy in his bulky Gear 4 Boundman form.", "subtype": "ui", "aspect_ratio": [672, 592], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "luffy_gear4_sprite": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/luffy_gear4_sprite_af39c7e3-01aa-4353-b5cb-84f0413cdcf7.webp", "type": "image", "prompt": "Generate a 2D stick figure sprite of Luffy in Gear 4 Boundman form based on the proportions of image 01KYBJ7SW71TJZ86WW5W7HP7X3. The character has an extremely muscular, rounded torso and massive arms coated in dark red and black Haki with spiral patterns. He wears a straw hat and is surrounded by swirling white steam clouds around his neck and shoulders. Side-view, right-facing combat stance, clean minimalist lines, high resolution, transparent background.", "description": "A side-view combat sprite of Luffy in Gear 4 Boundman form in a stick figure style.", "subtype": "character", "aspect_ratio": [612, 591], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "lobby_background_v2": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1784950014052_01KYBMZG347ZV06PTV49959N8E.1000000703.jpg", "type": "image", "prompt": null, "description": "New main menu lobby background featuring Sasuke and Naruto clashing fists.", "subtype": null, "aspect_ratio": [1600, 1125], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "lobby_background_v3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/lobby_background_v3_dee16a47-baa3-45a0-9acd-f61c61438b30.webp", "type": "image", "prompt": "Generate a 9:16 tall image for a mobile game lobby background. A high-energy, epic anime battle scene featuring Luffy in Gear 5 Nika form (white hair, laughing, glowing white aura) clashing against Naruto in Six Paths Sage Mode (golden chakra, glowing yellow eyes, and Truth-Seeker Orbs). Cinematic composition with vibrant lighting, intense energy sparks, and detailed anime poster art style. High resolution, professional quality, suitable for a 2D fighting game main menu.", "description": "High-energy anime battle lobby background featuring Gear 5 Luffy and Six Paths Naruto", "subtype": "background", "aspect_ratio": [832, 1248], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "map_cosmic_space": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1784977249392_01KYCEYN3GVPH7H3AYBGHP5FAF.1000000707.webp", "type": "image", "prompt": null, "description": "A cosmic space background with planets and nebulae for the level progression map.", "subtype": null, "aspect_ratio": [700, 467], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "ability1_icon_rimuru": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability1_icon_rimuru_c7920552-afb8-43bd-b082-48bb01e2ff3f.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Predation' ability. The design features a stylized wide-open mouth silhouette or a swirling engulfing vortex effect using vibrant blue and cyan slime colors. The style is clean, flat vector art suitable for a game skill button, high contrast, on a dark background. Professional game UI quality, square aspect ratio.", "description": "Minimalist UI icon for Rimuru's Predation ability featuring a blue slime engulfing effect.", "subtype": "ui", "aspect_ratio": [930, 930], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability2_icon_rimuru": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability2_icon_rimuru_c7b7be6e-67c0-402f-b69b-8695b5bfc349.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Sticky Shuriken' ability. The design features sharp blue slime shards and projectiles in motion with speed lines, using a vibrant cyan and dark blue color palette. Professional game UI style, flat design, clean vector-like appearance, square composition, isolated on a solid background for easy integration.", "description": "Minimalist UI icon for Rimuru's Sticky Shuriken ability featuring blue slime projectiles.", "subtype": "ui", "aspect_ratio": [750, 698], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability3_icon_rimuru": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability3_icon_rimuru_caedf6c9-db51-415c-9c2c-076f1c0d3f0f.webp", "type": "image", "prompt": "Create a minimalist UI game icon for Rimuru's 'Barrier Shield' ability. The design should feature a clean, stylized shield or protective dome silhouette with a blue and cyan slime aesthetic, incorporating soft rounded edges and a slight crystalline or blob-like pattern. Use a consistent minimalist vector style on a transparent background, matching the existing UI icons for anime stick figure combat games. High resolution, professional quality, square composition.", "description": "Minimalist UI icon for Rimuru's Barrier Shield ability featuring a blue slime shield.", "subtype": "ui", "aspect_ratio": [807, 696], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ability4_icon_rimuru": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ability4_icon_rimuru_bda7e82d-1d40-4360-b9fe-b6f14326077b.webp", "type": "image", "prompt": "Create a minimalist UI icon for a 'Massive Replication' ability. The design features an enlarged, explosive effect with glowing blue slime energy radiating outward from the center. High-contrast, clean lines, professional game UI style, matching the blue and cyan color palette of the Rimuru character. Square aspect ratio, centered composition, high resolution, detailed vector-like aesthetic.", "description": "Minimalist UI icon for Rimuru's Massive Replication ultimate ability", "subtype": "ui", "aspect_ratio": [962, 950], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "rimuru_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_portrait_655fce8f-bf1f-452d-bd3c-5823aed9afa8.webp", "type": "image", "prompt": "Generate a minimalist 2D anime character selection portrait of Rimuru Tempest based on the character in image 1. Rimuru is in human form with long light-blue hair, wearing a white fur scarf and a signature blue coat. The composition is a bust/headshot from the chest up, with the character looking confidently at the viewer. Use a clean, professional minimalist style that matches existing game portraits. High resolution, sharp lines, transparent background.", "description": "High-quality character selection portrait for Rimuru Tempest in human form.", "subtype": "ui", "aspect_ratio": [570, 646], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_idle_0be917c2-02bd-4d6d-a3b9-753a141d5c7b.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest, inspired by the character design in image 01KZAQZK6MWZG5QHP9V36RKNS7. The character should have long light-blue hair, a white fur scarf, a long blue coat over black pants, and black boots, carrying a katana at his side. Pose: idle standing pose, side view, right-facing character. Style: clean minimalist 2D side-view combat sprite for a fighting game, transparent background, high resolution.", "description": "Idle standing pose for Rimuru Tempest in minimalist stick figure style", "subtype": "character", "aspect_ratio": [480, 747], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_walk_72f6dda7-e482-453b-9af4-0e1be03b4b0d.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure character of Rimuru Tempest walking forward. The character should have long light-blue hair, a white fur scarf, and a long blue coat over black pants, as seen in image 1. Side view, right-facing character. Show the coat and hair flowing slightly to indicate motion. Professional quality game asset, side-view combat sprite, transparent background.", "description": "Walking animation frame for Rimuru Tempest in minimalist stick figure style", "subtype": "character", "aspect_ratio": [656, 1221], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_jump_c6d4c829-73b4-41a0-a7a7-73aafdfc4375.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest in a mid-air jumping pose, side view, right-facing. The character features long light-blue hair, a white fur scarf, and a long blue coat that is fluttering dynamically in the air. Based on the character design in image 1. Clean minimalist 2D side-view combat sprite, high resolution, transparent background.", "description": "Jumping animation frame for Rimuru Tempest stick figure", "subtype": "character", "aspect_ratio": [615, 617], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "rimuru_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_ability1_c5173c64-6385-49ed-9b88-d33bd56bbc42.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest based on the character design in image 1. The character has long light-blue hair, a white fur scarf, and a long blue coat. He is in an attacking pose, slashing forward with his katana. A vibrant blue slime energy effect surrounds the blade. Side-view, right-facing combat sprite illustration. High quality, clean lines, transparent background.", "description": "Rimuru Tempest performing a Predation sword slash attack with blue slime energy effects.", "subtype": "character", "aspect_ratio": [596, 416], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_ability2_b1a3bbff-5cf2-4c4d-a68f-d5abdbdde7a1.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest in a side-view combat pose. The character has long light-blue hair, a white fur scarf, and a long blue coat. Action: Rimuru is throwing a blue slime shuriken projectile with one arm extended forward. Professional quality game asset, side view, right-facing, transparent background, matching the style of image 1.", "description": "2D minimalist stick figure sprite of Rimuru Tempest throwing a slime shuriken", "subtype": "character", "aspect_ratio": [611, 568], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_ability3_50f58e78-2c3f-4506-936d-88e42909c3e9.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest, side view. The character has long light-blue hair, a white fur scarf, and a long blue coat. He is in a defensive bracing pose with a glowing blue semi-transparent slime barrier active in front of him. Maintain a clean, minimalist 2D fighting game aesthetic consistent with image 01KZAQZK6MWZG5QHP9V36RKNS7. Transparent background.", "description": "A side-view combat sprite of Rimuru Tempest in a defensive pose with a slime barrier.", "subtype": "character", "aspect_ratio": [603, 813], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_ability4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_ability4_b8590980-4733-4225-b85b-f2bb1f8d0229.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest performing an ultimate ability called Massive Replication. The character should have long light-blue hair, a white fur scarf, and a long blue coat, matching the design in image 01KZAQZK6MWZG5QHP9V36RKNS7. Pose: Epic side-view standing pose with arms outstretched, surrounded by several faint, semi-transparent blue slime silhouettes of himself. Style: Clean minimalist 2D side-view combat sprite, game-ready, transparent background, high resolution.", "description": "Ultimate ability pose for Rimuru Tempest featuring multiple slime silhouettes", "subtype": "character", "aspect_ratio": [832, 1105], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_hit_0dd77fee-407b-4dde-950b-59e228de3efa.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest in a hit recoil pose, reeling back from a blow with a pained expression. The character features long light-blue hair, a white fur scarf, and a long blue coat. Side view, right-facing character. Maintain the exact minimalist style and design of image 1. High resolution, clean edges, transparent background.", "description": "The Rimuru Tempest stick figure in a hit recoil pose for combat feedback", "subtype": "character", "aspect_ratio": [745, 1094], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "rimuru_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rimuru_victory_230c2e49-0cfc-44a7-acd5-f49acd1650e2.webp", "type": "image", "prompt": "Generate a 2D minimalist pixel art stick figure of Rimuru Tempest in a victory pose, inspired by the design in image 01KZAQZK6MWZG5QHP9V36RKNS7. The character features long light-blue hair, a white fur scarf, and a long blue coat. The pose is a side view of him standing confidently, sheathing his katana and giving a slight smile. Clean minimalist aesthetic, high-quality game-ready sprite, transparent background.", "description": "Victory pose for Rimuru Tempest stick figure character", "subtype": "character", "aspect_ratio": [497, 797], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "1000000862.jpg": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1787113405971_01M0C44ZGKKZCNESHKEW9NX076.1000000862.jpg", "type": "image", "prompt": null, "description": "Reference image for Itachi Edo skin appearance: pixel-art Itachi in a dark maroon Akatsuki cloak with pale collar and black hair, for use as a visual reference when creating the Itachi Edo character skin.", "subtype": null, "aspect_ratio": [481, 909], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_portrait_7c17bb36-3059-4b01-b8d6-69112b0c6aa9.webp", "type": "image", "prompt": "A minimalist character selection portrait for the stick figure character Itachi Edo. The character should have a lean stick-figure silhouette, black hair, a pale face, and be wearing a dark maroon Akatsuki-style cloak with a light collar and white vertical trim, with pale lower legs and sandals. Match the style and outfit of image 1 precisely. Front-facing three-quarter portrait, clean and crisp lines, high contrast, minimalist anime aesthetic, transparent background, professional game asset quality.", "description": "Character selection portrait for Itachi Edo skin in a minimalist stick-figure style.", "subtype": "ui", "aspect_ratio": [735, 1341], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_idle_dd7cf961-228c-4894-96d5-d79abc76258f.webp", "type": "image", "prompt": "Generate a full-body side-view combat idle pose for the stick figure character Itachi Edo. Match the visual style of image 1: dark maroon Akatsuki-style cloak with a pale collar and white vertical trim, black hair, pale face, and sandals. Maintain a minimalist anime stick-figure pixel art style with a clean silhouette, ensuring consistency with the proportions of itachi_idle. Transparent background, high resolution, professional game asset.", "description": "Side-view combat idle sprite for Itachi Edo skin", "subtype": "character", "aspect_ratio": [492, 1060], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_walk_74dc5c46-5b2e-49e5-a7f4-db23a80bf86c.webp", "type": "image", "prompt": "Generate a side-view, right-facing walking animation sprite for a minimalist anime stick-figure character skin. The character should wear a dark maroon Akatsuki-style cloak with a pale collar and white vertical trim, have black hair, pale legs, and sandals, matching the design in image 1. Maintain the exact minimalist pixel-art style and proportions of image 2. Full body standing illustration, transparent background, high resolution, clean lines, game-ready asset.", "description": "Walking animation frame for the Itachi Edo stick figure character skin.", "subtype": "character", "aspect_ratio": [749, 1056], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_jump_b33d01a6-b8ee-4181-90a0-7d7a806d49fe.webp", "type": "image", "prompt": "Generate a side-view jumping combat sprite for an Itachi Edo stick figure character. The character has black hair and a dark maroon Akatsuki-style cloak with a light collar and white vertical trim that flows slightly upwards to indicate jumping motion. Pale skin on the face and legs with traditional sandals. Style: clean minimalist pixel-art anime stick-figure, high contrast, full body standing illustration, transparent background. Proportions should match the existing 'itachi_jump' asset. Professional game-ready asset, no text, no extra characters.", "description": "Jumping combat sprite for the Itachi Edo skin in a minimalist stick-figure style.", "subtype": "character", "aspect_ratio": [947, 989], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_ability1_2b18ac27-f3f6-4b8e-8d75-aef8effda4bf.webp", "type": "image", "prompt": "Generate a side-view combat sprite of a minimalist stick-figure character inspired by the outfit in image 1. The character has black hair and a dark maroon Akatsuki-style cloak with a pale collar and white vertical trim. The character is performing a 'Fireball Jutsu' attack, exhaling or casting a bright orange-red fireball with subtle flame glow effects. Clean minimalist pixel-art style, anime aesthetic, full body, transparent background, high resolution, professional game asset.", "description": "Side-view combat sprite of Itachi Edo performing Fireball Jutsu with orange flames.", "subtype": "character", "aspect_ratio": [729, 505], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_ability2_d1cb9737-eef9-4dc9-ac57-94d35bee8dcd.webp", "type": "image", "prompt": "Generate a side-view combat sprite of a minimalist anime stick figure character named Itachi Edo dissolving into a flock of black crows. The character must wear a dark maroon Akatsuki-style cloak with a pale collar and white vertical trim, matching the style and colors of image 1000000862.jpg. Use a clean pixel-art style with high contrast and a strong silhouette. The character is partially transformed into multiple black crows flying outward. Transparent background, game-ready asset, full body illustration.", "description": "Ability sprite of Itachi Edo dissolving into crows for Crow Clone technique", "subtype": "effect", "aspect_ratio": [770, 1006], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_ability3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_ability3_475dae16-2708-4e4c-9619-7d14da7dc8b8.webp", "type": "image", "prompt": "Create a side-view combat ability sprite for the stick-figure character Itachi Edo. The character must wear the dark maroon Akatsuki cloak with a pale collar and white trim as seen in image 1. Add glowing intense red eyes and a subtle, restrained dark red energy aura surrounding the body. Use a clean, minimalist pixel-art anime stick-figure style with a sharp silhouette. Full body standing pose, side view, transparent background, high-quality game asset, no text.", "description": "Side-view combat sprite for Itachi Edo activating his ultimate Mangekyo Sharingan ability with a dark red aura", "subtype": "character", "aspect_ratio": [586, 1263], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_hit_2f0029a8-7f06-4c24-9509-fc71581ef2e7.webp", "type": "image", "prompt": "Generate a side-view combat hit recoil pose for a minimalist stick figure character named Itachi Edo. The character has black hair, a pale face, and wears a dark maroon Akatsuki-style cloak with a pale collar and white vertical trim, with pale legs and sandals, matching the style and colors of image 1. The pose should clearly convey taking damage or being knocked back. Clean pixel-art anime style, high contrast, transparent background, full body standing illustration.", "description": "A side-view hit recoil sprite for the Itachi Edo stick figure character skin.", "subtype": "character", "aspect_ratio": [823, 796], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_victory_6523fb84-cb73-494f-a610-885fa04ee1d4.webp", "type": "image", "prompt": "Generate a side-view victory pose for a minimalist stick-figure character skin. The character has black hair, a dark maroon Akatsuki-style cloak with a pale high collar and white vertical trim, pale legs, and sandals, matching the style and outfit in image 1. The character is looking back over their shoulder in a calm, victorious stance. Clean minimalist pixel-art style, side view, full body standing illustration, transparent background, high resolution, professional game asset.", "description": "Victory pose for the Itachi Edo stick figure character skin showing a calm over-the-shoulder pose.", "subtype": "character", "aspect_ratio": [286, 906], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_susanoo_reference": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1787115458440_01M0C63KW8HV65YCFSW224DMX0.1000000863.png", "type": "image", "prompt": null, "description": "User-provided reference image for Itachi Edo's Susanoo transformation visual: orange Susanoo with a purple shield, intended as the reference for Itachi Edo ability 4.", "subtype": null, "aspect_ratio": [286, 311], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_susanoo": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/itachi_edo_susanoo_bdedee88-d31f-4742-ae70-fd9c2beb5930.webp", "type": "image", "prompt": "Generate a transparent-background 2D anime game combat effect of a large orange/gold Susanoo avatar, inspired by the silhouette and colors in itachi_edo_susanoo_reference. The asset should feature a fierce demonic face, layered ribbed armor, and hold a prominent purple/dark-crimson circular shield with a bright yellow-orange energy blade crossing in front. Use a high-contrast hand-painted anime style with glowing edges. Clean cutout, professional game-ready asset, no text, no background, high resolution.", "description": "Large orange and purple Susanoo avatar combat effect for Itachi Edo skin", "subtype": "effect", "aspect_ratio": [944, 1050], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "itachi_edo_sharingan_reference": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1787320411464_01M0J9J9A8VJ04Q6Z4SM2TD9SZ.1000000866.jpg", "type": "image", "prompt": null, "description": "User-provided Sharingan reference image for Itachi Edo's Susanoo skill 3 visual; use as a visual reference for the rotating red-and-black vortex effect.", "subtype": null, "aspect_ratio": [736, 736], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_reference": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1787543208446_01M0RY1GFYP17670M5SNWT8XE8.1000000875.jpg", "type": "image", "prompt": null, "description": "User-provided reference image for the Doraemon Vietnam skin: Doraemon wearing a Vietnamese conical hat with pink chin straps, retaining the blue body, white face and belly, red nose, red collar, and yellow bell.", "subtype": null, "aspect_ratio": [481, 619], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_portrait": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_portrait_cbf9ce65-1560-4f07-82a0-4f4234c5a35a.webp", "type": "image", "prompt": "Create a clean, professional character-selection portrait for a Doraemon Vietnam skin. Match the minimalist 2D fighting game style of existing character portraits. The character must have a blue body, white face and belly, red nose, red collar, and yellow bell, while wearing a traditional Vietnamese n\u00f3n l\u00e1 conical hat with pink chin straps as seen in image 1. Front-facing three-quarter portrait, centered, high-quality cel shading, bold silhouettes, transparent background, high resolution.", "description": "Character selection portrait for Doraemon Vietnam skin wearing a N\u00f3n L\u00e1 hat.", "subtype": "ui", "aspect_ratio": [813, 923], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_idle_edafb66b-9814-43c0-b9a2-3a9bb724ae71.webp", "type": "image", "prompt": "Generate a side-view combat idle sprite of Doraemon wearing a traditional Vietnamese n\u00f3n l\u00e1 conical hat with pink chin straps. The character must have a blue body, white face and belly, red nose, red collar, and yellow bell. Full body standing illustration, facing right, minimalist 2D stick-figure fighting-game style. Clean polished silhouette, cel-shaded, transparent background, high resolution, professional game asset.", "description": "Side-view combat idle sprite for Doraemon Vietnam skin featuring a conical hat.", "subtype": "character", "aspect_ratio": [513, 814], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_walk_147f22aa-3077-4ea3-a1c5-7b9e4c92df51.webp", "type": "image", "prompt": "Generate a side-view walking animation sprite for a Doraemon character skin. The character is a minimalist 2D stick-figure-style robot cat with a blue body, white face and belly, red nose, red collar, and yellow bell. He is wearing a traditional Vietnamese n\u00f3n l\u00e1 conical hat with pink chin straps. The character should be in a mid-stride walking pose, facing right. Clean polished lines, cel-shaded style, transparent background, professional game asset quality, matching the proportions of existing doraemon_walk.", "description": "Walking animation frame for the Doraemon Vietnam skin wearing a conical hat.", "subtype": "character", "aspect_ratio": [780, 1263], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_jump": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_jump_f4fe9dc9-4561-4dad-a54d-3c9ac33e7c18.webp", "type": "image", "prompt": "Generate a side-view jumping combat sprite for a Doraemon Vietnam skin. The character is a blue robotic cat with a white face and belly, red nose, red collar, and a yellow bell. He is wearing a traditional Vietnamese n\u00f3n l\u00e1 (conical hat) with pink chin straps. The pose should be a dynamic jumping action suitable for a fighting game. Polished minimalist 2D stick-figure art style, clean lines, cel-shaded, facing right. Transparent background, high resolution, professional quality, no text.", "description": "Jumping combat sprite for the Doraemon Vietnam skin wearing a conical hat", "subtype": "character", "aspect_ratio": [653, 991], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_hit": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_hit_c676f19a-80e4-4b11-9e99-6862d88d6de5.webp", "type": "image", "prompt": "Generate a side-view hit recoil combat sprite for a Doraemon Vietnam skin. The character is a minimalist blue stick-figure style robot cat with a white face and belly, a red nose, a red collar with a yellow bell, and wearing a traditional Vietnamese n\u00f3n l\u00e1 conical hat with pink chin straps. The pose should show the character reeling back from an impact (damage recoil). High-quality 2D game asset, clean lines, polished cel shading, right-facing, full body, transparent background, no text, no extra characters.", "description": "Side-view hit recoil sprite for Doraemon Vietnam skin with a conical hat.", "subtype": "character", "aspect_ratio": [669, 1059], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_victory": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_victory_e800c2f5-e7d2-4029-8401-273d508c81a4.webp", "type": "image", "prompt": "Generate a side-view victory pose for a minimalist 2D stick-figure style Doraemon character. The character has a blue body, white face and belly, red nose, red collar, and a yellow bell. He is wearing a traditional Vietnamese n\u00f3n l\u00e1 (conical hat) with pink chin straps. The pose is cheerful and triumphant, full body, facing right. Match the artistic style of the existing game characters. Transparent background, high resolution, no text.", "description": "Victory pose for the Doraemon Vietnam skin wearing a conical hat", "subtype": "character", "aspect_ratio": [729, 1010], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_ability1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_ability1_43f08380-602c-4578-aa5a-f1e5de66dd24.webp", "type": "image", "prompt": "Create a side-view combat ability sprite for a Doraemon character skin. The character is a minimalist blue robotic cat with a white face and belly, a red nose, a red collar with a yellow bell, and is wearing a traditional Vietnamese n\u00f3n l\u00e1 conical hat with pink chin straps. The pose should show the character dynamically reaching into his 4D belly pocket for an item, matching the action style of image 2. Polished minimalist 2D fighting game style, clean readable silhouette, right-facing, transparent background, professional quality.", "description": "Side-view combat ability sprite for Doraemon Vietnam skin reaching into 4D pocket", "subtype": "character", "aspect_ratio": [658, 1192], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_ability2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_ability2_af02ad0a-2e09-4d32-894f-374cbb188014.webp", "type": "image", "prompt": "Generate a side-view combat ability sprite of a stick-figure style Doraemon wearing a Vietnamese n\u00f3n l\u00e1 (conical hat) with pink chin straps, based on the identity in image 01M0RY1GFYP17670M5SNWT8XE8. The character has a blue body, white face and belly, red nose, red collar, and yellow bell. He is in a dynamic flying pose with a yellow Takecopter propeller on top of his conical hat. Match the minimalist 2D fighting game art style, right-facing, full body, transparent background, high resolution, professional quality, no text.", "description": "Side-view combat sprite for Doraemon Vietnam skin flying with a Takecopter.", "subtype": "character", "aspect_ratio": [753, 670], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_flag_reference": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1787545178135_01M0RZXM0Q4294VNDS0GDB9F2N.1000000876.jpg", "type": "image", "prompt": null, "description": "User-provided reference image of the Vietnamese flag: a bright red circular field with a centered five-pointed yellow star, for Doraemon Vietnam's sky ultimate effect.", "subtype": null, "aspect_ratio": [612, 603], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "doraemon_vietnam_dragon_reference": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/doraemon_vietnam_dragon_reference_d52c8c6b-0720-41b0-bf3b-464d1e6201d6.webp", "type": "image", "prompt": "Clean up the golden Vietnamese-style dragon from image 1. Remove all background elements to make it perfectly transparent. Preserve the circular ring shape, golden scales, red-brown outlines, and detailed head with whiskers and horns. Maintain the original colors and ensure a clean cutout of the full circular body, centered and upright, suitable for a 2D game visual effect.", "description": "Cleaned golden Vietnamese-style dragon ring effect on transparent background", "subtype": "effect", "aspect_ratio": [616, 856], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "1000000879.webp": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1787566655751_01M0SMD287T6R0DDP76YJTA2SR.1000000879.webp", "type": "image", "prompt": null, "description": "Vietnamese national flag on a flagpole with a yellow star, used for Doraemon Vietnam's third ability effect.", "subtype": null, "aspect_ratio": [640, 640], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "1000000881.jpg": {"url": "https://dzmv1mxivz48k.cloudfront.net/images/Google_116999058777793026471/1787622361647_01M0V9H2HFK3Y4BGXA0YQ2F1Z9.1000000881.jpg", "type": "image", "prompt": null, "description": "User-provided image to use as the game's thumbnail, unchanged.", "subtype": null, "aspect_ratio": [639, 360], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}}, "game_code": "<!DOCTYPE html>\n<html>\n<head>\n    <title>Ng\u01b0\u1eddi Que \u0110\u1ed1i Kh\u00e1ng</title>\n    <link href=\"https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Inter:wght@400;600;700&display=swap\" rel=\"stylesheet\">\n    <style>\n        :root {\n            --transition-fast: 150ms;\n            --transition-normal: 300ms;\n            --transition-slow: 500ms;\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            --space-xs: 8px;\n            --space-sm: 16px;\n            --space-md: 24px;\n            --space-lg: 32px;\n            --space-xl: 48px;\n            --color-bat-bai: #4A90E2;\n            --color-bong-dem: #9B59B6;\n            --color-dark: #1a1a2e;\n            --color-panel: rgba(20, 20, 40, 0.92);\n            --color-btn: rgba(255, 255, 255, 0.12);\n            --color-btn-hover: rgba(255, 255, 255, 0.2);\n            --radius: 12px;\n        }\n\n        #loading-screen {\n            position: fixed;\n            top: 0; left: 0;\n            width: 100%; height: 100%;\n            background: #000;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            z-index: 9999;\n            transition: opacity 0.5s ease;\n        }\n\n        .loading-logo {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 64px;\n            color: #fff;\n            text-shadow: 0 0 20px rgba(74, 144, 226, 0.8);\n            margin-bottom: 40px;\n            letter-spacing: 4px;\n            animation: logoPulse 2s infinite alternate;\n        }\n\n        @keyframes logoPulse {\n            from { transform: scale(1); opacity: 0.8; }\n            to { transform: scale(1.05); opacity: 1; }\n        }\n\n        .loading-bar-bg {\n            width: 400px;\n            height: 12px;\n            background: rgba(255, 255, 255, 0.1);\n            border-radius: 6px;\n            border: 1px solid rgba(255, 255, 255, 0.2);\n            overflow: hidden;\n            position: relative;\n        }\n\n        .loading-bar-fill {\n            height: 100%;\n            width: 0%;\n            background: linear-gradient(90deg, #4A90E2, #9B59B6);\n            box-shadow: 0 0 15px #4A90E2;\n            transition: width 0.3s ease-out;\n        }\n\n        .loading-text {\n            margin-top: 16px;\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 24px;\n            color: #4A90E2;\n            letter-spacing: 2px;\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: 'Inter', sans-serif;\n            background: #000;\n        }\n\n        #game-world {\n            position: relative;\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n        }\n\n        canvas {\n            display: block;\n            width: 100%;\n            height: 100%;\n        }\n\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        .screen {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 100%;\n            display: none;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n        }\n\n        .screen.active {\n            display: flex;\n        }\n\n        .game-title {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 56px;\n            color: #fff;\n            text-shadow: 0 0 20px rgba(74, 144, 226, 0.6), 0 4px 8px rgba(0,0,0,0.5);\n            letter-spacing: 2px;\n            margin-bottom: 48px;\n            text-align: center;\n        }\n\n        .btn {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 28px;\n            letter-spacing: 1px;\n            color: #fff;\n            background: linear-gradient(135deg, rgba(74, 144, 226, 0.3), rgba(155, 89, 182, 0.3));\n            border: 2px solid rgba(255, 255, 255, 0.25);\n            border-radius: var(--radius);\n            padding: 16px 48px;\n            cursor: pointer;\n            min-width: 200px;\n            min-height: 56px;\n            transition: transform var(--transition-fast) var(--ease-out), background var(--transition-fast);\n            text-align: center;\n        }\n\n        .btn:hover {\n            background: linear-gradient(135deg, rgba(74, 144, 226, 0.5), rgba(155, 89, 182, 0.5));\n            transform: scale(1.05);\n        }\n\n        .btn:active {\n            transform: scale(0.95);\n            background: linear-gradient(135deg, rgba(74, 144, 226, 0.6), rgba(155, 89, 182, 0.6));\n        }\n\n        .char-select-container {\n            display: flex;\n            gap: 24px;\n            margin-bottom: 32px;\n            width: 100%;\n            justify-content: center;\n            padding: 0 16px;\n            box-sizing: border-box;\n        }\n\n        .char-card {\n            background: var(--color-panel);\n            border-radius: var(--radius);\n            border: 2px solid rgba(255,255,255,0.15);\n            padding: 16px;\n            width: 280px;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            cursor: pointer;\n            transition: transform var(--transition-fast) var(--ease-out), border-color var(--transition-fast);\n        }\n\n        .char-card:hover {\n            transform: translateY(-4px);\n            border-color: rgba(255,255,255,0.4);\n        }\n\n        .char-card.selected {\n            border-color: #fff;\n            box-shadow: 0 0 20px rgba(255,255,255,0.2);\n        }\n\n        .char-card img {\n            width: 120px;\n            height: 180px;\n            object-fit: contain;\n            margin-bottom: 12px;\n        }\n\n        .char-name {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 24px;\n            color: #fff;\n            margin-bottom: 8px;\n        }\n\n        .char-desc {\n            font-size: 14px;\n            color: rgba(255,255,255,0.7);\n            text-align: center;\n            line-height: 1.4;\n        }\n\n        .ability-btn {\n            position: absolute;\n            width: 96px;\n            height: 96px;\n            border-radius: 50%;\n            border: 3px solid rgba(255,255,255,0.4);\n            background: rgba(0,0,0,0.5);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            cursor: pointer;\n            transition: transform var(--transition-fast);\n            overflow: hidden;\n        }\n\n        .ability-btn:active {\n            transform: scale(0.9);\n        }\n\n        .ability-btn img {\n            width: 60px;\n            height: 60px;\n            object-fit: contain;\n        }\n\n        .ability-btn .cooldown-overlay {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 100%;\n            background: rgba(0,0,0,0.7);\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 24px;\n            color: #fff;\n        }\n\n        .health-bar-container {\n            position: absolute;\n            top: 16px;\n            left: 16px;\n            right: 16px;\n            display: flex;\n            gap: 8px;\n            align-items: center;\n        }\n\n        .health-bar {\n            flex: 1;\n            height: 24px;\n            background: rgba(0,0,0,0.6);\n            border-radius: 12px;\n            overflow: hidden;\n            border: 2px solid rgba(255,255,255,0.3);\n        }\n\n        .health-bar-fill {\n            height: 100%;\n            transition: width var(--transition-normal) var(--ease-out);\n            border-radius: 12px;\n        }\n\n        .health-label {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 18px;\n            color: #fff;\n            text-shadow: 0 1px 3px rgba(0,0,0,0.8);\n            min-width: 40px;\n            text-align: center;\n        }\n\n        .countdown {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 120px;\n            color: #fff;\n            text-shadow: 0 0 40px rgba(255,255,255,0.5);\n            animation: countPulse 0.5s var(--ease-bounce);\n        }\n\n        @keyframes countPulse {\n            from { transform: translate(-50%, -50%) scale(2); opacity: 0; }\n            to { transform: translate(-50%, -50%) scale(1); opacity: 1; }\n        }\n\n        .result-screen {\n            background: rgba(0,0,0,0.85);\n        }\n\n        .result-text {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 64px;\n            margin-bottom: 32px;\n            text-shadow: 0 0 30px currentColor;\n        }\n\n        .timer-display {\n            position: absolute;\n            top: 48px;\n            left: 50%;\n            transform: translateX(-50%);\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 28px;\n            color: #fff;\n            text-shadow: 0 2px 4px rgba(0,0,0,0.8);\n            background: rgba(0,0,0,0.5);\n            padding: 4px 16px;\n            border-radius: 8px;\n        }\n\n        .joystick-area {\n            position: absolute;\n            bottom: 80px;\n            left: 16px;\n            width: 180px;\n            height: 180px;\n        }\n\n        .selection-slots {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 24px;\n            margin-bottom: 24px;\n            width: 100%;\n        }\n\n        .slot {\n            width: 140px;\n            height: 180px;\n            background: rgba(0, 0, 0, 0.4);\n            border: 3px solid rgba(255, 255, 255, 0.1);\n            border-radius: var(--radius);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            position: relative;\n            overflow: hidden;\n            transition: all var(--transition-normal);\n        }\n\n        .slot.active {\n            border-color: #4A90E2;\n            box-shadow: 0 0 20px rgba(74, 144, 226, 0.4);\n            transform: scale(1.05);\n        }\n\n        .slot.ready {\n            border-color: #4CAF50;\n        }\n\n        .slot img {\n            width: 100%;\n            height: 100%;\n            object-fit: cover;\n        }\n\n        .slot-label {\n            position: absolute;\n            bottom: 0;\n            left: 0;\n            right: 0;\n            background: rgba(0,0,0,0.8);\n            color: #fff;\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 18px;\n            padding: 4px;\n            text-align: center;\n            z-index: 2;\n        }\n\n        .vs-text {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 40px;\n            color: #ff4444;\n            text-shadow: 0 0 10px rgba(255, 68, 68, 0.5);\n            font-style: italic;\n        }\n\n        .char-grid {\n            display: grid;\n            grid-template-columns: repeat(4, 1fr);\n            gap: 12px;\n            padding: 16px;\n            background: rgba(0,0,0,0.3);\n            border-radius: var(--radius);\n            max-height: 500px;\n            overflow-y: auto;\n            width: 90%;\n        }\n\n        .char-mini-card {\n            background: rgba(255,255,255,0.05);\n            border: 2px solid rgba(255,255,255,0.1);\n            border-radius: 8px;\n            padding: 4px;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n        }\n\n        .char-mini-card:hover {\n            background: rgba(255,255,255,0.15);\n            border-color: rgba(255,255,255,0.4);\n        }\n\n        .char-mini-card.selected {\n            border-color: #fff;\n            background: rgba(255,255,255,0.2);\n        }\n\n        .char-mini-card img {\n            width: 60px;\n            height: 60px;\n            object-fit: contain;\n        }\n\n        .char-mini-name {\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 14px;\n            color: #fff;\n            margin-top: 4px;\n            text-align: center;\n        }\n\n        .sel-tabs {\n            display: flex;\n            gap: 16px;\n            margin-bottom: 16px;\n        }\n        .sel-tab {\n            width: 140px;\n            height: 50px;\n            background: rgba(255, 255, 255, 0.05);\n            border: 2px solid rgba(255, 255, 255, 0.2);\n            border-radius: 10px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            color: #fff;\n            font-family: 'Bebas Neue', sans-serif;\n            font-size: 20px;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n        }\n        .sel-tab.active {\n            border-color: #4A90E2;\n            background: rgba(74, 144, 226, 0.3);\n            box-shadow: 0 0 15px rgba(74, 144, 226, 0.4);\n        }\n\n        @media (prefers-reduced-motion: reduce) {\n            * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }\n        }\n    </style>\n</head>\n<body>\n    <div id=\"game-world\">\n        <canvas id=\"game-canvas\"></canvas>\n        <div class=\"ui-overlay\" id=\"ui-overlay\"></div>\n    </div>\n\n    <script>\n    /*\n     * NG\u01af\u1edcI QUE \u0110\u1ed0I KH\u00c1NG (Stick Figure Fighting)\n     * - B\u00f3ng \u0110\u00eam (Assassin): Fast, agile, offensive abilities\n     * Players choose a character and fight against AI opponent.\n     */\n\n    async function run(mode) {\n        const canvas = document.getElementById('game-canvas');\n        const ctx = canvas.getContext('2d');\n        const uiOverlay = document.getElementById('ui-overlay');\n        const config = window.gameConfig;\n\n        // Create Loading Screen\n        const loadingScreen = document.createElement('div');\n        loadingScreen.id = 'loading-screen';\n        loadingScreen.innerHTML = `\n            <div class=\"loading-logo\">NG\u01af\u1edcI QUE \u0110\u1ed0I KH\u00c1NG</div>\n            <div class=\"loading-bar-bg\">\n                <div class=\"loading-bar-fill\" id=\"loading-fill\"></div>\n            </div>\n            <div class=\"loading-text\" id=\"loading-percentage\">LOADING... 0%</div>\n        `;\n        document.body.appendChild(loadingScreen);\n\n        const loadingFill = document.getElementById('loading-fill');\n        const loadingText = document.getElementById('loading-percentage');\n\n        function updateLoading(progress) {\n            const percent = Math.round(progress * 100);\n            loadingFill.style.width = percent + '%';\n            loadingText.textContent = `LOADING... ${percent}%`;\n        }\n\n        // Canvas setup\n        function resizeCanvas() {\n            canvas.width = 720;\n            canvas.height = 1280;\n        }\n        resizeCanvas();\n\n        // Audio context\n        let audioCtx = null;\n        const audioBuffers = {};\n\n        function getAudioCtx() {\n            if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();\n            return audioCtx;\n        }\n\n        function playSound(id, volume = 0.5, loop = false) {\n            try {\n                const ctx = getAudioCtx();\n                if (ctx.state === 'suspended') ctx.resume();\n                const buffer = audioBuffers[id];\n                if (!buffer) return null;\n                const source = ctx.createBufferSource();\n                const gain = ctx.createGain();\n                source.buffer = buffer;\n                source.loop = loop;\n                gain.gain.value = volume;\n                source.connect(gain);\n                gain.connect(ctx.destination);\n                source.start(0);\n                return { source, gain };\n            } catch(e) { return null; }\n        }\n\n        // Asset loading\n        const imageCache = {};\n            const assetIds = [\n                'obito_idle','obito_walk','obito_jump','obito_ability1','obito_ability2','obito_ability3','obito_ability4','obito_hit','obito_victory','obito_portrait','obito_ult_image','obito_god_tree',\n                'obito_fire_ring',\n                'rimuru_idle','rimuru_walk','rimuru_jump','rimuru_ability1','rimuru_ability2','rimuru_ability3','rimuru_ability4','rimuru_hit','rimuru_victory','rimuru_portrait',\n                'ability1_icon_rimuru','ability2_icon_rimuru','ability3_icon_rimuru','ability4_icon_rimuru',\n                'ability1_icon_obito','ability2_icon_obito','ability3_icon_obito','ability4_icon_obito',\n                'zoro_idle','zoro_walk','zoro_jump','zoro_ability1','zoro_ability2','zoro_ability3','zoro_ability4','zoro_hit','zoro_victory','zoro_portrait',\n                'ability1_icon_zoro','ability2_icon_zoro','ability3_icon_zoro','ability4_icon_zoro','zoro_ashura_bg',\n                'yuta_idle','yuta_walk','yuta_jump','yuta_ability1','yuta_ability2','yuta_ability3','yuta_ability4','yuta_hit','yuta_victory','yuta_portrait','rika_spirit','rika_v2',\n                'ability1_icon_yuta','ability2_icon_yuta','ability3_icon_yuta','ability4_icon_yuta',\n                'bat_bai_idle','bat_bai_walk','bat_bai_jump','bat_bai_ability1','bat_bai_ability2','bat_bai_ability3','bat_bai_hit','bat_bai_victory',\n                'bong_dem_idle','bong_dem_walk','bong_dem_jump','bong_dem_ability1','bong_dem_ability2','bong_dem_ability3','bong_dem_hit','bong_dem_victory',\n                'itachi_idle','itachi_walk','itachi_jump','itachi_ability1','itachi_ability2','itachi_ability3','itachi_hit','itachi_victory','itachi_edo_idle','itachi_edo_walk','itachi_edo_jump','itachi_edo_ability1','itachi_edo_ability2','itachi_edo_ability3','itachi_edo_ability4','itachi_edo_hit','itachi_edo_victory','itachi_edo_portrait','itachi_edo_susanoo','itachi_edo_sharingan_reference',\n                'madara_idle','madara_walk','madara_jump','madara_ability1','madara_ability2','madara_ability3','madara_hit','madara_victory',\n                'sasuke_idle','sasuke_walk','sasuke_jump','sasuke_ability1','sasuke_ability2','sasuke_ability3','sasuke_hit','sasuke_victory',\n                'sasuke_adult_idle','sasuke_adult_walk','sasuke_adult_jump','sasuke_adult_portrait',\n                'luffy_idle','luffy_walk','luffy_jump','luffy_ability1','luffy_ability2','luffy_ability3','luffy_hit','luffy_victory',\n                'sukuna_idle','sukuna_walk','sukuna_jump','sukuna_ability1','sukuna_ability2','sukuna_ability3','sukuna_hit','sukuna_victory',\n                'gojo_idle','gojo_walk','gojo_jump','gojo_ability1','gojo_ability2','gojo_ability3','gojo_hit','gojo_victory',\n                'saitama_idle','saitama_walk','saitama_jump','saitama_ability1','saitama_ability2','saitama_ability3','saitama_hit','saitama_victory',\n                'vua_quy_idle','vua_quy_walk','vua_quy_jump','vua_quy_ability1','vua_quy_ability2','vua_quy_ability3','vua_quy_hit','vua_quy_victory',\n                'goku_idle','goku_walk','goku_jump','goku_ability1','goku_ability2','goku_ability3','goku_hit','goku_victory',\n                'shadow_garden_idle','shadow_garden_walk','shadow_garden_jump','shadow_garden_ability1','shadow_garden_ability2','shadow_garden_ability3','shadow_garden_hit','shadow_garden_victory',\n                'naruto_idle','naruto_walk','naruto_jump','naruto_ability1','naruto_ability2','naruto_ability3','naruto_ability4','naruto_hit','naruto_victory',\n                'yuji_idle','yuji_walk','yuji_jump','yuji_ability1','yuji_ability2','yuji_ability3','yuji_hit','yuji_victory','yuji_portrait',\n                'enel_idle','enel_walk','enel_jump','enel_ability1','enel_ability2','enel_ability3','enel_hit','enel_victory','enel_portrait',\n                'mahoraga_idle','mahoraga_walk','mahoraga_jump','mahoraga_ability1','mahoraga_ability2','mahoraga_ability3','mahoraga_ability4','mahoraga_hit','mahoraga_victory','mahoraga_portrait',\n                'tanjiro_idle','tanjiro_walk','tanjiro_jump','tanjiro_ability1','tanjiro_ability2','tanjiro_ability3','tanjiro_hit','tanjiro_victory','tanjiro_portrait',\n                'yuji_portrait',\n                'gojo_infinite_void',\n                'vua_quy_beach_idle','vua_quy_beach_walk','vua_quy_beach_jump','vua_quy_beach_ability1','vua_quy_beach_victory','vua_quy_beach_portrait','coconut_tree',\n                'shuriken_projectile','fireball_projectile','magatama_projectile','rasenshuriken_projectile','impact_effect','arena_background',\n                'map_one_piece', 'map_naruto_village', 'map_naruto_valley', 'map_cosmic_space',\n                'bat_bai_portrait','bong_dem_portrait','itachi_portrait','itachi_edo_portrait','luffy_portrait','madara_portrait','sasuke_portrait',\n                'sukuna_portrait','gojo_portrait','saitama_portrait','vua_quy_portrait','goku_portrait','shadow_garden_portrait','naruto_portrait','garp_portrait',\n                'ability1_icon_bat_bai','ability2_icon_bat_bai','ability3_icon_bat_bai',\n                'ability1_icon_bong_dem','ability2_icon_bong_dem','ability3_icon_bong_dem',\n                'ability1_icon_itachi','ability2_icon_itachi','ability3_icon_itachi',\n                'ability1_icon_luffy','ability2_icon_luffy','ability3_icon_luffy',\n                'ability1_icon_madara','ability2_icon_madara','ability3_icon_madara',\n                'ability1_icon_sasuke','ability2_icon_sasuke','ability3_icon_sasuke',\n                'ability1_icon_sukuna','ability2_icon_sukuna','ability3_icon_sukuna',\n                'ability1_icon_gojo','ability2_icon_gojo','ability3_icon_gojo',\n                'ability1_icon_saitama','ability2_icon_saitama','ability3_icon_saitama',\n                'ability1_icon_vua_quy','ability2_icon_vua_quy','ability3_icon_vua_quy',\n                'ability1_icon_goku','ability2_icon_goku','ability3_icon_goku',\n                'ability1_icon_shadow_garden','ability2_icon_shadow_garden','ability3_icon_shadow_garden',\n                'ability1_icon_naruto','ability2_icon_naruto','ability3_icon_naruto','ability4_icon_naruto',\n                'ability1_icon_enel','ability2_icon_enel','ability3_icon_enel','ability4_icon_enel',\n                'ability1_icon_tanjiro','ability2_icon_tanjiro','ability3_icon_tanjiro','ability4_icon_tanjiro',\n                'ability1_icon_yuji','ability2_icon_yuji','ability3_icon_yuji','ability4_icon_yuji',\n                'garp_idle','garp_walk','garp_jump','garp_hit','garp_victory','garp_ability1','garp_ability2','garp_ability3','garp_ability4',\n                'ability1_icon_garp','ability2_icon_garp','ability3_icon_garp','ability4_icon_garp',\n                'ability4_icon_sukuna',\n                'doraemon_idle','doraemon_walk','doraemon_jump','doraemon_hit','doraemon_victory','doraemon_ability1','doraemon_ability2','doraemon_portrait','doraemon_vietnam_idle','doraemon_vietnam_walk','doraemon_vietnam_jump','doraemon_vietnam_hit','doraemon_vietnam_victory','doraemon_vietnam_ability1','doraemon_vietnam_ability2','doraemon_vietnam_portrait','doraemon_vietnam_flag_reference','doraemon_vietnam_dragon_reference','1000000879.webp',\n                'ability1_icon_doraemon','ability2_icon_doraemon','ability3_icon_doraemon','ability4_icon_doraemon',\n                'chaien_summon','nobita_summon',\n                'po_panda_idle','po_panda_walk','po_panda_jump','po_panda_ability1','po_panda_ability2','po_panda_ability3','po_panda_hit','po_panda_victory','po_panda_portrait',\n                'ability1_icon_po_panda','ability2_icon_po_panda','ability3_icon_po_panda','ability4_icon_po_panda',\n                'po_dragon_skin', 'madara_susanoo_perfect', 'goku_ssj2', 'goku_hair_ssj',\n                'hashirama_idle','hashirama_walk','hashirama_jump','hashirama_ability1','hashirama_ability2','hashirama_ability3','hashirama_hit','hashirama_victory','hashirama_portrait',\n                'ability1_icon_hashirama','ability2_icon_hashirama','ability3_icon_hashirama','wood_dragon_projectile','hashirama_ult_statue','hashirama_ult_fists','hashirama_tree_effect','hashirama_pillar_fist',\n                'main_menu_bg', 'lobby_background_v2', 'lobby_background_v3',\n                'zoro_wano_idle','zoro_wano_walk','zoro_wano_jump','zoro_wano_ability1','zoro_wano_ability2','zoro_wano_ability3','zoro_wano_ability4','zoro_wano_hit','zoro_wano_victory','zoro_wano_portrait',\n                'naruto_luc_dao_portrait', 'naruto_luc_dao_ability4', 'naruto_kurama_asura',\n                'luffy_nika_portrait', 'luffy_gear2', 'luffy_gear4_portrait', 'luffy_gear4_sprite'\n            ];\n        const audioIds = [\n            'punch_sfx','shield_activate_sfx','dash_sfx','shuriken_throw_sfx','fireball_sfx','crow_sfx','susanoo_sfx','chidori_sfx','kamehameha_sfx',\n            'combo_attack_sfx','hit_damage_sfx','victory_sfx','defeat_sfx',\n            'menu_music','combat_music','atomic_sfx','rasengan_sfx','naruto_transform_sfx','black_flash_sfx','sword_slash_sfx','rika_sfx'\n        ];\n\n        async function preloadAll(onProgress) {\n            let loadedCount = 0;\n            const totalCount = assetIds.length + audioIds.length;\n            \n            const itemLoaded = () => {\n                loadedCount++;\n                if (onProgress) onProgress(loadedCount / totalCount);\n            };\n\n            // Load images\n            const imgPromises = assetIds.map(id => {\n                return new Promise((resolve) => {\n                    const info = lib.getAsset(id);\n                    if (info && info.url) {\n                        const img = new Image();\n                        img.crossOrigin = 'anonymous';\n                        img.onload = () => { imageCache[id] = img; itemLoaded(); resolve(); };\n                        img.onerror = () => { itemLoaded(); resolve(); };\n                        img.src = info.url;\n                    } else { itemLoaded(); resolve(); }\n                });\n            });\n\n            // Load audio\n            const audioPromises = audioIds.map(id => {\n                return new Promise((resolve) => {\n                    const info = lib.getAsset(id);\n                    if (info && info.url) {\n                        fetch(info.url)\n                            .then(r => r.arrayBuffer())\n                            .then(buf => getAudioCtx().decodeAudioData(buf))\n                            .then(decoded => { audioBuffers[id] = decoded; itemLoaded(); resolve(); })\n                            .catch(() => { itemLoaded(); resolve(); });\n                    } else { itemLoaded(); resolve(); }\n                });\n            });\n\n            await Promise.all([...imgPromises, ...audioPromises]);\n        }\n\n        await preloadAll(updateLoading);\n        \n        // Brief pause for visual smoothness\n        await new Promise(r => setTimeout(r, 300));\n        loadingScreen.style.opacity = '0';\n        setTimeout(() => loadingScreen.remove(), 500);\n\n        // Player Progress State - Initialize with defaults FIRST\n        let playerProgress = {\n            diamonds: 4000,\n            exchangeTickets: 0,\n            unlockedCharacters: [\n                'batBai', 'bongDem', 'itachi', 'madara', 'sasuke', 'luffy', 'sukuna', 'gojo',\n                'saitama', 'vuaQuy', 'goku', 'naruto', 'enel', 'tanjiro', 'yuji', 'garp',\n                'obito', 'hashirama', 'doraemon', 'poPanda', 'shadowGarden', 'zoro', 'yuta', 'rimuru'\n            ],\n            unlockedStages: 1,\n            unlockedSkins: {\n                vuaQuy: ['default'],\n                batBai: ['default'],\n                bongDem: ['default'],\n                itachi: ['default'],\n                madara: ['default'],\n                sasuke: ['default'],\n                luffy: ['default'],\n                sukuna: ['default'],\n                gojo: ['default'],\n                saitama: ['default'],\n                goku: ['default'],\n                naruto: ['default'],\n                enel: ['default'],\n                tanjiro: ['default'],\n                yuji: ['default'],\n                garp: ['default'],\n                obito: ['default'],\n                hashirama: ['default'],\n                doraemon: ['default'],\n                poPanda: ['default'],\n                shadowGarden: ['default'],\n                zoro: ['default'],\n                rimuru: ['default']\n            },\n            redeemedCodes: [],\n            // Version marker prevents legacy starter ownership from returning while\n            // preserving skins that players unlock after this migration.\n            skinOwnershipMigrationVersion: 1\n        };\n\n        // Load player progress from persistent storage AFTER initializing defaults\n        await loadPlayerProgress();\n\n        const gameStages = [\n            { id: 1, opponent: 'batBai', map: 'map_cosmic_space', name: 'Kh\u1edfi \u0110\u1ea7u' },\n            { id: 2, opponent: 'bongDem', map: 'map_cosmic_space', name: 'B\u00f3ng T\u1ed1i Tr\u1ed7i D\u1eady' },\n            { id: 3, opponent: 'tanjiro', map: 'map_cosmic_space', name: 'S\u00e1t Qu\u1ef7 Nh\u00e2n' },\n            { id: 4, opponent: 'yuji', map: 'map_cosmic_space', name: 'V\u1eadt Ch\u1ee7 Sukuna' },\n            { id: 5, opponent: 'itachi', map: 'map_cosmic_space', name: '\u1ea2o Thu\u1eadt Gia' },\n            { id: 6, opponent: 'sasuke', map: 'map_cosmic_space', name: 'T\u1ed9c Uchiha' },\n            { id: 7, opponent: 'naruto', map: 'map_cosmic_space', name: 'C\u1eedu V\u0129' },\n            { id: 8, opponent: 'obito', map: 'map_cosmic_space', name: 'M\u1eb7t N\u1ea1 B\u00ed \u1ea8n' },\n            { id: 9, opponent: 'hashirama', map: 'map_cosmic_space', name: 'Vua Nh\u1eabn Gi\u1ea3' },\n            { id: 10, opponent: 'madara', map: 'map_cosmic_space', name: 'Chi\u1ebfn Th\u1ea7n Uchiha' },\n            { id: 11, opponent: 'luffy', map: 'map_cosmic_space', name: 'Vua H\u1ea3i T\u1eb7c' },\n            { id: 12, opponent: 'zoro', map: 'map_cosmic_space', name: 'Tam Ki\u1ebfm Ph\u00e1i' },\n            { id: 13, opponent: 'garp', map: 'map_cosmic_space', name: 'Anh H\u00f9ng H\u1ea3i Qu\u00e2n' },\n            { id: 14, opponent: 'enel', map: 'map_cosmic_space', name: 'Ch\u00faa Tr\u1eddi Skypeia' },\n            { id: 15, opponent: 'sukuna', map: 'map_cosmic_space', name: 'Ng\u1ef1 \u0110\u1ed9c T\u1eed' },\n            { id: 16, opponent: 'gojo', map: 'map_cosmic_space', name: 'V\u00f4 H\u1ea1n' },\n            { id: 17, opponent: 'saitama', map: 'map_cosmic_space', name: 'Th\u00e1nh Ph\u1ed3ng' },\n            { id: 18, opponent: 'goku', map: 'map_cosmic_space', name: 'Si\u00eau Saiyan' },\n            { id: 19, opponent: 'vuaQuy', map: 'map_cosmic_space', name: 'Ma V\u01b0\u01a1ng' },\n            { id: 19, opponent: 'shadowGarden', map: 'map_cosmic_space', name: 'Ch\u00faa T\u1ec3 B\u00f3ng T\u1ed1i' },\n            { id: 20, opponent: 'rimuru', map: 'map_cosmic_space', name: 'Rimuru Th\u1ea7n T\u01b0\u01a1i M\u1edbi' }\n        ];\n\n        // Load player progress from persistent storage\n        async function loadPlayerProgress() {\n            try {\n                const response = await lib.getUserGameState();\n                if (response.state) {\n                    // Deep merge for nested objects like unlockedSkins\n                    playerProgress.diamonds = response.state.diamonds ?? playerProgress.diamonds;\n                    playerProgress.exchangeTickets = response.state.exchangeTickets ?? playerProgress.exchangeTickets;\n                    playerProgress.unlockedStages = response.state.unlockedStages ?? playerProgress.unlockedStages;\n                    \n                    if (response.state.unlockedCharacters) {\n                        playerProgress.unlockedCharacters = response.state.unlockedCharacters;\n                    }\n                    \n                    // Deep merge unlockedSkins to preserve default skins while adding unlocked ones\n                    if (response.state.unlockedSkins) {\n                        // Merge saved skins with creator-provided defaults so newly added skins remain selectable.\n                        const mergedSkins = { ...playerProgress.unlockedSkins };\n                        Object.entries(response.state.unlockedSkins).forEach(([charId, skins]) => {\n                            mergedSkins[charId] = Array.from(new Set([...(mergedSkins[charId] || []), ...(Array.isArray(skins) ? skins : [])]));\n                        });\n                        playerProgress.unlockedSkins = mergedSkins;\n                    }\n\n                    if (Array.isArray(response.state.redeemedCodes)) {\n                        playerProgress.redeemedCodes = Array.from(new Set([\n                            ...playerProgress.redeemedCodes,\n                            ...response.state.redeemedCodes.filter(code => typeof code === 'string')\n                        ]));\n                    }\n\n                    // One-time migration: these two skins used to be incorrectly\n                    // granted as starter skins. Remove them from legacy saves, but\n                    // keep them permanently once a player unlocks them afterward.\n                    if (response.state.skinOwnershipMigrationVersion !== 1) {\n                        playerProgress.unlockedSkins.itachi = (playerProgress.unlockedSkins.itachi || ['default']).filter(skin => skin !== 'edo');\n                        playerProgress.unlockedSkins.doraemon = (playerProgress.unlockedSkins.doraemon || ['default']).filter(skin => skin !== 'vietnam');\n                        playerProgress.skinOwnershipMigrationVersion = 1;\n                        await savePlayerProgress();\n                    }\n                    \n                    lib.log('Player progress loaded successfully');\n                } else {\n                    lib.log('No saved progress found, using defaults');\n                }\n            } catch (error) {\n                lib.log(`Failed to load progress: ${error.message}`);\n            }\n        }\n\n        // Save player progress to persistent storage\n        async function savePlayerProgress() {\n            try {\n                await lib.saveUserGameState(playerProgress);\n                lib.log('Player progress saved successfully');\n            } catch (error) {\n                lib.log(`Failed to save progress: ${error.message}`);\n            }\n        }\n\n        // Helper functions for currency management\n        function addDiamonds(amount) {\n            playerProgress.diamonds += amount;\n            savePlayerProgress();\n        }\n\n        function spendDiamonds(amount) {\n            if (playerProgress.diamonds >= amount) {\n                playerProgress.diamonds -= amount;\n                savePlayerProgress();\n                return true;\n            }\n            return false;\n        }\n\n        // Helper functions for unlocking content\n        function unlockCharacter(charId) {\n            if (!playerProgress.unlockedCharacters.includes(charId)) {\n                playerProgress.unlockedCharacters.push(charId);\n                savePlayerProgress();\n                return true;\n            }\n            return false;\n        }\n\n        function unlockSkin(charId, skinId) {\n            if (!playerProgress.unlockedSkins[charId]) {\n                playerProgress.unlockedSkins[charId] = ['default'];\n            }\n            if (!playerProgress.unlockedSkins[charId].includes(skinId)) {\n                playerProgress.unlockedSkins[charId].push(skinId);\n                savePlayerProgress();\n                return true;\n            }\n            return false;\n        }\n\n        function isCharacterUnlocked(charId) {\n            return true; // All characters are free\n        }\n\n        function isSkinUnlocked(charId, skinId) {\n            return playerProgress.unlockedSkins[charId]?.includes(skinId) || false;\n        }\n\n        // Show game parameters\n        lib.showGameParameters({\n            name: 'Ng\u01b0\u1eddi Que \u0110\u1ed1i Kh\u00e1ng',\n            params: {\n                'B\u1ea5t B\u1ea1i HP': { key: 'characters.batBai.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'B\u00f3ng \u0110\u00eam HP': { key: 'characters.bongDem.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'ITACHI HP': { key: 'characters.itachi.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Sasuke HP': { key: 'characters.sasuke.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Sukuna HP': { key: 'characters.sukuna.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Gojo HP': { key: 'characters.gojo.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Madara HP': { key: 'characters.madara.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Goku HP': { key: 'characters.goku.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Shadow HP': { key: 'characters.shadowGarden.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Naruto HP': { key: 'characters.naruto.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Tanjiro HP': { key: 'characters.tanjiro.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Yuji HP': { key: 'characters.yuji.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Garp HP': { key: 'characters.garp.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Obito HP': { key: 'characters.obito.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Yuta HP': { key: 'characters.yuta.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Hashirama HP': { key: 'characters.hashirama.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Zoro HP': { key: 'characters.zoro.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Doraemon HP': { key: 'characters.doraemon.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Enel HP': { key: 'characters.enel.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Luffy HP': { key: 'characters.luffy.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Saitama HP': { key: 'characters.saitama.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Vua Qu\u1ef7 HP': { key: 'characters.vuaQuy.health', type: 'slider', min: 100, max: 2000, step: 10 },\n                'Rimuru HP': { key: 'characters.rimuru.health', type: 'slider', min: 100, max: 2500, step: 10 },\n                'Round Time (s)': { key: 'settings.roundTime', type: 'slider', min: 30, max: 180, step: 10 },\n                'Boss HP': { key: 'settings.bossHP', type: 'slider', min: 500, max: 5000, step: 100 },\n                'AI Difficulty': { key: 'settings.aiDifficulty', type: 'dropdown', options: [\n                    { label: 'Easy', value: 'easy' },\n                    { label: 'Medium', value: 'medium' },\n                    { label: 'Hard', value: 'hard' }\n                ]}\n            }\n        });\n\n        function isFighterPlayerSide(fighter) {\n            if (!fighter) return false;\n            if (fighter.owner) return isFighterPlayerSide(fighter.owner);\n            return fighter === player || allies.includes(fighter);\n        }\n\n        function getEnemies(fighter) {\n            const fighterIsPlayer = isFighterPlayerSide(fighter);\n            const enemies = [];\n            if (fighterIsPlayer) {\n                if (opponent && opponent.health > 0) enemies.push(opponent);\n            } else {\n                if (player && player.health > 0) enemies.push(player);\n            }\n            if (!fighterIsPlayer) {\n                allies.forEach(a => { if (a.health > 0) enemies.push(a); });\n            }\n            summons.forEach(s => {\n                if (s.health > 0) {\n                    const summonIsPlayerSide = isFighterPlayerSide(s);\n                    if (summonIsPlayerSide !== fighterIsPlayer) {\n                        enemies.push(s);\n                    }\n                }\n            });\n            return enemies;\n        }\n\n        function hitEnemiesInRange(fighter, range, damage, knockback = 0, lift = 0) {\n            const enemies = getEnemies(fighter);\n            let hitAny = false;\n            for (const enemy of enemies) {\n                if (enemy.invulnerable) continue;\n                const dist = Math.abs(fighter.x - enemy.x);\n                // Simple horizontal range check for most melee/aoe\n                if (dist < range) {\n                    dealDamage(enemy, damage, fighter);\n                    if (knockback !== 0 || lift !== 0) {\n                        const dir = enemy.x > fighter.x ? 1 : -1;\n                        enemy.vx = dir * knockback;\n                        enemy.vy = -lift;\n                        enemy.grounded = false;\n                    }\n                    hitAny = true;\n                }\n            }\n            return hitAny;\n        }\n\n        // Game state\n        const GROUND_Y = 920;\n        const GRAVITY = 0.6;\n        const ARENA_LEFT = 30;\n        const ARENA_RIGHT = 690;\n\n        let gameState = 'menu'; // menu, charSelect, mapSelect, countdown, combat, result, shop\n        let selectedPlayerChar = null;\n        let selectedOpponentChar = null;\n        let selectedPlayerSkin = 'default';\n        let selectedOpponentSkin = 'default';\n        let selectedMap = 'arena_background';\n        let isStageMode = false;\n        let currentStageId = 1;\n        let selectionStep = 0; // 0: Player, 1: Opponent\n        let selectionSubStep = 'char'; // 'char' or 'skin'\n        \n        // Custom modal system for confirmations and alerts\n        function showModal(message, options = {}) {\n            const isConfirm = options.isConfirm || false;\n            const onConfirm = options.onConfirm || (() => {});\n            const onCancel = options.onCancel || (() => {});\n\n            const modalOverlay = document.createElement('div');\n            modalOverlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:1000;display:flex;align-items:center;justify-content:center;';\n            \n            const modalContent = document.createElement('div');\n            modalContent.style.cssText = 'background:linear-gradient(135deg,rgba(26,26,46,0.98),rgba(22,33,62,0.98));border:2px solid rgba(255,255,255,0.3);border-radius:16px;padding:32px;max-width:400px;text-align:center;';\n            \n            modalContent.innerHTML = `\n                <div style=\"font-family:'Bebas Neue';font-size:24px;color:#fff;margin-bottom:24px;line-height:1.4;\">${message}</div>\n                <div style=\"display:flex;gap:16px;justify-content:center;\">\n                    ${isConfirm ? `\n                        <div class=\"btn\" id=\"modal-confirm\" style=\"min-width:120px;font-size:20px;padding:12px 24px;\">X\u00c1C NH\u1eacN</div>\n                        <div class=\"btn\" id=\"modal-cancel\" style=\"min-width:120px;font-size:20px;padding:12px 24px;background:rgba(244,67,54,0.3);border-color:#F44336;\">H\u1ee6Y</div>\n                    ` : `\n                        <div class=\"btn\" id=\"modal-ok\" style=\"min-width:120px;font-size:20px;padding:12px 24px;\">OK</div>\n                    `}\n                </div>\n            `;\n            \n            modalOverlay.appendChild(modalContent);\n            document.body.appendChild(modalOverlay);\n\n            if (isConfirm) {\n                document.getElementById('modal-confirm').onclick = () => {\n                    document.body.removeChild(modalOverlay);\n                    onConfirm();\n                };\n                document.getElementById('modal-cancel').onclick = () => {\n                    document.body.removeChild(modalOverlay);\n                    onCancel();\n                };\n            } else {\n                document.getElementById('modal-ok').onclick = () => {\n                    document.body.removeChild(modalOverlay);\n                };\n            }\n        }\n\n        const gameMaps = [\n            { id: 'arena_background', name: '\u0110\u1ea5u Tr\u01b0\u1eddng C\u01a1 B\u1ea3n', icon: 'arena_background' },\n            { id: 'map_one_piece', name: '\u0110\u1ea3o H\u1ea3i T\u1eb7c', icon: 'map_one_piece' },\n            { id: 'map_naruto_village', name: 'L\u00e0ng L\u00e1', icon: 'map_naruto_village' },\n            { id: 'map_naruto_valley', name: 'Thung L\u0169ng T\u1eadn C\u00f9ng', icon: 'map_naruto_valley' },\n            { id: 'map_cosmic_space', name: 'Kh\u00f4ng Gian V\u0169 Tr\u1ee5', icon: 'map_cosmic_space' }\n        ];\n        \n        const charSkins = {\n            vuaQuy: [\n                { id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh', portrait: 'vua_quy_portrait' },\n                { id: 'beach', name: 'B\u00e3i bi\u1ec3n', portrait: 'vua_quy_beach_portrait' }\n            ],\n            zoro: [\n                { id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh', portrait: 'zoro_portrait' },\n                { id: 'wano', name: 'Wano Country', portrait: 'zoro_wano_portrait' }\n            ],\n            itachi: [\n                { id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh', portrait: 'itachi_portrait' },\n                { id: 'edo', name: 'Itachi Edo', portrait: 'itachi_edo_portrait' }\n            ],\n            naruto: [\n                { id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh', portrait: 'naruto_portrait' },\n                { id: 'lucDao', name: 'L\u1ee5c \u0110\u1ea1o', portrait: 'naruto_luc_dao_portrait' }\n            ],\n            luffy: [\n                { id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh', portrait: 'luffy_portrait' },\n                { id: 'nika', name: 'Luffy Nika', portrait: 'luffy_nika_portrait' },\n                { id: 'gear4', name: 'Luffy Gear 4', portrait: 'luffy_gear4_portrait' }\n            ],\n            doraemon: [\n                { id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh', portrait: 'doraemon_portrait' },\n                { id: 'vietnam', name: 'Doraemon Vi\u1ec7t Nam', portrait: 'doraemon_vietnam_portrait' }\n            ]\n        };\n        let isBossMode = false;\n\n        // Boss mode fights against curated character skins instead of base-form bosses.\n        // These skins are available as boss opponents regardless of the player's unlocks.\n        const bossSkinRoster = [\n            { charId: 'itachi', skinId: 'edo', name: 'ITACHI EDO', portrait: 'itachi_edo_portrait', color: '#FF4444' },\n            { charId: 'vuaQuy', skinId: 'beach', name: 'VUA QU\u1ef6 B\u00c3I BI\u1ec2N', portrait: 'vua_quy_beach_portrait', color: '#00BFFF' },\n            { charId: 'zoro', skinId: 'wano', name: 'ZORO WANO', portrait: 'zoro_wano_portrait', color: '#32CD32' },\n            { charId: 'naruto', skinId: 'lucDao', name: 'NARUTO L\u1ee4C \u0110\u1ea0O', portrait: 'naruto_luc_dao_portrait', color: '#FFD700' },\n            { charId: 'luffy', skinId: 'nika', name: 'LUFFY NIKA', portrait: 'luffy_nika_portrait', color: '#FFFFFF' },\n            { charId: 'luffy', skinId: 'gear4', name: 'LUFFY GEAR 4', portrait: 'luffy_gear4_portrait', color: '#FF4444' },\n            { charId: 'doraemon', skinId: 'vietnam', name: 'DORAEMON VI\u1ec6T NAM', portrait: 'doraemon_vietnam_portrait', color: '#E21B23' }\n        ];\n\n        let player = null;\n        let opponent = null;\n        let allies = [];\n        let summons = [];\n        let projectiles = [];\n        let effects = [];\n        let damageNumbers = [];\n        let countdownTimer = 0;\n        let countdownText = '';\n        let matchTimer = 0;\n        let resultText = '';\n        let resultColor = '#fff';\n        let currentMusic = null;\n        let screenShake = 0;\n        let lastTime = 0;\n\n        // Input state\n        const keys = {};\n        let joystickActive = false;\n        let joystickX = 0;\n        let joystickY = 0;\n        let joystickBaseX = 0;\n        let joystickBaseY = 0;\n        let joystickTouchId = null;\n        let abilityPressed = [false, false, false, false];\n        let abilityHeld = [false, false, false, false];\n        let awakenPressed = false;\n\n        // Character factory\n        function createFighter(charType, x, facingRight, isAI, isBoss = false, skin = 'default') {\n            const charConfigs = {\n                batBai: config.characters.batBai,\n                bongDem: config.characters.bongDem,\n                itachi: config.characters.itachi || { health: 1500 },\n                madara: config.characters.madara || { health: 1500 },\n                sasuke: config.characters.sasuke || { health: 1500 },\n                luffy: config.characters.luffy || { health: 1500 },\n                enel: config.characters.enel || { health: 1400 },\n                tanjiro: config.characters.tanjiro || { health: 1500 },\n                sukuna: config.characters.sukuna || { health: 1100 },\n                gojo: config.characters.gojo || { health: 1500 },\n                saitama: config.characters.saitama || { health: 1500 },\n                vuaQuy: config.characters.vuaQuy || { health: 1500 },\n                goku: config.characters.goku || { health: 1500 },\n                naruto: config.characters.naruto || { health: 1500 },\n                garp: config.characters.garp || { health: 1800 },\n                obito: config.characters.obito || { health: 1600 },\n                poPanda: config.characters.poPanda || { health: 1700 },\n                yuji: config.characters.yuji || { health: 1500 },\n                hashirama: config.characters.hashirama || { health: 1800 },\n                doraemon: config.characters.doraemon || { health: 1500 },\n                shadowGarden: config.characters.shadowGarden || { health: 1500 },\n                zoro: config.characters.zoro || { health: 1500 },\n                yuta: config.characters.yuta || { health: 1500 },\n                rimuru: config.characters.rimuru || { health: 1800 },\n                mahoraga: { health: 500 },\n                chaien: { health: 500 },\n                nobita: { health: 500 }\n            };\n            const charConfig = charConfigs[charType] || { health: 1500 };\n            \n            let baseSpeed = 4;\n            let baseJump = 16;\n            if (charType === 'batBai') { baseSpeed = 3; baseJump = 14; }\n            if (charType === 'bongDem') { baseSpeed = 5; baseJump = 18; }\n            if (charType === 'itachi') {\n                // Itachi Edo moves with a controlled, grounded step instead of the\n                // faster base-Itachi pace.  The skin still uses the same combat\n                // physics, but feels heavier and more deliberate.\n                baseSpeed = skin === 'edo' ? 3.8 : 4.5;\n                baseJump = skin === 'edo' ? 16 : 17;\n            }\n            if (charType === 'madara') { baseSpeed = 4.2; baseJump = 16; }\n            if (charType === 'sasuke') { baseSpeed = 5.2; baseJump = 17; }\n            if (charType === 'luffy') { baseSpeed = 4.2; baseJump = 19; }\n            if (charType === 'sukuna') { baseSpeed = 4.2; baseJump = 16.5; }\n            if (charType === 'gojo') { baseSpeed = 5.0; baseJump = 18; }\n            if (charType === 'saitama') { baseSpeed = 6.0; baseJump = 20; }\n            if (charType === 'vuaQuy') { baseSpeed = 4.5; baseJump = 18; }\n            if (charType === 'goku') { baseSpeed = 5.5; baseJump = 19; }\n            if (charType === 'naruto') { baseSpeed = 5.4; baseJump = 18.5; }\n            if (charType === 'garp') { baseSpeed = 4.5; baseJump = 19.0; }\n            if (charType === 'obito') { baseSpeed = 5.0; baseJump = 18.0; }\n            if (charType === 'poPanda') { baseSpeed = 4.0; baseJump = 15.0; }\n            if (charType === 'yuji') { baseSpeed = 5.0; baseJump = 18.0; }\n            if (charType === 'enel') { baseSpeed = 5.5; baseJump = 18; }\n            if (charType === 'hashirama') { baseSpeed = 4.5; baseJump = 17; }\n            if (charType === 'tanjiro') { baseSpeed = 4.8; baseJump = 17.5; }\n            if (charType === 'shadowGarden') { baseSpeed = 5.2; baseJump = 18.5; }\n            if (charType === 'zoro') { baseSpeed = 4.8; baseJump = 17.0; }\n            if (charType === 'yuta') { baseSpeed = 5.0; baseJump = 17.5; }\n            if (charType === 'doraemon') { baseSpeed = 4.5; baseJump = 16.0; }\n            if (charType === 'rimuru') { baseSpeed = 5.3; baseJump = 18.5; }\n            if (charType === 'mahoraga') { baseSpeed = 4.0; baseJump = 15; }\n            if (charType === 'chaien') { baseSpeed = 0; baseJump = 0; }\n            if (charType === 'nobita') { baseSpeed = 0; baseJump = 0; }\n\n            const baseHealth = isBoss ? (config.settings.bossHP || 1500) : (charType === 'mahoraga' ? 500 : charConfig.health);\n\n            const abilities = {\n                batBai: [\n                    { name: 'T\u0103ng C\u01b0\u1eddng Ph\u00f2ng Th\u1ee7', cooldown: 5, currentCd: 0, duration: 4, active: false, activeTimer: 0 },\n                    { name: 'Khi\u00ean Th\u00e9p', cooldown: 6, currentCd: 0, duration: 3, active: false, activeTimer: 0, shieldHit: false },\n                    { name: 'C\u00fa \u0110\u1ea5m \u0110\u1ea9y L\u00f9i', cooldown: 8, currentCd: 0, range: 80, damage: 50 },\n                    { name: 'Thi\u00ean Khi\u00ean H\u1ee7y Di\u1ec7t', cooldown: 20, currentCd: 0, damage: 200 }\n                ],\n                bongDem: [\n                    { name: 'Phi Ti\u00eau B\u00f3ng T\u1ed1i', cooldown: 3, currentCd: 0, damage: 15 },\n                    { name: 'L\u01b0\u1edbt \u1ea2nh', cooldown: 4, currentCd: 0, distance: 300, invulnTimer: 0 },\n                    { name: 'Li\u00ean Ho\u00e0n \u00c1m S\u00e1t', cooldown: 10, currentCd: 0, range: 70, damage: 8, hits: 4, hitCount: 0, hitTimer: 0 },\n                    { name: 'L\u00e3nh \u0110\u1ecba B\u00f3ng \u0110\u00eam', cooldown: 20, currentCd: 0, damage: 20, duration: 7, active: false, activeTimer: 0 }\n                ],\n                vuaQuy: [\n                    { name: 'Vu\u1ed1t Qu\u1ef7', cooldown: 3, currentCd: 0, damage: 30, range: 120 },\n                    { name: 'H\u1ecfa Ng\u1ee5c', cooldown: 5, currentCd: 0, damage: 35 },\n                    { name: 'C\u1ed9t L\u1eeda H\u1ecfa Ng\u1ee5c', cooldown: 15, currentCd: 0, damage: 25 },\n                    { name: 'L\u00e3nh \u0110\u1ecba \u0110\u1ecba Ng\u1ee5c', cooldown: 25, currentCd: 0, damage: 40, duration: 7, active: false, activeTimer: 0 }\n                ],\n                madara: [\n                    { name: 'Thi\u00ean Ng\u1ea1i Ch\u1ea5n Tinh', cooldown: 12, currentCd: 0, damage: 45 },\n                    { name: 'H\u00e0o H\u1ecfa Di\u1ec7t', cooldown: 8, currentCd: 0, damage: 35, duration: 1.5, active: false, activeTimer: 0 },\n                    { name: 'Yasaka Magatama', cooldown: 4, currentCd: 0, damage: 20 },\n                    { name: 'Susanoo To\u00e0n Ch\u00e2n Th\u1ec3', cooldown: 25, currentCd: 0, damage: 60, duration: 7, active: false, activeTimer: 0 }\n                ],\n                sasuke: [\n                    { name: 'L\u00f4i Long Thi\u00ean Ph\u1ea1t', cooldown: 12, currentCd: 0, damage: 100, active: false, activeTimer: 0, strikeX: 0, strikeY: 0 },\n                    { name: 'H\u00e0o H\u1ecfa C\u1ea7u', cooldown: 4, currentCd: 0, damage: 25 },\n                    { name: 'Susanoo Strike', cooldown: 8, currentCd: 0, damage: 40, active: false, activeTimer: 0 },\n                    { name: '\u0110\u1ecba T\u0103ng Thi\u00ean Tinh', cooldown: 25, currentCd: 0, damage: 55, duration: 6, active: false, activeTimer: 0, sphereX: 360, sphereY: 300, particles: [] }\n                ],\n                itachi: [\n                    { name: 'H\u1ecfa \u0110\u1ed9n: H\u00e0o H\u1ecfa C\u1ea7u', cooldown: 3, currentCd: 0, damage: 25 },\n                    { name: '\u1ea2o Thu\u1eadt: Kh\u00f4ng Gian \u0110en', cooldown: 8, currentCd: 0, duration: 4, active: false, activeTimer: 0, damage: 15, susanooSlashDamage: 65, susanooExplosionDamage: 95, slashRange: 280 },\n                    { name: skin === 'edo' ? 'Susanoo: Sharingan H\u00fat Xo\u00e1y' : 'Tsukuyomi', cooldown: 12, currentCd: 0, range: 400, stunDuration: 2, damage: 10, explosionDamage: 80, vortexDuration: 5, pullRadius: 360, orbitRadius: 110 },\n                    { name: skin === 'edo' ? 'Susanoo Edo' : 'M\u1eb7t Tr\u0103ng M\u00e1u', cooldown: skin === 'edo' ? 25 : 15, currentCd: 0, damage: 30, duration: 17, active: false, activeTimer: 0 }\n                ],\n                luffy: [\n                    { name: 'Gomu Gomu no Pistol', cooldown: 3, currentCd: 0, damage: 15, range: 230 },\n                    { name: 'Gomu Gomu no Rocket', cooldown: 5, currentCd: 0, distance: 300, invulnTimer: 0.2 },\n                    { name: 'Gomu Gomu no Gatling', cooldown: 8, currentCd: 0, damage: 4, hits: 8, hitCount: 0, hitTimer: 0, range: 160 },\n                    { name: 'Tuy\u1ec7t K\u1ef9: C\u00fa \u0110\u1ea5m Kh\u1ed5ng L\u1ed3', cooldown: 25, currentCd: 0, damage: 120, active: false, activeTimer: 0 }\n                ],\n                sukuna: [\n                    { name: 'Dismantle', cooldown: 3.5, currentCd: 0, damage: 20, range: 200 },\n                    { name: 'Fuga (H\u1ecfa Ti\u1ec5n)', cooldown: 7, currentCd: 0, damage: 40 },\n                    { name: 'Malevolent Shrine', cooldown: 15, currentCd: 0, damage: 7, duration: 4, active: false, activeTimer: 0 },\n                    { name: 'Ch\u00e9m C\u1eaft Kh\u00f4ng Gian', cooldown: 15, currentCd: 0, damage: 40 }\n                ],\n                mahoraga: [\n                    { name: 'B\u00e1t Ch\u1ee7y Ki\u1ebfm', cooldown: 2, currentCd: 0, damage: 35, range: 150 },\n                    { name: '\u0110\u1eadp Ph\u00e1', cooldown: 3, currentCd: 0, damage: 40, range: 120 },\n                    { name: 'C\u00fa \u0110\u00e1 Uy L\u1ef1c', cooldown: 4, currentCd: 0, damage: 30, range: 140 },\n                    { name: 'V\u00f2ng Quay Th\u00edch Nghi', cooldown: 5, currentCd: 0, damage: 25, range: 250 }\n                ],\n                gojo: [\n                    { name: 'Cang (Blue)', cooldown: 4, currentCd: 0, damage: 20, range: 400 },\n                    { name: 'H\u00e1ch (Red)', cooldown: 6, currentCd: 0, damage: 35, range: 250 },\n                    { name: 'V\u00f4 H\u1ea1n Kh\u00f4ng (Domain)', cooldown: 18, currentCd: 0, damage: 15, duration: 4, active: false, activeTimer: 0 },\n                    { name: 'Hollow Purple (T\u1eed)', cooldown: 25, currentCd: 0, damage: 130, active: false, activeTimer: 0 }\n                ],\n                saitama: [\n                    { name: 'Normal Punch', cooldown: 1, currentCd: 0, damage: 25, range: 120 },\n                    { name: 'Consecutive Punches', cooldown: 5, currentCd: 0, damage: 8, hits: 10, hitCount: 0, hitTimer: 0, range: 150 },\n                    { name: 'Serious Punch', cooldown: 15, currentCd: 0, damage: 80, range: 400 },\n                    { name: 'S\u1ee9c M\u1ea1nh Tuy\u1ec7t \u0110\u1ed1i', cooldown: 25, currentCd: 0, duration: 6, active: false, activeTimer: 0, triggered: false, phase: 'idle' }\n                ],\n                goku: [\n                    { name: '\u0110\u1ea5m Li\u00ean Ho\u00e0n', cooldown: 3, currentCd: 0, damage: 8, hits: 6, hitCount: 0, hitTimer: 0, range: 150 },\n                    { name: 'D\u1ecbch Chuy\u1ec3n T\u1ee9c Th\u1eddi', cooldown: 5, currentCd: 0 },\n                    { name: 'Kamehameha', cooldown: 10, currentCd: 0, damage: 60, active: false, activeTimer: 0, charging: false },\n                    { name: 'Si\u00eau Saiyan 2', cooldown: 30, currentCd: 0, duration: 999999, active: true, activeTimer: 999999 }\n                ],\n                naruto: [\n                    { name: 'Rasengan', cooldown: 2.5, currentCd: 0, damage: 40, range: 180 },\n                    { name: 'Shadow Clone Strike', cooldown: 5, currentCd: 0, damage: 10, hits: 6, hitCount: 0, hitTimer: 0, range: 200 },\n                    { name: skin === 'lucDao' ? '\u0110\u1ea1i \u1ea2nh Ph\u00e2n Th\u00e2n' : 'Rasenshuriken', cooldown: 7, currentCd: 0, damage: 75 },\n                    { name: 'Nine-Tails Mode', cooldown: 35, currentCd: 0, duration: 14, active: false, activeTimer: 0, ultPhase: null }\n                ],\n                enel: [\n                    { name: 'L\u00f4i \u0110i\u1ec3u', cooldown: 3, currentCd: 0, damage: 25 },\n                    { name: 'L\u00f4i Th\u00fa', cooldown: 5, currentCd: 0, damage: 35 },\n                    { name: 'D\u1ecbch Chuy\u1ec3n \u0110i\u1ec7n', cooldown: 4, currentCd: 0, distance: 350, invulnTimer: 0 },\n                    { name: 'Raigo (C\u1ea7u S\u00e9t)', cooldown: 20, currentCd: 0, damage: 200, active: false, activeTimer: 0 }\n                ],\n                tanjiro: [\n                    { name: 'H\u01a1i Th\u1edf N\u01b0\u1edbc: Th\u1ee9c Th\u1ee9 2', cooldown: 4, currentCd: 0, damage: 20, range: 170 },\n                    { name: 'H\u01a1i Th\u1edf N\u01b0\u1edbc: Th\u1ee9c Th\u1ee9 6', cooldown: 6, currentCd: 0, damage: 30, range: 200 },\n                    { name: 'H\u01a1i Th\u1edf N\u01b0\u1edbc: Th\u1ee9c Th\u1ee9 10', cooldown: 10, currentCd: 0, damage: 40, range: 280, active: false, activeTimer: 0 },\n                    { name: '\u0110i\u1ec7u Nh\u1ea3y C\u1ee7a H\u1ecfa Th\u1ea7n', cooldown: 25, currentCd: 0, damage: 25, duration: 6, active: false, activeTimer: 0 }\n                ],\n                shadowGarden: [\n                    { name: 'Slime Slash', cooldown: 2.5, currentCd: 0, damage: 25, range: 180 },\n                    { name: 'Shadow Dash', cooldown: 4, currentCd: 0, distance: 350, invulnTimer: 0.3 },\n                    { name: 'Violet Burst', cooldown: 8, currentCd: 0, damage: 45, range: 300 },\n                    { name: 'I AM ATOMIC', cooldown: 25, currentCd: 0, damage: 200, active: false, activeTimer: 0 }\n                ],\n                yuji: [\n                    { name: 'K\u00ednh Loa Quy\u1ec1n', cooldown: 3, currentCd: 0, damage: 25, range: 150 },\n                    { name: 'Ph\u00f2ng Th\u1ee7 C\u1eadn Chi\u1ebfn', cooldown: 5, currentCd: 0, duration: 2, active: false, activeTimer: 0 },\n                    { name: 'Li\u00ean Ho\u00e0n C\u01b0\u1edbc', cooldown: 7, currentCd: 0, damage: 8, hits: 5, hitCount: 0, hitTimer: 0, range: 160 },\n                    { name: 'H\u1eafc Thi\u1ec3m (Black Flash)', cooldown: 10, currentCd: 0, damage: 50, active: false, activeTimer: 0, sequence: 'idle', targetFighter: null, punchCount: 0 }\n                ],\n                garp: [\n                    { name: 'C\u00fa \u0110\u1ea5m Y\u00eau Th\u01b0\u01a1ng', cooldown: 3, currentCd: 0, damage: 35, range: 140 },\n                    { name: 'N\u00e9m \u0110\u1ea1i B\u00e1c', cooldown: 5, currentCd: 0, damage: 40 },\n                    { name: 'Quy\u1ec1n N\u0103ng H\u1ea3i Qu\u00e2n', cooldown: 8, currentCd: 0, damage: 10, hits: 4, hitCount: 0, hitTimer: 0, range: 180 },\n                    { name: 'Galaxy Impact', cooldown: 25, currentCd: 0, damage: 15, duration: 6, active: false, activeTimer: 0, phase: 'idle' }\n                ],\n                obito: [\n                    { name: 'H\u1ecfa \u0110\u1ed9n: B\u1ea1o Phong Lo\u1ea1n V\u0169', cooldown: 4, currentCd: 0, damage: 35 },\n                    { name: 'Kamui', cooldown: 5, currentCd: 0, distance: 350, invulnTimer: 0.3 },\n                    { name: 'Tri\u1ec7u H\u1ed3i Th\u1ea7n Th\u1ee5: H\u1eafc H\u1ecfa Tr\u1ee5', cooldown: 12, currentCd: 0, damage: 60, active: false, activeTimer: 0, fired: false },\n                    { name: 'Ngo\u1ea1i \u0110\u1ea1o Ma T\u01b0\u1ee3ng: S\u1ea5m S\u00e9t', cooldown: 25, currentCd: 0, damage: 130, active: false, activeTimer: 0 }\n                ],\n                hashirama: [\n                    { name: 'M\u1ed9c Long Thu\u1eadt', cooldown: 4, currentCd: 0, damage: 30 },\n                    { name: 'M\u1ed9c Th\u1ee7 Gi\u00e1ng L\u00e2m', cooldown: 6, currentCd: 0, damage: 35, range: 400 },\n                    { name: 'M\u1ed9c \u0110\u1ed9n: Th\u1ebf Gi\u1edbi C\u00e2y Hoa', cooldown: 15, currentCd: 0, damage: 15, duration: 6, active: false, activeTimer: 0 },\n                    { name: 'Thi\u00ean Th\u1ee7 Quan \u00c2m', cooldown: 25, currentCd: 0, damage: 150, active: false, activeTimer: 0 }\n                ],\n                doraemon: [\n                    { name: 'B\u00e1nh R\u00e1n', cooldown: 3, currentCd: 0, damage: 20 },\n                    { name: '\u0110\u00e8n Pin Thu Nh\u1ecf', cooldown: 5, currentCd: 0, damage: 15, range: 400 },\n                    { name: skin === 'vietnam' ? 'L\u00e1 C\u1edd Vi\u1ec7t Nam' : 'Tri\u1ec7u h\u1ed3i Chaien', cooldown: 15, currentCd: 0, duration: 5, damage: 90 },\n                    { name: skin === 'vietnam' ? 'Long Th\u1ea7n Vi\u1ec7t Nam' : 'Tri\u1ec7u h\u1ed3i Nobita', cooldown: skin === 'vietnam' ? 25 : 20, currentCd: 0, duration: skin === 'vietnam' ? 7 : 5, damage: skin === 'vietnam' ? 10 : 8, explosionDamage: skin === 'vietnam' ? 140 : 0, orbitRadius: 190, orbitSpeed: 2.8, active: false, activeTimer: 0, phase: 'idle', captured: [], exploded: false }\n                ],\n                poPanda: [\n                    { name: 'C\u00fa \u0110\u1ea5m G\u1ea5u Tr\u00fac', cooldown: 2.5, currentCd: 0, damage: 25, range: 140 },\n                    { name: 'L\u0103n Tr\u00f2n', cooldown: 5, currentCd: 0, damage: 15, duration: 1.2, active: false, activeTimer: 0 },\n                    { name: 'V\u00f4 C\u1ef1c Ng\u00f3n Tay', cooldown: 15, currentCd: 0, damage: 100, range: 120, phase: 'idle', hitDone: false },\n                    { name: 'Long Th\u1ea7n B\u00e1t Qu\u00e1i', cooldown: 30, currentCd: 0, damage: 140, phase: 'idle', active: false, activeTimer: 0 }\n                ],\n                zoro: [\n                    { name: 'Tam Ki\u1ebfm Ph\u00e1i: Onigiri', cooldown: 3.5, currentCd: 0, damage: 35, range: 180 },\n                    { name: 'Phi\u00ean Thi\u00ean Ph\u01b0\u1ee3ng', cooldown: 5, currentCd: 0, damage: 45 },\n                    { name: 'Long Quy\u1ec3n Phong', cooldown: 12, currentCd: 0, damage: 10, range: 250, active: false, activeTimer: 0 },\n                    { name: 'C\u1eedu Ki\u1ebfm Ph\u00e1i: Ashura', cooldown: 25, currentCd: 0, damage: 3, duration: 8, active: false, activeTimer: 0, phase: 'idle' }\n                ],\n                yuta: [\n                    { name: 'Thanh Ki\u1ebfm Nguy\u1ec1n R\u1ee7a', cooldown: 3, currentCd: 0, damage: 25, range: 180 },\n                    { name: 'Ph\u1ea1n V\u0103n: Ch\u1ebft \u0110i', cooldown: 6, currentCd: 0, damage: 15, range: 400 },\n                    { name: 'H\u1eafc Thi\u1ec3m & C\u1ed9t \u00c1nh S\u00e1ng', cooldown: 10, currentCd: 0, damage: 70 },\n                    { name: 'Tri\u1ec7u H\u1ed3i Rika: T\u00ecnh Y\u00eau Thu\u1ea7n Khi\u1ebft', cooldown: 25, currentCd: 0, damage: 150, duration: 8, active: false, activeTimer: 0, phase: 'idle' }\n                ],\n                rimuru: [\n                    { name: 'B\u1ea1o Th\u1ef1c (Predation)', cooldown: 4, currentCd: 0, damage: 30, range: 150 },\n                    { name: 'Shuriken Nh\u1ea7y', cooldown: 5, currentCd: 0, damage: 20 },\n                    { name: 'H\u1eafc \u1ea4n C\u1ea7u', cooldown: 7, currentCd: 0, damage: 55 },\n                    { name: '\u0110\u1ea1i Hi\u1ec1n Gi\u1ea3: Ph\u00e2n Th\u00e2n H\u00e0ng Lo\u1ea1t', cooldown: 25, currentCd: 0, damage: 180, active: false, activeTimer: 0 }\n                ],\n                chaien: [],\n                nobita: []\n            };\n\n            return {\n                type: charType,\n                x, y: GROUND_Y,\n                vx: 0, vy: 0,\n                width: isBoss ? 100 : 70, height: isBoss ? 180 : 120,\n                facingRight,\n                isAI,\n                isBoss,\n                health: baseHealth,\n                maxHealth: baseHealth,\n                damageMultiplier: isBoss ? 1.2 : 1.0, // Boss deals 20% more damage (reduced from 50%)\n                energy: 0,\n                maxEnergy: 100,\n                speed: baseSpeed,\n                jumpForce: baseJump,\n                grounded: true,\n                state: 'idle', // idle, walk, jump, ability1, ability2, ability3, hit\n                stateTimer: 0,\n                stunTimer: 0,\n                // Bosses ignore every stun source so crowd-control cannot stop their AI or abilities.\n                stunImmune: isBoss,\n                abilities: abilities[charType],\n                invulnerable: false,\n                isAwakened: false,\n                isSSJ2: false,\n                awakenedTimer: 0,\n                damageReduction: 0,\n                animFrame: 0,\n                animTimer: 0,\n                skin: skin,\n                // Edo movement state: used for smooth thumb/keyboard movement and\n                // a subtle step cycle while the dedicated Edo walk sprite is shown.\n                targetVx: 0,\n                movementPhase: 0,\n                // AI state\n                aiTimer: 0,\n                aiAction: null\n            };\n        }\n        function getAssetPrefix(type) {\n            const mapping = {\n                batBai: 'bat_bai',\n                bongDem: 'bong_dem',\n                itachi: 'itachi',\n                madara: 'madara',\n                sasuke: 'sasuke',\n                luffy: 'luffy',\n                sukuna: 'sukuna',\n                gojo: 'gojo',\n                saitama: 'saitama',\n                vuaQuy: 'vua_quy',\n                goku: 'goku',\n                naruto: 'naruto',\n                enel: 'enel',\n                tanjiro: 'tanjiro',\n                obito: 'obito',\n                garp: 'garp',\n                hashirama: 'hashirama',\n                yuji: 'yuji',\n                doraemon: 'doraemon',\n                shadowGarden: 'shadow_garden',\n                zoro: 'zoro',\n                yuta: 'yuta',\n                rimuru: 'rimuru',\n                poPanda: 'po_panda',\n                mahoraga: 'mahoraga'\n            };\n            return mapping[type] || 'bat_bai';\n        }\n\n        function getSprite(fighter) {\n            const basePrefix = getAssetPrefix(fighter.type);\n            let prefix = basePrefix;\n            if (fighter.skin && fighter.skin !== 'default') {\n                prefix += '_' + fighter.skin;\n            }\n            let s = null;\n\n            // Luffy transformation override\n            // Itachi Edo skin uses a complete dedicated sprite set; fall back safely to base Itachi sprites if generation/loading is incomplete.\n            if (fighter.type === 'itachi' && fighter.skin === 'edo') {\n                const edoState = fighter.state === 'walk' ? 'walk' : (fighter.state === 'jump' ? 'jump' : (fighter.state === 'ability1' ? 'ability1' : (fighter.state === 'ability2' ? 'ability2' : (fighter.state === 'ability3' ? 'ability3' : (fighter.state === 'ability4' ? 'ability4' : (fighter.state === 'hit' ? 'hit' : (fighter.state === 'victory' ? 'victory' : 'idle')))))));\n                return imageCache['itachi_edo_' + edoState] || imageCache['itachi_' + edoState] || imageCache['itachi_idle'];\n            }\n\n            // Doraemon Vietnam skin uses a complete dedicated sprite set.\n            if (fighter.type === 'doraemon' && fighter.skin === 'vietnam') {\n                let vietnamState = 'idle';\n                if (fighter.state === 'walk') vietnamState = 'walk';\n                else if (fighter.state === 'jump') vietnamState = 'jump';\n                else if (fighter.state === 'ability1') vietnamState = 'ability1';\n                else if (fighter.state === 'ability2') vietnamState = 'ability2';\n                else if (fighter.state === 'hit') vietnamState = 'hit';\n                else if (fighter.state === 'victory') vietnamState = 'victory';\n                return imageCache['doraemon_vietnam_' + vietnamState] || imageCache['doraemon_' + vietnamState] || imageCache['doraemon_idle'];\n            }\n\n            if (fighter.type === 'luffy' && fighter.isAwakened) {\n                if (fighter.state !== 'hit' && fighter.state !== 'victory') {\n                    if (fighter.skin === 'nika' && imageCache['luffy_ability3']) {\n                        return imageCache['luffy_ability3'];\n                    }\n                    if (fighter.skin === 'gear4' && imageCache['luffy_gear4_sprite']) {\n                        return imageCache['luffy_gear4_sprite'];\n                    }\n                    return imageCache['luffy_gear2'] || imageCache['luffy_idle'];\n                }\n            }\n\n            // Naruto Nine-Tails Mode override\n            if (fighter.type === 'naruto' && fighter.abilities[3] && fighter.abilities[3].active) {\n                if (fighter.state !== 'hit' && fighter.state !== 'victory') {\n                    if (fighter.skin === 'lucDao' && imageCache['naruto_luc_dao_ability4']) {\n                        return imageCache['naruto_luc_dao_ability4'];\n                    }\n                    return imageCache['naruto_ability4'];\n                }\n            }\n\n            // Enel ultimate form check\n            if (fighter.type === 'enel' && fighter.abilities[3] && fighter.abilities[3].active) {\n                if (fighter.state !== 'hit' && fighter.state !== 'victory') {\n                    return imageCache['enel_ability2']; // Striking drums pose\n                }\n            }\n\n            // Yuji Ultimate pose\n            if (fighter.type === 'yuji' && fighter.abilities[3] && fighter.abilities[3].active) {\n                if (fighter.abilities[3].sequence === 'punching') return imageCache['yuji_ability1'];\n            }\n\n            // Garp Ultimate pose\n            if (fighter.type === 'garp' && fighter.abilities[3] && fighter.abilities[3].active) {\n                return imageCache['garp_ability4'] || imageCache['garp_idle']; \n            }\n\n            // Adult Sasuke form override\n            if (fighter.type === 'sasuke' && fighter.isAwakened) {\n                const sType = fighter.state === 'walk' ? 'walk' : (fighter.state === 'jump' ? 'jump' : 'idle');\n                const adultSprite = imageCache['sasuke_adult_' + sType];\n                if (adultSprite) return adultSprite;\n            }\n\n            if (fighter.type === 'chaien') {\n                return imageCache['chaien_summon'] || imageCache['bat_bai_idle'];\n            }\n            if (fighter.type === 'nobita') {\n                return imageCache['nobita_summon'] || imageCache['bong_dem_idle'];\n            }\n\n            switch(fighter.state) {\n                case 'walk': s = imageCache[prefix + '_walk']; break;\n                case 'jump': s = imageCache[prefix + '_jump']; break;\n                case 'ability1': s = imageCache[prefix + '_ability1']; break;\n                case 'ability2': s = imageCache[prefix + '_ability2']; break;\n                case 'ability3': \n                    if (fighter.type === 'luffy' && !fighter.isAwakened) s = imageCache['luffy_idle'];\n                    else s = imageCache[prefix + '_ability3'];\n                    break;\n                case 'ability4':\n                    if (fighter.type === 'naruto') s = imageCache['naruto_ability4'];\n                    else s = imageCache[prefix + '_ability4'] || imageCache[prefix + '_idle'];\n                    break;\n                case 'hit': s = imageCache[prefix + '_hit']; break;\n                case 'victory': s = imageCache[prefix + '_victory']; break;\n                default: s = imageCache[prefix + '_idle']; break;\n            }\n\n            // Fallback: if skin sprite is missing, use base character sprite\n            if (!s) {\n                switch(fighter.state) {\n                    case 'walk': s = imageCache[basePrefix + '_walk']; break;\n                    case 'jump': s = imageCache[basePrefix + '_jump']; break;\n                    case 'ability1': s = imageCache[basePrefix + '_ability1']; break;\n                    case 'ability2': s = imageCache[basePrefix + '_ability2']; break;\n                    case 'ability3': \n                        if (fighter.type === 'luffy' && !fighter.isAwakened) s = imageCache['luffy_idle'];\n                        else s = imageCache[basePrefix + '_ability3'];\n                        break;\n                    case 'ability4':\n                        if (fighter.type === 'naruto') s = imageCache['naruto_ability4'];\n                        else s = imageCache[basePrefix + '_ability4'] || imageCache[basePrefix + '_idle'];\n                        break;\n                    case 'hit': s = imageCache[basePrefix + '_hit']; break;\n                    case 'victory': s = imageCache[basePrefix + '_victory']; break;\n                    default: s = imageCache[basePrefix + '_idle']; break;\n                }\n            }\n\n            return s || imageCache[basePrefix + '_idle'];\n        }\n\n        // Damage dealing\n        function dealDamage(target, amount, source = null) {\n            if (target.invulnerable || target.health <= 0) return;\n            // Damage dealing\n            \n            // Saitama Life Steal fallback (Optional, but cleaning up Vua Quy check first)\n            if (source && source.type === 'vuaQuy' && source.state === 'ability1') {\n                const heal = Math.floor(amount * 0.3);\n                source.health = Math.min(source.maxHealth, source.health + heal);\n            }\n\n            // SAITAMA 4th ABILITY TRIGGER (Counter/Reaction)\n            const handleSaitamaTrigger = (saitama, other) => {\n                const ab = saitama.abilities[3];\n                if (ab && ab.active && !ab.triggered && other && other !== saitama) {\n                    ab.triggered = true;\n                    ab.activeTimer = 8.0; // Sequence duration: ~2s startup + 6s blast\n                    ab.phase = 'teleporting';\n                    ab.targetFighter = other;\n                    other.stunTimer = 8.0; // Keep target stunned for duration\n                    other.vx = 0;\n                    saitama.invulnerable = true;\n                    saitama.state = 'idle';\n                }\n            };\n\n            if (target.type === 'saitama') handleSaitamaTrigger(target, source);\n            else if (source && source.type === 'saitama') handleSaitamaTrigger(source, target);\n\n            if (target.type === 'mahoraga') {\n                amount = Math.floor(amount * 0.7); // Mahoraga reduction\n            }\n\n            if (target.type === 'rimuru' && target.abilities[2].active) {\n                amount = Math.floor(amount * 0.2); // 80% reduction for Rimuru shield\n                addEffect(target.x, target.y - 60, 'block');\n            }\n\n            // Check shields\n            if (target.type === 'batBai' || target.type === 'madara' || target.type === 'sasuke') {\n                // Steel Shield / Susanoo Ribcage check\n                if (target.type === 'batBai' && target.abilities[1].active && !target.abilities[1].shieldHit) {\n                    target.abilities[1].shieldHit = true;\n                    target.abilities[1].active = false;\n                    playSound('shield_activate_sfx', 0.4);\n                    addEffect(target.x, target.y - 60, 'block');\n                    return;\n                }\n                if (target.type === 'sasuke' && target.abilities[1].active) {\n                    amount = Math.floor(amount * 0.3); // 70% reduction\n                    addEffect(target.x, target.y - 60, 'block');\n                }\n                // Damage reduction from batBai ability1\n                if (target.type === 'batBai' && target.abilities[0].active) {\n                    amount = Math.floor(amount * 0.5);\n                }\n                // Yuji damage reduction\n                if (target.type === 'yuji' && target.abilities[1].active) {\n                    amount = Math.floor(amount * 0.4);\n                }\n            }\n\n            // Luffy Nika form protection\n            if (target.type === 'luffy' && target.isAwakened) {\n                amount = Math.floor(amount * 0.85);\n            }\n\n            // Awakening and SSJ2 power boosts\n            if (source && (source.isAwakened || source.isSSJ2)) {\n                const mult = source.isSSJ2 ? 1.6 : 1.3;\n                amount = Math.floor(amount * mult);\n            }\n\n            // Boss damage multiplier\n            if (source && source.damageMultiplier) {\n                amount = Math.floor(amount * source.damageMultiplier);\n            }\n\n            target.health = Math.max(0, target.health - amount);\n            \n            // Gain energy - Increased significantly\n            target.energy = Math.min(target.maxEnergy, target.energy + 15);\n            if (source) {\n                source.energy = Math.min(source.maxEnergy, source.energy + 20);\n            }\n\n            target.state = 'hit';\n            target.stateTimer = 0.3;\n            if (source && (source.type === 'yuji' || source.type === 'garp')) {\n                screenShake = 15;\n                playSound('black_flash_sfx', 0.6);\n                addDamageNumber(target.x, target.y - 80, amount);\n                addEffect(target.x, target.y - 40, 'black_flash');\n            } else {\n                screenShake = 5;\n                playSound('hit_damage_sfx', 0.4);\n                addDamageNumber(target.x, target.y - 80, amount);\n                addEffect(target.x, target.y - 40, 'impact');\n            }\n        }\n\n        function addEffect(x, y, type, params = {}) {\n            effects.push({ x, y, type, timer: 0.4, maxTimer: 0.4, ...params });\n        }\n\n        function addDamageNumber(x, y, amount) {\n            damageNumbers.push({ x, y, amount, timer: 1.0, vy: -2 });\n        }\n\n        // Ability execution\n        function useAbility(fighter, index, target) {\n            const ability = fighter.abilities[index];\n            if (ability.currentCd > 0) return false;\n\n            // Cannot use another ability while one is in progress (animation state)\n            if (fighter.state && fighter.state.startsWith('ability')) {\n                return false;\n            }\n\n            if (fighter.type === 'batBai') {\n                if (index === 0) {\n                    // Fortify Defense\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.damageReduction = 0.5;\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    playSound('shield_activate_sfx', 0.3);\n                } else if (index === 1) {\n                    // Steel Shield\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    ability.shieldHit = false;\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.5;\n                    playSound('shield_activate_sfx', 0.4);\n                } else if (index === 2) {\n                    // Knockback Punch\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 0.4;\n                    hitEnemiesInRange(fighter, ability.range + 40, ability.damage, 12, 5);\n                    playSound('punch_sfx', 0.5);\n                } else if (index === 3) {\n                    // Thi\u00ean Khi\u00ean H\u1ee7y Di\u1ec7t (Giant Map Shield)\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 1.0;\n                    projectiles.push({\n                        x: 360,\n                        y: -400,\n                        vx: 0,\n                        vy: 18,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 5.0,\n                        type: 'giant_shield'\n                    });\n                    playSound('shield_activate_sfx', 1.0);\n                    screenShake = 10;\n                }\n            } else if (fighter.type === 'bongDem') {\n                // B\u00f3ng \u0110\u00eam\n                if (index === 0) {\n                    // Shadow Shuriken\n                    const dir = fighter.facingRight ? 1 : -1;\n                    const numShurikens = fighter.isAwakened ? 12 : 7;\n                    for (let i = 0; i < numShurikens; i++) {\n                        const spread = (i - (numShurikens - 1) / 2) * 0.25;\n                        projectiles.push({\n                            x: fighter.x + dir * 40,\n                            y: fighter.y - 60,\n                            vx: dir * Math.cos(spread) * 12,\n                            vy: Math.sin(spread) * 12,\n                            owner: fighter,\n                            damage: Math.ceil(ability.damage / 3),\n                            timer: 1.5,\n                            type: 'shuriken'\n                        });\n                    }\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.3;\n                    playSound('shuriken_throw_sfx', 0.4);\n                } else if (index === 1) {\n                    // Shadow Dash\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.x += dir * ability.distance;\n                    fighter.x = Math.max(ARENA_LEFT, Math.min(ARENA_RIGHT, fighter.x));\n                    fighter.invulnerable = true;\n                    ability.invulnTimer = 0.3;\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.3;\n                    playSound('dash_sfx', 0.4);\n                } else if (index === 2) {\n                    // Assassination Combo\n                    const enemies = getEnemies(fighter);\n                    const inRange = enemies.some(e => Math.abs(fighter.x - e.x) < ability.range + 80);\n                    if (inRange) {\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 1.2;\n                        ability.hitCount = 0;\n                        ability.hitTimer = 0;\n                        playSound('combo_attack_sfx', 0.4);\n                    } else {\n                        return false;\n                    }\n                } else if (index === 3) {\n                    // L\u00e3nh \u0110\u1ecba B\u00f3ng \u0110\u00eam\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 1.0;\n                    playSound('susanoo_sfx', 0.8);\n                }\n            } else if (fighter.type === 'luffy') {\n                // Luffy\n                const isNika = fighter.isAwakened && fighter.skin === 'nika';\n                const isGear4 = fighter.isAwakened && fighter.skin === 'gear4';\n                const isGear2 = fighter.isAwakened && fighter.skin === 'default';\n\n                if (index === 0) {\n                    if (isNika) {\n                        // Gomu Gomu no Bajrang Gun (Massive Area)\n                        fighter.state = 'ability1';\n                        fighter.stateTimer = 0.8;\n                        hitEnemiesInRange(fighter, 400, 45, 20, 10);\n                        playSound('punch_sfx', 0.8);\n                    } else if (isGear4) {\n                        // Kong Gun\n                        fighter.state = 'ability1';\n                        fighter.stateTimer = 0.6;\n                        hitEnemiesInRange(fighter, 280, 55, 30, 8);\n                        playSound('punch_sfx', 0.9);\n                        screenShake = 20;\n                    } else {\n                        // Gomu Gomu no Pistol\n                        fighter.state = 'ability1';\n                        fighter.stateTimer = 0.4;\n                        hitEnemiesInRange(fighter, (ability.range || 230), ability.damage);\n                        playSound('punch_sfx', 0.5);\n                    }\n                } else if (index === 1) {\n                    if (isNika) {\n                        // Gomu Gomu no Gigant Punch (Jump & Smash Area)\n                        fighter.vy = -15;\n                        const dir = fighter.facingRight ? 1 : -1;\n                        fighter.vx = dir * 12;\n                        fighter.grounded = false;\n                        fighter.state = 'ability2';\n                        fighter.stateTimer = 0.7;\n                        \n                        hitEnemiesInRange(fighter, 350, 35);\n                        playSound('punch_sfx', 0.9);\n                    } else if (isGear4) {\n                        // Rhino Schneider\n                        fighter.vy = -15;\n                        const dir = fighter.facingRight ? 1 : -1;\n                        fighter.vx = dir * 25;\n                        fighter.grounded = false;\n                        fighter.state = 'ability2';\n                        fighter.stateTimer = 0.7;\n                        hitEnemiesInRange(fighter, 260, 45, 20, 15);\n                        playSound('punch_sfx', 0.8);\n                        screenShake = 15;\n                    } else {\n                        // Gomu Gomu no Rocket\n                        const dir = fighter.facingRight ? 1 : -1;\n                        fighter.x += dir * ability.distance;\n                        fighter.x = Math.max(ARENA_LEFT, Math.min(ARENA_RIGHT, fighter.x));\n                        fighter.invulnerable = true;\n                        ability.invulnTimer = 0.3;\n                        fighter.state = 'ability2';\n                        fighter.stateTimer = 0.3;\n                        playSound('dash_sfx', 0.4);\n                    }\n                } else if (index === 2) {\n                    if (isNika) {\n                        // Gomu Gomu no Gigant Stomp (Chi\u00eau 3 Nika)\n                        ability.active = true;\n                        ability.activeTimer = 2.5;\n                        ability.phase = 'jump';\n                        fighter.vy = -30;\n                        fighter.grounded = false;\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 2.5;\n                        ability.hitDone = false;\n                        playSound('susanoo_sfx', 0.8);\n                    } else if (isGear4) {\n                        // Kong Organ\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 1.2;\n                        ability.hitCount = 0;\n                        ability.hitTimer = 0;\n                        ability.hits = 10;\n                        ability.damage = 12;\n                        playSound('combo_attack_sfx', 0.6);\n                        screenShake = 10;\n                    } else {\n                        // Gomu Gomu no Gatling\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 1.0;\n                        ability.hitCount = 0;\n                        ability.hitTimer = 0;\n                        ability.hits = 8;\n                        ability.damage = 4;\n                        playSound('combo_attack_sfx', 0.4);\n                    }\n                } else if (index === 3) {\n                    // Ultimate Smash (Bajrang Gun for Nika, Giant Jet Smash for Gear 2)\n                    if (fighter.isAwakened) {\n                        ability.active = true;\n                        ability.activeTimer = 1.8;\n                        ability.hitDone = false;\n                        fighter.state = 'ability1';\n                        fighter.stateTimer = 1.8;\n                        fighter.vy = -30; // Jump high\n                        fighter.grounded = false;\n                        playSound('susanoo_sfx', 0.8);\n                    } else {\n                        return false;\n                    }\n                }\n            } else if (fighter.type === 'madara') {\n                // Madara\n                if (index === 0) {\n                    // Thi\u00ean Ng\u1ea1i Ch\u1ea5n Tinh (Meteor)\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 1.2;\n                    \n                    // Spawn 2 giant meteors\n                    projectiles.push({\n                        x: target.x,\n                        y: -400,\n                        vx: 0,\n                        vy: 12,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 6.0,\n                        type: 'meteor',\n                        id: 1\n                    });\n                    \n                    projectiles.push({\n                        x: target.x,\n                        y: -1200,\n                        vx: 0,\n                        vy: 12,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 8.0,\n                        type: 'meteor',\n                        id: 2\n                    });\n\n                    playSound('susanoo_sfx', 0.8);\n                    setTimeout(() => {\n                        if (gameState === 'combat') playSound('fireball_sfx', 0.9);\n                    }, 500);\n                } else if (index === 1) {\n                    // H\u00e0o H\u1ecfa Di\u1ec7t (Great Fire Annihilation)\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 1.5;\n                    ability.active = true;\n                    ability.activeTimer = 1.5;\n                    playSound('fireball_sfx', 0.8);\n                } else if (index === 2) {\n                    // Yasaka Magatama\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 60,\n                        y: fighter.y - 70,\n                        vx: dir * 14,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'magatama'\n                    });\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 0.5;\n                    playSound('shuriken_throw_sfx', 0.6);\n                } else if (index === 3) {\n                    // Susanoo To\u00e0n Ch\u00e2n Th\u1ec3\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 1.2;\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 25;\n                }\n            } else if (fighter.type === 'sasuke') {\n                // Sasuke\n                if (index === 0) {\n                    // L\u00f4i Long Thi\u00ean Ph\u1ea1t (Electric Dragon)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 15,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'lightning_dragon'\n                    });\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.6;\n                    playSound('chidori_sfx', 0.7);\n                } else if (index === 1) {\n                    // Fireball Jutsu\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 12,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'fireball'\n                    });\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    playSound('fireball_sfx', 0.5);\n                } else if (index === 2) {\n                    // Susanoo Strike (3rd move as requested)\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.0;\n                    const dist = Math.abs(fighter.x - target.x);\n                    if (dist < 300) {\n                        dealDamage(target, ability.damage, fighter);\n                        screenShake = 15;\n                    }\n                    playSound('susanoo_sfx', 0.8);\n                } else if (index === 3) {\n                    // \u0110\u1ecba T\u0103ng Thi\u00ean Tinh (Chibaku Tensei)\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    ability.sphereX = fighter.x;\n                    ability.sphereY = fighter.y - 100;\n                    ability.targetX = 360;\n                    ability.targetY = 300;\n                    ability.particles = [];\n                    // Initial launch\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.0;\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 10;\n                }\n            } else if (fighter.type === 'itachi') {\n                // ITACHI\n                if (index === 0) {\n                    // Fireball Jutsu\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 12,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'fireball'\n                    });\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.6;\n                    playSound('fireball_sfx', 0.5);\n                } else if (index === 1) {\n                    // Itachi Edo Susanoo: giant red chakra slash that detonates on impact.\n                    // Outside Susanoo, preserve the original Black Space illusion.\n                    if (fighter.skin === 'edo' && fighter.abilities[3] && fighter.abilities[3].active) {\n                        const dir = fighter.facingRight ? 1 : -1;\n                        projectiles.push({\n                            x: fighter.x + dir * 90,\n                            y: fighter.y - 125,\n                            vx: dir * 18,\n                            vy: 0,\n                            owner: fighter,\n                            damage: ability.susanooSlashDamage || 65,\n                            explosionDamage: ability.susanooExplosionDamage || 95,\n                            timer: 1.35,\n                            type: 'itachi_edo_susanoo_red_slash'\n                        });\n                        fighter.state = 'ability2';\n                        fighter.stateTimer = 0.7;\n                        playSound('sword_slash_sfx', 0.85);\n                        screenShake = 18;\n                    } else {\n                        // \u1ea2o Thu\u1eadt: Kh\u00f4ng Gian \u0110en\n                        ability.active = true;\n                        ability.activeTimer = ability.duration;\n                        fighter.state = 'ability2';\n                        fighter.stateTimer = 1.0;\n                        playSound('crow_sfx', 0.8);\n                    }\n                } else if (index === 2) {\n                    // Itachi Edo Susanoo: create a rotating Sharingan vortex.\n                    // The vortex lasts 5 seconds, pulls enemies into an orbit,\n                    // deals continuous damage, then ends in a black explosion.\n                    if (fighter.skin === 'edo' && fighter.abilities[3] && fighter.abilities[3].active) {\n                        const dir = fighter.facingRight ? 1 : -1;\n                        const centerX = target && target.health > 0\n                            ? target.x\n                            : fighter.x + dir * 220;\n                        const centerY = target && target.health > 0\n                            ? target.y - 140\n                            : fighter.y - 140;\n                        projectiles.push({\n                            x: Math.max(ARENA_LEFT + 40, Math.min(ARENA_RIGHT - 40, centerX)),\n                            y: centerY,\n                            vx: 0,\n                            vy: 0,\n                            owner: fighter,\n                            damage: ability.damage,\n                            explosionDamage: ability.explosionDamage || 80,\n                            timer: ability.vortexDuration || 5,\n                            maxTimer: ability.vortexDuration || 5,\n                            rotation: 0,\n                            rotationSpeed: Math.PI * 2.2,\n                            pullRadius: ability.pullRadius || 360,\n                            orbitRadius: ability.orbitRadius || 110,\n                            captured: [],\n                            type: 'itachi_edo_sharingan_vortex'\n                        });\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = ability.vortexDuration || 5;\n                        playSound('susanoo_sfx', 0.8);\n                        screenShake = 15;\n                    } else {\n                        // Tsukuyomi (Stun)\n                        const dist = Math.abs(fighter.x - target.x);\n                        if (dist < (fighter.isAwakened ? ability.range * 1.5 : ability.range)) {\n                            dealDamage(target, ability.damage, fighter);\n                            target.stunTimer = fighter.isAwakened ? ability.stunDuration * 1.5 : ability.stunDuration;\n                            target.vx = 0;\n                            fighter.state = 'ability3';\n                            fighter.stateTimer = 0.8;\n                            playSound('combo_attack_sfx', 0.5);\n                            addEffect(target.x, target.y - 100, 'impact');\n                        } else {\n                            return false;\n                        }\n                    }\n                } else if (index === 3) {\n                    if (fighter.skin === 'edo') {\n                        // Itachi Edo Susanoo transformation: active for 17 seconds.\n                        ability.active = true;\n                        ability.activeTimer = ability.duration;\n                        fighter.state = 'ability4';\n                        fighter.stateTimer = 1.0;\n                        playSound('susanoo_sfx', 1.0);\n                        screenShake = 25;\n                    } else {\n                        // Preserve base Itachi's Blood Moon ability.\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 1.0;\n                        projectiles.push({\n                            x: target.x,\n                            y: -200,\n                            vx: 0,\n                            vy: 10,\n                            owner: fighter,\n                            damage: ability.damage,\n                            timer: 5.0,\n                            type: 'red_moon'\n                        });\n                        playSound('fireball_sfx', 0.8);\n                        screenShake = 10;\n                    }\n                }\n            } else if (fighter.type === 'sukuna') {\n                // Sukuna\n                if (index === 0) {\n                    // Dismantle\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage);\n                    playSound('shuriken_throw_sfx', 0.6);\n                } else if (index === 1) {\n                    // Fuga (Fire Arrow -> Fire Column)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 16,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'fuga_arrow'\n                    });\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    playSound('fireball_sfx', 0.7);\n                } else if (index === 2) {\n                    // Malevolent Shrine (Domain Expansion)\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability3'; // Use the Domain sign pose for charging\n                    fighter.stateTimer = 1.5;\n                    playSound('susanoo_sfx', 1.0);\n                } else if (index === 3) {\n                    // Ch\u00e9m C\u1eaft Kh\u00f4ng Gian (World Slash)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x,\n                        y: fighter.y - 60,\n                        vx: dir * 20,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 1.0,\n                        type: 'world_slash'\n                    });\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.6;\n                    playSound('shuriken_throw_sfx', 0.8);\n                }\n            } else if (fighter.type === 'gojo') {\n                // Gojo\n                if (index === 0) {\n                    // Cang (Blue)\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage);\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 1) {\n                    // H\u00e1ch (Red)\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage);\n                    playSound('punch_sfx', 0.7);\n                } else if (index === 2) {\n                    // V\u00f4 H\u1ea1n Kh\u00f4ng (Domain)\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability3'; // Use the Domain sign pose for charging\n                    fighter.stateTimer = 1.5;\n                    playSound('susanoo_sfx', 1.0);\n                } else if (index === 3) {\n                    // Hollow Purple (T\u1eed)\n                    ability.active = true;\n                    ability.activeTimer = 3.0;\n                    ability.exploded = false;\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 3.0;\n                    playSound('atomic_sfx', 1.0);\n                }\n            } else if (fighter.type === 'saitama') {\n                // Saitama\n                if (index === 0) {\n                    // Normal Punch\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.3;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 10, 0);\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 1) {\n                    // Consecutive Normal Punches\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 1.0;\n                    ability.hitCount = 0;\n                    ability.hitTimer = 0;\n                    playSound('combo_attack_sfx', 0.5);\n                } else if (index === 2) {\n                    // Serious Punch\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.2;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 40, 10);\n                    screenShake = 30;\n                    playSound('punch_sfx', 1.0);\n                } else if (index === 3) {\n                    // S\u1ee9c M\u1ea1nh Tuy\u1ec7t \u0110\u1ed1i\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    ability.triggered = false;\n                    ability.phase = 'idle';\n                    fighter.state = 'idle';\n                    playSound('susanoo_sfx', 0.6);\n                }\n            } else if (fighter.type === 'vuaQuy') {\n                // Vua Qu\u1ef7\n                if (index === 0) {\n                    // Demon Claw\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage);\n                    playSound('punch_sfx', 0.7);\n                } else if (index === 1) {\n                    // Hellfire\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 14,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'fireball'\n                    });\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    playSound('fireball_sfx', 0.6);\n                } else if (index === 2) {\n                    // C\u1ed9t L\u1eeda H\u1ecfa Ng\u1ee5c (4 columns on both sides)\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.0;\n                    const offsets = [-300, -150, 150, 300];\n                    for (const offset of offsets) {\n                        projectiles.push({\n                            x: fighter.x + offset,\n                            y: GROUND_Y,\n                            vx: 0, vy: 0,\n                            owner: fighter,\n                            damage: ability.damage,\n                            timer: 3.0,\n                            type: fighter.skin === 'beach' ? 'water_column' : 'fire_column'\n                        });\n                    }\n                    screenShake = 30;\n                    playSound('fireball_sfx', 1.0);\n                } else if (index === 3) {\n                    // L\u00e3nh \u0110\u1ecba \u0110\u1ecba Ng\u1ee5c\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.0;\n                    playSound('fireball_sfx', 1.0);\n                    screenShake = 25;\n                }\n            } else if (fighter.type === 'shadowGarden') {\n                // Shadow Garden\n                if (index === 0) {\n                    // Slime Slash\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage);\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 1) {\n                    // Shadow Dash\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.x += dir * ability.distance;\n                    fighter.x = Math.max(ARENA_LEFT, Math.min(ARENA_RIGHT, fighter.x));\n                    fighter.invulnerable = true;\n                    ability.invulnTimer = 0.3;\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.3;\n                    playSound('dash_sfx', 0.4);\n                    addEffect(fighter.x, fighter.y - 60, 'impact');\n                } else if (index === 2) {\n                    // Violet Burst\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 0.8;\n                    const dist = Math.abs(fighter.x - target.x);\n                    if (dist < ability.range) {\n                        dealDamage(target, ability.damage, fighter);\n                        screenShake = 10;\n                    }\n                    playSound('fireball_sfx', 0.5);\n                } else if (index === 3) {\n                    // I AM ATOMIC\n                    ability.active = true;\n                    ability.activeTimer = 3.5; // Long epic charge\n                    ability.exploded = false;\n                    fighter.state = 'ability3'; // Use channeling pose\n                    fighter.stateTimer = 3.5;\n                    playSound('atomic_sfx', 1.0);\n                }\n            } else if (fighter.type === 'naruto') {\n                // Naruto\n                if (index === 0) {\n                    // Rasengan\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.vx = dir * 15;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 10, 0);\n                    playSound('rasengan_sfx', 0.6);\n                } else if (index === 1) {\n                    // Shadow Clone Strike\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.8;\n                    ability.hitCount = 0;\n                    ability.hitTimer = 0;\n                    playSound('combo_attack_sfx', 0.5);\n                } else if (index === 2) {\n                    // Rasenshuriken\n                    if (fighter.abilities[3] && fighter.abilities[3].active) {\n                        // Nine-Tails Special: Kurama Shockwave Beam\n                        // Allow refiring during Nine-Tails Mode with shorter cooldown\n                        ability.active = true;\n                        ability.activeTimer = 7.0; // 7 seconds\n                        ability.tickTimer = 0;\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 7.0;\n                        playSound('rasengan_sfx', 0.8);\n                        screenShake = 20;\n\n                        // Shorter cooldown during Nine-Tails Mode to allow multiple fires\n                        ability.currentCd = 15; \n                    } else if (fighter.skin === 'lucDao') {\n                        // Naruto Luc Dao Skill 3: 5 Clone Rush\n                        const dir = fighter.facingRight ? 1 : -1;\n                        for (let k = 0; k < 5; k++) {\n                            projectiles.push({\n                                x: fighter.x - dir * (k * 40),\n                                y: fighter.y,\n                                vx: dir * (10 + Math.random() * 5),\n                                vy: -2 - Math.random() * 4,\n                                owner: fighter,\n                                damage: 15,\n                                timer: 2.5,\n                                type: 'naruto_clone_rush',\n                                skin: fighter.skin\n                            });\n                        }\n                        fighter.state = 'ability2'; // Summoning pose\n                        fighter.stateTimer = 0.5;\n                        playSound('combo_attack_sfx', 0.6);\n                        ability.currentCd = ability.cooldown;\n                    } else {\n                        // Default Rasenshuriken\n                        const dir = fighter.facingRight ? 1 : -1;\n                        projectiles.push({\n                            x: fighter.x + dir * 60,\n                            y: fighter.y - 70,\n                            vx: dir * 15,\n                            vy: 0,\n                            owner: fighter,\n                            damage: ability.damage,\n                            timer: 2.5,\n                            type: 'rasenshuriken'\n                        });\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 0.6;\n                        playSound('rasengan_sfx', 0.7);\n                        // Regular cooldown\n                        ability.currentCd = ability.cooldown;\n                    }\n                    return true;\n                } else if (index === 3) {\n                    // Nine-Tails Mode\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    \n                    if (fighter.skin === 'lucDao') {\n                        ability.ultPhase = 'summon';\n                        ability.ultTimer = 3.5; // Sequence duration\n                        fighter.vx = 0;\n                        if (target) {\n                            target.stunTimer = 4.0;\n                            target.vx = 0;\n                        }\n                        ability.hitDone = false;\n                    }\n\n                    fighter.state = 'ability4';\n                    fighter.stateTimer = (fighter.skin === 'lucDao') ? 3.5 : 1.0;\n                    playSound('naruto_transform_sfx', 1.0);\n                    screenShake = 15;\n                }\n            } else if (fighter.type === 'enel') {\n                // Enel\n                if (index === 0) {\n                    // L\u00f4i \u0110i\u1ec3u (Lightning Bird)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 14,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'lightning_bird'\n                    });\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    playSound('chidori_sfx', 0.6);\n                } else if (index === 1) {\n                    // L\u00f4i Th\u00fa (Lightning Beast)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 16,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'lightning_beast'\n                    });\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    playSound('chidori_sfx', 0.7);\n                } else if (index === 2) {\n                    // D\u1ecbch Chuy\u1ec3n \u0110i\u1ec7n (Fast dash)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.x += dir * ability.distance;\n                    fighter.x = Math.max(ARENA_LEFT, Math.min(ARENA_RIGHT, fighter.x));\n                    fighter.invulnerable = true;\n                    ability.invulnTimer = 0.3;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 0.3;\n                    playSound('dash_sfx', 0.5);\n                    addEffect(fighter.x, fighter.y - 60, 'impact');\n                } else if (index === 3) {\n                    // Raigo (Giant Electric Sphere)\n                    ability.active = true;\n                    ability.activeTimer = 4.0;\n                    fighter.state = 'ability2'; // Use striking drums pose\n                    fighter.stateTimer = 4.0;\n                    projectiles.push({\n                        x: target.x,\n                        y: -400,\n                        vx: 0,\n                        vy: 6,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 10.0,\n                        type: 'raigo_sphere'\n                    });\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 15;\n                }\n            } else if (fighter.type === 'tanjiro') {\n                // Tanjiro\n                if (index === 0) {\n                    // Water Breathing Form 2 (Mizunotenmon) - Red Water\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage);\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 1) {\n                    // Water Breathing Form 6 (Rengoku no Yari) - Red Water\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.vx = dir * 15;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 10, 0);\n                    playSound('punch_sfx', 0.7);\n                } else if (index === 2) {\n                    // Water Breathing Form 10 (Constant Flux) - Red Water\n                    ability.active = true;\n                    ability.activeTimer = 1.5;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.5;\n                    playSound('susanoo_sfx', 0.6);\n                } else if (index === 3) {\n                    // H\u1ecfa Th\u1ea7n (Hinokami Kagura) - Phase 1: Jump\n                    ability.active = true;\n                    ability.activeTimer = 10; // Extended time for sequence\n                    ability.phase = 'jump';\n                    fighter.vy = -35;\n                    fighter.grounded = false;\n                    fighter.state = 'jump';\n                    fighter.stateTimer = 10;\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 15;\n                }\n            } else if (fighter.type === 'goku') {\n                // Goku\n                if (index === 0) {\n                    // \u0110\u1ea5m Li\u00ean Ho\u00e0n\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.8;\n                    ability.hitCount = 0;\n                    ability.hitTimer = 0;\n                    playSound('combo_attack_sfx', 0.5);\n                } else if (index === 1) {\n                    if (fighter.isSSJ2) {\n                        // Qu\u1ea3 C\u1ea7u Kh\u1ee7ng L\u1ed3 (Giant Sphere)\n                        fighter.state = 'ability2';\n                        fighter.stateTimer = 1.0;\n                        projectiles.push({\n                            x: target.x,\n                            y: -600,\n                            vx: 0,\n                            vy: 8,\n                            owner: fighter,\n                            damage: 150,\n                            timer: 8.0,\n                            type: 'goku_giant_sphere'\n                        });\n                        playSound('susanoo_sfx', 0.9);\n                    } else {\n                        // D\u1ecbch Chuy\u1ec3n T\u1ee9c Th\u1eddi\n                        const dir = fighter.facingRight ? 1 : -1;\n                        // Teleport behind target\n                        const targetDir = target.facingRight ? 1 : -1;\n                        fighter.x = target.x - targetDir * 80;\n                        fighter.x = Math.max(ARENA_LEFT, Math.min(ARENA_RIGHT, fighter.x));\n                        fighter.facingRight = target.x > fighter.x;\n                        fighter.state = 'ability2';\n                        fighter.stateTimer = 0.2;\n                        playSound('dash_sfx', 0.6);\n                        addEffect(fighter.x, fighter.y - 60, 'impact');\n                    }\n                } else if (index === 2) {\n                    // Kamehameha\n                    ability.active = true;\n                    ability.activeTimer = 1.5; // 0.8 charge, 0.7 fire\n                    ability.charging = true;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.5;\n                    playSound('kamehameha_sfx', 0.8);\n                } else if (index === 3) {\n                    // Si\u00eau Saiyan 2 Transformation\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability1'; // Use a power-up pose\n                    fighter.stateTimer = 1.0;\n                    playSound('susanoo_sfx', 0.8);\n                    screenShake = 15;\n                }\n            } else if (fighter.type === 'yuji') {\n                if (index === 0) {\n                    // K\u00ednh Loa Quy\u1ec1n (Divergent Fist)\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    if (hitEnemiesInRange(fighter, ability.range, ability.damage)) {\n                        // Delayed damage\n                        setTimeout(() => {\n                            if (gameState === 'combat') {\n                                hitEnemiesInRange(fighter, ability.range + 20, ability.damage * 0.5);\n                            }\n                        }, 300);\n                    }\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 1) {\n                    // Cursed Energy Guard\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.5;\n                    playSound('shield_activate_sfx', 0.4);\n                } else if (index === 2) {\n                    // Rapid Strikes\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.0;\n                    ability.hitCount = 0;\n                    ability.hitTimer = 0;\n                    playSound('combo_attack_sfx', 0.5);\n                } else if (index === 3) {\n                    // H\u1eafc Thi\u1ec3m (Rock -> Teleport -> 5 Black Flashes)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 18,\n                        vy: -2,\n                        owner: fighter,\n                        damage: 10,\n                        timer: 2.0,\n                        type: 'yuji_rock'\n                    });\n                    ability.sequence = 'throwing';\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.6;\n                    playSound('shuriken_throw_sfx', 0.6);\n                }\n            } else if (fighter.type === 'garp') {\n                if (index === 0) {\n                    // Fist of Love\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 15, 5);\n                    playSound('punch_sfx', 0.7);\n                } else if (index === 1) {\n                    // Cannonball\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 16,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'meteor' // Re-use meteor for cannonball\n                    });\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 2) {\n                    // Navy Strikes\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.0;\n                    ability.hitCount = 0;\n                    ability.hitTimer = 0;\n                    playSound('combo_attack_sfx', 0.5);\n                } else if (index === 3) {\n                    // Galaxy Impact: Phase 1: Jump\n                    ability.active = true;\n                    ability.activeTimer = 6.0; \n                    ability.phase = 'jump';\n                    fighter.vy = -18;\n                    fighter.grounded = false;\n                    fighter.state = 'jump';\n                    fighter.stateTimer = 1.5;\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 20;\n                }\n            } else if (fighter.type === 'doraemon') {\n                if (index === 0) {\n                    // B\u00e1nh R\u00e1n\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 12,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'dorayaki'\n                    });\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    playSound('shuriken_throw_sfx', 0.5);\n                } else if (index === 1) {\n                    // \u0110\u00e8n Pin Thu Nh\u1ecf\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    const dir = fighter.facingRight ? 1 : -1;\n                    const dist = Math.abs(fighter.x - target.x);\n                    if (dist < ability.range) {\n                        dealDamage(target, ability.damage, fighter);\n                        target.stunTimer = 1.5;\n                        addEffect(target.x, target.y - 60, 'impact');\n                    }\n                    playSound('chidori_sfx', 0.4);\n                } else if (index === 2) {\n                    // Doraemon Vi\u1ec7t Nam: replace Chaien with a Vietnamese flag\n                    // summon. The pole stays planted while red wind pressure\n                    // radiates around it and damages nearby enemies repeatedly.\n                    if (fighter.skin === 'vietnam') {\n                        const dir = fighter.facingRight ? 1 : -1;\n                        projectiles.push({\n                            x: Math.max(ARENA_LEFT + 70, Math.min(ARENA_RIGHT - 70, fighter.x + dir * 105)),\n                            y: GROUND_Y,\n                            vx: 0,\n                            vy: 0,\n                            owner: fighter,\n                            damage: ability.damage,\n                            timer: ability.duration,\n                            maxTimer: ability.duration,\n                            hitTick: 0,\n                            waveTimer: 0,\n                            type: 'doraemon_vietnam_flag_summon'\n                        });\n                        fighter.state = 'ability1';\n                        fighter.stateTimer = 0.5;\n                        playSound('victory_sfx', 0.6);\n                    } else {\n                        // Tri\u1ec7u h\u1ed3i Chaien\n                        const dir = fighter.facingRight ? 1 : -1;\n                        const summon = createFighter('chaien', fighter.x + dir * 100, fighter.facingRight, true);\n                        summon.owner = fighter;\n                        summon.health = 9999; // Invincible\n                        summon.activeTimer = ability.duration;\n                        summon.damage = ability.damage; // Use the damage from the ability config\n                        summon.shockwaveTimer = 0;\n                        summons.push(summon);\n                        fighter.state = 'ability1';\n                        fighter.stateTimer = 0.5;\n                        playSound('victory_sfx', 0.6);\n                    }\n                } else if (index === 3) {\n                    // Doraemon Vi\u1ec7t Nam: summon a glowing Vietnamese flag and a\n                    // golden dragon vortex in the sky. The normal Doraemon skin\n                    // keeps its original Nobita summon behavior.\n                    if (fighter.skin === 'vietnam') {\n                        ability.active = true;\n                        ability.activeTimer = 7.0;\n                        ability.duration = 7.0;\n                        ability.phase = 'sky_vortex';\n                        ability.centerX = 360;\n                        ability.centerY = 270;\n                        ability.rotation = 0;\n                        ability.dragonRotation = 0;\n                        ability.tickTimer = 0;\n                        ability.exploded = false;\n                        ability.captured = [];\n                        ability.targetFighter = target || null;\n                        fighter.vx = 0;\n                        fighter.vy = 0;\n                        fighter.state = 'ability4';\n                        fighter.stateTimer = 7.0;\n                        playSound('susanoo_sfx', 0.9);\n                        screenShake = 18;\n                    } else {\n                        // Tri\u1ec7u h\u1ed3i Nobita\n                        const dir = fighter.facingRight ? 1 : -1;\n                        const summon = createFighter('nobita', fighter.x + dir * 100, fighter.facingRight, true);\n                        summon.owner = fighter;\n                        summon.health = 9999; // Invincible\n                        summon.activeTimer = ability.duration;\n                        summon.damage = ability.damage; // Use the damage from the ability config\n                        summon.blastTimer = 0;\n                        summons.push(summon);\n                        fighter.state = 'ability1';\n                        fighter.stateTimer = 0.5;\n                        playSound('victory_sfx', 0.6);\n                    }\n                }\n            } else if (fighter.type === 'poPanda') {\n                if (index === 0) {\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 10, 2);\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 1) {\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = ability.duration;\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.vx = dir * 18;\n                    playSound('dash_sfx', 0.5);\n                } else if (index === 2) {\n                    // Wuxi Finger Hold\n                    const enemies = getEnemies(fighter);\n                    let caught = null;\n                    for (const e of enemies) {\n                        if (Math.abs(fighter.x - e.x) < ability.range) {\n                            caught = e;\n                            break;\n                        }\n                    }\n                    if (caught) {\n                        ability.phase = 'hold';\n                        ability.active = true;\n                        ability.activeTimer = 2.0;\n                        ability.targetFighter = caught;\n                        ability.hitDone = false;\n                        caught.stunTimer = 2.0;\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 2.0;\n                        fighter.invulnerable = true;\n                        playSound('susanoo_sfx', 0.8);\n                    } else {\n                        return false;\n                    }\n                } else if (index === 3) {\n                    // Long Th\u1ea7n B\u00e1t Qu\u00e1i\n                    ability.active = true;\n                    ability.activeTimer = 4.2;\n                    ability.phase = 'summoning';\n                    ability.targetFighter = target;\n                    ability.hitDone = false;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 4.2;\n                    playSound('susanoo_sfx', 1.0);\n                }\n            } else if (fighter.type === 'obito') {\n                if (index === 0) {\n                    // H\u1ecfa \u0110\u1ed9n: B\u1ea1o Phong Lo\u1ea1n V\u0169\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 16,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'obito_fire_vortex'\n                    });\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.6;\n                    playSound('fireball_sfx', 0.8);\n                } else if (index === 1) {\n                    // Kamui\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.x += dir * ability.distance;\n                    fighter.x = Math.max(ARENA_LEFT, Math.min(ARENA_RIGHT, fighter.x));\n                    fighter.invulnerable = true;\n                    ability.invulnTimer = 0.3;\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.3;\n                    playSound('dash_sfx', 0.4);\n                } else if (index === 2) {\n                    // Tri\u1ec7u H\u1ed3i Th\u1ea7n Th\u1ee5: V\u0129 Th\u00fa Ng\u1ecdc\n                    ability.active = true;\n                    ability.activeTimer = 1.8;\n                    ability.fired = false;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.8;\n                    fighter.vx = 0;\n                    playSound('susanoo_sfx', 0.8);\n                } else if (index === 3) {\n                    // Gedo Mazo: Ch\u1ea5n \u0110\u1ed9ng\n                    ability.active = true;\n                    ability.activeTimer = 4.0;\n                    fighter.state = 'ability4';\n                    fighter.stateTimer = 1.5;\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 30;\n                }\n            } else if (fighter.type === 'hashirama') {\n                if (index === 0) {\n                    // M\u1ed9c Long Thu\u1eadt\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 60,\n                        y: fighter.y - 70,\n                        vx: dir * 14,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.5,\n                        type: 'wood_dragon'\n                    });\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.6;\n                    playSound('shuriken_throw_sfx', 0.6);\n                } else if (index === 1) {\n                    // M\u1ed9c Th\u1ee7 Gi\u00e1ng L\u00e2m (Wood Hand from below)\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.8;\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: target.x,\n                        y: GROUND_Y,\n                        vx: 0, vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.5,\n                        type: 'wood_hand'\n                    });\n                    playSound('punch_sfx', 0.8);\n                } else if (index === 2) {\n                    // M\u1ed9c \u0110\u1ed9n: Th\u1ebf Gi\u1edbi C\u00e2y Hoa (Deep Forest Emergence)\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 1.5;\n                    playSound('susanoo_sfx', 1.0);\n                } else if (index === 3) {\n                    // Thi\u00ean Th\u1ee7 Quan \u00c2m\n                    ability.active = true;\n                    ability.activeTimer = 5.0;\n                    ability.fists = []; // For falling fists effect\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 5.0;\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 40;\n                }\n            } else if (fighter.type === 'zoro') {\n                if (index === 0) {\n                    // Onigiri\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.vx = dir * 20;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 10, 2);\n                    playSound('sword_slash_sfx', 0.6);\n                } else if (index === 1) {\n                    // Phoenix Slash\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 18,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'zoro_phoenix'\n                    });\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.6;\n                    playSound('sword_slash_sfx', 0.7);\n                } else if (index === 2) {\n                    // Long Quy\u1ec3n Phong (Ashura Visual)\n                    ability.active = true;\n                    ability.activeTimer = 3.0;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 0.8;\n                    playSound('susanoo_sfx', 0.6);\n                    screenShake = 15;\n                } else if (index === 3) {\n                    // Ashura: 4 seconds of continuous black slashes, followed by\n                    // a giant 3-second finishing slash and erupting ground.\n                    ability.active = true;\n                    ability.activeTimer = ability.duration || 8.0;\n                    ability.phase = 'startup';\n                    ability.targetFighter = target;\n                    ability.hitDone = false;\n                    ability.wanoStep = 0;\n                    ability.slashCount = 0;\n                    ability.tickTimer = 0;\n                    ability.groundBurstTimer = 0;\n                    ability.finalDamageTimer = 0;\n                    ability.finalSlashDone = false;\n                    fighter.state = 'ability4';\n                    fighter.stateTimer = 1.2;\n                    playSound('susanoo_sfx', 1.0);\n                    screenShake = 20;\n                    if (target) target.stunTimer = 8.0;\n                }\n            } else if (fighter.type === 'yuta') {\n                if (index === 0) {\n                    // Thanh Ki\u1ebfm Nguy\u1ec1n R\u1ee7a\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.5;\n                    hitEnemiesInRange(fighter, ability.range, ability.damage, 12, 2);\n                    playSound('sword_slash_sfx', 0.6);\n                } else if (index === 1) {\n                    // Ph\u1ea1n V\u0103n: Ch\u1ebft \u0110i (Cursed Speech)\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 1.0;\n                    const dir = fighter.facingRight ? 1 : -1;\n                    const enemies = getEnemies(fighter);\n                    for (const enemy of enemies) {\n                        const dx = (enemy.x - fighter.x) * dir;\n                        if (dx > 0 && dx < ability.range && Math.abs(enemy.y - fighter.y) < 200) {\n                            dealDamage(enemy, ability.damage, fighter);\n                            enemy.stunTimer = 2.0;\n                        }\n                    }\n                    playSound('victory_sfx', 0.8); // Use as placeholder for loud voice\n                } else if (index === 2) {\n                    // H\u1eafc Thi\u1ec3m & C\u1ed9t \u00c1nh S\u00e1ng V\u00e0ng\n                    if (target) {\n                        // 1. Teleport\n                        fighter.x = target.x - (target.facingRight ? 80 : -80);\n                        fighter.facingRight = (target.x > fighter.x);\n                        fighter.state = 'ability3';\n                        fighter.stateTimer = 0.6;\n                        \n                        // 2. Black Flash Hit\n                        dealDamage(target, ability.damage, fighter);\n                        addEffect(target.x, target.y - 60, 'black_flash');\n                        playSound('black_flash_sfx', 0.8);\n                        \n                        // 3. Spawn Yellow Pillar\n                        projectiles.push({\n                            x: target.x,\n                            y: GROUND_Y,\n                            vx: 0, vy: 0,\n                            owner: fighter,\n                            damage: Math.floor(ability.damage * 0.4),\n                            timer: 3.0,\n                            type: 'yellow_pillar'\n                        });\n                        \n                        screenShake = 40;\n                    } else {\n                        return false;\n                    }\n                } else if (index === 3) {\n                    // Tri\u1ec7u H\u1ed3i Rika: T\u00ecnh Y\u00eau Thu\u1ea7n Khi\u1ebft\n                    ability.active = true;\n                    ability.activeTimer = ability.duration;\n                    ability.phase = 'summoning';\n                    fighter.state = 'ability4';\n                    fighter.stateTimer = 1.5;\n                    playSound('rika_sfx', 1.0);\n                    screenShake = 40;\n                }\n            } else if (fighter.type === 'rimuru') {\n                if (index === 0) {\n                    // B\u1ea1o Th\u1ef1c (Predation)\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = 0.6;\n                    if (hitEnemiesInRange(fighter, ability.range, ability.damage)) {\n                        // Heal on hit\n                        fighter.health = Math.min(fighter.maxHealth, fighter.health + 40);\n                    }\n                    playSound('punch_sfx', 0.6);\n                } else if (index === 1) {\n                    // Sticky Shuriken\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 40,\n                        y: fighter.y - 70,\n                        vx: dir * 14,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'sticky_shuriken'\n                    });\n                    fighter.state = 'ability2';\n                    fighter.stateTimer = 0.5;\n                    playSound('shuriken_throw_sfx', 0.5);\n                } else if (index === 2) {\n                    // H\u1eafc \u1ea4n C\u1ea7u (Explosive Sphere)\n                    const dir = fighter.facingRight ? 1 : -1;\n                    projectiles.push({\n                        x: fighter.x + dir * 60,\n                        y: fighter.y - 70,\n                        vx: dir * 12,\n                        vy: 0,\n                        owner: fighter,\n                        damage: ability.damage,\n                        timer: 2.0,\n                        type: 'rimuru_explosive_sphere'\n                    });\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = 0.6;\n                    playSound('fireball_sfx', 0.7);\n                } else if (index === 3) {\n                    // Sky Energy Orbs (Inspired by user image 01KZCSBW97HNRJP8WJ8EAV8549)\n                    ability.active = true;\n                    ability.activeTimer = 7.0;\n                    ability.tickTimer = 0;\n                    // Initialize sky orbs\n                    ability.clones = [];\n                    const orbCount = 8;\n                    for(let k=0; k<orbCount; k++) {\n                        ability.clones.push({\n                            x: (k + 0.5) * (720 / orbCount) + (Math.random()-0.5)*40,\n                            y: 80 + Math.random() * 120,\n                            offset: Math.random() * Math.PI * 2\n                        });\n                    }\n                    fighter.state = 'ability4';\n                    fighter.stateTimer = 1.2;\n                    playSound('victory_sfx', 0.8);\n                    screenShake = 30;\n                }\n            }\n\n            ability.currentCd = ability.cooldown;\n            return true;\n        }\n\n        function useAwakening(fighter) {\n            if (fighter.energy < fighter.maxEnergy) return false;\n            \n            fighter.energy = 0;\n            fighter.isAwakened = true;\n            fighter.awakenedTimer = 20; // 20 seconds awakening\n            \n            if (fighter.type === 'luffy') {\n                fighter.health = Math.min(fighter.maxHealth, fighter.health + 50);\n                fighter.speed *= 1.15;\n                fighter.jumpForce *= 1.05;\n                playSound('victory_sfx', 0.6);\n            } else if (fighter.type === 'madara') {\n                fighter.health = Math.min(fighter.maxHealth, fighter.health + 30);\n                playSound('susanoo_sfx', 0.7);\n            } else if (fighter.type === 'sasuke') {\n                fighter.health = Math.min(fighter.maxHealth, fighter.health + 35);\n                fighter.speed *= 1.2; // Adult Sasuke is faster/more experienced\n                playSound('chidori_sfx', 0.7);\n            } else {\n                fighter.health = Math.min(fighter.maxHealth, fighter.health + 20);\n                playSound('victory_sfx', 0.4);\n            }\n            \n            addEffect(fighter.x, fighter.y - 60, 'impact');\n            screenShake = 10;\n            return true;\n        }\n\n        // AI logic\n        function updateAI(fighter, target, dt) {\n            // Bosses are immune to all stun effects and keep making decisions\n            // even during hit reactions, so they can always use abilities.\n            if (fighter.isBoss) fighter.stunTimer = 0;\n            if (fighter.stunTimer > 0 && !fighter.isBoss) return;\n            fighter.aiTimer -= dt;\n            if (fighter.aiTimer > 0) return;\n\n            const difficulty = config.settings.aiDifficulty;\n            const reactionTime = difficulty === 'easy' ? 0.8 : difficulty === 'hard' ? 0.3 : 0.5;\n            fighter.aiTimer = reactionTime + Math.random() * 0.3;\n\n            const dist = Math.abs(fighter.x - target.x);\n            const healthRatio = fighter.health / fighter.maxHealth;\n\n            // Face target (except when channeling a beam)\n            const isChanneledNarutoAI = fighter.type === 'naruto' && fighter.abilities[2] && fighter.abilities[2].active;\n            if (!isChanneledNarutoAI) {\n                fighter.facingRight = target.x > fighter.x;\n            }\n\n            // Use awakening if full energy\n            if (fighter.energy >= fighter.maxEnergy) {\n                useAwakening(fighter);\n            }\n\n            // Decision making\n            if (fighter.type === 'batBai') {\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && Math.random() > 0.8) {\n                    useAbility(fighter, 3, target);\n                } else if (healthRatio < 0.4 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (healthRatio < 0.6 && fighter.abilities[1].currentCd <= 0 && Math.random() > 0.5) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 120 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else if (dist < 80) {\n                    fighter.vx = fighter.facingRight ? -fighter.speed * 0.5 : fighter.speed * 0.5;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.7 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'bongDem') {\n                // B\u00f3ng \u0110\u00eam AI\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && dist < 350) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 300 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 200 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 100 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else if (dist < 60) {\n                    if (fighter.abilities[1].currentCd <= 0) {\n                        useAbility(fighter, 1, target);\n                    } else {\n                        fighter.vx = fighter.facingRight ? -fighter.speed : fighter.speed;\n                        if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                    }\n                } else {\n                    if (Math.random() > 0.5) {\n                        fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    }\n                    if (Math.random() > 0.7 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'luffy') {\n                // Luffy AI\n                const isNika = fighter.isAwakened;\n                if (isNika && fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && dist < 500) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 250 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 200 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (isNika && dist < 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (!isNika && dist < 100 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'madara') {\n                // Madara AI\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && dist < 450) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 400 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (healthRatio < 0.6 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 200 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'sasuke') {\n                // Sasuke AI\n                if (dist < 200 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 150 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && Math.random() > 0.8) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    if (Math.random() > 0.7 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'itachi') {\n                // ITACHI AI\n                if (fighter.skin === 'edo' && fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && Math.random() > 0.7) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 400 && fighter.abilities[2].currentCd <= 0 && Math.random() > 0.6) {\n                    useAbility(fighter, 2, target);\n                } else if (dist < 350 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 250 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 200) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else if (dist < 100) {\n                    fighter.vx = fighter.facingRight ? -fighter.speed : fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    if (Math.random() > 0.7 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'sukuna') {\n                // Sukuna AI\n                if (fighter.abilities[3].currentCd <= 0 && Math.random() > 0.7) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 350 && fighter.abilities[2].currentCd <= 0 && Math.random() > 0.6) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 300 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 200 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 100) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'gojo') {\n                // Gojo AI\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && Math.random() > 0.8) {\n                    useAbility(fighter, 3, target);\n                } else if (fighter.abilities[2].currentCd <= 0 && dist < 450) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 350 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 200 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 120) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'saitama') {\n                // Saitama AI\n                if (dist < 100 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist < 150 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 120 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 100) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'vuaQuy') {\n                // Vua Qu\u1ef7 AI\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && Math.random() > 0.7) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 350 && fighter.abilities[2].currentCd <= 0 && Math.random() > 0.6) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 120 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 100) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    if (Math.random() > 0.7 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'shadowGarden') {\n                // Shadow AI\n                if (fighter.abilities[3].currentCd <= 0 && Math.random() > 0.8) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 300 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 150 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 100) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'obito') {\n                // Obito AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 500 && Math.random() > 0.4) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 160 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 250 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 120) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'goku') {\n                // Goku AI\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && Math.random() > 0.8) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 400 && fighter.abilities[2].currentCd <= 0 && Math.random() > 0.7) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 150 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 120) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'naruto') {\n                // Naruto AI\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && Math.random() > 0.7) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 350 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist < 180 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 200 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'enel') {\n                // Enel AI\n                if (fighter.abilities[3] && fighter.abilities[3].currentCd <= 0 && dist < 500) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 300 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 250 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 150 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'tanjiro') {\n                // Tanjiro AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 600 && Math.random() > 0.4) {\n                    useAbility(fighter, 3, target);\n                } else if (fighter.energy >= fighter.maxEnergy) {\n                    useAwakening(fighter);\n                } else if (fighter.abilities[3].active && dist < 150) {\n                    // While Fire Breathing is active, stay close\n                    fighter.vx = fighter.facingRight ? fighter.speed * 1.2 : -fighter.speed * 1.2;\n                } else if (dist < 120 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 200 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 300 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'yuji') {\n                // Yuji AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 500) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 150 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 180 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (healthRatio < 0.5 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 120) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'garp') {\n                // Garp AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 600 && Math.random() > 0.4) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 150 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 180 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 120) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'doraemon') {\n                // Doraemon AI\n                if (fighter.abilities[2].currentCd <= 0 && dist < 400 && Math.random() > 0.6) {\n                    useAbility(fighter, 2, target);\n                } else if (fighter.abilities[3].currentCd <= 0 && dist < 400 && Math.random() > 0.6) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 300 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 400 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 200) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    if (Math.random() > 0.8 && fighter.grounded) {\n                        fighter.vy = -fighter.jumpForce;\n                        fighter.grounded = false;\n                    }\n                }\n            } else if (fighter.type === 'hashirama') {\n                // Hashirama AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 550 && Math.random() > 0.5) {\n                    useAbility(fighter, 3, target);\n                } else if (fighter.abilities[2].currentCd <= 0 && dist < 450 && Math.random() > 0.4) {\n                    useAbility(fighter, 2, target);\n                } else if (dist < 350 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 300 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 150) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                }\n            } else if (fighter.type === 'zoro') {\n                // Zoro AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 450 && Math.random() > 0.6) {\n                    useAbility(fighter, 3, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 180 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 220 && fighter.abilities[2].currentCd <= 0 && Math.random() > 0.4) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 140) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                }\n            } else if (fighter.type === 'yuta') {\n                // Yuta AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 500 && Math.random() > 0.4) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 400 && fighter.abilities[1].currentCd <= 0 && Math.random() > 0.5) {\n                    useAbility(fighter, 1, target);\n                } else if (dist > 300 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist < 150 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 140) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                }\n            } else if (fighter.type === 'rimuru') {\n                // Rimuru AI\n                if (fighter.abilities[3].currentCd <= 0 && dist < 500 && Math.random() > 0.6) {\n                    useAbility(fighter, 3, target);\n                } else if (dist < 400 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 120 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist < 350 && fighter.abilities[2].currentCd <= 0) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 140) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                }\n            } else if (fighter.type === 'poPanda') {\n                if (fighter.abilities[3].currentCd <= 0 && dist < 600 && Math.random() > 0.4) {\n                    useAbility(fighter, 3, target);\n                } else if (fighter.abilities[2].currentCd <= 0 && dist < 150) {\n                    useAbility(fighter, 2, target);\n                } else if (dist > 300 && fighter.abilities[1].currentCd <= 0) {\n                    useAbility(fighter, 1, target);\n                } else if (dist < 140 && fighter.abilities[0].currentCd <= 0) {\n                    useAbility(fighter, 0, target);\n                } else if (dist > 120) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                }\n            } else if (fighter.type === 'mahoraga') {\n                // Mahoraga AI behavior\n                if (dist > 130) {\n                    fighter.vx = fighter.facingRight ? fighter.speed : -fighter.speed;\n                    if (fighter.stateTimer <= 0) fighter.state = 'walk';\n                } else {\n                    fighter.vx = 0;\n                    // Try to use a random available ability\n                    const readyAbilities = [];\n                    for(let i=0; i<4; i++) {\n                        if (fighter.abilities[i].currentCd <= 0) readyAbilities.push(i);\n                    }\n                    if (readyAbilities.length > 0 && Math.random() > 0.5) {\n                        const randomIdx = readyAbilities[Math.floor(Math.random() * readyAbilities.length)];\n                        useAbility(fighter, randomIdx, target);\n                    }\n                }\n            }\n        }\n\n        // Update fighter\n        function updateFighter(fighter, target, dt) {\n            // Passive healing for Mahoraga\n            if (fighter.type === 'mahoraga') {\n                fighter.mahoragaTimer = (fighter.mahoragaTimer || 0) + dt;\n                if (fighter.mahoragaTimer >= 1.0) {\n                    fighter.mahoragaTimer = 0;\n                    fighter.health = Math.min(fighter.maxHealth, fighter.health + 10);\n                }\n            }\n\n            // Summon behavior for Chaien and Nobita\n            if (fighter.type === 'chaien' || fighter.type === 'nobita') {\n                fighter.activeTimer -= dt;\n                if (fighter.activeTimer <= 0) {\n                    fighter.health = 0; // Despawn\n                    return;\n                }\n                if (fighter.type === 'chaien') {\n                    fighter.shockwaveTimer += dt;\n                    if (fighter.shockwaveTimer >= 0.8) {\n                        fighter.shockwaveTimer = 0;\n                        hitEnemiesInRange(fighter, 350, fighter.damage || 20, 10, 2);\n                        screenShake = 10;\n                        addEffect(fighter.x, fighter.y - 60, 'impact');\n                        playSound('combo_attack_sfx', 0.5);\n                    }\n                } else if (fighter.type === 'nobita') {\n                    fighter.blastTimer += dt;\n                    if (fighter.blastTimer >= 0.1) {\n                        fighter.blastTimer = 0;\n                        const dir = fighter.facingRight ? 1 : -1;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            const dx = (enemy.x - fighter.x) * dir;\n                            if (dx > 0 && dx < 600 && Math.abs(enemy.y - (fighter.y - 60)) < 100) {\n                                dealDamage(enemy, fighter.damage || 5, fighter);\n                                enemy.vx += dir * 5; // Wind push\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Passive energy gain - Increased\n            fighter.energy = Math.min(fighter.maxEnergy, fighter.energy + 8.0 * dt);\n\n            // Awakening timer\n            if (fighter.isAwakened) {\n                fighter.awakenedTimer -= dt;\n                if (fighter.awakenedTimer <= 0) {\n                    fighter.isAwakened = false;\n                    // Reset stats\n                    if (fighter.type === 'sasuke') fighter.speed /= 1.2;\n                }\n            }\n\n            // Stun check. Bosses clear any stun immediately, including stuns\n            // applied directly by special abilities rather than dealDamage().\n            if (fighter.isBoss) fighter.stunTimer = 0;\n            if (fighter.stunTimer > 0 && !fighter.isBoss) {\n                fighter.stunTimer -= dt;\n                fighter.vx = 0;\n                fighter.state = 'hit';\n                if (fighter.stunTimer <= 0) fighter.state = 'idle';\n            }\n\n            // State timer\n            if (fighter.stateTimer > 0) {\n                fighter.stateTimer -= dt;\n                if (fighter.stateTimer <= 0 && fighter.state !== 'victory') {\n                    fighter.state = 'idle';\n                }\n            }\n\n            // Ability cooldowns\n            for (let ab of fighter.abilities) {\n                if (ab.currentCd > 0) ab.currentCd = Math.max(0, ab.currentCd - dt);\n                \n                // Hashirama abilities\n                if (fighter.type === 'hashirama' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    // Deep Forest Emergence Tick Damage\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.5) {\n                        ab.tickTimer = 0;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (Math.abs(fighter.x - enemy.x) < 500) {\n                                dealDamage(enemy, ab.damage, fighter);\n                                enemy.stunTimer = Math.max(enemy.stunTimer, 0.3);\n                            }\n                        }\n                    }\n                }\n                if (fighter.type === 'hashirama' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Giant Falling Fists logic (Anime Mugen style)\n                    ab.spawnTimer = (ab.spawnTimer || 0) + dt;\n                    if (ab.spawnTimer >= 0.12) { // Slightly faster spawn\n                        ab.spawnTimer = 0;\n                        if (!ab.fists) ab.fists = [];\n                        if (ab.fists.length < 35) { // More fists\n                            const enemies = getEnemies(fighter);\n                            const targetX = enemies.length > 0 ? enemies[0].x : fighter.x + (fighter.facingRight ? 400 : -400);\n                            ab.fists.push({\n                                x: targetX + (Math.random() - 0.5) * 1000,\n                                y: -1200, // Spawn much higher for better \"falling\" feel\n                                vy: 55 + Math.random() * 25, // Faster slam\n                                angle: (Math.random() - 0.5) * 0.1, // Near vertical\n                                scale: 2.5 + Math.random() * 1.5,\n                                hitDone: false\n                            });\n                        }\n                    }\n\n                    if (ab.fists) {\n                        for (let j = ab.fists.length - 1; j >= 0; j--) {\n                            const f = ab.fists[j];\n                            f.y += f.vy * dt * 60;\n                            if (f.y >= GROUND_Y && !f.hitDone) {\n                                f.hitDone = true;\n                                screenShake = Math.max(screenShake, 30);\n                                playSound('punch_sfx', 0.9);\n                                addEffect(f.x, GROUND_Y, 'impact');\n                                // Deal burst damage on impact\n                                const enemies = getEnemies(fighter);\n                                for (const enemy of enemies) {\n                                    if (Math.abs(enemy.x - f.x) < 150 * f.scale) {\n                                        dealDamage(enemy, 15, fighter);\n                                    }\n                                }\n                            }\n                            if (f.y > GROUND_Y + 1200) ab.fists.splice(j, 1);\n                        }\n                    }\n                }\n\n\n                if (fighter.type === 'zoro' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    // Skill 3 AOE Damage Tick\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.15) {\n                        ab.tickTimer = 0;\n                        hitEnemiesInRange(fighter, ab.range + 80, ab.damage, 6, 3);\n                        screenShake = Math.max(screenShake, 5);\n                        if (Math.random() > 0.5) playSound('sword_slash_sfx', 0.4);\n                    }\n                    // Pull enemies slightly towards Zoro (Suction)\n                    const enemies = getEnemies(fighter);\n                    for (const enemy of enemies) {\n                        if (Math.abs(fighter.x - enemy.x) < 250) {\n                            const pullDir = enemy.x > fighter.x ? -1 : 1;\n                            enemy.vx += pullDir * 1.5;\n                        }\n                    }\n                }\n\n                if (fighter.type === 'zoro' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Ashura Sequence: Startup -> Dash -> Impact\n                    fighter.vx = 0;\n                    fighter.vy = 0;\n                    if (ab.targetFighter) {\n                        ab.targetFighter.stunTimer = Math.max(ab.targetFighter.stunTimer, 0.2);\n                        ab.targetFighter.vx = 0;\n                    }\n\n                    if (ab.phase === 'startup') {\n                        if (ab.activeTimer < 7.2) {\n                            ab.phase = 'dash';\n                            const dir = fighter.facingRight ? 1 : -1;\n                            if (ab.targetFighter) {\n                                fighter.x = ab.targetFighter.x + dir * 180;\n                                fighter.facingRight = !fighter.facingRight; // Face back towards target\n                            }\n                            playSound('dash_sfx', 0.8);\n                            screenShake = 40;\n                        }\n                    } else if (ab.phase === 'dash') {\n                        if (ab.activeTimer < 7.0) {\n                            ab.phase = 'impact';\n                            ab.tickTimer = 0;\n                            ab.slashCount = 0;\n                        }\n                    } else if (ab.phase === 'impact') {\n                        if (fighter.skin === 'wano') {\n                            // Wano Ashura sequence: after the startup and dash,\n                            // the first 4 seconds are filled with rapid black\n                            // slashes. The final 3 seconds hold one much larger\n                            // slash while the ground repeatedly erupts.\n                            const t = ab.activeTimer;\n                            const continuousEnd = 3.0; // 7 -> 3 = 4 seconds\n\n                            if (t > continuousEnd) {\n                                ab.tickTimer = (ab.tickTimer || 0) + dt;\n                                if (ab.tickTimer >= 0.11) {\n                                    ab.tickTimer = 0;\n                                    ab.slashCount = (ab.slashCount || 0) + 1;\n                                    const victim = ab.targetFighter;\n                                    if (victim && victim.health > 0) {\n                                        dealDamage(victim, ab.damage, fighter);\n                                        addEffect(victim.x, victim.y - 65, 'zoro_wano_black_slash', {\n                                            rotation: (Math.random() - 0.5) * 0.9,\n                                            length: 520 + Math.random() * 180,\n                                            width: 36 + Math.random() * 18,\n                                            timer: 0.28,\n                                            maxTimer: 0.28\n                                        });\n                                        screenShake = Math.max(screenShake, 10);\n                                        if (Math.random() > 0.25) playSound('sword_slash_sfx', 0.45);\n                                    }\n                                }\n                            } else {\n                                if (!ab.finalSlashDone) {\n                                    ab.finalSlashDone = true;\n                                    ab.finalDamageTimer = 0;\n                                    const victim = ab.targetFighter;\n                                    if (victim && victim.health > 0) {\n                                        dealDamage(victim, ab.damage * 8, fighter);\n                                        addEffect(victim.x, victim.y - 70, 'zoro_wano_final_slash', {\n                                            rotation: -0.22,\n                                            length: 1080,\n                                            width: 190,\n                                            timer: 3.0,\n                                            maxTimer: 3.0\n                                        });\n                                        addEffect(victim.x, GROUND_Y, 'zoro_wano_ground_burst', {\n                                            radius: 380,\n                                            heavy: true,\n                                            timer: 3.0,\n                                            maxTimer: 3.0\n                                        });\n                                        screenShake = 75;\n                                        playSound('sword_slash_sfx', 1.0);\n                                    }\n                                }\n\n                                // The finishing slash keeps the opponent under\n                                // pressure while chunks of ground fly upward.\n                                ab.groundBurstTimer = (ab.groundBurstTimer || 0) + dt;\n                                if (ab.groundBurstTimer >= 0.28) {\n                                    ab.groundBurstTimer = 0;\n                                    const burstX = ab.targetFighter && ab.targetFighter.health > 0\n                                        ? ab.targetFighter.x\n                                        : fighter.x;\n                                    addEffect(burstX, GROUND_Y, 'zoro_wano_ground_burst', {\n                                        radius: 150 + Math.random() * 90,\n                                        timer: 0.65,\n                                        maxTimer: 0.65\n                                    });\n                                    screenShake = Math.max(screenShake, 16);\n                                }\n\n                                ab.finalDamageTimer = (ab.finalDamageTimer || 0) + dt;\n                                if (ab.finalDamageTimer >= 0.42) {\n                                    ab.finalDamageTimer = 0;\n                                    if (ab.targetFighter && ab.targetFighter.health > 0) {\n                                        dealDamage(ab.targetFighter, ab.damage * 2, fighter);\n                                    }\n                                }\n                            }\n                        } else {\n                            ab.tickTimer = (ab.tickTimer || 0) + dt;\n                            if (ab.tickTimer >= 0.08 && ab.activeTimer > 1.0) {\n                                ab.tickTimer = 0;\n                                ab.slashCount = (ab.slashCount || 0) + 1;\n                                if (ab.targetFighter) {\n                                    dealDamage(ab.targetFighter, ab.damage, fighter);\n                                    const rotation = ab.slashCount * (Math.PI / 4); \n                                    addEffect(ab.targetFighter.x, ab.targetFighter.y - 60, 'ashura_slash', { rotation, timer: 0.6, maxTimer: 0.6 });\n                                    screenShake = Math.max(screenShake, 35);\n                                    if (Math.random() > 0.3) playSound('sword_slash_sfx', 0.6);\n                                }\n                            }\n                        }\n\n                        if (ab.activeTimer <= 1.0 && !ab.hitDone) {\n                            ab.hitDone = true;\n                            if (ab.targetFighter) {\n                                dealDamage(ab.targetFighter, ab.damage * 4, fighter);\n                                addEffect(ab.targetFighter.x, ab.targetFighter.y - 60, 'impact');\n                                screenShake = 60;\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'yuta' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Yuta Ultimate: Stationary Purple Beam\n                    fighter.vx = 0;\n                    fighter.vy = 0;\n                    fighter.state = 'ability4';\n                    fighter.stateTimer = Math.max(fighter.stateTimer, 0.2);\n\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.1) {\n                        ab.tickTimer = 0;\n                        const dir = fighter.facingRight ? 1 : -1;\n                        const beamReach = 1000;\n                        const beamHeight = 250;\n                        \n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                const dx = (enemy.x - fighter.x) * dir;\n                                if (dx > 0 && dx < beamReach && Math.abs(enemy.y - (fighter.y - 60)) < beamHeight / 2) {\n                                    dealDamage(enemy, ab.damage / 20, fighter); // Tick damage\n                                    enemy.vx = dir * 5; // Slight push\n                                }\n                            }\n                        }\n                        screenShake = Math.max(screenShake, 20);\n                    }\n                }\n\n                // Domain Expansion specific behavior\n                if (fighter.type === 'itachi' && fighter.abilities.indexOf(ab) === 1 && ab.active) {\n                    // \u1ea2o Thu\u1eadt: Kh\u00f4ng Gian \u0110en Tick Damage\n                    const enemies = getEnemies(fighter);\n                    for (const enemy of enemies) {\n                        if (!enemy.invulnerable) {\n                            const dist = Math.abs(fighter.x - enemy.x);\n                            if (dist < 400) {\n                                enemy.stunTimer = Math.max(enemy.stunTimer, 0.2);\n                                ab.tickTimer = (ab.tickTimer || 0) + dt;\n                                if (ab.tickTimer >= 0.5) {\n                                    ab.tickTimer = 0;\n                                    dealDamage(enemy, ab.damage, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'sukuna' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    // Tick damage to enemies in range\n                    const enemies = getEnemies(fighter);\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.2) {\n                        ab.tickTimer = 0;\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                const dist = Math.abs(fighter.x - enemy.x);\n                                if (dist < 400) {\n                                    dealDamage(enemy, ab.damage, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'madara' && fighter.abilities.indexOf(ab) === 1 && ab.active) {\n                    // H\u00e0o H\u1ecfa Di\u1ec7t Tick Damage\n                    const enemies = getEnemies(fighter);\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.2) {\n                        ab.tickTimer = 0;\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                const dir = fighter.facingRight ? 1 : -1;\n                                const dx = (enemy.x - fighter.x) * dir;\n                                if (dx > 0 && dx < 550 && Math.abs(enemy.y - fighter.y) < 200) {\n                                    dealDamage(enemy, 8, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'madara' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Susanoo To\u00e0n Ch\u00e2n Th\u1ec3 Periodic Slash\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 1.5) {\n                        ab.tickTimer = 0;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            const dist = Math.abs(fighter.x - enemy.x);\n                            if (dist < 600) {\n                                dealDamage(enemy, ab.damage, fighter);\n                                addEffect(enemy.x, enemy.y - 80, 'impact');\n                            }\n                        }\n                        screenShake = 20;\n                    }\n                }\n\n                if (fighter.type === 'bongDem' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // L\u00e3nh \u0110\u1ecba B\u00f3ng \u0110\u00eam Tick Damage\n                    const enemies = getEnemies(fighter);\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 1.0) {\n                        ab.tickTimer = 0;\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                const dist = Math.abs(fighter.x - enemy.x);\n                                if (dist < 400) {\n                                    dealDamage(enemy, ab.damage, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'gojo' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    // Domain Expansion: Infinite Void effect\n                    const enemies = getEnemies(fighter);\n                    for (const enemy of enemies) {\n                        if (!enemy.invulnerable) {\n                            const dist = Math.abs(fighter.x - enemy.x);\n                            if (dist < 500) {\n                                enemy.stunTimer = Math.max(enemy.stunTimer, 0.5);\n                                ab.tickTimer = (ab.tickTimer || 0) + dt;\n                                if (ab.tickTimer >= 0.3) {\n                                    ab.tickTimer = 0;\n                                    dealDamage(enemy, ab.damage, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'gojo' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Hollow Purple logic\n                    if (ab.activeTimer <= 0.1 && !ab.exploded) {\n                        ab.exploded = true;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                dealDamage(enemy, ab.damage, fighter);\n                                const dir = enemy.x > fighter.x ? 1 : -1;\n                                enemy.vx = dir * 30;\n                                enemy.vy = -10;\n                                enemy.grounded = false;\n                            }\n                        }\n                        screenShake = 40;\n                        playSound('fireball_sfx', 1.0);\n                        addEffect(fighter.x, fighter.y - 300, 'impact');\n                    }\n                }\n\n                if (fighter.type === 'vuaQuy' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // L\u00e3nh \u0110\u1ecba \u0110\u1ecba Ng\u1ee5c Tick Damage\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 1.0) {\n                        ab.tickTimer = 0;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                dealDamage(enemy, ab.damage, fighter);\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'goku' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    // Kamehameha logic\n                    if (ab.activeTimer < 0.7 && ab.charging) {\n                        ab.charging = false;\n                        screenShake = 20;\n                    }\n                    if (!ab.charging) {\n                        ab.hitTick = (ab.hitTick || 0) + dt;\n                        if (ab.hitTick >= 0.1) {\n                            ab.hitTick = 0;\n                            const enemies = getEnemies(fighter);\n                            const dir = fighter.facingRight ? 1 : -1;\n                            const dmg = fighter.isSSJ2 ? 25 : 10;\n                            for (const enemy of enemies) {\n                                const dx = (enemy.x - fighter.x) * dir;\n                                if (dx > 0 && dx < 800 && Math.abs(enemy.y - fighter.y) < (fighter.isSSJ2 ? 200 : 100)) {\n                                    dealDamage(enemy, dmg, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'sasuke' && fighter.abilities.indexOf(ab) === 0 && ab.active) {\n                    // L\u00f4i Long Thi\u00ean Ph\u1ea1t immobilization\n                    fighter.vx = 0;\n                    fighter.vy = 0;\n                    fighter.state = 'ability1';\n                    fighter.stateTimer = Math.max(fighter.stateTimer, 0.2);\n\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.5) {\n                        ab.tickTimer = 0;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (Math.abs(enemy.x - ab.strikeX) < 150) {\n                                dealDamage(enemy, Math.floor(ab.damage / 5), fighter);\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'sasuke' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Chibaku Tensei logic\n                    ab.sphereX += (ab.targetX - ab.sphereX) * 0.05;\n                    ab.sphereY += (ab.targetY - ab.sphereY) * 0.05;\n\n                    const enemies = getEnemies(fighter);\n                    for (const enemy of enemies) {\n                        if (!enemy.invulnerable) {\n                            const dx = ab.sphereX - enemy.x;\n                            const dy = ab.sphereY - (enemy.y - 60);\n                            const dist = Math.sqrt(dx * dx + dy * dy);\n                            if (dist < 800) {\n                                const force = 1500 / (dist + 50);\n                                enemy.vx += (dx / dist) * force * dt * 20;\n                                enemy.vy += (dy / dist) * force * dt * 20;\n                                enemy.grounded = false;\n                            }\n                        }\n                    }\n\n                    if (Math.random() > 0.3) {\n                        const startX = Math.random() * 720;\n                        const startY = GROUND_Y;\n                        ab.particles.push({ x: startX, y: startY, size: 10 + Math.random() * 20, vx: 0, vy: 0 });\n                    }\n                    \n                    for (let j = ab.particles.length - 1; j >= 0; j--) {\n                        const p = ab.particles[j];\n                        const dx = ab.sphereX - p.x;\n                        const dy = ab.sphereY - p.y;\n                        const d = Math.sqrt(dx * dx + dy * dy);\n                        if (d < 30) {\n                            ab.particles.splice(j, 1);\n                        } else {\n                            p.vx += (dx / d) * 15 * dt * 60;\n                            p.vy += (dy / d) * 15 * dt * 60;\n                            p.x += p.vx * dt * 60;\n                            p.y += p.vy * dt * 60;\n                        }\n                    }\n\n                    if (ab.activeTimer <= 0.1) {\n                        for (const enemy of enemies) {\n                            const dx = ab.sphereX - enemy.x;\n                            const dy = ab.sphereY - (enemy.y - 60);\n                            const dist = Math.sqrt(dx * dx + dy * dy);\n                            if (dist < 250) {\n                                dealDamage(enemy, ab.damage, fighter);\n                            }\n                        }\n                        screenShake = 30;\n                        playSound('fireball_sfx', 1.0);\n                        addEffect(ab.sphereX, ab.sphereY, 'impact');\n                    }\n                }\n\n                if (fighter.type === 'luffy' && fighter.abilities.indexOf(ab) === 2 && ab.active && fighter.isAwakened && fighter.skin === 'nika') {\n                    // Gigant Stomp Logic\n                    fighter.vx = 0;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = Math.max(fighter.stateTimer, 0.2);\n\n                    if (ab.phase === 'jump') {\n                        if (fighter.vy > -5) {\n                            ab.phase = 'stomp';\n                            fighter.vy = 60; // Powerful downward slam\n                        }\n                    } else if (ab.phase === 'stomp') {\n                        if (fighter.y >= GROUND_Y - 20 && !ab.hitDone) {\n                            ab.hitDone = true;\n                            ab.phase = 'landed';\n                            ab.activeTimer = 0.8;\n                            screenShake = 100;\n                            playSound('fireball_sfx', 1.0);\n                            hitEnemiesInRange(fighter, 550, 60, 30, 20);\n                            \n                            // Massive ground explosion effects matching user reference\n                            for(let j=0; j<25; j++) {\n                                const offX = (Math.random()-0.5)*800;\n                                addEffect(fighter.x + offX, GROUND_Y, 'fire_land');\n                                if (j < 15) addEffect(fighter.x + offX*0.8, GROUND_Y, 'rock_debris');\n                                if (j < 10) addEffect(fighter.x + offX*0.6, GROUND_Y, 'impact');\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'luffy' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Bajrang Gun Smashing logic\n                    if (ab.activeTimer > 0.8) {\n                        const enemies = getEnemies(fighter);\n                        if (enemies.length > 0) {\n                            fighter.vx = (enemies[0].x - fighter.x) * 0.05;\n                        }\n                        fighter.vy = -5;\n                    } else if (ab.activeTimer > 0.1) {\n                        fighter.vy = 50;\n                    } else if (!ab.hitDone) {\n                        ab.hitDone = true;\n                        const isGear4 = fighter.type === 'luffy' && fighter.skin === 'gear4';\n                        hitEnemiesInRange(fighter, isGear4 ? 720 : 600, ab.damage, 35, 25);\n                        screenShake = isGear4 ? 85 : 50;\n                        playSound('punch_sfx', 1.0);\n                        addEffect(fighter.x, GROUND_Y - 20, 'impact');\n                        if (isGear4) {\n                            // Massive debris and extra impact effects for Gear 4 King Kong Gun\n                            for(let j=0; j<25; j++) {\n                                addEffect(fighter.x + (Math.random()-0.5)*720, GROUND_Y, 'rock_debris');\n                                if (j < 10) addEffect(fighter.x + (Math.random()-0.5)*600, GROUND_Y, 'impact');\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'shadowGarden' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // I AM ATOMIC logic\n                    if (ab.activeTimer <= 0.1 && !ab.exploded) {\n                        ab.exploded = true;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            dealDamage(enemy, ab.damage, fighter);\n                            const dir = enemy.x > fighter.x ? 1 : -1;\n                            enemy.vx = dir * 40;\n                            enemy.vy = -15;\n                            enemy.grounded = false;\n                        }\n                        screenShake = 60;\n                        playSound('fireball_sfx', 1.0);\n                        addEffect(fighter.x, fighter.y - 150, 'impact');\n                    }\n                }\n\n                if (fighter.type === 'naruto' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    // Kurama Shockwave Beam logic\n                    fighter.vx = 0; // Stop movement\n                    fighter.vy = 0;\n                    fighter.state = 'ability3';\n                    fighter.stateTimer = Math.max(fighter.stateTimer, 0.2);\n                    \n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.1) {\n                        ab.tickTimer = 0;\n                        const dir = fighter.facingRight ? 1 : -1;\n                        const reach = 1050; // Slightly more reach\n                        const beamHeight = 220; // Taller beam hitbox\n                        \n                        // Robust target detection: primary target + potential others\n                        const possibleTargets = [target, player, opponent, ...allies, ...summons];\n                        const enemies = [...new Set(possibleTargets)].filter(e => {\n                            if (!e || e.health <= 0 || e === fighter) return false;\n                            // Basic logic: if I'm player side, hit opponent side and vice versa\n                            const isFighterPlayerSide = (fighter === player || allies.includes(fighter) || (fighter.owner && (fighter.owner === player || allies.includes(fighter.owner))));\n                            const isTargetPlayerSide = (e === player || allies.includes(e) || (e.owner && (e.owner === player || allies.includes(e.owner))));\n                            return isFighterPlayerSide !== isTargetPlayerSide;\n                        });\n\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                const dx = (enemy.x - fighter.x) * dir;\n                                // Improved dy: Check if any part of the enemy (from feet to head) intersects the beam height (at y-100)\n                                const enemyTop = enemy.y - enemy.height;\n                                const enemyBottom = enemy.y;\n                                const beamY = fighter.y - 100;\n                                \n                                const isVerticalHit = (beamY + beamHeight/2 > enemyTop) && (beamY - beamHeight/2 < enemyBottom);\n                                \n                                if (dx > -20 && dx < reach && isVerticalHit) {\n                                    dealDamage(enemy, 8, fighter); \n                                    enemy.vx = dir * 8; // Controlled knockback\n                                    // Removed lift to prevent floating/hovering\n                                }\n                            }\n                        }\n                        screenShake = 15;\n                    }\n                }\n\n                if (fighter.type === 'naruto' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Nine-Tails Mode buffs\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.1) {\n                        ab.tickTimer = 0;\n                        // Reduced passive healing in Kurama mode\n                        fighter.health = Math.min(fighter.maxHealth, fighter.health + 1);\n                    }\n\n                    // Luc Dao Ultimate Sequence\n                    if (fighter.skin === 'lucDao' && ab.ultPhase) {\n                        ab.ultTimer -= dt;\n                        fighter.vx = 0;\n                        fighter.state = 'ability4';\n                        fighter.stateTimer = Math.max(fighter.stateTimer, 0.2);\n\n                        if (ab.ultPhase === 'summon' && ab.ultTimer < 2.5) {\n                            ab.ultPhase = 'holding';\n                        } else if (ab.ultPhase === 'holding' && ab.ultTimer < 1.0) {\n                            ab.ultPhase = 'throwing';\n                        } else if (ab.ultPhase === 'throwing' && !ab.hitDone) {\n                            ab.hitDone = true;\n                            const dir = fighter.facingRight ? 1 : -1;\n                            // Throw two giant projectiles\n                            for (let k = 0; k < 2; k++) {\n                                projectiles.push({\n                                    x: fighter.x + dir * 100,\n                                    y: fighter.y - 300,\n                                    vx: dir * 18,\n                                    vy: 10 + k * 5,\n                                    owner: fighter,\n                                    damage: 100,\n                                    timer: 3.0,\n                                    type: k === 0 ? 'rasenshuriken' : 'bijuu_bomb'\n                                });\n                            }\n                            playSound('rasengan_sfx', 1.0);\n                            screenShake = 30;\n                        }\n\n                        if (ab.ultTimer <= 0) {\n                            ab.ultPhase = null;\n                        }\n                    }\n\n                    // Stat buffs are applied in this block by logic\n                    if (!ab.buffsApplied) {\n                        ab.buffsApplied = true;\n                        fighter.speed *= 1.25;\n                        fighter.jumpForce *= 1.1;\n                    }\n                }\n\n                if (fighter.type === 'enel' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Raigo atmosphere\n                    screenShake = Math.max(screenShake, 3);\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.5) {\n                        ab.tickTimer = 0;\n                        // Small lightning bolts during charge\n                        const randX = Math.random() * 720;\n                        addEffect(randX, GROUND_Y, 'lightning_strike');\n                    }\n                }\n\n                if (fighter.type === 'tanjiro' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    // Constant Flux Tick Damage\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.2) {\n                        ab.tickTimer = 0;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (Math.abs(fighter.x - enemy.x) < ab.range) {\n                                dealDamage(enemy, Math.floor(ab.damage / 7), fighter);\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'tanjiro' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Sequence: Jump -> Dive -> Pillar\n                    if (ab.phase === 'jump') {\n                        fighter.vx = 0;\n                        if (fighter.vy > -5) {\n                            ab.phase = 'dive';\n                        }\n                    } else if (ab.phase === 'dive') {\n                        fighter.vx = 0;\n                        fighter.vy = 45; // Fast dive\n                        if (fighter.y >= GROUND_Y - 10) {\n                            ab.phase = 'pillar';\n                            ab.activeTimer = 4.0; // Last 4 seconds as requested\n                            screenShake = 60;\n                            playSound('fireball_sfx', 1.0);\n                        }\n                    } else if (ab.phase === 'pillar') {\n                        fighter.vx = 0;\n                        fighter.vy = 0;\n                        fighter.y = GROUND_Y;\n                        \n                        // Pillar tick damage\n                        ab.tickTimer = (ab.tickTimer || 0) + dt;\n                        if (ab.tickTimer >= 0.1) {\n                            ab.tickTimer = 0;\n                            const enemies = getEnemies(fighter);\n                            for (const enemy of enemies) {\n                                if (Math.abs(fighter.x - enemy.x) < 280) {\n                                    dealDamage(enemy, 12, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'yuji' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Ultimate Sequence: teleporting -> punching\n                    if (ab.sequence === 'teleporting') {\n                        if (ab.targetFighter && ab.targetFighter.health > 0) {\n                            fighter.x = ab.targetFighter.x - (ab.targetFighter.facingRight ? 80 : -80);\n                            fighter.facingRight = (ab.targetFighter.x > fighter.x);\n                            ab.sequence = 'punching';\n                            ab.punchCount = 0;\n                            ab.punchTimer = 0;\n                            fighter.state = 'ability3';\n                        } else {\n                            ab.active = false;\n                        }\n                    } else if (ab.sequence === 'punching') {\n                        fighter.vx = 0;\n                        fighter.vy = 0;\n                        ab.punchTimer -= dt;\n                        if (ab.punchTimer <= 0 && ab.punchCount < 5) {\n                            ab.punchTimer = 0.25;\n                            ab.punchCount++;\n                            if (ab.targetFighter && ab.targetFighter.health > 0) {\n                                dealDamage(ab.targetFighter, ab.damage, fighter);\n                                ab.targetFighter.stunTimer = 0.5;\n                                // dealDamage already handles black_flash effect and sound\n                                // We add extra screen shake for the ultimate\n                                screenShake = 45;\n                            }\n                        }\n                        if (ab.punchCount >= 5 && ab.punchTimer <= 0) {\n                            ab.active = false;\n                        }\n                    }\n                }\n\n                if (fighter.type === 'garp' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Sequence: Jump -> Explode & Stay\n                    if (ab.phase === 'jump') {\n                        fighter.vx = 0;\n                        if (fighter.vy > -5) {\n                            ab.phase = 'explode';\n                            ab.tickTimer = 0;\n                            screenShake = 60;\n                            playSound('fireball_sfx', 1.0);\n                        }\n                    } else if (ab.phase === 'explode') {\n                        fighter.vx = 0;\n                        fighter.vy = 0;\n                        // Galaxy Impact Explosion Damage\n                        ab.tickTimer = (ab.tickTimer || 0) + dt;\n                        if (ab.tickTimer >= 0.2) {\n                            ab.tickTimer = 0;\n                            const enemies = getEnemies(fighter);\n                            for (const enemy of enemies) {\n                                if (Math.abs(fighter.x - enemy.x) < 450) {\n                                    dealDamage(enemy, ab.damage, fighter);\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'saitama' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Saitama Ultimate Sequence\n                    if (ab.triggered) {\n                        if (ab.phase === 'teleporting') {\n                            if (ab.targetFighter && ab.targetFighter.health > 0) {\n                                fighter.x = ab.targetFighter.x - (ab.targetFighter.facingRight ? 160 : -160);\n                                fighter.facingRight = (ab.targetFighter.x > fighter.x);\n                                if (ab.activeTimer < 6.5) {\n                                    ab.phase = 'punching';\n                                    fighter.state = 'ability3';\n                                }\n                            } else {\n                                ab.active = false;\n                                fighter.invulnerable = false;\n                            }\n                        } else if (ab.phase === 'punching') {\n                            fighter.vx = 0;\n                            fighter.vy = 0;\n                            fighter.state = 'ability3';\n                            fighter.invulnerable = true;\n\n                            // Periodic Damage and Massive Pressure\n                            ab.hitTick = (ab.hitTick || 0) + dt;\n                            if (ab.hitTick >= 0.1) {\n                                ab.hitTick = 0;\n                                const dir = fighter.facingRight ? 1 : -1;\n                                const enemies = getEnemies(fighter);\n                                for (const enemy of enemies) {\n                                    const dx = (enemy.x - fighter.x) * dir;\n                                    // Massive reach for the air pressure blast\n                                    if (dx > 0 && dx < 1000 && Math.abs(enemy.y - fighter.y) < 400) {\n                                        dealDamage(enemy, 5, fighter);\n                                        enemy.vx = dir * 45; // Increased push\n                                        enemy.vy = 0;        // No upward lift\n                                        enemy.grounded = false;\n                                    }\n                                }\n                                screenShake = Math.max(screenShake, 40);\n                                if (Math.random() > 0.8) playSound('punch_sfx', 1.0);\n                            }\n\n                            if (ab.activeTimer <= 0.1) {\n                                ab.active = false;\n                                fighter.invulnerable = false;\n                                if (ab.targetFighter) ab.targetFighter.stunTimer = 0;\n                            }\n                        }\n                    } else {\n                        // Still in waiting window\n                        fighter.invulnerable = false;\n                    }\n                }\n\n                if (fighter.type === 'poPanda' && fighter.abilities.indexOf(ab) === 1 && ab.active) {\n                    // Rolling damage\n                    const dir = fighter.facingRight ? 1 : -1;\n                    fighter.vx = dir * 18;\n                    if (hitEnemiesInRange(fighter, 100, 5, 10, 2)) {\n                        screenShake = Math.max(screenShake, 5);\n                    }\n                }\n\n                if (fighter.type === 'poPanda' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    if (ab.phase === 'hold') {\n                        if (ab.targetFighter) {\n                            // Pull target close\n                            ab.targetFighter.x = fighter.x + (fighter.facingRight ? 40 : -40);\n                            ab.targetFighter.y = fighter.y;\n                        }\n                        if (ab.activeTimer <= 0.1 && !ab.hitDone) {\n                            ab.hitDone = true;\n                            ab.phase = 'skadoosh';\n                            if (ab.targetFighter) {\n                                dealDamage(ab.targetFighter, ab.damage, fighter);\n                                const dir = ab.targetFighter.x > fighter.x ? 1 : -1;\n                                ab.targetFighter.vx = dir * 50;\n                                ab.targetFighter.vy = -20;\n                                ab.targetFighter.grounded = false;\n                            }\n                            screenShake = 60;\n                            playSound('fireball_sfx', 1.0);\n                            addEffect(fighter.x, fighter.y - 60, 'skadoosh');\n                        }\n                    }\n                }\n\n                if (fighter.type === 'poPanda' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    if (ab.phase === 'summoning') {\n                        fighter.vx = 0;\n                        if (ab.activeTimer < 3.2) {\n                            ab.phase = 'rushing';\n                            ab.dragonX = fighter.x;\n                            ab.dragonY = fighter.y - 120;\n                        }\n                    } else if (ab.phase === 'rushing') {\n                        fighter.vx = 0;\n                        if (ab.targetFighter) {\n                            const dx = ab.targetFighter.x - ab.dragonX;\n                            const dy = (ab.targetFighter.y - 60) - ab.dragonY;\n                            const dist = Math.sqrt(dx*dx + dy*dy);\n                            if (dist < 40) {\n                                ab.phase = 'wrapping';\n                            } else {\n                                ab.dragonX += dx * 0.18;\n                                ab.dragonY += dy * 0.18;\n                            }\n                        }\n                    } else if (ab.phase === 'wrapping') {\n                        fighter.vx = 0;\n                        if (ab.targetFighter) {\n                            ab.targetFighter.stunTimer = 0.5;\n                            ab.targetFighter.vx = 0;\n                            ab.dragonX = ab.targetFighter.x;\n                            ab.dragonY = ab.targetFighter.y - 60;\n                            // Periodic shredding damage while wrapping\n                            ab.tickTimer = (ab.tickTimer || 0) + dt;\n                            if (ab.tickTimer >= 0.1) {\n                                ab.tickTimer = 0;\n                                dealDamage(ab.targetFighter, 8, fighter);\n                                screenShake = Math.max(screenShake, 12);\n                            }\n                        }\n                        if (ab.activeTimer < 0.6) {\n                            ab.phase = 'exploding';\n                        }\n                    } else if (ab.phase === 'exploding') {\n                        if (!ab.hitDone) {\n                            ab.hitDone = true;\n                            if (ab.targetFighter) {\n                                dealDamage(ab.targetFighter, ab.damage, fighter);\n                                const dir = ab.targetFighter.x > fighter.x ? 1 : -1;\n                                ab.targetFighter.vx = dir * 40;\n                                ab.targetFighter.vy = -15;\n                                ab.targetFighter.grounded = false;\n                                addEffect(ab.targetFighter.x, ab.targetFighter.y - 60, 'bagua_explosion');\n                            }\n                            screenShake = 70;\n                            playSound('fireball_sfx', 1.0);\n                        }\n                    }\n                }\n\n                if (fighter.type === 'obito' && fighter.abilities.indexOf(ab) === 2 && ab.active) {\n                    fighter.vx = 0;\n                    if (ab.activeTimer <= 1.0 && !ab.fired) {\n                        ab.fired = true;\n                        const dir = fighter.facingRight ? 1 : -1;\n                        const offsets = [150, 300, 450, 600];\n                        for (const offset of offsets) {\n                            projectiles.push({\n                                x: fighter.x + dir * offset,\n                                y: GROUND_Y,\n                                vx: 0, vy: 0,\n                                owner: fighter,\n                                damage: ab.damage,\n                                timer: 4.0, // Lasts 4 seconds as requested\n                                type: 'black_fire_column'\n                            });\n                        }\n                        playSound('fireball_sfx', 1.0);\n                        screenShake = 30;\n                    }\n                }\n\n                if (fighter.type === 'obito' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Ngo\u1ea1i \u0110\u1ea1o Ma T\u01b0\u1ee3ng Shockwave & Lightning tick\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.2) {\n                        ab.tickTimer = 0;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (Math.abs(fighter.x - enemy.x) < 450) {\n                                dealDamage(enemy, Math.floor(ab.damage / 8), fighter);\n                                // Spawn lightning strikes near enemies\n                                if (Math.random() > 0.4) {\n                                    addEffect(enemy.x + (Math.random()-0.5)*120, GROUND_Y, 'lightning_strike');\n                                }\n                            }\n                        }\n                        // Random atmospheric lightning strikes around the statue\n                        if (Math.random() > 0.3) {\n                            addEffect(fighter.x + (Math.random()-0.5)*600, GROUND_Y, 'lightning_strike');\n                            playSound('chidori_sfx', 0.3);\n                        }\n                        screenShake = Math.max(screenShake, 15);\n                    }\n                }\n\n                if (fighter.type === 'goku' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // SSJ2 Mode buffs\n                    if (!ab.buffsApplied) {\n                        ab.buffsApplied = true;\n                        fighter.speed *= 1.3;\n                        fighter.jumpForce *= 1.1;\n                        fighter.health = Math.min(fighter.maxHealth, fighter.health + 100);\n                        fighter.isSSJ2 = true;\n                    }\n                }\n\n                if (fighter.type === 'rimuru' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Sky Slime Beam Damage Tick\n                    ab.tickTimer = (ab.tickTimer || 0) + dt;\n                    if (ab.tickTimer >= 0.2) {\n                        ab.tickTimer = 0;\n                        const enemies = getEnemies(fighter);\n                        for (const enemy of enemies) {\n                            if (!enemy.invulnerable) {\n                                // Check if enemy is horizontally near any clone\n                                for (const clone of ab.clones) {\n                                    if (Math.abs(enemy.x - clone.x) < 80) {\n                                        dealDamage(enemy, ab.damage / 25, fighter);\n                                        screenShake = Math.max(screenShake, 5);\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (fighter.type === 'doraemon' && fighter.skin === 'vietnam' && fighter.abilities.indexOf(ab) === 3 && ab.active) {\n                    // Long Th\u1ea7n Vi\u1ec7t Nam: pull enemies into a sky orbit for 7\n                    // seconds, apply continuous damage, then detonate the vortex.\n                    fighter.vx = 0;\n                    fighter.vy = 0;\n                    fighter.y = GROUND_Y;\n                    fighter.state = 'ability4';\n                    fighter.stateTimer = Math.max(fighter.stateTimer, 0.2);\n                    ab.rotation = (ab.rotation || 0) + Math.PI * 2.2 * dt;\n                    ab.dragonRotation = (ab.dragonRotation || 0) + Math.PI * 1.7 * dt;\n\n                    const enemies = getEnemies(fighter);\n                    if (!Array.isArray(ab.captured)) ab.captured = [];\n                    for (const enemy of enemies) {\n                        if (!enemy || enemy.health <= 0 || enemy.invulnerable) continue;\n                        if (!ab.captured.some(entry => entry.fighter === enemy)) {\n                            const dx = enemy.x - (ab.centerX || 360);\n                            const dy = (enemy.y - 60) - (ab.centerY || 270);\n                            ab.captured.push({\n                                fighter: enemy,\n                                angle: Math.atan2(dy, dx),\n                                radius: ab.orbitRadius || 190,\n                                damageTimer: 0\n                            });\n                            enemy.stunTimer = Math.max(enemy.stunTimer, 0.5);\n                        }\n                    }\n\n                    for (let j = ab.captured.length - 1; j >= 0; j--) {\n                        const entry = ab.captured[j];\n                        const trapped = entry.fighter;\n                        if (!trapped || trapped.health <= 0 || trapped.invulnerable) {\n                            ab.captured.splice(j, 1);\n                            continue;\n                        }\n\n                        entry.angle += (ab.orbitSpeed || 2.8) * dt;\n                        const orbitX = (ab.centerX || 360) + Math.cos(entry.angle) * entry.radius;\n                        const orbitY = (ab.centerY || 270) + Math.sin(entry.angle) * entry.radius * 0.58;\n                        trapped.x = Math.max(ARENA_LEFT + trapped.width / 2, Math.min(ARENA_RIGHT - trapped.width / 2, orbitX));\n                        trapped.y = Math.max(80, Math.min(GROUND_Y - 120, orbitY + 60));\n                        trapped.vx = 0;\n                        trapped.vy = 0;\n                        trapped.grounded = false;\n                        trapped.stunTimer = Math.max(trapped.stunTimer, 0.25);\n\n                        entry.damageTimer += dt;\n                        if (entry.damageTimer >= 0.22) {\n                            entry.damageTimer = 0;\n                            dealDamage(trapped, ab.damage, fighter);\n                        }\n                    }\n\n                    if (ab.activeTimer <= 0.1 && !ab.exploded) {\n                        ab.exploded = true;\n                        const blastRadius = 360;\n                        addEffect(ab.centerX || 360, ab.centerY || 270, 'doraemon_vietnam_flag_explosion', {\n                            timer: 1.5,\n                            maxTimer: 1.5,\n                            radius: blastRadius\n                        });\n                        for (const enemy of getEnemies(fighter)) {\n                            if (!enemy || enemy.health <= 0 || enemy.invulnerable) continue;\n                            const dx = enemy.x - (ab.centerX || 360);\n                            const dy = (enemy.y - 60) - (ab.centerY || 270);\n                            if (Math.sqrt(dx * dx + dy * dy) < blastRadius) {\n                                dealDamage(enemy, ab.explosionDamage || 140, fighter);\n                                enemy.vx = (dx >= 0 ? 1 : -1) * 28;\n                                enemy.vy = -16;\n                                enemy.grounded = false;\n                            }\n                        }\n                        for (const entry of ab.captured) {\n                            if (entry.fighter) entry.fighter.stunTimer = Math.min(entry.fighter.stunTimer, 0.25);\n                        }\n                        screenShake = 65;\n                        playSound('fireball_sfx', 1.0);\n                    }\n                }\n\n                if (ab.activeTimer !== undefined && ab.activeTimer > 0) {\n                    ab.activeTimer -= dt;\n                    if (ab.activeTimer <= 0) {\n                        ab.active = false;\n                        if (fighter.type === 'batBai' && fighter.abilities.indexOf(ab) === 0) {\n                            fighter.damageReduction = 0;\n                        }\n                        if (fighter.type === 'naruto' && fighter.abilities.indexOf(ab) === 3) {\n                            fighter.speed /= 1.25;\n                            fighter.jumpForce /= 1.1;\n                            ab.buffsApplied = false;\n                        }\n                        if (fighter.type === 'saitama' && fighter.abilities.indexOf(ab) === 3) {\n                            fighter.invulnerable = false;\n                            ab.triggered = false;\n                            ab.phase = 'idle';\n                        }\n                        if (fighter.type === 'goku' && fighter.abilities.indexOf(ab) === 3) {\n                            fighter.speed /= 1.3;\n                            fighter.jumpForce /= 1.1;\n                            ab.buffsApplied = false;\n                            fighter.isSSJ2 = false;\n                        }\n                        if (fighter.type === 'itachi' && fighter.skin === 'edo' && fighter.abilities.indexOf(ab) === 3 && fighter.state === 'ability4') {\n                            fighter.state = 'idle';\n                        }\n                        if (fighter.type === 'poPanda' && fighter.abilities.indexOf(ab) === 2) {\n                            fighter.invulnerable = false;\n                            ab.phase = 'idle';\n                        }\n                    }\n                }\n                if (ab.invulnTimer !== undefined && ab.invulnTimer > 0) {\n                    ab.invulnTimer -= dt;\n                    if (ab.invulnTimer <= 0) fighter.invulnerable = false;\n                }\n            }\n\n            // Combo hits for skills with multiple hits\n            const currentAbIdx = fighter.state === 'ability1' ? 0 : (fighter.state === 'ability2' ? 1 : (fighter.state === 'ability3' ? 2 : -1));\n            if (currentAbIdx !== -1) {\n                const ab = fighter.abilities[currentAbIdx];\n                if (ab && ab.hits) {\n                    ab.hitTimer += dt;\n                    if (ab.hitTimer >= 0.08 && ab.hitCount < ab.hits) {\n                        ab.hitTimer = 0;\n                        ab.hitCount++;\n                        hitEnemiesInRange(fighter, (ab.range || 150) + 80, ab.damage);\n                    }\n                }\n            }\n\n            // Physics\n            if (!fighter.grounded) {\n                fighter.vy += GRAVITY;\n            }\n            fighter.x += fighter.vx * dt * 60;\n            fighter.y += fighter.vy * dt * 60;\n\n            // Ground collision\n            if (fighter.y >= GROUND_Y) {\n                fighter.y = GROUND_Y;\n                fighter.vy = 0;\n                fighter.grounded = true;\n            }\n\n            // Boundaries\n            fighter.x = Math.max(ARENA_LEFT + fighter.width/2, Math.min(ARENA_RIGHT - fighter.width/2, fighter.x));\n\n            // Friction - only apply when not intentionally moving\n            if (fighter.grounded && (fighter.state === 'idle' || fighter.state === 'hit')) {\n                fighter.vx *= 0.85;\n            }\n\n            // Only AI fighters should automatically face their target.  Player\n            // fighters (including Itachi Edo) must keep the direction chosen by\n            // the movement input instead of being turned around every frame.\n            if (fighter.isAI && (fighter.state === 'idle' || fighter.state === 'walk')) {\n                fighter.facingRight = target.x > fighter.x;\n            }\n\n            // Animation\n            fighter.animTimer += dt;\n            if (fighter.type === 'itachi' && fighter.skin === 'edo') {\n                const moving = fighter.grounded && Math.abs(fighter.vx) > 0.15 && fighter.state === 'walk';\n                fighter.movementPhase += dt * (moving ? 8 : 2);\n            }\n            if (fighter.animTimer > 0.15) {\n                fighter.animTimer = 0;\n                fighter.animFrame = (fighter.animFrame + 1) % 4;\n            }\n        }\n\n        // Draw a sprite, cropping the 2x2 Itachi Edo walking sheet to one frame.\n        // The walk asset contains four poses in a single image; drawing the full\n        // sheet was the reason several Itachis appeared at once while moving.\n        function drawFighterSprite(fighter, sprite, dx, dy, dw, dh) {\n            if (fighter.type === 'itachi' && fighter.skin === 'edo' && fighter.state === 'walk' && sprite === imageCache['itachi_edo_walk']) {\n                const cols = 2;\n                const rows = 2;\n                const frame = ((fighter.animFrame % (cols * rows)) + (cols * rows)) % (cols * rows);\n                const sourceW = sprite.naturalWidth / cols;\n                const sourceH = sprite.naturalHeight / rows;\n                const sourceX = (frame % cols) * sourceW;\n                const sourceY = Math.floor(frame / cols) * sourceH;\n                ctx.drawImage(sprite, sourceX, sourceY, sourceW, sourceH, dx, dy, dw, dh);\n                return;\n            }\n            ctx.drawImage(sprite, dx, dy, dw, dh);\n        }\n\n        // Draw fighter\n        function drawFighter(fighter) {\n            const isNika = fighter.type === 'luffy' && fighter.isAwakened && fighter.skin === 'nika';\n            const isGear4 = fighter.type === 'luffy' && fighter.isAwakened && fighter.skin === 'gear4';\n            const isGear2 = fighter.type === 'luffy' && fighter.isAwakened && fighter.skin === 'default';\n            const isAdultSasuke = fighter.type === 'sasuke' && fighter.isAwakened;\n            const sprite = getSprite(fighter);\n            \n            ctx.save();\n            // Apply translation\n            ctx.translate(fighter.x, fighter.y);\n\n            if (fighter.isBoss) {\n                ctx.scale(1.5, 1.5);\n                // Draw boss indicator\n                ctx.save();\n                ctx.globalAlpha = 0.3;\n                ctx.fillStyle = '#f00';\n                ctx.beginPath();\n                ctx.ellipse(0, 0, 80, 20, 0, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.restore();\n            }\n\n            // Luffy Nika Gigant Form (Skill 3)\n            if (isNika && fighter.abilities[2] && fighter.abilities[2].active) {\n                ctx.scale(2.8, 2.8);\n            }\n\n\n            if (fighter.type === 'mahoraga') {\n                ctx.save();\n                const time = Date.now() / 1000;\n                ctx.save();\n                ctx.translate(0, -70);\n                ctx.rotate(time * 2);\n                ctx.globalAlpha = 0.5;\n                ctx.strokeStyle = '#fff';\n                ctx.lineWidth = 4;\n                ctx.beginPath();\n                ctx.arc(0, 0, 45, 0, Math.PI * 2);\n                ctx.stroke();\n                for(let k=0; k<8; k++) {\n                    ctx.save();\n                    ctx.rotate(k * Math.PI/4);\n                    ctx.beginPath();\n                    ctx.moveTo(0, 0);\n                    ctx.lineTo(45, 0);\n                    ctx.stroke();\n                    ctx.restore();\n                }\n                ctx.restore();\n                ctx.globalAlpha = 0.2;\n                ctx.fillStyle = '#fff';\n                ctx.beginPath();\n                ctx.arc(0, -60, 80, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.restore();\n            }\n\n            if (fighter.type === 'chaien') {\n                const time = Date.now() / 1000;\n                ctx.save();\n                // Shockwave rings\n                ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)';\n                ctx.lineWidth = 4;\n                ctx.translate(0, -60);\n                for (let k = 0; k < 3; k++) {\n                    const ringProgress = (time * 1.5 + k / 3) % 1;\n                    const radius = ringProgress * 400;\n                    ctx.globalAlpha = (1 - ringProgress) * 0.8;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius, 0, Math.PI * 2);\n                    ctx.stroke();\n                }\n                \n                // Back to head for notes\n                ctx.translate(0, -60);\n                ctx.globalAlpha = 1.0;\n                // Musical notes\n                ctx.fillStyle = '#fff';\n                ctx.font = '32px Inter';\n                for(let k=0; k<3; k++) {\n                    const nx = Math.sin(time * 5 + k) * 40;\n                    const ny = -40 - k * 30;\n                    ctx.fillText('\u266a', nx, ny);\n                }\n                ctx.restore();\n            }\n\n            // Luffy Gear 2 / Nika / Gear 4 Visual Effects\n            if (isGear2) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                ctx.globalAlpha = 0.3 + Math.sin(time * 10) * 0.1;\n                ctx.fillStyle = 'rgba(255, 182, 193, 0.3)'; // Pinkish tint\n                ctx.beginPath();\n                ctx.arc(0, -60, 80, 0, Math.PI * 2);\n                ctx.fill();\n                \n                // Rising steam\n                ctx.fillStyle = '#fff';\n                for (let i = 0; i < 5; i++) {\n                    const sx = (Math.sin(time * 6 + i) * 40);\n                    const sy = -60 - ((time * 200 + i * 50) % 150);\n                    const sSize = 6 + Math.random() * 8;\n                    ctx.globalAlpha = 0.4 * (1 - (Math.abs(sy + 60) / 150));\n                    ctx.beginPath();\n                    ctx.arc(sx, sy, sSize, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                ctx.restore();\n            } else if (isNika || isGear4) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                ctx.globalAlpha = 0.3 + Math.sin(time * 5) * 0.1;\n                ctx.fillStyle = isNika ? '#fff' : 'rgba(255, 0, 0, 0.2)';\n                ctx.beginPath();\n                ctx.arc(0, -60, 80, 0, Math.PI * 2);\n                ctx.fill();\n                \n                // White smoke swirls (Ribbon style for Gear 4 / Nika)\n                ctx.fillStyle = '#fff';\n                ctx.globalAlpha = 0.5;\n                for (let i = 0; i < 3; i++) {\n                    const angle = (time * (isGear4 ? 4 : 2) + i * Math.PI * 2 / 3) % (Math.PI * 2);\n                    const rx = Math.cos(angle) * (isGear4 ? 80 : 60);\n                    const ry = -60 + Math.sin(angle) * (isGear4 ? 40 : 30);\n                    ctx.beginPath();\n                    ctx.arc(rx, ry, isGear4 ? 25 : 20, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                ctx.restore();\n            }\n\n            // Flip if facing left\n            if (!fighter.facingRight) {\n                ctx.scale(-1, 1);\n            }\n\n            // Gear 4 Bounce\n            if (isGear4 && fighter.grounded && (fighter.state === 'idle' || fighter.state === 'walk')) {\n                const bounce = Math.abs(Math.sin(Date.now() / 150)) * 25;\n                ctx.translate(0, -bounce);\n            }\n\n            // Draw Health Bar Above Head for Mahoraga\n            if (fighter.type === 'mahoraga') {\n                ctx.save();\n                ctx.scale(fighter.facingRight ? 1 : -1, 1); // Counter the scale flip\n                const barW = 80;\n                const barH = 10;\n                const px = -barW / 2;\n                const py = -fighter.height - 40;\n                \n                // Background\n                ctx.fillStyle = 'rgba(0,0,0,0.8)';\n                ctx.fillRect(px, py, barW, barH);\n                \n                // Fill\n                const healthRatio = fighter.health / fighter.maxHealth;\n                ctx.fillStyle = healthRatio > 0.5 ? '#4CAF50' : healthRatio > 0.25 ? '#FFC107' : '#F44336';\n                ctx.fillRect(px, py, barW * healthRatio, barH);\n                \n                // Border\n                ctx.strokeStyle = '#fff';\n                ctx.lineWidth = 1.5;\n                ctx.strokeRect(px, py, barW, barH);\n                ctx.restore();\n            }\n\n            // Awakening Aura (H\u00e0o quang)\n            if (fighter.isAwakened) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                const colorMap = {\n                    itachi: '#FF4444',\n                    sasuke: '#A020F0',\n                    batBai: '#4A90E2',\n                    bongDem: '#9B59B6',\n                    madara: '#4A90E2',\n                    luffy: '#FFD700',\n                    sukuna: '#FF4444',\n                    gojo: '#B0E0E6',\n                    saitama: '#FFD700',\n                    vuaQuy: '#8B0000'\n                };\n                const color = colorMap[fighter.type] || '#fff';\n                \n                // Pulsing outer glow\n                ctx.globalAlpha = 0.2 + Math.sin(time * 5) * 0.1;\n                ctx.fillStyle = color;\n                ctx.beginPath();\n                ctx.arc(0, -60, 90 + Math.sin(time * 4) * 10, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Rotating radiant lines (D\u00f2ng h\u00e0o quang)\n                ctx.globalAlpha = 0.6;\n                ctx.strokeStyle = color;\n                ctx.lineWidth = 4;\n                ctx.lineCap = 'round';\n                for (let i = 0; i < 3; i++) {\n                    ctx.beginPath();\n                    const angleStart = time * 3 + (i * Math.PI * 2 / 3);\n                    const angleEnd = angleStart + Math.PI / 2;\n                    ctx.arc(0, -60, 85, angleStart, angleEnd);\n                    ctx.stroke();\n                }\n                \n                // Inner particle sparks\n                ctx.fillStyle = '#fff';\n                for (let i = 0; i < 5; i++) {\n                    const angle = (time * 2 + i * 1.2) % (Math.PI * 2);\n                    const dist = 60 + Math.sin(time * 10 + i) * 20;\n                    ctx.beginPath();\n                    ctx.arc(Math.cos(angle) * dist, -60 + Math.sin(angle) * dist, 3, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                ctx.restore();\n            }\n\n            // Naruto Nine-Tails Mode Aura\n            if (fighter.type === 'naruto' && fighter.abilities[3] && fighter.abilities[3].active) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                const isLucDao = fighter.skin === 'lucDao';\n                \n                // Pulsing golden chakra aura\n                ctx.globalAlpha = 0.3 + Math.sin(time * 8) * 0.1;\n                ctx.fillStyle = isLucDao ? '#FFFACD' : '#FFD700'; // Paler gold for Luc Dao\n                ctx.shadowBlur = isLucDao ? 50 : 30;\n                ctx.shadowColor = isLucDao ? '#FFA500' : '#FF8C00'; \n                \n                ctx.beginPath();\n                ctx.arc(0, -60, isLucDao ? 130 : 110, 0, Math.PI * 2);\n                ctx.fill();\n\n                if (isLucDao) {\n                    // Gudodama (Truth-Seeker Orbs) - Procedural drawing for extra polish\n                    ctx.save();\n                    ctx.globalAlpha = 1.0;\n                    ctx.fillStyle = '#000';\n                    ctx.shadowBlur = 15;\n                    ctx.shadowColor = '#A020F0'; // Purple glow as in image\n                    for (let i = 0; i < 6; i++) {\n                        const angle = (time * 2) + (i * Math.PI * 2 / 6);\n                        const r = 90;\n                        const ox = Math.cos(angle) * r;\n                        const oy = -60 + Math.sin(angle) * r * 0.8;\n                        ctx.beginPath();\n                        ctx.arc(ox, oy, 10, 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n                    ctx.restore();\n\n                    // Kurama Asura Ultimate Visuals\n                    const ab4 = fighter.abilities[3];\n                    if (ab4 && ab4.active && ab4.ultPhase) {\n                        ctx.save();\n                        ctx.resetTransform();\n                        const kuramaImg = imageCache['naruto_kurama_asura'];\n                        const phase = ab4.ultPhase;\n                        const dir = fighter.facingRight ? 1 : -1;\n                        \n                        ctx.translate(fighter.x, fighter.y - 60);\n                        if (!fighter.facingRight) ctx.scale(-1, 1);\n                        \n                        // 1. Draw Kurama Asura Avatar\n                        if (kuramaImg) {\n                            ctx.globalAlpha = 0.75 + Math.sin(time * 5) * 0.1;\n                            const aspect = kuramaImg.naturalWidth / kuramaImg.naturalHeight;\n                            const imgH = 650;\n                            const imgW = imgH * aspect;\n                            ctx.shadowBlur = 40;\n                            ctx.shadowColor = '#FFD700';\n                            ctx.drawImage(kuramaImg, -imgW / 2, -imgH * 0.8, imgW, imgH);\n                        }\n\n                        // 2. Draw spheres in hands during 'holding' phase\n                        if (phase === 'holding' || phase === 'summon') {\n                            const prog = phase === 'summon' ? (3.5 - ab4.ultTimer) : 1.0;\n                            ctx.save();\n                            const sphereSize = 80 * prog;\n                            ctx.shadowBlur = 30;\n                            \n                            // Left-hand spheres (actually multiple arms)\n                            // Hand 1 (Top Left): Rasenshuriken\n                            ctx.save();\n                            ctx.translate(-180, -450);\n                            ctx.rotate(time * 20);\n                            ctx.shadowColor = '#00BFFF';\n                            const rsImg = imageCache['rasenshuriken_projectile'];\n                            if (rsImg) ctx.drawImage(rsImg, -sphereSize/2, -sphereSize/2, sphereSize, sphereSize);\n                            ctx.restore();\n\n                            // Hand 2 (Top Right): Bijuu Bomb\n                            ctx.save();\n                            ctx.translate(180, -450);\n                            ctx.shadowColor = '#f00';\n                            const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, sphereSize/2);\n                            grad.addColorStop(0, '#000');\n                            grad.addColorStop(0.5, '#4B0082');\n                            grad.addColorStop(1, 'transparent');\n                            ctx.fillStyle = grad;\n                            ctx.beginPath(); ctx.arc(0, 0, sphereSize/2, 0, Math.PI*2); ctx.fill();\n                            ctx.restore();\n\n                            ctx.restore();\n                        }\n                        ctx.restore();\n                    }\n                }\n\n                // Whisker-like chakra flares\n                ctx.globalAlpha = 0.5;\n                ctx.strokeStyle = isLucDao ? '#FFD700' : '#FF8C00';\n                ctx.lineWidth = 4;\n                for (let i = 0; i < 6; i++) {\n                    const angle = (i < 3 ? -0.2 + i * 0.2 : Math.PI - 0.2 + (i-3) * 0.2);\n                    const length = (isLucDao ? 50 : 40) + Math.sin(time * 12 + i) * 15;\n                    ctx.beginPath();\n                    ctx.moveTo(Math.cos(angle) * 20, -70 + Math.sin(angle) * 20);\n                    ctx.lineTo(Math.cos(angle) * length, -70 + Math.sin(angle) * length);\n                    ctx.stroke();\n                }\n                ctx.restore();\n            }\n\n            // Enel Aura\n            if (fighter.type === 'enel') {\n                ctx.save();\n                const time = Date.now() / 1000;\n                ctx.globalAlpha = 0.4 + Math.sin(time * 10) * 0.2;\n                ctx.shadowBlur = 20;\n                ctx.shadowColor = '#00BFFF';\n                ctx.strokeStyle = '#fff';\n                ctx.lineWidth = 2;\n                \n                // Static electricity sparks around Enel\n                for (let i = 0; i < 3; i++) {\n                    const ang = time * 5 + i * 2;\n                    ctx.beginPath();\n                    const r = 80 + Math.sin(time * 20 + i) * 10;\n                    ctx.moveTo(Math.cos(ang) * r, -60 + Math.sin(ang) * r);\n                    ctx.lineTo(Math.cos(ang + 0.2) * (r+10), -60 + Math.sin(ang + 0.2) * (r+10));\n                    ctx.stroke();\n                }\n                ctx.restore();\n            }\n\n            if (fighter.type === 'garp' && fighter.abilities[3] && fighter.abilities[3].active) {\n                const ab = fighter.abilities[3];\n                if (ab.phase === 'explode') {\n                    ctx.save();\n                    ctx.resetTransform();\n                    const time = Date.now() / 1000;\n                    ctx.translate(fighter.x, GROUND_Y);\n                    \n                    const radius = 450 + Math.sin(time * 20) * 30;\n                    \n                    // Dark Red and Black Explosion (Galaxy Impact)\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, radius);\n                    grad.addColorStop(0, 'rgba(0, 0, 0, 0.95)'); // Black core\n                    grad.addColorStop(0.4, 'rgba(139, 0, 0, 0.9)'); // Dark red\n                    grad.addColorStop(0.8, 'rgba(255, 0, 0, 0.5)'); // Red\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 80;\n                    ctx.shadowColor = '#f00';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Jagged Haki Lightning (Red and Black)\n                    for (let k = 0; k < 25; k++) {\n                        ctx.save();\n                        const ang = Math.random() * Math.PI * 2;\n                        const rStart = Math.random() * (radius * 0.3);\n                        const rEnd = radius * (0.8 + Math.random() * 0.4);\n                        \n                        ctx.strokeStyle = Math.random() > 0.4 ? '#f00' : '#000';\n                        ctx.lineWidth = 4 + Math.random() * 6;\n                        ctx.lineCap = 'round';\n                        ctx.shadowBlur = 15;\n                        ctx.shadowColor = ctx.strokeStyle;\n\n                        ctx.beginPath();\n                        let curR = rStart;\n                        let curAng = ang;\n                        ctx.moveTo(Math.cos(curAng) * curR, Math.sin(curAng) * curR);\n                        \n                        while (curR < rEnd) {\n                            curR += 40 + Math.random() * 40;\n                            curAng += (Math.random() - 0.5) * 0.5;\n                            ctx.lineTo(Math.cos(curAng) * curR, Math.sin(curAng) * curR);\n                        }\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n\n                    // Spatial Cracks (High Contrast)\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 2;\n                    ctx.globalAlpha = 0.4;\n                    for (let k = 0; k < 10; k++) {\n                        const ang = Math.random() * Math.PI * 2;\n                        const r = radius * (0.5 + Math.random() * 0.5);\n                        ctx.beginPath();\n                        ctx.moveTo(Math.cos(ang) * (r - 100), Math.sin(ang) * (r - 100));\n                        ctx.lineTo(Math.cos(ang) * (r + 100), Math.sin(ang) * (r + 100));\n                        ctx.stroke();\n                    }\n\n                    // Impact lines\n                    ctx.strokeStyle = '#fff';\n                    ctx.globalAlpha = 0.3;\n                    ctx.lineWidth = 3;\n                    for (let k = 0; k < 12; k++) {\n                        const ang = k * Math.PI / 6 + time;\n                        ctx.beginPath();\n                        ctx.moveTo(0, 0);\n                        ctx.lineTo(Math.cos(ang) * radius, Math.sin(ang) * radius);\n                        ctx.stroke();\n                    }\n\n                    ctx.restore();\n                }\n            }\n\n            if (fighter.type === 'tanjiro') {\n                const time = Date.now() / 1000;\n                const dir = 1; // Flipped context handles direction\n                \n                // Skill 1, 2, 3 Visuals (Red Water)\n                if (fighter.state === 'ability1' && !fighter.abilities[3].active) {\n                    ctx.save();\n                    ctx.translate(dir * 50, -60);\n                    const grad = ctx.createLinearGradient(0, -40, 0, 40);\n                    grad.addColorStop(0, 'rgba(255, 0, 0, 0.8)');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    ctx.ellipse(0, 0, 80, 40, dir * Math.PI/4, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                } else if (fighter.state === 'ability2') {\n                    ctx.save();\n                    ctx.translate(dir * 60, -60);\n                    ctx.strokeStyle = '#FF4500';\n                    ctx.lineWidth = 8;\n                    ctx.beginPath();\n                    ctx.moveTo(0, 0);\n                    ctx.lineTo(dir * 120, 0);\n                    ctx.stroke();\n                    ctx.restore();\n                } else if (fighter.state === 'ability3' || (fighter.abilities[2] && fighter.abilities[2].active)) {\n                    ctx.save();\n                    ctx.translate(0, -60);\n                    ctx.rotate(time * 10);\n                    ctx.strokeStyle = '#FF0000';\n                    ctx.lineWidth = 6;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, 100, 0, Math.PI);\n                    ctx.stroke();\n                    ctx.restore();\n                }\n\n                // Tanjiro Ultimate Visuals (Dragon & Pillar)\n                if (fighter.abilities[3] && fighter.abilities[3].active) {\n                    const ab4 = fighter.abilities[3];\n                    if (ab4.phase === 'jump' || ab4.phase === 'dive') {\n                        // Draw Red Dragon on sword\n                        ctx.save();\n                        const dir = fighter.facingRight ? 1 : -1;\n                        ctx.translate(dir * 30, -70);\n                        \n                        // Dragon Body (swirling)\n                        ctx.strokeStyle = '#FF0000';\n                        ctx.lineWidth = 12;\n                        ctx.shadowBlur = 30;\n                        ctx.shadowColor = '#FF0000';\n                        ctx.beginPath();\n                        for (let k = 0; k < 15; k++) {\n                            const ang = (k * 0.4) - (time * 15);\n                            const r = 40 + k * 8;\n                            const dx = Math.cos(ang) * r;\n                            const dy = Math.sin(ang) * r;\n                            if (k === 0) ctx.moveTo(dx, dy);\n                            else ctx.lineTo(dx, dy);\n                        }\n                        ctx.stroke();\n\n                        // Dragon Head\n                        ctx.fillStyle = '#FF0000';\n                        ctx.beginPath();\n                        ctx.arc(Math.cos(-time*15)*40, Math.sin(-time*15)*40, 30, 0, Math.PI*2);\n                        ctx.fill();\n                        \n                        // Eyes\n                        ctx.fillStyle = '#fff';\n                        ctx.beginPath();\n                        ctx.arc(Math.cos(-time*15)*40 + 10, Math.sin(-time*15)*40 - 5, 8, 0, Math.PI*2);\n                        ctx.fill();\n\n                        // Fire around dragon\n                        ctx.globalAlpha = 0.5;\n                        for (let k = 0; k < 8; k++) {\n                            const fang = Math.random() * Math.PI * 2;\n                            const fr = 40 + Math.random() * 80;\n                            ctx.fillStyle = '#FF4500';\n                            ctx.beginPath();\n                            ctx.arc(Math.cos(fang)*fr, Math.sin(fang)*fr, 15, 0, Math.PI*2);\n                            ctx.fill();\n                        }\n                        ctx.restore();\n                    } else if (ab4.phase === 'pillar') {\n                        // Massive fire pillar (Visual only, damage is handled in update)\n                        ctx.save();\n                        ctx.resetTransform();\n                        ctx.translate(fighter.x, GROUND_Y);\n                        \n                        const pW = 500 + Math.sin(time * 25) * 60;\n                        const pGrad = ctx.createLinearGradient(-pW/2, 0, pW/2, 0);\n                        pGrad.addColorStop(0, 'transparent');\n                        pGrad.addColorStop(0.3, 'rgba(255, 0, 0, 0.9)');\n                        pGrad.addColorStop(0.5, 'rgba(255, 165, 0, 0.9)');\n                        pGrad.addColorStop(0.7, 'rgba(255, 0, 0, 0.9)');\n                        pGrad.addColorStop(1, 'transparent');\n                        \n                        ctx.fillStyle = pGrad;\n                        ctx.shadowBlur = 50;\n                        ctx.shadowColor = '#FF4500';\n                        ctx.fillRect(-pW/2, -GROUND_Y - 200, pW, GROUND_Y + 200);\n                        \n                        // Inner white core\n                        ctx.fillStyle = '#fff';\n                        ctx.globalAlpha = 0.3;\n                        ctx.fillRect(-pW/6, -GROUND_Y - 200, pW/3, GROUND_Y + 200);\n                        \n                        // Fire sparks\n                        ctx.globalAlpha = 0.8;\n                        for (let k = 0; k < 12; k++) {\n                            const px = (Math.random() - 0.5) * pW;\n                            const py = -Math.random() * GROUND_Y;\n                            ctx.fillStyle = '#FFD700';\n                            ctx.beginPath();\n                            ctx.arc(px, py, 12, 0, Math.PI * 2);\n                            ctx.fill();\n                        }\n                        ctx.restore();\n                    }\n                }\n            }\n\n            // Po Chi Effect\n            if (fighter.type === 'poPanda') {\n                const time = Date.now() / 1000;\n                if (fighter.state === 'ability1') {\n                    ctx.save();\n                    const dir = 1; // Flipped context handles direction\n                    ctx.translate(dir * 50, -80);\n                    ctx.globalAlpha = 0.6 + Math.sin(time * 20) * 0.2;\n                    ctx.shadowBlur = 20;\n                    ctx.shadowColor = '#FFD700';\n                    ctx.fillStyle = '#FFD700';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, 30, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                }\n                \n                if (fighter.abilities[2] && fighter.abilities[2].active && fighter.abilities[2].phase === 'hold') {\n                    ctx.save();\n                    ctx.resetTransform();\n                    ctx.translate(fighter.x, fighter.y - 120);\n                    const abAlpha = fighter.abilities[2].activeTimer / 2.0;\n                    ctx.globalAlpha = 0.8 * abAlpha;\n                    \n                    // Large Golden Dragon behind Po\n                    const scale = 3.5 + Math.sin(time * 6) * 0.3;\n                    ctx.scale(scale * (fighter.facingRight ? 1 : -1), scale);\n                    \n                    ctx.strokeStyle = '#FFD700';\n                    ctx.lineWidth = 3;\n                    ctx.shadowBlur = 25;\n                    ctx.shadowColor = '#FFD700';\n                    \n                    // Procedural dragon body\n                    ctx.beginPath();\n                    for(let k = 0; k < 25; k++) {\n                        const ang = (k * 0.4) - (time * 12);\n                        const r = 25 + k * 6;\n                        const dx = Math.cos(ang) * r;\n                        const dy = Math.sin(ang) * r;\n                        if (k === 0) ctx.moveTo(dx, dy);\n                        else ctx.lineTo(dx, dy);\n                    }\n                    ctx.stroke();\n\n                    // Dragon Head\n                    const headAng = -time * 12;\n                    const hx = Math.cos(headAng) * 25;\n                    const hy = Math.sin(headAng) * 25;\n                    ctx.fillStyle = '#FFD700';\n                    ctx.beginPath();\n                    ctx.arc(hx, hy, 18, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Eye\n                    ctx.fillStyle = '#fff';\n                    ctx.beginPath();\n                    ctx.arc(hx + 8, hy - 4, 5, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    ctx.restore();\n                }\n\n                // Ability 4: Long Th\u1ea7n B\u00e1t Qu\u00e1i (Giant Golden Dragon Rush & Wrap)\n                if (fighter.abilities[3] && fighter.abilities[3].active) {\n                    const ab4 = fighter.abilities[3];\n                    ctx.save();\n                    ctx.resetTransform();\n                    const time = Date.now() / 1000;\n                    \n                    let dx = ab4.dragonX || fighter.x;\n                    let dy = ab4.dragonY || (fighter.y - 120);\n                    \n                    if (ab4.phase === 'summoning') {\n                        dx = fighter.x;\n                        dy = fighter.y - 120;\n                    } else if (ab4.phase === 'wrapping' && ab4.targetFighter) {\n                        dx = ab4.targetFighter.x;\n                        dy = ab4.targetFighter.y - 60;\n                    }\n\n                    ctx.translate(dx, dy);\n                    const abAlpha = Math.min(1, ab4.activeTimer / 0.5);\n                    ctx.globalAlpha = 0.9 * abAlpha;\n                    \n                    const dragonImg = imageCache['po_dragon_skin'];\n                    if (dragonImg) {\n                        const isHorizontal = ab4.phase === 'summoning' || ab4.phase === 'rushing';\n                        const scale = (isHorizontal ? 1.0 : 1.2) + Math.sin(time * 5) * 0.05;\n                        ctx.scale(scale * (fighter.facingRight ? 1 : -1), scale);\n                        \n                        // Rotation logic\n                        if (ab4.phase === 'wrapping') {\n                            ctx.rotate(time * 15);\n                        } else if (!isHorizontal && ab4.phase === 'exploding') {\n                            ctx.rotate(Math.PI / 2);\n                        }\n\n                        const dWidth = 600;\n                        const dHeight = dWidth * (dragonImg.naturalHeight / dragonImg.naturalWidth);\n                        ctx.shadowBlur = 40;\n                        ctx.shadowColor = '#FFD700';\n                        ctx.drawImage(dragonImg, -dWidth/2, -dHeight/2, dWidth, dHeight);\n                    } else {\n                        // Original procedural fallback...\n                        const isHorizontal = ab4.phase === 'summoning' || ab4.phase === 'rushing';\n                        const scale = (isHorizontal ? 6.5 : 7.5) + Math.sin(time * 10) * 0.5;\n                        ctx.scale(scale * (fighter.facingRight ? 1 : -1), scale);\n                        \n                        ctx.strokeStyle = '#FFD700';\n                        ctx.lineWidth = 15;\n                        ctx.lineCap = 'round';\n                        ctx.lineJoin = 'round';\n                        ctx.shadowBlur = 45;\n                        ctx.shadowColor = '#FFD700';\n                        \n                        const segments = 150;\n                        ctx.beginPath();\n                        for(let k = 0; k < segments; k++) {\n                            let px, py;\n                            if (ab4.phase === 'wrapping') {\n                                const ang = (k * 0.12) + (time * 35);\n                                const r = 15 + k * 4.5;\n                                px = Math.cos(ang) * r;\n                                py = Math.sin(ang) * r;\n                            } else {\n                                px = -k * 5.5;\n                                py = Math.sin(k * 0.22 - time * 20) * 18;\n                            }\n                            if (k === 0) ctx.moveTo(px, py);\n                            else ctx.lineTo(px, py);\n                        }\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                }\n            }\n\n            // Doraemon Vi\u1ec7t Nam ultimate visual: a compact, upright sky seal.\n            // The flag stays circular in the center; the cleaned dragon cutout is\n            // drawn as a true ring around it instead of exposing its source square.\n            if (fighter.type === 'doraemon' && fighter.skin === 'vietnam' && fighter.abilities[3] && fighter.abilities[3].active) {\n                const ab4 = fighter.abilities[3];\n                const time = Date.now() / 1000;\n                const cx = ab4.centerX || 360;\n                const cy = ab4.centerY || 270;\n                const flagImg = imageCache['doraemon_vietnam_flag_reference'];\n                const dragonImg = imageCache['doraemon_vietnam_dragon_reference'];\n                const fade = Math.min(1, (ab4.activeTimer || 0) / 0.45);\n                const pulse = 1 + Math.sin(time * 8) * 0.035;\n                const flagRadius = 108;\n                const dragonSize = 390 * pulse;\n\n                ctx.save();\n                ctx.resetTransform();\n\n                // Restrict the darkening to the arena sky, never the floor or UI.\n                ctx.globalAlpha = 0.12 * fade;\n                ctx.fillStyle = '#240008';\n                ctx.fillRect(0, 0, 720, GROUND_Y);\n\n                // Focused red-gold halo behind the seal.\n                ctx.globalAlpha = 0.28 * fade;\n                const halo = ctx.createRadialGradient(cx, cy, 10, cx, cy, 290);\n                halo.addColorStop(0, '#fff6a8');\n                halo.addColorStop(0.22, '#ff4a1f');\n                halo.addColorStop(0.62, 'rgba(170, 0, 25, 0.28)');\n                halo.addColorStop(1, 'transparent');\n                ctx.fillStyle = halo;\n                ctx.shadowBlur = 36;\n                ctx.shadowColor = '#ff2a00';\n                ctx.beginPath();\n                ctx.arc(cx, cy, 290, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Glowing round Vietnamese flag badge. The clip removes the\n                // rectangular corners of the supplied flag reference.\n                ctx.save();\n                ctx.translate(cx, cy);\n                ctx.scale(pulse, pulse);\n                ctx.globalAlpha = 0.98 * fade;\n                ctx.shadowBlur = 34;\n                ctx.shadowColor = '#ffd52a';\n                ctx.beginPath();\n                ctx.arc(0, 0, flagRadius, 0, Math.PI * 2);\n                ctx.clip();\n                if (flagImg) {\n                    ctx.drawImage(flagImg, -flagRadius, -flagRadius, flagRadius * 2, flagRadius * 2);\n                } else {\n                    ctx.fillStyle = '#e21b23';\n                    ctx.fillRect(-flagRadius, -flagRadius, flagRadius * 2, flagRadius * 2);\n                    ctx.fillStyle = '#ffe500';\n                    drawFivePointStar(ctx, 0, 0, 51, 22);\n                }\n                ctx.restore();\n\n                // Gold border and inner star glow make the badge read clearly.\n                ctx.save();\n                ctx.translate(cx, cy);\n                ctx.globalAlpha = 0.92 * fade;\n                ctx.strokeStyle = '#ffe044';\n                ctx.lineWidth = 6;\n                ctx.shadowBlur = 22;\n                ctx.shadowColor = '#ffc400';\n                ctx.beginPath();\n                ctx.arc(0, 0, flagRadius + 5, 0, Math.PI * 2);\n                ctx.stroke();\n                ctx.fillStyle = 'rgba(255, 245, 130, 0.3)';\n                drawFivePointStar(ctx, 0, 0, 52, 22);\n                ctx.restore();\n\n                // The dragon is an upright circular ring, centered on the flag.\n                // Do not rotate or skew its source rectangle; rotate the ring\n                // around its center so the composition never tilts sideways.\n                ctx.save();\n                ctx.translate(cx, cy);\n                ctx.rotate(ab4.dragonRotation || 0);\n                ctx.globalAlpha = 0.96 * fade;\n                ctx.shadowBlur = 28;\n                ctx.shadowColor = '#ffb300';\n                if (dragonImg) {\n                    ctx.drawImage(dragonImg, -dragonSize / 2, -dragonSize / 2, dragonSize, dragonSize);\n                } else {\n                    ctx.strokeStyle = '#ffd21f';\n                    ctx.lineWidth = 16;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, dragonSize * 0.38, 0.1, Math.PI * 1.9);\n                    ctx.stroke();\n                }\n                ctx.restore();\n\n                // A separate orbit line and sparks communicate suction without\n                // covering the flag with a second opaque square image.\n                ctx.save();\n                ctx.translate(cx, cy);\n                ctx.globalAlpha = 0.75 * fade;\n                ctx.strokeStyle = '#ffd52a';\n                ctx.lineWidth = 4;\n                ctx.shadowBlur = 16;\n                ctx.shadowColor = '#ffb000';\n                ctx.setLineDash([22, 14]);\n                ctx.lineDashOffset = -(ab4.rotation || 0) * 42;\n                ctx.beginPath();\n                ctx.arc(0, 0, 205 + Math.sin(time * 7) * 5, 0, Math.PI * 2);\n                ctx.stroke();\n                ctx.setLineDash([]);\n                ctx.restore();\n\n                ctx.globalAlpha = 0.95 * fade;\n                ctx.fillStyle = '#fff3a0';\n                for (let k = 0; k < 12; k++) {\n                    const angle = (ab4.rotation || 0) + k * Math.PI * 2 / 12;\n                    const radius = 155 + (k % 3) * 28;\n                    ctx.beginPath();\n                    ctx.arc(cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius * 0.58, 3 + (k % 2) * 2, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                ctx.restore();\n            }\n\n            // Naruto Nine-Tails Mode Kurama Beam Visuals\n            if (fighter.type === 'naruto' && fighter.abilities[2] && fighter.abilities[2].active) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                const dir = 1; // Flipped context handles direction\n                \n                // Position beam at Naruto's head height\n                ctx.translate(dir * 60, -100);\n                \n                // 1. Draw Kurama Head (Transparent golden head shape)\n                ctx.save();\n                ctx.globalAlpha = 0.8 + Math.sin(time * 15) * 0.2;\n                ctx.fillStyle = '#FFD700'; \n                ctx.strokeStyle = '#FF8C00'; \n                ctx.lineWidth = 4;\n                ctx.shadowBlur = 20;\n                ctx.shadowColor = '#FF8C00';\n\n                // Fox Head Shape\n                ctx.beginPath();\n                ctx.moveTo(0, -40);\n                ctx.lineTo(dir * 120, 0); // Long nose\n                ctx.lineTo(0, 40);\n                ctx.lineTo(dir * -30, 60);\n                ctx.lineTo(dir * -60, 40);\n                ctx.lineTo(dir * -60, -40);\n                ctx.lineTo(dir * -30, -60);\n                ctx.closePath();\n                ctx.fill();\n                ctx.stroke();\n\n                // Eyes (Glowing red)\n                ctx.fillStyle = '#f00';\n                ctx.shadowBlur = 15;\n                ctx.shadowColor = '#f00';\n                ctx.beginPath();\n                ctx.arc(dir * 40, -20, 10, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.restore();\n\n                // 2. Black Purple Shockwave Beam\n                ctx.save();\n                const beamReach = 1000;\n                const beamWidth = 160 + Math.sin(time * 30) * 40;\n                \n                const beamGrad = ctx.createLinearGradient(dir * 40, 0, dir * beamReach, 0);\n                beamGrad.addColorStop(0, '#4B0082'); // Indigo/Purple\n                beamGrad.addColorStop(0.3, '#000000'); // Black core\n                beamGrad.addColorStop(0.7, '#4B0082'); \n                beamGrad.addColorStop(1, 'transparent');\n                \n                ctx.fillStyle = beamGrad;\n                ctx.shadowBlur = 50;\n                ctx.shadowColor = '#9400D3';\n                ctx.fillRect(dir * 40, -beamWidth/2, dir * (beamReach - 40), beamWidth);\n                \n                // Inner white-purple lightning sparks\n                ctx.strokeStyle = '#DA70D6';\n                ctx.lineWidth = 4;\n                ctx.globalAlpha = 0.7;\n                for(let i=0; i<10; i++) {\n                    ctx.beginPath();\n                    const lx = dir * (40 + Math.random() * (beamReach * 0.7));\n                    const ly = (Math.random()-0.5)*beamWidth;\n                    ctx.moveTo(lx, ly);\n                    ctx.lineTo(lx + dir*100, ly + (Math.random()-0.5)*60);\n                    ctx.stroke();\n                }\n                ctx.restore();\n                ctx.restore();\n            }\n\n            // Itachi Edo Susanoo: use a deliberate low, grounded composition.\n            // The previous version rotated the square source image by 90 degrees;\n            // that made the shield/body fall to the side of the arena while Itachi\n            // was still drawn at the fighter origin, so he appeared outside it.\n            if (fighter.type === 'itachi' && fighter.skin === 'edo' && fighter.abilities[3] && fighter.abilities[3].active) {\n                ctx.save();\n                ctx.resetTransform();\n                const susanoo = imageCache['itachi_edo_susanoo'] || imageCache['itachi_edo_ability4'];\n                const time = Date.now() / 1000;\n                const groundY = GROUND_Y + 6;\n                const pulse = 1 + Math.sin(time * 5) * 0.025;\n\n                // Flat shadow anchors the transformation to the arena floor.\n                ctx.globalAlpha = 0.5;\n                ctx.fillStyle = '#160817';\n                ctx.shadowBlur = 28;\n                ctx.shadowColor = '#ff6a00';\n                ctx.beginPath();\n                ctx.ellipse(fighter.x, groundY - 5, 235, 30, 0, 0, Math.PI * 2);\n                ctx.fill();\n\n                if (susanoo) {\n                    const aspect = susanoo.naturalWidth / susanoo.naturalHeight;\n                    // Keep the reference readable, but compress it vertically into\n                    // a broad ground-hugging avatar instead of rotating it sideways.\n                    const shellW = 520 * pulse;\n                    const shellH = shellW / aspect * 0.62;\n                    const shellX = fighter.x - shellW / 2;\n                    const shellY = groundY - shellH + 14;\n                    ctx.globalAlpha = 0.94;\n                    ctx.shadowBlur = 42;\n                    ctx.shadowColor = '#ff6a00';\n                    ctx.drawImage(susanoo, shellX, shellY, shellW, shellH);\n                } else {\n                    // Fallback: low orange shell with the purple shield to its side.\n                    ctx.save();\n                    ctx.translate(fighter.x, groundY - 105);\n                    if (!fighter.facingRight) ctx.scale(-1, 1);\n                    ctx.globalAlpha = 0.92;\n                    ctx.fillStyle = '#e66b16';\n                    ctx.shadowBlur = 35;\n                    ctx.shadowColor = '#ff7a00';\n                    ctx.beginPath();\n                    ctx.ellipse(-35, 55, 205, 82, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.fillStyle = '#5a183e';\n                    ctx.beginPath();\n                    ctx.ellipse(150, 28, 82, 100, -0.18, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.fillStyle = '#ffd21a';\n                    ctx.fillRect(15, 0, 175, 14);\n                    ctx.restore();\n                }\n\n                // Inner chamber: Itachi is drawn afterward at the center, so the\n                // sprite visibly sits inside the orange Susanoo body.\n                ctx.save();\n                ctx.globalAlpha = 0.28 + Math.sin(time * 7) * 0.06;\n                ctx.fillStyle = '#ff9d28';\n                ctx.shadowBlur = 24;\n                ctx.shadowColor = '#ff8a1f';\n                ctx.beginPath();\n                ctx.ellipse(fighter.x - 28, groundY - 72, 78, 92, 0, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.restore();\n\n                // Small floor pulse, kept underneath the fighter rather than\n                // becoming a second oversized orange oval around his head.\n                ctx.save();\n                ctx.globalAlpha = 0.24 + Math.sin(time * 6) * 0.06;\n                ctx.strokeStyle = '#ff8a1f';\n                ctx.lineWidth = 4;\n                ctx.shadowBlur = 18;\n                ctx.shadowColor = '#ff6a00';\n                ctx.beginPath();\n                ctx.ellipse(fighter.x, groundY - 8, 220, 24, 0, 0, Math.PI * 2);\n                ctx.stroke();\n                ctx.restore();\n                ctx.restore();\n            }\n\n            // Uchiha Special Eyes (Sharingan/Rinnegan) - \"Gi\u1ed1ng trong phim\"\n            const isUchiha = ['itachi', 'sasuke', 'madara'].includes(fighter.type);\n            if (isUchiha) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                const isRinnegan = (fighter.type === 'sasuke' && fighter.isAwakened) || (fighter.type === 'madara' && fighter.isAwakened);\n                \n                // Position relative to stick figure head (ctx is already scaled for facing direction)\n                const eyeX = 6; \n                const eyeY = -104;\n                const eyeRadius = 3.5;\n\n                // Glowing effect\n                ctx.shadowBlur = 15;\n                ctx.shadowColor = isRinnegan ? '#A020F0' : '#FF0000';\n                \n                if (isRinnegan) {\n                    // Rinnegan: T\u00edm v\u1edbi c\u00e1c v\u00f2ng tr\u00f2n \u0111\u1ed3ng t\u00e2m\n                    ctx.fillStyle = '#A020F0';\n                    ctx.beginPath(); ctx.arc(eyeX, eyeY, eyeRadius, 0, Math.PI * 2); ctx.fill();\n                    \n                    // Concentric rings\n                    ctx.strokeStyle = 'rgba(0,0,0,0.4)';\n                    ctx.lineWidth = 0.5;\n                    ctx.shadowBlur = 0;\n                    for (let r = 1; r < eyeRadius; r += 0.8) {\n                        ctx.beginPath(); ctx.arc(eyeX, eyeY, r, 0, Math.PI * 2); ctx.stroke();\n                    }\n                } else {\n                    // Sharingan: \u0110\u1ecf v\u1edbi c\u00e1c ph\u1ea9y (tomoe) xoay\n                    ctx.fillStyle = '#FF0000';\n                    ctx.beginPath(); ctx.arc(eyeX, eyeY, eyeRadius, 0, Math.PI * 2); ctx.fill();\n                    \n                    // Pupil\n                    ctx.fillStyle = '#000';\n                    ctx.shadowBlur = 0;\n                    ctx.beginPath(); ctx.arc(eyeX, eyeY, 0.8, 0, Math.PI * 2); ctx.fill();\n                    \n                    // 3 Tomoe dots rotating\n                    const rot = time * 4;\n                    for (let i = 0; i < 3; i++) {\n                        const angle = rot + (i * Math.PI * 2 / 3);\n                        const tx = eyeX + Math.cos(angle) * (eyeRadius * 0.55);\n                        const ty = eyeY + Math.sin(angle) * (eyeRadius * 0.55);\n                        ctx.beginPath(); ctx.arc(tx, ty, 0.6, 0, Math.PI * 2); ctx.fill();\n                    }\n                }\n                \n                // Lightning sparks for awakened Uchiha\n                if (fighter.isAwakened) {\n                    if (Math.random() > 0.6) {\n                        ctx.strokeStyle = isRinnegan ? '#A020F0' : '#FF0000';\n                        ctx.lineWidth = 2;\n                        ctx.beginPath();\n                        const lx = (Math.random() - 0.5) * 80;\n                        const ly = -40 - Math.random() * 80;\n                        ctx.moveTo(lx, ly);\n                        ctx.lineTo(lx + (Math.random()-0.5)*30, ly + (Math.random()-0.5)*30);\n                        ctx.stroke();\n                    }\n                }\n                ctx.restore();\n            }\n\n            if (!sprite) {\n                // Fallback stick figure\n                const colors = {\n                    batBai: '#4A90E2',\n                    bongDem: '#9B59B6',\n                    itachi: '#FF4444',\n                    luffy: '#FFD700',\n                    sukuna: '#FF4444',\n                    gojo: '#B0E0E6',\n                    saitama: '#FFD700',\n                    vuaQuy: '#8B0000'\n                };\n                const color = colors[fighter.type] || '#fff';\n                ctx.strokeStyle = isNika ? '#fff' : color;\n                ctx.lineWidth = 4;\n                ctx.beginPath();\n                ctx.arc(0, -100, 15, 0, Math.PI * 2);\n                ctx.stroke();\n                ctx.beginPath();\n                ctx.moveTo(0, -85); ctx.lineTo(0, -40);\n                ctx.moveTo(-20, -70); ctx.lineTo(20, -70);\n                ctx.moveTo(0, -40); ctx.lineTo(-15, 0);\n                ctx.moveTo(0, -40); ctx.lineTo(15, 0);\n                ctx.stroke();\n                ctx.restore();\n                return;\n            }\n\n            // Obito Sharingan Eye\n            if (fighter.type === 'hashirama' && fighter.abilities[2].active) {\n                // Deep Forest Emergence Visual\n                ctx.save();\n                ctx.resetTransform();\n                const time = Date.now() / 1000;\n                \n                // Darken/Green tint atmosphere\n                ctx.globalAlpha = 0.4 + Math.sin(time * 3) * 0.1;\n                ctx.fillStyle = 'rgba(20, 50, 20, 0.4)';\n                ctx.fillRect(0, 0, 720, 1280);\n                \n                // Draw the tree effect image\n                const treeImg = imageCache['hashirama_tree_effect'];\n                if (treeImg) {\n                    ctx.globalAlpha = 0.9;\n                    const aspect = treeImg.naturalWidth / treeImg.naturalHeight;\n                    const imgH = 600;\n                    const imgW = imgH * aspect;\n                    \n                    // Draw multiple trees across the background\n                    for (let k = -1; k < 2; k++) {\n                        const tx = 360 + k * 600 + Math.sin(time * 0.5 + k) * 50;\n                        ctx.drawImage(treeImg, tx - imgW / 2, GROUND_Y - imgH + 100, imgW, imgH);\n                    }\n                } else {\n                    // Fallback to vines if image not loaded\n                    ctx.strokeStyle = '#006400';\n                    ctx.lineWidth = 4;\n                    for(let k=0; k<12; k++) {\n                        const tx = (k * 70 + time * 20) % 800 - 40;\n                        ctx.beginPath();\n                        ctx.moveTo(tx, GROUND_Y);\n                        ctx.lineTo(tx + Math.sin(time*2+k)*30, GROUND_Y - 400 - Math.cos(time+k)*100);\n                        ctx.stroke();\n                    }\n                }\n                ctx.restore();\n            }\n\n            if (fighter.type === 'hashirama' && fighter.abilities[3].active) {\n                // Giant Falling Fists visual (Including Thousand-Hand Bodhisattva statue)\n                const ab = fighter.abilities[3];\n                const statueImg = imageCache['hashirama_ult_statue'];\n                const fistImg = imageCache['hashirama_ult_fists'];\n\n                ctx.save();\n                ctx.resetTransform();\n\n                // 1. Draw the Thousand-Hand Bodhisattva Statue in the background\n                if (statueImg) {\n                    ctx.save();\n                    const time = Date.now() / 1000;\n                    ctx.globalAlpha = 0.85;\n                    const statueAspect = statueImg.naturalWidth / statueImg.naturalHeight;\n                    const statueH = 900 + Math.sin(time * 3) * 20; // Pulsing presence\n                    const statueW = statueH * statueAspect;\n                    ctx.shadowBlur = 50;\n                    ctx.shadowColor = '#FFD700';\n                    // Center behind fighter, sit on ground\n                    ctx.drawImage(statueImg, fighter.x - statueW / 2, GROUND_Y - statueH + 100, statueW, statueH);\n                    ctx.restore();\n                }\n                \n                // 2. Draw Falling Giant Fists\n                const pillarFistImg = imageCache['hashirama_pillar_fist'] || imageCache['hashirama_ult_fists'];\n                if (pillarFistImg && ab.fists) {\n                    ctx.save();\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = '#FFD700';\n                    \n                    for (const f of ab.fists) {\n                        ctx.save();\n                        ctx.translate(f.x, f.y);\n                        ctx.rotate(f.angle);\n                        ctx.scale(f.scale, f.scale);\n                        ctx.globalAlpha = 0.95;\n                        \n                        const fistW = 280; \n                        const fistH = fistW * (pillarFistImg.naturalHeight / pillarFistImg.naturalWidth);\n                        // Draw so the bottom of the image (the fist) hits the ground\n                        ctx.drawImage(pillarFistImg, -fistW / 2, -fistH, fistW, fistH);\n                        ctx.restore();\n                    }\n                    ctx.restore();\n                }\n                ctx.restore();\n            }\n\n            if (fighter.type === 'obito') {\n                ctx.save();\n                const time = Date.now() / 1000;\n                \n                // Kamui Distortion Swirl (Ability 2)\n                if (fighter.state === 'ability2') {\n                    ctx.save();\n                    ctx.translate(0, -60);\n                    ctx.globalAlpha = 0.6;\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 2;\n                    for (let i = 0; i < 3; i++) {\n                        ctx.rotate(time * 10 + i);\n                        ctx.beginPath();\n                        ctx.arc(0, 0, 40 + i * 20, 0, Math.PI);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                }\n\n                // God Tree (Ability 3)\n                const hasBlackFireColumns = projectiles.some(p => p.type === 'black_fire_column' && p.owner === fighter);\n                if ((fighter.abilities[2] && fighter.abilities[2].active) || hasBlackFireColumns) {\n                    ctx.save();\n                    ctx.resetTransform();\n                    const treeImg = imageCache['obito_god_tree'];\n                    if (treeImg) {\n                        ctx.globalAlpha = 1.0;\n                        const aspect = treeImg.width / treeImg.height;\n                        const imgH = 650;\n                        const imgW = imgH * aspect;\n                        // Center on fighter, sit on ground\n                        ctx.drawImage(treeImg, fighter.x - imgW/2, GROUND_Y - imgH, imgW, imgH);\n                    }\n                    ctx.restore();\n                }\n\n                // Ngo\u1ea1i \u0110\u1ea1o Ma T\u01b0\u1ee3ng Statue (Ability 4)\n                if (fighter.abilities[3] && fighter.abilities[3].active) {\n                    ctx.save();\n                    ctx.resetTransform();\n                    const time = Date.now() / 1000;\n                    \n                    const ultImg = imageCache['obito_ult_image'];\n                    if (ultImg) {\n                        ctx.globalAlpha = 0.6 + Math.sin(time * 5) * 0.1;\n                        const aspect = ultImg.width / ultImg.height;\n                        const imgH = 800;\n                        const imgW = imgH * aspect;\n                        // Center horizontally on fighter, sit on ground\n                        ctx.drawImage(ultImg, fighter.x - imgW/2, GROUND_Y - imgH, imgW, imgH);\n                    } else {\n                        // Fallback to simpler silhouette if image not loaded\n                        ctx.translate(fighter.x, fighter.y);\n                        ctx.globalAlpha = 0.4;\n                        ctx.fillStyle = '#3d2b22';\n                        ctx.beginPath();\n                        ctx.moveTo(-100, 0); ctx.lineTo(-80, -400); ctx.lineTo(80, -400); ctx.lineTo(100, 0);\n                        ctx.fill();\n                    }\n\n                    // Maintain atmospheric effects (lightning/shockwaves)\n                    ctx.translate(fighter.x, GROUND_Y);\n                    ctx.strokeStyle = 'rgba(255, 255, 255, 0.4)';\n                    ctx.lineWidth = 3;\n                    const rProgress = (time * 2.5) % 1;\n                    ctx.beginPath();\n                    ctx.ellipse(0, 0, 450 * rProgress, 120 * rProgress, 0, 0, Math.PI * 2);\n                    ctx.stroke();\n\n                    // Procedural lightning bolts during ultimate\n                    ctx.globalAlpha = 0.8;\n                    ctx.strokeStyle = '#fff';\n                    ctx.shadowBlur = 20;\n                    ctx.shadowColor = '#00BFFF';\n                    ctx.lineWidth = 2;\n                    if (Math.random() > 0.6) {\n                        ctx.beginPath();\n                        let lx = (Math.random() - 0.5) * 600;\n                        let ly = -800;\n                        ctx.moveTo(lx, ly);\n                        while (ly < 0) {\n                            ly += 40;\n                            lx += (Math.random() - 0.5) * 60;\n                            ctx.lineTo(lx, ly);\n                        }\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                }\n\n                // Gunbai Strike Effect (Ability 3)\n                if (fighter.state === 'ability3') {\n                    ctx.save();\n                    const dir = 1; // Flipped context handles direction\n                    ctx.translate(dir * 60, -60);\n                    ctx.globalAlpha = 0.5;\n                    ctx.fillStyle = '#fff';\n                    ctx.beginPath();\n                    ctx.ellipse(0, 0, 100, 140, dir * Math.PI/6, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                }\n\n                const eyeX = 6; \n                const eyeY = -104;\n                const eyeRadius = 2.5;\n                ctx.shadowBlur = 10;\n                ctx.shadowColor = '#FF0000';\n                ctx.fillStyle = '#FF0000';\n                ctx.beginPath();\n                ctx.arc(eyeX, eyeY, eyeRadius, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.restore();\n            }\n\n            if (fighter.type === 'zoro') {\n                ctx.save();\n                const time = Date.now() / 1000;\n                const dir = 1; // Flipped context handles direction\n\n                // Procedural Tornado for Skill 3 (Dragon Twister)\n                if (fighter.abilities[2] && fighter.abilities[2].active) {\n                    ctx.save();\n                    const ab = fighter.abilities[2];\n                    const tornadoH = 800;\n                    const maxRadius = 350;\n                    \n                    // Layered swirling wind\n                    for (let k = 0; k < 30; k++) {\n                        const progress = ( (time * 3 + k/30) % 1 );\n                        const ty = -progress * tornadoH;\n                        const tr = Math.max(0.1, (progress * maxRadius) + Math.sin(time * 20 + k) * 40);\n                        const alpha = (1 - progress) * 0.7;\n                        \n                        ctx.save();\n                        ctx.translate(0, ty);\n                        ctx.rotate(time * 25 + k * 0.3);\n                        \n                        // Zoro's characteristic green wind or Wano Black Haki\n                        const isWano = fighter.skin === 'wano';\n                        const colors = isWano ? ['#000', '#1a0033', '#4b0082', '#fff'] : ['#50C878', '#00FF7F', '#00FFFF', '#fff'];\n                        ctx.strokeStyle = colors[k % colors.length];\n                        ctx.globalAlpha = alpha;\n                        ctx.lineWidth = 2 + Math.random() * 4;\n                        \n                        ctx.beginPath();\n                        ctx.arc(0, 0, tr, 0, Math.PI * (0.5 + Math.random()));\n                        ctx.stroke();\n                        \n                        if (k % 5 === 0) {\n                            ctx.beginPath();\n                            ctx.moveTo(tr, 0);\n                            ctx.lineTo(tr + 50, -30);\n                            ctx.stroke();\n                        }\n                        ctx.restore();\n                    }\n                    \n                    // Base shockwave rings\n                    ctx.strokeStyle = fighter.skin === 'wano' ? '#4b0082' : '#00FF7F';\n                    ctx.lineWidth = 5;\n                    for (let i = 0; i < 3; i++) {\n                        const rProg = (time * 4 + i/3) % 1;\n                        ctx.globalAlpha = (1 - rProg) * 0.5;\n                        ctx.beginPath();\n                        const rw = Math.max(0.1, rProg * maxRadius);\n                        const rh = Math.max(0.1, rProg * 80);\n                        ctx.ellipse(0, 0, rw, rh, 0, 0, Math.PI * 2);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                }\n\n                // Ashura Ultimate Visual (Ashura Spirit only)\n                if (fighter.abilities[3] && fighter.abilities[3].active) {\n                    const ab = fighter.abilities[3];\n                    \n                    // Spinning Swords during Startup\n                    if (ab.phase === 'startup') {\n                        ctx.save();\n                        ctx.translate(0, -60);\n                        const spinRot = time * 25;\n                        ctx.shadowBlur = 30;\n                        ctx.shadowColor = fighter.skin === 'wano' ? '#4b0082' : '#32CD32';\n                        \n                        for (let k = 0; k < 6; k++) {\n                            ctx.save();\n                            ctx.rotate(spinRot + k * Math.PI / 3);\n                            \n                            // Blade streak\n                            const grad = ctx.createLinearGradient(100, 0, 180, 0);\n                            grad.addColorStop(0, 'rgba(255, 255, 255, 0)');\n                            grad.addColorStop(0.5, 'rgba(255, 255, 255, 0.8)');\n                            grad.addColorStop(1, fighter.skin === 'wano' ? 'rgba(75, 0, 130, 0)' : 'rgba(50, 205, 50, 0)');\n                            \n                            ctx.fillStyle = grad;\n                            ctx.beginPath();\n                            ctx.ellipse(140, 0, 40, 8, 0, 0, Math.PI * 2);\n                            ctx.fill();\n                            \n                            // Sharp white core\n                            ctx.fillStyle = '#fff';\n                            ctx.fillRect(120, -2, 40, 4);\n                            ctx.restore();\n                        }\n                        \n                        // Circular wind gust\n                        ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';\n                        ctx.lineWidth = 15;\n                        ctx.beginPath();\n                        ctx.arc(0, 0, 140, 0, Math.PI * 2);\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n                }\n\n                // Onigiri Slash Effect (Ability 1)\n                if (fighter.state === 'ability1') {\n                    ctx.save();\n                    ctx.translate(dir * 60, -60);\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 5;\n                    ctx.shadowBlur = 15;\n                    ctx.shadowColor = fighter.skin === 'wano' ? '#000' : '#32CD32';\n                    // Cross slashes\n                    ctx.beginPath();\n                    ctx.moveTo(-50, -50); ctx.lineTo(50, 50);\n                    ctx.moveTo(-50, 50); ctx.lineTo(50, -50);\n                    ctx.stroke();\n                    ctx.restore();\n                }\n\n                ctx.restore();\n            }\n\n            if (fighter.type === 'yuta') {\n                const time = Date.now() / 1000;\n                const dir = 1; // Flipped context handles direction\n                \n                // Cursed Energy Aura\n                ctx.save();\n                ctx.globalAlpha = 0.2 + Math.sin(time * 5) * 0.1;\n                ctx.fillStyle = '#00BFFF';\n                ctx.beginPath();\n                ctx.arc(0, -60, 80, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.restore();\n\n                // Skill 2: Cursed Speech Visual (Soundwaves)\n                if (fighter.state === 'ability2') {\n                    ctx.save();\n                    ctx.translate(dir * 40, -85);\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 3;\n                    for (let k = 0; k < 3; k++) {\n                        const progress = (time * 5 + k/3) % 1;\n                        ctx.globalAlpha = (1 - progress) * 0.8;\n                        ctx.beginPath();\n                        ctx.arc(0, 0, progress * 150, -Math.PI/4, Math.PI/4);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                }\n\n                // Skill 3: Black Flash Aura\n                if (fighter.state === 'ability3') {\n                    ctx.save();\n                    const dir = 1;\n                    ctx.translate(dir * 30, -80);\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = '#f00';\n                    ctx.strokeStyle = '#000';\n                    ctx.lineWidth = 4;\n                    // Sparkles of black lightning\n                    for(let k=0; k<3; k++) {\n                        ctx.beginPath();\n                        const ang = Math.random()*Math.PI*2;\n                        ctx.moveTo(0,0);\n                        ctx.lineTo(Math.cos(ang)*40, Math.sin(ang)*40);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                }\n\n                // Skill 4: Rika Summon & Purple Beam Visual\n                if (fighter.abilities[3] && fighter.abilities[3].active) {\n                    ctx.save();\n                    ctx.resetTransform();\n                    const ab = fighter.abilities[3];\n                    const rikaImg = imageCache['rika_v2'] || imageCache['rika_spirit'];\n                    const dir = fighter.facingRight ? 1 : -1;\n                    \n                    // 1. Draw Rika Spirit behind Yuta (Modified scale and position to match image)\n                    ctx.save();\n                    ctx.translate(fighter.x, fighter.y - 80);\n                    if (!fighter.facingRight) ctx.scale(-1, 1);\n                    \n                    if (rikaImg) {\n                        ctx.globalAlpha = 0.9 + Math.sin(time * 3) * 0.05;\n                        const aspect = rikaImg.naturalWidth / rikaImg.naturalHeight;\n                        const imgH = 340; // Reduced size as requested (no longer \"giant\")\n                        const imgW = imgH * aspect;\n                        // Positioned closely behind Yuta, emerging from his shadow\n                        ctx.drawImage(rikaImg, -imgW * 0.7, -imgH * 0.8, imgW, imgH);\n                    } else {\n                        // Procedural Skeletal Rika fallback\n                        ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';\n                        // Ribcage\n                        for(let k=0; k<5; k++) {\n                            ctx.fillRect(-60, -100 + k*12, 40, 4);\n                        }\n                        // Spine/Neck\n                        ctx.fillRect(-45, -180, 8, 100);\n                        // Head\n                        ctx.fillStyle = '#fff';\n                        ctx.fillRect(-60, -210, 40, 30);\n                        // Teeth\n                        ctx.fillStyle = '#000';\n                        for(let k=0; k<4; k++) {\n                             ctx.fillRect(-55 + k*8, -195, 4, 10);\n                        }\n                        // Base tail\n                        ctx.fillStyle = 'rgba(75, 0, 130, 0.6)';\n                        ctx.beginPath();\n                        ctx.moveTo(-20, 0);\n                        ctx.quadraticCurveTo(-100, 50, -150, 0);\n                        ctx.fill();\n                    }\n                    ctx.restore();\n\n                    // 2. Draw Purple Energy Beam\n                    ctx.save();\n                    ctx.translate(fighter.x, fighter.y - 80);\n                    const beamLen = 1000;\n                    const beamWidth = 200 + Math.sin(time * 25) * 50;\n                    \n                    const beamGrad = ctx.createLinearGradient(dir * 40, 0, dir * beamLen, 0);\n                    beamGrad.addColorStop(0, '#8A2BE2'); // Blue Violet\n                    beamGrad.addColorStop(0.3, '#4B0082'); // Indigo\n                    beamGrad.addColorStop(0.5, '#9400D3'); // Dark Violet\n                    beamGrad.addColorStop(0.8, '#8A2BE2');\n                    beamGrad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = beamGrad;\n                    ctx.shadowBlur = 60;\n                    ctx.shadowColor = '#9400D3';\n                    \n                    ctx.beginPath();\n                    ctx.moveTo(dir * 40, -beamWidth / 4);\n                    ctx.lineTo(dir * beamLen, -beamWidth / 2);\n                    ctx.lineTo(dir * beamLen, beamWidth / 2);\n                    ctx.lineTo(dir * 40, beamWidth / 4);\n                    ctx.fill();\n\n                    // Internal white/purple core streaks\n                    ctx.globalAlpha = 0.6;\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 6;\n                    for (let i = 0; i < 8; i++) {\n                        const ly = (i - 3.5) * 30 + Math.sin(time * 30 + i) * 15;\n                        ctx.beginPath();\n                        ctx.moveTo(dir * 50, ly);\n                        ctx.lineTo(dir * beamLen * 0.8, ly);\n                        ctx.stroke();\n                    }\n                    \n                    // Energy particles around the beam\n                    ctx.globalAlpha = 0.4;\n                    ctx.fillStyle = '#fff';\n                    for (let i = 0; i < 15; i++) {\n                        const px = dir * Math.random() * beamLen;\n                        const py = (Math.random() - 0.5) * beamWidth;\n                        ctx.beginPath();\n                        ctx.arc(px, py, 5 + Math.random() * 10, 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n                    ctx.restore();\n\n                    // Atmosphere for Rika / Summon\n                    ctx.save();\n                    ctx.translate(fighter.x, fighter.y - 120);\n                    ctx.strokeStyle = '#9400D3';\n                    ctx.lineWidth = 4;\n                    ctx.globalAlpha = 0.3;\n                    for(let i=0; i<5; i++) {\n                        ctx.beginPath();\n                        const r = 220 + i*50 + Math.sin(time*5+i)*30;\n                        ctx.arc(0, 0, r, 0, Math.PI*2);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                    \n                    ctx.restore();\n                }\n            }\n\n            // Draw effects\n            if (fighter.type === 'batBai' && fighter.abilities[0].active) {\n                ctx.globalAlpha = 0.3;\n                ctx.fillStyle = '#4A90E2';\n                ctx.beginPath();\n                ctx.ellipse(0, -60, 50, 70, 0, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.globalAlpha = 1;\n            }\n\n            if (fighter.invulnerable) {\n                ctx.globalAlpha = 0.5;\n            }\n\n            // Goku SSJ2 Lightning and Aura\n            if (fighter.type === 'goku' && fighter.abilities[3] && fighter.abilities[3].active) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                \n                // Spiky Golden Aura\n                ctx.globalAlpha = 0.3 + Math.sin(time * 10) * 0.1;\n                ctx.fillStyle = '#FFD700'; \n                ctx.beginPath();\n                ctx.arc(0, -60, 100, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Blue Lightning Sparks\n                ctx.strokeStyle = '#00BFFF';\n                ctx.lineWidth = 2;\n                ctx.shadowBlur = 10;\n                ctx.shadowColor = '#00BFFF';\n                for (let i = 0; i < 3; i++) {\n                    if (Math.random() > 0.6) {\n                        ctx.beginPath();\n                        const ang = Math.random() * Math.PI * 2;\n                        const r1 = 40 + Math.random() * 40;\n                        const r2 = r1 + 30;\n                        let lx = Math.cos(ang) * r1;\n                        let ly = -60 + Math.sin(ang) * r1;\n                        ctx.moveTo(lx, ly);\n                        for (let j = 0; j < 3; j++) {\n                            lx += (Math.random() - 0.5) * 40;\n                            ly += (Math.random() - 0.5) * 40;\n                            ctx.lineTo(lx, ly);\n                        }\n                        ctx.stroke();\n                    }\n                }\n                ctx.restore();\n            }\n\n            // Draw Goku Aura and Embers BEFORE sprite (Ultra Instinct)\n            if (fighter.type === 'goku' && fighter.isUI) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                \n                // Pulsing silver/white aura\n                ctx.globalAlpha = 0.3 + Math.sin(time * 10) * 0.1;\n                ctx.fillStyle = '#E6E6FA'; // Silvery white\n                ctx.beginPath();\n                ctx.arc(0, -60, 120, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Ultra Instinct Heat / Shimmer\n                ctx.globalAlpha = 0.2;\n                ctx.fillStyle = '#B0E0E6'; // Pale blue\n                for (let i = 0; i < 3; i++) {\n                    const angle = (time * 2 + i * 2) % (Math.PI * 2);\n                    ctx.beginPath();\n                    ctx.arc(Math.cos(angle) * 110, -60 + Math.sin(angle) * 40, 40, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n\n                // Fire spots / Embers (white/blue for UI)\n                for(let i=0; i<12; i++) {\n                    const seed = i * 2.1;\n                    const fx = (Math.sin(time * 3 + seed) * 80);\n                    const fy = -60 + (Math.cos(time * 2 + seed) * 100);\n                    const size = 3 + Math.sin(time * 6 + seed) * 2;\n                    \n                    const grad = ctx.createRadialGradient(fx, fy, 0, fx, fy, size);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.5, '#B0E0E6');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    ctx.arc(fx, fy, size, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                ctx.restore();\n            }\n\n            if (fighter.type === 'shadowGarden' && fighter.abilities[3].active) {\n                // I AM ATOMIC Visual\n                const ab = fighter.abilities[3];\n                const time = ab.activeTimer;\n                ctx.save();\n                ctx.resetTransform();\n                \n                // 1. Darken everything during charge\n                if (time > 0.5) {\n                    ctx.fillStyle = 'rgba(0,0,0,0.6)';\n                    ctx.fillRect(0, 0, 720, 1280);\n                }\n\n                // 2. Violet lines/cracks in space\n                ctx.strokeStyle = '#9370DB';\n                ctx.lineWidth = 2;\n                for(let i=0; i<10; i++) {\n                    const seed = i * 23.4;\n                    ctx.beginPath();\n                    const rx = (seed + Date.now()/10) % 720;\n                    ctx.moveTo(rx, 0); ctx.lineTo(rx, 1280);\n                    ctx.globalAlpha = 0.2;\n                    ctx.stroke();\n                }\n\n                // 3. Central Charge at Shadow's position\n                ctx.translate(fighter.x, fighter.y - 120);\n                const pulse = 100 + Math.sin(Date.now()/50) * 50;\n                \n                // Outer violet glow\n                const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, pulse * 2);\n                grad.addColorStop(0, 'rgba(147, 112, 219, 0.8)');\n                grad.addColorStop(0.5, 'rgba(75, 0, 130, 0.3)');\n                grad.addColorStop(1, 'transparent');\n                ctx.fillStyle = grad;\n                ctx.globalAlpha = 1.0;\n                ctx.beginPath();\n                ctx.arc(0, 0, pulse * 2, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Core white/violet sphere\n                ctx.fillStyle = '#fff';\n                ctx.beginPath();\n                ctx.arc(0, 0, 20 + Math.random()*10, 0, Math.PI * 2);\n                ctx.fill();\n\n                // 4. \"I AM ATOMIC\" Text during the whispering phase\n                if (time < 1.0 && time > 0.1) {\n                    ctx.save();\n                    ctx.resetTransform();\n                    ctx.font = 'italic bold 80px \"Bebas Neue\"';\n                    ctx.textAlign = 'center';\n                    ctx.fillStyle = '#fff';\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#9370DB';\n                    ctx.fillText('I AM ATOMIC', 360, 400);\n                    ctx.restore();\n                }\n\n                // 5. Final Explosion\n                if (time <= 0.2) {\n                    ctx.resetTransform();\n                    ctx.fillStyle = '#fff';\n                    ctx.fillRect(0, 0, 720, 1280);\n                    ctx.fillStyle = '#9370DB';\n                    ctx.globalAlpha = 0.5;\n                    ctx.fillRect(0, 0, 720, 1280);\n                }\n\n                ctx.restore();\n            }\n\n            // Saitama Anger Marks\n            if (fighter.type === 'saitama' && fighter.abilities[3] && fighter.abilities[3].active && !fighter.abilities[3].triggered) {\n                ctx.save();\n                const time = Date.now() / 1000;\n                ctx.translate(0, -fighter.height - 20 + Math.sin(time * 10) * 5);\n                ctx.strokeStyle = '#f00';\n                ctx.lineWidth = 3;\n                ctx.lineCap = 'round';\n                // Draw a simple \"anger vein\" \ud83d\udca2\n                for (let i = 0; i < 2; i++) {\n                    const offX = (i === 0 ? -15 : 15);\n                    ctx.save();\n                    ctx.translate(offX, 0);\n                    ctx.beginPath();\n                    ctx.moveTo(-10, -10); ctx.quadraticCurveTo(0, 0, -10, 10);\n                    ctx.moveTo(10, -10); ctx.quadraticCurveTo(0, 0, 10, 10);\n                    ctx.moveTo(-10, -10); ctx.quadraticCurveTo(0, 0, 10, -10);\n                    ctx.moveTo(-10, 10); ctx.quadraticCurveTo(0, 0, 10, 10);\n                    ctx.stroke();\n                    ctx.restore();\n                }\n                ctx.restore();\n            }\n\n            // Saitama Ultimate Blast Visual (Serious Pressure)\n            if (fighter.type === 'saitama' && fighter.abilities[3] && fighter.abilities[3].active && fighter.abilities[3].triggered && fighter.abilities[3].phase === 'punching') {\n                ctx.save();\n                const ab = fighter.abilities[3];\n                const time = Date.now() / 1000;\n                const dir = 1; // Flipped context handles direction\n                \n                // Position relative to fist\n                ctx.translate(dir * 60, -80);\n                \n                const blastLen = 1000;\n                const blastWidth = 550 + Math.sin(time * 30) * 60;\n                \n                // Massive white air pressure wave\n                const grad = ctx.createLinearGradient(0, 0, dir * blastLen, 0);\n                grad.addColorStop(0, 'rgba(255, 255, 255, 0.95)');\n                grad.addColorStop(0.2, 'rgba(255, 255, 255, 0.85)');\n                grad.addColorStop(0.5, 'rgba(255, 255, 255, 0.4)');\n                grad.addColorStop(1, 'transparent');\n                \n                ctx.fillStyle = grad;\n                ctx.shadowBlur = 80;\n                ctx.shadowColor = '#fff';\n                \n                // Draw a massive expanding cone/beam of air pressure\n                ctx.beginPath();\n                ctx.moveTo(0, -blastWidth/5);\n                ctx.quadraticCurveTo(dir * blastLen * 0.4, -blastWidth/2, dir * blastLen, -blastWidth/3);\n                ctx.lineTo(dir * blastLen, blastWidth/3);\n                ctx.quadraticCurveTo(dir * blastLen * 0.4, blastWidth/2, 0, blastWidth/5);\n                ctx.fill();\n\n                // Bright internal pressure lines\n                ctx.strokeStyle = '#fff';\n                ctx.lineWidth = 12;\n                ctx.globalAlpha = 0.6;\n                for (let i = 0; i < 6; i++) {\n                    const ly = (i - 2.5) * 50 + Math.sin(time * 25 + i) * 25;\n                    ctx.beginPath();\n                    ctx.moveTo(0, ly);\n                    ctx.lineTo(dir * blastLen * (0.7 + Math.random() * 0.2), ly);\n                    ctx.stroke();\n                }\n                \n                // Shockwave rings moving forward\n                ctx.lineWidth = 6;\n                for (let i = 0; i < 5; i++) {\n                    const progress = (time * 6 + i) % 5 / 5;\n                    ctx.globalAlpha = (1 - progress) * 0.5;\n                    ctx.beginPath();\n                    // Horizontal ellipse rings\n                    ctx.ellipse(dir * progress * blastLen, 0, 50 + progress * 150, 120 + progress * 300, 0, 0, Math.PI * 2);\n                    ctx.stroke();\n                }\n                \n                // Ground dust / impact at the base of the blast\n                ctx.globalAlpha = 0.4;\n                ctx.fillStyle = '#fff';\n                for (let i = 0; i < 15; i++) {\n                    const dx = dir * Math.random() * blastLen;\n                    const dy = (Math.random() - 0.5) * 150;\n                    ctx.beginPath();\n                    ctx.arc(dx, dy + 80, 10 + Math.random() * 30, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                \n                ctx.restore();\n            }\n\n            if (fighter.type === 'rimuru') {\n                const ab4 = fighter.abilities[3];\n                const isUlt = ab4 && ab4.active;\n                const time = Date.now() / 1000;\n\n                // Draw Wings during Ultimate (Human Form with Wings)\n                if (isUlt) {\n                    ctx.save();\n                    ctx.fillStyle = '#000';\n                    ctx.shadowBlur = 15;\n                    ctx.shadowColor = '#000';\n                    const wingSway = Math.sin(time * 4) * 0.1;\n                    \n                    for(let side = -1; side <= 1; side += 2) {\n                        ctx.save();\n                        ctx.scale(side, 1);\n                        ctx.rotate(wingSway);\n                        // Procedural Bat Wings\n                        ctx.beginPath();\n                        ctx.moveTo(-10, -80);\n                        ctx.quadraticCurveTo(-80, -150, -180, -90); // Top curve\n                        ctx.lineTo(-170, -60);\n                        ctx.lineTo(-140, -40);\n                        ctx.lineTo(-110, -60);\n                        ctx.lineTo(-80, -40);\n                        ctx.lineTo(-50, -60);\n                        ctx.closePath();\n                        ctx.fill();\n                        ctx.restore();\n                    }\n                    ctx.restore();\n                }\n\n                if (isUlt) {\n                    ctx.save();\n                    ctx.resetTransform();\n                    \n                    for (const orb of ab4.clones) {\n                        const pulse = Math.sin(time * 8 + orb.offset) * 15;\n                        const ox = orb.x;\n                        const oy = orb.y + pulse;\n                        \n                        // 1. Draw Energy Beam (Thick glowing blue)\n                        const beamWidth = 25 + Math.sin(time * 30 + orb.offset) * 8;\n                        const beamGrad = ctx.createLinearGradient(ox - beamWidth, 0, ox + beamWidth, 0);\n                        beamGrad.addColorStop(0, 'transparent');\n                        beamGrad.addColorStop(0.3, 'rgba(0, 191, 255, 0.6)');\n                        beamGrad.addColorStop(0.5, 'rgba(255, 255, 255, 0.9)');\n                        beamGrad.addColorStop(0.7, 'rgba(0, 191, 255, 0.6)');\n                        beamGrad.addColorStop(1, 'transparent');\n                        \n                        ctx.fillStyle = beamGrad;\n                        ctx.shadowBlur = 40;\n                        ctx.shadowColor = '#00BFFF';\n                        ctx.fillRect(ox - beamWidth, oy, beamWidth * 2, GROUND_Y - oy);\n                        \n                        // 2. Draw Energy Orb in the sky\n                        ctx.save();\n                        ctx.translate(ox, oy);\n                        const orbSize = 35 + pulse * 0.2;\n                        \n                        // Outer glow\n                        const orbGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, orbSize);\n                        orbGrad.addColorStop(0, '#fff');\n                        orbGrad.addColorStop(0.4, '#00BFFF');\n                        orbGrad.addColorStop(1, 'transparent');\n                        \n                        ctx.fillStyle = orbGrad;\n                        ctx.beginPath();\n                        ctx.arc(0, 0, orbSize, 0, Math.PI * 2);\n                        ctx.fill();\n                        \n                        // Core\n                        ctx.fillStyle = '#fff';\n                        ctx.beginPath();\n                        ctx.arc(0, 0, orbSize * 0.4, 0, Math.PI * 2);\n                        ctx.fill();\n                        ctx.restore();\n                        \n                        // 3. Ground Impact Pulse\n                        ctx.save();\n                        ctx.globalAlpha = 0.5;\n                        ctx.fillStyle = '#fff';\n                        ctx.beginPath();\n                        ctx.ellipse(ox, GROUND_Y, 40 + pulse, 10, 0, 0, Math.PI * 2);\n                        ctx.fill();\n                        ctx.restore();\n                    }\n                    ctx.restore();\n                }\n            }\n\n            // Draw sprite\n            const aspect = sprite.naturalWidth / sprite.naturalHeight;\n            let drawH = 130;\n\n            if (isNika && (fighter.state === 'ability1' || fighter.state === 'ability2' || fighter.state === 'ability3')) {\n                drawH = 180; // Bigger during attacks\n            }\n            const drawW = drawH * aspect;\n            \n            if (fighter.type === 'nobita' || (fighter.type === 'poPanda' && fighter.abilities[1].active)) {\n                const time = Date.now() / 1000;\n                const dir = 1; // Flipped context handles direction\n                ctx.save();\n                \n                if (fighter.type === 'poPanda') {\n                    // Po's Rolling Visual - spin the sprite\n                    ctx.rotate(time * 20 * dir);\n                    ctx.drawImage(sprite, -drawW/2, -drawH/2, drawW, drawH);\n                    ctx.restore();\n                    return;\n                }\n\n                ctx.translate(dir * 60, -70);\n                \n                // Dynamic white wind blast\n                for (let j = 0; j < 3; j++) {\n                    const offset = Math.sin(time * 15 + j) * 15;\n                    const grad = ctx.createLinearGradient(0, 0, dir * 600, 0);\n                    grad.addColorStop(0, 'rgba(255, 255, 255, 0.9)');\n                    grad.addColorStop(0.5, 'rgba(255, 255, 255, 0.4)');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.fillRect(0, -40 + j * 20 + offset, dir * 600, 50);\n                }\n\n                // White wind lines\n                ctx.strokeStyle = '#fff';\n                ctx.lineWidth = 3;\n                ctx.globalAlpha = 0.7;\n                for (let i = 0; i < 8; i++) {\n                    const lx = Math.random() * 500 * dir;\n                    const ly = (Math.random() - 0.5) * 120;\n                    ctx.beginPath();\n                    ctx.moveTo(lx, ly);\n                    ctx.lineTo(lx + dir * 120, ly);\n                    ctx.stroke();\n                }\n                ctx.restore();\n            }\n\n            // Apply Nika white tint or SSJ2 Golden Tint\n            if (isNika) {\n                ctx.save();\n                drawFighterSprite(fighter, sprite, -drawW/2, -drawH, drawW, drawH);\n                ctx.globalCompositeOperation = 'source-atop';\n                ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';\n                ctx.fillRect(-drawW/2, -drawH, drawW, drawH);\n                ctx.restore();\n            } else if (fighter.type === 'goku' && fighter.isUI) {\n                // Draw Normal Sprite first (Face and Clothes stay normal)\n                drawFighterSprite(fighter, sprite, -drawW/2, -drawH, drawW, drawH);\n                \n                // Draw Spiky Silver Hair\n                ctx.save();\n                ctx.fillStyle = '#C0C0C0'; // Silver color\n                ctx.shadowBlur = 15;\n                ctx.shadowColor = '#B0E0E6';\n                \n                const headY = -108; \n                ctx.beginPath();\n                // Base of hair\n                ctx.arc(0, headY, 18, Math.PI, 0); \n                \n                // Hair spikes\n                for (let i = 0; i <= 8; i++) {\n                    const angle = -Math.PI + (i / 8) * Math.PI;\n                    const outerR = 38 + (i % 2 === 0 ? 10 : 0); // Varying spike length\n                    const innerR = 18;\n                    \n                    const ox = Math.cos(angle) * outerR;\n                    const oy = headY + Math.sin(angle) * outerR;\n                    ctx.lineTo(ox, oy);\n                    \n                    const nextAngle = -Math.PI + ((i + 0.5) / 8) * Math.PI;\n                    const ix = Math.cos(nextAngle) * innerR;\n                    const iy = headY + Math.sin(nextAngle) * innerR;\n                    ctx.lineTo(ix, iy);\n                }\n                \n                ctx.closePath();\n                ctx.fill();\n                \n                // Inner hair shine for depth\n                ctx.globalAlpha = 0.5;\n                ctx.fillStyle = '#FFFFFF';\n                ctx.beginPath();\n                ctx.arc(0, headY, 12, Math.PI, 0);\n                ctx.fill();\n                ctx.restore();\n            } else if (fighter.type === 'shadowGarden') {\n                // Draw Shadow's Signature Trench Coat (Eminence style)\n                ctx.save();\n                const time = Date.now() / 1000;\n                const sway = Math.sin(time * 4) * 5;\n                const trail = -fighter.vx * 5;\n                const jumpTrail = fighter.vy * 4;\n                const walkBob = (fighter.state === 'walk') ? Math.sin(time * 12) * 3 : 0;\n\n                ctx.fillStyle = '#000000';\n                \n                // Draw several flowing tails for the coat to give it that \"anime\" flair\n                for (let j = 0; j < 3; j++) {\n                    ctx.save();\n                    const spread = (j - 1) * 12;\n                    ctx.beginPath();\n                    ctx.moveTo(-10 + spread, -85 + walkBob);\n                    // Curvy flowing tails\n                    ctx.bezierCurveTo(\n                        -30 + trail + spread, -40 + jumpTrail + walkBob,\n                        -70 + trail + sway + spread, -10 + jumpTrail + walkBob,\n                        -50 + trail + sway + spread, 30 + jumpTrail + walkBob\n                    );\n                    ctx.lineTo(spread, walkBob);\n                    ctx.lineTo(spread + 10, -85 + walkBob);\n                    ctx.fill();\n\n                    // Gold lines/trim on coat edges\n                    ctx.strokeStyle = '#FFD700'; // Gold\n                    ctx.lineWidth = 1.5;\n                    ctx.globalAlpha = 0.8;\n                    ctx.beginPath();\n                    ctx.moveTo(-10 + spread, -85 + walkBob);\n                    ctx.bezierCurveTo(\n                        -30 + trail + spread, -40 + jumpTrail + walkBob,\n                        -70 + trail + sway + spread, -10 + jumpTrail + walkBob,\n                        -50 + trail + sway + spread, 30 + jumpTrail + walkBob\n                    );\n                    ctx.stroke();\n                    ctx.restore();\n                }\n\n                // Shoulder mantle / Collar\n                ctx.fillStyle = '#000000';\n                ctx.fillRect(-22, -95 + walkBob, 44, 18);\n                \n                // Gold trim on mantle\n                ctx.strokeStyle = '#FFD700';\n                ctx.lineWidth = 1.5;\n                ctx.strokeRect(-22, -95 + walkBob, 44, 18);\n                \n                ctx.fillStyle = '#111';\n                ctx.fillRect(-20, -93 + walkBob, 40, 5); // Shoulder strap detail\n                \n                ctx.restore();\n\n                // Draw the stick figure sprite on top of the coat\n                ctx.drawImage(sprite, -drawW/2, -drawH + walkBob, drawW, drawH);\n\n                // Lord Shadow's iconic glowing violet eye\n                ctx.save();\n                // Dynamic eye positioning based on walk bob and animation\n                const eyeX = 7; \n                const eyeY = -104 + walkBob;\n                ctx.shadowBlur = 15;\n                ctx.shadowColor = '#9370DB';\n                ctx.fillStyle = '#9370DB';\n                ctx.beginPath();\n                ctx.arc(eyeX, eyeY, 3.8, 0, Math.PI * 2);\n                ctx.fill();\n                // Inner white spark for intensity\n                ctx.fillStyle = '#fff';\n                ctx.beginPath();\n                ctx.arc(eyeX, eyeY, 1.4, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.restore();\n            } else if (fighter.type === 'goku' && fighter.abilities[3] && fighter.abilities[3].active) {\n                // Super Saiyan 2 Golden Tint & Hair Replacement\n                ctx.save();\n                drawFighterSprite(fighter, sprite, -drawW/2, -drawH, drawW, drawH);\n                \n                // Mask black hair by redrawing the head circle in Goku's base color\n                ctx.fillStyle = '#FFA500';\n                ctx.beginPath();\n                ctx.arc(0, -100, 16, 0, Math.PI * 2);\n                ctx.fill();\n\n                ctx.globalCompositeOperation = 'source-atop';\n                ctx.fillStyle = 'rgba(255, 215, 0, 0.25)'; \n                ctx.fillRect(-drawW/2, -drawH, drawW, drawH);\n                ctx.restore();\n\n                const hair = imageCache['goku_hair_ssj'];\n                if (hair) {\n                    ctx.save();\n                    const headY = -102; \n                    const hSize = 80; // Smaller as requested\n                    const hAspect = hair.naturalWidth / hair.naturalHeight;\n                    const hW = hSize * hAspect;\n                    // Position hair to sit on the head correctly\n                    ctx.drawImage(hair, -hW/2, headY - hSize * 0.85, hW, hSize);\n                    ctx.restore();\n                }\n            } else {\n                drawFighterSprite(fighter, sprite, -drawW/2, -drawH, drawW, drawH);\n            }\n\n            // Draw Goku UI Effects AFTER sprite\n            if (fighter.type === 'goku' && fighter.isUI) {\n                ctx.save();\n                // Silvery lightning sparks for UI\n                ctx.strokeStyle = '#B0E0E6';\n                ctx.lineWidth = 1.5;\n                if (Math.random() > 0.7) {\n                    ctx.beginPath();\n                    const lx = (Math.random() - 0.5) * 180;\n                    const ly = -20 - Math.random() * 160;\n                    ctx.moveTo(lx, ly);\n                    ctx.lineTo(lx + (Math.random()-0.5)*50, ly + (Math.random()-0.5)*50);\n                    ctx.stroke();\n                }\n                ctx.restore();\n            }\n\n            // Giant Punch Visuals for Luffy (Nika, Gear 2, Gear 4)\n            if (isNika || isGear2 || isGear4) {\n                if (fighter.state === 'ability1' || (fighter.type === 'luffy' && fighter.abilities[3] && fighter.abilities[3].active)) {\n                    const ab4 = fighter.abilities[3];\n                    const isUlt = ab4 && ab4.active;\n                    \n                    if (isUlt) {\n                        // Preparation Visuals (Rings behind Luffy - King Kong Gun style)\n                        if (isGear4 && ab4.activeTimer > 0.8) {\n                            ctx.save();\n                            const time = Date.now() / 1000;\n                            // Central white flash core\n                            ctx.globalAlpha = 0.9;\n                            ctx.shadowBlur = 50;\n                            ctx.shadowColor = '#fff';\n                            ctx.fillStyle = '#fff';\n                            ctx.beginPath();\n                            ctx.arc(0, -60, 45 + Math.sin(time*20)*15, 0, Math.PI*2);\n                            ctx.fill();\n\n                            // Red expanding rings\n                            ctx.globalAlpha = 0.6;\n                            ctx.strokeStyle = '#f00';\n                            ctx.lineWidth = 14;\n                            ctx.shadowBlur = 40;\n                            ctx.shadowColor = '#f00';\n                            for(let k=0; k<4; k++) {\n                                const r = 110 + k * 55 + Math.sin(time * 12 + k) * 35;\n                                ctx.beginPath();\n                                ctx.arc(0, -60, r, 0, Math.PI * 2);\n                                ctx.stroke();\n                            }\n                            ctx.restore();\n                        }\n\n                        // Massive downward smash\n                        ctx.save();\n                        // Gear 4 King Kong Gun is the largest\n                        const fSize = isGear4 ? 320 : (isNika ? 220 : 180);\n                        const fistY = (isGear4 && ab4.activeTimer <= 0.8) ? 0 : -400; // King Kong Gun smash lead\n                        ctx.translate(0, fistY); \n                        ctx.translate(Math.sin(Date.now()/50)*10, Math.cos(Date.now()/70)*10);\n                        \n                        if (isNika) {\n                            drawGiantFist(ctx, 220, '#000', true); // Black Haki Bajrang Gun\n                        } else if (isGear4) {\n                            // Gear 4 King Kong Gun - Bulky and blocky as in reference image\n                            ctx.shadowBlur = 100;\n                            ctx.shadowColor = '#f00';\n                            \n                            // Draw the bulky square-ish fist\n                            ctx.save();\n                            const kw = fSize * 1.8;\n                            const kh = fSize * 1.4;\n                            \n                            // Main bulky fist body (rounded rectangle)\n                            const kGrad = ctx.createLinearGradient(0, -kh/2, 0, kh/2);\n                            kGrad.addColorStop(0, '#333');\n                            kGrad.addColorStop(0.5, '#000');\n                            kGrad.addColorStop(1, '#000');\n                            ctx.fillStyle = kGrad;\n                            ctx.strokeStyle = '#f00';\n                            ctx.lineWidth = 12;\n                            ctx.beginPath();\n                            ctx.roundRect(-kw/2, -kh/2, kw, kh, 40);\n                            ctx.fill();\n                            ctx.stroke();\n\n                            // Glowing Red Flame/Haki patterns (Reference-style)\n                            ctx.globalAlpha = 0.8;\n                            ctx.strokeStyle = '#f00';\n                            ctx.lineWidth = 8;\n                            ctx.lineCap = 'round';\n                            for (let p = 0; p < 4; p++) {\n                                ctx.beginPath();\n                                const px = -kw/2 + 40 + Math.random() * (kw - 80);\n                                ctx.moveTo(px, kh/2);\n                                ctx.quadraticCurveTo(px + 20, kh/4, px - 20, -kh/4);\n                                ctx.stroke();\n                            }\n\n                            // Knuckle definitions (square bumps)\n                            ctx.fillStyle = '#111';\n                            for(let k=0; k<4; k++) {\n                                const kx = -kw/2 + (k+0.5) * (kw/4);\n                                ctx.beginPath();\n                                ctx.roundRect(kx - 35, kh/2 - 20, 70, 40, 10);\n                                ctx.fill();\n                                ctx.stroke();\n                            }\n\n                            // Floating Rocks around the fist (Debris during descent)\n                            ctx.globalAlpha = 1.0;\n                            const time = Date.now() / 1000;\n                            for (let r = 0; r < 12; r++) {\n                                const rx = Math.sin(time * 10 + r) * (kw * 0.8);\n                                const ry = Math.cos(time * 8 + r) * (kh * 0.8);\n                                const rs = 15 + Math.random() * 25;\n                                ctx.save();\n                                ctx.translate(rx, ry);\n                                ctx.rotate(time * 5 + r);\n                                ctx.fillStyle = '#4a3728';\n                                ctx.strokeStyle = '#261a15';\n                                ctx.lineWidth = 2;\n                                ctx.beginPath();\n                                ctx.moveTo(-rs, -rs/2); ctx.lineTo(rs, -rs); ctx.lineTo(rs/2, rs); ctx.closePath();\n                                ctx.fill();\n                                ctx.stroke();\n                                ctx.restore();\n                            }\n                            ctx.restore();\n                            \n                            // Intense Haki Lightning for Gear 4\n                            ctx.globalAlpha = 0.9;\n                            for(let i=0; i<10; i++) {\n                                const ang = Math.random()*Math.PI*2;\n                                const r1 = fSize * 0.8;\n                                const r2 = fSize * 1.6;\n                                ctx.strokeStyle = Math.random() > 0.4 ? '#f00' : '#000';\n                                ctx.lineWidth = 6;\n                                ctx.beginPath();\n                                ctx.moveTo(Math.cos(ang)*r1, Math.sin(ang)*r1);\n                                ctx.lineTo(Math.cos(ang)*r2, Math.sin(ang)*r2);\n                                ctx.stroke();\n                            }\n                        } else {\n                            // Gear 2: Reddish/Pinkish massive fist with steam\n                            ctx.shadowBlur = 30;\n                            ctx.shadowColor = '#FF1493';\n                            drawGiantFist(ctx, fSize, '#FFB6C1', false); \n                            \n                            // Extra steam for the giant fist\n                            ctx.fillStyle = '#fff';\n                            for(let i=0; i<8; i++) {\n                                const ang = (Date.now()/200 + i) % (Math.PI*2);\n                                ctx.globalAlpha = 0.4;\n                                ctx.beginPath();\n                                ctx.arc(Math.cos(ang)*120, Math.sin(ang)*120, 30, 0, Math.PI*2);\n                                ctx.fill();\n                            }\n                        }\n                        ctx.restore();\n                    } else if (isNika) {\n                        // Nika Normal Punch\n                        ctx.save();\n                        ctx.translate(90, -75);\n                        drawGiantFist(ctx, 65, '#fff', false);\n                        ctx.restore();\n                    } else if (isGear4 && fighter.state === 'ability1') {\n                        // Kong Gun\n                        ctx.save();\n                        ctx.translate(110, -90);\n                        drawGiantFist(ctx, 85, '#000', true);\n                        ctx.restore();\n                    }\n                } else if (isNika && fighter.state === 'ability2') {\n                    // Gigant Punch (Standard Nika move)\n                    ctx.save();\n                    ctx.translate(60, -40);\n                    drawGiantFist(ctx, 55, '#fff', false);\n                    ctx.restore();\n                } else if (isGear4 && fighter.state === 'ability2') {\n                    // Rhino Schneider visual\n                    ctx.save();\n                    ctx.translate(30, 20);\n                    ctx.rotate(Math.PI / 4);\n                    drawGiantFist(ctx, 40, '#000', true); // Treat as compressed leg/foot\n                    ctx.restore();\n                } else if (fighter.state === 'ability3') {\n                    if (isNika) {\n                        // Dawn Gatling\n                        ctx.save();\n                        for (let i = 0; i < 4; i++) {\n                            ctx.save();\n                            const offX = 60 + Math.random() * 100;\n                            const offY = -40 - Math.random() * 100;\n                            ctx.translate(offX, offY);\n                            drawGiantFist(ctx, 30, '#fff', false);\n                            ctx.restore();\n                        }\n                        ctx.restore();\n                    } else if (isGear4) {\n                        // Kong Organ\n                        ctx.save();\n                        for (let i = 0; i < 6; i++) {\n                            ctx.save();\n                            const offX = 90 + Math.random() * 130;\n                            const offY = -40 - Math.random() * 110;\n                            ctx.translate(offX, offY);\n                            drawGiantFist(ctx, 45, '#000', true);\n                            ctx.restore();\n                        }\n                        ctx.restore();\n                    } else {\n                        // Regular Gatling\n                        ctx.save();\n                        ctx.fillStyle = '#fff';\n                        ctx.strokeStyle = '#000';\n                        for (let i = 0; i < 3; i++) {\n                            const offX = 40 + Math.random() * 40;\n                            const offY = -40 - Math.random() * 60;\n                            ctx.beginPath();\n                            ctx.arc(offX, offY, 15, 0, Math.PI * 2);\n                            ctx.fill();\n                            ctx.stroke();\n                        }\n                        ctx.restore();\n                    }\n                }\n            } else if (fighter.type === 'luffy' && fighter.state === 'ability3') {\n                // Normal Gatling fists\n                ctx.save();\n                ctx.fillStyle = '#fff';\n                ctx.strokeStyle = '#000';\n                for (let i = 0; i < 3; i++) {\n                    const offX = 40 + Math.random() * 40;\n                    const offY = -40 - Math.random() * 60;\n                    ctx.beginPath();\n                    ctx.arc(offX, offY, 15, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.stroke();\n                }\n                ctx.restore();\n            }\n\n            // Draw giant fist logic...\n            ctx.restore();\n\n            // Shield visual\n            if (fighter.type === 'batBai' && fighter.abilities[1].active && !fighter.abilities[1].shieldHit) {\n                ctx.save();\n                ctx.translate(fighter.x, fighter.y - 60);\n                ctx.globalAlpha = 0.4;\n                ctx.strokeStyle = '#4A90E2';\n                ctx.lineWidth = 3;\n                const dir = fighter.facingRight ? 1 : -1;\n                ctx.beginPath();\n                ctx.ellipse(dir * 35, 0, 20, 40, 0, 0, Math.PI * 2);\n                ctx.stroke();\n                ctx.fillStyle = 'rgba(74, 144, 226, 0.2)';\n                ctx.fill();\n                ctx.restore();\n            } else if (fighter.type === 'madara' && fighter.abilities[1].active) {\n                // H\u00e0o H\u1ecfa Di\u1ec7t Visual (Great Fire Annihilation)\n                ctx.save();\n                ctx.translate(fighter.x, fighter.y - 70);\n                const dir = fighter.facingRight ? 1 : -1;\n                const time = Date.now() / 1000;\n                \n                // Fire Wall effect\n                for (let i = 0; i < 15; i++) {\n                    const progress = ( (time * 5 + i) % 15 ) / 15;\n                    const fx = dir * progress * 550;\n                    const fy = Math.sin(time * 10 + i) * 30;\n                    const size = 40 + progress * 100;\n                    \n                    const grad = ctx.createRadialGradient(fx, fy, 0, fx, fy, size);\n                    grad.addColorStop(0, '#FFFACD');\n                    grad.addColorStop(0.3, '#FFD700');\n                    grad.addColorStop(0.6, '#FF4500');\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.globalAlpha = (1 - progress) * 0.8;\n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    ctx.arc(fx, fy, size, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                ctx.restore();\n            } else if (fighter.type === 'sukuna' && fighter.abilities[2].active) {\n                // Malevolent Shrine Visual (L\u00e3nh \u0111\u1ecba Ph\u1ee5c Ma Ng\u1ef1 \u0110\u1ed9c T\u1eed)\n                ctx.save();\n                ctx.resetTransform();\n                const time = Date.now() / 1000;\n                \n                // 1. Domain Atmosphere (Darken and slight red tint)\n                ctx.globalAlpha = 0.5;\n                ctx.fillStyle = '#000';\n                ctx.fillRect(0, 0, 720, 1280);\n                ctx.globalAlpha = 0.15;\n                ctx.fillStyle = '#f00';\n                ctx.fillRect(0, 0, 720, 1280);\n\n                // 2. Draw the Shrine (Temple) behind Sukuna\n                ctx.translate(fighter.x, fighter.y - 120);\n                ctx.globalAlpha = 1.0;\n                \n                // Shrine shadow/base\n                ctx.fillStyle = 'rgba(0,0,0,0.5)';\n                ctx.beginPath();\n                ctx.ellipse(0, 120, 200, 40, 0, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Piles of Skulls at the base\n                for(let k=0; k<16; k++) {\n                    const sx = (k-8) * 18 + Math.sin(k*2)*10;\n                    const sy = 120 + Math.cos(k)*5;\n                    ctx.fillStyle = '#d2d2d2';\n                    ctx.beginPath();\n                    ctx.arc(sx, sy, 10, 0, Math.PI*2);\n                    ctx.fill();\n                    // Eye sockets\n                    ctx.fillStyle = '#111';\n                    ctx.beginPath(); ctx.arc(sx-4, sy-2, 2.5, 0, Math.PI*2); ctx.fill();\n                    ctx.beginPath(); ctx.arc(sx+4, sy-2, 2.5, 0, Math.PI*2); ctx.fill();\n                }\n\n                // Main Structure (Dark Red Pillars)\n                ctx.fillStyle = '#400';\n                ctx.strokeStyle = '#200';\n                ctx.lineWidth = 2;\n                ctx.fillRect(-70, -100, 20, 220); // Left Pillar\n                ctx.strokeRect(-70, -100, 20, 220);\n                ctx.fillRect(50, -100, 20, 220); // Right Pillar\n                ctx.strokeRect(50, -100, 20, 220);\n\n                // The Mouth/Portal\n                ctx.fillStyle = '#000';\n                const pulse = Math.sin(time * 8) * 5;\n                ctx.beginPath();\n                ctx.ellipse(0, -10, 50 + pulse, 80, 0, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.strokeStyle = '#600';\n                ctx.lineWidth = 3;\n                ctx.stroke();\n\n                // Ornate Curved Roof (Multiple tiers)\n                const drawRoof = (y, w, h, curve) => {\n                    ctx.fillStyle = '#111';\n                    ctx.strokeStyle = '#300';\n                    ctx.lineWidth = 4;\n                    ctx.beginPath();\n                    ctx.moveTo(-w, y);\n                    ctx.quadraticCurveTo(0, y - curve, w, y);\n                    ctx.lineTo(w - 20, y - h);\n                    ctx.quadraticCurveTo(0, y - h - curve, -w + 20, y - h);\n                    ctx.closePath();\n                    ctx.fill();\n                    ctx.stroke();\n                    // Spikes at corners\n                    ctx.beginPath();\n                    ctx.moveTo(-w, y); ctx.lineTo(-w - 15, y - 25);\n                    ctx.moveTo(w, y); ctx.lineTo(w + 15, y - 25);\n                    ctx.stroke();\n                };\n\n                drawRoof(-100, 130, 40, 30); // Bottom tier\n                drawRoof(-160, 90, 50, 40);  // Top tier\n\n                // 3. Black and White Slashes (Cleave & Dismantle)\n                ctx.resetTransform();\n                const domainX = fighter.x;\n                const domainY = fighter.y;\n                const domainR = 400;\n\n                for(let i=0; i<15; i++) {\n                    const angle = Math.random() * Math.PI * 2;\n                    const dist = Math.random() * domainR;\n                    const sx = domainX + Math.cos(angle) * dist;\n                    const sy = domainY - 100 + Math.sin(angle) * dist;\n                    \n                    ctx.save();\n                    ctx.translate(sx, sy);\n                    ctx.rotate(Math.random() * Math.PI * 2);\n                    \n                    const len = 80 + Math.random() * 200;\n                    const color = Math.random() > 0.4 ? '#fff' : '#000';\n                    \n                    ctx.strokeStyle = color;\n                    ctx.lineWidth = 1 + Math.random() * 2;\n                    ctx.shadowBlur = color === '#fff' ? 10 : 0;\n                    ctx.shadowColor = '#fff';\n                    \n                    ctx.beginPath();\n                    ctx.moveTo(-len/2, 0);\n                    ctx.lineTo(len/2, 0);\n                    ctx.stroke();\n                    \n                    // Ghosting effect for speed\n                    ctx.globalAlpha = 0.5;\n                    ctx.beginPath();\n                    ctx.moveTo(-len/2, 4);\n                    ctx.lineTo(len/2, 4);\n                    ctx.stroke();\n                    \n                    ctx.restore();\n                }\n\n                // Domain Edge Pulse\n                ctx.globalAlpha = 0.1;\n                ctx.fillStyle = '#f00';\n                ctx.beginPath();\n                ctx.ellipse(domainX, domainY, domainR, 120, 0, 0, Math.PI * 2);\n                ctx.fill();\n                \n                ctx.restore();\n            } else if (fighter.type === 'itachi' && fighter.abilities[1].active) {\n                // \u1ea2o Thu\u1eadt: Kh\u00f4ng Gian \u0110en Visual\n                ctx.save();\n                ctx.resetTransform();\n                const time = Date.now() / 1000;\n                \n                // 1. Dark Red Void\n                const bgGrad = ctx.createRadialGradient(360, 640, 0, 360, 640, 800);\n                bgGrad.addColorStop(0, '#300000');\n                bgGrad.addColorStop(1, '#000000');\n                ctx.globalAlpha = 0.7;\n                ctx.fillStyle = bgGrad;\n                ctx.fillRect(0, 0, 720, 1280);\n\n                // 2. Swirling Crows / Feathers\n                ctx.globalAlpha = 1.0;\n                ctx.fillStyle = '#000';\n                for (let i = 0; i < 25; i++) {\n                    const seed = i * 137.5;\n                    const r = 100 + (Math.sin(time * 0.5 + seed) * 0.5 + 0.5) * 400;\n                    const angle = time * 2.5 + seed;\n                    const x = 360 + Math.cos(angle) * r;\n                    const y = 640 + Math.sin(angle) * r;\n                    \n                    ctx.save();\n                    ctx.translate(x, y);\n                    ctx.rotate(angle);\n                    // Feather shape\n                    ctx.beginPath();\n                    ctx.ellipse(0, 0, 15, 5, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                }\n\n                // 3. Static/Glitch Overlay\n                ctx.globalAlpha = 0.1;\n                ctx.fillStyle = '#fff';\n                for(let i=0; i<5; i++) {\n                    ctx.fillRect(0, Math.random()*1280, 720, 2);\n                }\n\n                // 4. Detailed Sharingan Eye in center\n                const eyeCenterX = 360;\n                const eyeCenterY = 450;\n                const eyeR = 80;\n                \n                ctx.globalAlpha = 0.5 + Math.sin(time * 3) * 0.1;\n                ctx.shadowBlur = 30;\n                ctx.shadowColor = '#f00';\n                \n                // Red Iris\n                ctx.fillStyle = '#f00';\n                ctx.beginPath();\n                ctx.ellipse(eyeCenterX, eyeCenterY, eyeR * 1.5, eyeR * 0.8, 0, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Inner Iris Rings\n                ctx.strokeStyle = 'rgba(0,0,0,0.3)';\n                ctx.lineWidth = 2;\n                ctx.shadowBlur = 0;\n                for (let r = 0.4; r < 1; r += 0.3) {\n                    ctx.beginPath();\n                    ctx.ellipse(eyeCenterX, eyeCenterY, eyeR * 1.5 * r, eyeR * 0.8 * r, 0, 0, Math.PI * 2);\n                    ctx.stroke();\n                }\n\n                // Black Pupil\n                ctx.fillStyle = '#000';\n                ctx.beginPath();\n                ctx.ellipse(eyeCenterX, eyeCenterY, 25, 20, 0, 0, Math.PI * 2);\n                ctx.fill();\n\n                // 3 Tomoe dots (The \"commas\")\n                const tomoeRot = time * 2.5;\n                for (let i = 0; i < 3; i++) {\n                    ctx.save();\n                    const angle = tomoeRot + (i * Math.PI * 2 / 3);\n                    const tx = eyeCenterX + Math.cos(angle) * (eyeR * 0.8);\n                    const ty = eyeCenterY + Math.sin(angle) * (eyeR * 0.45);\n                    \n                    ctx.translate(tx, ty);\n                    ctx.rotate(angle + Math.PI / 2);\n                    \n                    // Tomoe Body\n                    ctx.fillStyle = '#000';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, 8, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Tomoe Tail\n                    ctx.beginPath();\n                    ctx.moveTo(0, -8);\n                    ctx.quadraticCurveTo(15, -5, 10, 15);\n                    ctx.quadraticCurveTo(5, 5, 0, 8);\n                    ctx.fill();\n                    \n                    ctx.restore();\n                }\n\n                ctx.restore();\n            } else if (fighter.type === 'madara' && fighter.abilities[3] && fighter.abilities[3].active) {\n                // Susanoo To\u00e0n Ch\u00e2n Th\u1ec3 Visual (Giant Susanoo - Perfect Form)\n                ctx.save();\n                ctx.resetTransform();\n                const time = Date.now() / 1000;\n                \n                const susanoImg = imageCache['madara_susanoo_perfect'];\n                if (susanoImg) {\n                    ctx.globalAlpha = 0.6 + Math.sin(time * 3) * 0.1;\n                    const aspect = susanoImg.naturalWidth / susanoImg.naturalHeight;\n                    const imgH = 1000;\n                    const imgW = imgH * aspect;\n                    \n                    // Center on fighter, at chest height (Inside the Susanoo)\n                    ctx.translate(fighter.x, fighter.y - 60);\n                    if (!fighter.facingRight) ctx.scale(-1, 1);\n                    \n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#4A90E2';\n                    // Draw centered on origin\n                    ctx.drawImage(susanoImg, -imgW/2, -imgH/2, imgW, imgH);\n                }\n                ctx.restore();\n            } else if (fighter.type === 'vuaQuy' && fighter.abilities[3] && fighter.abilities[3].active) {\n                // L\u00e3nh \u0110\u1ecba Visual\n                if (fighter.skin === 'beach') {\n                    // B\u00e3i Bi\u1ec3n Visual\n                    ctx.save();\n                    ctx.resetTransform();\n                    const time = Date.now() / 1000;\n                    \n                    // 1. Sky (Blue)\n                    const skyGrad = ctx.createLinearGradient(0, 0, 0, GROUND_Y);\n                    skyGrad.addColorStop(0, '#87CEEB');\n                    skyGrad.addColorStop(1, '#E0F6FF');\n                    ctx.fillStyle = skyGrad;\n                    ctx.fillRect(0, 0, 720, GROUND_Y);\n\n                    // 2. Sand and Water Floor\n                    // Sand (Half left)\n                    ctx.fillStyle = '#F4A460';\n                    ctx.fillRect(0, GROUND_Y, 360, 1280 - GROUND_Y);\n                    // Water (Half right)\n                    ctx.fillStyle = '#1E90FF';\n                    ctx.fillRect(360, GROUND_Y, 360, 1280 - GROUND_Y);\n                    \n                    // Waves at the border\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 5;\n                    ctx.beginPath();\n                    for(let y=GROUND_Y; y<1280; y+=20) {\n                        ctx.lineTo(360 + Math.sin(y/20 + time*5)*10, y);\n                    }\n                    ctx.stroke();\n\n                    // 3. Coconut Tree\n                    const tree = imageCache['coconut_tree'];\n                    if (tree) {\n                        ctx.drawImage(tree, 50, GROUND_Y - 300, 200, 320);\n                    } else {\n                        // Fallback simple tree\n                        ctx.fillStyle = '#8B4513';\n                        ctx.fillRect(100, GROUND_Y - 200, 30, 200);\n                        ctx.fillStyle = '#228B22';\n                        ctx.beginPath();\n                        ctx.arc(115, GROUND_Y - 200, 60, 0, Math.PI*2);\n                        ctx.fill();\n                    }\n\n                    // 4. Sun\n                    ctx.fillStyle = '#FFD700';\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#FFFF00';\n                    ctx.beginPath();\n                    ctx.arc(600, 150, 60, 0, Math.PI*2);\n                    ctx.fill();\n                    ctx.shadowBlur = 0;\n\n                    ctx.restore();\n                } else {\n                    // Enhanced Hell Domain (Original logic)\n                    ctx.save();\n                    ctx.resetTransform();\n                    const time = Date.now() / 1000;\n                \n                // 1. Dark Hellish Sky Background\n                const bgGrad = ctx.createLinearGradient(0, 0, 0, 1280);\n                bgGrad.addColorStop(0, '#2d0000');\n                bgGrad.addColorStop(1, '#660000');\n                ctx.globalAlpha = 0.8;\n                ctx.fillStyle = bgGrad;\n                ctx.fillRect(0, 0, 720, 1280);\n\n                // 2. Draw Volcanoes in the background\n                ctx.globalAlpha = 1.0;\n                const drawVolcano = (vx, vy, vscale, vseed) => {\n                    ctx.save();\n                    ctx.translate(vx, vy);\n                    ctx.scale(vscale, vscale);\n                    \n                    // Volcano body\n                    ctx.fillStyle = '#1a0a0a';\n                    ctx.beginPath();\n                    ctx.moveTo(-150, 200);\n                    ctx.lineTo(0, -100);\n                    ctx.lineTo(150, 200);\n                    ctx.closePath();\n                    ctx.fill();\n                    \n                    // Lava at the peak\n                    const pulse = Math.sin(time * 2 + vseed) * 0.2 + 0.8;\n                    ctx.fillStyle = `rgba(255, 69, 0, ${pulse})`;\n                    ctx.shadowBlur = 20;\n                    ctx.shadowColor = '#FF4500';\n                    ctx.beginPath();\n                    ctx.moveTo(-30, -40);\n                    ctx.lineTo(0, -100);\n                    ctx.lineTo(30, -40);\n                    ctx.closePath();\n                    ctx.fill();\n                    \n                    // Lava flows down the side\n                    ctx.strokeStyle = '#FF8C00';\n                    ctx.lineWidth = 4;\n                    ctx.beginPath();\n                    ctx.moveTo(0, -80);\n                    ctx.lineTo(20, 20 + Math.sin(time + vseed) * 10);\n                    ctx.stroke();\n                    \n                    ctx.restore();\n                };\n\n                drawVolcano(100, GROUND_Y - 150, 0.6, 1);\n                drawVolcano(360, GROUND_Y - 200, 0.8, 2);\n                drawVolcano(620, GROUND_Y - 140, 0.5, 3);\n\n                // 3. Hellish Overlay (pulsing red mist)\n                ctx.globalAlpha = 0.2 + Math.sin(time * 1.5) * 0.1;\n                ctx.fillStyle = '#FF4500';\n                ctx.fillRect(0, 0, 720, 1280);\n\n                // 4. Lava Floor\n                ctx.globalAlpha = 0.7;\n                const floorGrad = ctx.createLinearGradient(0, GROUND_Y, 0, 1280);\n                floorGrad.addColorStop(0, '#FF4500');\n                floorGrad.addColorStop(0.5, '#8B0000');\n                floorGrad.addColorStop(1, '#000');\n                ctx.fillStyle = floorGrad;\n                ctx.fillRect(0, GROUND_Y, 720, 1280 - GROUND_Y);\n\n                // 5. Enhanced Flame Particles & Embers\n                ctx.globalAlpha = 0.8;\n                for (let i = 0; i < 25; i++) {\n                    const seed = i * 13.5;\n                    const fx = (i * 30 + time * 60) % 720;\n                    const fy = GROUND_Y - 20 - Math.abs(Math.sin(time * 3 + seed)) * 60;\n                    \n                    // Flame core\n                    ctx.fillStyle = i % 3 === 0 ? '#FFFACD' : (i % 2 === 0 ? '#FFD700' : '#FF4500');\n                    ctx.beginPath();\n                    const fSize = 10 + Math.random() * 15;\n                    ctx.arc(fx, fy, fSize, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Embers rising up\n                    const ex = (seed * 20 + time * 30) % 720;\n                    const ey = (1280 - (time * 150 + seed * 10) % 1280);\n                    ctx.fillStyle = '#FFA500';\n                    ctx.globalAlpha = 0.6 * (ey / 1280); // Fade as they go up\n                    ctx.beginPath();\n                    ctx.arc(ex, ey, 2 + Math.random() * 3, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.globalAlpha = 0.8;\n                }\n                ctx.restore();\n            }\n        } else if (fighter.type === 'goku' && fighter.abilities[2].active) {\n                // Kamehameha Visual\n                const ab = fighter.abilities[2];\n                ctx.save();\n                ctx.translate(fighter.x, fighter.y - 70);\n                const dir = fighter.facingRight ? 1 : -1;\n                \n                if (ab.charging) {\n                    // Charging sphere\n                    const pulse = 20 + Math.sin(Date.now() / 50) * 10;\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = '#00BFFF';\n                    ctx.fillStyle = '#ADD8E6';\n                    ctx.beginPath();\n                    ctx.arc(dir * 40, 0, pulse, 0, Math.PI * 2);\n                    ctx.fill();\n                    // Sparks\n                    ctx.strokeStyle = '#fff';\n                    for(let i=0; i<3; i++) {\n                        ctx.beginPath();\n                        const ang = Math.random()*Math.PI*2;\n                        ctx.moveTo(dir*40 + Math.cos(ang)*pulse, Math.sin(ang)*pulse);\n                        ctx.lineTo(dir*40 + Math.cos(ang)*pulse*1.5, Math.sin(ang)*pulse*1.5);\n                        ctx.stroke();\n                    }\n                } else {\n                    // Firing beam\n                    const beamGrad = ctx.createLinearGradient(dir * 40, 0, dir * 800, 0);\n                    beamGrad.addColorStop(0, '#fff');\n                    beamGrad.addColorStop(0.2, '#00BFFF');\n                    beamGrad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = beamGrad;\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#00BFFF';\n                    \n                    const beamH = (fighter.isSSJ2 ? 150 : 60) + Math.sin(Date.now() / 30) * 15;\n                    ctx.beginPath();\n                    ctx.rect(dir * 40, -beamH/2, dir * 800, beamH);\n                    ctx.fill();\n                    \n                    // Core white beam\n                    ctx.fillStyle = '#fff';\n                    ctx.globalAlpha = 0.6;\n                    ctx.beginPath();\n                    ctx.rect(dir * 40, -beamH/4, dir * 800, beamH/2);\n                    ctx.fill();\n                }\n                ctx.restore();\n            } else if (fighter.type === 'gojo' && fighter.abilities[2].active) {\n                // Infinite Void Visual (Enhanced using user asset)\n                ctx.save();\n                ctx.resetTransform();\n                const time = Date.now() / 1000;\n                \n                const voidImg = imageCache['gojo_infinite_void'];\n                if (voidImg) {\n                    // Draw full-screen background image\n                    const canvasRatio = 720 / 1280;\n                    const imgRatio = voidImg.naturalWidth / voidImg.naturalHeight;\n                    let sw, sh, sx, sy;\n                    if (imgRatio > canvasRatio) {\n                        sh = voidImg.naturalHeight;\n                        sw = sh * canvasRatio;\n                        sx = (voidImg.naturalWidth - sw) / 2;\n                        sy = 0;\n                    } else {\n                        sw = voidImg.naturalWidth;\n                        sh = sw / canvasRatio;\n                        sx = 0;\n                        sy = (voidImg.naturalHeight - sh) / 2;\n                    }\n                    \n                    // Pulse alpha slightly\n                    ctx.globalAlpha = 0.9 + Math.sin(time * 2) * 0.1;\n                    ctx.drawImage(voidImg, sx, sy, sw, sh, 0, 0, 720, 1280);\n                    \n                    // Add atmospheric glitch effect\n                    ctx.globalAlpha = 0.1;\n                    ctx.fillStyle = '#fff';\n                    if (Math.random() > 0.8) {\n                        ctx.fillRect(0, Math.random() * 1280, 720, 5);\n                    }\n                } else {\n                    // Fallback\n                    ctx.fillStyle = '#000';\n                    ctx.fillRect(0, 0, 720, 1280);\n                }\n                ctx.restore();\n            } else if (fighter.type === 'sasuke' && fighter.abilities[0] && fighter.abilities[0].active) {\n                // L\u00f4i Long Thi\u00ean Ph\u1ea1t Strike Visual (Kirin)\n                const ab = fighter.abilities[0];\n                ctx.save();\n                ctx.resetTransform();\n                const time = Date.now() / 1000;\n                const sx = ab.strikeX;\n                \n                ctx.shadowBlur = 30;\n                ctx.shadowColor = '#00BFFF';\n                ctx.strokeStyle = '#fff';\n                ctx.lineWidth = 4;\n                \n                for(let j=0; j<3; j++) {\n                    ctx.save();\n                    ctx.globalAlpha = 0.4 + Math.sin(time*20+j)*0.3;\n                    ctx.beginPath();\n                    let curY = -100;\n                    let curX = sx + (j-1)*30;\n                    ctx.moveTo(curX, curY);\n                    while(curY < GROUND_Y) {\n                        curY += 50;\n                        curX += (Math.random()-0.5)*80;\n                        ctx.lineTo(curX, curY);\n                    }\n                    ctx.stroke();\n                    \n                    ctx.translate(sx, GROUND_Y - 40);\n                    ctx.scale(2, 2);\n                    ctx.fillStyle = '#fff';\n                    ctx.beginPath();\n                    ctx.moveTo(0, -20);\n                    ctx.lineTo(30, 0);\n                    ctx.lineTo(0, 20);\n                    ctx.closePath();\n                    ctx.fill();\n                    ctx.restore();\n                }\n                \n                ctx.globalAlpha = 0.2;\n                ctx.fillStyle = '#00BFFF';\n                ctx.beginPath();\n                ctx.arc(sx, GROUND_Y, 200 * (0.8 + Math.sin(time*30)*0.2), 0, Math.PI*2);\n                ctx.fill();\n                ctx.restore();\n            } else if (fighter.type === 'sasuke' && fighter.abilities[3] && fighter.abilities[3].active) {\n                // Chibaku Tensei Visual\n                const ab = fighter.abilities[3];\n                ctx.save();\n                ctx.resetTransform();\n                \n                // Draw particles\n                ctx.fillStyle = '#5c4033';\n                ctx.strokeStyle = '#3d2b22';\n                ctx.lineWidth = 2;\n                for (const p of ab.particles) {\n                    ctx.beginPath();\n                    ctx.rect(p.x - p.size/2, p.y - p.size/2, p.size, p.size);\n                    ctx.fill();\n                    ctx.stroke();\n                }\n\n                // Draw central sphere\n                const time = Date.now() / 1000;\n                ctx.save();\n                ctx.translate(ab.sphereX, ab.sphereY);\n                \n                // Pulsing glow\n                const glow = ctx.createRadialGradient(0, 0, 10, 0, 0, 150);\n                glow.addColorStop(0, 'rgba(0, 0, 0, 1)');\n                glow.addColorStop(0.4, 'rgba(61, 43, 34, 0.8)');\n                glow.addColorStop(1, 'rgba(0, 0, 0, 0)');\n                ctx.fillStyle = glow;\n                ctx.beginPath();\n                ctx.arc(0, 0, 150, 0, Math.PI * 2);\n                ctx.fill();\n\n                // Core rock sphere (gets bigger)\n                const coreSize = 30 + (ab.duration - ab.activeTimer) * 15;\n                ctx.fillStyle = '#3d2b22';\n                ctx.beginPath();\n                ctx.arc(0, 0, coreSize, 0, Math.PI * 2);\n                ctx.fill();\n                \n                // Rock textures\n                ctx.strokeStyle = '#261a15';\n                ctx.lineWidth = 3;\n                for(let i=0; i<8; i++) {\n                    ctx.beginPath();\n                    const angle = i * Math.PI / 4 + time;\n                    ctx.moveTo(Math.cos(angle) * coreSize, Math.sin(angle) * coreSize);\n                    ctx.lineTo(Math.cos(angle + 0.5) * coreSize * 0.8, Math.sin(angle + 0.5) * coreSize * 0.8);\n                    ctx.stroke();\n                }\n\n                ctx.restore();\n                ctx.restore();\n            } else if (fighter.type === 'bongDem' && fighter.abilities[3] && fighter.abilities[3].active) {\n                // L\u00e3nh \u0110\u1ecba B\u00f3ng \u0110\u00eam Visual\n                ctx.save();\n                ctx.translate(fighter.x, fighter.y - 60);\n                \n                // Outer glow\n                const time = Date.now() / 1000;\n                ctx.globalAlpha = 0.3 + Math.sin(time * 2) * 0.1;\n                ctx.fillStyle = '#000';\n                ctx.beginPath();\n                ctx.arc(0, 0, 400, 0, Math.PI * 2);\n                ctx.fill();\n                \n                // Pulsing Purple Border\n                ctx.strokeStyle = '#9B59B6';\n                ctx.lineWidth = 8 + Math.sin(time * 4) * 4;\n                ctx.setLineDash([20, 10]);\n                ctx.lineDashOffset = -time * 50;\n                ctx.stroke();\n                \n                // Shadow particles\n                ctx.fillStyle = '#9B59B6';\n                for (let i = 0; i < 15; i++) {\n                    const r = (Math.sin(time + i) * 0.5 + 0.5) * 380;\n                    const angle = i * 1.5 + time * 0.5;\n                    ctx.globalAlpha = 0.4;\n                    ctx.beginPath();\n                    ctx.arc(Math.cos(angle) * r, Math.sin(angle) * r, 3, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                \n                ctx.restore();\n            }\n\n            if (fighter.type === 'gojo') {\n                ctx.save();\n                ctx.translate(fighter.x, fighter.y);\n                if (fighter.state === 'ability1') {\n                    // Blue effect\n                    ctx.save();\n                    ctx.translate(fighter.facingRight ? 60 : -60, -80);\n                    ctx.globalAlpha = 0.6;\n                    ctx.fillStyle = '#0000FF';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, 30 + Math.sin(Date.now()/50)*5, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                } else if (fighter.state === 'ability2') {\n                    // Red effect\n                    ctx.save();\n                    ctx.translate(fighter.facingRight ? 60 : -60, -80);\n                    ctx.globalAlpha = 0.6;\n                    ctx.fillStyle = '#FF0000';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, 30 + Math.sin(Date.now()/50)*5, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                }\n\n                // Hollow Purple rendering\n                if (fighter.abilities[3] && fighter.abilities[3].active) {\n                    const ab = fighter.abilities[3];\n                    const time = ab.activeTimer;\n                    ctx.save();\n                    // Draw relative to feet (0,0)\n                    if (time > 1.5) {\n                        const progress = (3.0 - time) / 1.5;\n                        // Blue\n                        const bx = -50 * (1 - progress);\n                        const by = -100 - progress * 200;\n                        ctx.shadowBlur = 25; ctx.shadowColor = '#00f';\n                        ctx.fillStyle = '#00f';\n                        ctx.beginPath(); ctx.arc(bx, by, 20, 0, Math.PI*2); ctx.fill();\n                        // Red\n                        const rx = 50 * (1 - progress);\n                        const ry = -100 - progress * 200;\n                        ctx.shadowColor = '#f00';\n                        ctx.fillStyle = '#f00';\n                        ctx.beginPath(); ctx.arc(rx, ry, 20, 0, Math.PI*2); ctx.fill();\n                        \n                        // Energy arcs connecting them\n                        ctx.shadowBlur = 0;\n                        ctx.strokeStyle = '#fff';\n                        ctx.globalAlpha = progress * 0.5;\n                        ctx.lineWidth = 2;\n                        ctx.beginPath();\n                        ctx.moveTo(bx, by);\n                        ctx.quadraticCurveTo(0, -200, rx, ry);\n                        ctx.stroke();\n                    } else if (time > 0.1) {\n                        const progress = (1.5 - time) / 1.4;\n                        const px = 0;\n                        const py = -300;\n                        const size = 30 + progress * 100;\n                        ctx.shadowBlur = 50; ctx.shadowColor = '#800080';\n                        ctx.fillStyle = '#800080';\n                        ctx.beginPath(); ctx.arc(px, py, size, 0, Math.PI*2); ctx.fill();\n                        // Core shine\n                        ctx.fillStyle = '#fff';\n                        ctx.globalAlpha = 0.4;\n                        ctx.beginPath(); ctx.arc(px, py, size*0.4, 0, Math.PI*2); ctx.fill();\n                        // Electricity\n                        ctx.strokeStyle = '#fff';\n                        ctx.lineWidth = 3;\n                        for(let i=0; i<3; i++) {\n                           ctx.beginPath();\n                           const ang = Math.random()*Math.PI*2;\n                           ctx.moveTo(px + Math.cos(ang)*size, py + Math.sin(ang)*size);\n                           ctx.lineTo(px + Math.cos(ang)*size*1.3, py + Math.sin(ang)*size*1.3);\n                           ctx.stroke();\n                        }\n                    }\n                    ctx.restore();\n                }\n                ctx.restore();\n            }\n        }\n\n        function drawFivePointStar(ctx, x, y, outerRadius, innerRadius) {\n            ctx.beginPath();\n            for (let i = 0; i < 10; i++) {\n                const angle = -Math.PI / 2 + i * Math.PI / 5;\n                const radius = i % 2 === 0 ? outerRadius : innerRadius;\n                const px = x + Math.cos(angle) * radius;\n                const py = y + Math.sin(angle) * radius;\n                if (i === 0) ctx.moveTo(px, py);\n                else ctx.lineTo(px, py);\n            }\n            ctx.closePath();\n            ctx.fill();\n        }\n\n        function drawGiantFist(ctx, size, color = '#fff', isHaki = false) {\n            ctx.save();\n            \n            // Perspective / Shading\n            const grad = ctx.createRadialGradient(0, 0, size * 0.2, 0, 0, size);\n            if (isHaki) {\n                grad.addColorStop(0, '#444');\n                grad.addColorStop(0.7, '#111');\n                grad.addColorStop(1, '#000');\n            } else {\n                grad.addColorStop(0, '#fff');\n                grad.addColorStop(0.8, '#ddd');\n                grad.addColorStop(1, '#bbb');\n            }\n            \n            ctx.fillStyle = grad;\n            ctx.strokeStyle = isHaki ? '#f00' : '#333';\n            ctx.lineWidth = size * 0.05;\n            \n            // Draw Knuckles (More fist-like shape)\n            ctx.beginPath();\n            // Bottom part of fist\n            ctx.arc(0, 0, size, 0, Math.PI * 2);\n            ctx.fill();\n            ctx.stroke();\n\n            // Knuckle bumps\n            for (let i = 0; i < 4; i++) {\n                ctx.beginPath();\n                const angle = -Math.PI/2 + (i - 1.5) * 0.4;\n                const kx = Math.cos(angle) * size;\n                const ky = Math.sin(angle) * size;\n                ctx.arc(kx, ky, size * 0.25, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.stroke();\n            }\n\n            // Thumb\n            ctx.beginPath();\n            ctx.arc(-size * 0.7, 0, size * 0.3, 0, Math.PI * 2);\n            ctx.fill();\n            ctx.stroke();\n\n            // Fist detail lines (Creases)\n            ctx.beginPath();\n            ctx.strokeStyle = isHaki ? 'rgba(255,0,0,0.5)' : 'rgba(0,0,0,0.2)';\n            ctx.lineWidth = size * 0.02;\n            ctx.moveTo(-size * 0.4, -size * 0.2);\n            ctx.lineTo(size * 0.4, -size * 0.2);\n            ctx.moveTo(-size * 0.4, size * 0.1);\n            ctx.lineTo(size * 0.4, size * 0.1);\n            ctx.moveTo(-size * 0.4, size * 0.4);\n            ctx.lineTo(size * 0.4, size * 0.4);\n            ctx.stroke();\n\n            // Haki Lightning (Red/Black sparks around the fist)\n            if (isHaki) {\n                for (let i = 0; i < 6; i++) {\n                    const ang = Math.random() * Math.PI * 2;\n                    const r1 = size * 1.1;\n                    const r2 = size * 1.5;\n                    ctx.strokeStyle = Math.random() > 0.5 ? '#f00' : '#000';\n                    ctx.lineWidth = size * 0.04;\n                    ctx.beginPath();\n                    ctx.moveTo(Math.cos(ang) * r1, Math.sin(ang) * r1);\n                    let lx = Math.cos(ang) * r1;\n                    let ly = Math.sin(ang) * r1;\n                    for (let j = 0; j < 3; j++) {\n                        lx += (Math.random() - 0.5) * size * 0.5;\n                        ly += (Math.random() - 0.5) * size * 0.5;\n                        ctx.lineTo(lx, ly);\n                    }\n                    ctx.stroke();\n                }\n            }\n\n            ctx.restore();\n        }\n\n        // Projectiles\n        function updateProjectiles(dt) {\n            for (let i = projectiles.length - 1; i >= 0; i--) {\n                const p = projectiles[i];\n                \n                // Itachi Edo Susanoo skill 3: rotating Sharingan vortex.\n                // Fighters inside the field are pulled into a circular orbit and\n                // receive repeated damage before the field detonates in black energy.\n                if (p.type === 'itachi_edo_sharingan_vortex') {\n                    p.timer -= dt;\n                    p.rotation = (p.rotation || 0) + (p.rotationSpeed || Math.PI * 2) * dt;\n                    const enemies = getEnemies(p.owner);\n                    const pullRadius = p.pullRadius || 360;\n                    const orbitRadius = p.orbitRadius || 110;\n\n                    for (const enemy of enemies) {\n                        if (!enemy || enemy.health <= 0 || enemy.invulnerable) continue;\n                        const dx = p.x - enemy.x;\n                        const dy = p.y - (enemy.y - 60);\n                        const distance = Math.sqrt(dx * dx + dy * dy);\n                        if (distance < pullRadius && !p.captured.some(entry => entry.fighter === enemy)) {\n                            p.captured.push({\n                                fighter: enemy,\n                                angle: Math.atan2(enemy.y - 60 - p.y, enemy.x - p.x),\n                                radius: Math.max(orbitRadius, Math.min(distance, orbitRadius + 120)),\n                                damageTimer: 0\n                            });\n                            enemy.stunTimer = Math.max(enemy.stunTimer, 0.35);\n                        }\n                    }\n\n                    for (let j = p.captured.length - 1; j >= 0; j--) {\n                        const entry = p.captured[j];\n                        const trapped = entry.fighter;\n                        if (!trapped || trapped.health <= 0 || trapped.invulnerable) {\n                            p.captured.splice(j, 1);\n                            continue;\n                        }\n\n                        entry.radius = Math.max(orbitRadius, entry.radius - 240 * dt);\n                        entry.angle += (Math.PI * 2.8 + (j % 2) * 0.35) * dt;\n                        trapped.x = Math.max(\n                            ARENA_LEFT + trapped.width / 2,\n                            Math.min(ARENA_RIGHT - trapped.width / 2, p.x + Math.cos(entry.angle) * entry.radius)\n                        );\n                        trapped.y = Math.max(0, Math.min(\n                            GROUND_Y,\n                            p.y + Math.sin(entry.angle) * entry.radius + 60\n                        ));\n                        trapped.vx = 0;\n                        trapped.vy = 0;\n                        trapped.grounded = false;\n                        trapped.stunTimer = Math.max(trapped.stunTimer, 0.22);\n\n                        entry.damageTimer += dt;\n                        if (entry.damageTimer >= 0.22) {\n                            entry.damageTimer = 0;\n                            dealDamage(trapped, p.damage, p.owner);\n                        }\n                    }\n\n                    if (p.timer <= 0) {\n                        const blastRadius = 320;\n                        addEffect(p.x, p.y, 'itachi_edo_sharingan_black_explosion', {\n                            timer: 1.35,\n                            maxTimer: 1.35,\n                            radius: blastRadius\n                        });\n                        const explosionTargets = getEnemies(p.owner);\n                        for (const enemy of explosionTargets) {\n                            if (!enemy || enemy.health <= 0 || enemy.invulnerable) continue;\n                            const dx = enemy.x - p.x;\n                            const dy = (enemy.y - 60) - p.y;\n                            if (Math.sqrt(dx * dx + dy * dy) < blastRadius) {\n                                dealDamage(enemy, p.explosionDamage || 80, p.owner);\n                                const pushDir = dx >= 0 ? 1 : -1;\n                                enemy.vx = pushDir * 24;\n                                enemy.vy = -12;\n                                enemy.grounded = false;\n                            }\n                        }\n                        if (p.owner && p.owner.state === 'ability3') {\n                            p.owner.state = 'idle';\n                            p.owner.stateTimer = 0;\n                        }\n                        // Kh\u00f4ng d\u00f9ng atomic_sfx \u1edf \u0111\u00e2y v\u00ec asset n\u00e0y c\u00f3 gi\u1ecdng \"I AM ATOMIC\".\n                        // V\u1ee5 n\u1ed5 Sharingan d\u00f9ng \u00e2m thanh n\u0103ng l\u01b0\u1ee3ng kh\u00f4ng l\u1eddi thay th\u1ebf.\n                        playSound('susanoo_sfx', 0.95);\n                        screenShake = 55;\n                        projectiles.splice(i, 1);\n                    }\n                    continue;\n                }\n\n                // Doraemon Vi\u1ec7t Nam skill 3: stationary flag summon with red\n                // wind-pressure pulses and continuous nearby damage.\n                if (p.type === 'doraemon_vietnam_flag_summon') {\n                    p.timer -= dt;\n                    p.waveTimer = (p.waveTimer || 0) + dt;\n                    p.hitTick = (p.hitTick || 0) + dt;\n                    if (p.hitTick >= 0.18) {\n                        p.hitTick = 0;\n                        const enemies = getEnemies(p.owner);\n                        for (const enemy of enemies) {\n                            if (!enemy || enemy.health <= 0 || enemy.invulnerable) continue;\n                            const dist = Math.abs(p.x - enemy.x);\n                            if (dist < 340 && Math.abs(enemy.y - p.y) < 260) {\n                                dealDamage(enemy, Math.max(1, Math.floor(p.damage / 4)), p.owner);\n                                enemy.vx += (enemy.x >= p.x ? 1 : -1) * 2.5;\n                                addEffect(enemy.x, enemy.y - 55, 'doraemon_vietnam_red_wind', {\n                                    timer: 0.28,\n                                    maxTimer: 0.28\n                                });\n                            }\n                        }\n                    }\n                    if (p.timer <= 0) projectiles.splice(i, 1);\n                    continue;\n                }\n\n                // Special update logic for area effects\n                if (p.type === 'fire_column' || p.type === 'water_column' || p.type === 'earth_column' || p.type === 'black_fire_column' || p.type === 'yellow_pillar' || p.type === 'goku_giant_sphere' || p.type === 'wood_hand') {\n                    p.timer -= dt;\n                    if (p.type === 'goku_giant_sphere') {\n                        p.y += (p.vy || 0) * dt * 60;\n                        if (p.y >= GROUND_Y) {\n                            p.timer = 0; // Explode on ground\n                        }\n                    }\n                    p.hitTick = (p.hitTick || 0) + dt;\n                    if (p.hitTick >= 0.2) {\n                        p.hitTick = 0;\n                        const isOwnerOpponent = (p.owner === opponent);\n                        const enemySummons = summons.filter(s => isOwnerOpponent ? (s.owner === player || allies.includes(s.owner)) : (s.owner === opponent));\n                        const targets = isOwnerOpponent ? [player, ...allies, ...enemySummons] : [opponent, ...enemySummons];\n                        \n                        for (const target of targets) {\n                            if (target.health > 0) {\n                                const dist = Math.abs(p.x - target.x);\n                                if (p.type === 'goku_giant_sphere') {\n                                    if (dist < 400 && Math.abs(p.y - (target.y - 60)) < 400) {\n                                        dealDamage(target, Math.floor(p.damage / 8), p.owner);\n                                        // Slight pull towards center\n                                        const dx = p.x - target.x;\n                                        target.vx += dx * 0.05;\n                                    }\n                                } else if (dist < 140) {\n                                    dealDamage(target, Math.floor(p.damage / 4), p.owner);\n                                }\n                            }\n                        }\n                    }\n                    if (p.timer <= 0) projectiles.splice(i, 1);\n                    continue;\n                }\n\n                if (p.type === 'rasenshuriken_sphere') {\n                    p.timer -= dt;\n                    p.hitTick = (p.hitTick || 0) + dt;\n                    if (p.hitTick >= 0.1) {\n                        p.hitTick = 0;\n                        const isOwnerOpponent = (p.owner === opponent);\n                        const enemySummons = summons.filter(s => isOwnerOpponent ? (s.owner === player || allies.includes(s.owner)) : (s.owner === opponent));\n                        const targets = isOwnerOpponent ? [player, ...allies, ...enemySummons] : [opponent, ...enemySummons];\n                        \n                        for (const target of targets) {\n                            if (target.health > 0 && Math.abs(p.x - target.x) < 250 && Math.abs(p.y - (target.y - 60)) < 250) {\n                                dealDamage(target, Math.floor(p.damage / 5), p.owner);\n                                // Stronger suction effect\n                                const dx = p.x - target.x;\n                                const dy = (p.y - 60) - (target.y - 60);\n                                target.vx += dx * 0.15;\n                                target.vy += dy * 0.15;\n                            }\n                        }\n                    }\n                    if (p.timer <= 0) projectiles.splice(i, 1);\n                    continue;\n                }\n\n                p.x += p.vx * dt * 60;\n                if (p.type === 'naruto_clone_rush') {\n                    p.vy = (p.vy || 0) + GRAVITY;\n                    p.y += p.vy * dt * 60;\n                    if (p.y >= GROUND_Y) {\n                        p.y = GROUND_Y;\n                        p.vy = 0;\n                    }\n                } else {\n                    p.y += (p.vy || 0) * dt * 60;\n                }\n                p.timer -= dt;\n\n                // Hit detection\n                let hitSomething = false;\n                let hitTarget = null;\n                const isOwnerOpponent = (p.owner === opponent);\n                const enemySummons = summons.filter(s => isOwnerOpponent ? (s.owner === player || allies.includes(s.owner)) : (s.owner === opponent));\n                const targets = isOwnerOpponent ? [player, ...allies, ...enemySummons] : [opponent, ...enemySummons];\n\n                for (const target of targets) {\n                    if (target.health <= 0 || target.invulnerable) continue;\n                    const dist = Math.abs(p.x - target.x);\n                    const yDist = Math.abs(p.y - (target.y - 60));\n                    const isLargeProjectile = p.type === 'red_moon' || p.type === 'meteor' || p.type === 'giant_shield' || p.type === 'world_slash' || p.type === 'raigo_sphere' || p.type === 'bijuu_bomb' || p.type === 'yuta_blast' || p.type === 'naruto_clone_rush' || p.type === 'itachi_edo_susanoo_orb' || p.type === 'itachi_edo_susanoo_red_slash';\n                    const hitRadius = isLargeProjectile ? (p.type === 'giant_shield' ? 400 : (p.type === 'raigo_sphere' ? 720 : (p.type === 'world_slash' ? 250 : (p.type === 'yuta_blast' ? 80 : (p.type === 'naruto_clone_rush' ? 60 : (p.type === 'itachi_edo_susanoo_orb' ? 65 : (p.type === 'itachi_edo_susanoo_red_slash' ? 230 : 180))))))) : 40;\n                    \n                    if (dist < hitRadius && yDist < (isLargeProjectile ? (p.type === 'itachi_edo_susanoo_orb' ? 90 : (p.type === 'itachi_edo_susanoo_red_slash' ? 170 : 300)) : 60)) {\n                        dealDamage(target, p.damage, p.owner);\n                        hitSomething = (p.type !== 'world_slash'); // World slash pierces everything\n                        hitTarget = target;\n                        if (p.type === 'red_moon' || p.type === 'meteor' || p.type === 'giant_shield' || p.type === 'world_slash' || p.type === 'raigo_sphere') screenShake = 25;\n                        break;\n                    }\n                }\n\n                if (p.type === 'giant_shield' && p.y >= GROUND_Y - 40) {\n                    hitSomething = true;\n                }\n                if (p.type === 'raigo_sphere' && p.y >= GROUND_Y - 50) {\n                    hitSomething = true;\n                }\n\n                if (p.type === 'dorayaki' && hitSomething) {\n                    addEffect(p.x, p.y, 'impact');\n                }\n\n                if (hitSomething || p.timer <= 0 || p.x < 0 || p.x > 720) {\n                    if (p.type === 'naruto_clone_rush' && hitSomething) {\n                        addEffect(p.x, p.y - 60, 'impact');\n                        playSound('punch_sfx', 0.4);\n                    }\n                    if (p.type === 'yuji_rock' && hitSomething && hitTarget) {\n                        const ult = p.owner.abilities[3];\n                        ult.active = true;\n                        ult.activeTimer = 10;\n                        ult.sequence = 'teleporting';\n                        ult.targetFighter = hitTarget;\n                        hitTarget.stunTimer = 2.0;\n                        p.owner.state = 'idle';\n                    }\n                    if (p.type === 'fuga_arrow' && hitSomething) {\n                         projectiles.push({\n                            x: p.x,\n                            y: GROUND_Y,\n                            vx: 0, vy: 0,\n                            owner: p.owner,\n                            damage: p.damage * 1.5,\n                            timer: 2.0,\n                            type: 'fire_column'\n                        });\n                        playSound('fireball_sfx', 1.0);\n                        screenShake = 35;\n                    }\n                    if (p.type === 'rasenshuriken' && hitSomething) {\n                        if (p.owner && p.owner.type === 'naruto' && p.owner.skin === 'lucDao') {\n                            addEffect(p.x, p.y, 'luc_dao_vortex', { timer: 2.5, maxTimer: 2.5 });\n                            // Naruto Luc Dao ultimate explosion creates a black fire column\n                            projectiles.push({\n                                x: p.x,\n                                y: GROUND_Y,\n                                vx: 0, vy: 0,\n                                owner: p.owner,\n                                damage: 25,\n                                timer: 3.0,\n                                type: 'black_fire_column'\n                            });\n                        } else {\n                            projectiles.push({\n                                x: p.x,\n                                y: p.y,\n                                vx: 0, vy: 0,\n                                owner: p.owner,\n                                damage: p.damage,\n                                timer: 1.8,\n                                type: 'rasenshuriken_sphere',\n                                maxTimer: 1.8\n                            });\n                        }\n                        playSound('rasengan_sfx', 1.0);\n                        screenShake = 30;\n                    }\n                    if (p.type === 'lightning_dragon' && hitSomething && hitTarget) {\n                        const ab = p.owner.abilities[0];\n                        ab.active = true;\n                        ab.activeTimer = 4.0;\n                        ab.strikeX = hitTarget.x;\n                        ab.strikeY = hitTarget.y;\n                        hitTarget.stunTimer = 4.0;\n                        p.owner.stateTimer = 4.0;\n                        p.owner.vx = 0;\n                        p.owner.vy = 0;\n                        playSound('chidori_sfx', 1.0);\n                        screenShake = 25;\n                    }\n                    if (p.type === 'giant_shield' || p.type === 'goku_giant_sphere') {\n                        // Spawn fire land effects\n                        for (let j = 0; j < 20; j++) {\n                            addEffect(p.x + (Math.random() - 0.5) * 720, GROUND_Y, 'fire_land');\n                        }\n                        if (p.type === 'goku_giant_sphere') {\n                             projectiles.push({\n                                x: p.x,\n                                y: GROUND_Y,\n                                vx: 0, vy: 0,\n                                owner: p.owner,\n                                damage: 120,\n                                timer: 4.0,\n                                type: 'fire_column'\n                            });\n                        }\n                        playSound('fireball_sfx', 1.0);\n                    }\n                    if (p.type === 'raigo_sphere') {\n                        // Explosion effects\n                        for (let j = 0; j < 15; j++) {\n                            addEffect(p.x + (Math.random() - 0.5) * 400, GROUND_Y, 'lightning_strike_big');\n                        }\n                        playSound('chidori_sfx', 1.0);\n                        screenShake = 50;\n                    }\n                    if (p.type === 'bijuu_bomb' && hitSomething) {\n                        if (p.owner && p.owner.type === 'naruto' && p.owner.skin === 'lucDao') {\n                            addEffect(p.x, p.y, 'luc_dao_vortex', { timer: 2.5, maxTimer: 2.5 });\n                            // Naruto Luc Dao ultimate explosion creates a black fire column\n                            projectiles.push({\n                                x: p.x,\n                                y: GROUND_Y,\n                                vx: 0, vy: 0,\n                                owner: p.owner,\n                                damage: 25,\n                                timer: 3.0,\n                                type: 'black_fire_column'\n                            });\n                        } else {\n                            // Create rings of fire - More widespread\n                            for(let j=0; j<15; j++) {\n                                addEffect(p.x + (Math.random()-0.5)*500, GROUND_Y, 'fire_land');\n                            }\n                            addEffect(p.x, p.y, 'fire_ring_obito');\n                        }\n                        playSound('fireball_sfx', 1.0);\n                        screenShake = 50;\n                    }\n                    if (p.type === 'zoro_phoenix' && hitSomething) {\n                        addEffect(p.x, p.y, 'impact');\n                        playSound('sword_slash_sfx', 0.6);\n                    }\n                    if (p.type === 'itachi_edo_susanoo_orb' && hitSomething) {\n                        // The orb bursts on contact, dealing a second short-range hit\n                        // and throwing nearby fighters away from the impact point.\n                        addEffect(p.x, p.y, 'itachi_edo_orb_explosion', {\n                            timer: 1.1,\n                            maxTimer: 1.1,\n                            radius: 230\n                        });\n                        const explosionTargets = p.owner === player\n                            ? [opponent, ...allies, ...summons.filter(s => s.owner === opponent)]\n                            : [player, ...allies, ...summons.filter(s => s.owner === player || allies.includes(s.owner))];\n                        for (const explosionTarget of explosionTargets) {\n                            if (explosionTarget && explosionTarget.health > 0 && !explosionTarget.invulnerable) {\n                                const dx = explosionTarget.x - p.x;\n                                const dy = (explosionTarget.y - 60) - p.y;\n                                if (Math.sqrt(dx * dx + dy * dy) < 230) {\n                                    dealDamage(explosionTarget, p.explosionDamage || p.damage, p.owner);\n                                    const pushDir = dx >= 0 ? 1 : -1;\n                                    explosionTarget.vx = pushDir * 18;\n                                    explosionTarget.vy = -8;\n                                    explosionTarget.grounded = false;\n                                }\n                            }\n                        }\n                        playSound('fireball_sfx', 0.95);\n                        screenShake = 35;\n                    }\n                    if (p.type === 'itachi_edo_susanoo_red_slash' && hitSomething) {\n                        // The giant red Susanoo crescent detonates on contact.\n                        addEffect(p.x, p.y, 'itachi_edo_susanoo_red_explosion', { timer: 1.15, maxTimer: 1.15, radius: 260 });\n                        const explosionTargets = getEnemies(p.owner);\n                        for (const explosionTarget of explosionTargets) {\n                            if (explosionTarget && explosionTarget.health > 0 && !explosionTarget.invulnerable) {\n                                const dx = explosionTarget.x - p.x;\n                                const dy = (explosionTarget.y - 60) - p.y;\n                                if (Math.sqrt(dx * dx + dy * dy) < 260) {\n                                    dealDamage(explosionTarget, p.explosionDamage || 95, p.owner);\n                                    explosionTarget.vx = (dx >= 0 ? 1 : -1) * 25;\n                                    explosionTarget.vy = -12;\n                                    explosionTarget.grounded = false;\n                                }\n                            }\n                        }\n                        playSound('fireball_sfx', 1.0);\n                        screenShake = 42;\n                    }\n                    if (p.type === 'itachi_edo_susanoo_orb' && hitSomething) {\n                        addEffect(p.x, p.y, 'rimuru_explosion', { timer: 1.0, maxTimer: 1.0 });\n                        // AOE damage\n                        const targets = (p.owner === player) ? [opponent, ...summons.filter(s => s.owner === opponent)] : [player, ...allies, ...summons.filter(s => s.owner === player || allies.includes(s.owner))];\n                        for (const target of targets) {\n                            if (target && target.health > 0) {\n                                const d = Math.sqrt(Math.pow(p.x - target.x, 2) + Math.pow(p.y - (target.y - 60), 2));\n                                if (d < 300) {\n                                    dealDamage(target, p.damage, p.owner);\n                                }\n                            }\n                        }\n                        playSound('fireball_sfx', 1.0);\n                        screenShake = 40;\n                    }\n                    projectiles.splice(i, 1);\n                }\n            }\n        }\n        function drawProjectiles() {\n            for (const p of projectiles) {\n                if (p.type === 'doraemon_vietnam_flag_summon') {\n                    ctx.save();\n                    const time = Date.now() / 1000;\n                    const remaining = Math.max(0, Math.min(1, p.timer / (p.maxTimer || 5)));\n                    const pulse = 1 + Math.sin(time * 7) * 0.04;\n                    ctx.translate(p.x, p.y);\n\n                    // Red atmospheric aura and expanding pressure rings.\n                    ctx.globalAlpha = 0.18 + Math.sin(time * 8) * 0.04;\n                    ctx.shadowBlur = 35;\n                    ctx.shadowColor = '#ff1e2d';\n                    const aura = ctx.createRadialGradient(0, -170, 10, 0, -170, 280);\n                    aura.addColorStop(0, 'rgba(255, 235, 190, 0.9)');\n                    aura.addColorStop(0.35, 'rgba(235, 25, 35, 0.55)');\n                    aura.addColorStop(1, 'transparent');\n                    ctx.fillStyle = aura;\n                    ctx.beginPath();\n                    ctx.arc(0, -170, 280, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    ctx.globalAlpha = 0.72 * remaining;\n                    ctx.strokeStyle = '#ff3545';\n                    ctx.lineWidth = 5;\n                    for (let k = 0; k < 3; k++) {\n                        const ring = ((time * 150 + k * 105) % 360);\n                        ctx.beginPath();\n                        ctx.ellipse(0, -25, ring, ring * 0.22, 0, 0, Math.PI * 2);\n                        ctx.stroke();\n                    }\n\n                    // Silver flagpole planted on the arena floor.\n                    ctx.globalAlpha = 0.98 * remaining;\n                    ctx.shadowBlur = 12;\n                    ctx.shadowColor = '#fff';\n                    const poleGrad = ctx.createLinearGradient(-10, 0, 10, 0);\n                    poleGrad.addColorStop(0, '#737b89');\n                    poleGrad.addColorStop(0.45, '#fff');\n                    poleGrad.addColorStop(1, '#8b93a0');\n                    ctx.fillStyle = poleGrad;\n                    ctx.fillRect(-7, -365, 14, 365);\n                    ctx.fillStyle = '#e8edf5';\n                    ctx.beginPath();\n                    ctx.arc(0, -375, 14, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.fillStyle = '#8c2b2b';\n                    ctx.beginPath();\n                    ctx.ellipse(0, 0, 48, 12, 0, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Waving red Vietnamese flag with a centered yellow star.\n                    ctx.save();\n                    ctx.translate(5, -350);\n                    ctx.scale(pulse, pulse);\n                    const flagW = 245;\n                    const flagH = 132;\n                    const wave = Math.sin(time * 5) * 9;\n                    const flagGrad = ctx.createLinearGradient(0, -flagH / 2, flagW, flagH / 2);\n                    flagGrad.addColorStop(0, '#b80d1c');\n                    flagGrad.addColorStop(0.5, '#ed1c2b');\n                    flagGrad.addColorStop(1, '#a90818');\n                    ctx.fillStyle = flagGrad;\n                    ctx.shadowBlur = 25;\n                    ctx.shadowColor = '#ff2638';\n                    ctx.beginPath();\n                    ctx.moveTo(0, -flagH / 2);\n                    for (let x = 0; x <= flagW; x += 14) {\n                        ctx.lineTo(x, -flagH / 2 + Math.sin(time * 5 + x * 0.045) * 7);\n                    }\n                    for (let x = flagW; x >= 0; x -= 14) {\n                        ctx.lineTo(x, flagH / 2 + Math.sin(time * 5 + x * 0.045 + 1.2) * 7);\n                    }\n                    ctx.closePath();\n                    ctx.fill();\n\n                    ctx.fillStyle = '#ffe600';\n                    ctx.shadowBlur = 18;\n                    ctx.shadowColor = '#ffd000';\n                    drawFivePointStar(ctx, flagW * 0.48, wave, 40, 17);\n                    ctx.restore();\n\n                    // Red wind streams replacing the original white airflow.\n                    ctx.globalAlpha = 0.8 * remaining;\n                    ctx.strokeStyle = '#ff2638';\n                    ctx.shadowBlur = 16;\n                    ctx.shadowColor = '#ff001c';\n                    ctx.lineCap = 'round';\n                    for (let k = 0; k < 10; k++) {\n                        const side = k % 2 === 0 ? -1 : 1;\n                        const y = -285 + (k % 5) * 54;\n                        const travel = ((time * (180 + k * 12) + k * 60) % 330);\n                        const startX = side * (35 + travel);\n                        const endX = side * (startX + 75 + (k % 3) * 25);\n                        ctx.lineWidth = 4 + (k % 3);\n                        ctx.beginPath();\n                        ctx.moveTo(startX, y + Math.sin(time * 8 + k) * 8);\n                        ctx.quadraticCurveTo(side * (startX + 40), y - 18, endX, y + 8);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'lightning_dragon' || p.type === 'lightning_bird' || p.type === 'lightning_beast') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const dir = p.vx > 0 ? 1 : -1;\n                    const time = Date.now() / 1000;\n                    ctx.scale(dir, 1);\n                    ctx.shadowBlur = 20;\n                    ctx.shadowColor = '#00BFFF';\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 3;\n                    \n                    if (p.type === 'lightning_dragon') {\n                        ctx.beginPath();\n                        ctx.moveTo(0, 0);\n                        for(let k=0; k<6; k++) {\n                            ctx.lineTo(k * -25, Math.sin(time * 15 + k) * 20);\n                        }\n                        ctx.stroke();\n                        ctx.fillStyle = '#00BFFF';\n                        ctx.beginPath();\n                        ctx.moveTo(0, -15);\n                        ctx.lineTo(35, 0);\n                        ctx.lineTo(0, 15);\n                        ctx.closePath();\n                        ctx.fill();\n                        ctx.stroke();\n                    } else if (p.type === 'lightning_bird') {\n                        // Bird shape\n                        ctx.beginPath();\n                        ctx.moveTo(0, 0);\n                        ctx.lineTo(-20, -15); ctx.lineTo(-10, 0); ctx.lineTo(-20, 15);\n                        ctx.closePath();\n                        ctx.fillStyle = '#00BFFF';\n                        ctx.fill();\n                        ctx.stroke();\n                        // Wings\n                        ctx.beginPath();\n                        const wingSway = Math.sin(time * 20) * 15;\n                        ctx.moveTo(-10, 0); ctx.lineTo(-20, -20 + wingSway);\n                        ctx.moveTo(-10, 0); ctx.lineTo(-20, 20 - wingSway);\n                        ctx.stroke();\n                    } else {\n                        // Beast shape\n                        ctx.beginPath();\n                        ctx.moveTo(0, 0);\n                        ctx.lineTo(-30, 0);\n                        ctx.stroke();\n                        ctx.beginPath();\n                        ctx.arc(-15, 0, 15, 0, Math.PI * 2);\n                        ctx.fillStyle = '#00BFFF';\n                        ctx.fill();\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'dorayaki') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    ctx.rotate(Date.now() / 100);\n                    ctx.fillStyle = '#8B4513';\n                    ctx.strokeStyle = '#DAA520';\n                    ctx.lineWidth = 2;\n                    ctx.beginPath();\n                    ctx.ellipse(0, 0, 20, 12, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.stroke();\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'raigo_sphere' || p.type === 'goku_giant_sphere') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const isGoku = p.type === 'goku_giant_sphere';\n                    const size = (isGoku ? 500 : 600) + Math.sin(time * 10) * 50;\n                    \n                    // Giant Sphere\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size);\n                    if (isGoku) {\n                        grad.addColorStop(0, '#fff');\n                        grad.addColorStop(0.2, '#ADD8E6');\n                        grad.addColorStop(0.6, '#4A90E2');\n                        grad.addColorStop(1, 'transparent');\n                    } else {\n                        grad.addColorStop(0, '#fff');\n                        grad.addColorStop(0.2, '#00BFFF');\n                        grad.addColorStop(0.6, '#000080');\n                        grad.addColorStop(1, 'transparent');\n                    }\n                    \n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 100;\n                    ctx.shadowColor = isGoku ? '#4A90E2' : '#00BFFF';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Arcs of electricity / energy on the sphere\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = isGoku ? 2 : 4;\n                    for (let i = 0; i < 4; i++) {\n                        ctx.beginPath();\n                        const ang = time * 2 + i * Math.PI / 2;\n                        ctx.arc(0, 0, size * 0.8, ang, ang + 1);\n                        ctx.stroke();\n                    }\n                    \n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'world_slash') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    \n                    // Giant High-Contrast Slash\n                    const dir = p.vx > 0 ? 1 : -1;\n                    const len = 600;\n                    const height = 400;\n\n                    // Black background of the slash\n                    ctx.fillStyle = '#000';\n                    ctx.beginPath();\n                    ctx.moveTo(0, -height/2);\n                    ctx.lineTo(dir * len, height/2);\n                    ctx.lineTo(dir * len + (dir * 20), height/2 - 20);\n                    ctx.lineTo(20, -height/2 + 20);\n                    ctx.closePath();\n                    ctx.fill();\n\n                    // White sharp core\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 15;\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = '#fff';\n                    ctx.beginPath();\n                    ctx.moveTo(0, -height/2);\n                    ctx.lineTo(dir * len, height/2);\n                    ctx.stroke();\n\n                    // Glitchy spatial cracks\n                    ctx.globalAlpha = 0.5;\n                    ctx.lineWidth = 2;\n                    for(let k=0; k<5; k++) {\n                        ctx.beginPath();\n                        const off = (k-2) * 30;\n                        ctx.moveTo(off, -height/2 + off);\n                        ctx.lineTo(dir * len + off, height/2 + off);\n                        ctx.stroke();\n                    }\n                    \n                    ctx.restore();\n                    continue;\n                }\n\n                if (p.type === 'fire_column' || p.type === 'water_column' || p.type === 'earth_column' || p.type === 'black_fire_column' || p.type === 'wood_hand' || p.type === 'yellow_pillar') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const alpha = Math.min(1, p.timer / 0.5); // Fade in/out\n                    ctx.globalAlpha = alpha;\n                    \n                    // Main pillar height and width\n                    const w = (p.type === 'earth_column' || p.type === 'wood_hand' || p.type === 'yellow_pillar' ? 320 : 240) * (0.8 + Math.sin(time * 25) * 0.2);\n                    \n                    const grad = ctx.createLinearGradient(-w/2, 0, w/2, 0);\n                    grad.addColorStop(0, 'transparent');\n                    if (p.type === 'water_column') {\n                        grad.addColorStop(0.3, 'rgba(30, 144, 255, 0.8)');\n                        grad.addColorStop(0.5, 'rgba(135, 206, 250, 0.9)');\n                        grad.addColorStop(0.7, 'rgba(30, 144, 255, 0.8)');\n                    } else if (p.type === 'earth_column' || p.type === 'wood_hand') {\n                        grad.addColorStop(0.3, p.type === 'wood_hand' ? 'rgba(34, 139, 34, 0.9)' : 'rgba(139, 69, 19, 0.9)');\n                        grad.addColorStop(0.5, p.type === 'wood_hand' ? 'rgba(0, 100, 0, 1.0)' : 'rgba(210, 180, 140, 1.0)');\n                        grad.addColorStop(0.7, p.type === 'wood_hand' ? 'rgba(34, 139, 34, 0.9)' : 'rgba(139, 69, 19, 0.9)');\n                    } else if (p.type === 'black_fire_column') {\n                        grad.addColorStop(0.3, 'rgba(20, 0, 30, 0.95)');\n                        grad.addColorStop(0.5, 'rgba(0, 0, 0, 1.0)');\n                        grad.addColorStop(0.7, 'rgba(40, 0, 60, 0.95)');\n                    } else if (p.type === 'yellow_pillar') {\n                        grad.addColorStop(0.3, 'rgba(255, 215, 0, 0.8)');\n                        grad.addColorStop(0.5, 'rgba(255, 255, 255, 0.95)');\n                        grad.addColorStop(0.7, 'rgba(255, 215, 0, 0.8)');\n                    } else {\n                        grad.addColorStop(0.3, 'rgba(255, 69, 0, 0.8)');\n                        grad.addColorStop(0.5, 'rgba(255, 215, 0, 0.9)');\n                        grad.addColorStop(0.7, 'rgba(255, 69, 0, 0.8)');\n                    }\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    // Giant pillar rising to top of screen\n                    ctx.fillRect(-w/2, -1280, w, 1280);\n                    \n                    // Heat haze/inner glow\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = p.type === 'water_column' ? '#1E90FF' : (p.type === 'earth_column' ? '#8B4513' : (p.type === 'black_fire_column' ? '#4B0082' : (p.type === 'yellow_pillar' ? '#FFD700' : '#FF4500')));\n                    ctx.fillStyle = p.type === 'water_column' ? '#E0FFFF' : (p.type === 'earth_column' ? '#FFF8DC' : (p.type === 'black_fire_column' ? '#9370DB' : (p.type === 'yellow_pillar' ? '#fff' : '#FFFACD')));\n                    ctx.globalAlpha = alpha * 0.4;\n                    ctx.fillRect(-w/6, -1280, w/3, 1280);\n                    \n                    // Rising particles\n                    ctx.shadowBlur = 0;\n                    ctx.globalAlpha = alpha;\n                    for (let j = 0; j < 15; j++) {\n                        const seed = j * 1.5;\n                        const px = (Math.sin(time * 4 + seed) * w/2.5);\n                        const py = -((time * 400 + seed * 100) % 1280);\n                        ctx.fillStyle = p.type === 'water_column' ? '#fff' : (p.type === 'earth_column' ? '#654321' : (p.type === 'black_fire_column' ? '#000' : (p.type === 'yellow_pillar' ? '#FFD700' : '#FFD700')));\n                        ctx.beginPath();\n                        ctx.arc(px, py, 6 + Math.random() * (p.type === 'earth_column' ? 12 : 8), 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'rasenshuriken_sphere') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const alpha = Math.min(1, p.timer / 0.3);\n                    const progress = 1 - (p.timer / p.maxTimer);\n                    ctx.globalAlpha = alpha;\n\n                    // Expanding blue vortex sphere\n                    const size = 100 + progress * 150 + Math.sin(time * 30) * 10;\n                    \n                    // Core gradient\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.2, 'rgba(0, 191, 255, 0.9)');\n                    grad.addColorStop(0.6, 'rgba(30, 144, 255, 0.4)');\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#00BFFF';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Swirling wind lines (White)\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 2 + progress * 4;\n                    ctx.globalAlpha = alpha * 0.6;\n                    for (let j = 0; j < 12; j++) {\n                        ctx.save();\n                        ctx.rotate(time * 20 + j * Math.PI / 6);\n                        ctx.beginPath();\n                        ctx.arc(0, 0, size * (0.3 + Math.random() * 0.6), 0, Math.PI / 3);\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n\n                    // Inner energy particles\n                    ctx.globalAlpha = alpha;\n                    ctx.fillStyle = '#fff';\n                    for (let j = 0; j < 10; j++) {\n                        const ang = Math.random() * Math.PI * 2;\n                        const r = Math.random() * size;\n                        ctx.beginPath();\n                        ctx.arc(Math.cos(ang) * r, Math.sin(ang) * r, 2 + Math.random() * 3, 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'giant_shield') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    // Majestic divine shield beam\n                    const time = Date.now() / 200;\n                    ctx.globalAlpha = 0.8 + Math.sin(time) * 0.1;\n                    ctx.shadowBlur = 60;\n                    ctx.shadowColor = '#FFD700';\n                    \n                    const w = 720;\n                    const h = 110;\n                    \n                    // Golden outer frame\n                    ctx.fillStyle = '#DAA520';\n                    ctx.beginPath();\n                    ctx.roundRect(-w/2 - 12, -h/2 - 12, w + 24, h + 24, 25);\n                    ctx.fill();\n\n                    // Main shield body with celestial gradient\n                    const grad = ctx.createLinearGradient(0, -h/2, 0, h/2);\n                    grad.addColorStop(0, '#FFD700'); // Gold\n                    grad.addColorStop(0.3, '#FFFACD'); // Light Yellow\n                    grad.addColorStop(0.5, '#4A90E2'); // Blue Core\n                    grad.addColorStop(0.7, '#1a1a2e'); // Deep Space\n                    grad.addColorStop(1, '#000');\n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    ctx.roundRect(-w/2, -h/2, w, h, 20);\n                    ctx.fill();\n                    \n                    // Ornate glowing symbols / runes\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 4;\n                    ctx.globalAlpha = 0.5;\n                    for (let i = 0; i < 8; i++) {\n                        const rx = -w/2 + (i + 0.5) * (w / 8);\n                        ctx.beginPath();\n                        ctx.arc(rx, 0, 35, 0, Math.PI * 2);\n                        ctx.stroke();\n                        // Inner cross symbols\n                        ctx.beginPath();\n                        ctx.moveTo(rx - 20, 0); ctx.lineTo(rx + 20, 0);\n                        ctx.moveTo(rx, -20); ctx.lineTo(rx, 20);\n                        ctx.stroke();\n                    }\n                    \n                    // Divine central light streak\n                    ctx.globalAlpha = 0.7;\n                    ctx.lineWidth = 8;\n                    ctx.beginPath();\n                    ctx.moveTo(-w/2 + 40, 0);\n                    ctx.lineTo(w/2 - 40, 0);\n                    ctx.stroke();\n\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'red_moon' || p.type === 'meteor') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const isMeteor = p.type === 'meteor';\n                    \n                    const glowR = isMeteor ? 180 : 100;\n                    const glow = ctx.createRadialGradient(0, 0, 20, 0, 0, glowR);\n                    glow.addColorStop(0, isMeteor ? '#FFA500' : '#FF0000');\n                    glow.addColorStop(0.5, isMeteor ? '#FF4500' : '#8B0000');\n                    glow.addColorStop(1, 'rgba(139, 0, 0, 0)');\n                    ctx.fillStyle = glow;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, glowR, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Rock body\n                    ctx.fillStyle = isMeteor ? '#4a3728' : '#4D0000';\n                    ctx.beginPath();\n                    const rockR = isMeteor ? 140 : 70;\n                    ctx.arc(0, 0, rockR, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Textures/Craters\n                    ctx.fillStyle = 'rgba(0,0,0,0.3)';\n                    const numCraters = isMeteor ? 8 : 3;\n                    for(let i=0; i<numCraters; i++) {\n                        const cx = Math.sin(i*2) * (rockR * 0.5);\n                        const cy = Math.cos(i*2) * (rockR * 0.5);\n                        const cr = 10 + Math.random() * 20;\n                        ctx.beginPath(); ctx.arc(cx, cy, cr, 0, Math.PI * 2); ctx.fill();\n                    }\n\n                    // Flames for meteor\n                    if (isMeteor) {\n                        ctx.globalAlpha = 0.6;\n                        ctx.fillStyle = '#FF8C00';\n                        for (let i = 0; i < 5; i++) {\n                            ctx.beginPath();\n                            const fx = (Math.random()-0.5) * 150;\n                            const fy = -100 - Math.random() * 100;\n                            ctx.arc(fx, fy, 30 + Math.random() * 20, 0, Math.PI * 2);\n                            ctx.fill();\n                        }\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'obito_fire_vortex' || p.type === 'wood_dragon') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    \n                    if (p.type === 'wood_dragon') {\n                        const sprite = imageCache['wood_dragon_projectile'];\n                        if (sprite) {\n                             const dir = p.vx > 0 ? 1 : -1;\n                             ctx.scale(dir, 1);\n                             const w = 180;\n                             const h = 80;\n                             ctx.drawImage(sprite, -w/2, -h/2, w, h);\n                        } else {\n                            ctx.fillStyle = '#8B4513';\n                            ctx.fillRect(-30, -10, 60, 20);\n                        }\n                    } else {\n                        ctx.rotate(time * 15);\n                        const size = 70 + Math.sin(time * 20) * 10;\n                        const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size);\n                        grad.addColorStop(0, '#fff');\n                        grad.addColorStop(0.3, '#FFD700');\n                        grad.addColorStop(0.7, '#FF4500');\n                        grad.addColorStop(1, 'transparent');\n                        ctx.fillStyle = grad;\n                        ctx.beginPath();\n                        ctx.arc(0, 0, size, 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'bijuu_bomb') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const size = 130 + Math.sin(time * 25) * 15;\n                    \n                    // Black/Purple Bijuu Bomb\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size);\n                    grad.addColorStop(0, '#000');\n                    grad.addColorStop(0.4, '#4B0082');\n                    grad.addColorStop(0.8, '#FF0000');\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#f00';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Small spinning sparks\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 2;\n                    for(let i=0; i<4; i++) {\n                        ctx.beginPath();\n                        const ang = time * 25 + i * Math.PI / 2;\n                        ctx.arc(0, 0, size * 0.7, ang, ang + 0.5);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'zoro_phoenix') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const dir = p.vx > 0 ? 1 : -1;\n                    ctx.scale(dir, 1);\n                    const time = Date.now() / 1000;\n                    \n                    // Green bird/crescent slash or Black/Purple Haki Slash\n                    const isWano = p.owner && p.owner.skin === 'wano';\n                    ctx.strokeStyle = isWano ? '#000' : '#32CD32';\n                    ctx.lineWidth = 8;\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = isWano ? '#4b0082' : '#006400';\n                    \n                    ctx.beginPath();\n                    ctx.moveTo(-40, -60);\n                    ctx.quadraticCurveTo(40, 0, -40, 60);\n                    ctx.stroke();\n                    \n                    // Inner white core\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 3;\n                    ctx.beginPath();\n                    ctx.moveTo(-35, -55);\n                    ctx.quadraticCurveTo(35, 0, -35, 55);\n                    ctx.stroke();\n\n                    // Trailing energy\n                    ctx.globalAlpha = 0.5;\n                    for (let k = 0; k < 3; k++) {\n                        ctx.beginPath();\n                        const offX = -20 - k * 30;\n                        ctx.moveTo(offX, -40);\n                        ctx.lineTo(offX + 40, 0);\n                        ctx.lineTo(offX, 40);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'itachi_edo_sharingan_vortex') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const remaining = Math.max(0, Math.min(1, p.timer / (p.maxTimer || 5)));\n                    const fade = Math.min(1, remaining * 4);\n                    const size = 165 + Math.sin(time * 10) * 8;\n                    const reference = imageCache['itachi_edo_sharingan_reference'];\n\n                    // Dark suction aura behind the Sharingan disk.\n                    ctx.globalAlpha = 0.28 * fade;\n                    const aura = ctx.createRadialGradient(0, 0, 15, 0, 0, size * 1.8);\n                    aura.addColorStop(0, '#000');\n                    aura.addColorStop(0.45, '#3b0013');\n                    aura.addColorStop(0.8, 'rgba(150, 0, 30, 0.35)');\n                    aura.addColorStop(1, 'transparent');\n                    ctx.fillStyle = aura;\n                    ctx.shadowBlur = 55;\n                    ctx.shadowColor = '#e00028';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size * 1.8, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Rotate the supplied Sharingan reference inside a circular clip\n                    // so it reads as a red-and-black eye rather than a square image.\n                    ctx.save();\n                    ctx.rotate(p.rotation || 0);\n                    ctx.globalAlpha = 0.98 * fade;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.clip();\n                    if (reference) {\n                        ctx.drawImage(reference, -size, -size, size * 2, size * 2);\n                    } else {\n                        ctx.fillStyle = '#8f1628';\n                        ctx.fillRect(-size, -size, size * 2, size * 2);\n                        ctx.fillStyle = '#050505';\n                        ctx.beginPath();\n                        ctx.arc(0, 0, size * 0.28, 0, Math.PI * 2);\n                        ctx.fill();\n                        for (let k = 0; k < 3; k++) {\n                            ctx.save();\n                            ctx.rotate(k * Math.PI * 2 / 3);\n                            ctx.beginPath();\n                            ctx.moveTo(0, -size * 0.12);\n                            ctx.quadraticCurveTo(size * 0.48, -size * 0.55, size * 0.7, -size * 0.12);\n                            ctx.quadraticCurveTo(size * 0.42, -size * 0.28, 0, size * 0.12);\n                            ctx.fill();\n                            ctx.restore();\n                        }\n                    }\n                    ctx.restore();\n\n                    // Outer rim and fast orbit trails emphasize the 5-second pull.\n                    ctx.globalAlpha = 0.9 * fade;\n                    ctx.strokeStyle = '#ff334f';\n                    ctx.lineWidth = 5;\n                    ctx.shadowBlur = 22;\n                    ctx.shadowColor = '#ff0033';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size + 4, 0, Math.PI * 2);\n                    ctx.stroke();\n                    for (let k = 0; k < 4; k++) {\n                        ctx.save();\n                        ctx.rotate(-(p.rotation || 0) * (1.1 + k * 0.15) + k * Math.PI / 2);\n                        ctx.globalAlpha = 0.65 * fade;\n                        ctx.strokeStyle = k % 2 ? '#160006' : '#ff203d';\n                        ctx.lineWidth = 8 - k;\n                        ctx.beginPath();\n                        ctx.arc(0, 0, size + 22 + k * 17, -0.6, 0.9);\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n                    ctx.globalAlpha = 0.8 * fade;\n                    ctx.fillStyle = '#ff5668';\n                    for (let k = 0; k < 10; k++) {\n                        const angle = (p.rotation || 0) * 1.8 + k * Math.PI / 5;\n                        const r = size + 35 + Math.sin(time * 8 + k) * 12;\n                        ctx.beginPath();\n                        ctx.arc(Math.cos(angle) * r, Math.sin(angle) * r, 3 + (k % 3), 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n\n                if (p.type === 'itachi_edo_susanoo_red_slash') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const dir = p.vx >= 0 ? 1 : -1;\n                    const pulse = 1 + Math.sin(time * 18) * 0.06;\n                    ctx.scale(dir, 1);\n                    ctx.rotate(-0.18);\n                    ctx.globalAlpha = Math.min(1, p.timer / 0.18);\n                    ctx.shadowBlur = 45;\n                    ctx.shadowColor = '#ff1800';\n\n                    // Broad red-orange Susanoo crescent inspired by the supplied visual.\n                    const slashW = 360 * pulse;\n                    const slashR = slashW * 0.58;\n                    const slashGrad = ctx.createLinearGradient(-slashW * 0.55, 0, slashW * 0.55, 0);\n                    slashGrad.addColorStop(0, 'rgba(255, 30, 0, 0)');\n                    slashGrad.addColorStop(0.25, '#ff2b00');\n                    slashGrad.addColorStop(0.52, '#ffb000');\n                    slashGrad.addColorStop(0.75, '#ff1b00');\n                    slashGrad.addColorStop(1, 'rgba(120, 0, 0, 0)');\n                    ctx.strokeStyle = slashGrad;\n                    ctx.lineWidth = 48;\n                    ctx.beginPath();\n                    ctx.arc(0, 20, slashR, -Math.PI * 0.78, Math.PI * 0.78);\n                    ctx.stroke();\n                    ctx.strokeStyle = '#ff3b12';\n                    ctx.lineWidth = 18;\n                    ctx.beginPath();\n                    ctx.arc(0, 20, slashR, -Math.PI * 0.78, Math.PI * 0.78);\n                    ctx.stroke();\n                    ctx.strokeStyle = '#fff3a0';\n                    ctx.lineWidth = 5;\n                    ctx.beginPath();\n                    ctx.arc(0, 20, slashR, -Math.PI * 0.72, Math.PI * 0.72);\n                    ctx.stroke();\n\n                    // Jagged chakra flames around the blade.\n                    ctx.fillStyle = '#ff2400';\n                    for (let k = 0; k < 9; k++) {\n                        const a = -Math.PI * 0.72 + k * Math.PI * 1.44 / 8;\n                        const sx = Math.cos(a) * slashR;\n                        const sy = 20 + Math.sin(a) * slashR * 0.72;\n                        ctx.beginPath();\n                        ctx.moveTo(sx, sy);\n                        ctx.lineTo(sx + Math.cos(a - 0.18) * 42, sy + Math.sin(a - 0.18) * 42);\n                        ctx.lineTo(sx + Math.cos(a + 0.12) * 18, sy + Math.sin(a + 0.12) * 58);\n                        ctx.closePath();\n                        ctx.fill();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'itachi_edo_susanoo_orb') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const dir = p.vx >= 0 ? 1 : -1;\n                    ctx.scale(dir, 1);\n                    const pulse = 1 + Math.sin(time * 18) * 0.08;\n\n                    // Compact Susanoo-like projectile inspired by the supplied\n                    // reference: orange body, purple energy crest, and a white-hot\n                    // spear rising from the core.\n                    ctx.globalAlpha = 0.28;\n                    ctx.fillStyle = '#ff6a00';\n                    ctx.shadowBlur = 45;\n                    ctx.shadowColor = '#ff4d00';\n                    ctx.beginPath();\n                    ctx.ellipse(-8, 8, 70 * pulse, 48 * pulse, -0.12, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    ctx.globalAlpha = 0.95;\n                    ctx.fillStyle = '#db5a12';\n                    ctx.beginPath();\n                    ctx.moveTo(-62, 20);\n                    ctx.quadraticCurveTo(-56, -32, -12, -45);\n                    ctx.quadraticCurveTo(28, -42, 50, 12);\n                    ctx.quadraticCurveTo(12, 42, -40, 34);\n                    ctx.closePath();\n                    ctx.fill();\n\n                    ctx.fillStyle = '#6b1649';\n                    ctx.shadowBlur = 20;\n                    ctx.shadowColor = '#b51d73';\n                    ctx.beginPath();\n                    ctx.arc(35, 0, 35 * pulse, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.strokeStyle = '#d84a94';\n                    ctx.lineWidth = 3;\n                    ctx.beginPath();\n                    ctx.arc(35, 0, 23 * pulse, 0, Math.PI * 1.7);\n                    ctx.stroke();\n\n                    // White/gold energy spear and bright impact core.\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = '#fff8bd';\n                    ctx.fillStyle = '#fffde0';\n                    ctx.beginPath();\n                    ctx.moveTo(-5, -15);\n                    ctx.lineTo(26, -92);\n                    ctx.lineTo(16, -18);\n                    ctx.lineTo(6, 10);\n                    ctx.closePath();\n                    ctx.fill();\n                    ctx.fillStyle = '#fff';\n                    ctx.beginPath();\n                    ctx.arc(-2, -5, 13 * pulse, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    ctx.strokeStyle = '#ffb52e';\n                    ctx.lineWidth = 4;\n                    ctx.globalAlpha = 0.8;\n                    for (let k = 0; k < 4; k++) {\n                        const a = time * 9 + k * Math.PI / 2;\n                        ctx.beginPath();\n                        ctx.moveTo(Math.cos(a) * 35, 8 + Math.sin(a) * 25);\n                        ctx.lineTo(Math.cos(a) * 85, 8 + Math.sin(a) * 48);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'rimuru_explosive_sphere') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    const size = 100 + Math.sin(time * 15) * 5;\n                    \n                    // 1. Red Aura (Outer Glow)\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#f00';\n                    ctx.fillStyle = 'rgba(255, 0, 0, 0.3)';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size * 1.2, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // 2. Black Core Sphere\n                    ctx.shadowBlur = 0;\n                    ctx.fillStyle = '#000';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // 3. Swirling Blue Bands\n                    ctx.strokeStyle = '#00BFFF';\n                    ctx.lineWidth = 6;\n                    ctx.globalAlpha = 0.8;\n                    for (let j = 0; j < 3; j++) {\n                        ctx.save();\n                        ctx.rotate(time * 8 + j * Math.PI / 3);\n                        ctx.beginPath();\n                        ctx.ellipse(0, 0, size, size * 0.4, 0, 0, Math.PI * 1.5);\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n                    \n                    // 4. Orange Lightning Crack\n                    ctx.strokeStyle = '#FF8C00';\n                    ctx.lineWidth = 4;\n                    ctx.shadowBlur = 15;\n                    ctx.shadowColor = '#FF8C00';\n                    ctx.beginPath();\n                    let curX = -20;\n                    let curY = -size;\n                    ctx.moveTo(curX, curY);\n                    while (curY < size) {\n                        curY += 20;\n                        curX += (Math.random() - 0.5) * 40;\n                        ctx.lineTo(curX, curY);\n                    }\n                    ctx.stroke();\n                    \n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'sticky_shuriken' || p.type === 'rimuru_clone') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    if (p.type === 'sticky_shuriken') {\n                        ctx.rotate(time * 20);\n                        ctx.fillStyle = '#00BFFF';\n                        ctx.beginPath();\n                        ctx.arc(0, 0, 15, 0, Math.PI * 2);\n                        ctx.fill();\n                        ctx.globalAlpha = 0.5;\n                        ctx.strokeStyle = '#fff';\n                        ctx.lineWidth = 2;\n                        for(let k=0; k<4; k++) {\n                            ctx.beginPath();\n                            ctx.moveTo(0, 0);\n                            const a = k * Math.PI / 2;\n                            ctx.lineTo(Math.cos(a) * 20, Math.sin(a) * 20);\n                            ctx.stroke();\n                        }\n                    } else {\n                        ctx.globalAlpha = 0.7;\n                        const sprite = imageCache['rimuru_idle'];\n                        if (sprite) {\n                            const w = 60;\n                            const h = 90;\n                            ctx.drawImage(sprite, -w/2, -h/2, w, h);\n                        } else {\n                            ctx.fillStyle = '#00BFFF';\n                            ctx.fillRect(-20, -30, 40, 60);\n                        }\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'yuta_blast') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const time = Date.now() / 1000;\n                    ctx.rotate(time * 5);\n                    const size = 50 + Math.sin(time * 20) * 10;\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.3, '#00BFFF');\n                    grad.addColorStop(0.7, '#0000FF');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = '#00BFFF';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                    continue;\n                }\n                if (p.type === 'naruto_clone_rush') {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    const dir = p.vx > 0 ? 1 : -1;\n                    if (dir < 0) ctx.scale(-1, 1);\n                    \n                    const time = Date.now() / 1000;\n                    const frame = Math.floor(time * 12) % 4; // Rapid cycle\n                    const s = (p.y < GROUND_Y - 10) ? imageCache['naruto_jump'] : (frame % 2 === 0 ? imageCache['naruto_walk'] : imageCache['naruto_idle']);\n                    \n                    if (s) {\n                        const aspect = s.naturalWidth / s.naturalHeight;\n                        const h = 120;\n                        const w = h * aspect;\n                        // Clone tint (slight transparency or blue tint)\n                        ctx.globalAlpha = 0.8;\n                        ctx.drawImage(s, -w/2, -h, w, h);\n                    }\n                    ctx.restore();\n                    continue;\n                }\n                const spriteId = (p.type === 'fireball' || p.type === 'fuga_arrow') ? 'fireball_projectile' : (p.type === 'magatama' ? 'magatama_projectile' : (p.type === 'rasenshuriken' ? 'rasenshuriken_projectile' : 'shuriken_projectile'));\n                const sprite = imageCache[spriteId];\n                if (sprite) {\n                    ctx.save();\n                    ctx.translate(p.x, p.y);\n                    if (p.type === 'shuriken') ctx.rotate(Date.now() / 100);\n                    if (p.type === 'rasenshuriken') ctx.rotate(Date.now() / 50);\n                    if (p.type === 'fuga_arrow') {\n                        // Point the arrow in movement direction\n                        const angle = Math.atan2(0, p.vx);\n                        ctx.rotate(angle);\n                        const w = 80;\n                        const h = 40;\n                        ctx.drawImage(sprite, -w/2, -h/2, w, h);\n                    } else if (p.type === 'yuji_rock') {\n                        ctx.save();\n                        ctx.fillStyle = '#666';\n                        ctx.strokeStyle = '#000';\n                        ctx.lineWidth = 2;\n                        ctx.beginPath();\n                        ctx.arc(0, 0, 15, 0, Math.PI * 2);\n                        ctx.fill();\n                        ctx.stroke();\n                        // Lightning around rock\n                        ctx.strokeStyle = '#f00';\n                        ctx.beginPath();\n                        for(let k=0; k<3; k++) {\n                            const a = Math.random() * Math.PI * 2;\n                            ctx.moveTo(Math.cos(a)*15, Math.sin(a)*15);\n                            ctx.lineTo(Math.cos(a)*25, Math.sin(a)*25);\n                        }\n                        ctx.stroke();\n                        ctx.restore();\n                    } else {\n                        const size = (p.type === 'fireball' || p.type === 'rasenshuriken') ? 60 : 30;\n                        if (p.type === 'rasenshuriken') {\n                            ctx.shadowBlur = 20;\n                            ctx.shadowColor = '#00BFFF';\n                        }\n                        ctx.drawImage(sprite, -size/2, -size/2, size, size);\n                    }\n                    ctx.restore();\n                } else {\n                    ctx.fillStyle = p.type === 'fireball' ? '#FF4444' : '#9B59B6';\n                    ctx.fillRect(p.x - 8, p.y - 8, 16, 16);\n                }\n            }\n        }\n\n        // Effects\n        function updateEffects(dt) {\n            for (let i = effects.length - 1; i >= 0; i--) {\n                effects[i].timer -= dt;\n                if (effects[i].timer <= 0) effects.splice(i, 1);\n            }\n            for (let i = damageNumbers.length - 1; i >= 0; i--) {\n                damageNumbers[i].timer -= dt;\n                damageNumbers[i].y += damageNumbers[i].vy;\n                if (damageNumbers[i].timer <= 0) damageNumbers.splice(i, 1);\n            }\n        }\n\n        function drawEffects() {\n            for (const e of effects) {\n                const alpha = e.timer / e.maxTimer;\n                if (e.type === 'impact') {\n                    const sprite = imageCache['impact_effect'];\n                    if (sprite) {\n                        ctx.save();\n                        ctx.globalAlpha = alpha;\n                        const s = 60 * (1 + (1-alpha) * 0.5);\n                        ctx.drawImage(sprite, e.x - s/2, e.y - s/2, s, s);\n                        ctx.restore();\n                    }\n                } else if (e.type === 'rock_debris') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    ctx.globalAlpha = alpha;\n                    \n                    const size = 30 + (1 - alpha) * 100;\n                    const count = 3;\n                    for(let k=0; k<count; k++) {\n                        ctx.save();\n                        const offX = (Math.sin(k + (1-alpha)*10) * size);\n                        const offY = - (1-alpha) * 400 - (k * 40);\n                        ctx.translate(offX, offY);\n                        ctx.rotate((1-alpha) * 10 + k);\n                        \n                        const rs = 20 + Math.random() * 40;\n                        ctx.fillStyle = '#5c4033';\n                        ctx.strokeStyle = '#261a15';\n                        ctx.lineWidth = 3;\n                        ctx.beginPath();\n                        ctx.moveTo(-rs, -rs/2); \n                        ctx.lineTo(rs, -rs); \n                        ctx.lineTo(rs/2, rs); \n                        ctx.lineTo(-rs/2, rs/2);\n                        ctx.closePath();\n                        ctx.fill();\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n                    ctx.restore();\n                } else if (e.type === 'fire_ring_obito') {\n                    const sprite = imageCache['obito_fire_ring'];\n                    if (sprite) {\n                        ctx.save();\n                        ctx.globalAlpha = alpha;\n                        const s = 600 * (1 + (1 - alpha) * 0.4);\n                        ctx.drawImage(sprite, e.x - s / 2, e.y - s / 2, s, s);\n                        ctx.restore();\n                    }\n                } else if (e.type === 'skadoosh') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    ctx.globalAlpha = alpha;\n                    \n                    // Golden Dragon Burst\n                    const size = 300 * (1 - alpha);\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size * 2);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.3, '#FFD700');\n                    grad.addColorStop(0.6, 'rgba(255, 215, 0, 0.4)');\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 50 * alpha;\n                    ctx.shadowColor = '#FFD700';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size * 2, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // GIANT CIRCLING DRAGON\n                    const dragonR = 450 * (1 - alpha);\n                    ctx.strokeStyle = '#FFD700';\n                    ctx.lineWidth = 20 * alpha;\n                    ctx.shadowBlur = 40;\n                    ctx.shadowColor = '#FFD700';\n                    \n                    // Body\n                    ctx.beginPath();\n                    for(let k = 0; k < 80; k++) {\n                        const ang = (k * 0.12) + (time * 18);\n                        const r = dragonR + Math.sin(k * 0.4 + time * 12) * 50;\n                        const dx = Math.cos(ang) * r;\n                        const dy = Math.sin(ang) * r;\n                        if (k === 0) ctx.moveTo(dx, dy);\n                        else ctx.lineTo(dx, dy);\n                    }\n                    ctx.stroke();\n\n                    // Giant dragon head at the front of the circle\n                    const headAng = (80 * 0.12) + (time * 18);\n                    const headR = dragonR + Math.sin(80 * 0.4 + time * 12) * 50;\n                    ctx.fillStyle = '#FFD700';\n                    ctx.save();\n                    ctx.translate(Math.cos(headAng) * headR, Math.sin(headAng) * headR);\n                    ctx.rotate(headAng + Math.PI/2);\n                    ctx.beginPath();\n                    ctx.ellipse(0, 0, 60 * alpha, 90 * alpha, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    // Glowing eyes\n                    ctx.fillStyle = '#fff';\n                    ctx.beginPath();\n                    ctx.arc(-20 * alpha, -30 * alpha, 10 * alpha, 0, Math.PI * 2);\n                    ctx.arc(20 * alpha, -30 * alpha, 10 * alpha, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n\n                    // Golden Rings\n                    ctx.strokeStyle = '#FFD700';\n                    ctx.lineWidth = 10 * alpha;\n                    for (let i = 0; i < 3; i++) {\n                        ctx.beginPath();\n                        ctx.arc(0, 0, size * (0.5 + i * 0.4), 0, Math.PI * 2);\n                        ctx.stroke();\n                    }\n                    \n                    ctx.restore();\n                } else if (e.type === 'bagua_explosion') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    ctx.globalAlpha = alpha;\n                    \n                    const size = 380 * (1 - alpha);\n                    \n                    // Golden Glow\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size * 1.8);\n                    grad.addColorStop(0, 'rgba(255, 215, 0, 0.9)');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size * 1.8, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Bagua Symbol\n                    ctx.strokeStyle = '#FFD700';\n                    ctx.lineWidth = 10 * alpha;\n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = '#FFD700';\n                    \n                    // Outer Octagon\n                    ctx.beginPath();\n                    for(let i=0; i<8; i++) {\n                        const angle = i * Math.PI / 4;\n                        const px = Math.cos(angle) * size;\n                        const py = Math.sin(angle) * size;\n                        if (i === 0) ctx.moveTo(px, py);\n                        else ctx.lineTo(px, py);\n                    }\n                    ctx.closePath();\n                    ctx.stroke();\n\n                    // Inner circles\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size * 0.75, 0, Math.PI * 2);\n                    ctx.stroke();\n\n                    // Yin-Yang like divider\n                    ctx.beginPath();\n                    ctx.moveTo(0, -size * 0.75);\n                    ctx.bezierCurveTo(size * 0.6, -size * 0.4, -size * 0.6, size * 0.4, 0, size * 0.75);\n                    ctx.stroke();\n\n                    // Trigrams (simplified as bars)\n                    ctx.fillStyle = '#FFD700';\n                    for(let i=0; i<8; i++) {\n                        ctx.save();\n                        ctx.rotate(i * Math.PI / 4 + Math.PI/8);\n                        ctx.translate(size * 0.9, 0);\n                        // Three bars for each trigram\n                        for(let b=0; b<3; b++) {\n                            const isBroken = (i + b) % 2 === 0;\n                            if (isBroken) {\n                                ctx.fillRect(-22, -12 + b*8, 18, 5);\n                                ctx.fillRect(4, -12 + b*8, 18, 5);\n                            } else {\n                                ctx.fillRect(-22, -12 + b*8, 44, 5);\n                            }\n                        }\n                        ctx.restore();\n                    }\n\n                    ctx.restore();\n                } else if (e.type === 'lightning_strike' || e.type === 'lightning_strike_big') {\n                    ctx.save();\n                    ctx.globalAlpha = alpha;\n                    ctx.shadowBlur = 20;\n                    ctx.shadowColor = '#00BFFF';\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = e.type === 'lightning_strike_big' ? 10 : 3;\n                    ctx.beginPath();\n                    let curY = -100;\n                    let curX = e.x;\n                    ctx.moveTo(curX, curY);\n                    while(curY < GROUND_Y) {\n                        curY += 50;\n                        curX += (Math.random()-0.5)*80;\n                        ctx.lineTo(curX, curY);\n                    }\n                    ctx.stroke();\n                    ctx.restore();\n                } else if (e.type === 'fire_land') {\n                    ctx.save();\n                    ctx.globalAlpha = alpha;\n                    const s = 40 + (1 - alpha) * 150;\n                    const grad = ctx.createRadialGradient(e.x, e.y, 0, e.x, e.y, s);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.2, '#ffeb3b');\n                    grad.addColorStop(0.5, '#ff5722');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    // Floating fire effect\n                    ctx.arc(e.x, e.y - (1 - alpha) * 80, s, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.restore();\n                } else if (e.type === 'ashura_slash') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    ctx.rotate(e.rotation || 0);\n                    ctx.globalAlpha = alpha;\n                    \n                    const len = 650; \n                    const width = 100 * alpha;\n                    \n                    ctx.shadowBlur = 30;\n                    ctx.shadowColor = e.color === '#000' ? '#4b0082' : (e.color || '#FFD700');\n                    \n                    const grad = ctx.createLinearGradient(-len/2, 0, len/2, 0);\n                    grad.addColorStop(0, 'transparent');\n                    grad.addColorStop(0.5, e.color || '#FFD700');\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    ctx.moveTo(-len/2, 0);\n                    ctx.lineTo(0, -width/2);\n                    ctx.lineTo(len/2, 0);\n                    ctx.lineTo(0, width/2);\n                    ctx.closePath();\n                    ctx.fill();\n\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 4 * alpha;\n                    ctx.beginPath();\n                    ctx.moveTo(-len/2, 0);\n                    ctx.lineTo(len/2, 0);\n                    ctx.stroke();\n                    \n                    ctx.restore();\n                } else if (e.type === 'zoro_wano_black_slash') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    ctx.rotate(e.rotation || 0);\n                    ctx.globalAlpha = alpha;\n                    const time = Date.now() / 1000;\n                    const len = e.length || 620;\n                    const width = e.width || 44;\n                    const pulse = 1 + Math.sin(time * 32) * 0.04;\n\n                    // Dark violet glow underneath a dense black blade trail.\n                    ctx.scale(pulse, pulse);\n                    ctx.shadowBlur = 32;\n                    ctx.shadowColor = '#32104f';\n                    ctx.strokeStyle = 'rgba(60, 12, 88, 0.8)';\n                    ctx.lineWidth = width + 24;\n                    ctx.lineCap = 'round';\n                    ctx.beginPath();\n                    ctx.moveTo(-len / 2, 0);\n                    ctx.lineTo(len / 2, 0);\n                    ctx.stroke();\n\n                    ctx.shadowBlur = 12;\n                    ctx.shadowColor = '#000';\n                    ctx.strokeStyle = '#050505';\n                    ctx.lineWidth = width;\n                    ctx.beginPath();\n                    ctx.moveTo(-len / 2, 0);\n                    ctx.lineTo(len / 2, 0);\n                    ctx.stroke();\n\n                    // Two thin black after-images sell the continuous barrage.\n                    ctx.globalAlpha = alpha * 0.45;\n                    ctx.strokeStyle = '#000';\n                    ctx.lineWidth = Math.max(4, width * 0.12);\n                    ctx.beginPath();\n                    ctx.moveTo(-len / 2 + 20, -width * 0.38);\n                    ctx.lineTo(len / 2 - 30, -width * 0.38);\n                    ctx.moveTo(-len / 2 + 45, width * 0.42);\n                    ctx.lineTo(len / 2 - 10, width * 0.42);\n                    ctx.stroke();\n                    ctx.restore();\n                } else if (e.type === 'zoro_wano_final_slash') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    ctx.rotate(e.rotation || -0.22);\n                    const progress = 1 - alpha;\n                    const time = Date.now() / 1000;\n                    const len = (e.length || 1080) * (0.9 + progress * 0.12);\n                    const width = (e.width || 190) * (0.82 + Math.sin(time * 9) * 0.06);\n                    ctx.globalAlpha = alpha;\n                    ctx.lineCap = 'round';\n                    ctx.shadowBlur = 80;\n                    ctx.shadowColor = '#3b0a57';\n\n                    // Oversized final black slash, visible for the full 3-second\n                    // eruption window.\n                    ctx.strokeStyle = 'rgba(80, 14, 112, 0.75)';\n                    ctx.lineWidth = width + 48;\n                    ctx.beginPath();\n                    ctx.moveTo(-len / 2, 0);\n                    ctx.lineTo(len / 2, 0);\n                    ctx.stroke();\n                    ctx.shadowBlur = 28;\n                    ctx.strokeStyle = '#000';\n                    ctx.lineWidth = width;\n                    ctx.beginPath();\n                    ctx.moveTo(-len / 2, 0);\n                    ctx.lineTo(len / 2, 0);\n                    ctx.stroke();\n\n                    // Heavy central edge and trailing ghost cuts.\n                    ctx.globalAlpha = alpha * 0.85;\n                    ctx.strokeStyle = '#171717';\n                    ctx.lineWidth = Math.max(8, width * 0.13);\n                    ctx.beginPath();\n                    ctx.moveTo(-len / 2 + 25, -width * 0.28);\n                    ctx.lineTo(len / 2 - 35, -width * 0.28);\n                    ctx.stroke();\n                    ctx.globalAlpha = alpha * 0.42;\n                    ctx.lineWidth = Math.max(5, width * 0.08);\n                    ctx.beginPath();\n                    ctx.moveTo(-len / 2 + 55, width * 0.38);\n                    ctx.lineTo(len / 2, width * 0.38);\n                    ctx.stroke();\n                    ctx.restore();\n                } else if (e.type === 'zoro_wano_ground_burst') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const progress = 1 - alpha;\n                    const time = Date.now() / 1000;\n                    const baseRadius = e.radius || 150;\n                    const radius = baseRadius * (0.25 + progress * 0.95);\n                    ctx.globalAlpha = alpha;\n\n                    // Cracked ground and a dusty shockwave.\n                    ctx.shadowBlur = 28;\n                    ctx.shadowColor = '#6b321d';\n                    const dust = ctx.createRadialGradient(0, 0, 0, 0, 0, radius * 1.4);\n                    dust.addColorStop(0, 'rgba(255, 211, 157, 0.7)');\n                    dust.addColorStop(0.35, 'rgba(126, 69, 38, 0.55)');\n                    dust.addColorStop(1, 'transparent');\n                    ctx.fillStyle = dust;\n                    ctx.beginPath();\n                    ctx.ellipse(0, -18 * progress, radius * 1.35, 48 + progress * 40, 0, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    ctx.shadowBlur = 0;\n                    ctx.strokeStyle = '#24130d';\n                    ctx.lineWidth = e.heavy ? 8 : 5;\n                    ctx.lineCap = 'round';\n                    for (let k = 0; k < 10; k++) {\n                        const angle = k * Math.PI / 5 + time * 0.35;\n                        const inner = radius * 0.12;\n                        const outer = radius * (0.72 + (k % 3) * 0.1);\n                        ctx.beginPath();\n                        ctx.moveTo(Math.cos(angle) * inner, Math.sin(angle) * inner * 0.28);\n                        ctx.lineTo(Math.cos(angle) * outer, Math.sin(angle) * outer * 0.28);\n                        ctx.stroke();\n                    }\n\n                    // Dirt and stone fragments are launched above the floor.\n                    for (let k = 0; k < (e.heavy ? 22 : 12); k++) {\n                        const angle = k * 2.399 + (e.x % 31) * 0.1;\n                        const launch = progress * (45 + (k % 5) * 18);\n                        const dx = Math.cos(angle) * (radius * (0.35 + (k % 4) * 0.16));\n                        const dy = -Math.abs(Math.sin(angle)) * launch - (progress * (25 + (k % 3) * 22));\n                        const size = (e.heavy ? 8 : 6) + (k % 4) * 3;\n                        ctx.save();\n                        ctx.translate(dx, dy);\n                        ctx.rotate(time * 4 + k);\n                        ctx.fillStyle = k % 3 === 0 ? '#8a4d2d' : '#4b2b1c';\n                        ctx.strokeStyle = '#24130d';\n                        ctx.lineWidth = 2;\n                        ctx.beginPath();\n                        ctx.moveTo(-size, -size * 0.45);\n                        ctx.lineTo(size * 0.8, -size);\n                        ctx.lineTo(size, size * 0.55);\n                        ctx.lineTo(-size * 0.35, size);\n                        ctx.closePath();\n                        ctx.fill();\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n                    ctx.restore();\n                } else if (e.type === 'luc_dao_vortex') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    ctx.globalAlpha = alpha;\n                    \n                    const size = 520 * (1 - alpha * 0.15); \n                    \n                    // 1. Bright Cyan/White Core (Reference 01KY93FGH7XCZARASR477Z24Z3)\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.2, '#00ffff');\n                    grad.addColorStop(0.5, 'rgba(0, 206, 209, 0.6)');\n                    grad.addColorStop(0.8, 'rgba(0, 0, 0, 0.8)'); \n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 60 * alpha;\n                    ctx.shadowColor = '#00ffff';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // 2. Continuous Swirling Black Rings\n                    ctx.shadowBlur = 0;\n                    ctx.strokeStyle = '#000';\n                    ctx.lineWidth = 20 * alpha;\n                    ctx.lineCap = 'round';\n                    for (let j = 0; j < 6; j++) {\n                        ctx.save();\n                        ctx.rotate(time * 25 + j * Math.PI / 3);\n                        ctx.beginPath();\n                        const r = size * (0.3 + (j * 0.12));\n                        ctx.arc(0, 0, r, 0, Math.PI * 0.8);\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n\n                    // 3. Truth-Seeker Orb shards\n                    ctx.fillStyle = '#000';\n                    for (let j = 0; j < 10; j++) {\n                        const ang = (j * Math.PI * 2 / 10) - time * 10;\n                        const dist = size * (0.6 + Math.sin(time * 5 + j) * 0.2);\n                        ctx.beginPath();\n                        ctx.arc(Math.cos(ang) * dist, Math.sin(ang) * dist, 15 * alpha, 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n                    \n                    ctx.restore();\n                } else if (e.type === 'black_flash') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    ctx.globalAlpha = alpha;\n                    \n                    // Outer Red Distortion\n                    ctx.shadowBlur = 60 * alpha;\n                    ctx.shadowColor = '#f00';\n                    ctx.strokeStyle = '#f00';\n                    ctx.lineWidth = 12 * alpha;\n                    \n                    // Draw many jagged arcs\n                    for(let i=0; i<12; i++) {\n                        ctx.save();\n                        ctx.rotate(i * Math.PI / 6 + Math.sin(time * 20 + i) * 0.5);\n                        ctx.beginPath();\n                        let r = 0;\n                        ctx.moveTo(0, 0);\n                        for(let j=0; j<5; j++) {\n                            r += (25 + Math.random() * 35) * alpha;\n                            const off = (Math.random() - 0.5) * 40 * alpha;\n                            ctx.lineTo(r, off);\n                        }\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n\n                    // Inner Black Core Lightning\n                    ctx.shadowBlur = 0;\n                    ctx.strokeStyle = '#000';\n                    ctx.lineWidth = 6 * alpha;\n                    for(let i=0; i<8; i++) {\n                        ctx.save();\n                        ctx.rotate(i * Math.PI / 4 - Math.sin(time * 15 + i) * 0.3);\n                        ctx.beginPath();\n                        let r = 0;\n                        ctx.moveTo(0, 0);\n                        for(let j=0; j<4; j++) {\n                            r += (20 + Math.random() * 30) * alpha;\n                            const off = (Math.random() - 0.5) * 20 * alpha;\n                            ctx.lineTo(r, off);\n                        }\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n\n                    // Intense Central Flash\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, 100 * alpha);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.2, 'rgba(255, 0, 0, 0.8)');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, 100 * alpha, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Spatial cracks (white/red)\n                    ctx.strokeStyle = '#fff';\n                    ctx.lineWidth = 2;\n                    for(let i=0; i<4; i++) {\n                        const ang = Math.random() * Math.PI * 2;\n                        const len = 150 * alpha;\n                        ctx.beginPath();\n                        ctx.moveTo(Math.cos(ang) * len, Math.sin(ang) * len);\n                        ctx.lineTo(Math.cos(ang) * (len + 50), Math.sin(ang) * (len + 50));\n                        ctx.stroke();\n                    }\n\n                    ctx.restore();\n                } else if (e.type === 'doraemon_vietnam_flag_explosion') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    const progress = 1 - alpha;\n                    const radius = (e.radius || 360) * (0.12 + progress * 0.88);\n                    ctx.globalAlpha = alpha;\n\n                    // Red-and-gold sky detonation after the dragon vortex ends.\n                    const blast = ctx.createRadialGradient(0, 0, 0, 0, 0, radius);\n                    blast.addColorStop(0, '#fffbd0');\n                    blast.addColorStop(0.12, '#fff000');\n                    blast.addColorStop(0.34, '#ff4b18');\n                    blast.addColorStop(0.7, 'rgba(190, 0, 20, 0.75)');\n                    blast.addColorStop(1, 'transparent');\n                    ctx.fillStyle = blast;\n                    ctx.shadowBlur = 80 * alpha;\n                    ctx.shadowColor = '#ff2a00';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    // Expanding golden rings.\n                    ctx.strokeStyle = '#ffe83b';\n                    ctx.lineWidth = 12 * alpha;\n                    ctx.shadowBlur = 25;\n                    ctx.shadowColor = '#ffd000';\n                    for (let k = 0; k < 3; k++) {\n                        ctx.beginPath();\n                        ctx.arc(0, 0, radius * (0.42 + k * 0.22), time * 2 + k, time * 2 + k + Math.PI * 1.55);\n                        ctx.stroke();\n                    }\n\n                    // Five-point star shards echo the flag reference.\n                    ctx.fillStyle = '#fff04a';\n                    for (let k = 0; k < 10; k++) {\n                        const angle = time * 2 + k * Math.PI / 5;\n                        const sx = Math.cos(angle) * radius * 0.72;\n                        const sy = Math.sin(angle) * radius * 0.72;\n                        ctx.save();\n                        ctx.translate(sx, sy);\n                        ctx.rotate(angle);\n                        ctx.globalAlpha = alpha * 0.8;\n                        drawFivePointStar(ctx, 0, 0, 14 + progress * 18, 6 + progress * 8);\n                        ctx.restore();\n                    }\n                    ctx.restore();\n                } else if (e.type === 'doraemon_vietnam_red_wind') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    ctx.globalAlpha = alpha;\n                    ctx.strokeStyle = '#ff2638';\n                    ctx.shadowBlur = 18;\n                    ctx.shadowColor = '#ff001c';\n                    ctx.lineWidth = 5;\n                    for (let k = 0; k < 4; k++) {\n                        const spread = (k - 1.5) * 18;\n                        ctx.beginPath();\n                        ctx.moveTo(-10, spread);\n                        ctx.quadraticCurveTo(35, spread - 18 + Math.sin(time * 10 + k) * 8, 80, spread + 4);\n                        ctx.stroke();\n                    }\n                    ctx.restore();\n                } else if (e.type === 'itachi_edo_susanoo_red_explosion') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    const progress = 1 - alpha;\n                    const radius = (e.radius || 260) * (0.12 + progress * 0.88);\n                    ctx.globalAlpha = alpha;\n\n                    // Violent black-red Susanoo detonation after the slash connects.\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, radius);\n                    grad.addColorStop(0, '#fff3b0');\n                    grad.addColorStop(0.12, '#ff3b12');\n                    grad.addColorStop(0.42, '#b00000');\n                    grad.addColorStop(0.72, '#160006');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 75 * alpha;\n                    ctx.shadowColor = '#ff1600';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    ctx.strokeStyle = '#ff2b00';\n                    ctx.lineWidth = 12 * alpha;\n                    for (let k = 0; k < 12; k++) {\n                        const angle = k * Math.PI / 6 + time * 2;\n                        const inner = radius * 0.18;\n                        const outer = radius * (0.72 + 0.24 * Math.sin(time * 8 + k));\n                        ctx.beginPath();\n                        ctx.moveTo(Math.cos(angle) * inner, Math.sin(angle) * inner);\n                        ctx.lineTo(Math.cos(angle) * outer, Math.sin(angle) * outer);\n                        ctx.stroke();\n                    }\n                    ctx.strokeStyle = '#000';\n                    ctx.lineWidth = 8 * alpha;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius * 0.65, time, time + Math.PI * 1.7);\n                    ctx.stroke();\n                    ctx.restore();\n                } else if (e.type === 'itachi_edo_sharingan_black_explosion') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    const progress = 1 - alpha;\n                    const radius = (e.radius || 320) * (0.15 + progress * 0.85);\n                    ctx.globalAlpha = alpha;\n\n                    // Black detonation: a dark core, crimson rim and expanding shards.\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, radius);\n                    grad.addColorStop(0, '#000');\n                    grad.addColorStop(0.28, '#050505');\n                    grad.addColorStop(0.62, 'rgba(45, 0, 12, 0.95)');\n                    grad.addColorStop(0.86, 'rgba(170, 0, 30, 0.65)');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 75 * alpha;\n                    ctx.shadowColor = '#ff0033';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    ctx.globalAlpha = alpha * 0.9;\n                    ctx.strokeStyle = '#000';\n                    ctx.lineWidth = 12 * alpha;\n                    for (let k = 0; k < 14; k++) {\n                        const angle = k * Math.PI / 7 + time * 0.8;\n                        const inner = radius * 0.16;\n                        const outer = radius * (0.75 + 0.25 * Math.sin(time * 7 + k));\n                        ctx.beginPath();\n                        ctx.moveTo(Math.cos(angle) * inner, Math.sin(angle) * inner);\n                        ctx.lineTo(Math.cos(angle) * outer, Math.sin(angle) * outer);\n                        ctx.stroke();\n                    }\n                    ctx.strokeStyle = '#ff173d';\n                    ctx.lineWidth = 5 * alpha;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius * 0.72, time, time + Math.PI * 1.7);\n                    ctx.stroke();\n                    ctx.restore();\n                } else if (e.type === 'itachi_edo_orb_explosion') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    const time = Date.now() / 1000;\n                    const progress = 1 - alpha;\n                    const radius = (e.radius || 230) * (0.18 + progress * 0.82);\n                    ctx.globalAlpha = alpha;\n\n                    // Orange-white detonation with the purple Susanoo shield motif.\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, radius);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.16, '#fff3a0');\n                    grad.addColorStop(0.42, '#ff7a00');\n                    grad.addColorStop(0.72, 'rgba(112, 18, 72, 0.75)');\n                    grad.addColorStop(1, 'transparent');\n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 55 * alpha;\n                    ctx.shadowColor = '#ff6a00';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius, 0, Math.PI * 2);\n                    ctx.fill();\n\n                    ctx.strokeStyle = '#fff4b0';\n                    ctx.lineWidth = 8 * alpha;\n                    ctx.globalAlpha = alpha * 0.9;\n                    for (let k = 0; k < 8; k++) {\n                        const angle = k * Math.PI / 4 + time * 2;\n                        const inner = radius * 0.25;\n                        const outer = radius * (0.85 + 0.12 * Math.sin(time * 8 + k));\n                        ctx.beginPath();\n                        ctx.moveTo(Math.cos(angle) * inner, Math.sin(angle) * inner);\n                        ctx.lineTo(Math.cos(angle) * outer, Math.sin(angle) * outer);\n                        ctx.stroke();\n                    }\n\n                    ctx.strokeStyle = '#8e1b63';\n                    ctx.lineWidth = 5 * alpha;\n                    ctx.beginPath();\n                    ctx.arc(0, 0, radius * 0.62, time, time + Math.PI * 1.6);\n                    ctx.stroke();\n                    ctx.restore();\n                } else if (e.type === 'rimuru_explosion') {\n                    ctx.save();\n                    ctx.translate(e.x, e.y);\n                    ctx.globalAlpha = alpha;\n                    const time = Date.now() / 1000;\n                    \n                    // Massive Black & Blue Nova\n                    const size = 450 * (1 - alpha);\n                    const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, size);\n                    grad.addColorStop(0, '#fff');\n                    grad.addColorStop(0.3, '#00BFFF');\n                    grad.addColorStop(0.6, '#000');\n                    grad.addColorStop(1, 'transparent');\n                    \n                    ctx.fillStyle = grad;\n                    ctx.shadowBlur = 100 * alpha;\n                    ctx.shadowColor = '#00BFFF';\n                    ctx.beginPath();\n                    ctx.arc(0, 0, size, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Orange Lightning Remnants\n                    ctx.strokeStyle = '#FF8C00';\n                    ctx.lineWidth = 10 * alpha;\n                    for(let i=0; i<8; i++) {\n                        ctx.save();\n                        ctx.rotate(i * Math.PI / 4 + time);\n                        ctx.beginPath();\n                        ctx.moveTo(size * 0.5, 0);\n                        ctx.lineTo(size * 1.2, (Math.random()-0.5)*100);\n                        ctx.stroke();\n                        ctx.restore();\n                    }\n                    \n                    ctx.restore();\n                }\n            }\n            for (const d of damageNumbers) {\n                ctx.save();\n                ctx.globalAlpha = d.timer;\n                ctx.font = 'bold 28px Inter';\n                ctx.fillStyle = '#FF4444';\n                ctx.textAlign = 'center';\n                ctx.strokeStyle = '#000';\n                ctx.lineWidth = 3;\n                ctx.strokeText('-' + d.amount, d.x, d.y);\n                ctx.fillText('-' + d.amount, d.x, d.y);\n                ctx.restore();\n            }\n        }\n\n        // Draw background\n        function drawBackground() {\n            let bgId = selectedMap;\n            if (gameState === 'menu' || gameState === 'charSelect' || gameState === 'stageSelect' || gameState === 'mapSelect' || gameState === 'shop') {\n                bgId = 'lobby_background_v3';\n            }\n            const bg = imageCache[bgId];\n            if (bg) {\n                // Cover scaling\n                const canvasRatio = 720 / 1280;\n                const imgRatio = bg.naturalWidth / bg.naturalHeight;\n                let sw, sh, sx, sy;\n                if (imgRatio > canvasRatio) {\n                    sh = bg.naturalHeight;\n                    sw = sh * canvasRatio;\n                    sx = (bg.naturalWidth - sw) / 2;\n                    sy = 0;\n                } else {\n                    sw = bg.naturalWidth;\n                    sh = sw / canvasRatio;\n                    sx = 0;\n                    sy = (bg.naturalHeight - sh) / 2;\n                }\n                ctx.drawImage(bg, sx, sy, sw, sh, 0, 0, 720, 1280);\n                \n                // Add a darkening overlay to menus for better UI readability\n                if (gameState !== 'combat' && gameState !== 'countdown' && gameState !== 'result') {\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';\n                    ctx.fillRect(0, 0, 720, 1280);\n                }\n            } else {\n                const grad = ctx.createLinearGradient(0, 0, 0, 1280);\n                grad.addColorStop(0, '#1a1a2e');\n                grad.addColorStop(1, '#16213e');\n                ctx.fillStyle = grad;\n                ctx.fillRect(0, 0, 720, 1280);\n            }\n\n            // Draw Po vs Obito Background silhouettes if it's the main arena or menu\n            if (selectedMap === 'arena_background' || gameState === 'menu') {\n                ctx.save();\n                ctx.globalAlpha = 0.15; // Subtle background appearance\n                \n                const poPort = imageCache['po_panda_portrait'];\n                const obitoPort = imageCache['obito_portrait'];\n                \n                if (poPort) {\n                    // Po on the left\n                    const pW = 400;\n                    const pH = pW * (poPort.naturalHeight / poPort.naturalWidth);\n                    ctx.drawImage(poPort, -50, GROUND_Y - pH, pW, pH);\n                }\n                \n                if (obitoPort) {\n                    // Obito on the right\n                    const oW = 400;\n                    const oH = oW * (obitoPort.naturalHeight / obitoPort.naturalWidth);\n                    ctx.save();\n                    ctx.scale(-1, 1);\n                    ctx.drawImage(obitoPort, -770, GROUND_Y - oH, oW, oH);\n                    ctx.restore();\n                }\n                ctx.restore();\n            }\n\n            // Ground\n            ctx.fillStyle = 'rgba(255,255,255,0.1)';\n            ctx.fillRect(0, GROUND_Y, 720, 360);\n            ctx.strokeStyle = 'rgba(255,255,255,0.3)';\n            ctx.lineWidth = 2;\n            ctx.beginPath();\n            ctx.moveTo(0, GROUND_Y);\n            ctx.lineTo(720, GROUND_Y);\n            ctx.stroke();\n        }\n\n        // UI rendering\n        function renderUI() {\n            uiOverlay.innerHTML = '';\n            if (gameState !== 'combat') return;\n\n            // Health bars\n            const hbContainer = document.createElement('div');\n            hbContainer.className = 'health-bar-container';\n            hbContainer.style.pointerEvents = 'none';\n            hbContainer.style.flexDirection = 'column';\n            hbContainer.style.gap = '4px';\n\n            const pRatio = player.health / player.maxHealth;\n            const oRatio = opponent.health / opponent.maxHealth;\n            const pEnergy = player.energy / player.maxEnergy;\n            const oEnergy = opponent.energy / opponent.maxEnergy;\n\n            const charColors = {\n                batBai: '#4A90E2',\n                bongDem: '#9B59B6',\n                itachi: '#FF4444',\n                sasuke: '#A020F0',\n                madara: '#4A90E2',\n                luffy: '#FFD700',\n                sukuna: '#FF4444',\n                gojo: '#B0E0E6'\n            };\n\n            hbContainer.innerHTML = `\n                <div style=\"display:flex; gap:8px; align-items:center; width:100%\">\n                    <span class=\"health-label\" style=\"color:${charColors[player.type]}\">${player.health}</span>\n                    <div class=\"health-bar\">\n                        <div class=\"health-bar-fill\" style=\"width:${pRatio*100}%;background:${pRatio > 0.5 ? '#4CAF50' : pRatio > 0.25 ? '#FFC107' : '#F44336'}\"></div>\n                    </div>\n                    <div class=\"health-bar\">\n                        <div class=\"health-bar-fill\" style=\"width:${oRatio*100}%;background:${oRatio > 0.5 ? '#4CAF50' : oRatio > 0.25 ? '#FFC107' : '#F44336'};float:right\"></div>\n                    </div>\n                    <span class=\"health-label\" style=\"color:${charColors[opponent.type]}\">${opponent.health}</span>\n                </div>\n                <div style=\"display:flex; gap:8px; align-items:center; width:100%; margin-top:-4px\">\n                    <div style=\"width:40px\"></div>\n                    <div style=\"flex:1; height:8px; background:rgba(0,0,0,0.5); border-radius:4px; overflow:hidden\">\n                        <div style=\"height:100%; width:${pEnergy*100}%; background:#FFEB3B; box-shadow:0 0 5px #FFEB3B; transition:width 0.2s\"></div>\n                    </div>\n                    <div style=\"flex:1; height:8px; background:rgba(0,0,0,0.5); border-radius:4px; overflow:hidden\">\n                        <div style=\"height:100%; width:${oEnergy*100}%; background:#FFEB3B; box-shadow:0 0 5px #FFEB3B; transition:width 0.2s; float:right\"></div>\n                    </div>\n                    <div style=\"width:40px\"></div>\n                </div>\n            `;\n            uiOverlay.appendChild(hbContainer);\n\n            // Timer\n            const timer = document.createElement('div');\n            timer.className = 'timer-display';\n            timer.style.pointerEvents = 'none';\n            timer.textContent = Math.ceil(matchTimer) + 's';\n            uiOverlay.appendChild(timer);\n\n            // Ability buttons\n            const isNika = player.type === 'luffy' && player.isAwakened;\n            \n            // Draw skills\n            for (let i = 0; i < player.abilities.length; i++) {\n                const btn = document.createElement('div');\n                btn.className = 'ability-btn';\n                btn.style.right = '16px';\n                btn.style.bottom = (80 + i * 112) + 'px';\n\n                const charPrefix = getAssetPrefix(player.type);\n                let iconId = `ability${i+1}_icon_${charPrefix}`;\n                if (player.type === 'doraemon' && player.skin === 'vietnam' && i === 3) {\n                    iconId = 'doraemon_vietnam_flag_reference';\n                }\n                \n                // Fallback for missing 4th icons\n                if (i === 3 && !lib.getAsset(iconId)) {\n                    btn.style.backgroundColor = 'rgba(128, 0, 128, 0.6)'; // Purple for ult\n                    const btnLabel = (player.type === 'goku') ? (player.isUI ? 'MAX' : 'UI') : 'ULT';\n                    btn.innerHTML = `<span style=\"color:#fff;font-family:'Bebas Neue';font-size:32px\">${btnLabel}</span>`;\n                } else {\n                    const icon = imageCache[iconId];\n                    if (icon) {\n                        const img = document.createElement('img');\n                        img.src = icon.src;\n                        btn.appendChild(img);\n                    } else {\n                        btn.textContent = (i+1);\n                        btn.style.color = '#fff';\n                        btn.style.fontSize = '28px';\n                        btn.style.fontFamily = 'Bebas Neue';\n                    }\n                }\n\n                const ab = player.abilities[i];\n                if (ab.currentCd > 0) {\n                    const overlay = document.createElement('div');\n                    overlay.className = 'cooldown-overlay';\n                    overlay.textContent = Math.ceil(ab.currentCd);\n                    btn.appendChild(overlay);\n                }\n\n                const idx = i;\n                btn.addEventListener('touchstart', (e) => { e.preventDefault(); abilityPressed[idx] = true; abilityHeld[idx] = true; });\n                btn.addEventListener('touchend', (e) => { e.preventDefault(); abilityHeld[idx] = false; });\n                btn.addEventListener('mousedown', (e) => { e.preventDefault(); abilityPressed[idx] = true; abilityHeld[idx] = true; });\n                btn.addEventListener('mouseup', (e) => { e.preventDefault(); abilityHeld[idx] = false; });\n                btn.addEventListener('mouseleave', (e) => { e.preventDefault(); abilityHeld[idx] = false; });\n                uiOverlay.appendChild(btn);\n            }\n\n            // Awakening Button\n            const awakenBtn = document.createElement('div');\n            awakenBtn.className = 'ability-btn';\n            awakenBtn.style.right = '128px';\n            awakenBtn.style.bottom = '80px';\n            awakenBtn.style.width = '100px';\n            awakenBtn.style.height = '100px';\n            awakenBtn.style.borderColor = '#FFD700';\n            awakenBtn.style.background = player.energy >= player.maxEnergy ? 'rgba(255, 215, 0, 0.4)' : 'rgba(0,0,0,0.5)';\n            awakenBtn.style.boxShadow = player.energy >= player.maxEnergy ? '0 0 20px #FFD700' : 'none';\n            \n            awakenBtn.innerHTML = `\n                <div style=\"font-family:'Bebas Neue'; color:#fff; font-size:20px; text-align:center;\">\n                    ${player.isAwakened ? 'ACTIVE' : 'AWAKEN'}\n                </div>\n            `;\n\n            if (player.energy < player.maxEnergy && !player.isAwakened) {\n                const overlay = document.createElement('div');\n                overlay.className = 'cooldown-overlay';\n                overlay.style.fontSize = '18px';\n                overlay.textContent = Math.floor(player.energy) + '%';\n                awakenBtn.appendChild(overlay);\n            }\n\n            awakenBtn.addEventListener('touchstart', (e) => { e.preventDefault(); awakenPressed = true; });\n            awakenBtn.addEventListener('mousedown', (e) => { e.preventDefault(); awakenPressed = true; });\n            uiOverlay.appendChild(awakenBtn);\n\n            // Joystick visual\n            if (joystickActive) {\n                const jBase = document.createElement('div');\n                jBase.style.cssText = `position:absolute;left:${joystickBaseX-60}px;top:${joystickBaseY-60}px;width:120px;height:120px;border-radius:50%;background:rgba(255,255,255,0.1);border:2px solid rgba(255,255,255,0.3);pointer-events:none;`;\n                uiOverlay.appendChild(jBase);\n                const jThumb = document.createElement('div');\n                jThumb.style.cssText = `position:absolute;left:${joystickBaseX+joystickX-25}px;top:${joystickBaseY+joystickY-25}px;width:50px;height:50px;border-radius:50%;background:rgba(255,255,255,0.4);pointer-events:none;`;\n                uiOverlay.appendChild(jThumb);\n            }\n        }\n\n        // Process player input\n        function processInput() {\n            if (!player || gameState !== 'combat') return;\n            if (player.stunTimer > 0) return;\n            if (player.state === 'hit') return;\n\n            let moveX = 0;\n            let jump = false;\n\n            // Keyboard\n            if (keys['a'] || keys['arrowleft']) moveX = -1;\n            if (keys['d'] || keys['arrowright']) moveX = 1;\n            if (keys['w'] || keys['arrowup'] || keys[' ']) jump = true;\n            if (keys['j'] || keys['1']) { abilityPressed[0] = true; }\n            if (keys['k'] || keys['2']) { abilityPressed[1] = true; }\n            if (keys['l'] || keys['3']) { abilityPressed[2] = true; }\n            if (keys['i'] || keys['4']) { abilityPressed[3] = true; }\n            if (keys['u'] || keys['5'] || keys['q']) { awakenPressed = true; }\n\n            // Joystick\n            if (joystickActive) {\n                if (joystickX > 15) moveX = 1;\n                else if (joystickX < -15) moveX = -1;\n                if (joystickY < -25) jump = true;\n            }\n\n            // Itachi Edo movement uses acceleration and braking so the cloak\n            // glides naturally, while still stopping promptly when the thumb is\n            // released. This also prevents residual vx from carrying him across\n            // the arena after a direction change.\n            const isItachiEdo = player.type === 'itachi' && player.skin === 'edo';\n            if (moveX !== 0) {\n                if (isItachiEdo) {\n                    player.targetVx = moveX * player.speed;\n                    const acceleration = player.grounded ? 0.24 : 0.14;\n                    player.vx += (player.targetVx - player.vx) * acceleration;\n                    if (Math.abs(player.vx) < 0.05) player.vx = 0;\n                } else {\n                    player.vx = moveX * player.speed;\n                }\n                // Allow flipping direction during abilities except for channeled beams like Naruto's Kurama Beam\n                const isChanneledNaruto = player.type === 'naruto' && player.abilities[2].active;\n                if (player.state !== 'hit' && !isChanneledNaruto) {\n                    player.facingRight = moveX > 0;\n                }\n                if (player.stateTimer <= 0) player.state = 'walk';\n            } else if (isItachiEdo) {\n                player.targetVx = 0;\n                const braking = player.grounded ? 0.32 : 0.08;\n                player.vx += (player.targetVx - player.vx) * braking;\n                if (Math.abs(player.vx) < 0.08) player.vx = 0;\n                if (player.stateTimer <= 0 && player.grounded && Math.abs(player.vx) < 0.15) {\n                    player.state = 'idle';\n                }\n            } else {\n                if (player.stateTimer <= 0 && player.grounded) player.state = 'idle';\n            }\n\n            if (jump && player.grounded) {\n                player.vy = -player.jumpForce;\n                player.grounded = false;\n                player.state = 'jump';\n                player.stateTimer = 0.1;\n            }\n\n            if (!player.grounded && player.stateTimer <= 0) {\n                player.state = 'jump';\n            }\n\n            // Abilities\n            for (let i = 0; i < player.abilities.length; i++) {\n                if (abilityPressed[i]) {\n                    useAbility(player, i, opponent);\n                    abilityPressed[i] = false;\n                }\n            }\n\n            if (awakenPressed) {\n                useAwakening(player);\n                awakenPressed = false;\n            }\n\n            // Clear key-triggered abilities\n            keys['j'] = false; keys['k'] = false; keys['l'] = false;\n            keys['1'] = false; keys['2'] = false; keys['3'] = false;\n            keys['u'] = false; keys['4'] = false; keys['q'] = false;\n            keys['i'] = false;\n        }\n\n        function showMenu() {\n            gameState = 'menu';\n            isBossMode = false;\n            isStageMode = false;\n            stopMusic();\n            playMusic('menu_music');\n            uiOverlay.innerHTML = `\n                <div class=\"screen active\">\n                    <div style=\"position:absolute;top:16px;right:16px;display:flex;gap:16px;align-items:center;\">\n                        <div style=\"background:rgba(0,191,255,0.3);border:2px solid #00BFFF;border-radius:8px;padding:8px 16px;display:flex;align-items:center;gap:8px;\">\n                            <div style=\"font-size:24px;\">\ud83d\udc8e</div>\n                            <div style=\"font-family:'Bebas Neue';font-size:24px;color:#00BFFF;\">${playerProgress.diamonds}</div>\n                        </div>\n                    </div>\n                    <div class=\"game-title\">NG\u01af\u1edcI QUE<br>\u0110\u1ed0I KH\u00c1NG</div>\n                    <div class=\"btn\" id=\"btn-stage\" style=\"margin-bottom:16px\">V\u01af\u1ee2T \u1ea2I</div>\n                    <div class=\"btn\" id=\"btn-boss\" style=\"margin-bottom:16px; border-color: #ff4444; background: linear-gradient(135deg, rgba(255, 68, 68, 0.3), rgba(0,0,0,0.4))\">CH\u1ebe \u0110\u1ed8 BOSS</div>\n                    <div class=\"btn\" id=\"btn-shop\" style=\"margin-bottom:16px; border-color: #FFD700; background: linear-gradient(135deg, rgba(255, 215, 0, 0.3), rgba(255, 165, 0, 0.3))\">CHI\u00caU M\u1ed8</div>\n                </div>\n            `;\n            document.getElementById('btn-stage').onclick = () => { isStageMode = true; isBossMode = false; showStageSelect(); };\n            document.getElementById('btn-boss').onclick = () => { isStageMode = false; isBossMode = true; showCharSelect(); };\n            document.getElementById('btn-shop').onclick = () => { showSummon(); };\n        }\n\n        function showSummon() {\n            gameState = 'shop'; // Re-use shop state for simplicity or change to 'summon'\n            \n            const featuredSkin = { charId: 'luffy', skinId: 'nika', name: 'LUFFY NIKA', rate: 0.4, portrait: 'luffy_nika_portrait' };\n            const pool = [\n                { charId: 'vuaQuy', skinId: 'beach', name: 'VUA QU\u1ef6 B\u00c3I BI\u1ec2N', rate: 1.2, portrait: 'vua_quy_beach_portrait' },\n                { charId: 'zoro', skinId: 'wano', name: 'ZORO WANO', rate: 1.2, portrait: 'zoro_wano_portrait' },\n                { charId: 'naruto', skinId: 'lucDao', name: 'NARUTO L\u1ee4C \u0110\u1ea0O', rate: 1.2, portrait: 'naruto_luc_dao_portrait' },\n                { charId: 'luffy', skinId: 'gear4', name: 'LUFFY GEAR 4', rate: 1.2, portrait: 'luffy_gear4_portrait' },\n                { charId: 'doraemon', skinId: 'vietnam', name: 'DORAEMON VI\u1ec6T NAM', rate: 1.2, portrait: 'doraemon_vietnam_portrait' },\n                { charId: 'itachi', skinId: 'edo', name: 'ITACHI EDO', rate: 1.2, portrait: 'itachi_edo_portrait' }\n            ];\n\n            uiOverlay.innerHTML = `\n                <div class=\"screen active\" style=\"background:#000; color:#fff; flex-direction:row; padding:0; align-items:stretch; gap:0;\">\n                    \n                    <div style=\"position:absolute; top:12px; right:12px; display:flex; align-items:center; gap:8px; z-index:20;\">\n                        <div style=\"background:rgba(255,215,0,0.2); border:2px solid #FFD700; border-radius:12px; padding:4px 12px; display:flex; align-items:center; gap:6px;\">\n                            <span style=\"font-size:16px;\">\ud83c\udfab</span>\n                            <span style=\"font-family:'Bebas Neue'; font-size:18px; color:#FFD700;\">${playerProgress.exchangeTickets || 0}</span>\n                        </div>\n                        <div style=\"background:rgba(0,191,255,0.2); border:2px solid #00BFFF; border-radius:12px; padding:4px 12px; display:flex; align-items:center; gap:6px;\">\n                            <span style=\"font-size:16px;\">\ud83d\udc8e</span>\n                            <span style=\"font-family:'Bebas Neue'; font-size:18px; color:#00BFFF;\">${playerProgress.diamonds}</span>\n                        </div>\n                        <div id=\"btn-summon-back\" class=\"btn\" style=\"min-width:auto; padding:6px 12px; font-size:14px; min-height:32px;\">X</div>\n                    </div>\n\n                    <div style=\"flex:0.8; display:flex; flex-direction:column; align-items:center; justify-content:center; position:relative; background: radial-gradient(circle at center, #1a1a2e 0%, #000 70%); padding:20px;\">\n                        \n                        <div style=\"position:absolute; left:12px; bottom:100px; display:flex; flex-direction:column; gap:10px;\">\n                            <div style=\"display:flex; align-items:center; gap:8px;\">\n                                <div style=\"width:70px; height:12px; background:#222; border-radius:6px; border:1px solid #444; position:relative; overflow:hidden;\">\n                                    <div style=\"width:40%; height:100%; background:#FFD700;\"></div>\n                                </div>\n                                <span style=\"font-family:'Bebas Neue'; font-size:12px; color:#FFD700;\">100 L\u1ea7n</span>\n                            </div>\n                            <div style=\"display:flex; align-items:center; gap:8px;\">\n                                <div style=\"width:70px; height:12px; background:#222; border-radius:6px; border:1px solid #444; position:relative; overflow:hidden;\">\n                                    <div style=\"width:60%; height:100%; background:#00BFFF;\"></div>\n                                </div>\n                                <span style=\"font-family:'Bebas Neue'; font-size:12px; color:#00BFFF;\">25 L\u1ea7n</span>\n                            </div>\n                        </div>\n\n                        <img src=\"${imageCache[featuredSkin.portrait]?.src}\" style=\"height:360px; object-fit:contain; filter:drop-shadow(0 0 30px #FFD700); margin-bottom:16px;\">\n                        <div style=\"text-align:center;\">\n                            <div style=\"font-family:'Bebas Neue'; font-size:22px; color:#FFD700; text-shadow:0 0 10px #000; margin-bottom:4px;\">${featuredSkin.name}</div>\n                            <div style=\"font-family:'Bebas Neue'; font-size:12px; color:rgba(255,215,0,0.7);\">X\u00e1c su\u1ea5t: ${featuredSkin.rate}%</div>\n                        </div>\n                    </div>\n\n                    <div style=\"flex:1.2; padding:24px 20px; display:flex; flex-direction:column; justify-content:center; overflow-y:auto;\">\n                        <div style=\"display:grid; grid-template-columns:repeat(3, 1fr); gap:12px; margin-bottom:32px;\">\n                            ${pool.map(item => `\n                                <div style=\"display:flex; flex-direction:column; align-items:center;\">\n                                    <img src=\"${imageCache[item.portrait]?.src}\" style=\"width:70px; height:70px; object-fit:contain; background:rgba(255,255,255,0.05); border-radius:8px; padding:6px;\">\n                                    <div style=\"font-family:'Bebas Neue'; font-size:12px; color:#FFD700; margin-top:6px; text-align:center; line-height:1.2; max-height:36px; overflow:hidden;\">${item.name}</div>\n                                    <div style=\"font-size:10px; color:rgba(255,255,255,0.5);\">X\u00e1c su\u1ea5t: ${item.rate}%</div>\n                                </div>\n                            `).join('')}\n                        </div>\n\n                        <div style=\"display:flex; flex-direction:column; gap:12px; justify-content:center;\">\n                            <div class=\"btn\" id=\"btn-summon-1\" style=\"background:linear-gradient(to right, #ff00ff, #800080); border:none; border-radius:20px; padding:10px 20px; display:flex; align-items:center; justify-content:center; gap:8px; font-size:14px; min-height:auto;\">\n                                <span>Quay 1 l\u1ea7n</span>\n                                <span style=\"color:#FFD700;\">\ud83d\udc8e x200</span>\n                            </div>\n                            <div class=\"btn\" id=\"btn-summon-10\" style=\"background:linear-gradient(to right, #ff00ff, #800080); border:none; border-radius:20px; padding:10px 20px; display:flex; align-items:center; justify-content:center; gap:8px; font-size:14px; min-height:auto;\">\n                                <span>Quay 10 l\u1ea7n</span>\n                                <span style=\"color:#FFD700;\">\ud83d\udc8e x2000</span>\n                            </div>\n                            <div class=\"btn\" id=\"btn-open-exchange\" style=\"background:linear-gradient(to right, #FFD700, #DAA520); color:#000; border:none; border-radius:20px; padding:10px 20px; display:flex; align-items:center; justify-content:center; gap:8px; font-size:14px; min-height:auto; margin-top:8px;\">\n                                <span>Trao \u0111\u1ed5i Skin</span>\n                                <span style=\"font-size:16px;\">\ud83c\udfab</span>\n                            </div>\n                            <div style=\"margin-top:16px; padding:14px; border:2px solid rgba(0,191,255,0.55); border-radius:16px; background:rgba(0,191,255,0.08);\">\n                                <div style=\"font-family:'Bebas Neue'; font-size:18px; color:#00BFFF; text-align:center; margin-bottom:8px;\">NH\u1eacP M\u00c3 QU\u00c0 T\u1eb6NG</div>\n                                <div style=\"display:flex; gap:8px; align-items:stretch;\">\n                                    <input id=\"gift-code-input\" type=\"text\" maxlength=\"32\" autocomplete=\"off\" placeholder=\"Nh\u1eadp m\u00e3 code\" style=\"flex:1; min-width:0; border:2px solid rgba(255,255,255,0.25); border-radius:10px; background:rgba(0,0,0,0.45); color:#fff; padding:10px; font-family:Inter; font-size:14px; text-transform:uppercase;\">\n                                    <div class=\"btn\" id=\"btn-redeem-code\" style=\"min-width:110px; padding:10px 12px; font-size:16px; min-height:auto;\">NH\u1eacN QU\u00c0</div>\n                                </div>\n                                <div style=\"font-size:11px; color:rgba(255,255,255,0.55); text-align:center; margin-top:7px;\">M\u1ed7i m\u00e3 ch\u1ec9 s\u1eed d\u1ee5ng \u0111\u01b0\u1ee3c m\u1ed9t l\u1ea7n.</div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            `;\n\n            document.getElementById('btn-summon-back').onclick = () => showMenu();\n            document.getElementById('btn-summon-1').onclick = () => performSummon(1);\n            document.getElementById('btn-summon-10').onclick = () => performSummon(10);\n            document.getElementById('btn-open-exchange').onclick = () => showSkinExchange();\n            document.getElementById('btn-redeem-code').onclick = redeemGiftCode;\n            document.getElementById('gift-code-input').addEventListener('keydown', (event) => {\n                if (event.key === 'Enter') redeemGiftCode();\n            });\n\n            function redeemGiftCode() {\n                const input = document.getElementById('gift-code-input');\n                const enteredCode = (input.value || '').trim().toUpperCase();\n                const giftCodes = {\n                    'CHUCMUNGDAT170K': 1700,\n                    'DENBUVUOTAI': 3333\n                };\n\n                if (!enteredCode) {\n                    showModal('H\u00e3y nh\u1eadp m\u00e3 qu\u00e0 t\u1eb7ng tr\u01b0\u1edbc nh\u00e9!');\n                    return;\n                }\n                const reward = giftCodes[enteredCode];\n                if (reward === undefined) {\n                    showModal('M\u00e3 code kh\u00f4ng h\u1ee3p l\u1ec7 ho\u1eb7c \u0111\u00e3 h\u1ebft h\u1ea1n.');\n                    return;\n                }\n                if (!Array.isArray(playerProgress.redeemedCodes)) playerProgress.redeemedCodes = [];\n                if (playerProgress.redeemedCodes.includes(enteredCode)) {\n                    showModal('B\u1ea1n \u0111\u00e3 s\u1eed d\u1ee5ng m\u00e3 n\u00e0y r\u1ed3i!');\n                    return;\n                }\n\n                playerProgress.redeemedCodes.push(enteredCode);\n                addDiamonds(reward);\n                savePlayerProgress();\n                showModal(`Ch\u00fac m\u1eebng! B\u1ea1n nh\u1eadn \u0111\u01b0\u1ee3c \ud83d\udc8e+${reward}.`);\n                showSummon();\n            }\n\n            function showSkinExchange() {\n                const exchangeOverlay = document.createElement('div');\n                exchangeOverlay.style.cssText = 'position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.95); z-index:200; display:flex; flex-direction:column; align-items:center; justify-content:center; padding:20px;';\n                \n                const exchangeOptions = [\n                    { charId: 'luffy', skinId: 'nika', name: 'Luffy Nika', cost: 50, portrait: 'luffy_nika_portrait' },\n                    { charId: 'vuaQuy', skinId: 'beach', name: 'Vua Qu\u1ef7 Bi\u1ec3n', cost: 40, portrait: 'vua_quy_beach_portrait' },\n                    { charId: 'zoro', skinId: 'wano', name: 'Zoro Wano', cost: 40, portrait: 'zoro_wano_portrait' },\n                    { charId: 'naruto', skinId: 'lucDao', name: 'Naruto L\u1ee5c \u0110\u1ea1o', cost: 40, portrait: 'naruto_luc_dao_portrait' },\n                    { charId: 'luffy', skinId: 'gear4', name: 'Luffy Gear 4', cost: 40, portrait: 'luffy_gear4_portrait' },\n                    { charId: 'doraemon', skinId: 'vietnam', name: 'Doraemon Vi\u1ec7t Nam', cost: 40, portrait: 'doraemon_vietnam_portrait' },\n                    { charId: 'itachi', skinId: 'edo', name: 'Itachi Edo', cost: 40, portrait: 'itachi_edo_portrait' }\n                ];\n\n                exchangeOverlay.innerHTML = `\n                    <div style=\"font-family:'Bebas Neue'; font-size:40px; color:#FFD700; margin-bottom:10px;\">TI\u1ec6M TRAO \u0110\u1ed4I SKIN</div>\n                    <div style=\"background:rgba(255,215,0,0.2); border:2px solid #FFD700; border-radius:12px; padding:6px 16px; display:flex; align-items:center; gap:8px; margin-bottom:30px;\">\n                        <span style=\"font-size:20px;\">\ud83c\udfab</span>\n                        <span style=\"font-family:'Bebas Neue'; font-size:24px; color:#FFD700;\">V\u00e9 hi\u1ec7n c\u00f3: ${playerProgress.exchangeTickets || 0}</span>\n                    </div>\n\n                    <div style=\"display:grid; grid-template-columns:repeat(3, 1fr); gap:20px; width:100%; max-width:600px; margin-bottom:40px;\">\n                        ${exchangeOptions.map((opt, idx) => {\n                            const owned = isSkinUnlocked(opt.charId, opt.skinId);\n                            const canAfford = (playerProgress.exchangeTickets || 0) >= opt.cost;\n                            return `\n                                <div style=\"background:rgba(255,255,255,0.05); border:2px solid ${owned ? '#4CAF50' : '#444'}; border-radius:12px; padding:15px; display:flex; flex-direction:column; align-items:center; position:relative;\">\n                                    <img src=\"${imageCache[opt.portrait]?.src}\" style=\"width:90px; height:90px; object-fit:contain; margin-bottom:10px; ${owned ? '' : 'filter:grayscale(0.5)'}\">\n                                    <div style=\"font-family:'Bebas Neue'; font-size:16px; color:#fff; text-align:center;\">${opt.name}</div>\n                                    <div style=\"font-family:'Bebas Neue'; font-size:18px; color:#FFD700; margin-top:5px;\">\ud83c\udfab x${opt.cost}</div>\n                                    <div class=\"btn\" id=\"exchange-btn-${idx}\" style=\"min-width:auto; width:100%; padding:8px; font-size:16px; margin-top:10px; min-height:auto; ${owned ? 'background:#4CAF50; opacity:0.7;' : (canAfford ? 'background:#FFD700; color:#000;' : 'opacity:0.4; pointer-events:none;')}\">\n                                        ${owned ? '\u0110\u00c3 S\u1ede H\u1eeeU' : '\u0110\u1ed4I NGAY'}\n                                    </div>\n                                </div>\n                            `;\n                        }).join('')}\n                    </div>\n\n                    <div class=\"btn\" id=\"btn-close-exchange\" style=\"padding:10px 40px; font-size:20px;\">\u0110\u00d3NG</div>\n                `;\n\n                document.body.appendChild(exchangeOverlay);\n\n                exchangeOptions.forEach((opt, idx) => {\n                    const btn = document.getElementById(`exchange-btn-${idx}`);\n                    if (btn && !isSkinUnlocked(opt.charId, opt.skinId) && (playerProgress.exchangeTickets || 0) >= opt.cost) {\n                        btn.onclick = () => {\n                            playerProgress.exchangeTickets -= opt.cost;\n                            unlockSkin(opt.charId, opt.skinId);\n                            savePlayerProgress();\n                            document.body.removeChild(exchangeOverlay);\n                            showModal(`Ch\u00fac m\u1eebng! B\u1ea1n \u0111\u00e3 s\u1edf h\u1eefu Skin ${opt.name}! \u2728`);\n                            showSummon(); // Refresh count in summon screen\n                        };\n                    }\n                });\n\n                document.getElementById('btn-close-exchange').onclick = () => {\n                    document.body.removeChild(exchangeOverlay);\n                };\n            }\n\n            function performSummon(count) {\n                const cost = count * 200;\n                if (playerProgress.diamonds < cost) {\n                    showModal('Kh\u00f4ng \u0111\u1ee7 Kim C\u01b0\u01a1ng! \ud83d\udc8e');\n                    return;\n                }\n\n                spendDiamonds(cost);\n                const results = [];\n                // Use a local copy of owned skins to ensure no duplicates within the same 10-pull\n                const workingUnlocked = JSON.parse(JSON.stringify(playerProgress.unlockedSkins));\n\n                for(let i=0; i<count; i++) {\n                    const rand = Math.random() * 100;\n                    let currentRate = 0;\n                    let rolledSkin = null;\n                    \n                    // Check featured\n                    currentRate += featuredSkin.rate;\n                    if (rand < currentRate) {\n                        rolledSkin = featuredSkin;\n                    } else {\n                        // Check pool\n                        for(const item of pool) {\n                            currentRate += item.rate;\n                            if (rand < currentRate) {\n                                rolledSkin = item;\n                                break;\n                            }\n                        }\n                    }\n\n                    if (rolledSkin) {\n                        // We rolled a skin! Check if it's already owned\n                        const isOwned = workingUnlocked[rolledSkin.charId]?.includes(rolledSkin.skinId);\n                        \n                        if (isOwned) {\n                            // Find another unowned skin from the pool\n                            const allSkins = [featuredSkin, ...pool];\n                            const unowned = allSkins.filter(s => !workingUnlocked[s.charId]?.includes(s.skinId));\n                            \n                            if (unowned.length > 0) {\n                                // Replacement roll from unowned set\n                                rolledSkin = unowned[Math.floor(Math.random() * unowned.length)];\n                                results.push(rolledSkin);\n                                if (!workingUnlocked[rolledSkin.charId]) workingUnlocked[rolledSkin.charId] = [];\n                                workingUnlocked[rolledSkin.charId].push(rolledSkin.skinId);\n                            } else {\n                                // All possible skins already owned - fallback to ticket\n                                results.push({ name: 'V\u00e9 trao \u0111\u1ed5i', isTicket: true });\n                                playerProgress.exchangeTickets = (playerProgress.exchangeTickets || 0) + 1;\n                            }\n                        } else {\n                            // New skin unlock\n                            results.push(rolledSkin);\n                            if (!workingUnlocked[rolledSkin.charId]) workingUnlocked[rolledSkin.charId] = [];\n                            workingUnlocked[rolledSkin.charId].push(rolledSkin.skinId);\n                        }\n                    } else {\n                        // No skin rolled\n                        results.push({ name: 'V\u00e9 trao \u0111\u1ed5i', isTicket: true });\n                        playerProgress.exchangeTickets = (playerProgress.exchangeTickets || 0) + 1;\n                    }\n                }\n                \n                // Process all results to unlock skins and save progress\n                results.forEach(res => {\n                    if (!res.isTicket) unlockSkin(res.charId, res.skinId);\n                });\n                \n                savePlayerProgress();\n                showSummonResults(results);\n            }\n\n            function showSummonResults(results) {\n                const resultOverlay = document.createElement('div');\n                resultOverlay.style.cssText = 'position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.9); z-index:100; display:flex; flex-direction:column; align-items:center; justify-content:center;';\n                \n                let hasNewSkin = false;\n                const itemsHtml = results.map(res => {\n                    if (!res.isTicket) {\n                        hasNewSkin = true;\n                        return `\n                            <div style=\"text-align:center; padding:10px; border:2px solid #FFD700; border-radius:10px; background:rgba(255,215,0,0.1);\">\n                                <img src=\"${imageCache[res.portrait]?.src}\" style=\"width:80px; height:80px; object-fit:contain;\">\n                                <div style=\"font-family:'Bebas Neue'; font-size:14px; color:#FFD700; margin-top:5px;\">${res.name}</div>\n                                <div style=\"font-size:10px; color:#4CAF50;\">M\u1edaI!</div>\n                            </div>\n                        `;\n                    } else {\n                        return `\n                            <div style=\"text-align:center; padding:10px; border:1px solid #FFD700; border-radius:10px; background:rgba(255,215,0,0.05); color:#FFD700;\">\n                                <div style=\"font-size:40px;\">\ud83c\udfab</div>\n                                <div style=\"font-family:'Bebas Neue'; font-size:14px;\">V\u00c9 TRAO \u0110\u1ed4I</div>\n                                <div style=\"font-size:10px;\">+1</div>\n                            </div>\n                        `;\n                    }\n                }).join('');\n\n                resultOverlay.innerHTML = `\n                    <div style=\"font-family:'Bebas Neue'; font-size:48px; color:#FFD700; margin-bottom:40px; text-shadow:0 0 20px #FFD700;\">K\u1ebeT QU\u1ea2 CHI\u00caU M\u1ed8</div>\n                    <div style=\"display:grid; grid-template-columns:repeat(5, 1fr); gap:15px; max-width:800px; margin-bottom:40px;\">\n                        ${itemsHtml}\n                    </div>\n                    <div class=\"btn\" id=\"btn-close-summon\" style=\"padding:15px 60px;\">X\u00c1C NH\u1eacN</div>\n                `;\n\n                document.body.appendChild(resultOverlay);\n                document.getElementById('btn-close-summon').onclick = () => {\n                    document.body.removeChild(resultOverlay);\n                    showSummon(); // Refresh summon screen to update diamond count\n                };\n\n                if (hasNewSkin) playSound('victory_sfx', 0.6);\n            }\n        }\n\n\n        function showStageSelect() {\n            gameState = 'stageSelect';\n            uiOverlay.innerHTML = `\n                <div class=\"screen active\" style=\"padding:16px;box-sizing:border-box;\">\n                    <div class=\"game-title\" style=\"font-size:48px;margin-bottom:32px\">CH\u1eccN \u1ea2I</div>\n                    \n                    <div class=\"char-grid\" style=\"grid-template-columns: repeat(4, 1fr); gap: 12px; max-height: 600px; overflow-y: auto;\">\n                        ${gameStages.map(stage => {\n                            const isUnlocked = stage.id <= playerProgress.unlockedStages;\n                            return `\n                                <div class=\"char-mini-card ${isUnlocked ? '' : 'locked'}\" id=\"stage-${stage.id}\" style=\"${isUnlocked ? '' : 'opacity:0.4; filter:grayscale(100%);'} position:relative;\">\n                                    <div style=\"font-family:'Bebas Neue'; font-size:32px; color:#fff; margin-bottom:4px;\">${stage.id}</div>\n                                    <div class=\"char-mini-name\" style=\"font-size:12px; height: 30px; display:flex; align-items:center; justify-content:center;\">${stage.name}</div>\n                                    ${!isUnlocked ? '<div style=\"position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:24px;\">\ud83d\udd12</div>' : ''}\n                                </div>\n                            `;\n                        }).join('')}\n                    </div>\n\n                    <div style=\"display:flex; gap:16px; margin-top:32px;\">\n                        <div class=\"btn\" id=\"stage-btn-back\" style=\"min-width:140px; font-size:20px; padding:12px 24px;\">QUAY L\u1ea0I</div>\n                    </div>\n                </div>\n            `;\n\n            gameStages.forEach(stage => {\n                const el = document.getElementById(`stage-${stage.id}`);\n                if (el && stage.id <= playerProgress.unlockedStages) {\n                    el.onclick = () => {\n                        currentStageId = stage.id;\n                        const stageData = gameStages.find(s => s.id === currentStageId);\n                        selectedOpponentChar = stageData.opponent;\n                        selectedMap = stageData.map;\n                        showCharSelect();\n                    };\n                }\n            });\n\n            document.getElementById('stage-btn-back').onclick = () => showMenu();\n        }\n\n        function showCharSelect() {\n            gameState = 'charSelect';\n            selectedPlayerChar = null;\n            if (!isStageMode) {\n                selectedOpponentChar = null;\n                selectedOpponentSkin = 'default';\n            }\n            selectedPlayerSkin = 'default';\n            selectionStep = 0;\n            renderSelectionScreen();\n        }\n\n        // Boss mode no longer asks the player to choose a base-form boss.\n        // After choosing P1, the player picks one of the available character skins.\n        function showBossSkinSelect() {\n            gameState = 'charSelect';\n            selectionStep = 1;\n            selectionSubStep = 'skin';\n\n            const selectedBoss = bossSkinRoster.find(skin =>\n                skin.charId === selectedOpponentChar && skin.skinId === selectedOpponentSkin\n            );\n\n            uiOverlay.innerHTML = `\n                <div class=\"screen active\" style=\"padding:16px;box-sizing:border-box;\">\n                    <div class=\"sel-tabs\">\n                        <div class=\"sel-tab active\">SKIN BOSS</div>\n                    </div>\n                    <div class=\"game-title\" style=\"font-size:40px;margin-bottom:24px\">CH\u1eccN SKIN \u0110\u1ed0I \u0110\u1ea6U</div>\n                    <div class=\"selection-slots\">\n                        <div class=\"slot ready\">\n                            <img src=\"${getSelectionPortraitUrl(selectedPlayerChar, selectedPlayerSkin) || ''}\">\n                            <div class=\"slot-label\">P1: ${getCharacterDisplayName(selectedPlayerChar)}</div>\n                        </div>\n                        <div class=\"vs-text\">VS</div>\n                        <div class=\"slot ${selectedBoss ? 'active' : ''}\">\n                            ${selectedBoss ? `<img src=\"${imageCache[selectedBoss.portrait]?.src || ''}\">` : '<div style=\"font-size:48px;color:rgba(255,255,255,0.1)\">?</div>'}\n                            <div class=\"slot-label\">BOSS: ${selectedBoss ? selectedBoss.name : 'CH\u1eccN SKIN'}</div>\n                        </div>\n                    </div>\n                    <div class=\"char-grid\" style=\"grid-template-columns:repeat(3,1fr);\">\n                        ${bossSkinRoster.map(skin => `\n                            <div class=\"char-mini-card ${selectedBoss && selectedBoss.charId === skin.charId && selectedBoss.skinId === skin.skinId ? 'selected' : ''}\" id=\"boss-skin-${skin.charId}-${skin.skinId}\" style=\"border-color:${skin.color};\">\n                                <img src=\"${imageCache[skin.portrait]?.src || ''}\" alt=\"${skin.name}\">\n                                <div class=\"char-mini-name\" style=\"color:${skin.color}\">${skin.name}</div>\n                                <div style=\"font-size:11px;color:#FFD700;margin-top:3px;\">BOSS SKIN</div>\n                            </div>\n                        `).join('')}\n                    </div>\n                    <div style=\"display:flex;gap:16px;margin-top:24px;\">\n                        <div class=\"btn\" id=\"boss-skin-back\" style=\"min-width:140px;font-size:20px;padding:12px 24px;\">QUAY L\u1ea0I</div>\n                        <div class=\"btn\" id=\"boss-skin-start\" style=\"min-width:180px;opacity:${selectedBoss ? '1' : '0.5'};pointer-events:${selectedBoss ? 'auto' : 'none'};\">B\u1eaeT \u0110\u1ea6U</div>\n                    </div>\n                </div>\n            `;\n\n            bossSkinRoster.forEach(skin => {\n                const el = document.getElementById(`boss-skin-${skin.charId}-${skin.skinId}`);\n                if (el) {\n                    el.onclick = () => {\n                        selectedOpponentChar = skin.charId;\n                        selectedOpponentSkin = skin.skinId;\n                        showBossSkinSelect();\n                    };\n                }\n            });\n\n            document.getElementById('boss-skin-back').onclick = () => {\n                selectionStep = 0;\n                selectionSubStep = 'char';\n                renderSelectionScreen();\n            };\n            document.getElementById('boss-skin-start').onclick = () => {\n                selectedMap = 'arena_background';\n                showMapSelect();\n            };\n        }\n\n        function getCharacterDisplayName(type) {\n            const names = {\n                batBai: 'B\u1ea4T B\u1ea0I', bongDem: 'B\u00d3NG \u0110\u00caM', itachi: 'ITACHI', vuaQuy: 'VUA QU\u1ef6',\n                hashirama: 'HASHIRAMA', obito: 'OBITO', garp: 'GARP', poPanda: 'PO PANDA',\n                doraemon: 'DORAEMON', enel: 'ENEL', zoro: 'ZORO', naruto: 'NARUTO', yuji: 'YUJI',\n                tanjiro: 'TANJIRO', shadowGarden: 'SHADOW', rimuru: 'RIMURU', yuta: 'YUTA',\n                sasuke: 'SASUKE', madara: 'MADARA', luffy: 'LUFFY', sukuna: 'SUKUNA',\n                gojo: 'GOJO', saitama: 'SAITAMA', goku: 'GOKU'\n            };\n            return names[type] || type || 'PENDING';\n        }\n\n        function getSelectionPortraitUrl(type, skin = 'default') {\n            if (!type) return null;\n            const prefix = getAssetPrefix(type);\n            const skinPortrait = skin && skin !== 'default' ? imageCache[prefix + '_' + skin + '_portrait'] : null;\n            const portrait = skinPortrait || imageCache[prefix + '_portrait'];\n            return portrait ? portrait.src : null;\n        }\n\n        function renderSelectionScreen() {\n            const title = selectionStep === 0 ? \"CH\u1eccN NH\u00c2N V\u1eacT P1\" : \"CH\u1eccN \u0110\u1ed0I TH\u1ee6 CPU\";\n            const btnText = selectionStep === 0 ? (isBossMode ? \"CH\u1eccN SKIN BOSS\" : \"TI\u1ebeP THEO\") : \"B\u1eaeT \u0110\u1ea6U\";\n\n            const getPortraitUrl = getSelectionPortraitUrl;\n\n            const p1Portrait = getPortraitUrl(selectedPlayerChar, selectedPlayerSkin);\n            const p2Portrait = getPortraitUrl(selectedOpponentChar, selectedOpponentSkin);\n\n            const characters = [\n                { id: 'batBai', name: 'B\u1ea4T B\u1ea0I', color: '#4A90E2' },\n                { id: 'bongDem', name: 'B\u00d3NG \u0110\u00caM', color: '#9B59B6' },\n                { id: 'itachi', name: 'ITACHI', color: '#FF4444' },\n                { id: 'vuaQuy', name: 'VUA QU\u1ef6', color: '#8B0000' },\n                { id: 'hashirama', name: 'HASHIRAMA', color: '#228B22' },\n                { id: 'obito', name: 'OBITO', color: '#4A90E2' },\n                { id: 'garp', name: 'GARP', color: '#fff' },\n                { id: 'poPanda', name: 'PO PANDA', color: '#fff' },\n                { id: 'doraemon', name: 'DORAEMON', color: '#4A90E2' },\n                { id: 'enel', name: 'ENEL', color: '#00BFFF' },\n                { id: 'zoro', name: 'ZORO', color: '#228B22' },\n                { id: 'naruto', name: 'NARUTO', color: '#FFA500' },\n                { id: 'yuji', name: 'YUJI', color: '#FF4444' },\n                { id: 'tanjiro', name: 'TANJIRO', color: '#FF0000' },\n                { id: 'shadowGarden', name: 'SHADOW', color: '#9370DB' },\n                { id: 'rimuru', name: 'RIMURU', color: '#00BFFF' },\n                { id: 'yuta', name: 'YUTA', color: '#fff' },\n                { id: 'sasuke', name: 'SASUKE', color: '#A020F0' },\n                { id: 'madara', name: 'MADARA', color: '#4A90E2' },\n                { id: 'luffy', name: 'LUFFY', color: '#FFD700' },\n                { id: 'sukuna', name: 'SUKUNA', color: '#FF4444' },\n                { id: 'gojo', name: 'GOJO', color: '#B0E0E6' },\n                { id: 'saitama', name: 'SAITAMA', color: '#FFD700' },\n                { id: 'goku', name: 'GOKU', color: '#FFA500' }\n            ];\n\n            uiOverlay.innerHTML = `\n                <div class=\"screen active\" style=\"padding:16px;box-sizing:border-box;\">\n                    <div class=\"sel-tabs\">\n                        <div class=\"sel-tab ${selectionSubStep === 'char' ? 'active' : ''}\" id=\"tab-char\">NH\u00c2N V\u1eacT</div>\n                        <div class=\"sel-tab ${selectionSubStep === 'skin' ? 'active' : ''}\" id=\"tab-skin\">SKIN</div>\n                    </div>\n\n                    <div class=\"game-title\" style=\"font-size:40px;margin-bottom:24px\">${title}</div>\n                    \n                    <div class=\"selection-slots\">\n                        <div class=\"slot ${selectionStep === 0 ? 'active' : (selectedPlayerChar ? 'ready' : '')}\" id=\"slot-p1\">\n                            ${p1Portrait ? `<img src=\"${p1Portrait}\">` : '<div style=\"font-size:48px;color:rgba(255,255,255,0.1)\">?</div>'}\n                            <div class=\"slot-label\">P1: ${selectedPlayerChar ? characters.find(c => c.id === selectedPlayerChar).name : 'PENDING'}</div>\n                        </div>\n                        <div class=\"vs-text\">VS</div>\n                        <div class=\"slot ${selectionStep === 1 ? 'active' : (selectedOpponentChar ? 'ready' : '')}\" id=\"slot-p2\">\n                            ${p2Portrait ? `<img src=\"${p2Portrait}\">` : '<div style=\"font-size:48px;color:rgba(255,255,255,0.1)\">?</div>'}\n                            <div class=\"slot-label\">${isBossMode ? 'BOSS SKIN' : 'CPU'}: ${selectedOpponentChar ? getCharacterDisplayName(selectedOpponentChar) : 'PENDING'}</div>\n                        </div>\n                    </div>\n\n                    <div class=\"char-grid\">\n                        ${selectionSubStep === 'char' ? \n                            characters.map(char => {\n                                const isShadow = char.id === 'shadowGarden';\n                                const isDoraemon = char.id === 'doraemon';\n                                let specialStyle = isShadow ? 'box-shadow: 0 0 10px rgba(147, 112, 219, 0.5); border-color: rgba(147, 112, 219, 0.3);' : '';\n                                if (isDoraemon) specialStyle = 'box-shadow: 0 0 20px rgba(74, 144, 226, 0.9); border: 2px solid #4A90E2; background: rgba(74, 144, 226, 0.2);';\n                                \n                                return `\n                                <div class=\"char-mini-card ${(selectionStep === 0 ? selectedPlayerChar : selectedOpponentChar) === char.id ? 'selected' : ''}\" id=\"card-${char.id}\" style=\"${specialStyle}\">\n                                    <img src=\"${getPortraitUrl(char.id)}\" alt=\"${char.name}\">\n                                    <div class=\"char-mini-name\" style=\"color:${char.color}\">${char.name}</div>\n                                </div>\n                            `}).join('') :\n                            // Skin grid\n                            (() => {\n                                const currentChar = selectionStep === 0 ? selectedPlayerChar : selectedOpponentChar;\n                                if (!currentChar) return `<div style=\"color:rgba(255,255,255,0.5); font-family:'Bebas Neue'; font-size:24px; grid-column: span 4; text-align:center; padding: 40px;\">H\u00e3y ch\u1ecdn nh\u00e2n v\u1eadt tr\u01b0\u1edbc</div>`;\n                                const skins = charSkins[currentChar] || [{ id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh', portrait: getAssetPrefix(currentChar) + '_portrait' }];\n                                return skins.map(skin => {\n                                    const isUnlocked = isSkinUnlocked(currentChar, skin.id);\n                                    const lockedStyle = !isUnlocked ? 'opacity:0.4;filter:grayscale(100%);position:relative;' : '';\n                                    \n                                    return `\n                                    <div class=\"char-mini-card ${(selectionStep === 0 ? selectedPlayerSkin : selectedOpponentSkin) === skin.id ? 'selected' : ''}\" id=\"skin-${skin.id}\" style=\"${lockedStyle}\">\n                                        <img src=\"${imageCache[skin.portrait] ? imageCache[skin.portrait].src : ''}\" alt=\"${skin.name}\">\n                                        <div class=\"char-mini-name\">${skin.name}</div>\n                                        ${!isUnlocked ? '<div style=\"position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:32px;\">\ud83d\udd12</div>' : ''}\n                                    </div>\n                                `}).join('');\n                            })()\n                        }\n                    </div>\n\n                    <div style=\"display:flex; gap:16px; margin-top:24px;\">\n                        <div class=\"btn\" id=\"btn-back\" style=\"min-width:140px; font-size:20px; padding:12px 24px;\">QUAY L\u1ea0I</div>\n                        <div class=\"btn\" id=\"btn-action\" style=\"min-width:180px; opacity:${(selectionStep === 0 ? selectedPlayerChar : selectedOpponentChar) ? '1' : '0.5'}; pointer-events:${(selectionStep === 0 ? selectedPlayerChar : selectedOpponentChar) ? 'auto' : 'none'};\">${btnText}</div>\n                    </div>\n                </div>\n            `;\n\n            document.getElementById('tab-char').onclick = () => { selectionSubStep = 'char'; renderSelectionScreen(); };\n            document.getElementById('tab-skin').onclick = () => { selectionSubStep = 'skin'; renderSelectionScreen(); };\n\n            if (selectionSubStep === 'char') {\n                characters.forEach(char => {\n                    const el = document.getElementById(`card-${char.id}`);\n                    if (el) {\n                        el.onclick = () => {\n                            if (selectionStep === 0) {\n                                selectedPlayerChar = char.id;\n                                selectedPlayerSkin = 'default';\n                            } else {\n                                selectedOpponentChar = char.id;\n                                selectedOpponentSkin = 'default';\n                            }\n                            renderSelectionScreen();\n                        };\n                    }\n                });\n            } else {\n                            // Skin selection clicks\n                const currentChar = selectionStep === 0 ? selectedPlayerChar : selectedOpponentChar;\n                if (currentChar) {\n                    const skins = charSkins[currentChar] || [{ id: 'default', name: 'M\u1eb7c \u0111\u1ecbnh' }];\n                    skins.forEach(skin => {\n                        const el = document.getElementById(`skin-${skin.id}`);\n                        if (el) {\n                            const isUnlocked = isSkinUnlocked(currentChar, skin.id);\n                            if (isUnlocked) {\n                                el.onclick = () => {\n                                    if (selectionStep === 0) selectedPlayerSkin = skin.id;\n                                    else selectedOpponentSkin = skin.id;\n                                    renderSelectionScreen();\n                                };\n                            } else {\n                                el.onclick = () => {\n                                    showModal('Skin n\u00e0y ch\u01b0a \u0111\u01b0\u1ee3c m\u1edf kh\u00f3a! H\u00e3y mua trong c\u1eeda h\u00e0ng. \ud83d\udd12');\n                                };\n                            }\n                        }\n                    });\n                }\n            }\n\n            document.getElementById('btn-action').onclick = () => {\n                if (selectionStep === 0) {\n                    if (isStageMode) {\n                        startMatch();\n                    } else if (isBossMode) {\n                        showBossSkinSelect();\n                    } else {\n                        selectionStep = 1;\n                        renderSelectionScreen();\n                    }\n                } else {\n                    showMapSelect();\n                }\n            };\n            document.getElementById('btn-back').onclick = () => {\n                if (selectionStep === 1) {\n                    selectionStep = 0;\n                    renderSelectionScreen();\n                } else {\n                    if (isStageMode) showStageSelect();\n                    else showMenu();\n                }\n            };\n        }\n        function showMapSelect() {\n            gameState = 'mapSelect';\n            uiOverlay.innerHTML = `\n                <div class=\"screen active\" style=\"padding:16px;box-sizing:border-box;\">\n                    <div class=\"game-title\" style=\"font-size:48px;margin-bottom:32px\">CH\u1eccN B\u1ea2N \u0110\u1ed2</div>\n                    \n                    <div class=\"char-grid\" style=\"grid-template-columns: repeat(2, 1fr); gap: 20px;\">\n                        ${gameMaps.map(map => `\n                            <div class=\"char-card ${selectedMap === map.id ? 'selected' : ''}\" id=\"map-${map.id}\" style=\"width: 100%; height: auto; aspect-ratio: 16/9;\">\n                                <img src=\"${imageCache[map.icon] ? imageCache[map.icon].src : ''}\" style=\"width:100%; height:120px; border-radius:8px; object-fit:cover;\">\n                                <div class=\"char-name\" style=\"font-size:18px; margin-top:8px;\">${map.name}</div>\n                            </div>\n                        `).join('')}\n                    </div>\n\n                    <div style=\"display:flex; gap:16px; margin-top:48px;\">\n                        <div class=\"btn\" id=\"map-btn-back\" style=\"min-width:140px; font-size:20px; padding:12px 24px;\">QUAY L\u1ea0I</div>\n                        <div class=\"btn\" id=\"map-btn-start\" style=\"min-width:180px;\">B\u1eaeT \u0110\u1ea6U</div>\n                    </div>\n                </div>\n            `;\n\n            gameMaps.forEach(map => {\n                const el = document.getElementById(`map-${map.id}`);\n                if (el) {\n                    el.onclick = () => {\n                        selectedMap = map.id;\n                        showMapSelect();\n                    };\n                }\n            });\n\n            document.getElementById('map-btn-back').onclick = () => {\n                if (isBossMode) {\n                    showBossSkinSelect();\n                } else {\n                    showCharSelect();\n                    selectionStep = 1; // Return to opponent select\n                    renderSelectionScreen();\n                }\n            };\n            document.getElementById('map-btn-start').onclick = () => {\n                startMatch();\n            };\n        }\n\n        function startMatch() {\n            const types = ['batBai', 'bongDem', 'itachi', 'luffy', 'madara', 'sasuke', 'sukuna', 'gojo', 'saitama', 'vuaQuy'];\n            let opponentType = selectedOpponentChar;\n            allies = [];\n            \n            if (isBossMode) {\n                // Add 2 AI allies\n                const allyCount = 2;\n                for (let i = 0; i < allyCount; i++) {\n                    let allyType;\n                    do {\n                        allyType = types[Math.floor(Math.random() * types.length)];\n                    } while (allyType === selectedPlayerChar); \n                    const ally = createFighter(allyType, 100 + Math.random() * 100, true, true);\n                    allies.push(ally);\n                }\n            }\n\n            player = createFighter(selectedPlayerChar, 180, true, false, false, selectedPlayerSkin);\n            opponent = createFighter(opponentType, 540, false, true, isBossMode, selectedOpponentSkin);\n\n            // Some skin variants are transformation forms whose dedicated combat\n            // sprite is shown while awakened. Keep them active for the whole boss fight.\n            if (isBossMode && opponent.type === 'luffy' && (opponent.skin === 'nika' || opponent.skin === 'gear4')) {\n                opponent.isAwakened = true;\n                opponent.awakenedTimer = 999999;\n            }\n            \n            // Reduce enemy strength in Stage mode to make it easier as requested\n            if (isStageMode) {\n                opponent.health = Math.floor(opponent.health * 0.85); // 15% less health\n                opponent.maxHealth = opponent.health;\n                opponent.damageMultiplier = 0.85; // 15% less damage\n                \n                // Add a small health boost to player in stage mode\n                player.health = Math.floor(player.health * 1.1);\n                player.maxHealth = player.health;\n            }\n            projectiles = [];\n            effects = [];\n            damageNumbers = [];\n            matchTimer = config.settings.roundTime;\n            screenShake = 0;\n\n            stopMusic();\n            gameState = 'countdown';\n            countdownTimer = 3;\n            countdownText = '3';\n            uiOverlay.innerHTML = '';\n        }\n\n        let musicNode = null;\n        function playMusic(id) {\n            musicNode = playSound(id, 0.3, true);\n        }\n        function stopMusic() {\n            if (musicNode) {\n                try { musicNode.source.stop(); } catch(e) {}\n                musicNode = null;\n            }\n        }\n\n        function showResult(won) {\n            gameState = 'result';\n            stopMusic();\n            if (won) {\n                if (player.health > 0) {\n                    player.state = 'victory';\n                    player.stateTimer = 99;\n                }\n                for (const ally of allies) {\n                    if (ally.health > 0) {\n                        ally.state = 'victory';\n                        ally.stateTimer = 99;\n                    }\n                }\n                resultText = 'CHI\u1ebeN TH\u1eaeNG!';\n                resultColor = '#4CAF50';\n                playSound('victory_sfx', 0.5);\n                \n                // Boss skin victories give a larger fixed reward.\n                const diamondsEarned = isBossMode ? 500 : 100;\n                addDiamonds(diamondsEarned);\n\n                // Stage progression\n                if (isStageMode && currentStageId === playerProgress.unlockedStages) {\n                    playerProgress.unlockedStages = Math.min(gameStages.length, playerProgress.unlockedStages + 1);\n                    savePlayerProgress();\n                }\n            } else {\n                opponent.state = 'victory';\n                opponent.stateTimer = 99;\n                resultText = 'TH\u1ea4T B\u1ea0I!';\n                resultColor = '#F44336';\n                playSound('defeat_sfx', 0.5);\n            }\n\n            setTimeout(() => {\n                const rewardsText = won ? `\n                    <div style=\"font-family:'Bebas Neue';font-size:24px;color:#fff;margin-bottom:24px;\">\n                        Ph\u1ea7n th\u01b0\u1edfng: \ud83d\udc8e+${isBossMode ? 500 : 100}\n                    </div>\n                ` : '';\n                \n                const showNextBtn = won && isStageMode && currentStageId < gameStages.length;\n\n                uiOverlay.innerHTML = `\n                    <div class=\"screen active result-screen\">\n                        <div class=\"result-text\" style=\"color:${resultColor}\">${resultText}</div>\n                        ${rewardsText}\n                        ${showNextBtn ? `<div class=\"btn\" id=\"btn-next\" style=\"margin-bottom:16px; border-color:#FFD700;\">\u1ea2I TI\u1ebeP THEO</div>` : ''}\n                        <div class=\"btn\" id=\"btn-retry\" style=\"margin-bottom:16px\">CH\u01a0I L\u1ea0I</div>\n                        <div class=\"btn\" id=\"btn-menu\">MENU</div>\n                    </div>\n                `;\n                if (showNextBtn) {\n                    document.getElementById('btn-next').onclick = () => {\n                        currentStageId++;\n                        const stageData = gameStages.find(s => s.id === currentStageId);\n                        selectedOpponentChar = stageData.opponent;\n                        selectedMap = stageData.map;\n                        // Player keeps their character but starts new match\n                        startMatch();\n                    };\n                }\n                document.getElementById('btn-retry').onclick = () => {\n                    if (isStageMode) {\n                        startMatch();\n                    } else {\n                        showCharSelect();\n                    }\n                };\n                document.getElementById('btn-menu').onclick = () => showMenu();\n            }, 1500);\n        }\n\n        // Main game loop\n        function gameLoop(timestamp) {\n            if (!lastTime) lastTime = timestamp;\n            let dt = (timestamp - lastTime) / 1000;\n            lastTime = timestamp;\n            dt = Math.min(dt, 0.11);\n\n            // Clear\n            ctx.clearRect(0, 0, 720, 1280);\n\n            // Screen shake\n            ctx.save();\n            if (screenShake > 0) {\n                ctx.translate(Math.random() * screenShake - screenShake/2, Math.random() * screenShake - screenShake/2);\n                screenShake *= 0.85;\n                if (screenShake < 0.5) screenShake = 0;\n            }\n\n            drawBackground();\n\n            if (gameState === 'countdown') {\n                countdownTimer -= dt;\n                if (countdownTimer > 2) countdownText = '3';\n                else if (countdownTimer > 1) countdownText = '2';\n                else if (countdownTimer > 0) countdownText = '1';\n                else {\n                    countdownText = 'FIGHT!';\n                    if (countdownTimer < -0.5) {\n                        gameState = 'combat';\n                        playMusic('combat_music');\n                    }\n                }\n\n                drawFighter(player);\n                drawFighter(opponent);\n\n                // Draw countdown\n                ctx.save();\n                ctx.font = 'bold 100px \"Bebas Neue\"';\n                ctx.fillStyle = '#fff';\n                ctx.textAlign = 'center';\n                ctx.textBaseline = 'middle';\n                ctx.shadowColor = 'rgba(255,255,255,0.5)';\n                ctx.shadowBlur = 30;\n                ctx.fillText(countdownText, 360, 500);\n                ctx.restore();\n            }\n\n            if (gameState === 'combat' || gameState === 'result') {\n                if (gameState === 'combat') {\n                    processInput();\n                    \n                    // Update Player\n                    updateFighter(player, opponent, dt);\n\n                    // Update Summons\n                    for (let i = summons.length - 1; i >= 0; i--) {\n                        const s = summons[i];\n                        if (s.health <= 0) {\n                            summons.splice(i, 1);\n                            continue;\n                        }\n                        const target = (s.owner === player) ? opponent : player;\n                        updateAI(s, target, dt);\n                        updateFighter(s, target, dt);\n                    }\n\n                    // Update Allies\n                    for (const ally of allies) {\n                        if (ally.health > 0) {\n                            updateAI(ally, opponent, dt);\n                            updateFighter(ally, opponent, dt);\n                        }\n                    }\n\n                    // Boss target: closest player-side fighter that is alive\n                    let bossTarget = player;\n                    let minDist = player.health > 0 ? Math.abs(opponent.x - player.x) : 9999;\n                    \n                    for (const ally of allies) {\n                        if (ally.health > 0) {\n                            const d = Math.abs(opponent.x - ally.x);\n                            if (d < minDist) {\n                                minDist = d;\n                                bossTarget = ally;\n                            }\n                        }\n                    }\n                    \n                    // Allow boss to target summons owned by player/allies\n                    for (const s of summons) {\n                        if (s.health > 0 && (s.owner === player || allies.includes(s.owner))) {\n                            const d = Math.abs(opponent.x - s.x);\n                            if (d < minDist) {\n                                minDist = d;\n                                bossTarget = s;\n                            }\n                        }\n                    }\n\n                    updateAI(opponent, bossTarget, dt);\n                    updateFighter(opponent, bossTarget, dt);\n                    updateProjectiles(dt);\n\n                    matchTimer -= dt;\n\n                    // Check win/loss\n                    const teamAlive = player.health > 0 || allies.some(a => a.health > 0);\n                    if (!teamAlive) {\n                        showResult(false);\n                    } else if (opponent.health <= 0) {\n                        showResult(true);\n                    } else if (matchTimer <= 0) {\n                        showResult(player.health > opponent.health);\n                    }\n                }\n\n                if (player.health > 0 || player.state === 'victory') drawFighter(player);\n                for (const s of summons) {\n                    drawFighter(s);\n                }\n                for (const ally of allies) {\n                    if (ally.health > 0 || ally.state === 'victory') drawFighter(ally);\n                }\n                drawFighter(opponent);\n                drawProjectiles();\n                updateEffects(dt);\n                drawEffects();\n\n                if (gameState === 'combat') renderUI();\n            }\n\n            ctx.restore();\n\n            if (gameState === 'menu' || gameState === 'charSelect') {\n                // Draw some ambient bg\n            }\n\n            requestAnimationFrame(gameLoop);\n        }\n\n        // Edit mode\n        // Input listeners\n        window.addEventListener('keydown', e => {\n            keys[e.key.toLowerCase()] = true;\n        });\n        window.addEventListener('keyup', e => {\n            keys[e.key.toLowerCase()] = false;\n        });\n\n        canvas.addEventListener('touchstart', e => {\n            const touch = e.changedTouches[0];\n            const rect = canvas.getBoundingClientRect();\n            const x = (touch.clientX - rect.left) * (canvas.width / rect.width);\n            const y = (touch.clientY - rect.top) * (canvas.height / rect.height);\n            \n            if (x < 360) {\n                joystickActive = true;\n                joystickTouchId = touch.identifier;\n                joystickBaseX = x;\n                joystickBaseY = y;\n                joystickX = 0;\n                joystickY = 0;\n            }\n        });\n\n        canvas.addEventListener('touchmove', e => {\n            if (!joystickActive) return;\n            const rect = canvas.getBoundingClientRect();\n            for (let i = 0; i < e.changedTouches.length; i++) {\n                const touch = e.changedTouches[i];\n                if (touch.identifier === joystickTouchId) {\n                    const x = (touch.clientX - rect.left) * (canvas.width / rect.width);\n                    const y = (touch.clientY - rect.top) * (canvas.height / rect.height);\n                    const dx = x - joystickBaseX;\n                    const dy = y - joystickBaseY;\n                    const dist = Math.sqrt(dx*dx + dy*dy);\n                    const maxDist = 60;\n                    if (dist > maxDist) {\n                        joystickX = (dx / dist) * maxDist;\n                        joystickY = (dy / dist) * maxDist;\n                    } else {\n                        joystickX = dx;\n                        joystickY = dy;\n                    }\n                }\n            }\n        });\n\n        canvas.addEventListener('touchend', e => {\n            for (let i = 0; i < e.changedTouches.length; i++) {\n                const touch = e.changedTouches[i];\n                if (touch.identifier === joystickTouchId) {\n                    joystickActive = false;\n                    joystickTouchId = null;\n                    joystickX = 0;\n                    joystickY = 0;\n                }\n            }\n        });\n\n        if (mode === 'edit') {\n            drawBackground();\n            // Draw characters for preview\n            const p = createFighter('batBai', 100, true, false);\n            const en = createFighter('enel', 150, true, false);\n            const o = createFighter('bongDem', 180, false, false);\n            const i = createFighter('itachi', 260, false, false);\n            const vq = createFighter('vuaQuy', 340, false, false);\n            const m = createFighter('madara', 420, false, false);\n            const l = createFighter('luffy', 500, false, false);\n            const s = createFighter('sasuke', 580, false, false);\n            const su = createFighter('sukuna', 640, false, false);\n            const zo = createFighter('zoro', 680, false, false);\n            const sai = createFighter('saitama', 700, false, false);\n            const tan = createFighter('tanjiro', 710, false, false);\n            const yu = createFighter('yuta', 660, false, false);\n            drawFighter(p);\n            drawFighter(o);\n            drawFighter(en);\n            drawFighter(i);\n            drawFighter(vq);\n            drawFighter(m);\n            drawFighter(l);\n            drawFighter(s);\n            drawFighter(su);\n            drawFighter(zo);\n            drawFighter(sai);\n            drawFighter(tan);\n            drawFighter(yu);\n\n            ctx.font = 'bold 32px \"Bebas Neue\"';\n            ctx.fillStyle = '#fff';\n            ctx.textAlign = 'center';\n            ctx.fillText('EDIT MODE - Adjust parameters in settings', 360, 100);\n\n            // Simple redraw on config change\n            setInterval(() => {\n                ctx.clearRect(0, 0, 720, 1280);\n                drawBackground();\n                const p2 = createFighter('batBai', 80, true, false);\n                const o2 = createFighter('bongDem', 180, false, false);\n                const i2 = createFighter('itachi', 280, false, false);\n                const m2 = createFighter('madara', 380, false, false);\n                const n2 = createFighter('naruto', 430, false, false);\n                const l2 = createFighter('luffy', 480, false, false);\n                const s2 = createFighter('sasuke', 580, false, false);\n                const su2 = createFighter('sukuna', 650, false, false);\n                const g2 = createFighter('gojo', 680, false, false);\n                const z2 = createFighter('zoro', 700, false, false);\n                const tan2 = createFighter('tanjiro', 710, false, false);\n                const has2 = createFighter('hashirama', 60, true, false);\n                const obi2 = createFighter('obito', 220, true, false);\n                const en2 = createFighter('enel', 50, false, false);\n                const sai2 = createFighter('saitama', 150, false, false);\n                const vq2 = createFighter('vuaQuy', 250, false, false);\n                const po2 = createFighter('poPanda', 200, true, false);\n            const sg2 = createFighter('shadowGarden', 300, false, false);\n                const ri2 = createFighter('rimuru', 340, false, false);\n                const gok2 = createFighter('goku', 380, false, false);\n                const yu2 = createFighter('yuta', 440, true, false);\n                drawFighter(p2);\n                drawFighter(o2);\n                drawFighter(i2);\n                drawFighter(vq2);\n                drawFighter(po2);\n                drawFighter(sg2);\n                drawFighter(ri2);\n                drawFighter(m2);\n                drawFighter(n2);\n                drawFighter(l2);\n                drawFighter(s2);\n                drawFighter(su2);\n                drawFighter(g2);\n                drawFighter(z2);\n                drawFighter(tan2);\n                drawFighter(has2);\n                drawFighter(obi2);\n                drawFighter(en2);\n                drawFighter(sai2);\n                drawFighter(gok2);\n                drawFighter(yu2);\n                ctx.font = 'bold 32px \"Bebas Neue\"';\n                ctx.fillStyle = '#fff';\n                ctx.textAlign = 'center';\n                ctx.fillText('EDIT MODE - Adjust parameters in settings', 360, 100);\n                ctx.font = '22px Inter';\n                ctx.fillText(`Round Time: ${config.settings.roundTime}s | AI: ${config.settings.aiDifficulty}`, 360, 220);\n            }, 500);\n        } else {\n            showMenu();\n            requestAnimationFrame(gameLoop);\n        }\n    }\n    </script>\n</body>\n</html>", "game_config": "{\n  \"characters\": {\n    \"gojo\": {\n      \"health\": 1500,\n      \"speedMultiplier\": 1.15,\n      \"jumpMultiplier\": 1.2\n    },\n    \"batBai\": {\n      \"jumpMultiplier\": 1,\n      \"speedMultiplier\": 1,\n      \"health\": 1500\n    },\n    \"luffy\": {\n      \"health\": 1200,\n      \"speedMultiplier\": 1.1,\n      \"jumpMultiplier\": 1.2\n    },\n    \"sasuke\": {\n      \"jumpMultiplier\": 1.15,\n      \"health\": 1300,\n      \"speedMultiplier\": 1.2\n    },\n    \"vuaQuy\": {\n      \"jumpMultiplier\": 1.1,\n      \"speedMultiplier\": 1.05,\n      \"health\": 1500\n    },\n    \"sukuna\": {\n      \"speedMultiplier\": 1.1,\n      \"health\": 1100,\n      \"jumpMultiplier\": 1.1\n    },\n    \"bongDem\": {\n      \"jumpMultiplier\": 1,\n      \"speedMultiplier\": 1,\n      \"health\": 1500\n    },\n    \"saitama\": {\n      \"speedMultiplier\": 1.3,\n      \"health\": 1500,\n      \"jumpMultiplier\": 1.2\n    },\n    \"madara\": {\n      \"speedMultiplier\": 1.1,\n      \"health\": 1500,\n      \"jumpMultiplier\": 1.1\n    },\n    \"shadowGarden\": {\n      \"jumpMultiplier\": 1.1,\n      \"health\": 1500,\n      \"speedMultiplier\": 1.1\n    },\n    \"goku\": {\n      \"speedMultiplier\": 1.2,\n      \"health\": 1500,\n      \"jumpMultiplier\": 1.15\n    },\n    \"itachi\": {\n      \"jumpMultiplier\": 1.1,\n      \"speedMultiplier\": 1.1,\n      \"health\": 1500,\n      \"abilities\": {\n        \"4\": {\n          \"name\": \"Susanoo Edo\",\n          \"cooldown\": 25,\n          \"duration\": 17,\n          \"damage\": 30\n        }\n      }\n    },\n    \"naruto\": {\n      \"health\": 1350,\n      \"jumpMultiplier\": 1.15,\n      \"speedMultiplier\": 1.15\n    },\n    \"enel\": {\n      \"speedMultiplier\": 1.1,\n      \"jumpMultiplier\": 1.1,\n      \"health\": 1400\n    },\n    \"tanjiro\": {\n      \"health\": 1300,\n      \"speedMultiplier\": 1.1,\n      \"jumpMultiplier\": 1.1\n    },\n    \"yuji\": {\n      \"jumpMultiplier\": 1.1,\n      \"speedMultiplier\": 1.1,\n      \"health\": 1500\n    },\n    \"garp\": {\n      \"health\": 1800,\n      \"speedMultiplier\": 1,\n      \"jumpMultiplier\": 1.1\n    },\n    \"doraemon\": {\n      \"health\": 1500,\n      \"speedMultiplier\": 1,\n      \"jumpMultiplier\": 1\n    },\n    \"poPanda\": {\n      \"jumpMultiplier\": 1,\n      \"health\": 1700,\n      \"speedMultiplier\": 0.9\n    },\n    \"obito\": {\n      \"health\": 1600,\n      \"speedMultiplier\": 1.1,\n      \"jumpMultiplier\": 1.1\n    },\n    \"hashirama\": {\n      \"speedMultiplier\": 1,\n      \"health\": 1800,\n      \"jumpMultiplier\": 1.1\n    },\n    \"rimuru\": {\n      \"health\": 1800,\n      \"speedMultiplier\": 1.1,\n      \"jumpMultiplier\": 1.15\n    }\n  },\n  \"settings\": {\n    \"roundTime\": 90,\n    \"aiDifficulty\": \"medium\",\n    \"rounds\": 1,\n    \"bossHP\": 3900\n  },\n  \"assets_map\": {\n    \"ability3_icon_rimuru\": \"A dark, explosive sphere with a red aura, blue energy bands, and an orange lightning crack, inspired by Rimuru's power.\"\n  }\n}", "game_design_document": "## Core Game Loop and Mechanics\n\n**Ng\u01b0\u1eddi Que \u0110\u1ed1i Kh\u00e1ng** is a 2D fighting game where players choose between two distinct stick figure characters and engage in fast-paced 1v1 battles. The core gameplay revolves around:\n\n1. **Character Selection**: Players start by choosing between two fighters with contrasting playstyles\n2. **Combat**: Use three unique abilities per character to attack, defend, and outmaneuver opponents\n3. **Health Management**: Each character has a health bar; reduce opponent's health to zero to win\n4. **Ability Cooldowns**: Strategic use of abilities with cooldown timers adds depth\n5. **Victory/Defeat**: Win rounds to progress, lose and retry with potentially different character choice\n\n**What makes it compelling:**\n- Two distinct playstyles create varied gameplay experiences\n- Simple 3-ability system is easy to learn but allows for strategic depth\n- Fast-paced rounds encourage \"one more match\" engagement\n- Clear visual feedback for hits, blocks, and special moves\n\n**Win Condition:** Reduce opponent's health to zero\n**Lose Condition:** Player's health reaches zero\n\n## Starting Scope\n\nFor the initial implementation, we'll focus on creating a polished, playable prototype with:\n\n**Must Have (First Iteration):**\n- Character selection screen with visual previews of both fighters\n- Single arena/stage for combat\n- Both characters fully implemented with all 3 abilities\n- AI opponent with basic behavior (attacks, uses abilities, moves)\n- Health bars and ability cooldown indicators\n- Hit detection and damage system\n- Victory/defeat screens with replay option\n- Touch controls (mobile) and keyboard controls (desktop)\n- Sound effects for attacks, abilities, hits, and victory/defeat\n- Background music during combat\n\n**Future Iterations:**\n- Multiple AI difficulty levels\n- Additional characters with unique movesets\n- Multiple arenas/stages\n- Combo system and special finishers\n- Character customization (colors, accessories)\n- Tournament/campaign mode\n- Local multiplayer (two players on same device)\n- Power-ups or environmental hazards\n- Achievement system\n\n## Game Perspective\n\n**Side-scrolling (2D fighting game perspective)**\n\nThe game uses a classic 2D fighting game view where:\n- Both characters face each other on a horizontal plane\n- Camera is fixed, showing the entire arena\n- Characters are rendered in profile view\n- All movement and combat happens on a 2D plane (left/right movement, jumping)\n- The 720\u00d71280 portrait orientation means the arena is taller than wide, with characters positioned in the middle vertical space\n\n## Game World and Level Design\n\n**Arena Design:**\n\nThe game takes place in a single, self-contained arena for the first iteration:\n\n- **Dimensions**: The arena spans the full width of the 720px screen, with a ground level at approximately 900px from the top\n- **Background**: A simple but atmospheric backdrop (could be a dojo, street, or abstract space) that doesn't distract from combat\n- **Ground**: A flat platform where characters stand and move\n- **Boundaries**: Invisible walls at screen edges prevent characters from leaving the arena\n- **Visual Layers**:\n  - Background layer (parallax optional for polish)\n  - Ground/platform layer\n  - Character layer\n  - UI layer (health bars, ability cooldowns)\n\n**Spatial Layout:**\n- Characters spawn at opposite sides of the arena (approximately 150px from each edge)\n- Center of arena is at 360px horizontal\n- Combat zone is the entire ground area between boundaries\n- UI elements positioned at top (health bars) and bottom (ability buttons for mobile)\n\n**Future arenas could include:**\n- Different visual themes (forest, rooftop, temple)\n- Multiple platforms at different heights\n- Environmental hazards or interactive elements\n\n## Edit Mode Design\n\nEdit mode allows players to customize their gameplay experience while maintaining game balance.\n\n**Editable Properties:**\n\n1. **Character Stats** (per character):\n   - Health: 80-150 HP (default: 100)\n   - Movement Speed: 0.8x-1.5x (default: 1.0x)\n   - Jump Height: 0.8x-1.5x (default: 1.0x)\n\n2. **Ability Parameters** (per ability, per character):\n   - Damage: 50%-150% of base (default: 100%)\n   - Cooldown: 0.5x-2.0x of base (default: 1.0x)\n   - Range/Duration: 0.8x-1.2x of base (default: 1.0x)\n\n3. **Match Settings**:\n   - Round Time Limit: 30-180 seconds (default: 90 seconds)\n   - Number of Rounds: 1-5 (default: 1)\n   - AI Difficulty: Easy/Medium/Hard (default: Medium)\n\n4. **Visual Customization**:\n   - Character Colors: RGB color picker for primary/secondary colors\n   - Arena Background: Choice of 3-5 preset backgrounds\n\n**Constraints:**\n- Stat multipliers are capped to prevent broken gameplay (no 0 damage or infinite health)\n- At least one ability must have reasonable cooldown (prevent spam)\n- Time limits ensure matches don't drag on indefinitely\n- Color changes are cosmetic only, don't affect gameplay\n\n**Edit Mode UI:**\n- Accessible from main menu or character select screen\n- Organized in tabs: Characters, Abilities, Match Settings, Visuals\n- Real-time preview of changes where possible\n- Reset to defaults button for each section\n- Changes persist in window.gameConfig\n\n## Control Design\n\nThe game uses a **2D Fighting Game** control scheme optimized for both mobile touch and desktop keyboard/mouse.\n\n**Mobile Controls (Touch):**\n\n1. **Movement Virtual Joystick (Left Side)**:\n   - Appears where player touches on left half of screen (below y=640px to avoid UI)\n   - Analog input: left/right movement, up for jump\n   - Base moves with finger if exceeding max radius\n   - Dead zone: 15px, Max radius: 60px\n\n2. **Ability Buttons (Right Side)**:\n   - Three large buttons (96\u00d796px minimum) positioned in bottom-right area\n   - Button 1 (Ability 1): Bottom-right corner\n   - Button 2 (Ability 2): Above Button 1\n   - Button 3 (Ability 3): Above Button 2\n   - Buttons show ability icons and cooldown overlays\n   - Tap to activate ability\n\n3. **Touch ID Tracking**:\n   - Each touch tracked by unique ID\n   - Joystick and buttons don't interfere with each other\n   - Multiple simultaneous touches supported (move + ability)\n\n**Desktop Controls (Keyboard):**\n\n- **Movement**: \n  - A/D or Left/Right Arrow keys: Move left/right\n  - W or Up Arrow or Space: Jump\n- **Abilities**:\n  - J or 1: Ability 1\n  - K or 2: Ability 2\n  - L or 3: Ability 3\n- **Menu**:\n  - ESC: Pause/Menu\n\n**Input Handling:**\n- Prevent default browser behavior for all used keys\n- Clear input state on window blur\n- Convert keycodes to lowercase before storing\n- Responsive button feedback (visual press state)\n\n**Character-Specific Controls:**\n\nBoth characters use the same control scheme but abilities behave differently:\n\n**Ng\u01b0\u1eddi Que B\u1ea5t B\u1ea1i (Tank):**\n- Ability 1 (T\u0103ng C\u01b0\u1eddng Ph\u00f2ng Th\u1ee7): Activates defensive buff, reduces incoming damage for duration\n- Ability 2 (Khi\u00ean Th\u00e9p): Creates a shield that blocks next attack completely\n- Ability 3 (C\u00fa \u0110\u1ea5m \u0110\u1ea9y L\u00f9i): Powerful punch that deals damage and knocks opponent back\n\n**Ng\u01b0\u1eddi Que B\u00f3ng \u0110\u00eam (Assassin):**\n- Ability 1 (Phi Ti\u00eau B\u00f3ng T\u1ed1i): Throws a projectile that travels across screen\n- Ability 2 (L\u01b0\u1edbt \u1ea2nh): Quick dash forward or backward (direction based on movement input)\n- Ability 3 (Li\u00ean Ho\u00e0n \u00c1m S\u00e1t): Rapid multi-hit combo attack\n\n## Character Design Details\n\n### Ng\u01b0\u1eddi Que B\u1ea5t B\u1ea1i (The Unstoppable)\n\n**Playstyle:** Tank/Defender - High health, slower movement, focuses on absorbing damage and counter-attacking\n\n**Base Stats:**\n- Health: 120 HP\n- Movement Speed: 3 pixels/frame (slower)\n- Jump Height: 150 pixels (moderate)\n\n**Abilities:**\n\n1. **T\u0103ng C\u01b0\u1eddng Ph\u00f2ng Th\u1ee7 (Fortify Defense)**\n   - Type: Self-buff\n   - Effect: Reduces incoming damage by 50% for 4 seconds\n   - Cooldown: 10 seconds\n   - Visual: Character glows with a blue aura, stance becomes more defensive\n   - Animation: Character crosses arms briefly, then maintains defensive posture\n\n2. **Khi\u00ean Th\u00e9p (Steel Shield)**\n   - Type: Block\n   - Effect: Blocks the next incoming attack completely (negates 100% damage)\n   - Duration: Shield lasts 3 seconds or until hit\n   - Cooldown: 12 seconds\n   - Visual: Translucent shield appears in front of character\n   - Animation: Character raises arm, shield materializes\n\n3. **C\u00fa \u0110\u1ea5m \u0110\u1ea9y L\u00f9i (Knockback Punch)**\n   - Type: Melee attack\n   - Damage: 25 HP\n   - Effect: Pushes opponent back 150 pixels\n   - Range: 80 pixels (close range)\n   - Cooldown: 6 seconds\n   - Visual: Powerful wind-up punch with impact effect\n   - Animation: Wind-up, forward thrust, follow-through\n\n### Ng\u01b0\u1eddi Que B\u00f3ng \u0110\u00eam (Shadow)\n\n**Playstyle:** Assassin/Speedster - Lower health, faster movement, focuses on mobility and quick strikes\n\n**Base Stats:**\n- Health: 80 HP\n- Movement Speed: 5 pixels/frame (faster)\n- Jump Height: 200 pixels (higher)\n\n**Abilities:**\n\n1. **Phi Ti\u00eau B\u00f3ng T\u1ed1i (Shadow Shuriken)**\n   - Type: Ranged projectile\n   - Damage: 15 HP\n   - Speed: 8 pixels/frame\n   - Range: Full screen width\n   - Cooldown: 5 seconds\n   - Visual: Dark spinning projectile with trail effect\n   - Animation: Quick throwing motion\n\n2. **L\u01b0\u1edbt \u1ea2nh (Shadow Dash)**\n   - Type: Movement/Dodge\n   - Effect: Instantly moves 200 pixels in current facing direction\n   - Invulnerability: 0.3 seconds during dash\n   - Cooldown: 8 seconds\n   - Visual: Character becomes semi-transparent blur during dash\n   - Animation: Quick burst of movement with afterimage trail\n\n3. **Li\u00ean Ho\u00e0n \u00c1m S\u00e1t (Assassination Combo)**\n   - Type: Melee combo\n   - Damage: 8 HP \u00d7 4 hits = 32 HP total\n   - Range: 70 pixels\n   - Duration: 1.2 seconds (all hits)\n   - Cooldown: 10 seconds\n   - Visual: Rapid flurry of strikes with slash effects\n   - Animation: Four quick strike animations in sequence\n\n## AI Opponent Behavior\n\nFor the initial implementation, the AI will have basic but functional behavior:\n\n**AI Decision Making:**\n- Evaluates situation every 0.5 seconds\n- Considers: distance to player, own health, player health, ability cooldowns\n\n**AI Actions:**\n- **Movement**: Moves toward player if far away, maintains medium distance if close\n- **Jumping**: Jumps occasionally for unpredictability, jumps to dodge projectiles\n- **Ability Usage**:\n  - Uses abilities when off cooldown and in appropriate range\n  - Prioritizes defensive abilities when health is low\n  - Uses offensive abilities when player is in range\n- **Reaction Time**: 0.3-0.5 second delay to simulate human reaction\n\n**Difficulty Levels (for future):**\n- Easy: Slower reactions, less optimal ability usage\n- Medium: Balanced reactions and strategy\n- Hard: Fast reactions, optimal ability usage, better prediction\n\n## Game Flow\n\n**1. Main Menu:**\n- Title display\n- \"Play\" button\n- \"Edit\" button (opens edit mode)\n- Background music starts\n\n**2. Character Selection:**\n- Two character portraits side by side\n- Character names and brief descriptions\n- Ability icons shown for each character\n- \"Select\" button for each character\n- \"Back\" button to return to main menu\n\n**3. Pre-Match:**\n- Brief \"Ready\" countdown (3, 2, 1, Fight!)\n- Characters spawn at opposite sides\n- UI elements appear (health bars, ability buttons)\n\n**4. Combat:**\n- Players control their character\n- AI controls opponent\n- Health bars update in real-time\n- Ability cooldowns shown visually\n- Round timer counts down (if enabled)\n\n**5. Victory/Defeat:**\n- Winning character plays victory animation\n- \"Victory!\" or \"Defeat!\" text displays\n- Final stats shown (damage dealt, abilities used, time)\n- \"Play Again\" button (returns to character select)\n- \"Main Menu\" button\n\n**6. Edit Mode:**\n- Tabbed interface for different customization categories\n- Real-time preview of changes\n- \"Save\" and \"Cancel\" buttons\n- \"Reset to Defaults\" option\n\n## Art Style and Visual Theme\n\n**Overall Style:** Clean, modern stick figure aesthetic with dynamic action effects\n\n**Character Design:**\n- Simple stick figure silhouettes with distinct proportions\n- B\u1ea5t B\u1ea1i: Thicker lines, stockier build, suggests strength\n- B\u00f3ng \u0110\u00eam: Thinner lines, leaner build, suggests agility\n- Both characters have simple head (circle), body (lines), and limbs\n- Customizable colors for personalization\n\n**Color Palette:**\n- **B\u1ea5t B\u1ea1i Default**: Blue/steel tones (suggests defense, stability)\n  - Primary: #4A90E2 (blue)\n  - Secondary: #7B8D93 (steel gray)\n- **B\u00f3ng \u0110\u00eam Default**: Purple/dark tones (suggests stealth, speed)\n  - Primary: #9B59B6 (purple)\n  - Secondary: #2C3E50 (dark gray)\n- **UI**: Clean whites, grays, with accent colors matching characters\n- **Effects**: Bright, saturated colors for visual impact (yellow impacts, red damage numbers)\n\n**Visual Effects:**\n- Hit impacts: Bright flash, radial lines, screen shake (subtle)\n- Ability effects: Glows, particles, trails appropriate to each ability\n- Damage numbers: Pop up briefly above damaged character\n- Health bars: Smooth depletion animation, color changes (green\u2192yellow\u2192red)\n- Cooldown indicators: Circular fill or overlay on ability buttons\n\n**Arena Aesthetic:**\n- Simple, clean background that doesn't compete with characters\n- Subtle gradient or geometric patterns\n- Ground clearly defined with simple line or platform\n- Lighting suggests time of day or mood (default: neutral daylight)\n\n**UI Design:**\n- Minimalist, non-intrusive\n- Health bars at top: horizontal bars with character colors\n- Ability buttons (mobile): Large, clear icons with cooldown overlays\n- Character select: Clean portraits with ability previews\n- Fonts: Bold, readable sans-serif for all text\n\n**Animation Principles:**\n- Snappy, responsive animations (no lag feel)\n- Clear anticipation, action, follow-through for attacks\n- Exaggerated movements for readability\n- Smooth transitions between states\n\n**Asset Rendering Strategy:**\n- Characters: Generated sprite assets for different poses/actions\n- Effects: Mix of generated assets and canvas-drawn particles\n- UI: CSS/HTML for clean, scalable interface\n- Background: Generated asset or CSS gradient", "persistent_storage_config": {"leaderboard": {"sort_ascending": false}}, "game_metadata": {"game_id": "01KSW1BCTV49C2S7SQ5V8EEG0G", "title": "Ng\u01b0\u1eddi Que \u0110\u1ed1i Kh\u00e1ng", "description": "**Description:** Ch\u1ecdn chi\u1ebfn binh v\u00e0 l\u00e0m ch\u1ee7 3 chi\u00eau th\u1ee9c \u0111\u1ed9c \u0111\u00e1o \u0111\u1ec3 \u0111\u00e1nh b\u1ea1i \u0111\u1ed1i th\u1ee7 trong tr\u1eadn \u0111\u1ea5u 1v1 c\u0103ng th\u1eb3ng!", "thumbnail_url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/thumbnail_a6a7fbd7-937e-4118-9c89-8031761cb059.webp", "created_at": 1780131632, "updated_at": 1787632283685.8494, "art_style": null}, "task_plan": null}