{"asset_map": {"player_character_idle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/player_character_idle_f25e7e60-e7ec-45aa-b376-aaa3ffcb6505.webp", "type": "image", "prompt": "Generate a top-down view, 90 degree overhead pixel art character sprite. Standing idle pose, arms slightly away from body, facing downward. Wearing a bright blue jacket, orange shirt collar, brown hair, light skin tone, black pants, and black shoes. High-quality clean pixel art, HDR-inspired vibrant colors, soft oval shadow beneath, light source from top-left, transparent background.", "description": "Top-down idle sprite of the main player character with a blue jacket and orange shirt.", "subtype": "character", "aspect_ratio": [476, 837], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "player_character_walking": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/player_character_walking_bf8ad54a-3c41-4aa2-b333-b2c88cba3a93.webp", "type": "image", "prompt": "Generate a top-down view, 90 degree overhead pixel art character sprite in a mid-walk stride pose. One leg forward, arms in natural walking motion. Same character as image 1: blue jacket, orange shirt, brown hair, light skin, black pants. Maintain exact pixel density, colors, and shadow style as image 1. High-quality pixel art, transparent background, facing downward.", "description": "Top-down walking animation sprite for the main player character.", "subtype": "character", "aspect_ratio": [552, 821], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "npc_civilian_1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/npc_civilian_1_014a01de-a290-4323-9234-a78850b84866.webp", "type": "image", "prompt": "Generate a top-down view, 90 degree overhead pixel art NPC sprite. Character has dark skin, black hair, wearing a red t-shirt, blue jeans, and white sneakers. Standing idle pose. Match the pixel art style, size, and HDR lighting of image 1. Soft shadow beneath, light from top-left, transparent background.", "description": "Top-down sprite for a civilian NPC in a red t-shirt and blue jeans.", "subtype": "character", "aspect_ratio": [716, 1245], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "npc_civilian_2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/npc_civilian_2_28221a1e-28cb-4d78-94eb-8f4fe2a64fda.webp", "type": "image", "prompt": "Generate a top-down view, 90 degree overhead pixel art NPC sprite. Character has light skin, blonde hair, wearing a green hoodie, gray pants, and brown shoes. Standing idle pose. Match the pixel art style and scale of image 1. Vibrant HDR colors, soft shadow, transparent background.", "description": "Top-down sprite for a civilian NPC in a green hoodie and gray pants.", "subtype": "character", "aspect_ratio": [707, 1243], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "npc_civilian_3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/npc_civilian_3_d070cafe-8638-45b9-80d5-13390d1d0c21.webp", "type": "image", "prompt": "Generate a top-down view, 90 degree overhead pixel art NPC sprite. Character has medium skin tone, black hair, wearing a yellow dress and white sandals. Standing idle pose. Match the pixel art style and scale of image 1. Vibrant HDR colors, soft shadow, transparent background.", "description": "Top-down sprite for a civilian NPC in a yellow dress.", "subtype": "character", "aspect_ratio": [521, 1105], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "civilian_car_sedan": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/civilian_car_sedan_8ab026ac-01b2-44bb-8e2b-efdd1b74f139.webp", "type": "image", "prompt": "Generate a 90 degree overhead top-down view pixel art car sprite. Modern red sedan with black tinted windows, white headlights at front, red taillights at rear. Car is facing downward. Clean pixel art, vibrant HDR colors, subtle shadow beneath. Clear silhouette, doors and hood lines subtly indicated. Transparent background.", "description": "Top-down red civilian sedan car.", "subtype": "object", "aspect_ratio": [543, 993], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "civilian_car_suv": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/civilian_car_suv_de890859-3616-49f1-ab09-25834a88d40d.webp", "type": "image", "prompt": "Generate a 90 degree overhead top-down view pixel art SUV vehicle sprite. Blue body color, black windows, white headlights, red taillights. Wider and longer than image 1, roof rack indicated on top. Match the pixel art style and shading of image 1. Car is facing downward. Transparent background.", "description": "Top-down blue civilian SUV.", "subtype": "object", "aspect_ratio": [645, 1220], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "police_car": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/police_car_d8206185-f847-4e24-af84-490f8f957e0b.webp", "type": "image", "prompt": "Generate a 90 degree overhead top-down view pixel art police cruiser sprite. Black and white body with 'POLICE' text on the hood. Prominent red and blue light bar on the roof. More aggressive, boxy design than image 1. Facing downward. High-quality pixel art, vibrant colors, transparent background.", "description": "Top-down police cruiser with light bar and markings.", "subtype": "object", "aspect_ratio": [654, 1240], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "bank_building": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bank_building_35b2da10-169e-4e01-a14a-8e91bda6e6f7.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art building of a grand bank. Classical architecture with columns at entrance, beige stone walls, dark gray roof with a dollar sign symbol. Windows along sides. Large scale, approximately 256x256 pixels. Depth suggested by columns and shadows. High-quality HDR pixel art, light from top-left, transparent background.", "description": "Large classical bank building seen from above.", "subtype": "background", "aspect_ratio": [640, 848], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "building_shop_1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/building_shop_1_e4665fb4-efb7-4893-8194-50ce622677ba.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art shop building. Brick red walls, dark gray roof, striped red and white awning over the entrance. Large glass storefront window. Match the pixel art style of image 1. Rectangular shape, subtle shadow at base, transparent background.", "description": "Small retail shop building with a red and white awning.", "subtype": "background", "aspect_ratio": [649, 1020], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "building_shop_2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/building_shop_2_280ba95e-a9ec-4029-a769-f4ba247b908a.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art shop building. Yellow/cream walls, brown roof, blue door, and large windows. Different layout than image 2 but same style and size. High-quality pixel art, HDR colors, depth indication, transparent background.", "description": "Small yellow retail store building.", "subtype": "background", "aspect_ratio": [820, 1060], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "building_residential_1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/building_residential_1_28825dff-cd6c-43d5-9cf2-58554cb33d99.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art apartment building. Gray concrete walls, dark roof, grid of multiple small windows with a yellow glow inside. Larger and taller than the shops. Depth indicated by shadow, HDR-inspired style, transparent background.", "description": "Medium-sized apartment building with glowing windows.", "subtype": "background", "aspect_ratio": [564, 1089], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "building_residential_2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/building_residential_2_f0d148a9-a575-4a2f-a413-cccbd20a534d.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art house building. Red brick walls, dark gray roof, white-framed windows. Different design from image 2 but same medium scale. HDR colors, clean pixel art, transparent background.", "description": "Medium-sized red brick residential building.", "subtype": "background", "aspect_ratio": [822, 1067], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tree_1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tree_1_48c958ee-dbdb-40a6-9961-23f5b111c67e.webp", "type": "image", "prompt": "Generate a top-down 90 degree overhead pixel art tree. Round bushy green canopy with layered shades of green to suggest volume. Brown trunk barely visible in the center. Organic circular shape, soft shadow beneath, vibrant HDR colors, transparent background.", "description": "Round deciduous tree from a top-down perspective.", "subtype": "other", "aspect_ratio": [877, 899], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "tree_2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tree_2_db992280-4b48-4fc9-87ff-9560a6d1c81b.webp", "type": "image", "prompt": "Generate a top-down 90 degree overhead pixel art tree. Pointed/angular canopy like a pine tree, star-shaped silhouette from above. Darker green colors than image 1. Match pixel art style and shadow quality. Transparent background.", "description": "Conifer/pine style tree from a top-down perspective.", "subtype": "other", "aspect_ratio": [1015, 1007], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "bench": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/bench_520b040e-ed8a-4b06-8d54-616c6f916d5d.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art park bench. Brown wooden slats with a black metal frame. Simple rectangular shape, subtle shadow beneath. Match game art style, clean lines, transparent background.", "description": "Pixel art park bench seen from above.", "subtype": "ui", "aspect_ratio": [905, 513], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "trash_can": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/trash_can_f492c4c6-dc70-4cfc-90fa-517df3afe1d6.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art trash can. Circular dark green body with a black lid. Simple design, soft shadow, matches city aesthetic. Transparent background.", "description": "Pixel art trash bin seen from above.", "subtype": "ui", "aspect_ratio": [661, 760], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "lamp_post": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/lamp_post_e88c0da5-2d19-4914-84a2-2b95f388592e.webp", "type": "image", "prompt": "Generate a top-down view 90 degree overhead pixel art street lamp. Black metal pole in center, circular light fixture at top with a yellow/white glow and HDR bloom effect. Subtle shadow at base, transparent background.", "description": "Street lamp with a glowing light fixture, top-down view.", "subtype": "other", "aspect_ratio": [277, 931], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "car_theft_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/car_theft_sfx_15939a4c-f167-4e51-9682-50b9c8f04b86.mp3", "type": "audio", "prompt": "Arcade-style car theft sequence: a sharp metallic car door handle pull and creak, followed by a split-second pause, ending with a powerful, satisfying engine ignition and high-revving roar. Punchy, clean, and modern urban game aesthetic.", "description": "Sound effect for the sequence of breaking into and starting a car.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.19, "loop": false, "animation": null}, "bank_robbery_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/bank_robbery_sfx_0542d887-9670-409e-914b-1ab759e00fa3.mp3", "type": "audio", "prompt": "Urgent arcade bank robbery sound: a loud electric alarm bell ringing rapidly, layered with the crisp sound of cascading coins and rustling paper bills. Chaotic, dramatic, and high-stakes feel with a retro-modern production style.", "description": "Dramatic audio cue for a successful bank heist.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3, "loop": false, "animation": null}, "police_siren_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/police_siren_sfx_1cc6ee60-9cdf-447a-b32a-a5f9ddb7012c.mp3", "type": "audio", "prompt": "Classic 'wee-woo' police siren, medium intensity, stylized for a top-down arcade action game. Clear, recognizable pitch oscillation, designed to loop seamlessly without clicks or pops. Focused mid-range frequencies to avoid being overly shrill.", "description": "A seamless looping siren for police pursuit vehicles.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 4, "loop": true, "animation": null}, "car_engine_loop": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/car_engine_loop_dd20101d-066b-4960-b662-af42e9adfe79.mp3", "type": "audio", "prompt": "Mid-range steady car engine rumble, consistent cruising speed RPM. Smooth, mechanical hum with a slight bassy vibration. Arcade racing aesthetic, clean and non-distracting, designed for a perfect seamless loop.", "description": "Steady engine rumble for the player's vehicle.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3, "loop": true, "animation": null}, "car_crash_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/car_crash_sfx_5f4c8291-e755-4e2d-bd4e-abc9d2df203c.mp3", "type": "audio", "prompt": "Punchy arcade car crash: a heavy metal crunch impact followed by a short shimmer of breaking glass. High-impact feedback, satisfying and sharp, without excessive tail reverb. Suitable for frequent collisions.", "description": "Impact sound for vehicle collisions.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.3, "loop": false, "animation": null}, "game_over_sfx": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/game_over_sfx_2bf45c6e-3235-4b6d-9513-d9c9bbd26a66.mp3", "type": "audio", "prompt": "Game over sequence: brief muffled police radio chatter, a metallic 'click' of handcuffs, and a descending 3-note minor key musical failure motif. Clear game-over feedback with a retro-modern touch.", "description": "Audio sequence for when the player is busted by the police.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.08, "loop": false, "animation": null}, "background_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/background_music_0fa69c11-eb02-464b-bce1-499200eec318.mp3", "type": "audio", "prompt": "Urban energetic electronic background track, 125 BPM. Driving synth bassline, punchy drum machine beats, and catchy lead synth melodies. Mix of modern synthwave and action game tension. Seamlessly loopable, professional production, dynamic and exciting but balanced for long play sessions.", "description": "Main gameplay loop music with an urban electronic vibe.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30, "loop": true, "animation": null}, "intro_epic_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/intro_epic_sound_a9235bb7-57ac-404c-986d-1d8da617b246.mp3", "type": "audio", "prompt": "An epic, high-stakes cinematic intro fanfare for a crime action game. Starts with a heavy sub-bass impact/boom, followed by a rapid 4-second crescendo of aggressive orchestral strings and dramatic brass stabs. Includes a rising metallic whoosh/sweep that builds tension and culminates in a final, powerful, and clean orchestral hit with a long cinematic reverb tail. Professional, polished, high-energy, and dramatic, conveying a sense of urban grit and grand scale.", "description": "Epic cinematic intro sting with orchestral build-up and a powerful final impact for the game LIFECITY.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 6, "loop": false, "animation": null}, "lobby_city_background": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/lobby_city_background_190c7f0a-063a-428f-acf6-dab2d3c8db43.webp", "type": "image", "prompt": "Generate a 9:16 tall image of a beautiful pixel art urban cityscape for a game lobby screen. The scene features a dense city with tall skyscrapers at night. Use a moody color palette of dark blues and purples, contrasted with vibrant cyan, pink, and yellow neon signs and glowing windows. Include street-level details like sidewalks, roads, and parked cars similar in style to 'civilian_car_sedan'. Atmospheric lighting with retro 8-bit aesthetic, high-quality pixel art, professional game title screen background.", "description": "A moody, neon-lit pixel art urban cityscape for the game's vertical lobby screen.", "subtype": "background", "aspect_ratio": [832, 1248], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}}, "game_code": "<!DOCTYPE html>\n<html>\n<head>\n    <title>LIFECITY BETA TEST 0.1</title>\n    <style>\n        @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');\n\n        :root {\n            --transition-fast: 150ms;\n            --transition-normal: 300ms;\n            --ease-out: cubic-bezier(0.0, 0, 0.2, 1);\n            --space-sm: 16px;\n            --space-md: 24px;\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: 'Press Start 2P', monospace;\n        }\n\n        #game-world {\n            position: relative;\n            width: 100%;\n            height: 100%;\n            background-color: #2D5016;\n        }\n\n        #game-canvas {\n            display: block;\n            width: 100%;\n            height: 100%;\n            image-rendering: pixelated;\n            image-rendering: crisp-edges;\n        }\n\n        /* UI Overlay */\n        .ui-overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            pointer-events: none;\n            z-index: 10;\n        }\n\n        .ui-overlay > * {\n            pointer-events: auto;\n        }\n\n        /* HUD */\n        .hud {\n            position: absolute;\n            top: var(--space-sm);\n            left: var(--space-sm);\n            right: var(--space-sm);\n            display: flex;\n            justify-content: space-between;\n            align-items: flex-start;\n        }\n\n        .wanted-display {\n            background: rgba(0, 0, 0, 0.7);\n            padding: 12px 16px;\n            border-radius: 8px;\n            display: flex;\n            align-items: center;\n            gap: 8px;\n        }\n\n        .star {\n            width: 32px;\n            height: 32px;\n            color: #FFD700;\n            font-size: 32px;\n            filter: drop-shadow(0 0 4px #FFD700);\n        }\n\n        .star.inactive {\n            color: #444;\n            filter: none;\n        }\n\n        .score-display {\n            background: rgba(0, 0, 0, 0.7);\n            padding: 12px 16px;\n            border-radius: 8px;\n            color: #FFFFFF;\n            font-size: 24px;\n        }\n\n        .player-stats {\n            position: absolute;\n            top: var(--space-sm);\n            left: 50%;\n            transform: translateX(-50%);\n            background: rgba(0, 0, 0, 0.7);\n            padding: 12px 20px;\n            border-radius: 8px;\n            display: flex;\n            gap: 20px;\n            align-items: center;\n        }\n\n        .stat-bar {\n            display: flex;\n            flex-direction: column;\n            gap: 4px;\n            align-items: center;\n        }\n\n        .stat-bar-label {\n            color: #FFFFFF;\n            font-size: 12px;\n            font-weight: bold;\n        }\n\n        .stat-bar-container {\n            width: 120px;\n            height: 12px;\n            background: rgba(0, 0, 0, 0.5);\n            border: 2px solid #FFFFFF;\n            border-radius: 4px;\n            overflow: hidden;\n        }\n\n        .stat-bar-fill {\n            height: 100%;\n            transition: width 0.1s linear;\n        }\n\n        .hunger-bar-fill {\n            background: linear-gradient(90deg, #FF6B6B, #FFD700);\n        }\n\n        .stamina-bar-fill {\n            background: linear-gradient(90deg, #4A90E2, #00FF00);\n        }\n\n        /* Mini-map */\n        .minimap {\n            position: absolute;\n            bottom: 240px;\n            right: var(--space-sm);\n            width: 160px;\n            height: 160px;\n            background: rgba(0, 0, 0, 0.8);\n            border: 2px solid #FFFFFF;\n            border-radius: 8px;\n        }\n\n        /* Action Prompt */\n        .action-prompt {\n            position: absolute;\n            bottom: 260px;\n            left: 50%;\n            transform: translateX(-50%);\n            background: rgba(0, 0, 0, 0.9);\n            color: #FFFFFF;\n            padding: 16px 32px;\n            border-radius: 12px;\n            font-size: 20px;\n            white-space: nowrap;\n            opacity: 0;\n            transition: opacity var(--transition-normal) var(--ease-out);\n            border: 2px solid rgba(255, 255, 255, 0.3);\n        }\n\n        .action-prompt.visible {\n            opacity: 1;\n        }\n\n        /* Touch Controls */\n        .touch-controls {\n            position: absolute;\n            bottom: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            pointer-events: none;\n        }\n\n        .virtual-joystick {\n            position: absolute;\n            width: 160px;\n            height: 160px;\n            opacity: 0;\n            transition: opacity var(--transition-fast);\n            pointer-events: none;\n        }\n\n        .virtual-joystick.active {\n            opacity: 0.8;\n        }\n\n        .joystick-base {\n            position: absolute;\n            width: 100%;\n            height: 100%;\n            background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.1) 100%);\n            border: 3px solid rgba(255,255,255,0.5);\n            border-radius: 50%;\n        }\n\n        .joystick-knob {\n            position: absolute;\n            width: 60px;\n            height: 60px;\n            background: radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0.5) 100%);\n            border: 3px solid rgba(255,255,255,0.9);\n            border-radius: 50%;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n        }\n\n        .touch-button {\n            position: absolute;\n            background: rgba(255, 255, 255, 0.3);\n            border: 3px solid rgba(255, 255, 255, 0.7);\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            color: #FFFFFF;\n            font-size: 22px;\n            font-weight: bold;\n            transition: all var(--transition-fast);\n            pointer-events: auto;\n            user-select: none;\n            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);\n        }\n\n        .touch-button:active {\n            background: rgba(255, 255, 255, 0.5);\n            transform: scale(0.95);\n        }\n\n        .action-button {\n            bottom: var(--space-md);\n            right: var(--space-md);\n            width: 96px;\n            height: 96px;\n        }\n\n        .sprint-button {\n            bottom: 140px;\n            right: var(--space-md);\n            width: 80px;\n            height: 80px;\n        }\n\n        .exit-button {\n            top: 80px;\n            right: var(--space-md);\n            width: 80px;\n            height: 80px;\n            display: none;\n        }\n\n        .exit-button.visible {\n            display: flex;\n        }\n\n        /* Game Over Screen */\n        .game-over-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.9);\n            display: none;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            gap: var(--space-md);\n            z-index: 100;\n        }\n\n        .game-over-screen.visible {\n            display: flex;\n        }\n\n        .game-over-title {\n            font-size: 52px;\n            color: #FF0000;\n            text-shadow: 0 0 20px #FF0000;\n            margin-bottom: var(--space-md);\n        }\n\n        .game-over-stats {\n            background: rgba(255, 255, 255, 0.1);\n            padding: var(--space-md);\n            border-radius: 8px;\n            text-align: center;\n        }\n\n        .stat-line {\n            color: #FFFFFF;\n            font-size: 24px;\n            margin: 16px 0;\n            line-height: 1.4;\n        }\n\n        .restart-button {\n            background: #2E5C9A;\n            color: #FFFFFF;\n            border: none;\n            padding: 24px 48px;\n            font-size: 26px;\n            font-family: 'Press Start 2P', monospace;\n            border-radius: 12px;\n            cursor: pointer;\n            transition: all var(--transition-normal);\n            margin-top: 32px;\n            min-height: 96px;\n        }\n\n        .restart-button:hover {\n            background: #3A6FB0;\n            transform: scale(1.05);\n        }\n\n        .restart-button:active {\n            transform: scale(0.95);\n        }\n\n        /* Intro Screen */\n        .intro-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            gap: var(--space-md);\n            z-index: 200;\n        }\n\n        .intro-screen.hidden {\n            display: none;\n        }\n\n        .intro-title {\n            font-size: 48px;\n            color: #FFD700;\n            text-shadow: 0 0 20px #FFD700, 0 0 40px rgba(255, 215, 0, 0.5);\n            animation: pulse 1s ease-in-out infinite;\n            margin-bottom: 32px;\n        }\n\n        @keyframes pulse {\n            0%, 100% { opacity: 1; }\n            50% { opacity: 0.7; }\n        }\n\n        /* Lobby Screen */\n        .lobby-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n            background-size: cover;\n            background-position: center;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            gap: var(--space-md);\n            z-index: 200;\n        }\n\n        .lobby-screen::before {\n            content: '';\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.3);\n            z-index: -1;\n        }\n\n        .lobby-screen.hidden {\n            display: none;\n        }\n\n        .lobby-title {\n            font-size: 56px;\n            color: #FFFFFF;\n            text-shadow: 0 0 20px rgba(255, 255, 255, 0.5);\n            margin-bottom: 48px;\n        }\n\n        .lobby-version {\n            position: absolute;\n            bottom: 20px;\n            left: 20px;\n            font-size: 18px;\n            color: #FFFFFF;\n            opacity: 0.7;\n        }\n\n        .lobby-buttons {\n            display: flex;\n            flex-direction: column;\n            gap: 20px;\n            align-items: center;\n        }\n\n        .lobby-button {\n            background: linear-gradient(135deg, #2E5C9A 0%, #1a3a52 100%);\n            color: #FFFFFF;\n            border: 3px solid #FFD700;\n            padding: 24px 64px;\n            font-size: 28px;\n            font-family: 'Press Start 2P', monospace;\n            border-radius: 12px;\n            cursor: pointer;\n            transition: all var(--transition-normal);\n            min-width: 300px;\n            text-align: center;\n            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);\n        }\n\n        .lobby-button:hover {\n            background: linear-gradient(135deg, #3A6FB0 0%, #2a4a62 100%);\n            transform: scale(1.05);\n            box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4);\n        }\n\n        .lobby-button:active {\n            transform: scale(0.95);\n        }\n\n        /* Settings Screen */\n        .settings-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            gap: var(--space-md);\n            z-index: 200;\n            overflow-y: auto;\n            padding: 40px 20px;\n        }\n\n        .settings-screen.hidden {\n            display: none;\n        }\n\n        .settings-title {\n            font-size: 48px;\n            color: #FFD700;\n            text-shadow: 0 0 20px #FFD700;\n            margin-bottom: 32px;\n        }\n\n        .settings-content {\n            background: rgba(0, 0, 0, 0.5);\n            padding: 32px;\n            border-radius: 12px;\n            border: 2px solid #FFD700;\n            max-width: 500px;\n            max-height: 600px;\n            overflow-y: auto;\n        }\n\n        .settings-section {\n            margin-bottom: 32px;\n            color: #FFFFFF;\n        }\n\n        .settings-section-title {\n            font-size: 20px;\n            color: #FFD700;\n            margin-bottom: 16px;\n            border-bottom: 2px solid #FFD700;\n            padding-bottom: 8px;\n        }\n\n        .settings-item {\n            margin-bottom: 16px;\n            font-size: 16px;\n        }\n\n        .settings-item label {\n            display: block;\n            margin-bottom: 8px;\n        }\n\n        .settings-item input[type=\"range\"] {\n            width: 100%;\n            cursor: pointer;\n        }\n\n        .settings-item input[type=\"checkbox\"] {\n            margin-right: 8px;\n            cursor: pointer;\n        }\n\n        .back-button {\n            background: #2E5C9A;\n            color: #FFFFFF;\n            border: 2px solid #FFD700;\n            padding: 16px 32px;\n            font-size: 20px;\n            font-family: 'Press Start 2P', monospace;\n            border-radius: 8px;\n            cursor: pointer;\n            transition: all var(--transition-normal);\n            margin-top: 24px;\n        }\n\n        .back-button:hover {\n            background: #3A6FB0;\n            transform: scale(1.05);\n        }\n\n        .back-button:active {\n            transform: scale(0.95);\n        }\n\n        .shop-close-button {\n            position: absolute;\n            top: 20px;\n            right: 20px;\n            width: 50px;\n            height: 50px;\n            background: #FF0000;\n            border: 3px solid #FFFFFF;\n            border-radius: 50%;\n            color: #FFFFFF;\n            font-size: 32px;\n            font-weight: bold;\n            cursor: pointer;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            transition: all var(--transition-normal);\n            z-index: 1000;\n        }\n\n        .shop-close-button:hover {\n            background: #CC0000;\n            transform: scale(1.1);\n        }\n\n        .shop-close-button:active {\n            transform: scale(0.95);\n        }\n\n        /* Phone UI */\n        .phone-button {\n            position: absolute;\n            bottom: 240px;\n            left: var(--space-md);\n            width: 80px;\n            height: 80px;\n            background: rgba(50, 50, 50, 0.9);\n            border: 3px solid #00FF00;\n            border-radius: 12px;\n            color: #00FF00;\n            font-size: 32px;\n            cursor: pointer;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            transition: all var(--transition-normal);\n            pointer-events: auto;\n            user-select: none;\n            box-shadow: 0 0 10px rgba(0, 255, 0, 0.5);\n        }\n\n        .phone-button:hover {\n            background: rgba(70, 70, 70, 0.95);\n            box-shadow: 0 0 20px rgba(0, 255, 0, 0.8);\n            transform: scale(1.05);\n        }\n\n        .phone-button:active {\n            transform: scale(0.95);\n        }\n\n        /* Phone Screen */\n        .phone-screen {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n            width: 320px;\n            height: 640px;\n            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n            border: 4px solid #00FF00;\n            border-radius: 20px;\n            display: none;\n            flex-direction: column;\n            z-index: 150;\n            box-shadow: 0 0 30px rgba(0, 255, 0, 0.6);\n            overflow: hidden;\n        }\n\n        .phone-screen.visible {\n            display: flex;\n        }\n\n        .phone-header {\n            background: rgba(0, 255, 0, 0.2);\n            padding: 16px;\n            border-bottom: 2px solid #00FF00;\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n\n        .phone-title {\n            color: #00FF00;\n            font-size: 20px;\n            font-weight: bold;\n        }\n\n        .phone-close-btn {\n            background: #FF0000;\n            border: 2px solid #FFFFFF;\n            color: #FFFFFF;\n            width: 30px;\n            height: 30px;\n            border-radius: 50%;\n            cursor: pointer;\n            font-size: 18px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            transition: all var(--transition-fast);\n        }\n\n        .phone-close-btn:hover {\n            background: #CC0000;\n            transform: scale(1.1);\n        }\n\n        .phone-content {\n            flex: 1;\n            overflow-y: auto;\n            padding: 16px;\n            color: #FFFFFF;\n        }\n\n        .phone-menu {\n            display: flex;\n            flex-direction: column;\n            gap: 12px;\n        }\n\n        .phone-menu-item {\n            background: rgba(0, 255, 0, 0.1);\n            border: 2px solid #00FF00;\n            padding: 16px;\n            border-radius: 8px;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n            text-align: center;\n            font-size: 16px;\n            color: #00FF00;\n            font-weight: bold;\n        }\n\n        .phone-menu-item:hover {\n            background: rgba(0, 255, 0, 0.3);\n            transform: scale(1.02);\n        }\n\n        .phone-menu-item:active {\n            transform: scale(0.98);\n        }\n\n        .phone-info-section {\n            background: rgba(0, 255, 0, 0.1);\n            border: 2px solid #00FF00;\n            padding: 16px;\n            border-radius: 8px;\n            margin-bottom: 12px;\n        }\n\n        .phone-info-title {\n            color: #FFD700;\n            font-size: 16px;\n            font-weight: bold;\n            margin-bottom: 8px;\n            border-bottom: 1px solid #00FF00;\n            padding-bottom: 8px;\n        }\n\n        .phone-info-line {\n            color: #FFFFFF;\n            font-size: 14px;\n            margin: 6px 0;\n            display: flex;\n            justify-content: space-between;\n        }\n\n        .phone-footer {\n            background: rgba(0, 255, 0, 0.1);\n            border-top: 2px solid #00FF00;\n            padding: 12px;\n            text-align: center;\n            color: #00FF00;\n            font-size: 12px;\n        }\n    </style>\n</head>\n<body>\n    <div id=\"game-world\">\n        <canvas id=\"game-canvas\"></canvas>\n        \n        <div class=\"ui-overlay\">\n            <!-- HUD -->\n            <div class=\"hud\">\n                <div class=\"wanted-display\">\n                    <span class=\"star\" id=\"star1\">\u2605</span>\n                    <span class=\"star\" id=\"star2\">\u2605</span>\n                    <span class=\"star\" id=\"star3\">\u2605</span>\n                </div>\n                <div class=\"player-stats\">\n                    <div class=\"stat-bar\">\n                        <div class=\"stat-bar-label\">HUNGER</div>\n                        <div class=\"stat-bar-container\">\n                            <div class=\"stat-bar-fill hunger-bar-fill\" id=\"hunger-bar\" style=\"width: 100%;\"></div>\n                        </div>\n                    </div>\n                    <div class=\"stat-bar\">\n                        <div class=\"stat-bar-label\">STAMINA</div>\n                        <div class=\"stat-bar-container\">\n                            <div class=\"stat-bar-fill stamina-bar-fill\" id=\"stamina-bar\" style=\"width: 100%;\"></div>\n                        </div>\n                    </div>\n                </div>\n                <div class=\"score-display\">\n                    SCORE: <span id=\"score\">0</span>\n                </div>\n            </div>\n\n            <!-- Mini-map -->\n            <canvas class=\"minimap\" id=\"minimap\"></canvas>\n\n            <!-- Action Prompt -->\n            <div class=\"action-prompt\" id=\"action-prompt\"></div>\n\n            <!-- Touch Controls -->\n            <div class=\"touch-controls\" id=\"touch-controls\">\n                <div class=\"virtual-joystick\" id=\"virtual-joystick\">\n                    <div class=\"joystick-base\"></div>\n                    <div class=\"joystick-knob\" id=\"joystick-knob\"></div>\n                </div>\n                <div class=\"touch-button action-button\" id=\"action-button\">E</div>\n                <div class=\"touch-button sprint-button\" id=\"sprint-button\">\u26a1</div>\n                <div class=\"touch-button exit-button\" id=\"exit-button\">EXIT</div>\n                <div class=\"touch-button phone-button\" id=\"phone-button\">\ud83d\udcf1</div>\n            </div>\n\n            <!-- Phone Screen -->\n            <div class=\"phone-screen\" id=\"phone-screen\">\n                <div class=\"phone-header\">\n                    <div class=\"phone-title\" id=\"phone-title\">PHONE</div>\n                    <div class=\"phone-close-btn\" id=\"phone-close-btn\">\u2715</div>\n                </div>\n                <div class=\"phone-content\" id=\"phone-content\">\n                    <!-- Phone menu will be rendered here -->\n                </div>\n                <div class=\"phone-footer\">\n                    LIFECITY MOBILE v1.0\n                </div>\n            </div>\n\n            <!-- Game Over Screen -->\n            <div class=\"game-over-screen\" id=\"game-over-screen\">\n                <div class=\"game-over-title\">BUSTED!</div>\n                <div class=\"game-over-stats\">\n                    <div class=\"stat-line\">FINAL SCORE: <span id=\"final-score\">0</span></div>\n                    <div class=\"stat-line\">CRIMES: <span id=\"final-crimes\">0</span></div>\n                    <div class=\"stat-line\">TIME: <span id=\"final-time\">0</span>s</div>\n                </div>\n                <button class=\"restart-button\" id=\"restart-button\">RESTART</button>\n            </div>\n\n            <!-- Intro Screen -->\n            <div class=\"intro-screen\" id=\"intro-screen\">\n                <div class=\"intro-title\">A GAME BY PIUNOD</div>\n            </div>\n\n            <!-- Story Screen -->\n            <div class=\"lobby-screen hidden\" id=\"story-screen\">\n                <div id=\"story-content\" style=\"max-width: 600px; text-align: center; color: #FFFFFF; font-size: 18px; line-height: 1.6; margin: 40px auto;\">\n                    <!-- Story will be rendered here -->\n                </div>\n                <button class=\"lobby-button\" id=\"story-continue-button\" style=\"margin-top: 40px;\">CONTINUE</button>\n            </div>\n\n            <!-- Lobby Screen -->\n            <div class=\"lobby-screen hidden\" id=\"lobby-screen\">\n                <div class=\"lobby-title\">LIFECITY</div>\n                <div class=\"lobby-buttons\">\n                    <button class=\"lobby-button\" id=\"play-button\">PLAY</button>\n                    <button class=\"lobby-button\" id=\"settings-button\">SETTINGS</button>\n                    <button class=\"lobby-button\" id=\"how-to-play-button\">HOW TO PLAY</button>\n                </div>\n                <div class=\"lobby-version\">v0.2</div>\n            </div>\n\n            <!-- Settings Screen -->\n            <div class=\"settings-screen hidden\" id=\"settings-screen\">\n                <div class=\"settings-title\">SETTINGS</div>\n                <div class=\"settings-content\">\n                    <div class=\"settings-section\">\n                        <div class=\"settings-section-title\">GRAPHICS</div>\n                        <div class=\"settings-item\">\n                            <label>Master Volume</label>\n                            <input type=\"range\" id=\"volume-slider\" min=\"0\" max=\"100\" value=\"50\">\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>\n                                <input type=\"checkbox\" id=\"shadows-toggle\" checked>\n                                Enable Shadows\n                            </label>\n                        </div>\n                    </div>\n\n                    <div class=\"settings-section\">\n                        <div class=\"settings-section-title\">CONTROLS</div>\n                        <div class=\"settings-item\">\n                            <label>Movement: WASD or Arrow Keys</label>\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>Sprint: SHIFT</label>\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>Action: E or Touch Button</label>\n                        </div>\n                    </div>\n\n                    <div class=\"settings-section\">\n                        <div class=\"settings-section-title\">HOW TO PLAY</div>\n                        <div class=\"settings-item\">\n                            <label>\u2022 Explore the city and commit crimes</label>\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>\u2022 Steal cars (5 before police chase)</label>\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>\u2022 Rob the bank for big money</label>\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>\u2022 Punch NPCs to steal their money</label>\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>\u2022 Evade police for as long as possible</label>\n                        </div>\n                        <div class=\"settings-item\">\n                            <label>\u2022 Visit shops to buy items</label>\n                        </div>\n                    </div>\n                </div>\n                <button class=\"back-button\" id=\"back-button\">BACK</button>\n            </div>\n        </div>\n    </div>\n\n    <script>\n        /**\n         * LIFECITY - Top-down open-world crime game\n         * \n         * Core Mechanics:\n         * - Explore a living city with traffic, NPCs, and buildings\n         * - Commit crimes (car theft, bank robbery) to earn points\n         * - Evade police pursuit triggered by wanted level\n         * - Survive as long as possible for high scores\n         * \n         * Technical Architecture:\n         * - Canvas-based rendering with camera system\n         * - Physics simulation for vehicles\n         * - AI systems for traffic, NPCs, and police\n         * - Touch and keyboard controls\n         */\n\n        async function run(mode) {\n            const gameWorld = document.getElementById('game-world');\n            const canvas = document.getElementById('game-canvas');\n            const ctx = canvas.getContext('2d');\n            const minimapCanvas = document.getElementById('minimap');\n            const minimapCtx = minimapCanvas.getContext('2d');\n\n            // Game state for lobby/intro\n            let gamePhase = 'intro'; // 'intro', 'lobby', 'story', 'playing'\n            let introTimer = 2; // Show intro for 2 seconds\n            let introSoundPlayed = false;\n            let storyTimer = 0;\n            let storyPhase = 0; // 0, 1, 2, 3 for different story screens\n\n            // Initialize display\n            function resizeCanvas() {\n                canvas.width = gameWorld.clientWidth;\n                canvas.height = gameWorld.clientHeight;\n                minimapCanvas.width = 160;\n                minimapCanvas.height = 160;\n            }\n            resizeCanvas();\n            window.addEventListener('resize', resizeCanvas);\n\n            // Asset cache\n            const assets = {\n                images: {},\n                audio: {}\n            };\n\n            // Audio context\n            const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n            const audioBuffers = {};\n            const activeSounds = {};\n\n            // Preload assets\n            async function preloadAssets() {\n                const imageIds = [\n                    'player_character_idle', 'player_character_walking',\n                    'npc_civilian_1', 'npc_civilian_2', 'npc_civilian_3',\n                    'civilian_car_sedan', 'civilian_car_suv', 'police_car',\n                    'bank_building', 'building_shop_1', 'building_shop_2',\n                    'building_residential_1', 'building_residential_2',\n                    'tree_1', 'tree_2', 'bench', 'trash_can', 'lamp_post',\n                    'lobby_city_background'\n                ];\n\n                const audioIds = [\n                    'car_theft_sfx', 'bank_robbery_sfx', 'police_siren_sfx',\n                    'car_engine_loop', 'car_crash_sfx', 'game_over_sfx', 'background_music',\n                    'intro_epic_sound'\n                ];\n\n                // Load images\n                const imagePromises = imageIds.map(id => {\n                    return new Promise((resolve, reject) => {\n                        const assetInfo = lib.getAsset(id);\n                        if (!assetInfo) {\n                            resolve();\n                            return;\n                        }\n                        const img = new Image();\n                        img.onload = () => {\n                            assets.images[id] = { img, info: assetInfo };\n                            resolve();\n                        };\n                        img.onerror = () => resolve();\n                        img.src = assetInfo.url;\n                    });\n                });\n\n                // Load audio\n                const audioPromises = audioIds.map(id => {\n                    return new Promise((resolve) => {\n                        const assetInfo = lib.getAsset(id);\n                        if (!assetInfo) {\n                            resolve();\n                            return;\n                        }\n                        fetch(assetInfo.url)\n                            .then(response => response.arrayBuffer())\n                            .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer))\n                            .then(audioBuffer => {\n                                audioBuffers[id] = audioBuffer;\n                                assets.audio[id] = assetInfo;\n                                resolve();\n                            })\n                            .catch(() => resolve());\n                    });\n                });\n\n                await Promise.all([...imagePromises, ...audioPromises]);\n            }\n\n            await preloadAssets();\n\n            // Set lobby background\n            const lobbyBgAsset = assets.images['lobby_city_background'];\n            if (lobbyBgAsset) {\n                const lobbyScreen = document.getElementById('lobby-screen');\n                lobbyScreen.style.backgroundImage = `url('${lobbyBgAsset.info.url}')`;\n                lobbyScreen.style.backgroundSize = 'cover';\n                lobbyScreen.style.backgroundPosition = 'center';\n            }\n\n            // Audio helper functions\n            function playSound(id, loop = false, volume = 1.0) {\n                if (!audioBuffers[id]) return null;\n                \n                const source = audioContext.createBufferSource();\n                const gainNode = audioContext.createGain();\n                \n                source.buffer = audioBuffers[id];\n                source.loop = loop;\n                gainNode.gain.value = volume;\n                \n                source.connect(gainNode);\n                gainNode.connect(audioContext.destination);\n                \n                source.start(0);\n                \n                if (loop) {\n                    activeSounds[id] = { source, gainNode };\n                }\n                \n                return { source, gainNode };\n            }\n\n            function stopSound(id) {\n                if (activeSounds[id]) {\n                    activeSounds[id].source.stop();\n                    delete activeSounds[id];\n                }\n            }\n\n            function setVolume(id, volume) {\n                if (activeSounds[id]) {\n                    activeSounds[id].gainNode.gain.value = volume;\n                }\n            }\n\n            // Detect device capabilities\n            const isTouchDevice = lib.shouldUseTouchControls();\n\n            // Show game parameters\n            lib.showGameParameters({\n                name: \"LIFECITY Settings\",\n                params: {\n                    \"Jacket Color\": { \n                        key: \"player.jacketColor\", \n                        type: \"color\" \n                    },\n                    \"Shirt Color\": { \n                        key: \"player.shirtColor\", \n                        type: \"color\" \n                    },\n                    \"Pants Color\": { \n                        key: \"player.pantsColor\", \n                        type: \"color\" \n                    },\n                    \"Police Aggression\": { \n                        key: \"difficulty.policeAggression\", \n                        type: \"slider\", \n                        min: 0.5, \n                        max: 1.5, \n                        step: 0.1 \n                    },\n                    \"Wanted Decay Speed\": { \n                        key: \"difficulty.wantedDecay\", \n                        type: \"dropdown\", \n                        options: [\n                            { label: \"Slow\", value: 60 },\n                            { label: \"Normal\", value: 30 },\n                            { label: \"Fast\", value: 15 }\n                        ]\n                    },\n                    \"Traffic Density\": { \n                        key: \"difficulty.trafficDensity\", \n                        type: \"dropdown\", \n                        options: [\n                            { label: \"Low\", value: 5 },\n                            { label: \"Medium\", value: 8 },\n                            { label: \"High\", value: 12 }\n                        ]\n                    },\n                    \"Car Theft Points\": { \n                        key: \"rewards.carTheft\", \n                        type: \"slider\", \n                        min: 50, \n                        max: 200, \n                        step: 10 \n                    },\n                    \"Bank Robbery Points\": { \n                        key: \"rewards.bankRobbery\", \n                        type: \"slider\", \n                        min: 200, \n                        max: 1000, \n                        step: 50 \n                    }\n                }\n            });\n\n            // World constants\n            const WORLD_SIZE = 2000;\n            const BLOCK_SIZE = 400;\n            const STREET_WIDTH = 80;\n            const LANE_WIDTH = 40;\n            const GRASS_COLOR = '#2D5016';\n            const ROAD_COLOR = '#3A3A3A';\n            const HOUSE_WIDTH = 120;\n            const HOUSE_HEIGHT = 120;\n            \n            // Job system constants\n            const JOB_STATES = {\n                IDLE: 'idle',\n                PICKUP: 'pickup',\n                DROPOFF: 'dropoff',\n                CHASE: 'chase',\n                RETURN: 'return'\n            };\n\n            // Game state\n            const gameState = {\n                mode: mode,\n                screenShake: 0,\n                player: {\n                    x: WORLD_SIZE / 2,\n                    y: WORLD_SIZE / 2,\n                    vx: 0,\n                    vy: 0,\n                    speed: 150,\n                    sprintSpeed: 250,\n                    angle: 0,\n                    width: 60,\n                    height: 90,\n                    inVehicle: false,\n                    vehicle: null,\n                    isMoving: false,\n                    isSprinting: false,\n                    animationFrame: 0,\n                    animationTimer: 0,\n                    isPunching: false,\n                    punchTimer: 0,\n                    money: 0,\n                    health: 100,\n                    maxHealth: 100,\n                    hunger: 100,\n                    maxHunger: 100,\n                    stamina: 100,\n                    maxStamina: 100,\n                    inHouse: false,\n                    currentHouse: null\n                },\n                phone: {\n                    isOpen: false,\n                    currentScreen: 'menu', // 'menu', 'messages', 'contacts', 'stats', 'settings', 'cheats', 'jobs'\n                    cheatInput: '',\n                    cheatMessage: '',\n                    cheatMessageTimer: 0,\n                    activeCheats: {\n                        moneyBoost: false,\n                        godMode: false,\n                        noPoliceChase: false\n                    }\n                },\n                jobs: {\n                    currentJob: null, // 'taxi', 'doctor', 'police'\n                    jobTimer: 0,\n                    jobDuration: 60, // seconds per job shift\n                    taxiEarnings: 0,\n                    doctorEarnings: 0,\n                    policeEarnings: 0,\n                    totalJobEarnings: 0,\n                    jobState: JOB_STATES.IDLE,\n                    jobVehicle: null,\n                    pickupNPC: null,\n                    pickupLocation: null,\n                    dropoffLocation: null,\n                    targetVehicle: null,\n                    taskTimer: 0,\n                    taskTimeLimit: 0,\n                    jobFailed: false,\n                    jobFailedTimer: 0,\n                    completedTasks: 0, // Track completed tasks\n                    tasksRequired: { 'taxi': 3, 'doctor': 5, 'police': 10 } // Tasks needed to earn money\n                },\n                camera: {\n                    x: WORLD_SIZE / 2,\n                    y: WORLD_SIZE / 2\n                },\n                vehicles: [],\n                npcs: [],\n                police: [],\n                buildings: [],\n                houses: [],\n                trafficLights: [],\n                trees: [],\n                furniture: [],\n                bloodParticles: [],\n                moneyDrops: [],\n                wantedLevel: 0,\n                wantedTimer: 0,\n                policeChaseTimer: 0,\n                score: 0,\n                crimes: 0,\n                carThefts: 0,\n                npcKills: 0,\n                gameTime: 0,\n                gameOver: false,\n                nearestInteractable: null,\n                shopOpen: false,\n                selectedShop: null,\n                // Time and weather system\n                clockTime: 6 * 3600, // Start at 06:00 (in seconds)\n                weatherType: 'clear', // 'clear', 'heat', 'rain', 'storm'\n                weatherTimer: 0,\n                weatherDuration: 60, // seconds per weather cycle\n                rainParticles: [],\n                stormIntensity: 0,\n                // Mission system\n                missions: [\n                    {\n                        id: 1,\n                        title: 'GATHER EVIDENCE',\n                        description: 'Steal from 3 houses to find evidence of corruption',\n                        type: 'houses',\n                        target: 3,\n                        current: 0,\n                        completed: false,\n                        reward: 500\n                    },\n                    {\n                        id: 2,\n                        title: 'ROB THE BANK',\n                        description: 'Rob the bank to expose the corrupt police chief',\n                        type: 'bank',\n                        target: 1,\n                        current: 0,\n                        completed: false,\n                        reward: 1000\n                    },\n                    {\n                        id: 3,\n                        title: 'ESCAPE THE POLICE',\n                        description: 'Survive police chase for 60 seconds',\n                        type: 'survive',\n                        target: 60,\n                        current: 0,\n                        completed: false,\n                        reward: 300\n                    }\n                ],\n                currentMissionIndex: 0,\n                missionStartTime: 0\n            };\n\n            // Input state\n            const input = {\n                keys: {},\n                touch: {\n                    joystick: { active: false, x: 0, y: 0, startX: 0, startY: 0, touchId: null },\n                    action: false,\n                    sprint: false,\n                    exit: false\n                }\n            };\n\n            // Initialize city\n            function initCity() {\n                // Create buildings on grass blocks (between roads) - centered in grass areas\n                // Grass blocks are between roads. Roads are at: 0, 480, 960, 1440, 1920\n                // Grass blocks: 80-400, 560-880, 1040-1360, 1520-1840\n                const buildingPositions = [\n                    // Bank (center grass block) - in block 1040-1360\n                    { x: 1200, y: 1200, type: 'bank_building', width: 200, height: 200, isBank: true, shopType: null, isPolicStation: false, isHospital: false },\n                    \n                    // Police Station (top-left area)\n                    { x: 240, y: 240, type: 'building_shop_1', width: 160, height: 160, isBank: false, shopType: null, isPolicStation: true, isHospital: false },\n                    \n                    // Hospital (top-right area)\n                    { x: 1680, y: 240, type: 'building_shop_2', width: 160, height: 160, isBank: false, shopType: null, isPolicStation: false, isHospital: true },\n                    \n                    // Shops on grass blocks\n                    { x: 720, y: 240, type: 'building_shop_1', width: 120, height: 120, isBank: false, shopType: 'weapon', isPolicStation: false, isHospital: false },\n                    { x: 1200, y: 240, type: 'building_shop_2', width: 120, height: 120, isBank: false, shopType: 'clothing', isPolicStation: false, isHospital: false },\n                    { x: 240, y: 1680, type: 'building_shop_1', width: 120, height: 120, isBank: false, shopType: 'food', isPolicStation: false, isHospital: false },\n                    { x: 1680, y: 1680, type: 'building_shop_2', width: 120, height: 120, isBank: false, shopType: null, isPolicStation: false, isHospital: false },\n                    \n                    // Residential on grass blocks\n                    { x: 720, y: 1680, type: 'building_residential_1', width: 160, height: 160, isBank: false, shopType: null, isPolicStation: false, isHospital: false },\n                    { x: 1200, y: 1680, type: 'building_residential_2', width: 160, height: 160, isBank: false, shopType: null, isPolicStation: false, isHospital: false }\n                ];\n\n                buildingPositions.forEach(pos => {\n                    gameState.buildings.push({\n                        x: pos.x,\n                        y: pos.y,\n                        width: pos.width,\n                        height: pos.height,\n                        type: pos.type,\n                        isBank: pos.isBank,\n                        shopType: pos.shopType,\n                        isPolicStation: pos.isPolicStation,\n                        isHospital: pos.isHospital\n                    });\n                });\n\n                // Create houses scattered around grass blocks\n                const housePositions = [\n                    // Top-left block\n                    { x: 150, y: 150 }, { x: 350, y: 150 }, { x: 150, y: 350 }, { x: 350, y: 350 },\n                    // Top-right block\n                    { x: 1650, y: 150 }, { x: 1850, y: 150 }, { x: 1650, y: 350 }, { x: 1850, y: 350 },\n                    // Bottom-left block\n                    { x: 150, y: 1650 }, { x: 350, y: 1650 }, { x: 150, y: 1850 }, { x: 350, y: 1850 },\n                    // Bottom-right block\n                    { x: 1650, y: 1650 }, { x: 1850, y: 1650 }, { x: 1650, y: 1850 }, { x: 1850, y: 1850 }\n                ];\n\n                housePositions.forEach((pos, index) => {\n                    gameState.houses.push({\n                        id: index,\n                        x: pos.x,\n                        y: pos.y,\n                        width: HOUSE_WIDTH,\n                        height: HOUSE_HEIGHT,\n                        isEntered: false,\n                        hasBeenRobbed: false,\n                        money: 500 + Math.floor(Math.random() * 500),\n                        furniture: [\n                            { name: 'Sofa', value: 200, robbed: false },\n                            { name: 'TV', value: 300, robbed: false },\n                            { name: 'Bed', value: 250, robbed: false },\n                            { name: 'Desk', value: 150, robbed: false },\n                            { name: 'Lamp', value: 100, robbed: false }\n                        ]\n                    });\n                });\n\n                // Create traffic lights at intersections\n                for (let i = 0; i <= 4; i++) {\n                    for (let j = 0; j <= 4; j++) {\n                        const x = i * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                        const y = j * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                        \n                        gameState.trafficLights.push({\n                            x: x,\n                            y: y,\n                            nsState: 'green', // north-south\n                            ewState: 'red',   // east-west\n                            timer: Math.random() * 15,\n                            greenTime: 8,\n                            yellowTime: 2,\n                            redTime: 10\n                        });\n                    }\n                }\n\n                // Create trees\n                const treePositions = [\n                    { x: 300, y: 300 }, { x: 350, y: 320 }, { x: 320, y: 360 },\n                    { x: 1600, y: 300 }, { x: 1650, y: 320 },\n                    { x: 300, y: 1600 }, { x: 350, y: 1620 },\n                    { x: 1600, y: 1600 }, { x: 1650, y: 1620 }\n                ];\n\n                treePositions.forEach((pos, i) => {\n                    gameState.trees.push({\n                        x: pos.x,\n                        y: pos.y,\n                        type: i % 2 === 0 ? 'tree_1' : 'tree_2',\n                        width: 64,\n                        height: 64\n                    });\n                });\n\n                // Create street furniture\n                const furniturePositions = [\n                    { x: 280, y: 280, type: 'bench' },\n                    { x: 1620, y: 280, type: 'bench' },\n                    { x: 280, y: 1620, type: 'trash_can' },\n                    { x: 1620, y: 1620, type: 'trash_can' }\n                ];\n\n                furniturePositions.forEach(pos => {\n                    gameState.furniture.push({\n                        x: pos.x,\n                        y: pos.y,\n                        type: pos.type,\n                        width: pos.type === 'bench' ? 48 : 32,\n                        height: pos.type === 'bench' ? 32 : 32\n                    });\n                });\n\n                // Create NPCs\n                for (let i = 0; i < 15; i++) {\n                    spawnNPC();\n                }\n\n                // Create civilian vehicles\n                const targetCount = window.gameConfig.difficulty.trafficDensity;\n                for (let i = 0; i < targetCount; i++) {\n                    spawnCivilianVehicle();\n                }\n            }\n\n            function isOnRoad(x, y, width, height) {\n                // Check if position overlaps with any road\n                // Horizontal roads\n                for (let i = 0; i <= 4; i++) {\n                    const roadY = i * (BLOCK_SIZE + STREET_WIDTH);\n                    if (y - height / 2 < roadY + STREET_WIDTH && y + height / 2 > roadY) {\n                        return true;\n                    }\n                }\n                \n                // Vertical roads\n                for (let i = 0; i <= 4; i++) {\n                    const roadX = i * (BLOCK_SIZE + STREET_WIDTH);\n                    if (x - width / 2 < roadX + STREET_WIDTH && x + width / 2 > roadX) {\n                        return true;\n                    }\n                }\n                \n                return false;\n            }\n\n            function getClosestRoadLane(x, y) {\n                // Find closest road lane and snap vehicle to it\n                let closestDist = Infinity;\n                let closestLane = null;\n                \n                // Check horizontal roads\n                for (let i = 0; i <= 4; i++) {\n                    const roadY = i * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    const dist = Math.abs(y - roadY);\n                    if (dist < closestDist && dist < STREET_WIDTH / 2) {\n                        closestDist = dist;\n                        closestLane = { type: 'horizontal', y: roadY, x: x };\n                    }\n                }\n                \n                // Check vertical roads\n                for (let i = 0; i <= 4; i++) {\n                    const roadX = i * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    const dist = Math.abs(x - roadX);\n                    if (dist < closestDist && dist < STREET_WIDTH / 2) {\n                        closestDist = dist;\n                        closestLane = { type: 'vertical', x: roadX, y: y };\n                    }\n                }\n                \n                return closestLane;\n            }\n\n            function spawnNPC() {\n                const npcTypes = ['npc_civilian_1', 'npc_civilian_2', 'npc_civilian_3'];\n                const type = npcTypes[Math.floor(Math.random() * npcTypes.length)];\n                \n                // Spawn on sidewalk (not on roads)\n                let x, y;\n                let validSpawn = false;\n                \n                while (!validSpawn) {\n                    x = Math.random() * WORLD_SIZE;\n                    y = Math.random() * WORLD_SIZE;\n                    \n                    // Check if position is NOT on a road\n                    let onRoad = false;\n                    \n                    // Check horizontal roads\n                    for (let i = 0; i <= 4; i++) {\n                        const roadY = i * (BLOCK_SIZE + STREET_WIDTH);\n                        if (y > roadY - 30 && y < roadY + STREET_WIDTH + 30) {\n                            onRoad = true;\n                            break;\n                        }\n                    }\n                    \n                    // Check vertical roads\n                    if (!onRoad) {\n                        for (let i = 0; i <= 4; i++) {\n                            const roadX = i * (BLOCK_SIZE + STREET_WIDTH);\n                            if (x > roadX - 30 && x < roadX + STREET_WIDTH + 30) {\n                                onRoad = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    validSpawn = !onRoad;\n                }\n                \n                gameState.npcs.push({\n                    x: x,\n                    y: y,\n                    vx: 0,\n                    vy: 0,\n                    speed: 50,\n                    type: type,\n                    width: 60,\n                    height: 90,\n                    state: 'walking',\n                    targetX: x + (Math.random() - 0.5) * 200,\n                    targetY: y + (Math.random() - 0.5) * 200,\n                    fleeTimer: 0,\n                    animationFrame: 0,\n                    animationTimer: 0,\n                    health: 100,\n                    maxHealth: 100,\n                    isDead: false,\n                    deathTimer: 0\n                });\n            }\n\n            function spawnCivilianVehicle() {\n                const types = ['civilian_car_sedan', 'civilian_car_suv'];\n                const type = types[Math.floor(Math.random() * types.length)];\n                \n                // Spawn on a road lane\n                const roadChoice = Math.floor(Math.random() * 2); // 0 = horizontal, 1 = vertical\n                let x, y, vx, vy, angle;\n                \n                if (roadChoice === 0) {\n                    // Horizontal road\n                    const roadIndex = Math.floor(Math.random() * 5);\n                    const roadY = roadIndex * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    x = Math.random() * WORLD_SIZE;\n                    y = roadY;\n                    \n                    // Random direction - face the direction of travel\n                    if (Math.random() > 0.5) {\n                        vx = 1;\n                        vy = 0;\n                        angle = 0; // Facing right\n                    } else {\n                        vx = -1;\n                        vy = 0;\n                        angle = Math.PI; // Facing left\n                    }\n                } else {\n                    // Vertical road\n                    const roadIndex = Math.floor(Math.random() * 5);\n                    const roadX = roadIndex * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    x = roadX;\n                    y = Math.random() * WORLD_SIZE;\n                    \n                    // Random direction - face the direction of travel\n                    if (Math.random() > 0.5) {\n                        vx = 0;\n                        vy = 1;\n                        angle = Math.PI / 2; // Facing down\n                    } else {\n                        vx = 0;\n                        vy = -1;\n                        angle = -Math.PI / 2; // Facing up\n                    }\n                }\n                \n                gameState.vehicles.push({\n                    x: x,\n                    y: y,\n                    vx: vx,\n                    vy: vy,\n                    speed: 220, // Increased from 180\n                    maxSpeed: 220, // Increased from 180\n                    angle: angle,\n                    type: type,\n                    width: 64,\n                    height: 96,\n                    isPolice: false,\n                    isCivilian: true,\n                    driver: null,\n                    stoppedAtLight: false,\n                    targetSpeed: 220 // Increased from 180\n                });\n            }\n\n            function updateVehicleAngle(vehicle) {\n                // Update angle to face direction of movement\n                if (Math.abs(vehicle.vx) > 0.1 || Math.abs(vehicle.vy) > 0.1) {\n                    vehicle.angle = Math.atan2(vehicle.vy, vehicle.vx);\n                }\n            }\n\n            function spawnPoliceVehicle() {\n                // Spawn at map edge\n                const edge = Math.floor(Math.random() * 4);\n                let x, y, angle;\n                \n                if (edge === 0) { // top\n                    x = Math.random() * WORLD_SIZE;\n                    y = 0;\n                    angle = Math.PI / 2; // Face down\n                } else if (edge === 1) { // right\n                    x = WORLD_SIZE;\n                    y = Math.random() * WORLD_SIZE;\n                    angle = Math.PI; // Face left\n                } else if (edge === 2) { // bottom\n                    x = Math.random() * WORLD_SIZE;\n                    y = WORLD_SIZE;\n                    angle = -Math.PI / 2; // Face up\n                } else { // left\n                    x = 0;\n                    y = Math.random() * WORLD_SIZE;\n                    angle = 0; // Face right\n                }\n                \n                const police = {\n                    x: x,\n                    y: y,\n                    vx: 0,\n                    vy: 0,\n                    speed: 200 * window.gameConfig.difficulty.policeAggression,\n                    maxSpeed: 200 * window.gameConfig.difficulty.policeAggression,\n                    angle: angle,\n                    type: 'police_car',\n                    width: 80,\n                    height: 120,\n                    isPolice: true,\n                    isCivilian: false,\n                    driver: null\n                };\n                \n                gameState.police.push(police);\n            }\n\n            // Update functions\n            function updatePlayer(deltaTime) {\n                if (gameState.gameOver) return;\n\n                const player = gameState.player;\n                \n                // Update hunger (decreases over time) - unless god mode is active\n                if (!gameState.phone.activeCheats.godMode) {\n                    player.hunger = Math.max(0, player.hunger - deltaTime / 60); // Decreases 1 per minute\n                } else {\n                    player.hunger = player.maxHunger; // Keep at max when god mode active\n                }\n                \n                // Update stamina - unless god mode is active\n                if (!gameState.phone.activeCheats.godMode) {\n                    if (player.isSprinting && player.stamina > 0) {\n                        player.stamina = Math.max(0, player.stamina - deltaTime * 40); // Depletes 40 per second while sprinting\n                    } else if (!player.isSprinting) {\n                        player.stamina = Math.min(player.maxStamina, player.stamina + deltaTime * 30); // Regenerates 30 per second\n                    }\n                } else {\n                    player.stamina = player.maxStamina; // Keep at max when god mode active\n                }\n                \n                // Prevent sprinting if stamina is too low (unless god mode)\n                if (!gameState.phone.activeCheats.godMode && player.stamina < 10) {\n                    player.isSprinting = false;\n                }\n                \n                // Reduce speed if hunger is very low\n                const hungerPenalty = Math.max(0.5, player.hunger / player.maxHunger);\n                \n                // Update punch timer\n                if (player.isPunching) {\n                    player.punchTimer -= deltaTime;\n                    if (player.punchTimer <= 0) {\n                        player.isPunching = false;\n                    }\n                }\n                \n                if (player.inVehicle && player.vehicle) {\n                    // Player is driving\n                    return;\n                }\n\n                // Get input\n                let moveX = 0;\n                let moveY = 0;\n                let sprint = false;\n\n                if (isTouchDevice) {\n                    if (input.touch.joystick.active) {\n                        moveX = input.touch.joystick.x;\n                        moveY = input.touch.joystick.y;\n                    }\n                    sprint = input.touch.sprint;\n                } else {\n                    if (input.keys['w'] || input.keys['arrowup']) moveY -= 1;\n                    if (input.keys['s'] || input.keys['arrowdown']) moveY += 1;\n                    if (input.keys['a'] || input.keys['arrowleft']) moveX -= 1;\n                    if (input.keys['d'] || input.keys['arrowright']) moveX += 1;\n                    sprint = input.keys['shift'];\n                }\n\n                // Normalize diagonal movement\n                const magnitude = Math.sqrt(moveX * moveX + moveY * moveY);\n                if (magnitude > 0) {\n                    moveX /= magnitude;\n                    moveY /= magnitude;\n                }\n\n                player.isMoving = magnitude > 0;\n                player.isSprinting = sprint && player.isMoving && player.stamina > 10;\n\n                // Update animation\n                if (player.isMoving) {\n                    player.animationTimer += deltaTime;\n                    if (player.animationTimer > 0.1) {\n                        player.animationFrame = (player.animationFrame + 1) % 4;\n                        player.animationTimer = 0;\n                    }\n                } else {\n                    player.animationFrame = 0;\n                    player.animationTimer = 0;\n                }\n\n                // Apply movement with hunger penalty\n                const currentSpeed = (player.isSprinting ? player.sprintSpeed : player.speed) * hungerPenalty;\n                player.vx = moveX * currentSpeed;\n                player.vy = moveY * currentSpeed;\n\n                // Update angle to face direction of movement\n                if (player.isMoving) {\n                    player.angle = Math.atan2(moveY, moveX);\n                }\n\n                // Update position\n                player.x += player.vx * deltaTime;\n                player.y += player.vy * deltaTime;\n\n                // Collision with buildings\n                gameState.buildings.forEach(building => {\n                    if (checkAABBCollision(\n                        player.x - player.width / 2, player.y - player.height / 2, player.width, player.height,\n                        building.x - building.width / 2, building.y - building.height / 2, building.width, building.height\n                    )) {\n                        // Push player out\n                        const dx = player.x - building.x;\n                        const dy = player.y - building.y;\n                        const absDx = Math.abs(dx);\n                        const absDy = Math.abs(dy);\n                        \n                        if (absDx > absDy) {\n                            player.x = building.x + Math.sign(dx) * (building.width / 2 + player.width / 2);\n                        } else {\n                            player.y = building.y + Math.sign(dy) * (building.height / 2 + player.height / 2);\n                        }\n                    }\n                });\n\n                // Keep in bounds\n                player.x = Math.max(player.width / 2, Math.min(WORLD_SIZE - player.width / 2, player.x));\n                player.y = Math.max(player.height / 2, Math.min(WORLD_SIZE - player.height / 2, player.y));\n\n                // Check for interactables\n                checkInteractables();\n            }\n\n            function updateVehicles(deltaTime) {\n                if (gameState.gameOver) return;\n\n                gameState.vehicles.forEach((vehicle, index) => {\n                    if (vehicle.driver) return; // Skip player-driven vehicle\n\n                    // Keep vehicle on road lane\n                    const lane = getClosestRoadLane(vehicle.x, vehicle.y);\n                    if (lane) {\n                        if (lane.type === 'horizontal') {\n                            vehicle.y = lane.y;\n                            // Constrain to lane width\n                            vehicle.y = Math.max(lane.y - LANE_WIDTH / 2, Math.min(lane.y + LANE_WIDTH / 2, vehicle.y));\n                        } else {\n                            vehicle.x = lane.x;\n                            // Constrain to lane width\n                            vehicle.x = Math.max(lane.x - LANE_WIDTH / 2, Math.min(lane.x + LANE_WIDTH / 2, vehicle.x));\n                        }\n                    }\n\n                    // Traffic AI\n                    if (vehicle.isCivilian) {\n                        // Check traffic lights\n                        let shouldStop = false;\n                        gameState.trafficLights.forEach(light => {\n                            const dist = Math.hypot(vehicle.x - light.x, vehicle.y - light.y);\n                            if (dist < 100) {\n                                // Determine direction\n                                const angle = Math.atan2(vehicle.vy, vehicle.vx);\n                                const isNS = Math.abs(Math.sin(angle)) > 0.5;\n                                const state = isNS ? light.nsState : light.ewState;\n                                \n                                if (state === 'red' || state === 'yellow') {\n                                    shouldStop = true;\n                                }\n                            }\n                        });\n\n                        vehicle.targetSpeed = shouldStop ? 0 : vehicle.maxSpeed;\n                        \n                        // Smooth speed change\n                        if (vehicle.speed < vehicle.targetSpeed) {\n                            vehicle.speed = Math.min(vehicle.targetSpeed, vehicle.speed + 200 * deltaTime);\n                        } else if (vehicle.speed > vehicle.targetSpeed) {\n                            vehicle.speed = Math.max(vehicle.targetSpeed, vehicle.speed - 200 * deltaTime);\n                        }\n                    }\n\n                    // Update position\n                    const speed = vehicle.speed * deltaTime;\n                    vehicle.x += Math.cos(vehicle.angle) * speed;\n                    vehicle.y += Math.sin(vehicle.angle) * speed;\n                    \n                    // Update vehicle angle to face direction of travel\n                    updateVehicleAngle(vehicle);\n\n                    // Check collision with player (not in vehicle)\n                    if (!gameState.player.inVehicle) {\n                        const dist = Math.hypot(vehicle.x - gameState.player.x, vehicle.y - gameState.player.y);\n                        if (dist < 80) {\n                            // Vehicle stops and honks when player is in front\n                            vehicle.targetSpeed = 0;\n                            vehicle.speed = 0;\n                            \n                            // Honk sound (use car engine as honk substitute)\n                            if (Math.random() < 0.1) {\n                                playSound('car_engine_loop', false, 0.2);\n                            }\n                        }\n                    }\n\n                    // Remove if off-screen (but not job vehicles)\n                    if (!vehicle.isJobVehicle && (vehicle.x < -100 || vehicle.x > WORLD_SIZE + 100 ||\n                        vehicle.y < -100 || vehicle.y > WORLD_SIZE + 100)) {\n                        gameState.vehicles.splice(index, 1);\n                        \n                        // Respawn civilian vehicle\n                        if (vehicle.isCivilian) {\n                            const targetCount = window.gameConfig.difficulty.trafficDensity;\n                            if (gameState.vehicles.filter(v => v.isCivilian).length < targetCount) {\n                                spawnCivilianVehicle();\n                            }\n                        }\n                    }\n                });\n\n                // Update player vehicle\n                if (gameState.player.inVehicle && gameState.player.vehicle) {\n                    updatePlayerVehicle(deltaTime);\n                }\n            }\n\n            function updatePlayerVehicle(deltaTime) {\n                const vehicle = gameState.player.vehicle;\n                const player = gameState.player;\n\n                // Get input\n                let moveX = 0;\n                let moveY = 0;\n\n                if (isTouchDevice) {\n                    if (input.touch.joystick.active) {\n                        moveX = input.touch.joystick.x;\n                        moveY = input.touch.joystick.y;\n                    }\n                } else {\n                    if (input.keys['w'] || input.keys['arrowup']) moveY -= 1;\n                    if (input.keys['s'] || input.keys['arrowdown']) moveY += 1;\n                    if (input.keys['a'] || input.keys['arrowleft']) moveX -= 1;\n                    if (input.keys['d'] || input.keys['arrowright']) moveX += 1;\n                }\n\n                // Normalize diagonal movement\n                const magnitude = Math.sqrt(moveX * moveX + moveY * moveY);\n                if (magnitude > 0) {\n                    moveX /= magnitude;\n                    moveY /= magnitude;\n                }\n\n                // Physics\n                const maxSpeed = vehicle.maxSpeed;\n                const acceleration = 300;\n                const friction = 0.92;\n\n                // Direct movement based on input\n                if (magnitude > 0) {\n                    vehicle.angle = Math.atan2(moveY, moveX);\n                    vehicle.speed = Math.min(maxSpeed, vehicle.speed + acceleration * deltaTime);\n                } else {\n                    vehicle.speed *= friction;\n                }\n\n                vehicle.speed = Math.max(0, vehicle.speed);\n\n                // Update position\n                vehicle.vx = Math.cos(vehicle.angle) * vehicle.speed;\n                vehicle.vy = Math.sin(vehicle.angle) * vehicle.speed;\n                vehicle.x += vehicle.vx * deltaTime;\n                vehicle.y += vehicle.vy * deltaTime;\n\n                // Update player position\n                player.x = vehicle.x;\n                player.y = vehicle.y;\n                player.angle = vehicle.angle;\n\n                // Collision with buildings\n                gameState.buildings.forEach(building => {\n                    if (checkAABBCollision(\n                        vehicle.x - vehicle.width / 2, vehicle.y - vehicle.height / 2, vehicle.width, vehicle.height,\n                        building.x - building.width / 2, building.y - building.height / 2, building.width, building.height\n                    )) {\n                        // Bounce back\n                        vehicle.x -= vehicle.vx * deltaTime * 2;\n                        vehicle.y -= vehicle.vy * deltaTime * 2;\n                        vehicle.speed *= -0.3;\n                        \n                        playSound('car_crash_sfx', false, 0.5);\n                        gameState.screenShake = 15;\n                    }\n                });\n\n                // Keep in bounds\n                vehicle.x = Math.max(vehicle.width / 2, Math.min(WORLD_SIZE - vehicle.width / 2, vehicle.x));\n                vehicle.y = Math.max(vehicle.height / 2, Math.min(WORLD_SIZE - vehicle.height / 2, vehicle.y));\n                player.x = vehicle.x;\n                player.y = vehicle.y;\n            }\n\n            function updateNPCs(deltaTime) {\n                if (gameState.gameOver) return;\n\n                gameState.npcs.forEach((npc, index) => {\n                    if (npc.isDead) {\n                        npc.deathTimer -= deltaTime;\n                        if (npc.deathTimer <= 0) {\n                            gameState.npcs.splice(index, 1);\n                        }\n                        return;\n                    }\n                    \n                    // Update animation\n                    npc.animationTimer += deltaTime;\n                    if (npc.animationTimer > 0.15) {\n                        npc.animationFrame = (npc.animationFrame + 1) % 4;\n                        npc.animationTimer = 0;\n                    }\n                    \n                    if (npc.fleeTimer > 0) {\n                        npc.fleeTimer -= deltaTime;\n                        \n                        // Flee from player\n                        const dx = npc.x - gameState.player.x;\n                        const dy = npc.y - gameState.player.y;\n                        const dist = Math.hypot(dx, dy);\n                        \n                        if (dist > 0) {\n                            npc.vx = (dx / dist) * npc.speed * 2;\n                            npc.vy = (dy / dist) * npc.speed * 2;\n                        }\n                    } else {\n                        // Walk to target\n                        const dx = npc.targetX - npc.x;\n                        const dy = npc.targetY - npc.y;\n                        const dist = Math.hypot(dx, dy);\n                        \n                        if (dist < 10) {\n                            // Pick new target on sidewalk\n                            let validTarget = false;\n                            while (!validTarget) {\n                                npc.targetX = npc.x + (Math.random() - 0.5) * 300;\n                                npc.targetY = npc.y + (Math.random() - 0.5) * 300;\n                                npc.targetX = Math.max(50, Math.min(WORLD_SIZE - 50, npc.targetX));\n                                npc.targetY = Math.max(50, Math.min(WORLD_SIZE - 50, npc.targetY));\n                                \n                                // Check if target is NOT on road\n                                let onRoad = false;\n                                for (let i = 0; i <= 4; i++) {\n                                    const roadY = i * (BLOCK_SIZE + STREET_WIDTH);\n                                    if (npc.targetY > roadY - 30 && npc.targetY < roadY + STREET_WIDTH + 30) {\n                                        onRoad = true;\n                                        break;\n                                    }\n                                }\n                                if (!onRoad) {\n                                    for (let i = 0; i <= 4; i++) {\n                                        const roadX = i * (BLOCK_SIZE + STREET_WIDTH);\n                                        if (npc.targetX > roadX - 30 && npc.targetX < roadX + STREET_WIDTH + 30) {\n                                            onRoad = true;\n                                            break;\n                                        }\n                                    }\n                                }\n                                validTarget = !onRoad;\n                            }\n                        } else {\n                            npc.vx = (dx / dist) * npc.speed;\n                            npc.vy = (dy / dist) * npc.speed;\n                        }\n                    }\n\n                    // Update position\n                    npc.x += npc.vx * deltaTime;\n                    npc.y += npc.vy * deltaTime;\n\n                    // Keep in bounds and off roads\n                    npc.x = Math.max(npc.width / 2, Math.min(WORLD_SIZE - npc.width / 2, npc.x));\n                    npc.y = Math.max(npc.height / 2, Math.min(WORLD_SIZE - npc.height / 2, npc.y));\n                    \n                    // Push away from roads\n                    for (let i = 0; i <= 4; i++) {\n                        const roadY = i * (BLOCK_SIZE + STREET_WIDTH);\n                        if (npc.y > roadY - 40 && npc.y < roadY + STREET_WIDTH + 40) {\n                            if (npc.y < roadY + STREET_WIDTH / 2) {\n                                npc.y = roadY - 40;\n                            } else {\n                                npc.y = roadY + STREET_WIDTH + 40;\n                            }\n                        }\n                    }\n                    \n                    for (let i = 0; i <= 4; i++) {\n                        const roadX = i * (BLOCK_SIZE + STREET_WIDTH);\n                        if (npc.x > roadX - 40 && npc.x < roadX + STREET_WIDTH + 40) {\n                            if (npc.x < roadX + STREET_WIDTH / 2) {\n                                npc.x = roadX - 40;\n                            } else {\n                                npc.x = roadX + STREET_WIDTH + 40;\n                            }\n                        }\n                    }\n\n                    // Check collision with vehicles\n                    gameState.vehicles.forEach(vehicle => {\n                        const dist = Math.hypot(vehicle.x - npc.x, vehicle.y - npc.y);\n                        if (dist < 70) {\n                            // Vehicle hits NPC - deal damage\n                            const damage = 35;\n                            npc.health -= damage;\n                            \n                            // Create blood particles\n                            for (let i = 0; i < 10; i++) {\n                                const angle = (Math.PI * 2 * i) / 10;\n                                gameState.bloodParticles.push({\n                                    x: npc.x,\n                                    y: npc.y - 20,\n                                    vx: Math.cos(angle) * 180,\n                                    vy: Math.sin(angle) * 180 - 50,\n                                    life: 1.0,\n                                    size: 4 + Math.random() * 4\n                                });\n                            }\n                            \n                            // Knock back NPC\n                            const dx = npc.x - vehicle.x;\n                            const dy = npc.y - vehicle.y;\n                            const pushDist = Math.hypot(dx, dy);\n                            if (pushDist > 0) {\n                                npc.vx = (dx / pushDist) * 250;\n                                npc.vy = (dy / pushDist) * 250;\n                            }\n                            \n                            // Check if NPC died\n                            if (npc.health <= 0) {\n                                npc.isDead = true;\n                                npc.deathTimer = 2.0;\n                                \n                                // Drop money\n                                const moneyAmount = 50 + Math.floor(Math.random() * 50);\n                                gameState.moneyDrops.push({\n                                    x: npc.x,\n                                    y: npc.y,\n                                    vx: (Math.random() - 0.5) * 100,\n                                    vy: -100,\n                                    amount: moneyAmount,\n                                    life: 5.0\n                                });\n                            }\n                        }\n                    });\n                });\n            }\n\n            function updatePolice(deltaTime) {\n                if (gameState.gameOver) return;\n\n                // If police immunity cheat is active, don't spawn police\n                if (gameState.phone.activeCheats.noPoliceChase) {\n                    gameState.police = [];\n                    gameState.wantedLevel = 0;\n                    gameState.wantedTimer = 0;\n                    stopSound('police_siren_sfx');\n                    return;\n                }\n\n                // Update police chase timer\n                if (gameState.policeChaseTimer > 0) {\n                    gameState.policeChaseTimer -= deltaTime;\n                    if (gameState.policeChaseTimer <= 0) {\n                        // Police chase time expired - remove all police and reset wanted level\n                        gameState.police = [];\n                        gameState.wantedLevel = 0;\n                        gameState.wantedTimer = 0;\n                        stopSound('police_siren_sfx');\n                        updateWantedDisplay();\n                    }\n                }\n\n                gameState.police.forEach((police, index) => {\n                    // Chase player\n                    const dx = gameState.player.x - police.x;\n                    const dy = gameState.player.y - police.y;\n                    const dist = Math.hypot(dx, dy);\n\n                    if (dist > 0) {\n                        police.angle = Math.atan2(dy, dx);\n                        police.vx = (dx / dist) * police.speed;\n                        police.vy = (dy / dist) * police.speed;\n                    }\n\n                    // Update position\n                    police.x += police.vx * deltaTime;\n                    police.y += police.vy * deltaTime;\n                    \n                    // Update angle to face direction of travel\n                    updateVehicleAngle(police);\n\n                    // Check if caught player\n                    if (!gameState.player.inVehicle) {\n                        const catchDist = Math.hypot(\n                            police.x - gameState.player.x,\n                            police.y - gameState.player.y\n                        );\n                        \n                        if (catchDist < 60) {\n                            gameState.screenShake = 20;\n                            triggerGameOver();\n                        }\n                    }\n\n                    // Remove if too far\n                    if (dist > WORLD_SIZE * 1.5) {\n                        gameState.police.splice(index, 1);\n                    }\n                });\n\n                // Spawn police based on wanted level and chase timer\n                const targetPoliceCount = gameState.wantedLevel;\n                const spawnRate = window.gameConfig.difficulty.policeAggression;\n                \n                if (gameState.policeChaseTimer > 0 && gameState.police.length < targetPoliceCount && Math.random() < spawnRate * deltaTime) {\n                    spawnPoliceVehicle();\n                }\n                \n                // Update survive mission\n                if (gameState.policeChaseTimer > 0 && gameState.missions[2] && gameState.missions[2].type === 'survive') {\n                    const surviveTime = gameState.gameTime - gameState.missionStartTime;\n                    gameState.missions[2].current = Math.floor(surviveTime);\n                    if (gameState.missions[2].current >= gameState.missions[2].target) {\n                        gameState.missions[2].completed = true;\n                    }\n                }\n            }\n\n            function updateBloodParticles(deltaTime) {\n                gameState.bloodParticles.forEach((particle, index) => {\n                    particle.vy += 300 * deltaTime; // Gravity\n                    particle.x += particle.vx * deltaTime;\n                    particle.y += particle.vy * deltaTime;\n                    particle.life -= deltaTime;\n                    \n                    if (particle.life <= 0) {\n                        gameState.bloodParticles.splice(index, 1);\n                    }\n                });\n            }\n\n            function updateMoneyDrops(deltaTime) {\n                gameState.moneyDrops.forEach((drop, index) => {\n                    drop.vy += 200 * deltaTime; // Gravity\n                    drop.x += drop.vx * deltaTime;\n                    drop.y += drop.vy * deltaTime;\n                    drop.life -= deltaTime;\n                    \n                    // Check if player collects money\n                    const dist = Math.hypot(drop.x - gameState.player.x, drop.y - gameState.player.y);\n                    if (dist < 50) {\n                        gameState.player.money += drop.amount;\n                        addScore(50);\n                        gameState.moneyDrops.splice(index, 1);\n                    } else if (drop.life <= 0) {\n                        gameState.moneyDrops.splice(index, 1);\n                    }\n                });\n            }\n\n            function updateTrafficLights(deltaTime) {\n                gameState.trafficLights.forEach(light => {\n                    light.timer += deltaTime;\n                    \n                    const cycleTime = light.greenTime + light.yellowTime + light.redTime;\n                    const phase = light.timer % cycleTime;\n                    \n                    if (phase < light.greenTime) {\n                        light.nsState = 'green';\n                        light.ewState = 'red';\n                    } else if (phase < light.greenTime + light.yellowTime) {\n                        light.nsState = 'yellow';\n                        light.ewState = 'red';\n                    } else if (phase < light.greenTime + light.yellowTime + light.redTime) {\n                        light.nsState = 'red';\n                        light.ewState = 'green';\n                    }\n                });\n            }\n\n            function updateWantedLevel(deltaTime) {\n                if (gameState.wantedLevel > 0) {\n                    gameState.wantedTimer += deltaTime;\n                    \n                    const decayTime = window.gameConfig.difficulty.wantedDecay;\n                    if (gameState.wantedTimer >= decayTime) {\n                        gameState.wantedLevel = Math.max(0, gameState.wantedLevel - 1);\n                        gameState.wantedTimer = 0;\n                        \n                        if (gameState.wantedLevel === 0) {\n                            stopSound('police_siren_sfx');\n                        }\n                    }\n                }\n            }\n\n            function updateJobs(deltaTime) {\n                if (gameState.jobs.currentJob) {\n                    gameState.jobs.jobTimer += deltaTime;\n                    gameState.jobs.taskTimer += deltaTime;\n                    \n                    // Check if job shift ends\n                    if (gameState.jobs.jobTimer >= gameState.jobs.jobDuration) {\n                        completeJobShift();\n                        return;\n                    }\n                    \n                    // Handle job-specific logic\n                    if (gameState.jobs.currentJob === 'taxi') {\n                        updateTaxiJob(deltaTime);\n                    } else if (gameState.jobs.currentJob === 'doctor') {\n                        updateDoctorJob(deltaTime);\n                    } else if (gameState.jobs.currentJob === 'police') {\n                        updatePoliceJob(deltaTime);\n                    }\n                    \n                    // Only award salary if completed tasks requirement is met\n                    const tasksRequired = gameState.jobs.tasksRequired[gameState.jobs.currentJob] || 0;\n                    if (gameState.jobs.completedTasks >= tasksRequired) {\n                        // Base salary accumulation\n                        const salaryRates = {\n                            'taxi': 10,\n                            'doctor': 15,\n                            'police': 20\n                        };\n                        \n                        const rate = salaryRates[gameState.jobs.currentJob] || 0;\n                        const earnings = rate * deltaTime;\n                        \n                        gameState.player.money += earnings;\n                        gameState.jobs.totalJobEarnings += earnings;\n                        \n                        // Track earnings by job type\n                        if (gameState.jobs.currentJob === 'taxi') {\n                            gameState.jobs.taxiEarnings += earnings;\n                        } else if (gameState.jobs.currentJob === 'doctor') {\n                            gameState.jobs.doctorEarnings += earnings;\n                        } else if (gameState.jobs.currentJob === 'police') {\n                            gameState.jobs.policeEarnings += earnings;\n                        }\n                    }\n                }\n                \n                // Show job failed message\n                if (gameState.jobs.jobFailed) {\n                    gameState.jobs.jobFailedTimer -= deltaTime;\n                    if (gameState.jobs.jobFailedTimer <= 0) {\n                        gameState.jobs.jobFailed = false;\n                    }\n                }\n            }\n            \n            function updateTaxiJobDebug(deltaTime) {\n                lib.log(`Taxi Job State: ${gameState.jobs.jobState}, Vehicle: ${gameState.jobs.jobVehicle ? 'exists' : 'null'}, Timer: ${gameState.jobs.taskTimer.toFixed(2)}/${gameState.jobs.taskTimeLimit}`);\n            }\n            \n            function updateTaxiJob(deltaTime) {\n                if (gameState.jobs.jobState === JOB_STATES.IDLE) {\n                    // Spawn taxi and first passenger\n                    if (!gameState.jobs.jobVehicle) {\n                        spawnJobVehicle('taxi');\n                        spawnPickupNPC();\n                        gameState.jobs.jobState = JOB_STATES.PICKUP;\n                        gameState.jobs.taskTimeLimit = 30; // 30 seconds to pickup\n                        gameState.jobs.taskTimer = 0;\n                        lib.log('Taxi job started - vehicle spawned at (' + gameState.jobs.jobVehicle.x + ', ' + gameState.jobs.jobVehicle.y + '), waiting for pickup');\n                    }\n                } else if (gameState.jobs.jobState === JOB_STATES.PICKUP) {\n                    // Check if time limit exceeded\n                    if (gameState.jobs.taskTimer > gameState.jobs.taskTimeLimit) {\n                        failJobTask('PICKUP TIMEOUT!');\n                        return;\n                    }\n                    \n                    // Check if player reached pickup location\n                    if (gameState.player.inVehicle && gameState.jobs.jobVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                        const dist = Math.hypot(gameState.player.x - gameState.jobs.pickupLocation.x, gameState.player.y - gameState.jobs.pickupLocation.y);\n                        if (dist < 100) {\n                            // Pickup successful\n                            gameState.jobs.jobState = JOB_STATES.DROPOFF;\n                            spawnDropoffLocation();\n                            gameState.jobs.taskTimeLimit = 40; // 40 seconds to dropoff\n                            gameState.jobs.taskTimer = 0;\n                            lib.log('Passenger picked up - heading to dropoff');\n                        }\n                    }\n                } else if (gameState.jobs.jobState === JOB_STATES.DROPOFF) {\n                    // Check if time limit exceeded\n                    if (gameState.jobs.taskTimer > gameState.jobs.taskTimeLimit) {\n                        failJobTask('DROPOFF TIMEOUT!');\n                        return;\n                    }\n                    \n                    // Check if player reached dropoff location\n                    if (gameState.player.inVehicle && gameState.jobs.jobVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                        const dist = Math.hypot(gameState.player.x - gameState.jobs.dropoffLocation.x, gameState.player.y - gameState.jobs.dropoffLocation.y);\n                        if (dist < 100) {\n                            // Dropoff successful - repeat\n                            gameState.player.money += 50; // Bonus for completing task\n                            gameState.jobs.completedTasks++; // Increment completed tasks\n                            gameState.jobs.jobState = JOB_STATES.PICKUP;\n                            spawnPickupNPC();\n                            gameState.jobs.taskTimeLimit = 30;\n                            gameState.jobs.taskTimer = 0;\n                            lib.log(`Passenger delivered! Tasks completed: ${gameState.jobs.completedTasks}`);\n                        }\n                    }\n                }\n            }\n            \n            function updateDoctorJob(deltaTime) {\n                if (gameState.jobs.jobState === JOB_STATES.IDLE) {\n                    // Spawn ambulance and first patient\n                    if (!gameState.jobs.jobVehicle) {\n                        spawnJobVehicle('doctor');\n                        spawnPickupNPC();\n                        gameState.jobs.jobState = JOB_STATES.PICKUP;\n                        gameState.jobs.taskTimeLimit = 30;\n                        gameState.jobs.taskTimer = 0;\n                    }\n                } else if (gameState.jobs.jobState === JOB_STATES.PICKUP) {\n                    // Check if time limit exceeded\n                    if (gameState.jobs.taskTimer > gameState.jobs.taskTimeLimit) {\n                        failJobTask('PATIENT PICKUP TIMEOUT!');\n                        return;\n                    }\n                    \n                    // Check if player reached pickup location\n                    if (gameState.player.inVehicle && gameState.jobs.jobVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                        const dist = Math.hypot(gameState.player.x - gameState.jobs.pickupLocation.x, gameState.player.y - gameState.jobs.pickupLocation.y);\n                        if (dist < 100) {\n                            // Pickup successful\n                            gameState.jobs.jobState = JOB_STATES.DROPOFF;\n                            // Dropoff is at hospital\n                            const hospital = gameState.buildings.find(b => b.isHospital);\n                            gameState.jobs.dropoffLocation = { x: hospital.x, y: hospital.y };\n                            gameState.jobs.taskTimeLimit = 40;\n                            gameState.jobs.taskTimer = 0;\n                        }\n                    }\n                } else if (gameState.jobs.jobState === JOB_STATES.DROPOFF) {\n                    // Check if time limit exceeded\n                    if (gameState.jobs.taskTimer > gameState.jobs.taskTimeLimit) {\n                        failJobTask('HOSPITAL DELIVERY TIMEOUT!');\n                        return;\n                    }\n                    \n                    // Check if player reached hospital\n                    if (gameState.player.inVehicle && gameState.jobs.jobVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                        const dist = Math.hypot(gameState.player.x - gameState.jobs.dropoffLocation.x, gameState.player.y - gameState.jobs.dropoffLocation.y);\n                        if (dist < 100) {\n                            // Delivery successful - repeat\n                            gameState.player.money += 75; // Bonus for completing task\n                            gameState.jobs.completedTasks++; // Increment completed tasks\n                            gameState.jobs.jobState = JOB_STATES.PICKUP;\n                            spawnPickupNPC();\n                            gameState.jobs.taskTimeLimit = 30;\n                            gameState.jobs.taskTimer = 0;\n                        }\n                    }\n                }\n            }\n            \n            function updatePoliceJob(deltaTime) {\n                if (gameState.jobs.jobState === JOB_STATES.IDLE) {\n                    // Spawn police car and target vehicle\n                    if (!gameState.jobs.jobVehicle) {\n                        spawnJobVehicle('police');\n                        spawnTargetVehicle();\n                        gameState.jobs.jobState = JOB_STATES.CHASE;\n                        gameState.jobs.taskTimeLimit = 60; // 60 seconds to catch\n                        gameState.jobs.taskTimer = 0;\n                    }\n                } else if (gameState.jobs.jobState === JOB_STATES.CHASE) {\n                    // Check if time limit exceeded\n                    if (gameState.jobs.taskTimer > gameState.jobs.taskTimeLimit) {\n                        failJobTask('SUSPECT ESCAPED!');\n                        return;\n                    }\n                    \n                    // Check if player caught the target vehicle\n                    if (gameState.player.inVehicle && gameState.jobs.jobVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                        if (gameState.jobs.targetVehicle) {\n                            const dist = Math.hypot(gameState.player.x - gameState.jobs.targetVehicle.x, gameState.player.y - gameState.jobs.targetVehicle.y);\n                            if (dist < 80) {\n                                // Target caught - go to police station\n                                gameState.jobs.jobState = JOB_STATES.RETURN;\n                                const policeStation = gameState.buildings.find(b => b.isPolicStation);\n                                gameState.jobs.dropoffLocation = { x: policeStation.x, y: policeStation.y };\n                                gameState.jobs.taskTimeLimit = 30;\n                                gameState.jobs.taskTimer = 0;\n                            }\n                        }\n                    }\n                } else if (gameState.jobs.jobState === JOB_STATES.RETURN) {\n                    // Check if time limit exceeded\n                    if (gameState.jobs.taskTimer > gameState.jobs.taskTimeLimit) {\n                        failJobTask('STATION DELIVERY TIMEOUT!');\n                        return;\n                    }\n                    \n                    // Check if player reached police station\n                    if (gameState.player.inVehicle && gameState.jobs.jobVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                        const dist = Math.hypot(gameState.player.x - gameState.jobs.dropoffLocation.x, gameState.player.y - gameState.jobs.dropoffLocation.y);\n                        if (dist < 100) {\n                            // Delivery successful - repeat\n                            gameState.player.money += 100; // Bonus for completing task\n                            gameState.jobs.completedTasks++; // Increment completed tasks\n                            gameState.jobs.jobState = JOB_STATES.CHASE;\n                            spawnTargetVehicle();\n                            gameState.jobs.taskTimeLimit = 60;\n                            gameState.jobs.taskTimer = 0;\n                        }\n                    }\n                }\n            }\n            \n            function spawnJobVehicle(jobType) {\n                let vehicleType, x, y;\n                \n                // Spawn close to player (within 150 units)\n                const angle = Math.random() * Math.PI * 2;\n                const distance = 100 + Math.random() * 50;\n                x = gameState.player.x + Math.cos(angle) * distance;\n                y = gameState.player.y + Math.sin(angle) * distance;\n                \n                // Clamp to world bounds\n                x = Math.max(50, Math.min(WORLD_SIZE - 50, x));\n                y = Math.max(50, Math.min(WORLD_SIZE - 50, y));\n                \n                if (jobType === 'taxi') {\n                    vehicleType = 'civilian_car_sedan';\n                } else if (jobType === 'doctor') {\n                    vehicleType = 'civilian_car_suv'; // Use SUV as ambulance\n                } else if (jobType === 'police') {\n                    vehicleType = 'police_car';\n                }\n                \n                const vehicle = {\n                    x: x,\n                    y: y,\n                    vx: 0,\n                    vy: 0,\n                    speed: 0,\n                    maxSpeed: 220,\n                    angle: 0,\n                    type: vehicleType,\n                    width: 64,\n                    height: 96,\n                    isPolice: jobType === 'police',\n                    isCivilian: jobType !== 'police',\n                    driver: null,\n                    isJobVehicle: true,\n                    stoppedAtLight: false,\n                    targetSpeed: 0\n                };\n                \n                gameState.vehicles.push(vehicle);\n                gameState.jobs.jobVehicle = vehicle;\n                lib.log('Job vehicle spawned: ' + jobType + ' at (' + x + ', ' + y + ')');\n            }\n            \n            function spawnPickupNPC() {\n                // Spawn NPC at random location on sidewalk\n                let x, y;\n                let validSpawn = false;\n                \n                while (!validSpawn) {\n                    x = Math.random() * WORLD_SIZE;\n                    y = Math.random() * WORLD_SIZE;\n                    \n                    // Check if position is NOT on a road\n                    let onRoad = false;\n                    for (let i = 0; i <= 4; i++) {\n                        const roadY = i * (BLOCK_SIZE + STREET_WIDTH);\n                        if (y > roadY - 30 && y < roadY + STREET_WIDTH + 30) {\n                            onRoad = true;\n                            break;\n                        }\n                    }\n                    \n                    if (!onRoad) {\n                        for (let i = 0; i <= 4; i++) {\n                            const roadX = i * (BLOCK_SIZE + STREET_WIDTH);\n                            if (x > roadX - 30 && x < roadX + STREET_WIDTH + 30) {\n                                onRoad = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    validSpawn = !onRoad;\n                }\n                \n                gameState.jobs.pickupLocation = { x: x, y: y };\n            }\n            \n            function spawnDropoffLocation() {\n                // Spawn random dropoff location on sidewalk\n                let x, y;\n                let validSpawn = false;\n                \n                while (!validSpawn) {\n                    x = Math.random() * WORLD_SIZE;\n                    y = Math.random() * WORLD_SIZE;\n                    \n                    // Check if position is NOT on a road\n                    let onRoad = false;\n                    for (let i = 0; i <= 4; i++) {\n                        const roadY = i * (BLOCK_SIZE + STREET_WIDTH);\n                        if (y > roadY - 30 && y < roadY + STREET_WIDTH + 30) {\n                            onRoad = true;\n                            break;\n                        }\n                    }\n                    \n                    if (!onRoad) {\n                        for (let i = 0; i <= 4; i++) {\n                            const roadX = i * (BLOCK_SIZE + STREET_WIDTH);\n                            if (x > roadX - 30 && x < roadX + STREET_WIDTH + 30) {\n                                onRoad = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    validSpawn = !onRoad;\n                }\n                \n                gameState.jobs.dropoffLocation = { x: x, y: y };\n            }\n            \n            function spawnTargetVehicle() {\n                // Spawn black car on road for police to chase\n                const roadChoice = Math.floor(Math.random() * 2);\n                let x, y, vx, vy, angle;\n                \n                if (roadChoice === 0) {\n                    const roadIndex = Math.floor(Math.random() * 5);\n                    const roadY = roadIndex * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    x = Math.random() * WORLD_SIZE;\n                    y = roadY;\n                    \n                    if (Math.random() > 0.5) {\n                        vx = 1;\n                        vy = 0;\n                        angle = 0;\n                    } else {\n                        vx = -1;\n                        vy = 0;\n                        angle = Math.PI;\n                    }\n                } else {\n                    const roadIndex = Math.floor(Math.random() * 5);\n                    const roadX = roadIndex * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    x = roadX;\n                    y = Math.random() * WORLD_SIZE;\n                    \n                    if (Math.random() > 0.5) {\n                        vx = 0;\n                        vy = 1;\n                        angle = Math.PI / 2;\n                    } else {\n                        vx = 0;\n                        vy = -1;\n                        angle = -Math.PI / 2;\n                    }\n                }\n                \n                const targetVehicle = {\n                    x: x,\n                    y: y,\n                    vx: vx,\n                    vy: vy,\n                    speed: 200,\n                    maxSpeed: 200,\n                    angle: angle,\n                    type: 'civilian_car_sedan',\n                    width: 64,\n                    height: 96,\n                    isPolice: false,\n                    isCivilian: true,\n                    driver: null,\n                    isTargetVehicle: true,\n                    targetSpeed: 200\n                };\n                \n                gameState.vehicles.push(targetVehicle);\n                gameState.jobs.targetVehicle = targetVehicle;\n            }\n            \n            function failJobTask(reason) {\n                gameState.jobs.jobFailed = true;\n                gameState.jobs.jobFailedTimer = 3;\n                gameState.jobs.jobFailedReason = reason;\n                \n                // Lose some money as penalty\n                gameState.player.money = Math.max(0, gameState.player.money - 100);\n                \n                // Reset job state\n                gameState.jobs.jobState = JOB_STATES.IDLE;\n                gameState.jobs.taskTimer = 0;\n            }\n            \n            function completeJobShift() {\n                // Job shift complete\n                gameState.jobs.currentJob = null;\n                gameState.jobs.jobTimer = 0;\n                gameState.jobs.jobState = JOB_STATES.IDLE;\n                gameState.jobs.taskTimer = 0;\n                gameState.jobs.completedTasks = 0; // Reset task counter\n                \n                // Remove job vehicle\n                if (gameState.jobs.jobVehicle) {\n                    const index = gameState.vehicles.indexOf(gameState.jobs.jobVehicle);\n                    if (index > -1) {\n                        gameState.vehicles.splice(index, 1);\n                    }\n                    gameState.jobs.jobVehicle = null;\n                }\n                \n                // Remove target vehicle if police job\n                if (gameState.jobs.targetVehicle) {\n                    const index = gameState.vehicles.indexOf(gameState.jobs.targetVehicle);\n                    if (index > -1) {\n                        gameState.vehicles.splice(index, 1);\n                    }\n                    gameState.jobs.targetVehicle = null;\n                }\n                \n                // Exit vehicle if player is in job vehicle\n                if (gameState.player.inVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                    exitVehicle();\n                }\n            }\n            \n            function quitCurrentJob() {\n                completeJobShift();\n            }\n\n            function updateTimeAndWeather(deltaTime) {\n                // Update game clock (1 real second = 60 game seconds)\n                gameState.clockTime += deltaTime * 60;\n                \n                // Wrap around at 24 hours (86400 seconds)\n                if (gameState.clockTime >= 86400) {\n                    gameState.clockTime = 0;\n                }\n                \n                // Update weather\n                gameState.weatherTimer += deltaTime;\n                \n                if (gameState.weatherTimer >= gameState.weatherDuration) {\n                    gameState.weatherTimer = 0;\n                    \n                    // Random weather selection\n                    const weatherOptions = ['clear', 'heat', 'rain', 'storm'];\n                    gameState.weatherType = weatherOptions[Math.floor(Math.random() * weatherOptions.length)];\n                    \n                    // Vary duration based on weather type\n                    if (gameState.weatherType === 'clear') {\n                        gameState.weatherDuration = 60 + Math.random() * 40;\n                    } else if (gameState.weatherType === 'heat') {\n                        gameState.weatherDuration = 40 + Math.random() * 30;\n                    } else if (gameState.weatherType === 'rain') {\n                        gameState.weatherDuration = 30 + Math.random() * 30;\n                    } else if (gameState.weatherType === 'storm') {\n                        gameState.weatherDuration = 20 + Math.random() * 20;\n                    }\n                }\n                \n                // Update rain particles for rain/storm\n                if (gameState.weatherType === 'rain' || gameState.weatherType === 'storm') {\n                    // Spawn new rain particles\n                    const spawnRate = gameState.weatherType === 'storm' ? 50 : 30;\n                    for (let i = 0; i < spawnRate; i++) {\n                        gameState.rainParticles.push({\n                            x: gameState.camera.x - canvas.width / 2 + Math.random() * canvas.width,\n                            y: gameState.camera.y - canvas.height / 2 - 20,\n                            vx: gameState.weatherType === 'storm' ? (Math.random() - 0.5) * 200 : 0,\n                            vy: gameState.weatherType === 'storm' ? 400 + Math.random() * 200 : 300,\n                            life: 1.0\n                        });\n                    }\n                    \n                    // Update existing rain particles\n                    gameState.rainParticles = gameState.rainParticles.filter(particle => {\n                        particle.y += particle.vy * deltaTime;\n                        particle.x += particle.vx * deltaTime;\n                        particle.life -= deltaTime * 2;\n                        return particle.life > 0;\n                    });\n                    \n                    // Update storm intensity\n                    if (gameState.weatherType === 'storm') {\n                        gameState.stormIntensity = Math.min(1, gameState.stormIntensity + deltaTime * 0.5);\n                    }\n                } else {\n                    gameState.rainParticles = [];\n                    gameState.stormIntensity = Math.max(0, gameState.stormIntensity - deltaTime * 0.3);\n                }\n            }\n\n\n            function checkInteractables() {\n                const player = gameState.player;\n                let nearest = null;\n                let nearestDist = Infinity;\n\n                // Check vehicles\n                if (!player.inVehicle) {\n                    gameState.vehicles.forEach(vehicle => {\n                        const dist = Math.hypot(vehicle.x - player.x, vehicle.y - player.y);\n                        if (dist < 100 && dist < nearestDist && !vehicle.driver) {\n                            nearest = { type: 'vehicle', object: vehicle };\n                            nearestDist = dist;\n                        }\n                    });\n                }\n\n                // Check bank\n                gameState.buildings.forEach(building => {\n                    if (building.isBank) {\n                        const dist = Math.hypot(building.x - player.x, building.y - player.y);\n                        if (dist < 150 && dist < nearestDist) {\n                            nearest = { type: 'bank', object: building };\n                            nearestDist = dist;\n                        }\n                    }\n                });\n\n                // Check houses\n                gameState.houses.forEach(house => {\n                    const dist = Math.hypot(house.x - player.x, house.y - player.y);\n                    if (dist < 100 && dist < nearestDist) {\n                        nearest = { type: 'house', object: house };\n                        nearestDist = dist;\n                    }\n                });\n\n                // Check shops\n                gameState.buildings.forEach(building => {\n                    if (building.shopType) {\n                        const dist = Math.hypot(building.x - player.x, building.y - player.y);\n                        if (dist < 150 && dist < nearestDist) {\n                            nearest = { type: 'shop', object: building };\n                            nearestDist = dist;\n                        }\n                    }\n                });\n\n                // Check NPCs\n                gameState.npcs.forEach(npc => {\n                    if (!npc.isDead) {\n                        const dist = Math.hypot(npc.x - player.x, npc.y - player.y);\n                        if (dist < 100 && dist < nearestDist) {\n                            nearest = { type: 'npc', object: npc };\n                            nearestDist = dist;\n                        }\n                    }\n                });\n\n                gameState.nearestInteractable = nearest;\n                updateActionPrompt();\n            }\n\n            function updateActionPrompt() {\n                const prompt = document.getElementById('action-prompt');\n                const actionButton = document.getElementById('action-button');\n                \n                if (gameState.player.inHouse) {\n                    prompt.textContent = 'Press E to Exit House';\n                    prompt.classList.add('visible');\n                    actionButton.textContent = 'EXIT';\n                } else if (gameState.player.inVehicle) {\n                    prompt.textContent = 'Press E to Exit Vehicle';\n                    prompt.classList.add('visible');\n                    actionButton.textContent = 'EXIT';\n                } else if (gameState.nearestInteractable) {\n                    if (gameState.nearestInteractable.type === 'vehicle') {\n                        prompt.textContent = 'Press E to Steal Car';\n                        prompt.classList.add('visible');\n                        actionButton.textContent = 'STEAL';\n                    } else if (gameState.nearestInteractable.type === 'bank') {\n                        prompt.textContent = 'Press E to Rob Bank';\n                        prompt.classList.add('visible');\n                        actionButton.textContent = 'ROB';\n                    } else if (gameState.nearestInteractable.type === 'house') {\n                        const house = gameState.nearestInteractable.object;\n                        if (house.hasBeenRobbed) {\n                            prompt.textContent = 'Press E to Enter House (Empty)';\n                        } else {\n                            prompt.textContent = 'Press E to Enter House';\n                        }\n                        prompt.classList.add('visible');\n                        actionButton.textContent = 'ENTER';\n                    } else if (gameState.nearestInteractable.type === 'shop') {\n                        const shopType = gameState.nearestInteractable.object.shopType;\n                        const shopNames = { weapon: 'Weapon', clothing: 'Clothing', food: 'Food' };\n                        prompt.textContent = `Press E to Enter ${shopNames[shopType]} Shop`;\n                        prompt.classList.add('visible');\n                        actionButton.textContent = 'SHOP';\n                    } else if (gameState.nearestInteractable.type === 'npc') {\n                        prompt.textContent = 'Press E to Punch';\n                        prompt.classList.add('visible');\n                        actionButton.textContent = 'PUNCH';\n                    }\n                } else {\n                    prompt.classList.remove('visible');\n                    actionButton.textContent = 'E';\n                }\n            }\n\n            function performAction() {\n                if (gameState.gameOver) return;\n\n                if (gameState.player.inHouse) {\n                    exitHouse();\n                } else if (gameState.player.inVehicle) {\n                    exitVehicle();\n                } else if (gameState.nearestInteractable) {\n                    if (gameState.nearestInteractable.type === 'vehicle') {\n                        stealCar(gameState.nearestInteractable.object);\n                    } else if (gameState.nearestInteractable.type === 'bank') {\n                        robBank();\n                    } else if (gameState.nearestInteractable.type === 'house') {\n                        enterHouse(gameState.nearestInteractable.object);\n                    } else if (gameState.nearestInteractable.type === 'shop') {\n                        openShop(gameState.nearestInteractable.object);\n                    } else if (gameState.nearestInteractable.type === 'npc') {\n                        punchNPC(gameState.nearestInteractable.object);\n                    }\n                } else {\n                    // Try to punch nearby NPCs\n                    punchNearbyNPC();\n                }\n            }\n\n            function enterHouse(house) {\n                gameState.player.inHouse = true;\n                gameState.player.currentHouse = house;\n                house.isEntered = true;\n                \n                updateActionPrompt();\n            }\n\n            function exitHouse() {\n                gameState.player.inHouse = false;\n                gameState.player.currentHouse = null;\n                \n                updateActionPrompt();\n            }\n\n            function robHouse(house) {\n                if (house.hasBeenRobbed) {\n                    addScore(10); // Small score for entering empty house\n                    return;\n                }\n                \n                // Rob money from house\n                const moneyStolen = house.money;\n                gameState.player.money += moneyStolen;\n                addScore(moneyStolen / 2);\n                gameState.crimes++;\n                \n                // Rob furniture\n                let furnitureValue = 0;\n                house.furniture.forEach(item => {\n                    if (!item.robbed) {\n                        item.robbed = true;\n                        furnitureValue += item.value;\n                    }\n                });\n                \n                gameState.player.money += furnitureValue;\n                addScore(furnitureValue / 2);\n                \n                house.hasBeenRobbed = true;\n                \n                // Update mission progress\n                if (gameState.missions[0] && gameState.missions[0].type === 'houses') {\n                    gameState.missions[0].current++;\n                    if (gameState.missions[0].current >= gameState.missions[0].target) {\n                        gameState.missions[0].completed = true;\n                    }\n                }\n                \n                // Trigger police\n                increaseWantedLevel(1);\n                gameState.policeChaseTimer = 300;\n                \n                // Make NPCs flee\n                gameState.npcs.forEach(npc => {\n                    const dist = Math.hypot(npc.x - gameState.player.x, npc.y - gameState.player.y);\n                    if (dist < 400) {\n                        npc.fleeTimer = 3;\n                    }\n                });\n            }\n\n            function stealCar(vehicle) {\n                gameState.player.inVehicle = true;\n                gameState.player.vehicle = vehicle;\n                vehicle.driver = gameState.player;\n                \n                playSound('car_theft_sfx', false, 0.7);\n                playSound('car_engine_loop', true, 0.3);\n                \n                gameState.carThefts++;\n                \n                // Only trigger police after 5 car thefts\n                if (gameState.carThefts >= 5) {\n                    increaseWantedLevel(1);\n                    gameState.policeChaseTimer = 300; // 5 minutes in seconds\n                }\n                \n                addScore(window.gameConfig.rewards.carTheft);\n                gameState.crimes++;\n                \n                // Make NPCs flee\n                gameState.npcs.forEach(npc => {\n                    const dist = Math.hypot(npc.x - gameState.player.x, npc.y - gameState.player.y);\n                    if (dist < 300) {\n                        npc.fleeTimer = 3;\n                    }\n                });\n                \n                document.getElementById('exit-button').classList.add('visible');\n            }\n\n            function exitVehicle() {\n                if (gameState.player.vehicle) {\n                    gameState.player.vehicle.driver = null;\n                    gameState.player.vehicle = null;\n                }\n                gameState.player.inVehicle = false;\n                \n                stopSound('car_engine_loop');\n                \n                document.getElementById('exit-button').classList.remove('visible');\n            }\n\n            function punchNPC(npc) {\n                if (npc.isDead) return;\n                \n                // Trigger punch animation\n                gameState.player.isPunching = true;\n                gameState.player.punchTimer = 0.3;\n                \n                // Deal damage\n                const damage = 25;\n                npc.health -= damage;\n                \n                // Create blood particles\n                for (let i = 0; i < 8; i++) {\n                    const angle = (Math.PI * 2 * i) / 8;\n                    gameState.bloodParticles.push({\n                        x: npc.x,\n                        y: npc.y - 20,\n                        vx: Math.cos(angle) * 150,\n                        vy: Math.sin(angle) * 150 - 50,\n                        life: 1.0,\n                        size: 4 + Math.random() * 4\n                    });\n                }\n                \n                // Make NPC flee\n                npc.fleeTimer = 3;\n                \n                // Knock back NPC\n                const dx = npc.x - gameState.player.x;\n                const dy = npc.y - gameState.player.y;\n                const dist = Math.hypot(dx, dy);\n                \n                if (dist > 0) {\n                    npc.vx = (dx / dist) * 200;\n                    npc.vy = (dy / dist) * 200;\n                }\n                \n                // Add score for punching\n                addScore(25);\n                gameState.crimes++;\n                \n                // Check if NPC died\n                if (npc.health <= 0) {\n                    npc.isDead = true;\n                    npc.deathTimer = 2.0;\n                    \n                    // Increment NPC kills\n                    gameState.npcKills = (gameState.npcKills || 0) + 1;\n                    \n                    // Only trigger police after 3 kills\n                    if (gameState.npcKills >= 3) {\n                        increaseWantedLevel(2);\n                        gameState.policeChaseTimer = 300; // 5 minutes police chase\n                    }\n                    \n                    // Drop money\n                    const moneyAmount = 50 + Math.floor(Math.random() * 50);\n                    gameState.moneyDrops.push({\n                        x: npc.x,\n                        y: npc.y,\n                        vx: (Math.random() - 0.5) * 100,\n                        vy: -100,\n                        amount: moneyAmount,\n                        life: 5.0\n                    });\n                    \n                    addScore(100);\n                    gameState.player.money += moneyAmount;\n                }\n            }\n\n            function punchNearbyNPC() {\n                // Find closest NPC within punch range\n                let closest = null;\n                let closestDist = 100;\n                \n                gameState.npcs.forEach(npc => {\n                    const dist = Math.hypot(npc.x - gameState.player.x, npc.y - gameState.player.y);\n                    if (dist < closestDist) {\n                        closest = npc;\n                        closestDist = dist;\n                    }\n                });\n                \n                if (closest) {\n                    punchNPC(closest);\n                }\n            }\n\n            function robBank() {\n                playSound('bank_robbery_sfx', false, 0.7);\n                \n                increaseWantedLevel(2);\n                addScore(window.gameConfig.rewards.bankRobbery);\n                gameState.crimes++;\n                \n                // Add money from bank robbery\n                const bankMoney = 1000 + Math.floor(Math.random() * 500);\n                gameState.player.money += bankMoney;\n                \n                // Update mission progress\n                if (gameState.missions[1] && gameState.missions[1].type === 'bank') {\n                    gameState.missions[1].current++;\n                    if (gameState.missions[1].current >= gameState.missions[1].target) {\n                        gameState.missions[1].completed = true;\n                    }\n                }\n                \n                // Make all NPCs flee\n                gameState.npcs.forEach(npc => {\n                    npc.fleeTimer = 5;\n                });\n                \n                gameState.policeChaseTimer = 300; // 5 minutes police chase\n            }\n\n            function increaseWantedLevel(amount) {\n                gameState.wantedLevel = Math.min(3, gameState.wantedLevel + amount);\n                gameState.wantedTimer = 0;\n                \n                updateWantedDisplay();\n                \n                if (gameState.wantedLevel > 0 && !activeSounds['police_siren_sfx']) {\n                    playSound('police_siren_sfx', true, 0.4);\n                }\n            }\n\n            function addScore(points) {\n                gameState.score += points;\n                document.getElementById('score').textContent = gameState.score;\n            }\n\n            function updateWantedDisplay() {\n                for (let i = 1; i <= 3; i++) {\n                    const star = document.getElementById(`star${i}`);\n                    if (i <= gameState.wantedLevel) {\n                        star.classList.remove('inactive');\n                    } else {\n                        star.classList.add('inactive');\n                    }\n                }\n            }\n\n            function updateStatBars() {\n                const hungerPercent = (gameState.player.hunger / gameState.player.maxHunger) * 100;\n                const staminaPercent = (gameState.player.stamina / gameState.player.maxStamina) * 100;\n                \n                document.getElementById('hunger-bar').style.width = hungerPercent + '%';\n                document.getElementById('stamina-bar').style.width = staminaPercent + '%';\n            }\n\n            function triggerGameOver() {\n                gameState.gameOver = true;\n                \n                stopSound('police_siren_sfx');\n                stopSound('car_engine_loop');\n                stopSound('background_music');\n                playSound('game_over_sfx', false, 0.8);\n                \n                document.getElementById('final-score').textContent = gameState.score;\n                document.getElementById('final-crimes').textContent = gameState.crimes;\n                document.getElementById('final-time').textContent = Math.floor(gameState.gameTime);\n                document.getElementById('game-over-screen').classList.add('visible');\n            }\n\n            function openShop(building) {\n                gameState.shopOpen = true;\n                gameState.selectedShop = building;\n            }\n\n            function closeShop() {\n                gameState.shopOpen = false;\n                gameState.selectedShop = null;\n            }\n\n            function buyItem(itemIndex) {\n                if (!gameState.shopItems || itemIndex >= gameState.shopItems.length) return;\n                \n                const item = gameState.shopItems[itemIndex];\n                if (gameState.player.money >= item.cost) {\n                    gameState.player.money -= item.cost;\n                    addScore(10);\n                    \n                    // Apply item effects based on type\n                    if (item.type === 'food') {\n                        gameState.player.hunger = Math.min(gameState.player.maxHunger, gameState.player.hunger + 50);\n                        updateStatBars();\n                    }\n                    \n                    return true;\n                }\n                return false;\n            }\n\n            // Collision detection\n            function checkAABBCollision(x1, y1, w1, h1, x2, y2, w2, h2) {\n                return x1 < x2 + w2 &&\n                       x1 + w1 > x2 &&\n                       y1 < y2 + h2 &&\n                       y1 + h1 > y2;\n            }\n\n            // Rendering\n            function render() {\n                // Clear canvas\n                ctx.fillStyle = GRASS_COLOR;\n                ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n                ctx.save();\n                \n                // Apply camera transform and screen shake\n                const shakeX = (Math.random() - 0.5) * gameState.screenShake;\n                const shakeY = (Math.random() - 0.5) * gameState.screenShake;\n                ctx.translate(canvas.width / 2 - gameState.camera.x + shakeX, canvas.height / 2 - gameState.camera.y + shakeY);\n\n                // Render world\n                renderRoads();\n                renderBuildings();\n                renderHouses();\n                renderTrees();\n                renderFurniture();\n                renderVehicles();\n                renderNPCs();\n                renderPlayer();\n                renderPolice();\n                renderTrafficLights();\n                renderBloodParticles();\n                renderMoneyDrops();\n                renderWeather();\n\n                ctx.restore();\n\n                // Apply Lighting Pass (64-bit style HDR lighting)\n                renderLighting();\n\n                // Render minimap\n                renderMinimap();\n                \n                // Render UI\n                renderUI();\n                \n                // Decay screen shake\n                if (gameState.screenShake > 0) {\n                    gameState.screenShake *= 0.9;\n                }\n            }\n\n            function renderLighting() {\n                // Create lighting overlay\n                ctx.save();\n                \n                // Ambient darkness based on time of day\n                const hours = (gameState.clockTime / 3600) % 24;\n                let ambientAlpha = 0;\n                \n                if (hours < 5 || hours > 19) ambientAlpha = 0.6; // Night\n                else if (hours < 7) ambientAlpha = 0.3 * (1 - (hours - 5) / 2); // Dawn\n                else if (hours > 17) ambientAlpha = 0.3 * ((hours - 17) / 2); // Dusk\n                \n                if (gameState.weatherType === 'storm') ambientAlpha = Math.max(ambientAlpha, 0.5);\n\n                if (ambientAlpha > 0) {\n                    ctx.fillStyle = `rgba(0, 5, 20, ${ambientAlpha})`;\n                    ctx.fillRect(0, 0, canvas.width, canvas.height);\n                    \n                    // Composite light sources (Simple additive blend)\n                    ctx.globalCompositeOperation = 'lighter';\n                    \n                    // Lights follow camera\n                    const camX = canvas.width / 2 - gameState.camera.x;\n                    const camY = canvas.height / 2 - gameState.camera.y;\n\n                    // 1. Street Lamps\n                    gameState.furniture.forEach(item => {\n                        if (item.type === 'lamp_post') {\n                            drawLight(item.x + camX, item.y + camY, 150, 'rgba(255, 200, 100, 0.4)');\n                        }\n                    });\n\n                    // 2. Police Sirens\n                    gameState.police.forEach(p => {\n                        const time = Date.now() / 200;\n                        const color = Math.floor(time) % 2 === 0 ? 'rgba(0, 0, 255, 0.5)' : 'rgba(255, 0, 0, 0.5)';\n                        drawLight(p.x + camX, p.y + camY, 200, color);\n                    });\n                    \n                    // 3. Traffic Lights\n                    gameState.trafficLights.forEach(l => {\n                        const nsColor = l.nsState === 'green' ? 'rgba(0, 255, 0, 0.3)' : l.nsState === 'yellow' ? 'rgba(255, 255, 0, 0.3)' : 'rgba(255, 0, 0, 0.3)';\n                        drawLight(l.x + camX - 20, l.y + camY, 60, nsColor);\n                    });\n                }\n                \n                // Vignette\n                const gradient = ctx.createRadialGradient(canvas.width/2, canvas.height/2, canvas.width/4, canvas.width/2, canvas.height/2, canvas.width);\n                gradient.addColorStop(0, 'rgba(0,0,0,0)');\n                gradient.addColorStop(1, 'rgba(0,0,0,0.5)');\n                ctx.fillStyle = gradient;\n                ctx.globalCompositeOperation = 'source-over';\n                ctx.fillRect(0, 0, canvas.width, canvas.height);\n                \n                ctx.restore();\n            }\n\n            function drawLight(x, y, radius, color) {\n                const grad = ctx.createRadialGradient(x, y, 0, x, y, radius);\n                grad.addColorStop(0, color);\n                grad.addColorStop(1, 'rgba(0,0,0,0)');\n                ctx.fillStyle = grad;\n                ctx.beginPath();\n                ctx.arc(x, y, radius, 0, Math.PI * 2);\n                ctx.fill();\n            }\n\n            function renderRoads() {\n                // Draw roads with gradient\n                ctx.fillStyle = '#3A3A3A';\n                \n                // Horizontal roads\n                for (let i = 0; i <= 4; i++) {\n                    const y = i * (BLOCK_SIZE + STREET_WIDTH);\n                    ctx.fillRect(0, y, WORLD_SIZE, STREET_WIDTH);\n                    \n                    // Add road edge shadow\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';\n                    ctx.fillRect(0, y, WORLD_SIZE, 3);\n                    ctx.fillStyle = '#3A3A3A';\n                }\n                \n                // Vertical roads\n                for (let i = 0; i <= 4; i++) {\n                    const x = i * (BLOCK_SIZE + STREET_WIDTH);\n                    ctx.fillRect(x, 0, STREET_WIDTH, WORLD_SIZE);\n                    \n                    // Add road edge shadow\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';\n                    ctx.fillRect(x, 0, 3, WORLD_SIZE);\n                    ctx.fillStyle = '#3A3A3A';\n                }\n                \n                // Draw lane markings\n                ctx.strokeStyle = '#FFFFFF';\n                ctx.lineWidth = 2;\n                ctx.setLineDash([20, 20]);\n                \n                // Horizontal lane markings\n                for (let i = 0; i <= 4; i++) {\n                    const y = i * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    ctx.beginPath();\n                    ctx.moveTo(0, y);\n                    ctx.lineTo(WORLD_SIZE, y);\n                    ctx.stroke();\n                }\n                \n                // Vertical lane markings\n                for (let i = 0; i <= 4; i++) {\n                    const x = i * (BLOCK_SIZE + STREET_WIDTH) + STREET_WIDTH / 2;\n                    ctx.beginPath();\n                    ctx.moveTo(x, 0);\n                    ctx.lineTo(x, WORLD_SIZE);\n                    ctx.stroke();\n                }\n                \n                ctx.setLineDash([]);\n                \n                // Draw sidewalks with gradient\n                ctx.fillStyle = '#C0C0C0';\n                const sidewalkWidth = 20;\n                \n                // Around roads\n                for (let i = 0; i <= 4; i++) {\n                    const y = i * (BLOCK_SIZE + STREET_WIDTH);\n                    ctx.fillRect(0, y - sidewalkWidth, WORLD_SIZE, sidewalkWidth);\n                    ctx.fillRect(0, y + STREET_WIDTH, WORLD_SIZE, sidewalkWidth);\n                }\n                \n                for (let i = 0; i <= 4; i++) {\n                    const x = i * (BLOCK_SIZE + STREET_WIDTH);\n                    ctx.fillRect(x - sidewalkWidth, 0, sidewalkWidth, WORLD_SIZE);\n                    ctx.fillRect(x + STREET_WIDTH, 0, sidewalkWidth, WORLD_SIZE);\n                }\n            }\n\n            function renderBuildings() {\n                gameState.buildings.forEach(building => {\n                    // Draw shadow\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';\n                    ctx.fillRect(\n                        building.x - building.width / 2 + 4,\n                        building.y - building.height / 2 + 4,\n                        building.width,\n                        building.height\n                    );\n                    \n                    const asset = assets.images[building.type];\n                    if (asset) {\n                        drawImage(asset.img, building.x, building.y, building.width, building.height);\n                    } else {\n                        // Fallback\n                        ctx.fillStyle = building.isBank ? '#E8D4B0' : '#A0522D';\n                        ctx.fillRect(\n                            building.x - building.width / 2,\n                            building.y - building.height / 2,\n                            building.width,\n                            building.height\n                        );\n                    }\n                });\n            }\n\n            function renderHouses() {\n                gameState.houses.forEach(house => {\n                    // Draw shadow\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';\n                    ctx.fillRect(\n                        house.x - house.width / 2 + 4,\n                        house.y - house.height / 2 + 4,\n                        house.width,\n                        house.height\n                    );\n                    \n                    // Draw house body\n                    ctx.fillStyle = house.hasBeenRobbed ? '#8B4513' : '#A0522D';\n                    ctx.fillRect(\n                        house.x - house.width / 2,\n                        house.y - house.height / 2,\n                        house.width,\n                        house.height\n                    );\n                    \n                    // Draw roof\n                    ctx.fillStyle = house.hasBeenRobbed ? '#654321' : '#8B0000';\n                    ctx.beginPath();\n                    ctx.moveTo(house.x - house.width / 2, house.y - house.height / 2);\n                    ctx.lineTo(house.x, house.y - house.height / 2 - 20);\n                    ctx.lineTo(house.x + house.width / 2, house.y - house.height / 2);\n                    ctx.fill();\n                    \n                    // Draw door\n                    ctx.fillStyle = '#654321';\n                    ctx.fillRect(\n                        house.x - 15,\n                        house.y + house.height / 2 - 30,\n                        30,\n                        30\n                    );\n                    \n                    // Draw door handle\n                    ctx.fillStyle = '#FFD700';\n                    ctx.beginPath();\n                    ctx.arc(house.x + 10, house.y + house.height / 2 - 15, 3, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // Draw windows\n                    ctx.fillStyle = '#87CEEB';\n                    ctx.fillRect(house.x - 30, house.y - 15, 15, 15);\n                    ctx.fillRect(house.x + 15, house.y - 15, 15, 15);\n                    \n                    // Draw window panes\n                    ctx.strokeStyle = '#000000';\n                    ctx.lineWidth = 1;\n                    ctx.beginPath();\n                    ctx.moveTo(house.x - 22, house.y - 15);\n                    ctx.lineTo(house.x - 22, house.y);\n                    ctx.stroke();\n                    ctx.beginPath();\n                    ctx.moveTo(house.x - 30, house.y - 7);\n                    ctx.lineTo(house.x - 15, house.y - 7);\n                    ctx.stroke();\n                    \n                    ctx.beginPath();\n                    ctx.moveTo(house.x + 22, house.y - 15);\n                    ctx.lineTo(house.x + 22, house.y);\n                    ctx.stroke();\n                    ctx.beginPath();\n                    ctx.moveTo(house.x + 15, house.y - 7);\n                    ctx.lineTo(house.x + 30, house.y - 7);\n                    ctx.stroke();\n                    \n                    // Draw robbed indicator\n                    if (house.hasBeenRobbed) {\n                        ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';\n                        ctx.font = 'bold 12px Arial';\n                        ctx.textAlign = 'center';\n                        ctx.textBaseline = 'middle';\n                        ctx.fillText('ROBBED', house.x, house.y);\n                    }\n                });\n            }\n\n            function renderTrees() {\n                gameState.trees.forEach(tree => {\n                    // Draw shadow\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.15)';\n                    ctx.beginPath();\n                    ctx.ellipse(tree.x + 3, tree.y + tree.height / 2 - 3, tree.width / 2 - 5, 6, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    const asset = assets.images[tree.type];\n                    if (asset) {\n                        drawImage(asset.img, tree.x, tree.y, tree.width, tree.height);\n                    }\n                });\n            }\n\n            function renderFurniture() {\n                gameState.furniture.forEach(item => {\n                    // Draw shadow\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.15)';\n                    ctx.fillRect(\n                        item.x - item.width / 2 + 2,\n                        item.y - item.height / 2 + 2,\n                        item.width,\n                        item.height\n                    );\n                    \n                    const asset = assets.images[item.type];\n                    if (asset) {\n                        drawImage(asset.img, item.x, item.y, item.width, item.height);\n                    }\n                });\n            }\n\n            function renderVehicles() {\n                gameState.vehicles.forEach(vehicle => {\n                    if (vehicle === gameState.player.vehicle) return; // Skip player vehicle\n                    \n                    // Draw shadow\n                    ctx.save();\n                    ctx.translate(vehicle.x, vehicle.y);\n                    ctx.rotate(vehicle.angle);\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';\n                    ctx.fillRect(-vehicle.width / 2 + 3, -vehicle.height / 2 + 3, vehicle.width, vehicle.height);\n                    ctx.restore();\n                    \n                    const asset = assets.images[vehicle.type];\n                    if (asset) {\n                        drawImageRotated(asset.img, vehicle.x, vehicle.y, vehicle.width, vehicle.height, vehicle.angle);\n                    }\n                });\n                \n                // Render player vehicle last (on top)\n                if (gameState.player.inVehicle && gameState.player.vehicle) {\n                    const vehicle = gameState.player.vehicle;\n                    \n                    // Draw shadow\n                    ctx.save();\n                    ctx.translate(vehicle.x, vehicle.y);\n                    ctx.rotate(vehicle.angle);\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';\n                    ctx.fillRect(-vehicle.width / 2 + 3, -vehicle.height / 2 + 3, vehicle.width, vehicle.height);\n                    ctx.restore();\n                    \n                    const asset = assets.images[vehicle.type];\n                    if (asset) {\n                        drawImageRotated(asset.img, vehicle.x, vehicle.y, vehicle.width, vehicle.height, vehicle.angle);\n                    }\n                }\n            }\n\n            function renderNPCs() {\n                gameState.npcs.forEach(npc => {\n                    // Draw shadow\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';\n                    ctx.beginPath();\n                    ctx.ellipse(npc.x + 2, npc.y + npc.height / 2 - 5, npc.width / 2 - 5, 8, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    const asset = assets.images[npc.type];\n                    if (asset) {\n                        drawImage(asset.img, npc.x, npc.y, npc.width, npc.height);\n                    }\n                    \n                    // Draw health bar if damaged\n                    if (npc.health < npc.maxHealth) {\n                        const barWidth = 50;\n                        const barHeight = 6;\n                        const barX = npc.x - barWidth / 2;\n                        const barY = npc.y - npc.height / 2 - 15;\n                        \n                        // Background\n                        ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';\n                        ctx.fillRect(barX, barY, barWidth, barHeight);\n                        \n                        // Health\n                        const healthPercent = npc.health / npc.maxHealth;\n                        ctx.fillStyle = healthPercent > 0.5 ? '#00FF00' : healthPercent > 0.25 ? '#FFFF00' : '#FF0000';\n                        ctx.fillRect(barX, barY, barWidth * healthPercent, barHeight);\n                        \n                        // Border\n                        ctx.strokeStyle = '#FFFFFF';\n                        ctx.lineWidth = 1;\n                        ctx.strokeRect(barX, barY, barWidth, barHeight);\n                    }\n                });\n            }\n\n            function renderPlayer() {\n                if (gameState.player.inVehicle) return; // Don't render player when in vehicle\n                \n                const player = gameState.player;\n                \n                // Draw shadow\n                ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';\n                ctx.beginPath();\n                ctx.ellipse(player.x + 2, player.y + player.height / 2 - 5, player.width / 2 - 5, 8, 0, 0, Math.PI * 2);\n                ctx.fill();\n                \n                // Draw punch effect\n                if (player.isPunching) {\n                    ctx.fillStyle = 'rgba(255, 200, 0, 0.4)';\n                    ctx.beginPath();\n                    ctx.arc(player.x, player.y, 40, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n                \n                const assetId = player.isMoving ? 'player_character_walking' : 'player_character_idle';\n                const asset = assets.images[assetId];\n                \n                if (asset) {\n                    drawImage(asset.img, player.x, player.y, player.width, player.height);\n                }\n            }\n\n            function renderPolice() {\n                gameState.police.forEach(police => {\n                    // Draw shadow\n                    ctx.save();\n                    ctx.translate(police.x, police.y);\n                    ctx.rotate(police.angle);\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';\n                    ctx.fillRect(-police.width / 2 + 3, -police.height / 2 + 3, police.width, police.height);\n                    ctx.restore();\n                    \n                    const asset = assets.images[police.type];\n                    if (asset) {\n                        drawImageRotated(asset.img, police.x, police.y, police.width, police.height, police.angle);\n                        \n                        // Draw siren effect\n                        const time = Date.now() / 200;\n                        const color = Math.floor(time) % 2 === 0 ? '#0D47A1' : '#C62828';\n                        ctx.fillStyle = color;\n                        ctx.globalAlpha = 0.6;\n                        ctx.beginPath();\n                        ctx.arc(police.x, police.y - police.height / 2, 15, 0, Math.PI * 2);\n                        ctx.fill();\n                        ctx.globalAlpha = 1;\n                    }\n                });\n            }\n\n            function renderTrafficLights() {\n                gameState.trafficLights.forEach(light => {\n                    const size = 12;\n                    \n                    // North-South lights\n                    const nsColor = light.nsState === 'green' ? '#00FF00' : \n                                   light.nsState === 'yellow' ? '#FFFF00' : '#FF0000';\n                    ctx.fillStyle = nsColor;\n                    ctx.shadowBlur = 10;\n                    ctx.shadowColor = nsColor;\n                    ctx.beginPath();\n                    ctx.arc(light.x - 20, light.y, size, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    // East-West lights\n                    const ewColor = light.ewState === 'green' ? '#00FF00' : \n                                   light.ewState === 'yellow' ? '#FFFF00' : '#FF0000';\n                    ctx.fillStyle = ewColor;\n                    ctx.shadowColor = ewColor;\n                    ctx.beginPath();\n                    ctx.arc(light.x + 20, light.y, size, 0, Math.PI * 2);\n                    ctx.fill();\n                    \n                    ctx.shadowBlur = 0;\n                });\n            }\n\n            function renderBloodParticles() {\n                gameState.bloodParticles.forEach(particle => {\n                    ctx.fillStyle = `rgba(255, 0, 0, ${particle.life})`;\n                    ctx.beginPath();\n                    ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);\n                    ctx.fill();\n                });\n            }\n\n            function renderMoneyDrops() {\n                gameState.moneyDrops.forEach(drop => {\n                    ctx.fillStyle = `rgba(255, 215, 0, ${drop.life})`;\n                    ctx.font = 'bold 16px Arial';\n                    ctx.textAlign = 'center';\n                    ctx.textBaseline = 'middle';\n                    ctx.fillText('$' + drop.amount, drop.x, drop.y);\n                });\n            }\n\n            function renderWeather() {\n                if (gameState.weatherType === 'rain' || gameState.weatherType === 'storm') {\n                    // Draw rain particles\n                    ctx.strokeStyle = gameState.weatherType === 'storm' ? 'rgba(150, 150, 200, 0.8)' : 'rgba(200, 220, 255, 0.6)';\n                    ctx.lineWidth = gameState.weatherType === 'storm' ? 3 : 2;\n                    \n                    gameState.rainParticles.forEach(particle => {\n                        ctx.globalAlpha = particle.life * 0.8;\n                        ctx.beginPath();\n                        ctx.moveTo(particle.x, particle.y);\n                        ctx.lineTo(particle.x + particle.vx * 0.02, particle.y + 10);\n                        ctx.stroke();\n                    });\n                    ctx.globalAlpha = 1;\n                    \n                    // Storm lightning effect\n                    if (gameState.weatherType === 'storm' && gameState.stormIntensity > 0.5) {\n                        if (Math.random() < gameState.stormIntensity * 0.05) {\n                            ctx.fillStyle = `rgba(255, 255, 255, ${gameState.stormIntensity * 0.3})`;\n                            ctx.fillRect(-10000, -10000, 20000, 20000);\n                        }\n                    }\n                } else if (gameState.weatherType === 'heat') {\n                    // Heat haze effect\n                    ctx.fillStyle = `rgba(255, 200, 0, ${0.1 * Math.sin(gameState.gameTime * 3)})`;\n                    ctx.fillRect(-10000, -10000, 20000, 20000);\n                }\n            }\n\n            function renderMinimap() {\n                const mmCtx = minimapCtx;\n                const scale = 160 / WORLD_SIZE;\n                \n                // Clear\n                mmCtx.fillStyle = '#1A1A1A';\n                mmCtx.fillRect(0, 0, 160, 160);\n                \n                // Draw roads\n                mmCtx.fillStyle = '#3A3A3A';\n                for (let i = 0; i <= 4; i++) {\n                    const y = i * (BLOCK_SIZE + STREET_WIDTH) * scale;\n                    mmCtx.fillRect(0, y, 160, STREET_WIDTH * scale);\n                }\n                for (let i = 0; i <= 4; i++) {\n                    const x = i * (BLOCK_SIZE + STREET_WIDTH) * scale;\n                    mmCtx.fillRect(x, 0, STREET_WIDTH * scale, 160);\n                }\n                \n                // Draw bank\n                gameState.buildings.forEach(building => {\n                    if (building.isBank) {\n                        mmCtx.fillStyle = '#FFD700';\n                        mmCtx.fillRect(\n                            (building.x - building.width / 2) * scale,\n                            (building.y - building.height / 2) * scale,\n                            building.width * scale,\n                            building.height * scale\n                        );\n                    }\n                });\n                \n                // Draw police\n                mmCtx.fillStyle = '#FF0000';\n                gameState.police.forEach(police => {\n                    mmCtx.beginPath();\n                    mmCtx.arc(police.x * scale, police.y * scale, 3, 0, Math.PI * 2);\n                    mmCtx.fill();\n                });\n                \n                // Draw player\n                mmCtx.fillStyle = '#2E5C9A';\n                mmCtx.beginPath();\n                mmCtx.arc(gameState.player.x * scale, gameState.player.y * scale, 4, 0, Math.PI * 2);\n                mmCtx.fill();\n            }\n\n            function drawImage(img, x, y, width, height) {\n                ctx.drawImage(\n                    img,\n                    x - width / 2,\n                    y - height / 2,\n                    width,\n                    height\n                );\n            }\n\n            function drawImageRotated(img, x, y, width, height, angle) {\n                ctx.save();\n                ctx.translate(x, y);\n                ctx.rotate(angle);\n                ctx.drawImage(img, -width / 2, -height / 2, width, height);\n                ctx.restore();\n            }\n\n            function renderUI() {\n                // Render money display\n                ctx.fillStyle = '#FFFFFF';\n                ctx.font = 'bold 24px Arial';\n                ctx.textAlign = 'left';\n                ctx.textBaseline = 'top';\n                ctx.fillText('MONEY: $' + gameState.player.money, 20, 80);\n                \n                // Render current job status\n                if (gameState.jobs.currentJob) {\n                    ctx.fillStyle = '#00FF00';\n                    ctx.font = 'bold 18px Arial';\n                    ctx.fillText('JOB: ' + gameState.jobs.currentJob.toUpperCase(), 20, 50);\n                    \n                    // Show if player is in job vehicle\n                    if (gameState.player.inVehicle && gameState.jobs.jobVehicle && gameState.player.vehicle === gameState.jobs.jobVehicle) {\n                        ctx.fillStyle = '#00FFFF';\n                        ctx.font = 'bold 16px Arial';\n                        ctx.fillText('IN VEHICLE \u2713', 20, 25);\n                    }\n                }\n                \n                // Render job failed message\n                if (gameState.jobs.jobFailed) {\n                    ctx.fillStyle = 'rgba(255, 0, 0, 0.8)';\n                    ctx.font = 'bold 28px Arial';\n                    ctx.textAlign = 'center';\n                    ctx.textBaseline = 'middle';\n                    ctx.fillText(gameState.jobs.jobFailedReason, canvas.width / 2, 100);\n                }\n                \n                // Render current mission\n                const currentMission = gameState.missions[gameState.currentMissionIndex];\n                if (currentMission && !currentMission.completed) {\n                    ctx.fillStyle = '#FFD700';\n                    ctx.font = 'bold 18px Arial';\n                    ctx.textAlign = 'left';\n                    ctx.textBaseline = 'top';\n                    ctx.fillText('MISSION: ' + currentMission.title, 20, 160);\n                    \n                    ctx.fillStyle = '#FFFFFF';\n                    ctx.font = '16px Arial';\n                    ctx.fillText(currentMission.description, 20, 185);\n                    \n                    // Progress bar\n                    const progressWidth = 200;\n                    const progressHeight = 20;\n                    const progressX = 20;\n                    const progressY = 210;\n                    \n                    // Background\n                    ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';\n                    ctx.fillRect(progressX, progressY, progressWidth, progressHeight);\n                    \n                    // Progress\n                    const progress = Math.min(1, currentMission.current / currentMission.target);\n                    ctx.fillStyle = '#00FF00';\n                    ctx.fillRect(progressX, progressY, progressWidth * progress, progressHeight);\n                    \n                    // Border\n                    ctx.strokeStyle = '#FFFFFF';\n                    ctx.lineWidth = 2;\n                    ctx.strokeRect(progressX, progressY, progressWidth, progressHeight);\n                    \n                    // Text\n                    ctx.fillStyle = '#FFFFFF';\n                    ctx.font = 'bold 14px Arial';\n                    ctx.textAlign = 'center';\n                    ctx.fillText(`${currentMission.current}/${currentMission.target}`, progressX + progressWidth / 2, progressY + 14);\n                } else if (gameState.currentMissionIndex < gameState.missions.length - 1) {\n                    // Show next mission\n                    gameState.currentMissionIndex++;\n                    const nextMission = gameState.missions[gameState.currentMissionIndex];\n                    if (nextMission) {\n                        ctx.fillStyle = '#FFD700';\n                        ctx.font = 'bold 18px Arial';\n                        ctx.fillText('NEXT MISSION: ' + nextMission.title, 20, 160);\n                    }\n                } else if (gameState.missions.every(m => m.completed)) {\n                    // All missions complete\n                    ctx.fillStyle = '#00FF00';\n                    ctx.font = 'bold 24px Arial';\n                    ctx.fillText('ALL MISSIONS COMPLETE!', 20, 160);\n                    ctx.fillStyle = '#FFD700';\n                    ctx.font = 'bold 18px Arial';\n                    ctx.fillText('Escape the police to win!', 20, 190);\n                }\n                \n                // Render time display\n                const timeStr = formatGameTime(gameState.clockTime);\n                ctx.fillStyle = '#FFD700';\n                ctx.font = 'bold 20px Arial';\n                ctx.fillText('TIME: ' + timeStr, 20, 110);\n                \n                // Render weather display\n                const weatherNames = {\n                    'clear': 'CLEAR',\n                    'heat': 'HEAT WAVE',\n                    'rain': 'RAIN',\n                    'storm': 'STORM'\n                };\n                const weatherColors = {\n                    'clear': '#87CEEB',\n                    'heat': '#FF6B6B',\n                    'rain': '#4A90E2',\n                    'storm': '#2C3E50'\n                };\n                ctx.fillStyle = weatherColors[gameState.weatherType];\n                ctx.font = 'bold 18px Arial';\n                ctx.fillText('WEATHER: ' + weatherNames[gameState.weatherType], 20, 135);\n                \n                // Render job waypoints and indicators\n                if (gameState.jobs.currentJob && gameState.jobs.jobState !== JOB_STATES.IDLE) {\n                    renderJobWaypoints();\n                }\n                \n                // Render house interior if player is in house\n                if (gameState.player.inHouse && gameState.player.currentHouse) {\n                    renderHouseInterior();\n                }\n                \n                // Render shop UI if open\n                if (gameState.shopOpen && gameState.selectedShop) {\n                    renderShopUI();\n                }\n            }\n            \n            function renderJobWaypoints() {\n                // Draw job vehicle location first (always show where the job vehicle is)\n                if (gameState.jobs.jobVehicle && !gameState.player.inVehicle) {\n                    drawWaypoint({ x: gameState.jobs.jobVehicle.x, y: gameState.jobs.jobVehicle.y }, 'VEHICLE', '#00FFFF');\n                }\n                \n                // Draw waypoint indicators on screen\n                if (gameState.jobs.jobState === JOB_STATES.PICKUP && gameState.jobs.pickupLocation) {\n                    drawWaypoint(gameState.jobs.pickupLocation, 'PICKUP', '#00FF00');\n                } else if (gameState.jobs.jobState === JOB_STATES.DROPOFF && gameState.jobs.dropoffLocation) {\n                    drawWaypoint(gameState.jobs.dropoffLocation, 'DROPOFF', '#FFD700');\n                } else if (gameState.jobs.jobState === JOB_STATES.CHASE && gameState.jobs.targetVehicle) {\n                    drawWaypoint({ x: gameState.jobs.targetVehicle.x, y: gameState.jobs.targetVehicle.y }, 'CHASE', '#FF0000');\n                } else if (gameState.jobs.jobState === JOB_STATES.RETURN && gameState.jobs.dropoffLocation) {\n                    drawWaypoint(gameState.jobs.dropoffLocation, 'STATION', '#0099FF');\n                }\n                \n                // Draw task timer\n                ctx.fillStyle = '#FFD700';\n                ctx.font = 'bold 18px Arial';\n                ctx.textAlign = 'right';\n                ctx.textBaseline = 'top';\n                const timeRemaining = Math.max(0, gameState.jobs.taskTimeLimit - gameState.jobs.taskTimer);\n                ctx.fillText(`TIME: ${Math.ceil(timeRemaining)}s`, canvas.width - 20, 80);\n            }\n            \n            function drawWaypoint(location, label, color) {\n                // Convert world coordinates to screen coordinates\n                const screenX = location.x - gameState.camera.x + canvas.width / 2;\n                const screenY = location.y - gameState.camera.y + canvas.height / 2;\n                \n                // Draw even if slightly off-screen for edge indicators\n                const arrowSize = 30;\n                \n                // Clamp to screen edges if off-screen\n                let drawX = screenX;\n                let drawY = screenY;\n                let isOffScreen = false;\n                \n                if (screenX < 0) {\n                    drawX = 50;\n                    isOffScreen = true;\n                } else if (screenX > canvas.width) {\n                    drawX = canvas.width - 50;\n                    isOffScreen = true;\n                }\n                \n                if (screenY < 0) {\n                    drawY = 50;\n                    isOffScreen = true;\n                } else if (screenY > canvas.height) {\n                    drawY = canvas.height - 50;\n                    isOffScreen = true;\n                }\n                \n                // Draw arrow pointing to waypoint\n                ctx.fillStyle = color;\n                ctx.globalAlpha = 0.9;\n                \n                // Draw circle\n                ctx.beginPath();\n                ctx.arc(drawX, drawY, arrowSize, 0, Math.PI * 2);\n                ctx.fill();\n                \n                // Draw border\n                ctx.strokeStyle = '#FFFFFF';\n                ctx.lineWidth = 3;\n                ctx.stroke();\n                \n                // Draw label\n                ctx.fillStyle = '#000000';\n                ctx.font = 'bold 14px Arial';\n                ctx.textAlign = 'center';\n                ctx.textBaseline = 'middle';\n                ctx.fillText(label, drawX, drawY);\n                \n                // If on-screen, draw distance\n                if (!isOffScreen) {\n                    const dist = Math.hypot(screenX - canvas.width / 2, screenY - canvas.height / 2);\n                    ctx.fillStyle = '#FFFFFF';\n                    ctx.font = 'bold 12px Arial';\n                    ctx.fillText(`${Math.floor(dist)}m`, drawX, drawY + arrowSize + 15);\n                }\n                \n                ctx.globalAlpha = 1;\n            }\n\n            function renderHouseInterior() {\n                const house = gameState.player.currentHouse;\n                \n                // Semi-transparent overlay\n                ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';\n                ctx.fillRect(0, 0, canvas.width, canvas.height);\n                \n                // House interior panel\n                const panelWidth = 500;\n                const panelHeight = 650;\n                const panelX = (canvas.width - panelWidth) / 2;\n                const panelY = (canvas.height - panelHeight) / 2;\n                \n                ctx.fillStyle = '#8B7355';\n                ctx.fillRect(panelX, panelY, panelWidth, panelHeight);\n                \n                // Border\n                ctx.strokeStyle = '#654321';\n                ctx.lineWidth = 4;\n                ctx.strokeRect(panelX, panelY, panelWidth, panelHeight);\n                \n                // Close button (X)\n                const closeButtonSize = 40;\n                const closeButtonX = panelX + panelWidth - closeButtonSize - 10;\n                const closeButtonY = panelY + 10;\n                \n                ctx.fillStyle = '#FF0000';\n                ctx.fillRect(closeButtonX, closeButtonY, closeButtonSize, closeButtonSize);\n                \n                ctx.strokeStyle = '#FFFFFF';\n                ctx.lineWidth = 2;\n                ctx.strokeRect(closeButtonX, closeButtonY, closeButtonSize, closeButtonSize);\n                \n                // X symbol\n                ctx.strokeStyle = '#FFFFFF';\n                ctx.lineWidth = 3;\n                ctx.beginPath();\n                ctx.moveTo(closeButtonX + 8, closeButtonY + 8);\n                ctx.lineTo(closeButtonX + closeButtonSize - 8, closeButtonY + closeButtonSize - 8);\n                ctx.stroke();\n                \n                ctx.beginPath();\n                ctx.moveTo(closeButtonX + closeButtonSize - 8, closeButtonY + 8);\n                ctx.lineTo(closeButtonX + 8, closeButtonY + closeButtonSize - 8);\n                ctx.stroke();\n                \n                // Store close button position for click detection\n                gameState.houseCloseButtonX = closeButtonX;\n                gameState.houseCloseButtonY = closeButtonY;\n                gameState.houseCloseButtonSize = closeButtonSize;\n                \n                // Title\n                ctx.fillStyle = '#FFD700';\n                ctx.font = 'bold 28px Arial';\n                ctx.textAlign = 'center';\n                ctx.textBaseline = 'top';\n                ctx.fillText('HOUSE INTERIOR', canvas.width / 2, panelY + 20);\n                \n                // Status\n                ctx.fillStyle = house.hasBeenRobbed ? '#FF6666' : '#66FF66';\n                ctx.font = 'bold 18px Arial';\n                ctx.fillText(house.hasBeenRobbed ? 'ALREADY ROBBED' : 'NOT ROBBED', canvas.width / 2, panelY + 55);\n                \n                // Furniture list\n                ctx.fillStyle = '#FFFFFF';\n                ctx.font = 'bold 16px Arial';\n                ctx.textAlign = 'left';\n                ctx.textBaseline = 'top';\n                ctx.fillText('FURNITURE:', panelX + 20, panelY + 90);\n                \n                let yOffset = panelY + 120;\n                const itemHeight = 45;\n                \n                house.furniture.forEach((item, index) => {\n                    const itemY = yOffset;\n                    \n                    // Item background (clickable area)\n                    if (item.robbed) {\n                        ctx.fillStyle = 'rgba(100, 100, 100, 0.3)';\n                    } else {\n                        ctx.fillStyle = 'rgba(100, 200, 100, 0.2)';\n                    }\n                    ctx.fillRect(panelX + 10, itemY - 5, panelWidth - 20, itemHeight);\n                    \n                    // Item text\n                    ctx.fillStyle = item.robbed ? '#888888' : '#FFFFFF';\n                    ctx.font = '16px Arial';\n                    ctx.fillText(`${index + 1}. ${item.name}`, panelX + 30, itemY + 5);\n                    \n                    // Value\n                    ctx.fillStyle = item.robbed ? '#666666' : '#FFD700';\n                    ctx.textAlign = 'right';\n                    ctx.fillText(`$${item.value}${item.robbed ? ' (STOLEN)' : ''}`, panelX + panelWidth - 30, itemY + 5);\n                    ctx.textAlign = 'left';\n                    \n                    yOffset += itemHeight + 5;\n                });\n                \n                // Money in house\n                ctx.fillStyle = '#FFFFFF';\n                ctx.font = 'bold 16px Arial';\n                ctx.fillText('CASH IN HOUSE:', panelX + 20, yOffset + 10);\n                \n                ctx.fillStyle = house.hasBeenRobbed ? '#FF6666' : '#66FF66';\n                ctx.font = 'bold 18px Arial';\n                ctx.fillText(`$${house.hasBeenRobbed ? '0' : house.money}`, panelX + 30, yOffset + 35);\n                \n                // Rob button\n                if (!house.hasBeenRobbed) {\n                    const robButtonX = panelX + 30;\n                    const robButtonY = yOffset + 70;\n                    const robButtonWidth = panelWidth - 60;\n                    const robButtonHeight = 50;\n                    \n                    ctx.fillStyle = '#FF0000';\n                    ctx.fillRect(robButtonX, robButtonY, robButtonWidth, robButtonHeight);\n                    \n                    ctx.strokeStyle = '#FFFFFF';\n                    ctx.lineWidth = 2;\n                    ctx.strokeRect(robButtonX, robButtonY, robButtonWidth, robButtonHeight);\n                    \n                    ctx.fillStyle = '#FFFFFF';\n                    ctx.font = 'bold 20px Arial';\n                    ctx.textAlign = 'center';\n                    ctx.textBaseline = 'middle';\n                    ctx.fillText('ROB HOUSE', robButtonX + robButtonWidth / 2, robButtonY + robButtonHeight / 2);\n                    \n                    // Store button position for click detection\n                    gameState.robHouseButtonX = robButtonX;\n                    gameState.robHouseButtonY = robButtonY;\n                    gameState.robHouseButtonWidth = robButtonWidth;\n                    gameState.robHouseButtonHeight = robButtonHeight;\n                }\n                \n                // Instructions\n                ctx.fillStyle = '#AAAAAA';\n                ctx.font = '14px Arial';\n                ctx.textAlign = 'left';\n                ctx.fillText('Click ROB button or Press E to exit', panelX + 30, panelY + panelHeight - 20);\n            }\n\n            function renderShopUI() {\n                const shop = gameState.selectedShop;\n                const shopType = shop.shopType;\n                \n                // Semi-transparent overlay\n                ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';\n                ctx.fillRect(0, 0, canvas.width, canvas.height);\n                \n                // Shop panel\n                const panelWidth = 450;\n                const panelHeight = 600;\n                const panelX = (canvas.width - panelWidth) / 2;\n                const panelY = (canvas.height - panelHeight) / 2;\n                \n                ctx.fillStyle = '#1A1A1A';\n                ctx.fillRect(panelX, panelY, panelWidth, panelHeight);\n                \n                // Border\n                ctx.strokeStyle = '#FFD700';\n                ctx.lineWidth = 3;\n                ctx.strokeRect(panelX, panelY, panelWidth, panelHeight);\n                \n                // Close button (X)\n                const closeButtonSize = 40;\n                const closeButtonX = panelX + panelWidth - closeButtonSize - 10;\n                const closeButtonY = panelY + 10;\n                \n                ctx.fillStyle = '#FF0000';\n                ctx.fillRect(closeButtonX, closeButtonY, closeButtonSize, closeButtonSize);\n                \n                ctx.strokeStyle = '#FFFFFF';\n                ctx.lineWidth = 2;\n                ctx.strokeRect(closeButtonX, closeButtonY, closeButtonSize, closeButtonSize);\n                \n                // X symbol\n                ctx.strokeStyle = '#FFFFFF';\n                ctx.lineWidth = 3;\n                ctx.beginPath();\n                ctx.moveTo(closeButtonX + 8, closeButtonY + 8);\n                ctx.lineTo(closeButtonX + closeButtonSize - 8, closeButtonY + closeButtonSize - 8);\n                ctx.stroke();\n                \n                ctx.beginPath();\n                ctx.moveTo(closeButtonX + closeButtonSize - 8, closeButtonY + 8);\n                ctx.lineTo(closeButtonX + 8, closeButtonY + closeButtonSize - 8);\n                ctx.stroke();\n                \n                // Store close button position for click detection\n                gameState.shopCloseButtonX = closeButtonX;\n                gameState.shopCloseButtonY = closeButtonY;\n                gameState.shopCloseButtonSize = closeButtonSize;\n                \n                // Title\n                ctx.fillStyle = '#FFD700';\n                ctx.font = 'bold 28px Arial';\n                ctx.textAlign = 'center';\n                ctx.textBaseline = 'top';\n                const shopNames = { weapon: 'WEAPON SHOP', clothing: 'CLOTHING SHOP', food: 'FOOD SHOP' };\n                ctx.fillText(shopNames[shopType], canvas.width / 2, panelY + 20);\n                \n                // Items\n                ctx.fillStyle = '#FFFFFF';\n                ctx.font = '16px Arial';\n                ctx.textAlign = 'left';\n                ctx.textBaseline = 'top';\n                \n                let items = [];\n                if (shopType === 'weapon') {\n                    items = [\n                        { name: 'Pistol', cost: 200, type: 'weapon' },\n                        { name: 'Shotgun', cost: 500, type: 'weapon' },\n                        { name: 'Rifle', cost: 800, type: 'weapon' },\n                        { name: 'Grenade', cost: 300, type: 'weapon' }\n                    ];\n                } else if (shopType === 'clothing') {\n                    items = [\n                        { name: 'Red Jacket', cost: 150, type: 'clothing' },\n                        { name: 'Black Suit', cost: 300, type: 'clothing' },\n                        { name: 'Gold Chain', cost: 250, type: 'clothing' },\n                        { name: 'Sunglasses', cost: 100, type: 'clothing' }\n                    ];\n                } else if (shopType === 'food') {\n                    items = [\n                        { name: 'Burger', cost: 50, type: 'food' },\n                        { name: 'Pizza', cost: 75, type: 'food' },\n                        { name: 'Energy Drink', cost: 100, type: 'food' },\n                        { name: 'Steak', cost: 150, type: 'food' }\n                    ];\n                }\n                \n                // Store items for click detection\n                gameState.shopItems = items;\n                gameState.shopPanelX = panelX;\n                gameState.shopPanelY = panelY;\n                \n                let yOffset = panelY + 80;\n                items.forEach((item, index) => {\n                    // Item background (clickable area)\n                    const itemHeight = 50;\n                    const itemY = yOffset;\n                    \n                    // Highlight if affordable\n                    if (gameState.player.money >= item.cost) {\n                        ctx.fillStyle = 'rgba(100, 200, 100, 0.2)';\n                    } else {\n                        ctx.fillStyle = 'rgba(200, 100, 100, 0.2)';\n                    }\n                    ctx.fillRect(panelX + 10, itemY - 5, panelWidth - 20, itemHeight);\n                    \n                    // Item text\n                    ctx.fillStyle = gameState.player.money >= item.cost ? '#FFFFFF' : '#888888';\n                    ctx.font = '16px Arial';\n                    ctx.fillText(`${index + 1}. ${item.name}`, panelX + 30, itemY + 10);\n                    \n                    // Price\n                    ctx.fillStyle = gameState.player.money >= item.cost ? '#FFD700' : '#FF6666';\n                    ctx.textAlign = 'right';\n                    ctx.fillText(`$${item.cost}`, panelX + panelWidth - 30, itemY + 10);\n                    ctx.textAlign = 'left';\n                    \n                    yOffset += itemHeight + 5;\n                });\n                \n                // Instructions\n                ctx.fillStyle = '#AAAAAA';\n                ctx.font = '14px Arial';\n                ctx.textAlign = 'left';\n                ctx.fillText('Click item to buy or Press E to close', panelX + 30, panelY + panelHeight - 40);\n                ctx.fillStyle = '#FFD700';\n                ctx.fillText(`Money: $${gameState.player.money}`, panelX + 30, panelY + panelHeight - 15);\n            }\n\n            // Story functions\n            function renderStoryScreen() {\n                const storyContent = document.getElementById('story-content');\n                const continueButton = document.getElementById('story-continue-button');\n                \n                const storyTexts = [\n                    {\n                        title: 'THE CORRUPT CHIEF',\n                        text: 'Detective, we have a problem.<br><br>Chief of Police MARCUS STONE has been stealing money from the city for years. He\\'s hidden the evidence in houses across the city and stashed the bank\\'s money in his personal account.<br><br>We need YOU to expose him.'\n                    },\n                    {\n                        title: 'YOUR MISSION',\n                        text: 'MISSION BRIEFING:<br><br>1. GATHER EVIDENCE - Rob 3 houses to find proof of his corruption<br><br>2. ROB THE BANK - Steal the money he stashed there<br><br>3. ESCAPE - Survive the police chase for 60 seconds<br><br>Once you complete all missions, the truth will be exposed!'\n                    },\n                    {\n                        title: 'FINAL WARNING',\n                        text: 'Be careful - Stone will send his corrupt officers after you. They\\'ll try to stop you at any cost.<br><br>Use the city to your advantage. Steal cars, hide in houses, and use the chaos to your benefit.<br><br>Good luck, Detective. The city is counting on you.'\n                    }\n                ];\n                \n                if (storyPhase < storyTexts.length) {\n                    const story = storyTexts[storyPhase];\n                    storyContent.innerHTML = `\n                        <div style=\"margin-bottom: 30px;\">\n                            <div style=\"font-size: 32px; color: #FF0000; margin-bottom: 20px; text-shadow: 0 0 10px #FF0000;\">\n                                ${story.title}\n                            </div>\n                            <div style=\"font-size: 18px; color: #FFFFFF; line-height: 1.8;\">\n                                ${story.text}\n                            </div>\n                        </div>\n                    `;\n                    continueButton.textContent = storyPhase === storyTexts.length - 1 ? 'START GAME' : 'CONTINUE';\n                }\n            }\n\n            // Cheat code system\n            function validateCheatCode(code) {\n                if (code === '11233') {\n                    gameState.player.money += 900;\n                    gameState.phone.cheatInput = '';\n                    return 'MONEY +900!';\n                } else if (code === '4322') {\n                    gameState.phone.activeCheats.godMode = !gameState.phone.activeCheats.godMode;\n                    gameState.phone.cheatInput = '';\n                    return gameState.phone.activeCheats.godMode ? 'GOD MODE ACTIVATED!' : 'GOD MODE DEACTIVATED!';\n                } else if (code === '9111') {\n                    gameState.phone.activeCheats.noPoliceChase = !gameState.phone.activeCheats.noPoliceChase;\n                    gameState.phone.cheatInput = '';\n                    return gameState.phone.activeCheats.noPoliceChase ? 'POLICE IMMUNITY ACTIVATED!' : 'POLICE IMMUNITY DEACTIVATED!';\n                }\n                return null;\n            }\n\n            // Phone functions\n            function togglePhone() {\n                gameState.phone.isOpen = !gameState.phone.isOpen;\n                const phoneScreen = document.getElementById('phone-screen');\n                \n                if (gameState.phone.isOpen) {\n                    phoneScreen.classList.add('visible');\n                    renderPhoneScreen();\n                } else {\n                    phoneScreen.classList.remove('visible');\n                }\n            }\n\n            function closePhone() {\n                gameState.phone.isOpen = false;\n                document.getElementById('phone-screen').classList.remove('visible');\n            }\n\n            function renderPhoneScreen() {\n                const phoneContent = document.getElementById('phone-content');\n                const phoneTitle = document.getElementById('phone-title');\n                \n                if (gameState.phone.currentScreen === 'menu') {\n                    phoneTitle.textContent = 'PHONE';\n                    phoneContent.innerHTML = `\n                        <div class=\"phone-menu\">\n                            <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('messages')\">\ud83d\udce8 MESSAGES</div>\n                            <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('contacts')\">\ud83d\udc65 CONTACTS</div>\n                            <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('jobs')\">\ud83d\udcbc JOBS</div>\n                            <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('stats')\">\ud83d\udcca STATS</div>\n                            <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('settings')\">\u2699\ufe0f SETTINGS</div>\n                            <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('cheats')\" style=\"color: #FF6B6B; border-color: #FF6B6B;\">\ud83d\udd13 CHEATS</div>\n                        </div>\n                    `;\n                } else if (gameState.phone.currentScreen === 'messages') {\n                    phoneTitle.textContent = '\ud83d\udce8 MESSAGES';\n                    phoneContent.innerHTML = `\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">INCOMING MESSAGES</div>\n                            <div class=\"phone-info-line\">\n                                <span>Boss:</span>\n                                <span style=\"color: #FFD700;\">New Job Available</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Police:</span>\n                                <span style=\"color: #FF6666;\">WANTED!</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Shop:</span>\n                                <span style=\"color: #00FF00;\">Sale Today!</span>\n                            </div>\n                        </div>\n                        <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('menu')\">\u2190 BACK</div>\n                    `;\n                } else if (gameState.phone.currentScreen === 'contacts') {\n                    phoneTitle.textContent = '\ud83d\udc65 CONTACTS';\n                    phoneContent.innerHTML = `\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">SAVED CONTACTS</div>\n                            <div class=\"phone-info-line\">\n                                <span>\ud83d\ude97 Car Dealer</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>\ud83c\udfe6 Bank Manager</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>\ud83d\udd2b Weapon Dealer</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>\ud83d\udc6e Police Station</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>\ud83c\udfe5 Hospital</span>\n                            </div>\n                        </div>\n                        <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('menu')\">\u2190 BACK</div>\n                    `;\n                } else if (gameState.phone.currentScreen === 'jobs') {\n                    phoneTitle.textContent = '\ud83d\udcbc JOBS';\n                    const currentJobStatus = gameState.jobs.currentJob ? \n                        `<div style=\"color: #00FF00; margin-bottom: 12px; padding: 12px; background: rgba(0, 255, 0, 0.2); border: 1px solid #00FF00; border-radius: 4px; text-align: center; font-weight: bold;\">CURRENTLY WORKING: ${gameState.jobs.currentJob.toUpperCase()}</div>\n                         <div style=\"color: #FFD700; margin-bottom: 12px; padding: 12px; background: rgba(255, 215, 0, 0.2); border: 1px solid #FFD700; border-radius: 4px; text-align: center;\">\n                            TASKS COMPLETED: ${gameState.jobs.completedTasks}/${gameState.jobs.tasksRequired[gameState.jobs.currentJob]}\n                            <div style=\"color: ${gameState.jobs.completedTasks >= gameState.jobs.tasksRequired[gameState.jobs.currentJob] ? '#00FF00' : '#FF6666'}; font-size: 12px; margin-top: 6px;\">\n                                ${gameState.jobs.completedTasks >= gameState.jobs.tasksRequired[gameState.jobs.currentJob] ? '\u2713 EARNING MONEY!' : '\u23f3 Complete tasks to earn money'}\n                            </div>\n                         </div>\n                         <button onclick=\"window.quitJob()\" style=\"width: 100%; margin-bottom: 12px; padding: 12px; background: #FF6666; color: #FFF; border: 2px solid #FF0000; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 14px; font-family: 'Press Start 2P', monospace;\">QUIT JOB</button>` : \n                        '';\n                    \n                    phoneContent.innerHTML = `\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">AVAILABLE JOBS</div>\n                            ${currentJobStatus}\n                            <div class=\"phone-info-line\" style=\"flex-direction: column; align-items: flex-start; gap: 8px; margin-bottom: 16px; padding: 12px; background: rgba(255, 200, 0, 0.2); border: 1px solid #FFD700; border-radius: 4px;\">\n                                <div style=\"color: #FFD700; font-weight: bold;\">\ud83d\ude95 TAXI DRIVER</div>\n                                <div style=\"color: #AAAAAA; font-size: 12px;\">Salary: $10/sec (after 3 tasks)</div>\n                                <div style=\"color: #FFFFFF; font-size: 12px;\">Total Earned: $${Math.floor(gameState.jobs.taxiEarnings)}</div>\n                                <button onclick=\"window.startJob('taxi')\" style=\"margin-top: 8px; padding: 8px 16px; background: #FFD700; color: #000; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 12px;\" ${gameState.jobs.currentJob ? 'disabled' : ''}>\n                                    ${gameState.jobs.currentJob === 'taxi' ? 'WORKING...' : 'START JOB'}\n                                </button>\n                            </div>\n                            <div class=\"phone-info-line\" style=\"flex-direction: column; align-items: flex-start; gap: 8px; margin-bottom: 16px; padding: 12px; background: rgba(0, 255, 0, 0.2); border: 1px solid #00FF00; border-radius: 4px;\">\n                                <div style=\"color: #00FF00; font-weight: bold;\">\u2695\ufe0f DOCTOR</div>\n                                <div style=\"color: #AAAAAA; font-size: 12px;\">Salary: $15/sec (after 5 tasks)</div>\n                                <div style=\"color: #FFFFFF; font-size: 12px;\">Total Earned: $${Math.floor(gameState.jobs.doctorEarnings)}</div>\n                                <button onclick=\"window.startJob('doctor')\" style=\"margin-top: 8px; padding: 8px 16px; background: #00FF00; color: #000; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 12px;\" ${gameState.jobs.currentJob ? 'disabled' : ''}>\n                                    ${gameState.jobs.currentJob === 'doctor' ? 'WORKING...' : 'START JOB'}\n                                </button>\n                            </div>\n                            <div class=\"phone-info-line\" style=\"flex-direction: column; align-items: flex-start; gap: 8px; padding: 12px; background: rgba(255, 0, 0, 0.2); border: 1px solid #FF0000; border-radius: 4px;\">\n                                <div style=\"color: #FF0000; font-weight: bold;\">\ud83d\udc6e POLICE OFFICER</div>\n                                <div style=\"color: #AAAAAA; font-size: 12px;\">Salary: $20/sec (after 10 tasks)</div>\n                                <div style=\"color: #FFFFFF; font-size: 12px;\">Total Earned: $${Math.floor(gameState.jobs.policeEarnings)}</div>\n                                <button onclick=\"window.startJob('police')\" style=\"margin-top: 8px; padding: 8px 16px; background: #FF0000; color: #FFF; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 12px;\" ${gameState.jobs.currentJob ? 'disabled' : ''}>\n                                    ${gameState.jobs.currentJob === 'police' ? 'WORKING...' : 'START JOB'}\n                                </button>\n                            </div>\n                        </div>\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">JOB STATS</div>\n                            <div class=\"phone-info-line\">\n                                <span>Total Job Earnings:</span>\n                                <span style=\"color: #FFD700;\">$${Math.floor(gameState.jobs.totalJobEarnings)}</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Current Job:</span>\n                                <span style=\"color: ${gameState.jobs.currentJob ? '#00FF00' : '#FF6666'};\">${gameState.jobs.currentJob ? gameState.jobs.currentJob.toUpperCase() : 'NONE'}</span>\n                            </div>\n                            ${gameState.jobs.currentJob ? `<div class=\"phone-info-line\">\n                                <span>Time Remaining:</span>\n                                <span style=\"color: #00FFFF;\">${Math.ceil(gameState.jobs.jobDuration - gameState.jobs.jobTimer)}s</span>\n                            </div>` : ''}\n                        </div>\n                        <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('menu')\">\u2190 BACK</div>\n                    `;\n                } else if (gameState.phone.currentScreen === 'stats') {\n                    phoneTitle.textContent = '\ud83d\udcca STATS';\n                    phoneContent.innerHTML = `\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">GAME STATISTICS</div>\n                            <div class=\"phone-info-line\">\n                                <span>Score:</span>\n                                <span style=\"color: #FFD700;\">$${gameState.score}</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Money:</span>\n                                <span style=\"color: #00FF00;\">$${gameState.player.money}</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Crimes:</span>\n                                <span style=\"color: #FF6666;\">${gameState.crimes}</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Car Thefts:</span>\n                                <span style=\"color: #FF8C42;\">${gameState.carThefts}</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>NPC Kills:</span>\n                                <span style=\"color: #FF0000;\">${gameState.npcKills || 0}</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Wanted Level:</span>\n                                <span style=\"color: #FF0000;\">\u2b50 ${gameState.wantedLevel}/3</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Time Played:</span>\n                                <span style=\"color: #00FFFF;\">${Math.floor(gameState.gameTime)}s</span>\n                            </div>\n                        </div>\n                        <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('menu')\">\u2190 BACK</div>\n                    `;\n                } else if (gameState.phone.currentScreen === 'settings') {\n                    phoneTitle.textContent = '\u2699\ufe0f SETTINGS';\n                    phoneContent.innerHTML = `\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">PHONE SETTINGS</div>\n                            <div class=\"phone-info-line\">\n                                <span>Volume:</span>\n                                <span style=\"color: #00FF00;\">ON</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Brightness:</span>\n                                <span style=\"color: #FFD700;\">MAX</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Network:</span>\n                                <span style=\"color: #00FF00;\">CONNECTED</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Battery:</span>\n                                <span style=\"color: #00FF00;\">100%</span>\n                            </div>\n                        </div>\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">ABOUT</div>\n                            <div class=\"phone-info-line\">\n                                <span>LIFECITY Mobile OS</span>\n                            </div>\n                            <div class=\"phone-info-line\">\n                                <span>Version 1.0</span>\n                            </div>\n                        </div>\n                        <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('menu')\">\u2190 BACK</div>\n                    `;\n                } else if (gameState.phone.currentScreen === 'cheats') {\n                    phoneTitle.textContent = '\ud83d\udd13 CHEATS';\n                    let messageHTML = '';\n                    if (gameState.phone.cheatMessage) {\n                        const isSuccess = gameState.phone.cheatMessage.includes('ACTIVATED') || gameState.phone.cheatMessage.includes('DEACTIVATED') || gameState.phone.cheatMessage.includes('+');\n                        messageHTML = `<div style=\"margin-bottom: 12px; padding: 12px; background: ${isSuccess ? 'rgba(0, 255, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)'}; border: 1px solid ${isSuccess ? '#00FF00' : '#FF0000'}; border-radius: 4px; color: ${isSuccess ? '#00FF00' : '#FF0000'}; text-align: center; font-weight: bold;\">${gameState.phone.cheatMessage}</div>`;\n                    }\n                    phoneContent.innerHTML = `\n                        <div class=\"phone-info-section\">\n                            <div class=\"phone-info-title\">CHEAT CODES</div>\n                            ${messageHTML}\n                            <div style=\"margin-bottom: 16px; padding: 12px; background: rgba(255, 107, 107, 0.2); border: 1px solid #FF6B6B; border-radius: 4px;\">\n                                <div style=\"color: #FFD700; font-size: 12px; margin-bottom: 8px;\">ENTER CODE:</div>\n                                <input type=\"text\" id=\"cheat-input\" placeholder=\"Type code...\" style=\"width: 100%; padding: 8px; background: #000; color: #00FF00; border: 1px solid #00FF00; border-radius: 4px; font-family: monospace; font-size: 14px;\" maxlength=\"5\" value=\"${gameState.phone.cheatInput}\">\n                            </div>\n                            <div class=\"phone-info-section\">\n                                <div class=\"phone-info-title\">AVAILABLE CODES</div>\n                                <div class=\"phone-info-line\" style=\"flex-direction: column; align-items: flex-start; gap: 8px;\">\n                                    <div style=\"color: #FFD700;\">11233</div>\n                                    <div style=\"color: #AAAAAA; font-size: 12px;\">Money +900</div>\n                                </div>\n                                <div style=\"margin-top: 12px; border-top: 1px solid #00FF00; padding-top: 12px;\"></div>\n                                <div class=\"phone-info-line\" style=\"flex-direction: column; align-items: flex-start; gap: 8px;\">\n                                    <div style=\"color: #FFD700;\">4322</div>\n                                    <div style=\"color: #AAAAAA; font-size: 12px;\">God Mode (Health/Stamina)</div>\n                                    <div style=\"color: ${gameState.phone.activeCheats.godMode ? '#00FF00' : '#FF6666'}; font-size: 12px;\">Status: ${gameState.phone.activeCheats.godMode ? 'ACTIVE' : 'INACTIVE'}</div>\n                                </div>\n                                <div style=\"margin-top: 12px; border-top: 1px solid #00FF00; padding-top: 12px;\"></div>\n                                <div class=\"phone-info-line\" style=\"flex-direction: column; align-items: flex-start; gap: 8px;\">\n                                    <div style=\"color: #FFD700;\">9111</div>\n                                    <div style=\"color: #AAAAAA; font-size: 12px;\">Police Immunity</div>\n                                    <div style=\"color: ${gameState.phone.activeCheats.noPoliceChase ? '#00FF00' : '#FF6666'}; font-size: 12px;\">Status: ${gameState.phone.activeCheats.noPoliceChase ? 'ACTIVE' : 'INACTIVE'}</div>\n                                </div>\n                            </div>\n                        </div>\n                        <div class=\"phone-menu-item\" onclick=\"window.phoneMenuClick('menu')\">\u2190 BACK</div>\n                    `;\n                    \n                    // Setup cheat input handler after rendering\n                    setTimeout(() => {\n                        const cheatInput = document.getElementById('cheat-input');\n                        if (cheatInput) {\n                            cheatInput.focus();\n                            cheatInput.addEventListener('input', (e) => {\n                                gameState.phone.cheatInput = e.target.value;\n                            });\n                            cheatInput.addEventListener('keypress', (e) => {\n                                if (e.key === 'Enter') {\n                                    const result = validateCheatCode(gameState.phone.cheatInput);\n                                    if (result) {\n                                        // Show success message\n                                        gameState.phone.cheatMessage = result;\n                                        gameState.phone.cheatMessageTimer = 3;\n                                        renderPhoneScreen();\n                                    } else {\n                                        gameState.phone.cheatMessage = 'INVALID CODE!';\n                                        gameState.phone.cheatMessageTimer = 2;\n                                        gameState.phone.cheatInput = '';\n                                        renderPhoneScreen();\n                                    }\n                                }\n                            });\n                        }\n                    }, 0);\n                }\n            }\n\n            // Global function for phone menu clicks\n            window.phoneMenuClick = function(screen) {\n                gameState.phone.currentScreen = screen;\n                renderPhoneScreen();\n            };\n\n            // Global function to start a job\n            window.startJob = function(jobType) {\n                gameState.jobs.currentJob = jobType;\n                gameState.jobs.jobTimer = 0;\n                gameState.jobs.jobState = JOB_STATES.IDLE;\n                gameState.jobs.taskTimer = 0;\n                gameState.jobs.completedTasks = 0; // Reset task counter\n                renderPhoneScreen();\n            };\n            \n            // Global function to quit current job\n            window.quitJob = function() {\n                quitCurrentJob();\n                renderPhoneScreen();\n            };\n\n            // Input handling\n            function setupInput() {\n                // Keyboard\n                window.addEventListener('keydown', (e) => {\n                    const key = e.key.toLowerCase();\n                    input.keys[key] = true;\n                    \n                    if (key === 'e' || key === ' ') {\n                        e.preventDefault();\n                        if (gameState.shopOpen) {\n                            closeShop();\n                        } else if (gameState.phone.isOpen) {\n                            closePhone();\n                        } else {\n                            performAction();\n                        }\n                    }\n                    \n                    // Phone toggle with P key\n                    if (key === 'p') {\n                        e.preventDefault();\n                        togglePhone();\n                    }\n                    \n                    // Prevent default for game keys\n                    if (['w', 's', 'a', 'd', 'arrowup', 'arrowdown', 'arrowleft', 'arrowright', ' '].includes(key)) {\n                        e.preventDefault();\n                    }\n                });\n\n                window.addEventListener('keyup', (e) => {\n                    const key = e.key.toLowerCase();\n                    input.keys[key] = false;\n                });\n\n                window.addEventListener('blur', () => {\n                    input.keys = {};\n                });\n\n                // Touch controls\n                if (isTouchDevice) {\n                    setupTouchControls();\n                }\n            }\n\n            // Canvas click handling for shop items and house interior\n            canvas.addEventListener('click', (e) => {\n                const rect = canvas.getBoundingClientRect();\n                const clickX = e.clientX - rect.left;\n                const clickY = e.clientY - rect.top;\n                \n                // Handle house interior clicks\n                if (gameState.player.inHouse && gameState.player.currentHouse) {\n                    // Check if close button was clicked\n                    if (gameState.houseCloseButtonX !== undefined) {\n                        if (clickX >= gameState.houseCloseButtonX && \n                            clickX <= gameState.houseCloseButtonX + gameState.houseCloseButtonSize &&\n                            clickY >= gameState.houseCloseButtonY && \n                            clickY <= gameState.houseCloseButtonY + gameState.houseCloseButtonSize) {\n                            exitHouse();\n                            return;\n                        }\n                    }\n                    \n                    // Check if rob button was clicked\n                    if (gameState.robHouseButtonX !== undefined && !gameState.player.currentHouse.hasBeenRobbed) {\n                        if (clickX >= gameState.robHouseButtonX && \n                            clickX <= gameState.robHouseButtonX + gameState.robHouseButtonWidth &&\n                            clickY >= gameState.robHouseButtonY && \n                            clickY <= gameState.robHouseButtonY + gameState.robHouseButtonHeight) {\n                            robHouse(gameState.player.currentHouse);\n                            return;\n                        }\n                    }\n                    return;\n                }\n                \n                // Handle shop clicks\n                if (!gameState.shopOpen || !gameState.shopItems) return;\n                \n                // Check if close button was clicked\n                if (gameState.shopCloseButtonX !== undefined) {\n                    if (clickX >= gameState.shopCloseButtonX && \n                        clickX <= gameState.shopCloseButtonX + gameState.shopCloseButtonSize &&\n                        clickY >= gameState.shopCloseButtonY && \n                        clickY <= gameState.shopCloseButtonY + gameState.shopCloseButtonSize) {\n                        closeShop();\n                        return;\n                    }\n                }\n                \n                const panelX = gameState.shopPanelX;\n                const panelY = gameState.shopPanelY;\n                const panelWidth = 450;\n                const itemHeight = 50;\n                \n                // Check which item was clicked\n                let yOffset = panelY + 80;\n                gameState.shopItems.forEach((item, index) => {\n                    const itemY = yOffset;\n                    \n                    if (clickX >= panelX + 10 && clickX <= panelX + panelWidth - 10 &&\n                        clickY >= itemY - 5 && clickY <= itemY + itemHeight) {\n                        buyItem(index);\n                    }\n                    \n                    yOffset += itemHeight + 5;\n                });\n            });\n\n            function setupTouchControls() {\n                const joystickElement = document.getElementById('virtual-joystick');\n                const joystickKnob = document.getElementById('joystick-knob');\n                const actionButton = document.getElementById('action-button');\n                const sprintButton = document.getElementById('sprint-button');\n                const exitButton = document.getElementById('exit-button');\n\n                // Joystick\n                canvas.addEventListener('touchstart', (e) => {\n                    Array.from(e.changedTouches).forEach(touch => {\n                        if (touch.clientX < canvas.width / 2 && !input.touch.joystick.active) {\n                            input.touch.joystick.active = true;\n                            input.touch.joystick.touchId = touch.identifier;\n                            input.touch.joystick.startX = touch.clientX;\n                            input.touch.joystick.startY = touch.clientY;\n                            \n                            joystickElement.style.left = (touch.clientX - 80) + 'px';\n                            joystickElement.style.top = (touch.clientY - 80) + 'px';\n                            joystickElement.classList.add('active');\n                        }\n                    });\n                });\n\n                canvas.addEventListener('touchmove', (e) => {\n                    e.preventDefault();\n                    Array.from(e.changedTouches).forEach(touch => {\n                        if (touch.identifier === input.touch.joystick.touchId) {\n                            const dx = touch.clientX - input.touch.joystick.startX;\n                            const dy = touch.clientY - input.touch.joystick.startY;\n                            const distance = Math.hypot(dx, dy);\n                            const maxDistance = 50;\n                            \n                            if (distance > maxDistance) {\n                                const angle = Math.atan2(dy, dx);\n                                input.touch.joystick.x = Math.cos(angle);\n                                input.touch.joystick.y = Math.sin(angle);\n                                \n                                joystickKnob.style.left = (80 + Math.cos(angle) * maxDistance - 30) + 'px';\n                                joystickKnob.style.top = (80 + Math.sin(angle) * maxDistance - 30) + 'px';\n                            } else {\n                                input.touch.joystick.x = dx / maxDistance;\n                                input.touch.joystick.y = dy / maxDistance;\n                                \n                                joystickKnob.style.left = (80 + dx - 30) + 'px';\n                                joystickKnob.style.top = (80 + dy - 30) + 'px';\n                            }\n                        }\n                    });\n                });\n\n                canvas.addEventListener('touchend', (e) => {\n                    Array.from(e.changedTouches).forEach(touch => {\n                        if (touch.identifier === input.touch.joystick.touchId) {\n                            input.touch.joystick.active = false;\n                            input.touch.joystick.x = 0;\n                            input.touch.joystick.y = 0;\n                            input.touch.joystick.touchId = null;\n                            \n                            joystickElement.classList.remove('active');\n                            joystickKnob.style.left = '50px';\n                            joystickKnob.style.top = '50px';\n                        }\n                    });\n                });\n\n                // Action button\n                actionButton.addEventListener('touchstart', (e) => {\n                    e.preventDefault();\n                    if (gameState.shopOpen) {\n                        closeShop();\n                    } else {\n                        performAction();\n                    }\n                });\n\n                // Sprint button\n                sprintButton.addEventListener('touchstart', (e) => {\n                    e.preventDefault();\n                    input.touch.sprint = true;\n                });\n\n                sprintButton.addEventListener('touchend', (e) => {\n                    e.preventDefault();\n                    input.touch.sprint = false;\n                });\n\n                // Exit button\n                exitButton.addEventListener('touchstart', (e) => {\n                    e.preventDefault();\n                    exitVehicle();\n                });\n\n                // Phone button\n                const phoneButton = document.getElementById('phone-button');\n                phoneButton.addEventListener('touchstart', (e) => {\n                    e.preventDefault();\n                    togglePhone();\n                });\n            }\n\n            // Phone button click handler\n            document.getElementById('phone-button').addEventListener('click', () => {\n                togglePhone();\n            });\n\n            // Phone close button handler\n            document.getElementById('phone-close-btn').addEventListener('click', () => {\n                closePhone();\n            });\n\n            // Restart button\n            document.getElementById('restart-button').addEventListener('click', () => {\n                // Reset game state completely\n                gamePhase = 'lobby';\n                gameState.gameOver = false;\n                gameState.score = 0;\n                gameState.crimes = 0;\n                gameState.carThefts = 0;\n                gameState.npcKills = 0;\n                gameState.gameTime = 0;\n                gameState.wantedLevel = 0;\n                gameState.wantedTimer = 0;\n                gameState.policeChaseTimer = 0;\n                gameState.player.money = 0;\n                gameState.player.health = 100;\n                gameState.player.hunger = 100;\n                gameState.player.stamina = 100;\n                gameState.player.inVehicle = false;\n                gameState.player.vehicle = null;\n                gameState.player.inHouse = false;\n                gameState.player.currentHouse = null;\n                gameState.player.x = WORLD_SIZE / 2;\n                gameState.player.y = WORLD_SIZE / 2;\n                gameState.vehicles = [];\n                gameState.npcs = [];\n                gameState.police = [];\n                gameState.houses = [];\n                gameState.bloodParticles = [];\n                gameState.moneyDrops = [];\n                gameState.clockTime = 6 * 3600; // Reset to 06:00\n                gameState.weatherType = 'clear';\n                gameState.weatherTimer = 0;\n                gameState.weatherDuration = 60;\n                gameState.rainParticles = [];\n                gameState.stormIntensity = 0;\n                \n                // Stop all sounds\n                stopSound('police_siren_sfx');\n                stopSound('car_engine_loop');\n                stopSound('background_music');\n                stopSound('game_over_sfx');\n                \n                // Reinitialize city\n                initCity();\n                \n                // Hide game over screen and show lobby\n                document.getElementById('game-over-screen').classList.remove('visible');\n                document.getElementById('lobby-screen').classList.remove('hidden');\n                document.getElementById('game-canvas').style.display = 'none';\n                \n                // Reset UI\n                updateWantedDisplay();\n                updateStatBars();\n                document.getElementById('score').textContent = '0';\n                document.getElementById('exit-button').classList.remove('visible');\n            });\n\n            // Lobby buttons\n            document.getElementById('play-button').addEventListener('click', () => {\n                gamePhase = 'story';\n                storyPhase = 0;\n                storyTimer = 0;\n                document.getElementById('lobby-screen').classList.add('hidden');\n                document.getElementById('story-screen').classList.remove('hidden');\n                renderStoryScreen();\n            });\n\n            document.getElementById('story-continue-button').addEventListener('click', () => {\n                storyPhase++;\n                if (storyPhase >= 3) {\n                    // Start the game\n                    gamePhase = 'playing';\n                    document.getElementById('story-screen').classList.add('hidden');\n                    document.getElementById('game-canvas').style.display = 'block';\n                    playSound('background_music', true, 0.3);\n                    gameState.missionStartTime = gameState.gameTime;\n                } else {\n                    renderStoryScreen();\n                }\n            });\n\n            document.getElementById('settings-button').addEventListener('click', () => {\n                document.getElementById('lobby-screen').classList.add('hidden');\n                document.getElementById('settings-screen').classList.remove('hidden');\n            });\n\n            document.getElementById('how-to-play-button').addEventListener('click', () => {\n                document.getElementById('lobby-screen').classList.add('hidden');\n                document.getElementById('settings-screen').classList.remove('hidden');\n            });\n\n            document.getElementById('back-button').addEventListener('click', () => {\n                document.getElementById('settings-screen').classList.add('hidden');\n                document.getElementById('lobby-screen').classList.remove('hidden');\n            });\n\n            // Volume control\n            document.getElementById('volume-slider').addEventListener('change', (e) => {\n                const volume = e.target.value / 100;\n                setVolume('background_music', volume * 0.3);\n                setVolume('police_siren_sfx', volume * 0.4);\n            });\n\n            // Camera update function\n            function updateCamera() {\n                // Smooth camera follow\n                const targetX = gameState.player.x;\n                const targetY = gameState.player.y;\n                const cameraSpeed = 0.1;\n                \n                gameState.camera.x += (targetX - gameState.camera.x) * cameraSpeed;\n                gameState.camera.y += (targetY - gameState.camera.y) * cameraSpeed;\n                \n                // Clamp camera to world bounds\n                gameState.camera.x = Math.max(canvas.width / 2, Math.min(WORLD_SIZE - canvas.width / 2, gameState.camera.x));\n                gameState.camera.y = Math.max(canvas.height / 2, Math.min(WORLD_SIZE - canvas.height / 2, gameState.camera.y));\n            }\n\n            // Format game time to HH:MM format\n            function formatGameTime(seconds) {\n                const hours = Math.floor(seconds / 3600) % 24;\n                const minutes = Math.floor((seconds % 3600) / 60);\n                return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;\n            }\n\n            // Initialize game\n            initCity();\n            setupInput();\n            updateWantedDisplay();\n\n            // Hide canvas initially (show intro)\n            document.getElementById('game-canvas').style.display = 'none';\n\n            // Start background music only in play mode\n            if (mode === 'play') {\n                // Music will start when player clicks PLAY button\n            }\n\n            // Game loop\n            let lastTime = performance.now();\n            \n            function gameLoop(timestamp) {\n                let deltaTime = (timestamp - lastTime) / 1000;\n                lastTime = timestamp;\n                \n                // Limit delta time\n                deltaTime = Math.min(deltaTime, 0.11);\n\n                // Handle intro phase\n                if (gamePhase === 'intro') {\n                    if (!introSoundPlayed) {\n                        playSound('intro_epic_sound', false, 0.8);\n                        introSoundPlayed = true;\n                    }\n                    introTimer -= deltaTime;\n                    if (introTimer <= 0) {\n                        gamePhase = 'lobby';\n                        document.getElementById('intro-screen').classList.add('hidden');\n                        document.getElementById('lobby-screen').classList.remove('hidden');\n                    }\n                }\n\n                // Update game only when playing\n                if (gamePhase === 'playing' && mode === 'play' && !gameState.gameOver) {\n                    gameState.gameTime += deltaTime;\n                    \n                    updatePlayer(deltaTime);\n                    updateVehicles(deltaTime);\n                    updateNPCs(deltaTime);\n                    updatePolice(deltaTime);\n                    updateTrafficLights(deltaTime);\n                    updateWantedLevel(deltaTime);\n                    updateTimeAndWeather(deltaTime);\n                    updateBloodParticles(deltaTime);\n                    updateMoneyDrops(deltaTime);\n                    updateJobs(deltaTime);\n                    updateCamera();\n                    updateStatBars();\n                }\n\n                render();\n                requestAnimationFrame(gameLoop);\n            }\n\n            requestAnimationFrame(gameLoop);\n        }\n    </script>\n</body>\n</html>", "game_config": "{\"player\": {\"jacketColor\": \"#2E5C9A\", \"shirtColor\": \"#FF8C42\", \"pantsColor\": \"#1A1A1A\"}, \"difficulty\": {\"policeAggression\": 1.0, \"wantedDecay\": 30, \"trafficDensity\": 8}, \"rewards\": {\"carTheft\": 100, \"bankRobbery\": 500}}", "game_design_document": "## Core Game Loop and Mechanics\n\n**LIFECITY** is a top-down, semi-open-world action game where players experience life as a criminal in a bustling city. The core gameplay revolves around:\n\n### Moment-to-Moment Gameplay\n- **Exploration**: Players freely roam a city district with streets, intersections, buildings, and NPCs going about their daily lives\n- **Criminal Activities**: Players can interact with vehicles to steal them, approach banks to rob them, and engage in other criminal acts\n- **Wanted System**: Each crime increases the player's wanted level (1-5 stars), triggering police response\n- **Police Chases**: Police cars spawn and pursue the player, attempting to arrest them through collision/proximity\n- **Escape & Survival**: Players must evade police by driving stolen vehicles, hiding, or outrunning them until the wanted level decreases over time\n\n### Progression & Engagement\n- **Wanted Level Escalation**: More stars = more aggressive police response (more cars, faster pursuit)\n- **Score System**: Points earned for successful crimes, time survived at high wanted levels, and distance traveled\n- **Risk vs Reward**: Bigger crimes (bank robbery) give more points but trigger higher wanted levels immediately\n- **High Score Tracking**: Players compete against their personal best scores\n\n### Win/Lose Conditions\n- **Lose**: Player is caught by police (collision with police car while on foot, or surrounded by multiple police cars)\n- **Win**: No traditional \"win\" - it's about achieving the highest score before getting caught\n- **Game Over**: Shows final score, crimes committed, and time survived\n\n### What Makes It Compelling\n- **Dynamic City Life**: Traffic follows rules, NPCs react to crimes, creating an immersive living world\n- **Tension & Release**: The thrill of committing crimes followed by intense chase sequences\n- **Emergent Gameplay**: Each playthrough is different based on traffic patterns, police spawns, and player choices\n- **Skill Mastery**: Learning optimal escape routes, timing crimes, and managing wanted levels\n\n## Starting Scope\n\nFor the first iteration, we'll implement a **focused, polished prototype** that captures the core experience:\n\n### What to Implement First\n1. **Playable City District**: One medium-sized city block (approximately 3-4 screen widths \u00d7 3-4 screen heights)\n   - Grid-based street layout with 4-6 intersections\n   - Working traffic lights at each intersection\n   - Sidewalks and road lanes clearly defined\n\n2. **Core Character & Movement**\n   - Player character (blue jacket, orange shirt, brown hair, white skin, black pants/shoes)\n   - Smooth top-down movement on foot\n   - Basic collision with buildings and obstacles\n\n3. **Essential NPCs & Traffic**\n   - 10-15 civilian NPCs walking on sidewalks\n   - 5-8 civilian cars driving on roads, obeying traffic lights\n   - Simple AI: NPCs flee when crimes occur nearby\n\n4. **Two Core Crimes**\n   - **Car Theft**: Approach parked/stopped car, press button to steal, enter driving mode\n   - **Bank Robbery**: Approach bank building, press button to rob, instant wanted level increase\n\n5. **Basic Wanted System**\n   - 3 wanted levels (1-3 stars) for simplicity\n   - Visual indicator showing current wanted level\n   - 1 star: 1 police car spawns\n   - 2 stars: 2 police cars spawn\n   - 3 stars: 3 police cars spawn, faster pursuit\n\n6. **Police Chase Mechanics**\n   - Police cars spawn at map edges when wanted\n   - Simple pursuit AI: drive toward player\n   - Collision detection: caught if police car touches player on foot\n   - Wanted level decreases slowly when out of sight\n\n7. **Driving System**\n   - Enter/exit vehicles\n   - Basic car physics (acceleration, turning, momentum)\n   - Collision with other vehicles and buildings\n\n8. **UI Elements**\n   - Wanted level display (stars)\n   - Score counter\n   - Mini-map showing player position and police locations\n   - Simple on-screen prompts (\"Press E to steal car\")\n\n9. **Game Over Screen**\n   - Final score\n   - Crimes committed count\n   - Time survived\n   - Restart button\n\n### What to Add Later\n- Expanded city (multiple districts, larger map)\n- More crime types (mugging NPCs, store robberies, vehicle destruction)\n- 5-star wanted system with helicopters at max level\n- More vehicle types (motorcycles, trucks, police cars)\n- Day/night cycle\n- More detailed NPC behaviors and reactions\n- Pedestrian traffic on crosswalks\n- Weapon system\n- Safe houses to reduce wanted level\n- Mission structure\n- More sophisticated police AI (roadblocks, coordinated pursuit)\n\n## Game Perspective\n\n**Top-Down View** - The camera is positioned directly above the city, looking straight down. This perspective is ideal for:\n- Navigating the city streets and intersections\n- Seeing traffic patterns and police positions\n- Managing chases and escape routes\n- Providing clear visibility of the game world\n\nThe camera follows the player character smoothly, keeping them centered on screen. When driving, the camera may zoom out slightly to show more of the road ahead.\n\n## Game World and Level Design\n\n### City Layout\nThe game world is a **grid-based urban environment** designed to feel like a living city district:\n\n**Street Grid**:\n- 4\u00d74 block layout creating a 5\u00d75 intersection grid\n- Each block is approximately 400\u00d7400 pixels\n- Total playable area: ~2000\u00d72000 pixels (scrolling viewport)\n- Streets are 2-lane roads (one lane each direction) with clear lane markings\n\n**Intersections**:\n- Each intersection has working traffic lights (red/yellow/green cycle)\n- Traffic lights cycle every 8-10 seconds\n- Crosswalks marked at each intersection\n- Stop lines for vehicles\n\n**Buildings & Structures**:\n- **Bank** (1): Large, prominent building with distinct architecture (columns, grand entrance) - robbery target\n- **Shops/Stores** (4-6): Various storefronts along streets\n- **Residential Buildings** (8-10): Apartment buildings and houses\n- **Parking Areas** (3-4): Small lots with parked cars\n- **Park/Plaza** (1): Small green space with trees and benches\n\n**Environmental Details**:\n- Sidewalks along all streets (lighter gray than roads)\n- Street lamps at intersections\n- Trees and vegetation in park area and along some streets\n- Trash cans, benches, and other street furniture\n- Clear visual distinction between drivable roads and walkable sidewalks\n\n### Traffic & NPC Placement\n- **Civilian Cars**: Spawn at map edges, drive along roads, stop at red lights, turn at intersections\n- **Parked Cars**: 8-12 cars parked along streets and in parking lots (steal-able)\n- **Pedestrian NPCs**: Walk on sidewalks, cross at crosswalks when safe, congregate near shops\n- **Police Cars**: Spawn at map edges when player has wanted level, ignore traffic rules during pursuit\n\n### Map Design\nA mini-map in the corner shows:\n- Player position (blue dot)\n- Police positions (red dots) when wanted\n- Bank location (dollar sign icon)\n- Current block layout (simplified)\n- Zoom level shows ~3\u00d73 blocks at once\n\n### Boundaries\n- Invisible walls at map edges prevent leaving the playable area\n- Visual cues (construction barriers, water, or \"end of city\" graphics) indicate boundaries\n- Police spawn just inside boundaries when chasing player\n\n## Edit Mode Design\n\nEdit mode allows players to customize their LIFECITY experience while maintaining game balance and fun. The focus is on **visual customization and difficulty tuning** rather than structural changes.\n\n### Editable Properties\n\n**Player Character Customization**:\n- **Outfit Colors**: Change jacket color (default: blue), shirt color (default: orange), pants color (default: black)\n- **Skin Tone**: Select from preset skin tones\n- **Hair Color**: Choose hair color (default: brown)\n- **Character Name**: Custom name displayed in UI\n\n**City Appearance**:\n- **Time of Day**: Toggle between day/night visual themes (affects lighting, sky color)\n- **Street Color Scheme**: Choose from preset color palettes (modern gray, retro brown, neon city)\n- **Building Colors**: Adjust building color palette (warm tones, cool tones, mixed)\n\n**Gameplay Difficulty**:\n- **Police Aggression**: Slider from \"Relaxed\" to \"Intense\" (affects police spawn rate and speed)\n  - Relaxed: 50% normal spawn rate, 80% normal speed\n  - Normal: 100% spawn rate and speed\n  - Intense: 150% spawn rate, 120% speed\n- **Wanted Level Decay**: How quickly wanted level decreases (Slow/Normal/Fast)\n  - Slow: 60 seconds per star\n  - Normal: 30 seconds per star\n  - Fast: 15 seconds per star\n- **Traffic Density**: Low/Medium/High (affects number of civilian cars)\n  - Low: 5 cars\n  - Medium: 8 cars\n  - High: 12 cars\n\n**Crime Rewards**:\n- **Car Theft Points**: 50-200 points (default: 100)\n- **Bank Robbery Points**: 200-1000 points (default: 500)\n- **Survival Bonus Multiplier**: 1x-3x (points per second survived at wanted level)\n\n### Constraints\n- Player character must remain visible and distinct from NPCs\n- Police must always be able to catch the player (minimum speed limits)\n- At least 1 bank must exist and be accessible\n- Traffic density cannot be zero (minimum 3 cars)\n- Wanted level decay cannot be instant (minimum 10 seconds per star)\n- Map layout and building positions are fixed (not editable in first version)\n\n### Edit Mode UI\n- Side panel with collapsible sections for each category\n- Color pickers for visual customization\n- Sliders with value displays for numerical properties\n- Preset buttons for quick configurations (\"Easy Mode\", \"Hard Mode\", \"Chaos Mode\")\n- \"Reset to Default\" button for each section\n- Live preview of changes (see character color changes immediately)\n\n## Control Design\n\nLIFECITY uses a **top-down action control scheme** optimized for both mobile touch and desktop keyboard/mouse input.\n\n### Mobile Controls (Touch)\n\n**On Foot**:\n- **Left Virtual Joystick**: Movement (appears where left side of screen is touched)\n  - Base moves with finger if dragged beyond max radius\n  - Dead zone: 15% of max radius\n  - Max radius: 80 pixels\n  - Analog output for smooth 8-directional movement\n- **Right Side Buttons**:\n  - **Action Button** (bottom right): Context-sensitive (steal car, rob bank, exit vehicle)\n  - **Sprint Button** (above action): Hold to run faster\n\n**In Vehicle**:\n- **Left Virtual Joystick**: Steering (left/right) and acceleration (up) / brake (down)\n  - Same joystick mechanics as on-foot\n  - Forward = accelerate, backward = brake/reverse\n  - Left/right = steer\n- **Exit Button** (top right): Leave vehicle\n\n**UI Interactions**:\n- **Tap**: Menu buttons, restart after game over\n- **Pinch**: Zoom mini-map (optional enhancement)\n\n### Desktop Controls (Keyboard + Mouse)\n\n**On Foot**:\n- **WASD / Arrow Keys**: 8-directional movement\n  - W/Up: Move up\n  - S/Down: Move down\n  - A/Left: Move left\n  - D/Right: Move right\n  - Diagonals: Combine keys (W+D = up-right)\n- **Shift**: Hold to sprint\n- **E / Space**: Context-sensitive action (steal car, rob bank, exit vehicle)\n\n**In Vehicle**:\n- **W/Up Arrow**: Accelerate\n- **S/Down Arrow**: Brake / Reverse\n- **A/Left Arrow**: Steer left\n- **D/Right Arrow**: Steer right\n- **E / Space**: Exit vehicle\n\n**Camera**:\n- **Mouse Wheel**: Zoom mini-map in/out (optional)\n- No mouse look needed (fixed top-down camera)\n\n**UI**:\n- **Mouse Click**: Menu buttons, restart\n- **Escape**: Pause menu (future feature)\n\n### Input Handling Details\n\n**Touch Tracking**:\n- Track touch IDs to prevent interference between joystick and buttons\n- Left half of screen (x < 360) reserved for movement joystick\n- Right half for action buttons\n- Joystick persists until touch ends, then fades out\n- Multiple simultaneous touches supported (move + action)\n\n**Keyboard State**:\n- Maintain key state object (keydown/keyup events)\n- Convert keycodes to lowercase before storing\n- Prevent default browser behavior for game keys (arrows, space)\n- Clear all input states on window blur\n\n**Vehicle vs On-Foot**:\n- Same keys/joystick, different behavior based on player state\n- Smooth transition when entering/exiting vehicles\n- Action button label changes contextually (\"Steal Car\" \u2192 \"Exit Vehicle\")\n\n**Responsiveness**:\n- Input polling every frame (60 FPS target)\n- Immediate visual feedback (button press animations, joystick knob movement)\n- No input lag or buffering\n\n## Art Style and Visual Theme\n\nLIFECITY features a **vibrant pixel art style** with HDR-inspired lighting and color depth, creating a modern take on retro aesthetics.\n\n### Overall Art Direction\n- **Pixel Art with HDR Flair**: Clean pixel art with enhanced color gradients, bloom effects, and dynamic lighting\n- **Isometric-Inspired Top-Down**: While purely top-down, assets have slight depth/shadow to suggest 3D form\n- **Urban Realism**: Recognizable city elements (cars, buildings, streets) with stylized, game-friendly proportions\n- **High Contrast**: Bold colors and clear silhouettes for gameplay clarity\n\n### Color Palette & Mood\n- **Daytime Theme** (default):\n  - Bright, saturated colors\n  - Sky: Gradient from light blue (#87CEEB) to deeper blue (#4A90E2)\n  - Roads: Dark gray (#3A3A3A) with white/yellow lane markings\n  - Sidewalks: Light gray (#B0B0B0)\n  - Buildings: Varied warm tones (reds, oranges, yellows, browns)\n  - Vegetation: Rich greens (#2D5016, #4A7C2E)\n  \n- **Lighting & Effects**:\n  - Soft shadows beneath all objects (suggesting overhead sun)\n  - Subtle bloom/glow on traffic lights, car headlights, and police sirens\n  - HDR-style color grading: slightly boosted saturation and contrast\n\n### Asset Specifications\n\n**Character Scale**:\n- Player character: ~32\u00d748 pixels (body ~32\u00d732, with head extending up)\n- NPCs: Same scale as player for consistency\n- Vehicles: ~64\u00d796 pixels (civilian cars), ~80\u00d7120 pixels (police cars)\n\n**Building Scale**:\n- Small buildings: ~128\u00d7128 pixels\n- Medium buildings: ~192\u00d7192 pixels\n- Bank (large): ~256\u00d7256 pixels\n- All buildings viewed from directly above with slight depth indication\n\n**Viewing Angle**:\n- Pure top-down (90\u00b0 overhead view)\n- Slight shadow/outline to suggest volume\n- No perspective distortion\n\n**Consistency Requirements**:\n- All assets share the same pixel density and level of detail\n- Consistent light source direction (top-left) for shadows\n- Unified color saturation and contrast levels\n- Same outline/anti-aliasing style across all sprites\n\n### Visual Elements\n\n**Generated Assets** (detailed in Assets section):\n- Player character (multiple poses: idle, walking, driving)\n- NPC civilians (3-4 variations)\n- Civilian cars (2-3 types)\n- Police cars\n- Bank building\n- Generic buildings (shops, residential)\n- Trees and vegetation\n- Street furniture (benches, trash cans, lamp posts)\n\n**Code-Rendered Elements** (CSS/Canvas):\n- Roads and lane markings (precise grid layout)\n- Sidewalks\n- Traffic lights (simple colored circles with glow)\n- Mini-map (simplified geometric shapes)\n- UI elements (wanted stars, score display, buttons)\n- Particle effects (tire smoke, police sirens)\n\n### UI Visual Style\n- **Pixel Font**: Retro-style pixel font for all text\n- **HUD Elements**: Semi-transparent dark panels with bright text/icons\n- **Wanted Stars**: Bright yellow/gold stars with subtle glow\n- **Mini-map**: Dark background with high-contrast icons\n- **Buttons**: Pixel art style with hover/press states", "persistent_storage_config": null, "game_metadata": {"game_id": "01KQM411B1AW27PKSNJN1ZB8HS", "title": "LIFECITY", "description": "Explore a living city, commit crimes like stealing cars and robbing banks, but face intense police chases in this top-down open-world action game!", "thumbnail_url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/thumbnail_d75e22db-fefe-437c-bba1-bf6160a3a435.webp", "created_at": 1777718272, "updated_at": 1778998696313.1538, "art_style": null}}