{"asset_map": {"baby_panda": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_panda_6fb16952-4f38-4fe6-9387-89b8cbb3b8bd.webp", "type": "image", "prompt": "Redraw the baby panda character to perfectly match the artistic style, line weight, and color palette of the baby bunny in image 1. Generate a full-body, front-facing kawaii baby panda with large sparkly eyes, rosy cheeks, and soft shading. Ensure a clean, professional game-ready illustration on a transparent background with a cohesive aesthetic to image 1.", "description": "Redrawn kawaii baby panda to match the style and quality of the baby bunny asset.", "subtype": "character", "aspect_ratio": [683, 811], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "baby_bunny": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_bunny_e55746ee-4985-4a1e-a5ae-2adbc18e57e7.webp", "type": "image", "prompt": "Generate a full-body, front-view illustration of a kawaii baby bunny. Oversized round head, large sparkly light blue eyes, long floppy ears, tiny pink nose, and rosy pink cheeks. Small chubby body sitting down. Soft white/cream fur with pink inner ears. Soft rounded shapes, gentle smile, Japanese kawaii art style with soft shading and highlights, matching the style of baby_panda. High resolution, centered on a transparent background.", "description": "Kawaii baby bunny character with long floppy ears for memory card face.", "subtype": "character", "aspect_ratio": [844, 680], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "baby_fox": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_fox_4c41e0e9-1dfb-49ef-ad63-2ae0b193be33.webp", "type": "image", "prompt": "Redraw the baby fox character to perfectly match the artistic style, line weight, and color palette of the baby bunny in image 1. Generate a full-body, front-facing kawaii baby fox with orange fur, pointed ears, large sparkly eyes, and soft shading. Maintain a clean, polished, game-ready aesthetic with a transparent background to ensure consistency with the existing animal set.", "description": "A kawaii baby fox character for a memory card face, styled to match the baby bunny.", "subtype": "character", "aspect_ratio": [720, 858], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "baby_penguin": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_penguin_fd91653f-42fd-4b11-9728-12b078f42c4b.webp", "type": "image", "prompt": "Redraw the baby penguin character to perfectly match the artistic style, line weight, and color palette of the baby bunny in image 1. Generate a full-body, front-facing illustration of a baby penguin with large sparkly eyes, rosy cheeks, and soft shading. Ensure it has the same 'kawaii' aesthetic, clean lines, and pastel-leaning colors as image 1. Transparent background, high resolution, professional game asset.", "description": "A kawaii baby penguin character redesigned to match the visual style of the baby bunny for consistency.", "subtype": "character", "aspect_ratio": [717, 809], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "baby_koala": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_koala_cf82091e-9a08-4fdc-854f-4d7556d3d6b3.webp", "type": "image", "prompt": "Redraw the baby koala in image 2 to perfectly match the artistic style, line weight, and color palette of the baby bunny in image 1. Generate a full-body, front-facing kawaii baby koala with large sparkly eyes, rosy cheeks, soft shading, and thick clean outlines on a transparent background. Ensure the aesthetic is cohesive with the other animals in the set.", "description": "Kawaii baby koala character redesigned to match the established visual style of the animal card set.", "subtype": "character", "aspect_ratio": [1011, 838], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "baby_cat": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_cat_9e52a4a0-5388-4716-b99d-b543ccad6eea.webp", "type": "image", "prompt": "Redraw the baby cat character to perfectly match the artistic style, line weight, and color palette of the baby bunny in image 1. Generate a full-body, front-facing kawaii baby kitten with orange tabby markings, large sparkly eyes, rosy cheeks, and soft shading. Ensure it has the exact same 'kawaii' aesthetic and level of detail as image 1 for a cohesive memory card set. Transparent background, high resolution, professional game asset.", "description": "A kawaii baby kitten character redesigned to perfectly match the artistic style of the baby bunny.", "subtype": "character", "aspect_ratio": [698, 828], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "card_back_pattern": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/card_back_pattern_7360fbc9-0890-4a41-ad9d-2eb83b1109f5.webp", "type": "image", "prompt": "Generate a seamless, fully tileable pattern for a card back. The design should feature tiny pastel-colored hearts, stars, and paw prints (baby pink, light blue, pale yellow, mint green) scattered evenly across a soft cream background. Clean, gentle aesthetic, subtle and balanced distribution with no visible seams, matching the kawaii art style of the animal characters.", "description": "Seamless pastel pattern featuring hearts and stars for the card backs.", "subtype": "other", "aspect_ratio": [1024, 1024], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "card_flip_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/card_flip_sound_3939d350-8ea6-4dad-a24c-ca3f219f7a5d.mp3", "type": "audio", "prompt": "Short, gentle card flip sound effect. A soft 'whoosh' followed by a subtle paper flick. Light, airy, and playful tone. Clean and non-intrusive, suitable for frequent repetition in a kawaii puzzle game. High-quality foley with a cute, polished feel.", "description": "A light and playful sound effect for flipping a card.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.53, "loop": false, "animation": null}, "match_found_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/match_found_sound_4c68e3fc-2da3-4890-9c6c-e578d810a26d.mp3", "type": "audio", "prompt": "Cheerful and rewarding match-found sound effect. High-pitched bright chime with a magical 'twinkle' or sparkle texture. Positive, uplifting, and kawaii aesthetic. Clear, harmonic resonance that feels satisfying and celebratory. 0.8 seconds of active sound with a clean decay.", "description": "A celebratory chime sound for finding a matching pair.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.45, "loop": false, "animation": null}, "no_match_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/no_match_sound_aaff68b1-14d8-42b1-8fee-75d6b373d1a3.mp3", "type": "audio", "prompt": "Soft, gentle 'try again' sound effect. A light, rounded descending two-tone 'boop' or soft woodblock hit. Non-jarring, encouraging, and cute. Subtle and low-energy to indicate a mistake without being negative or harsh. Fits a pastel kawaii aesthetic.", "description": "A soft, non-punishing sound for a mismatched pair.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.11, "loop": false, "animation": null}, "victory_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/victory_sound_b0dc2196-0976-4c7c-8ead-4bc43fbebdac.mp3", "type": "audio", "prompt": "Joyful and sparkly victory fanfare for a kawaii animal game. Bright ascending melody played with glockenspiel, magical bells, and soft synth swells. Shimmering texture, celebratory and rewarding. Ends on a strong, happy major chord with a light reverb tail. No drums or aggressive brass.", "description": "A joyful fanfare for completing the entire game board.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.94, "loop": false, "animation": null}, "background_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/background_music_6410dfe0-91ed-425b-816f-6a5d5926c336.mp3", "type": "audio", "prompt": "A cheerful, cute, and upbeat background music track for a kawaii-style memory card game. High-quality 2D aesthetic, light and whimsical atmosphere. The arrangement features melodic xylophones, twinkling bells, soft pluck synths, and a gentle, bouncy rhythmic beat. Tempo is 110 BPM, in a bright major key. The mood is happy, relaxing, and non-intrusive, suitable for concentration. Instrumental only, designed with a seamless transition for continuous looping.", "description": "A cheerful, kawaii-themed background track for a memory card game featuring whimsical xylophones and soft synths.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30, "loop": true, "animation": null}, "baby_chick": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_chick_94b2480d-38e7-461a-b39c-7fe7848774e1.webp", "type": "image", "prompt": "Redraw the baby chick character to perfectly match the artistic style, line weight, and color palette of the baby bunny in image 1. Generate a full-body, front-facing kawaii yellow baby chick with large sparkly eyes, rosy cheeks, and soft shading. Ensure a clean, polished, game-ready aesthetic on a transparent background, matching the visual treatment of the existing animal set.", "description": "Kawaii baby chick character for memory card face, styled to match the baby bunny.", "subtype": "character", "aspect_ratio": [708, 838], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "baby_pig": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/baby_pig_23908f23-fdda-417c-b14e-4861002a7e73.webp", "type": "image", "prompt": "Redraw the baby pig character to perfectly match the artistic style, line weight, and color palette of the baby bunny in image 1. Generate a full-body, front-facing kawaii baby pig with large sparkly eyes, rosy cheeks, and soft pastel shading. Ensure a clean, polished game-ready illustration with a transparent background to match the cohesive set of animal memory cards.", "description": "A kawaii baby pig character for a memory card, styled to match the baby bunny.", "subtype": "character", "aspect_ratio": [790, 800], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "ui_icon_save": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ui_icon_save_02c2b337-ead6-4b31-84a6-1592659f0b83.webp", "type": "image", "prompt": "Generate a kawaii-style floppy disk icon for a 'Save' button. The disk is pastel pink with a tiny cute smiling face and a small heart detail. Style: thick brown outlines, soft pastel colors, bubbly and rounded shapes, matching the artistic style of image 1. Professional vector art style, clean lines, high resolution, transparent background.", "description": "A kawaii pastel pink floppy disk icon with a cute face for the save button.", "subtype": "ui", "aspect_ratio": [595, 592], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ui_icon_load": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ui_icon_load_9b2eeaeb-a6cc-4483-9b28-bc7a15f61b93.webp", "type": "image", "prompt": "Generate a kawaii open folder icon for a 'Load' button, pastel blue color. Features a tiny cute smiling face and a small star decoration. Style: clean vector art, thick brown outlines, soft pastel colors, bubbly and rounded shapes. Professional quality, game-ready UI element. Must match the artistic style of the baby bunny in image 1. Transparent background, front-view.", "description": "A kawaii pastel blue folder icon for the Load button with a smiling face and star detail.", "subtype": "ui", "aspect_ratio": [774, 609], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "ui_icon_restart": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/ui_icon_restart_27e6bf15-3b75-4817-9231-92d15def9830.webp", "type": "image", "prompt": "Generate a kawaii circular refresh arrow icon for a 'Restart' button. Pastel yellow color with a tiny cute smiling face and small sparkles. Style: thick brown outlines, soft pastel colors, bubbly and rounded shape, high-quality vector art style. Match the artistic style and line weight of the baby_bunny asset. Transparent background, professional game UI icon.", "description": "A kawaii yellow refresh icon for the Restart button, matching the game's UI style.", "subtype": "ui", "aspect_ratio": [892, 783], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}}, "game_code": "<!DOCTYPE html>\n<html>\n<head>\n    <title>FurFlip - Kawaii Memory Card Game</title>\n    <style>\n        /* CSS Reset and Base Styles */\n        *, *::before, *::after {\n            box-sizing: border-box;\n            margin: 0;\n            padding: 0;\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: 'Fredoka', cursive, sans-serif;\n        }\n\n        /* CSS Custom Properties */\n        :root {\n            --transition-fast: 150ms;\n            --transition-normal: 300ms;\n            --transition-slow: 500ms;\n            --ease-out: cubic-bezier(0.0, 0, 0.2, 1);\n            --ease-bounce: cubic-bezier(0.68, -0.6, 0.32, 1.6);\n            --space-xs: 8px;\n            --space-sm: 16px;\n            --space-md: 24px;\n            --space-lg: 32px;\n            --space-xl: 48px;\n            \n            --bg-gradient-start: #FFE5E5;\n            --bg-gradient-end: #E5F3FF;\n            --card-back: #FFF8F0;\n            --card-front: #FFFFFF;\n            --text-dark: #4A4A4A;\n            --accent-pink: #FFB3D9;\n            --accent-blue: #B3D9FF;\n            --accent-yellow: #FFE5B3;\n        }\n\n        /* Load Google Fonts */\n        @import url('https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&display=swap');\n\n        /* Game World Container */\n        #game-world {\n            position: relative;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(135deg, var(--bg-gradient-start) 0%, var(--bg-gradient-end) 100%);\n            display: flex;\n            flex-direction: column;\n            overflow: hidden;\n        }\n\n        /* Top Bar */\n        .top-bar {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            padding: var(--space-md) var(--space-lg);\n            height: 96px;\n            background: rgba(255, 255, 255, 0.3);\n            backdrop-filter: blur(10px);\n            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n            flex-shrink: 0;\n        }\n\n        .top-bar-item {\n            flex: 1;\n            font-size: 32px;\n            font-weight: 700;\n            color: var(--text-dark);\n            text-shadow: 0 2px 4px rgba(255, 255, 255, 0.8);\n            font-family: 'Fredoka', cursive, sans-serif;\n        }\n\n        .top-bar-item:first-child {\n            text-align: left;\n        }\n\n        .top-bar-item:last-child {\n            text-align: right;\n        }\n\n        /* Main Play Area */\n        .play-area {\n            flex: 1;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            padding: var(--space-sm) var(--space-md);\n            position: relative;\n            overflow: hidden;\n        }\n\n        /* Card Grid */\n        .card-grid {\n            display: grid;\n            gap: 12px;\n            margin: 0 auto;\n            justify-content: center;\n            align-content: center;\n        }\n\n        /* Card Styles */\n        .card {\n            position: relative;\n            cursor: pointer;\n            transform-style: preserve-3d;\n            transition: transform var(--transition-normal) var(--ease-out);\n            border-radius: 16px;\n            user-select: none;\n            -webkit-tap-highlight-color: transparent;\n            width: 100%;\n            height: 100%;\n            aspect-ratio: 1 / 1;\n            margin: auto;\n        }\n\n        .card.flipped {\n            transform: rotateY(180deg);\n        }\n\n        .card.matched {\n            pointer-events: none;\n            transform: rotateY(180deg) scale(1.05);\n            z-index: 5;\n        }\n\n        .card.matched .card-front {\n            border: none;\n            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);\n        }\n\n        .card.disabled {\n            pointer-events: none;\n        }\n\n        .card:active:not(.matched) {\n            transform: scale(0.95);\n        }\n\n        .card.flipped:active:not(.matched) {\n            transform: rotateY(180deg) scale(0.95);\n        }\n\n        .card-face {\n            position: absolute;\n            width: 100%;\n            height: 100%;\n            backface-visibility: hidden;\n            border-radius: 20px;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);\n            border: 4px solid white;\n        }\n\n        .card-front {\n            background: var(--card-front);\n            transform: rotateY(180deg);\n            padding: 4px;\n        }\n\n        .card-back {\n            background: #E5F3FF;\n            background-size: cover;\n            background-position: center;\n            border: 4px solid white;\n        }\n\n        .card-front img {\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n            display: block;\n        }\n\n        /* Bottom Area */\n        .bottom-area {\n            display: flex;\n            justify-content: center;\n            align-items: flex-start;\n            gap: 24px;\n            padding: var(--space-sm) var(--space-md) var(--space-md) var(--space-md);\n            flex-shrink: 0;\n        }\n\n        .button-wrapper {\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            gap: 8px;\n        }\n\n        .button-label {\n            font-family: 'Fredoka', cursive, sans-serif;\n            font-size: 18px;\n            font-weight: 600;\n            color: var(--text-dark);\n            text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);\n        }\n\n        .restart-button {\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            padding: 10px;\n            background: white;\n            border: 4px solid var(--accent-pink);\n            border-radius: 24px;\n            cursor: pointer;\n            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);\n            transition: transform var(--transition-fast) var(--ease-out), box-shadow var(--transition-fast) var(--ease-out);\n            width: 84px;\n            height: 84px;\n            flex-shrink: 0;\n        }\n\n        .restart-button img {\n            width: 100%;\n            height: 100%;\n            object-fit: contain;\n        }\n\n        .restart-button:hover {\n            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n        }\n\n        .restart-button:active {\n            transform: scale(0.95);\n        }\n\n        /* Overlay Styles (Generic) */\n        .overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(255, 255, 255, 0.95);\n            backdrop-filter: blur(10px);\n            display: none;\n            justify-content: center;\n            align-items: center;\n            z-index: 1000;\n            animation: fadeIn var(--transition-slow) var(--ease-out);\n        }\n\n        .overlay.show {\n            display: flex;\n        }\n\n        .overlay-content {\n            text-align: center;\n            padding: var(--space-xl);\n            background: white;\n            border-radius: 48px;\n            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n            max-width: 80%;\n            width: 560px;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            border: 8px solid var(--accent-pink);\n        }\n\n        .welcome-bunny {\n            width: 240px;\n            height: 240px;\n            object-fit: contain;\n            margin-bottom: var(--space-md);\n            filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1));\n            animation: bounce 2s infinite ease-in-out;\n        }\n\n        @keyframes bounce {\n            0%, 100% { transform: translateY(0); }\n            50% { transform: translateY(-20px); }\n        }\n\n        .overlay-title {\n            font-size: 96px;\n            font-weight: 700;\n            color: var(--accent-pink);\n            margin-bottom: var(--space-xs);\n            text-shadow: 3px 3px 0px rgba(255, 255, 255, 1), 6px 6px 0px rgba(0, 0, 0, 0.05);\n            line-height: 1.1;\n            font-family: 'Fredoka', cursive, sans-serif;\n        }\n\n        .overlay-subtitle {\n            font-size: 32px;\n            font-weight: 600;\n            color: var(--text-dark);\n            margin-bottom: var(--space-xl);\n            opacity: 0.8;\n        }\n\n        .overlay-button {\n            padding: 20px 64px;\n            font-size: 28px;\n            font-weight: 700;\n            color: white;\n            background: linear-gradient(135deg, var(--accent-pink) 0%, var(--accent-blue) 100%);\n            border: none;\n            border-radius: 56px;\n            cursor: pointer;\n            box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);\n            transition: transform var(--transition-fast) var(--ease-out), box-shadow var(--transition-fast) var(--ease-out);\n            font-family: 'Fredoka', cursive, sans-serif;\n            min-width: 240px;\n            min-height: 96px;\n        }\n\n        .overlay-button:active {\n            transform: scale(0.95);\n        }\n\n        /* Victory Overlay (Inheriting/Using similar styles) */\n        .victory-overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(255, 255, 255, 0.95);\n            backdrop-filter: blur(10px);\n            display: none;\n            justify-content: center;\n            align-items: center;\n            z-index: 1000;\n            animation: fadeIn var(--transition-slow) var(--ease-out);\n        }\n\n        .victory-overlay.show {\n            display: flex;\n        }\n\n        .victory-content {\n            text-align: center;\n            padding: var(--space-xl);\n            background: white;\n            border-radius: 24px;\n            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);\n            max-width: 80%;\n        }\n\n        .victory-title {\n            font-size: 56px;\n            font-weight: 700;\n            color: var(--accent-pink);\n            margin-bottom: var(--space-lg);\n            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);\n            line-height: 1.2;\n            font-family: 'Fredoka', cursive, sans-serif;\n        }\n\n        .victory-stats {\n            font-size: 36px;\n            font-weight: 600;\n            color: var(--text-dark);\n            margin-bottom: var(--space-xl);\n            line-height: 1.8;\n            font-family: 'Fredoka', cursive, sans-serif;\n        }\n\n        .victory-stats div {\n            margin: var(--space-sm) 0;\n        }\n\n        .victory-button {\n            padding: 20px 64px;\n            font-size: 28px;\n            font-weight: 700;\n            color: white;\n            background: linear-gradient(135deg, var(--accent-pink) 0%, var(--accent-blue) 100%);\n            border: none;\n            border-radius: 56px;\n            cursor: pointer;\n            box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);\n            transition: transform var(--transition-fast) var(--ease-out), box-shadow var(--transition-fast) var(--ease-out);\n            font-family: 'Fredoka', cursive, sans-serif;\n            min-width: 200px;\n            min-height: 96px;\n        }\n\n        .victory-button:hover {\n            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);\n        }\n\n        .victory-button:active {\n            transform: scale(0.95);\n        }\n\n        /* Edit Mode Indicator */\n        .edit-indicator {\n            position: absolute;\n            top: 104px;\n            left: 50%;\n            transform: translateX(-50%);\n            background: rgba(255, 179, 217, 0.95);\n            color: white;\n            padding: 16px 32px;\n            border-radius: 28px;\n            font-size: 24px;\n            font-weight: 600;\n            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n            z-index: 100;\n            display: none;\n            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n        }\n\n        .edit-indicator.show {\n            display: block;\n        }\n\n        /* Animations */\n        @keyframes fadeIn {\n            from {\n                opacity: 0;\n            }\n            to {\n                opacity: 1;\n            }\n        }\n    </style>\n</head>\n<body>\n    <div id=\"game-world\">\n        <!-- Top Bar -->\n        <div class=\"top-bar\">\n            <div class=\"top-bar-item\" id=\"level-display\">\ud83c\udf1f Level 1</div>\n            <div class=\"top-bar-item\" id=\"timer\">\u23f1\ufe0f 0:00</div>\n            <div class=\"top-bar-item\" id=\"moves\">\ud83c\udfaf 0</div>\n        </div>\n\n        <!-- Edit Mode Indicator -->\n        <div class=\"edit-indicator\" id=\"edit-indicator\">\n            \u2728 Edit Mode - Click cards to preview animals\n        </div>\n\n        <!-- Play Area -->\n        <div class=\"play-area\">\n            <div class=\"card-grid\" id=\"card-grid\"></div>\n        </div>\n\n        <!-- Bottom Area -->\n        <div class=\"bottom-area\">\n            <div class=\"button-wrapper\">\n                <button class=\"restart-button\" id=\"save-button\" title=\"Save\">\n                    <img id=\"save-icon-img\" src=\"\" alt=\"Save\">\n                </button>\n                <div class=\"button-label\">Save</div>\n            </div>\n            <div class=\"button-wrapper\">\n                <button class=\"restart-button\" id=\"load-button\" title=\"Load\">\n                    <img id=\"load-icon-img\" src=\"\" alt=\"Load\">\n                </button>\n                <div class=\"button-label\">Load</div>\n            </div>\n            <div class=\"button-wrapper\">\n                <button class=\"restart-button\" id=\"restart-button\" title=\"Restart\">\n                    <img id=\"restart-icon-img\" src=\"\" alt=\"Restart\">\n                </button>\n                <div class=\"button-label\">Restart</div>\n            </div>\n        </div>\n\n        <!-- Victory Overlay -->\n        <!-- Start Screen Overlay -->\n        <div class=\"overlay\" id=\"start-screen\">\n            <div class=\"overlay-content\">\n                <img id=\"welcome-bunny-img\" class=\"welcome-bunny\" src=\"\" alt=\"Welcome Bunny\">\n                <div class=\"overlay-title\">FurFlip</div>\n                <div class=\"overlay-subtitle\">\ud83d\udc3e Match the cute baby animals! \ud83d\udc3e</div>\n                <button class=\"overlay-button\" id=\"start-button\">Start Game</button>\n            </div>\n        </div>\n\n        <div class=\"victory-overlay\" id=\"victory-overlay\">\n            <div class=\"victory-content\">\n                <div class=\"victory-title\">\ud83c\udf89 You Win! \ud83c\udf89</div>\n                <div class=\"victory-stats\" id=\"victory-stats\"></div>\n                <button class=\"victory-button\" id=\"victory-button\">Play Again</button>\n            </div>\n        </div>\n    </div>\n\n    <script>\n        /**\n         * FurFlip - Kawaii Baby Animal Memory Card Game\n         * \n         * A charming memory matching game featuring adorable baby animals.\n         * Players flip cards to find matching pairs, tracking time and moves.\n         * \n         * Gameplay:\n         * - 4x4 grid with 8 pairs of cute baby animals\n         * - Tap/click cards to flip them over\n         * - Find matching pairs to clear the board\n         * - Try to complete the game in the fewest moves and shortest time\n         * \n         * Features:\n         * - Smooth card flip animations with 3D perspective\n         * - Audio feedback for flips, matches, and victory\n         * - Timer and move counter\n         * - Victory screen with performance stats\n         * - Edit mode for previewing animals\n         * - Mobile-first design with touch support\n         */\n\n        async function run(mode) {\n            const gameWorld = document.getElementById('game-world');\n            const cardGrid = document.getElementById('card-grid');\n            const timerElement = document.getElementById('timer');\n            const movesElement = document.getElementById('moves');\n            const restartButton = document.getElementById('restart-button');\n            const saveButton = document.getElementById('save-button');\n            const loadButton = document.getElementById('load-button');\n            const victoryOverlay = document.getElementById('victory-overlay');\n            const victoryStats = document.getElementById('victory-stats');\n            const victoryButton = document.getElementById('victory-button');\n            const editIndicator = document.getElementById('edit-indicator');\n            const levelDisplay = document.getElementById('level-display');\n            const startScreen = document.getElementById('start-screen');\n            const startButton = document.getElementById('start-button');\n\n            // Game state (runtime, not in gameConfig)\n            let currentLevelIndex = 0;\n            let cards = [];\n            let flippedCards = [];\n            let matchedPairs = 0;\n            let moves = 0;\n            let startTime = null;\n            let timerInterval = null;\n            let isChecking = false;\n            let gameStarted = false;\n            let timeLeft = 120; // Time remaining in seconds\n\n            // Audio context for Web Audio API\n            const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n            const audioBuffers = {};\n            let musicSource = null;\n            let musicStarted = false;\n            let musicGainNode = audioContext.createGain();\n            musicGainNode.connect(audioContext.destination);\n            musicGainNode.gain.value = window.gameConfig.settings.musicVolume || 0.5;\n\n            // Asset cache for images\n            const imageCache = {};\n\n            // Preload all assets\n            async function preloadAssets() {\n                const assetIds = [\n                    'baby_panda', 'baby_bunny', 'baby_fox', \n                    'baby_penguin', 'baby_koala', 'baby_cat',\n                    'baby_chick', 'baby_pig',\n                    'card_back_pattern',\n                    'card_flip_sound', 'match_found_sound', \n                    'no_match_sound', 'victory_sound',\n                    'background_music',\n                    'ui_icon_save', 'ui_icon_load', 'ui_icon_restart'\n                ];\n\n                const promises = assetIds.map(async (id) => {\n                    const assetInfo = lib.getAsset(id);\n                    if (!assetInfo) return;\n\n                    if (assetInfo.type === 'image') {\n                        return new Promise((resolve, reject) => {\n                            const img = new Image();\n                            img.onload = () => {\n                                imageCache[id] = img;\n                                resolve();\n                            };\n                            img.onerror = () => {\n                                console.error(`Failed to load image: ${id}`);\n                                resolve(); // Continue even if one asset fails\n                            };\n                            img.src = assetInfo.url;\n                        });\n                    } else if (assetInfo.type === 'audio') {\n                        try {\n                            const response = await fetch(assetInfo.url);\n                            const arrayBuffer = await response.arrayBuffer();\n                            const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n                            audioBuffers[id] = audioBuffer;\n                        } catch (error) {\n                            console.error(`Failed to load audio: ${id}`, error);\n                        }\n                    }\n                });\n\n                await Promise.all(promises);\n                initButtonIcons(); // Update icons after preload\n            }\n\n            // Play audio using Web Audio API\n            function playSound(soundId) {\n                if (!audioBuffers[soundId]) return;\n                \n                try {\n                    const source = audioContext.createBufferSource();\n                    source.buffer = audioBuffers[soundId];\n                    source.connect(audioContext.destination);\n                    source.start(0);\n                } catch (error) {\n                    console.error(`Failed to play sound: ${soundId}`, error);\n                }\n            }\n\n            // Start background music\n            function startBackgroundMusic() {\n                if (musicStarted || !audioBuffers['background_music']) return;\n                \n                try {\n                    if (audioContext.state === 'suspended') {\n                        audioContext.resume();\n                    }\n\n                    musicSource = audioContext.createBufferSource();\n                    musicSource.buffer = audioBuffers['background_music'];\n                    musicSource.loop = true;\n                    musicSource.connect(musicGainNode);\n                    musicSource.start(0);\n                    musicStarted = true;\n                } catch (error) {\n                    console.error('Failed to start background music', error);\n                }\n            }\n\n            // Initialize game board\n            function initializeGame() {\n                // Get levels from config\n                const levels = window.gameConfig.levels || [{ rows: 4, cols: 4, pairs: 8 }];\n                const currentLevel = levels[currentLevelIndex] || levels[0];\n\n                // Clear existing cards\n                cardGrid.innerHTML = '';\n                cards = [];\n                flippedCards = [];\n                matchedPairs = 0;\n                moves = 0;\n                startTime = null;\n                gameStarted = false;\n                isChecking = false;\n\n                // Stop timer\n                if (timerInterval) {\n                    clearInterval(timerInterval);\n                    timerInterval = null;\n                }\n\n                // Update UI\n                levelDisplay.textContent = `\ud83c\udf1f Level ${currentLevelIndex + 1}`;\n                timerElement.textContent = '\u23f1\ufe0f 0:00';\n                movesElement.textContent = '\ud83c\udfaf 0';\n                victoryOverlay.classList.remove('show');\n\n                // Set grid layout\n                cardGrid.style.gridTemplateColumns = `repeat(${currentLevel.cols}, 1fr)`;\n                cardGrid.style.gridTemplateRows = `repeat(${currentLevel.rows}, 1fr)`;\n\n                // Function to resize grid based on current play area dimensions\n                function resizeGrid() {\n                    const playArea = document.querySelector('.play-area');\n                    if (!playArea || !cardGrid) return;\n\n                    // Re-fetch current level in case it changed\n                    const levels = window.gameConfig.levels || [{ rows: 4, cols: 4, pairs: 8 }];\n                    const currentLevel = levels[currentLevelIndex] || levels[0];\n\n                    const availWidth = playArea.clientWidth * 0.9;\n                    const availHeight = playArea.clientHeight * 0.9;\n                    \n                    if (availWidth <= 0 || availHeight <= 0) {\n                        return;\n                    }\n\n                    // Adjust gap based on card count\n                    const totalCards = currentLevel.cols * currentLevel.rows;\n                    let gap = 12;\n                    if (totalCards > 12) gap = 10;\n                    if (totalCards > 20) gap = 8;\n                    if (totalCards > 30) gap = 6;\n                    cardGrid.style.gap = `${gap}px`;\n                    \n                    const cardSizeW = (availWidth - (currentLevel.cols - 1) * gap) / currentLevel.cols;\n                    const cardSizeH = (availHeight - (currentLevel.rows - 1) * gap) / currentLevel.rows;\n                    \n                    let cardSize = Math.min(cardSizeW, cardSizeH);\n                    \n                    // Limit maximum card size for smaller grids to keep them \"kawaii\"\n                    const maxCardSize = 250; \n                    if (cardSize > maxCardSize) cardSize = maxCardSize;\n\n                    const gridWidth = Math.floor(cardSize * currentLevel.cols + (currentLevel.cols - 1) * gap);\n                    const gridHeight = Math.floor(cardSize * currentLevel.rows + (currentLevel.rows - 1) * gap);\n\n                    cardGrid.style.width = `${gridWidth}px`;\n                    cardGrid.style.height = `${gridHeight}px`;\n                }\n\n                // Call resize immediately\n                resizeGrid();\n                \n                // Add window resize listener to ensure it stays fit (only once)\n                if (!window._gridResizeListenerAdded) {\n                    window.addEventListener('resize', () => {\n                        resizeGrid();\n                    });\n                    window._gridResizeListenerAdded = true;\n                }\n\n                // Get animals from config\n                let animals = window.gameConfig.animals || [\n                    'baby_panda', 'baby_bunny', 'baby_fox',\n                    'baby_penguin', 'baby_koala', 'baby_cat',\n                    'baby_chick', 'baby_pig'\n                ];\n\n                // Shuffle animals list to get different ones if we have more than needed\n                animals = [...animals].sort(() => Math.random() - 0.5);\n\n                // Create pairs\n                const numPairs = currentLevel.pairs;\n                const pairs = [];\n                \n                // Ensure we have enough animals by repeating if necessary\n                for (let i = 0; i < numPairs; i++) {\n                    const animal = animals[i % animals.length];\n                    pairs.push(animal);\n                    pairs.push(animal);\n                }\n\n                // Shuffle pairs using Fisher-Yates algorithm\n                for (let i = pairs.length - 1; i > 0; i--) {\n                    const j = Math.floor(Math.random() * (i + 1));\n                    [pairs[i], pairs[j]] = [pairs[j], pairs[i]];\n                }\n\n                // Create card elements\n                pairs.forEach((animal, index) => {\n                    const card = createCard(animal, index);\n                    cards.push(card);\n                    cardGrid.appendChild(card.element);\n                });\n            }\n\n            // Create a card element\n            function createCard(animal, index) {\n                const cardElement = document.createElement('div');\n                cardElement.className = 'card';\n                cardElement.dataset.index = index;\n\n                // Card back (face-down)\n                const cardBack = document.createElement('div');\n                cardBack.className = 'card-face card-back';\n                const cardBackPattern = lib.getAsset('card_back_pattern');\n                if (cardBackPattern) {\n                    cardBack.style.backgroundImage = `url(${cardBackPattern.url})`;\n                }\n\n                // Card front (face-up with animal)\n                const cardFront = document.createElement('div');\n                cardFront.className = 'card-face card-front';\n                const animalImg = document.createElement('img');\n                const animalAsset = lib.getAsset(animal);\n                if (animalAsset) {\n                    animalImg.src = animalAsset.url;\n                    animalImg.alt = animal;\n                }\n                cardFront.appendChild(animalImg);\n\n                cardElement.appendChild(cardBack);\n                cardElement.appendChild(cardFront);\n                const cardData = {\n                    element: cardElement,\n                    animal: animal,\n                    isFlipped: false,\n                    isMatched: false,\n                    index: index\n                };\n\n                // Add click handler\n                cardElement.addEventListener('click', () => handleCardClick(cardData));\n\n                return cardData;\n            }\n\n            // Handle card click\n            function handleCardClick(card) {\n                // Ensure music starts on first interaction\n                startBackgroundMusic();\n\n                if (mode === 'edit') {\n                    // In edit mode, just toggle flip for preview\n                    card.element.classList.toggle('flipped');\n                    return;\n                }\n\n                // Play mode logic\n                if (isChecking || card.isFlipped || card.isMatched || flippedCards.length >= 2) {\n                    return;\n                }\n\n                // Start timer on first card flip\n                if (!gameStarted) {\n                    gameStarted = true;\n                    startTime = Date.now();\n                    startTimer();\n                }\n\n                // Flip the card\n                flipCard(card);\n            }\n\n            // Flip a card face-up\n            function flipCard(card) {\n                card.isFlipped = true;\n                card.element.classList.add('flipped');\n                flippedCards.push(card);\n                playSound('card_flip_sound');\n\n                // Check for match when 2 cards are flipped\n                if (flippedCards.length === 2) {\n                    moves++;\n                    movesElement.textContent = `\ud83c\udfaf ${moves}`;\n                    checkMatch();\n                }\n            }\n\n            // Check if two flipped cards match\n            function checkMatch() {\n                isChecking = true;\n                const [card1, card2] = flippedCards;\n\n                // Wait 800ms before checking (allows player to see both cards)\n                setTimeout(() => {\n                    if (card1.animal === card2.animal) {\n                        handleMatch();\n                    } else {\n                        handleNoMatch();\n                    }\n                    isChecking = false;\n                }, 800);\n            }\n\n            // Handle successful match\n            function handleMatch() {\n                const [card1, card2] = flippedCards;\n                card1.isMatched = true;\n                card2.isMatched = true;\n                card1.element.classList.add('matched');\n                card2.element.classList.add('matched');\n                \n                playSound('match_found_sound');\n                matchedPairs++;\n\n                flippedCards = [];\n\n                // Check if all pairs are found\n                const levels = window.gameConfig.levels || [{ pairs: 8 }];\n                const currentLevel = levels[currentLevelIndex] || levels[0];\n                if (matchedPairs === currentLevel.pairs) {\n                    checkVictory();\n                }\n            }\n\n            // Handle non-matching cards\n            function handleNoMatch() {\n                const [card1, card2] = flippedCards;\n                \n                playSound('no_match_sound');\n\n                // Flip cards back face-down\n                card1.isFlipped = false;\n                card2.isFlipped = false;\n                card1.element.classList.remove('flipped');\n                card2.element.classList.remove('flipped');\n\n                flippedCards = [];\n            }\n\n            // Start the game timer (Countdown)\n            function startTimer() {\n                const levels = window.gameConfig.levels || [];\n                const currentLevel = levels[currentLevelIndex] || { timeLimit: 120 };\n                timeLeft = currentLevel.timeLimit || 120;\n\n                const updateDisplay = () => {\n                    const minutes = Math.floor(timeLeft / 60);\n                    const seconds = timeLeft % 60;\n                    timerElement.textContent = `\u23f1\ufe0f ${minutes}:${seconds.toString().padStart(2, '0')}`;\n                };\n\n                updateDisplay();\n\n                if (timerInterval) clearInterval(timerInterval);\n                \n                timerInterval = setInterval(() => {\n                    timeLeft--;\n                    updateDisplay();\n\n                    if (timeLeft <= 0) {\n                        clearInterval(timerInterval);\n                        handleGameOver();\n                    }\n                }, 1000);\n            }\n\n            function handleGameOver() {\n                victoryStats.innerHTML = `\n                    <div style=\"color: #ff4d4d; font-size: 40px; margin-bottom: 20px;\">\u23f0 Time's up! \u23f0</div>\n                    <div style=\"font-size: 28px;\">Moves: ${moves}</div>\n                `;\n                const victoryTitle = document.querySelector('.victory-title');\n                victoryTitle.textContent = \"\ud83d\udc94 Oh No! \ud83d\udc94\";\n                victoryButton.textContent = \"Try Again\";\n                isChecking = true; // Block card clicks\n                victoryOverlay.classList.add('show');\n            }\n\n            // Check for victory and show results\n            function checkVictory() {\n                if (timerInterval) {\n                    clearInterval(timerInterval);\n                    timerInterval = null;\n                }\n\n                victoryStats.innerHTML = `\n                    <div>\u23f1\ufe0f Time Left: ${timeLeft}s</div>\n                    <div>\ud83c\udfaf Moves: ${moves}</div>\n                `;\n\n                const levels = window.gameConfig.levels || [];\n                const hasNextLevel = currentLevelIndex < levels.length - 1;\n                \n                const victoryTitle = document.querySelector('.victory-title');\n                if (hasNextLevel) {\n                    victoryButton.textContent = 'Next Level';\n                    victoryTitle.textContent = `\ud83c\udf89 Level ${currentLevelIndex + 1} Complete! \ud83c\udf89`;\n                } else {\n                    victoryButton.textContent = 'Play Again';\n                    victoryTitle.textContent = '\ud83c\udf8a All Levels Clear! \ud83c\udf8a';\n                }\n\n                // Show victory screen with delay for dramatic effect\n                setTimeout(() => {\n                    playSound('victory_sound');\n                    victoryOverlay.classList.add('show');\n                }, 500);\n            }\n\n            // Restart the game\n            function restart() {\n                startBackgroundMusic();\n                initializeGame();\n            }\n\n            // Save game state\n            async function saveGame() {\n                try {\n                    // Gather current game state\n                    const cardStates = cards.map(card => ({\n                        animal: card.animal,\n                        isMatched: card.isMatched,\n                        isFlipped: card.isFlipped\n                    }));\n\n                    const saveData = {\n                        currentLevelIndex: currentLevelIndex,\n                        moves: moves,\n                        timeLeft: timeLeft,\n                        matchedPairs: matchedPairs,\n                        cardStates: cardStates,\n                        gameStarted: gameStarted,\n                        startTime: startTime ? Date.now() - startTime : null\n                    };\n\n                    await lib.saveUserGameState(saveData);\n                    lib.log('Game saved successfully! \ud83d\udcbe');\n                    \n                    // Show visual feedback\n                    saveButton.style.transform = 'scale(1.1)';\n                    saveButton.style.borderColor = '#98FB98'; \n                    setTimeout(() => {\n                        saveButton.style.transform = '';\n                        saveButton.style.borderColor = '';\n                    }, 1500);\n                } catch (error) {\n                    lib.log(`Failed to save game: ${error.message}`);\n                    saveButton.style.borderColor = '#FF6B6B'; \n                    setTimeout(() => {\n                        saveButton.style.borderColor = '';\n                    }, 1500);\n                }\n            }\n\n            // Load game state\n            async function loadGame() {\n                try {\n                    const response = await lib.getUserGameState();\n                    \n                    if (!response.state) {\n                        lib.log('No saved game found');\n                        loadButton.style.borderColor = '#FF6B6B';\n                        setTimeout(() => {\n                            loadButton.style.borderColor = '';\n                        }, 1500);\n                        return;\n                    }\n\n                    const saveData = response.state;\n                    \n                    // Stop current game\n                    if (timerInterval) {\n                        clearInterval(timerInterval);\n                        timerInterval = null;\n                    }\n\n                    // Restore game state\n                    currentLevelIndex = saveData.currentLevelIndex || 0;\n                    moves = saveData.moves || 0;\n                    timeLeft = saveData.timeLeft || 120;\n                    matchedPairs = saveData.matchedPairs || 0;\n                    gameStarted = saveData.gameStarted || false;\n                    \n                    // Clear existing cards\n                    cardGrid.innerHTML = '';\n                    cards = [];\n                    flippedCards = [];\n                    isChecking = false;\n                    victoryOverlay.classList.remove('show');\n\n                    // Get current level config\n                    const levels = window.gameConfig.levels || [{ rows: 4, cols: 4, pairs: 8 }];\n                    const currentLevel = levels[currentLevelIndex] || levels[0];\n\n                    // Update UI\n                    levelDisplay.textContent = `\ud83c\udf1f Level ${currentLevelIndex + 1}`;\n                    movesElement.textContent = `\ud83c\udfaf ${moves}`;\n                    const minutes = Math.floor(timeLeft / 60);\n                    const seconds = timeLeft % 60;\n                    timerElement.textContent = `\u23f1\ufe0f ${minutes}:${seconds.toString().padStart(2, '0')}`;\n\n                    // Set grid layout\n                    cardGrid.style.gridTemplateColumns = `repeat(${currentLevel.cols}, 1fr)`;\n                    cardGrid.style.gridTemplateRows = `repeat(${currentLevel.rows}, 1fr)`;\n\n                    // Restore cards from saved state\n                    if (saveData.cardStates && saveData.cardStates.length > 0) {\n                        saveData.cardStates.forEach((cardState, index) => {\n                            const card = createCard(cardState.animal, index);\n                            \n                            // Restore matched state\n                            if (cardState.isMatched) {\n                                card.isMatched = true;\n                                card.isFlipped = true;\n                                card.element.classList.add('matched', 'flipped');\n                            } else if (cardState.isFlipped) {\n                                // Don't restore flipped state for non-matched cards\n                                // They should start face-down\n                                card.isFlipped = false;\n                            }\n                            \n                            cards.push(card);\n                            cardGrid.appendChild(card.element);\n                        });\n                    }\n\n                    // Resume timer if game was in progress\n                    if (gameStarted && timeLeft > 0) {\n                        startTime = Date.now();\n                        startTimer();\n                    }\n\n                    lib.log('Game loaded successfully! \ud83d\udcc2');\n                    loadButton.style.transform = 'scale(1.1)';\n                    loadButton.style.borderColor = '#98FB98';\n                    setTimeout(() => {\n                        loadButton.style.transform = '';\n                        loadButton.style.borderColor = '';\n                    }, 1500);\n\n                    // Start music if not already playing\n                    startBackgroundMusic();\n\n                } catch (error) {\n                    lib.log(`Failed to load game: ${error.message}`);\n                    loadButton.style.borderColor = '#FF6B6B';\n                    setTimeout(() => {\n                        loadButton.style.borderColor = '';\n                    }, 1500);\n                }\n            }\n\n            // Event listeners\n            restartButton.addEventListener('click', restart);\n            \n            // Save and Load buttons - only work in play mode\n            if (mode !== 'edit') {\n                saveButton.addEventListener('click', saveGame);\n                loadButton.addEventListener('click', loadGame);\n            } else {\n                // Hide save/load buttons in edit mode\n                saveButton.closest('.button-wrapper').style.display = 'none';\n                loadButton.closest('.button-wrapper').style.display = 'none';\n            }\n            \n            victoryButton.addEventListener('click', () => {\n                startBackgroundMusic();\n                \n                const levels = window.gameConfig.levels || [];\n                if (currentLevelIndex < levels.length - 1) {\n                    currentLevelIndex++;\n                } else {\n                    currentLevelIndex = 0;\n                }\n                \n                initializeGame();\n            });\n\n            // Keyboard shortcuts for desktop\n            document.addEventListener('keydown', (e) => {\n                if (e.key === 'r' || e.key === 'R' || e.key === ' ') {\n                    e.preventDefault();\n                    restart();\n                }\n            });\n\n            // Show game parameters panel\n            lib.showGameParameters({\n                name: 'FurFlip Settings',\n                params: {\n                    'Current Level': {\n                        key: 'runtime.currentLevel',\n                        type: 'dropdown',\n                        options: window.gameConfig.levels.map((_, index) => ({\n                            label: `Level ${index + 1}`,\n                            value: index\n                        })),\n                        onChange: (value) => {\n                            currentLevelIndex = parseInt(value);\n                            initializeGame();\n                        }\n                    },\n                    'Background Color': {\n                        key: 'settings.backgroundColor',\n                        type: 'color',\n                        onChange: (value) => {\n                            window.gameConfig.settings.backgroundColor = value;\n                            document.documentElement.style.setProperty('--bg-gradient-start', value);\n                        }\n                    },\n                    'Music Volume': {\n                        key: 'settings.musicVolume',\n                        type: 'slider',\n                        min: 0,\n                        max: 1,\n                        step: 0.1,\n                        onChange: (value) => {\n                            window.gameConfig.settings.musicVolume = value;\n                            if (musicGainNode) {\n                                musicGainNode.gain.setTargetAtTime(value, audioContext.currentTime, 0.1);\n                            }\n                        }\n                    }\n                }\n            });\n\n            // Initialize button icons\n            function initButtonIcons() {\n                const saveIcon = lib.getAsset('ui_icon_save');\n                const loadIcon = lib.getAsset('ui_icon_load');\n                const restartIcon = lib.getAsset('ui_icon_restart');\n                \n                if (saveIcon) document.getElementById('save-icon-img').src = saveIcon.url;\n                if (loadIcon) document.getElementById('load-icon-img').src = loadIcon.url;\n                if (restartIcon) document.getElementById('restart-icon-img').src = restartIcon.url;\n            }\n            initButtonIcons();\n\n            // Initialize the game board immediately\n            initializeGame();\n\n            // Mode-specific setup\n            if (mode === 'edit') {\n                editIndicator.classList.add('show');\n                preloadAssets();\n            } else {\n                editIndicator.classList.remove('show');\n                \n                const welcomeBunnyImg = document.getElementById('welcome-bunny-img');\n                const bunnyAsset = lib.getAsset('baby_bunny');\n                if (bunnyAsset && welcomeBunnyImg) {\n                    welcomeBunnyImg.src = bunnyAsset.url;\n                }\n\n                startScreen.classList.add('show');\n                \n                // Allow starting immediately as requested\n                startButton.textContent = 'Start Game';\n                startButton.disabled = false;\n                \n                startButton.addEventListener('click', () => {\n                    startScreen.classList.remove('show');\n                    startBackgroundMusic();\n                    gameStarted = true;\n                    startTime = Date.now();\n                    startTimer();\n                }, { once: true });\n\n                // Still preload assets in background for better experience\n                preloadAssets().catch(err => console.error(\"Preload error\", err));\n            }\n        }\n    </script>\n</body>\n</html>", "game_config": "{\n  \"animals\": [\n    \"baby_panda\",\n    \"baby_bunny\",\n    \"baby_fox\",\n    \"baby_penguin\",\n    \"baby_koala\",\n    \"baby_cat\",\n    \"baby_chick\",\n    \"baby_pig\"\n  ],\n  \"gridSize\": {\n    \"rows\": 4,\n    \"cols\": 4\n  },\n  \"settings\": {\n    \"backgroundColor\": \"#FFE5E5\",\n    \"musicVolume\": 0.5\n  },\n  \"levels\": [\n    {\n      \"rows\": 2,\n      \"timeLimit\": 45,\n      \"cols\": 2,\n      \"pairs\": 2\n    },\n    {\n      \"timeLimit\": 60,\n      \"pairs\": 3,\n      \"cols\": 3,\n      \"rows\": 2\n    },\n    {\n      \"pairs\": 4,\n      \"cols\": 4,\n      \"timeLimit\": 75,\n      \"rows\": 2\n    },\n    {\n      \"rows\": 2,\n      \"cols\": 5,\n      \"pairs\": 5,\n      \"timeLimit\": 90\n    },\n    {\n      \"rows\": 3,\n      \"timeLimit\": 105,\n      \"pairs\": 6,\n      \"cols\": 4\n    },\n    {\n      \"rows\": 2,\n      \"pairs\": 7,\n      \"cols\": 7,\n      \"timeLimit\": 120\n    },\n    {\n      \"pairs\": 8,\n      \"cols\": 4,\n      \"timeLimit\": 135,\n      \"rows\": 4\n    }\n  ]\n}", "game_design_document": "## Core Game Loop and Mechanics\n\n**Gameplay Flow:**\n1. Player starts with a grid of face-down cards (each card has a kawaii baby animal on it)\n2. Player taps/clicks to flip two cards at a time\n3. If the cards match, they stay face-up and are marked as found\n4. If they don't match, they flip back face-down after a brief delay\n5. Player continues until all pairs are found\n6. Game tracks time and number of moves\n7. Victory screen shows completion time and moves, with star rating based on performance\n\n**What Makes It Compelling:**\n- Cute, rewarding visuals that make players smile\n- Progressive difficulty as players improve\n- Satisfying \"match found\" animations and sounds\n- Replayability through trying to beat personal best times\n- Simple enough for children, engaging enough for adults\n\n**Win Condition:** Find all matching pairs\n**Lose Condition:** None (casual, relaxing experience) - but timer creates urgency\n\n## Starting Scope\n\n**First Implementation (Minimal Viable Game):**\n- Single difficulty level with 4x4 grid (8 pairs, 16 cards total)\n- 6 different kawaii baby animals (used in the 8 pairs)\n- Basic flip animation\n- Match/no-match feedback with sound effects\n- Timer counting up\n- Move counter\n- Simple victory screen with time and moves\n- Restart button\n\n**Future Iterations:**\n- Multiple difficulty levels (3x4 Easy, 4x4 Medium, 4x6 Hard)\n- More baby animal varieties (12+ animals)\n- Star rating system based on time/moves\n- Particle effects on successful matches\n- Background music toggle\n- High score persistence\n- Combo system for consecutive matches\n- Hint system (briefly show all cards)\n\n## Game Perspective\n\n**Fixed-screen** - Single screen view showing the entire card grid at once. No scrolling needed. The game board is centered in the viewport with UI elements (timer, moves) at the top.\n\n## Game World and Level Design\n\n**Layout:**\n- Top bar (80px height): Timer on left, Moves counter on right, centered title\n- Main play area: 4x4 grid of cards, centered vertically and horizontally\n- Bottom area: Restart button (always visible)\n- Victory overlay: Appears over the game when all pairs are found\n\n**Card Grid Specifications:**\n- 4x4 grid = 16 cards total (8 pairs)\n- Cards are square with rounded corners\n- Gap between cards: 12px\n- Card size: Calculated to fit optimally in the available space (approximately 140x140px)\n- Grid is centered in the play area with equal margins\n\n**Visual Hierarchy:**\n- Cards are the primary focus, taking up most of the screen\n- UI elements are minimal and non-intrusive\n- Victory screen uses a semi-transparent overlay to maintain context\n\n## Edit Mode Design\n\n**Editable Properties:**\n\n1. **Animal Selection** (Simple version for first iteration)\n   - List of 6 baby animals currently in the game\n   - Each animal shows its card image as a thumbnail\n   - Users can tap an animal to see a larger preview\n   - Note: For first iteration, this is view-only. Future: allow swapping animals\n\n2. **Grid Size** (Future iteration)\n   - Dropdown: \"Easy (3x4)\", \"Medium (4x4)\", \"Hard (4x6)\"\n   - Default: Medium\n\n3. **Card Back Design** (Future iteration)\n   - Choice of 3-4 card back patterns\n   - Preview shown for each option\n\n4. **Theme Colors** (Future iteration)\n   - Background color picker\n   - Card back color picker\n   - UI accent color picker\n\n**Constraints:**\n- Must always have even number of cards (pairs)\n- Minimum 6 cards (3 pairs), maximum 24 cards (12 pairs)\n- At least 3 different animals required for any grid size\n\n## Control Design\n\n**Mobile (Touch):**\n- **Tap card**: Flip card face-up\n- **Tap restart button**: Reset game\n- **Tap victory screen**: Dismiss and restart\n\n**Desktop (Mouse + Keyboard):**\n- **Click card**: Flip card face-up\n- **Click restart button**: Reset game\n- **Click victory screen**: Dismiss and restart\n- **R key**: Restart game (keyboard shortcut)\n- **Spacebar**: Restart game (alternative shortcut)\n\n**Control Logic:**\n- Only allow flipping when fewer than 2 cards are currently face-up\n- Disable all card interactions during the \"checking match\" delay (0.8 seconds)\n- Disable interactions with already-matched cards\n- Prevent double-flipping the same card\n\n## Art Style and Visual Theme\n\n**Overall Style:** Kawaii/cute Japanese-inspired aesthetic with soft colors, rounded shapes, and adorable baby animals\n\n**Color Palette:**\n- Background: Soft pastel gradient (light pink to light blue)\n- Cards (face-down): Soft cream/white with subtle pattern\n- Card borders: Light pastel colors that complement the animals\n- UI elements: Soft pastels (pink, blue, yellow) for buttons and text\n- Text: Dark gray for readability, never pure black\n\n**Visual Characteristics:**\n- All animals drawn in consistent kawaii style: oversized heads, large sparkly eyes, tiny bodies, rosy cheeks\n- Soft shadows and highlights for depth\n- Rounded corners on all UI elements\n- Gentle, non-jarring animations\n- Particle effects (stars, hearts) for successful matches\n\n**Asset Specifications:**\n- Animal illustrations: 400x400px, transparent background, centered\n- Card back pattern: 400x400px, seamless if tiled\n- All assets should feel cohesive and part of the same art style\n\n**Code-Rendered Elements:**\n- Card containers (CSS with border-radius, box-shadow)\n- Grid layout (CSS Grid)\n- UI panels and buttons (CSS with gradients and shadows)\n- Timer and counter displays (HTML/CSS)\n- Victory overlay (CSS with backdrop-filter blur)", "persistent_storage_config": null, "game_metadata": {"game_id": "01KSGQ2M6E1HY4SZPC6QFWERS8", "title": "FurFlip", "description": "Match adorable kawaii baby animals in this charming memory card game flip cards to find pairs before time runs out!", "thumbnail_url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/thumbnail_7af0ae19-3839-445a-b833-72791f600e72.webp", "created_at": 1779751304, "updated_at": 1781623195968.6116, "art_style": null}, "task_plan": null}