<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>Fruit Rhythm Tap! 🎶</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
            background: linear-gradient(to right, #ffecd2 0%, #fcb69f 100%);
            color: #5D4037;
            text-align: center;
            overflow-x: hidden;
            touch-action: manipulation;
            padding: 10px 0;
        }
        #game-wrapper {
            background-color: rgba(255, 255, 255, 0.8); /* Slightly more opaque */
            padding: 20px 25px; /* Adjusted padding */
            border-radius: 20px;
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2); /* Softer shadow */
            width: 90%;
            max-width: 420px; /* Slightly wider for emojis */
        }
        #current-fruit-name {
            font-size: 2.5em; /* Adjusted for emojis */
            font-weight: bold;
            color: #E64A19;
            margin-bottom: 8px;
            height: 55px; /* Increased height for emojis */
            line-height: 55px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        #current-fruit-taps {
            font-size: 1.1em; /* Adjusted */
            color: #795548;
            margin-bottom: 20px;
            height: 20px;
        }
        #tap-indicators {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 25px;
            min-height: 30px;
        }
        .indicator-dot {
            width: 18px; /* Slightly smaller */
            height: 18px;
            background-color: #FFCC80;
            border: 2px solid #FFA726;
            border-radius: 50%;
            margin: 0 5px; /* Adjusted margin */
            transition: all 0.2s ease;
        }
        .indicator-dot.tapped {
            background-color: #FFA726;
            transform: scale(1.25); /* Slightly more pop */
        }
        .indicator-dot.correct {
            background-color: #81C784;
            border-color: #4CAF50;
        }
         .indicator-dot.incorrect {
            background-color: #E57373;
            border-color: #F44336;
        }
        #action-button {
            padding: 15px 35px; /* Adjusted padding */
            font-size: 1.5em; /* Adjusted for emojis */
            background-color: #FF7043;
            color: white;
            border: none;
            border-radius: 12px;
            cursor: pointer;
            box-shadow: 0 5px 12px rgba(0,0,0,0.1);
            transition: background-color 0.2s, transform 0.1s;
            user-select: none;
            -webkit-tap-highlight-color: transparent;
            width: 85%; /* Adjusted width */
            max-width: 280px; /* Adjusted max-width */
        }
        #action-button:active {
            background-color: #F4511E;
            transform: scale(0.96);
        }
        #action-button:disabled {
            background-color: #BDBDBD;
            cursor: not-allowed;
        }
        #feedback-message {
            font-size: 1.25em; /* Adjusted */
            margin-top: 20px;
            height: 30px;
            font-weight: bold;
            color: #D32F2F;
        }
        #feedback-message.correct {
             color: #388E3C;
        }
        #score-area {
            margin-top: 18px; /* Adjusted */
            font-size: 1.25em; /* Adjusted */
            color: #4E342E;
        }
        #waveform-canvas {
            width: 100%;
            height: 70px; /* Adjusted height */
            background-color: rgba(255, 255, 255, 0.2); /* More transparent */
            border-radius: 10px;
            margin-top: 20px;
            border: 1px solid #FFCC80;
        }
    </style>
</head>
<body>
    <div id="game-wrapper">
        <div id="current-fruit-name">Fruit Rhythm! 🎶</div>
        <div id="current-fruit-taps">Tap to Start!</div>
        <div id="tap-indicators"></div>
        <button id="action-button">▶️ Start Game</button>
        <div id="feedback-message"></div>
        <div id="score-area">Score: <span id="score">0</span></div>
        <canvas id="waveform-canvas"></canvas>
    </div>

    <script>
        const fruitNameDisplay = document.getElementById('current-fruit-name');
        const fruitTapsDisplay = document.getElementById('current-fruit-taps');
        const tapIndicatorsContainer = document.getElementById('tap-indicators');
        const actionButton = document.getElementById('action-button');
        const feedbackMessageDisplay = document.getElementById('feedback-message');
        const scoreDisplay = document.getElementById('score');
        const waveformCanvas = document.getElementById('waveform-canvas');
        const canvasCtx = waveformCanvas.getContext('2d');

        const FRUITS_RHYTHMS = [
            { name: 'PEAR', emoji: '🍐', beats: 1 },
            { name: 'PLUM', emoji: '🍑', beats: 1 }, // Using peach as plum often doesn't have its own
            { name: 'APPLE', emoji: '🍎', beats: 2 },
            { name: 'MANGO', emoji: '🥭', beats: 2 },
            { name: 'GRAPES', emoji: '🍇', beats: 2 },
            { name: 'ORANGE', emoji: '🍊', beats: 2 },
            { name: 'BANANA', emoji: '🍌', beats: 3 },
            { name: 'COCONUT', emoji: '🥥', beats: 3 },
            { name: 'BLUEBERRY', emoji: '🫐', beats: 3 }, // May need good font/OS support
            { name: 'PINEAPPLE', emoji: '🍍', beats: 4 },
            { name: 'WATERMELON', emoji: '🍉', beats: 4 }
        ];
        let currentFruitChallenge = null;
        let userTapCount = 0;
        let currentScore = 0;
        let gameInProgress = false;
        let tapTimeoutId = null;
        const TAP_SEQUENCE_TIMEOUT = 1100; // ms
        const CORRECT_FEEDBACK_DURATION = 1000; // ms
        const INCORRECT_FEEDBACK_DURATION = 1500; // ms

        // --- Web Audio API Setup ---
        let audioCtx;
        let analyserNode;
        let waveformDataArray;
        let waveformBufferLength;

        function initAudio() {
            if (!audioCtx) {
                audioCtx = new (window.AudioContext || window.webkitAudioContext)();
                analyserNode = audioCtx.createAnalyser();
                analyserNode.fftSize = 2048;
                waveformBufferLength = analyserNode.frequencyBinCount;
                waveformDataArray = new Uint8Array(waveformBufferLength);
                analyserNode.connect(audioCtx.destination);
            }
             if (audioCtx.state === 'suspended') {
                audioCtx.resume();
            }
        }

        function playSound(type, tapIndex = 0, totalTapsInSequence = 1) {
            if (!audioCtx) initAudio(); // Ensure audio is initialized
            if (audioCtx.state === 'suspended') audioCtx.resume(); // Try to resume if suspended

            const now = audioCtx.currentTime;

            if (type === 'tap') {
                const osc = audioCtx.createOscillator();
                const gainNode = audioCtx.createGain();
                osc.connect(gainNode);
                gainNode.connect(analyserNode);

                let baseFreq = 220; // A3
                // Make taps ascend in pitch for multi-tap fruits
                if (totalTapsInSequence > 1) {
                    baseFreq += (tapIndex * 40); // Each tap in sequence is ~a third higher
                }
                osc.frequency.setValueAtTime(baseFreq + Math.random() * 20, now);
                osc.type = 'square'; // More percussive
                gainNode.gain.setValueAtTime(0.25, now);
                gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.15);
                osc.start(now);
                osc.stop(now + 0.15);

            } else if (type === 'correct') {
                // Play a C-major arpeggio (C4-E4-G4)
                const baseCorrectFreq = 261.63; // C4
                const frequencies = [baseCorrectFreq, baseCorrectFreq * Math.pow(2, 4/12), baseCorrectFreq * Math.pow(2, 7/12)];
                const noteDuration = 0.1;
                const gap = 0.03;
                let time = now;

                frequencies.forEach((freq, index) => {
                    const osc = audioCtx.createOscillator();
                    const g = audioCtx.createGain();
                    osc.connect(g);
                    g.connect(analyserNode);

                    osc.frequency.setValueAtTime(freq, time);
                    osc.type = 'triangle'; // Softer, pleasant tone
                    g.gain.setValueAtTime(0.3, time);
                    g.gain.setValueAtTime(0.3, time + noteDuration * 0.8); // Sustain briefly
                    g.gain.exponentialRampToValueAtTime(0.01, time + noteDuration);

                    osc.start(time);
                    osc.stop(time + noteDuration + 0.05);
                    time += noteDuration + gap;
                });

            } else if (type === 'incorrect') {
                // Play two dissonant notes
                const freqs = [164.81, 155.56]; // E3, D#3
                const noteDur = 0.12;
                let t = now;
                freqs.forEach((f, i) => {
                    const osc = audioCtx.createOscillator();
                    const g = audioCtx.createGain();
                    osc.connect(g);
                    g.connect(analyserNode);
                    osc.type = 'sawtooth';
                    osc.frequency.setValueAtTime(f, t);
                    g.gain.setValueAtTime(0.25, t);
                    g.gain.exponentialRampToValueAtTime(0.01, t + noteDur);
                    osc.start(t);
                    osc.stop(t + noteDur + 0.02);
                    t += noteDur * 0.7; // Slight overlap
                });
            }
        }

        // --- Waveform Drawing ---
        let animationFrameId_waveform;
        function drawWaveform() {
            animationFrameId_waveform = requestAnimationFrame(drawWaveform);
            if (!analyserNode || !gameInProgress) {
                // canvasCtx.clearRect(0, 0, waveformCanvas.width, waveformCanvas.height); // Handled by DPR scaling now
                return;
            }

            analyserNode.getByteTimeDomainData(waveformDataArray);

            // Use canvas.width/height which are scaled by DPR
            canvasCtx.fillStyle = 'rgba(255, 255, 255, 0.2)';
            canvasCtx.fillRect(0, 0, waveformCanvas.width, waveformCanvas.height);

            canvasCtx.lineWidth = 2.5; // Slightly thicker line
            canvasCtx.strokeStyle = '#FF7043';
            canvasCtx.beginPath();

            // Calculations should use the CSS dimensions (clientWidth) for sliceWidth,
            // but drawing happens on the scaled canvas.
            const cssWidth = waveformCanvas.clientWidth;
            const cssHeight = waveformCanvas.clientHeight;
            const sliceWidth = cssWidth * 1.0 / waveformBufferLength;
            let x = 0;

            for (let i = 0; i < waveformBufferLength; i++) {
                const v = waveformDataArray[i] / 128.0; // Normalize (0-255 -> 0-2)
                const y = v * cssHeight / 2; // Scale to CSS height

                if (i === 0) {
                    canvasCtx.moveTo(x, y);
                } else {
                    canvasCtx.lineTo(x, y);
                }
                x += sliceWidth;
            }
            canvasCtx.lineTo(cssWidth, cssHeight / 2);
            canvasCtx.stroke();
        }

        function setupCanvas() {
            const dpr = window.devicePixelRatio || 1;
            waveformCanvas.width = waveformCanvas.clientWidth * dpr;
            waveformCanvas.height = waveformCanvas.clientHeight * dpr;
            canvasCtx.scale(dpr, dpr); // Scale context for sharper drawing
            // Initial clear
            canvasCtx.fillStyle = 'rgba(255, 255, 255, 0.2)';
            canvasCtx.fillRect(0, 0, waveformCanvas.width, waveformCanvas.height);
        }


        // --- Game Logic Functions ---
        function startGame() {
            setupCanvas(); // Setup canvas dimensions and scaling
            initAudio();
            
            gameInProgress = true;
            currentScore = 0;
            scoreDisplay.textContent = currentScore;
            actionButton.innerHTML = '👆 Tap!'; // Using innerHTML for emoji
            actionButton.removeEventListener('click', startGame);
            actionButton.addEventListener('click', handleUserTap);
            feedbackMessageDisplay.textContent = '';
            
            nextFruit();
            if (animationFrameId_waveform) cancelAnimationFrame(animationFrameId_waveform); // Clear previous if any
            drawWaveform();
        }

        function nextFruit() {
            userTapCount = 0;
            clearTimeout(tapTimeoutId);
            currentFruitChallenge = FRUITS_RHYTHMS[Math.floor(Math.random() * FRUITS_RHYTHMS.length)];
            
            fruitNameDisplay.textContent = `${currentFruitChallenge.emoji} ${currentFruitChallenge.name}`;
            fruitTapsDisplay.textContent = `${currentFruitChallenge.beats} tap${currentFruitChallenge.beats > 1 ? 's' : ''}!`;
            actionButton.disabled = false;
            feedbackMessageDisplay.textContent = '';
            feedbackMessageDisplay.className = '';
            renderTapIndicators();
        }

        function renderTapIndicators(resultState = null) {
            tapIndicatorsContainer.innerHTML = '';
            for (let i = 0; i < currentFruitChallenge.beats; i++) {
                const dot = document.createElement('div');
                dot.classList.add('indicator-dot');
                if (i < userTapCount) {
                    dot.classList.add('tapped');
                }
                if (resultState) {
                    dot.classList.add(resultState);
                }
                tapIndicatorsContainer.appendChild(dot);
            }
        }

        function handleUserTap() {
            if (!gameInProgress || !currentFruitChallenge) return;
            initAudio(); // Ensure audio context is active

            // Pass current tap number (1-indexed for sound logic) and total beats
            playSound('tap', userTapCount, currentFruitChallenge.beats);
            userTapCount++;
            renderTapIndicators();
            clearTimeout(tapTimeoutId);

            if (userTapCount === currentFruitChallenge.beats) {
                checkRhythm();
            } else if (userTapCount < currentFruitChallenge.beats) {
                tapTimeoutId = setTimeout(() => {
                    if(gameInProgress) {
                        feedbackMessageDisplay.textContent = '⏳ Timeout! Too slow.';
                        feedbackMessageDisplay.className = '';
                        playSound('incorrect');
                        renderTapIndicators('incorrect');
                        actionButton.disabled = true;
                        setTimeout(nextFruit, INCORRECT_FEEDBACK_DURATION);
                    }
                }, TAP_SEQUENCE_TIMEOUT);
            } else {
                 // This case should ideally not be reached if button is disabled correctly,
                 // but as a fallback:
                checkRhythm(); 
            }
        }

        function checkRhythm() {
            clearTimeout(tapTimeoutId);
            actionButton.disabled = true;
            if (userTapCount === currentFruitChallenge.beats) {
                currentScore += 10 * currentFruitChallenge.beats;
                scoreDisplay.textContent = currentScore;
                feedbackMessageDisplay.textContent = '✅ Correct! Great job!';
                feedbackMessageDisplay.className = 'correct';
                playSound('correct');
                renderTapIndicators('correct');
                setTimeout(nextFruit, CORRECT_FEEDBACK_DURATION);
            } else {
                feedbackMessageDisplay.textContent = '❌ Oops! Try again.';
                feedbackMessageDisplay.className = '';
                playSound('incorrect');
                renderTapIndicators('incorrect');
                setTimeout(nextFruit, INCORRECT_FEEDBACK_DURATION);
            }
        }

        // Initial setup
        actionButton.addEventListener('click', startGame);
        
        document.addEventListener('keydown', (event) => {
            if (event.code === 'Space' || event.key === 'Enter') { // Added Enter key
                event.preventDefault();
                if (actionButton.disabled === false) {
                     actionButton.click();
                }
            }
        });
        
        // Call setupCanvas once on load to prepare it.
        // It will be called again in startGame for dynamic resizing if needed.
        window.addEventListener('load', setupCanvas);
        window.addEventListener('resize', setupCanvas); // Re-setup canvas on resize

    </script>
</body>
</html>