<style>
    * {
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        user-select: none;
        touch-action: none;
        box-sizing: border-box;
    }
    body {
        font-family: 'Zen Maru Gothic', sans-serif;
        background: radial-gradient(circle at center, #2e1065 0%, #0f172a 100%);
        color: #ffffff;
        overflow: hidden;
        position: fixed;
        width: 100%;
        height: 100%;
    }
    .glass-card {
        background: rgba(255, 255, 255, 0.08);
        backdrop-filter: blur(16px);
        -webkit-backdrop-filter: blur(16px);
        border: 1px solid rgba(255, 255, 255, 0.15);
    }
    .glass-btn {
        background: rgba(255, 255, 255, 0.12);
        backdrop-filter: blur(10px);
        border: 1px solid rgba(255, 255, 255, 0.2);
    }
    .glass-btn:active {
        transform: scale(0.94);
        background: rgba(255, 255, 255, 0.25);
    }
    canvas {
        display: block;
    }
</style>
<!-- Top Bar HUD -->
<header class="w-full max-w-md px-4 pt-3 pb-1 flex justify-between items-center z-10">
    <!-- Score Box -->
    <div class="glass-card px-3.5 py-1.5 rounded-2xl flex flex-col items-center min-w-[95px]">
        <span class="text-[10px] font-bold uppercase tracking-wider text-purple-300">SCORE</span>
        <span id="scoreText" class="text-2xl font-black text-amber-300 tracking-tight">0</span>
    </div>

    <!-- Next Item Preview -->
    <div class="glass-card px-4 py-1.5 rounded-2xl flex flex-col items-center min-w-[85px]">
        <span class="text-[10px] font-bold uppercase tracking-wider text-purple-300">NEXT</span>
        <div id="nextPreview" class="w-8 h-8 flex items-center justify-center text-2xl mt-0.5">πŸ’</div>
    </div>

    <!-- High Score Box & Sound Toggle -->
    <div class="flex gap-2">
        <div class="glass-card px-3 py-1.5 rounded-2xl flex flex-col items-center min-w-[80px]">
            <span class="text-[10px] font-bold uppercase tracking-wider text-purple-300">BEST</span>
            <span id="bestText" class="text-lg font-bold text-emerald-400">0</span>
        </div>
        <button id="soundToggleBtn" class="glass-btn w-10 h-10 rounded-2xl flex items-center justify-center text-base text-purple-200 hover:text-white transition-colors">
            <i id="soundIcon" class="fa-solid fa-volume-high"></i>
        </button>
    </div>
</header>

<!-- Main Game Box Container -->
<main class="relative flex-1 w-full max-w-md flex flex-col items-center justify-center px-3 pb-2">
    <div id="canvasContainer" class="relative w-full h-full rounded-3xl overflow-hidden glass-card shadow-2xl flex justify-center items-center border border-white/20">
        <canvas id="gameCanvas" class="w-full h-full"></canvas>
        
        <!-- Aim Guide Line & Preview Dropper -->
        <div id="dropGuide" class="absolute top-0 bottom-0 pointer-events-none hidden flex flex-col items-center">
            <div class="w-0.5 h-full border-r-2 border-dashed border-white/50"></div>
        </div>
        <div id="droppingEmoji" class="absolute pointer-events-none transform -translate-x-1/2 -translate-y-1/2 hidden text-center flex items-center justify-center">
        </div>

        <!-- Red Deadline Indicator (Clean red dashed line with NO text) -->
        <div id="dangerLine" class="absolute w-full border-b-2 border-dashed border-red-500/80 top-[13%] pointer-events-none hidden transition-opacity duration-300 shadow-[0_0_12px_rgba(239,68,68,0.7)]">
        </div>
    </div>
</main>

<!-- Evolution Hierarchy Bottom Bar -->
<footer class="w-full max-w-md px-3 pb-3 z-10">
    <div class="glass-card p-2 rounded-2xl flex justify-between items-center overflow-x-auto gap-1 text-xs" id="evolutionBar">
        <!-- Populated via JS -->
    </div>
</footer>

<!-- Game Over Modal Overlay -->
<div id="gameOverModal" class="fixed inset-0 bg-black/80 backdrop-blur-md z-50 flex items-center justify-center p-6 hidden">
    <div class="glass-card bg-slate-900/95 border border-slate-700/80 p-6 rounded-3xl max-w-xs w-full text-center flex flex-col items-center shadow-2xl">
        <div class="w-16 h-16 mb-3 rounded-2xl bg-gradient-to-br from-red-500 to-pink-600 flex items-center justify-center shadow-lg shadow-red-500/40 text-3xl">
            πŸ’₯
        </div>
        <h2 class="text-3xl font-black text-white mb-1">GAME OVER</h2>
        <p class="text-xs text-slate-300 mb-5">γ‚³γƒ³γƒ†γƒŠγ‹γ‚‰γ‚γ΅γ‚Œγ¦γ—γΎγ„γΎγ—γŸοΌ</p>

        <div class="w-full space-y-2 mb-6">
            <div class="p-3 rounded-2xl bg-slate-800/80 border border-slate-700/60 flex justify-between items-center">
                <span class="text-xs text-slate-400 font-semibold">FINAL SCORE</span>
                <span id="finalScoreText" class="text-2xl font-black text-amber-300">0</span>
            </div>
            <div class="p-3 rounded-2xl bg-slate-800/80 border border-slate-700/60 flex justify-between items-center">
                <span class="text-xs text-slate-400 font-semibold">BEST SCORE</span>
                <span id="finalBestText" class="text-lg font-bold text-emerald-400">0</span>
            </div>
        </div>

        <button id="restartBtn" class="w-full py-3.5 rounded-2xl bg-gradient-to-r from-pink-500 to-purple-600 hover:from-pink-600 hover:to-purple-700 font-black text-white text-base shadow-lg shadow-purple-500/40 active:scale-95 transition-all">
            もう一度あそぢ
        </button>
    </div>
</div>

<script>
    // Web Audio Procedural Synthesizer
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    let isMuted = false;

    const audio = {
        init() {
            if (audioCtx.state === 'suspended') {
                audioCtx.resume();
            }
        },
        playPop(tierIndex) {
            if (isMuted) return;
            this.init();
            const osc = audioCtx.createOscillator();
            const gain = audioCtx.createGain();

            // Frequency rises smoothly with higher fruit stages
            const baseFreq = 420 - (tierIndex * 24);
            osc.type = 'sine';
            osc.frequency.setValueAtTime(Math.max(130, baseFreq), audioCtx.currentTime);
            osc.frequency.exponentialRampToValueAtTime(Math.max(180, baseFreq * 1.6), audioCtx.currentTime + 0.12);

            gain.gain.setValueAtTime(0.3, audioCtx.currentTime);
            gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.12);

            osc.connect(gain);
            gain.connect(audioCtx.destination);

            osc.start();
            osc.stop(audioCtx.currentTime + 0.12);
        },
        playGameOver() {
            if (isMuted) return;
            this.init();
            const osc = audioCtx.createOscillator();
            const gain = audioCtx.createGain();

            osc.type = 'sawtooth';
            osc.frequency.setValueAtTime(220, audioCtx.currentTime);
            osc.frequency.exponentialRampToValueAtTime(50, audioCtx.currentTime + 0.6);

            gain.gain.setValueAtTime(0.35, audioCtx.currentTime);
            gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.6);

            osc.connect(gain);
            gain.connect(audioCtx.destination);

            osc.start();
            osc.stop(audioCtx.currentTime + 0.6);
        }
    };

    // 12 Tier Fruit Hierarchy
    const TIERS = [
        { level: 0,  name: 'さくらんぼ',   radius: 16, points: 2,   emoji: 'πŸ’', color: '#ef4444', shape: 'circle' },
        { level: 1,  name: 'いけご',       radius: 22, points: 4,   emoji: 'πŸ“', color: '#f43f5e', shape: 'strawberry' },
        { level: 2,  name: 'ぢどう',       radius: 29, points: 8,   emoji: 'πŸ‡', color: '#8b5cf6', shape: 'bunch' },
        { level: 3,  name: 'デコポン',     radius: 36, points: 16,  emoji: '🍊', color: '#f97316', shape: 'dekopon' },
        { level: 4,  name: 'γ‚ͺレンジ',     radius: 43, points: 32,  emoji: '🍊', color: '#f97316', shape: 'circle' },
        { level: 5,  name: 'γ‚Šγ‚“γ”',       radius: 52, points: 64,  emoji: '🍎', color: '#dc2626', shape: 'apple' },
        { level: 6,  name: 'ζ΄‹γͺし',       radius: 61, points: 128, emoji: '🍐', color: '#84cc16', shape: 'pear' },
        { level: 7,  name: 'γ‚‚γ‚‚',         radius: 71, points: 256, emoji: 'πŸ‘', color: '#f472b6', shape: 'peach' },
        { level: 8,  name: 'γƒ‘γ‚€γƒŠγƒƒγƒ—γƒ«', radius: 82, points: 512, emoji: '🍍', color: '#eab308', shape: 'pineapple' },
        { level: 9,  name: 'パロン',       radius: 94, points: 1024,emoji: '🍈', color: '#22c55e', shape: 'circle' },
        { level: 10, name: 'γ‚Ήγ‚€γ‚«',       radius: 108,points: 2048,emoji: 'πŸ‰', color: '#15803d', shape: 'circle' },
        { level: 11, name: 'γ‚­γƒ³γ‚°ηŽ‹ε† ',   radius: 120,points: 4096,emoji: 'πŸ‘‘', color: '#f59e0b', shape: 'crown' }
    ];

    // Matter.js Engine Aliases
    const { Engine, Bodies, Composite, Events, Vertices } = Matter;

    // DOM Element Cache
    const canvasContainer = document.getElementById('canvasContainer');
    const gameCanvas = document.getElementById('gameCanvas');
    const scoreText = document.getElementById('scoreText');
    const bestText = document.getElementById('bestText');
    const nextPreview = document.getElementById('nextPreview');
    const dropGuide = document.getElementById('dropGuide');
    const droppingEmoji = document.getElementById('droppingEmoji');
    const dangerLine = document.getElementById('dangerLine');
    const evolutionBar = document.getElementById('evolutionBar');
    const gameOverModal = document.getElementById('gameOverModal');
    const restartBtn = document.getElementById('restartBtn');
    const finalScoreText = document.getElementById('finalScoreText');
    const finalBestText = document.getElementById('finalBestText');
    const soundToggleBtn = document.getElementById('soundToggleBtn');
    const soundIcon = document.getElementById('soundIcon');

    // State Flags & Variables
    let engine;
    let score = 0;
    let bestScore = parseInt(localStorage.getItem('suika_best_score') || '0');
    let currentNextTierIndex = 0;
    let currentDroppingTierIndex = 0;
    let isAiming = false;
    let canDrop = true;
    let aimX = 0;
    let isGameOver = false;
    let dangerTimer = null;
    let particles = [];
    let floatingScores = [];

    let width, height;
    let wallThickness = 60;

    function initPhysics() {
        width = canvasContainer.clientWidth;
        height = canvasContainer.clientHeight;

        gameCanvas.width = width;
        gameCanvas.height = height;

        engine = Engine.create({
            gravity: { x: 0, y: 1.25 }
        });

        createWalls();
        Events.on(engine, 'collisionStart', handleCollisions);

        requestAnimationFrame(gameLoop);

        prepareNextDrop();
        renderEvolutionBar();
        bestText.textContent = bestScore;
    }

    function createWalls() {
        const ground = Bodies.rectangle(width / 2, height + wallThickness / 2 - 8, width * 2, wallThickness, {
            isStatic: true,
            friction: 0.6,
            restitution: 0.2
        });
        const leftWall = Bodies.rectangle(-wallThickness / 2 + 6, height / 2, wallThickness, height * 2, {
            isStatic: true,
            friction: 0.6,
            restitution: 0.2
        });
        const rightWall = Bodies.rectangle(width + wallThickness / 2 - 6, height / 2, wallThickness, height * 2, {
            isStatic: true,
            friction: 0.6,
            restitution: 0.2
        });

        Composite.add(engine.world, [ground, leftWall, rightWall]);
    }

    function createFruitVertices(r, shape) {
        const points = 16;
        const verts = [];

        for (let i = 0; i < points; i++) {
            const angle = (i / points) * Math.PI * 2;
            let scaleR = 1.0;

            switch (shape) {
                case 'strawberry': // Heart / tapered cone
                    if (angle > Math.PI * 0.25 && angle < Math.PI * 0.75) {
                        scaleR = 0.72 + 0.28 * Math.abs(Math.cos(angle));
                    } else if (angle > Math.PI * 1.15 && angle < Math.PI * 1.85) {
                        scaleR = 1.08;
                    }
                    break;

                case 'bunch': // Bumpy organic cluster
                    scaleR = 0.86 + 0.14 * Math.sin(angle * 3);
                    break;

                case 'dekopon': // Round with top bump
                    if (angle > Math.PI * 1.35 && angle < Math.PI * 1.65) {
                        scaleR = 1.22;
                    } else {
                        scaleR = 0.96;
                    }
                    break;

                case 'apple': // Top stem indentation & bottom taper
                    if (angle > Math.PI * 0.35 && angle < Math.PI * 0.65) {
                        scaleR = 0.88;
                    } else if (angle > Math.PI * 1.35 && angle < Math.PI * 1.65) {
                        scaleR = 0.82;
                    }
                    break;

                case 'pear': // Bottom-heavy teardrop
                    if (angle > Math.PI * 0.25 && angle < Math.PI * 0.75) {
                        scaleR = 1.15;
                    } else if (angle > Math.PI * 1.25 && angle < Math.PI * 1.75) {
                        scaleR = 0.78;
                    }
                    break;

                case 'peach': // Top crease notch
                    if (angle > Math.PI * 1.35 && angle < Math.PI * 1.65) {
                        scaleR = 0.82;
                    }
                    break;

                case 'pineapple': // Cylindrical barrel with flared top
                    if (angle > Math.PI * 1.25 && angle < Math.PI * 1.75) {
                        scaleR = 1.18 + 0.08 * Math.sin(angle * 4);
                    } else {
                        scaleR = 0.88 + 0.2 * Math.sin(angle) ** 2;
                    }
                    break;

                case 'crown': // Wide flared top points
                    if (angle > Math.PI * 0.25 && angle < Math.PI * 0.75) {
                        scaleR = 0.85;
                    } else {
                        scaleR = 1.12;
                    }
                    break;

                case 'circle':
                default:
                    scaleR = 1.0;
                    break;
            }

            const x = Math.cos(angle) * r * scaleR;
            const y = Math.sin(angle) * r * scaleR;
            verts.push({ x, y });
        }

        return Vertices.create(verts);
    }

    function createFruitBody(x, y, tierIndex) {
        const tier = TIERS[tierIndex];
        const r = tier.radius;

        let body;
        if (tier.shape !== 'circle') {
            const verts = createFruitVertices(r, tier.shape);
            body = Bodies.fromVertices(x, y, [verts], {
                restitution: 0.18,
                friction: 0.45,
                density: 0.002 * (1 + tierIndex * 0.08),
                label: `fruit_${tierIndex}`
            });
        } else {
            body = Bodies.circle(x, y, r, {
                restitution: 0.18,
                friction: 0.45,
                density: 0.002 * (1 + tierIndex * 0.08),
                label: `fruit_${tierIndex}`
            });
        }

        body.tierIndex = tierIndex;
        return body;
    }

    function handleCollisions(event) {
        if (isGameOver) return;

        const pairs = event.pairs;
        for (let i = 0; i < pairs.length; i++) {
            const { bodyA, bodyB } = pairs[i];

            if (bodyA.tierIndex !== undefined && bodyB.tierIndex !== undefined) {
                if (bodyA.tierIndex === bodyB.tierIndex && !bodyA.isMerging && !bodyB.isMerging) {
                    const tierIdx = bodyA.tierIndex;

                    if (tierIdx < TIERS.length - 1) {
                        bodyA.isMerging = true;
                        bodyB.isMerging = true;

                        const midX = (bodyA.position.x + bodyB.position.x) / 2;
                        const midY = (bodyA.position.y + bodyB.position.y) / 2;

                        Composite.remove(engine.world, [bodyA, bodyB]);

                        const nextTierIdx = tierIdx + 1;
                        const mergedFruit = createFruitBody(midX, midY, nextTierIdx);
                        Composite.add(engine.world, mergedFruit);

                        const gainedPoints = TIERS[nextTierIdx].points;
                        score += gainedPoints;
                        scoreText.textContent = score;

                        if (score > bestScore) {
                            bestScore = score;
                            bestText.textContent = bestScore;
                            localStorage.setItem('suika_best_score', bestScore.toString());
                        }

                        spawnParticles(midX, midY, TIERS[nextTierIdx].color);
                        addFloatingScore(midX, midY, `+${gainedPoints}`);
                        audio.playPop(nextTierIdx);
                    }
                }
            }
        }
    }

    function prepareNextDrop() {
        currentDroppingTierIndex = currentNextTierIndex;
        currentNextTierIndex = Math.floor(Math.random() * 5); // Random fruit (Cherry to Dekopon)

        const nextTier = TIERS[currentNextTierIndex];
        nextPreview.textContent = nextTier.emoji;
    }

    function updateAimPosition(clientX) {
        if (!canDrop || isGameOver) return;
        const rect = canvasContainer.getBoundingClientRect();
        const rawX = clientX - rect.left;

        const radius = TIERS[currentDroppingTierIndex].radius;
        aimX = Math.max(radius + 12, Math.min(width - radius - 12, rawX));

        dropGuide.style.left = `${aimX}px`;
        dropGuide.classList.remove('hidden');

        const topY = 42;
        droppingEmoji.style.left = `${aimX}px`;
        droppingEmoji.style.top = `${topY}px`;
        
        const droppingTier = TIERS[currentDroppingTierIndex];
        droppingEmoji.style.fontSize = `${droppingTier.radius * 1.3}px`;
        droppingEmoji.textContent = droppingTier.emoji;
        droppingEmoji.classList.remove('hidden');
    }

    function executeDrop() {
        if (!canDrop || !isAiming || isGameOver) return;

        canDrop = false;
        isAiming = false;

        dropGuide.classList.add('hidden');
        droppingEmoji.classList.add('hidden');

        const topY = 42;
        const fruitBody = createFruitBody(aimX, topY, currentDroppingTierIndex);
        Composite.add(engine.world, fruitBody);

        audio.init();

        setTimeout(() => {
            if (!isGameOver) {
                prepareNextDrop();
                canDrop = true;
            }
        }, 550);
    }

    // Touch Event Listeners for iPhone
    canvasContainer.addEventListener('touchstart', (e) => {
        if (e.touches.length > 0) {
            isAiming = true;
            updateAimPosition(e.touches[0].clientX);
        }
    }, { passive: true });

    canvasContainer.addEventListener('touchmove', (e) => {
        if (isAiming && e.touches.length > 0) {
            updateAimPosition(e.touches[0].clientX);
        }
    }, { passive: true });

    canvasContainer.addEventListener('touchend', () => {
        executeDrop();
    });

    // Mouse Listeners for desktop preview
    canvasContainer.addEventListener('mousedown', (e) => {
        isAiming = true;
        updateAimPosition(e.clientX);
    });
    canvasContainer.addEventListener('mousemove', (e) => {
        if (isAiming) updateAimPosition(e.clientX);
    });
    canvasContainer.addEventListener('mouseup', () => {
        executeDrop();
    });

    function spawnParticles(x, y, color) {
        for (let i = 0; i < 16; i++) {
            const angle = Math.random() * Math.PI * 2;
            const speed = Math.random() * 6 + 2;
            particles.push({
                x, y,
                vx: Math.cos(angle) * speed,
                vy: Math.sin(angle) * speed,
                radius: Math.random() * 4 + 2,
                color: color,
                alpha: 1.0
            });
        }
    }

    function addFloatingScore(x, y, text) {
        floatingScores.push({
            x, y,
            text,
            vy: -1.8,
            alpha: 1.0
        });
    }

    const ctx = gameCanvas.getContext('2d');

    function gameLoop() {
        Engine.update(engine, 1000 / 60);

        ctx.clearRect(0, 0, width, height);

        const dangerY = height * 0.13;
        dangerLine.style.top = `${dangerY}px`;
        dangerLine.classList.remove('hidden');

        let isAnyFruitOverDanger = false;

        const bodies = Composite.allBodies(engine.world);
        bodies.forEach(body => {
            if (body.tierIndex !== undefined) {
                const { x, y } = body.position;
                const tier = TIERS[body.tierIndex];

                if (y - tier.radius < dangerY && body.velocity.y > -0.5 && body.speed < 1.0) {
                    isAnyFruitOverDanger = true;
                }

                ctx.save();
                ctx.translate(x, y);
                ctx.rotate(body.angle);

                ctx.font = `${tier.radius * 1.3}px 'Zen Maru Gothic', sans-serif`;
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText(tier.emoji, 0, 2);

                ctx.restore();
            }
        });

        // Danger Timer Trigger
        if (isAnyFruitOverDanger && !isGameOver) {
            if (!dangerTimer) {
                dangerTimer = setTimeout(() => {
                    triggerGameOver();
                }, 2200);
            }
        } else if (!isAnyFruitOverDanger && dangerTimer) {
            clearTimeout(dangerTimer);
            dangerTimer = null;
        }

        // Render Juice Particles
        for (let i = particles.length - 1; i >= 0; i--) {
            const p = particles[i];
            p.x += p.vx;
            p.y += p.vy;
            p.vy += 0.15;
            p.alpha -= 0.03;

            ctx.save();
            ctx.globalAlpha = Math.max(p.alpha, 0);
            ctx.fillStyle = p.color;
            ctx.beginPath();
            ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
            ctx.fill();
            ctx.restore();

            if (p.alpha <= 0) particles.splice(i, 1);
        }

        // Render Floating Score Text
        for (let i = floatingScores.length - 1; i >= 0; i--) {
            const fs = floatingScores[i];
            fs.y += fs.vy;
            fs.alpha -= 0.025;

            ctx.save();
            ctx.globalAlpha = Math.max(fs.alpha, 0);
            ctx.font = '900 20px "Zen Maru Gothic", sans-serif';
            ctx.fillStyle = '#fef08a';
            ctx.shadowColor = 'rgba(0,0,0,0.5)';
            ctx.shadowBlur = 6;
            ctx.textAlign = 'center';
            ctx.fillText(fs.text, fs.x, fs.y);
            ctx.restore();

            if (fs.alpha <= 0) floatingScores.splice(i, 1);
        }

        requestAnimationFrame(gameLoop);
    }

    function triggerGameOver() {
        isGameOver = true;
        audio.playGameOver();
        finalScoreText.textContent = score;
        finalBestText.textContent = bestScore;
        gameOverModal.classList.remove('hidden');
    }

    function restartGame() {
        const bodies = Composite.allBodies(engine.world);
        bodies.forEach(body => {
            if (body.tierIndex !== undefined) {
                Composite.remove(engine.world, body);
            }
        });

        score = 0;
        scoreText.textContent = '0';
        isGameOver = false;
        canDrop = true;
        if (dangerTimer) {
            clearTimeout(dangerTimer);
            dangerTimer = null;
        }

        gameOverModal.classList.add('hidden');
        prepareNextDrop();
    }

    function renderEvolutionBar() {
        evolutionBar.innerHTML = '';
        TIERS.forEach((tier, i) => {
            const item = document.createElement('div');
            item.className = 'flex flex-col items-center min-w-[26px]';
            item.innerHTML = `
                <span class="text-base">${tier.emoji}</span>
                <span class="text-[9px] text-purple-300 font-bold mt-0.5">${i + 1}</span>
            `;
            evolutionBar.appendChild(item);
        });
    }

    soundToggleBtn.addEventListener('click', () => {
        isMuted = !isMuted;
        soundIcon.className = isMuted ? 'fa-solid fa-volume-xmark text-red-400' : 'fa-solid fa-volume-high text-purple-200';
    });

    restartBtn.addEventListener('click', restartGame);

    window.onload = () => {
        initPhysics();
    };

    window.addEventListener('resize', () => {
        if (canvasContainer) {
            width = canvasContainer.clientWidth;
            height = canvasContainer.clientHeight;
            gameCanvas.width = width;
            gameCanvas.height = height;
        }
    });
</script>