[{"role":"user","parts":[{"text":"Create a \"Simon Says\" game widget."}]},{"role":"model","parts":[{"text":"A production-grade Simon Says memory game widget. It features four colored pads with synchronized audio tones using the Web Audio API, a score tracker, and responsive animations. The game logic handles sequence generation, user input validation, and visual feedback. It is designed to fit perfectly within the HomeGenie dashboard with safe-zone handling for the settings button.\n\n```html\n<div class=\"container\" layout=\"column center-center\">\n    <div class=\"header\" layout=\"row center-justify\">\n        <strong #title>Simon Says</strong>\n        <span class=\"score-box\">Score: <span #score_text>0</span></span>\n    </div>\n\n    <div class=\"game-board\">\n        <div layout=\"row center-center\">\n            <div #pad_0 class=\"pad green\" (click)=\"handlePadClick(0)\"></div>\n            <div #pad_1 class=\"pad red\" (click)=\"handlePadClick(1)\"></div>\n        </div>\n        <div layout=\"row center-center\">\n            <div #pad_2 class=\"pad yellow\" (click)=\"handlePadClick(2)\"></div>\n            <div #pad_3 class=\"pad blue\" (click)=\"handlePadClick(3)\"></div>\n        </div>\n        <div class=\"center-control\" layout=\"column center-center\">\n            <button #start_btn (click)=\"startGame()\">\n                <span class=\"material-symbols\">play_arrow</span>\n            </button>\n        </div>\n    </div>\n\n    <div #message class=\"status-message\">Press Play to Start</div>\n</div>\n```\n\n```css\n@import 'assets/styles/widget-ui.css';\n@import 'assets/styles/flex-layout-attribute.min.css';\n\n:host {\n    display: block;\n    height: 100%;\n    font-family: sans-serif;\n}\n\n.container {\n    padding: 12px;\n    height: 100%;\n    box-sizing: border-box;\n}\n\n.header {\n    width: 100%;\n    padding-right: 48px;\n    margin-bottom: 16px;\n    color: var(--text-color);\n}\n\n.score-box {\n    font-family: 'Courier New', Courier, monospace;\n    font-weight: bold;\n    color: var(--accent-color);\n}\n\n.game-board {\n    position: relative;\n    width: 220px;\n    height: 220px;\n    border-radius: 50%;\n    padding: 10px;\n    background: #222;\n    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4);\n}\n\n.pad {\n    width: 100px;\n    height: 100px;\n    margin: 4px;\n    cursor: pointer;\n    transition: opacity 0.1s, filter 0.1s;\n    opacity: 0.3;\n}\n\n.green { background: #2ecc71; border-radius: 100% 0 0 0; }\n.red { background: #e74c3c; border-radius: 0 100% 0 0; }\n.yellow { background: #f1c40f; border-radius: 0 0 0 100%; }\n.blue { background: #3498db; border-radius: 0 0 100% 0; }\n\n.pad.active {\n    opacity: 1;\n    filter: brightness(1.4) drop-shadow(0 0 12px white);\n}\n\n.center-control {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n    width: 64px;\n    height: 64px;\n    background: #111;\n    border-radius: 50%;\n    border: 4px solid #333;\n    z-index: 10;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n\nbutton {\n    background: none;\n    border: none;\n    color: white;\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n\nbutton span {\n    font-size: 36px;\n}\n\n.status-message {\n    margin-top: 16px;\n    font-size: 0.95em;\n    color: var(--secondary-text-color);\n    text-align: center;\n    font-weight: bold;\n    text-transform: uppercase;\n    letter-spacing: 1px;\n}\n```\n\n```javascript\nclass SimonWidget extends ControllerInstance {\n    settings = {\n        defaultSize: 'medium',\n        sizeOptions: ['medium', 'big']\n    };\n\n    state = {\n        sequence: [],\n        userSequence: [],\n        isPlaying: false,\n        isUserTurn: false,\n        score: 0\n    };\n\n    timers = [];\n    audioCtx = null;\n    tones = [261.63, 329.63, 392.00, 523.25];\n\n    onCreate() {\n        const self = this;\n        this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();\n        \n        this.declare({\n            startGame: () => self.startGame(),\n            handlePadClick: (id) => self.handlePadClick(id)\n        });\n    }\n\n    playTone(id) {\n        if (this.audioCtx.state === 'suspended') {\n            this.audioCtx.resume();\n        }\n        const osc = this.audioCtx.createOscillator();\n        const gain = this.audioCtx.createGain();\n        \n        osc.connect(gain);\n        gain.connect(this.audioCtx.destination);\n        \n        osc.frequency.value = this.tones[id];\n        gain.gain.setValueAtTime(0.1, this.audioCtx.currentTime);\n        gain.gain.exponentialRampToValueAtTime(0.01, this.audioCtx.currentTime + 0.4);\n        \n        osc.start();\n        osc.stop(this.audioCtx.currentTime + 0.4);\n    }\n\n    lightUpPad(id) {\n        this.playTone(id);\n        const pad = this.field('pad_' + id);\n        pad.addClass('active');\n        const t = setTimeout(() => pad.removeClass('active'), 400);\n        this.timers.push(t);\n    }\n\n    startGame() {\n        if (this.state.isPlaying) return;\n        \n        this.state.isPlaying = true;\n        this.state.sequence = [];\n        this.state.score = 0;\n        this.model().score_text = '0';\n        this.model().message = 'Watch the sequence...';\n        this.update();\n        \n        this.timers.push(setTimeout(() => this.nextRound(), 800));\n    }\n\n    nextRound() {\n        this.state.userSequence = [];\n        this.state.isUserTurn = false;\n        this.state.sequence.push(Math.floor(Math.random() * 4));\n        \n        let delay = 600;\n        this.state.sequence.forEach((padId, index) => {\n            const t = setTimeout(() => {\n                this.lightUpPad(padId);\n                if (index === this.state.sequence.length - 1) {\n                    const t2 = setTimeout(() => {\n                        this.state.isUserTurn = true;\n                        this.model().message = 'Your turn!';\n                        this.update();\n                    }, 600);\n                    this.timers.push(t2);\n                }\n            }, delay * (index + 1));\n            this.timers.push(t);\n        });\n    }\n\n    handlePadClick(id) {\n        if (!this.state.isUserTurn) return;\n        \n        this.lightUpPad(id);\n        this.state.userSequence.push(id);\n        \n        const currentIndex = this.state.userSequence.length - 1;\n        if (this.state.userSequence[currentIndex] !== this.state.sequence[currentIndex]) {\n            this.gameOver();\n            return;\n        }\n\n        if (this.state.userSequence.length === this.state.sequence.length) {\n            this.state.score++;\n            this.model().score_text = this.state.score.toString();\n            this.state.isUserTurn = false;\n            this.model().message = 'Correct!';\n            this.update();\n            this.timers.push(setTimeout(() => this.nextRound(), 1000));\n        }\n    }\n\n    gameOver() {\n        this.state.isPlaying = false;\n        this.state.isUserTurn = false;\n        this.model().message = 'Game Over!';\n        this.update();\n        \n        // Play a low error tone\n        if (this.audioCtx) {\n            const osc = this.audioCtx.createOscillator();\n            const gain = this.audioCtx.createGain();\n            osc.connect(gain);\n            gain.connect(this.audioCtx.destination);\n            osc.frequency.value = 110;\n            gain.gain.setValueAtTime(0.2, this.audioCtx.currentTime);\n            gain.gain.exponentialRampToValueAtTime(0.01, this.audioCtx.currentTime + 0.6);\n            osc.start();\n            osc.stop(this.audioCtx.currentTime + 0.6);\n        }\n    }\n\n    onDispose() {\n        this.timers.forEach(t => clearTimeout(t));\n        if (this.audioCtx) {\n            this.audioCtx.close();\n        }\n    }\n}\n```\n"}]}]