<!DOCTYPE html>
<html lang="cs">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>gateverse.cz</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
            color: #f8fafc;
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            user-select: none;
            -webkit-user-select: none;
        }
        .container {
            text-align: center;
            padding: 2rem;
            max-width: 600px;
            width: 100%;
        }
        .domain-name {
            font-size: 2.5rem;
            font-weight: 700;
            margin-bottom: 1rem;
            background: linear-gradient(90deg, #38bdf8, #818cf8);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        .tagline {
            font-size: 1.1rem;
            color: #94a3b8;
            margin-bottom: 2rem;
        }

        /* Puzzle challenge */
        .challenge-box {
            background: rgba(255,255,255,0.05);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 16px;
            padding: 1.5rem;
            margin-top: 1rem;
        }
        .challenge-label {
            font-size: 0.85rem;
            color: #94a3b8;
            margin-bottom: 1rem;
        }
        .puzzle-track {
            position: relative;
            width: 100%;
            max-width: 400px;
            height: 56px;
            margin: 0 auto;
            background: rgba(255,255,255,0.06);
            border-radius: 28px;
            border: 1px solid rgba(255,255,255,0.1);
            overflow: hidden;
            touch-action: none;
        }
        .puzzle-target {
            position: absolute;
            top: 6px;
            width: 44px;
            height: 44px;
            border-radius: 12px;
            border: 2px dashed rgba(129, 140, 248, 0.5);
            background: rgba(129, 140, 248, 0.08);
            transition: border-color 0.2s, background 0.2s;
        }
        .puzzle-target.near {
            border-color: rgba(129, 140, 248, 0.8);
            background: rgba(129, 140, 248, 0.15);
        }
        .puzzle-piece {
            position: absolute;
            top: 4px;
            left: 4px;
            width: 48px;
            height: 48px;
            cursor: grab;
            z-index: 10;
            filter: drop-shadow(0 2px 6px rgba(0,0,0,0.3));
            transition: transform 0.1s;
        }
        .puzzle-piece:active { cursor: grabbing; }
        .puzzle-piece.snapped {
            transition: left 0.2s ease, transform 0.2s ease;
            transform: scale(1.05);
        }
        .puzzle-piece svg {
            width: 48px;
            height: 48px;
        }

        /* Feedback */
        .challenge-feedback {
            margin-top: 1rem;
            font-size: 0.85rem;
            min-height: 1.3em;
            transition: opacity 0.3s;
        }
        .feedback-success { color: #4ade80; }
        .feedback-error { color: #f87171; }
        .feedback-loading { color: #94a3b8; }

        /* Info box */
        .info {
            background: rgba(255,255,255,0.05);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 12px;
            padding: 1.5rem 2rem;
            color: #cbd5e1;
            font-size: 0.95rem;
            line-height: 1.6;
            margin-top: 1.5rem;
        }

        @media (max-width: 480px) {
            .domain-name { font-size: 1.8rem; }
            .container { padding: 1rem; }
            .puzzle-track { max-width: 320px; }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1 class="domain-name">gateverse.cz</h1>
        <p class="tagline">Verify you are human to continue</p>

                <div class="challenge-box">
            <div class="challenge-label">Drag the puzzle piece to the highlighted target</div>
            <div class="puzzle-track" id="puzzleTrack">
                <div class="puzzle-target" id="puzzleTarget"></div>
                <div class="puzzle-piece" id="puzzlePiece">
                    <svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
                        <defs>
                            <linearGradient id="pg" x1="0" y1="0" x2="1" y2="1">
                                <stop offset="0%" stop-color="#818cf8"/>
                                <stop offset="100%" stop-color="#38bdf8"/>
                            </linearGradient>
                        </defs>
                        <path d="M8 4h10c0-3 4-5 6-3s2 5 0 7c-1 1-3 1-4 0h-2v10h10v-2c-1-1-1-3 0-4 2-2 5-2 7 0s1 6-3 6h0v10H8a4 4 0 01-4-4V8a4 4 0 014-4z"
                              fill="url(#pg)" stroke="rgba(255,255,255,0.2)" stroke-width="1"/>
                    </svg>
                </div>
            </div>
            <div class="challenge-feedback" id="challengeFeedback"></div>
        </div>

        <script>
        (function() {
            var TOKEN = "Q1U6fSVBzrQm8JYHMGhS7turUxUGJf6qgeBeHI7vTg6oB5VM";
            var TARGET_X = 250;
            var track = document.getElementById('puzzleTrack');
            var piece = document.getElementById('puzzlePiece');
            var target = document.getElementById('puzzleTarget');
            var feedback = document.getElementById('challengeFeedback');

            var trackRect, trackWidth, pieceW = 48, maxLeft;
            var dragging = false;
            var startOffsetX = 0;
            var trajectory = [];
            var solved = false;

            // Position the target
            function init() {
                trackRect = track.getBoundingClientRect();
                trackWidth = track.offsetWidth;
                maxLeft = trackWidth - pieceW - 8;
                // Target left is targetX scaled to track width (targetX is based on 400px)
                var scaledTarget = (TARGET_X / 400) * trackWidth;
                target.style.left = (scaledTarget - 22) + 'px';
            }
            init();
            window.addEventListener('resize', init);

            function getCurrentX() {
                return parseFloat(piece.style.left) || 4;
            }

            function addPoint(clientX, clientY) {
                if (trajectory.length < 200) {
                    trajectory.push({
                        x: Math.round(clientX * 10) / 10,
                        y: Math.round(clientY * 10) / 10,
                        t: Math.round(performance.now())
                    });
                }
            }

            // Check if piece is near target
            function checkNear() {
                var pieceCenterX = getCurrentX() + pieceW / 2;
                var scaledTarget = (TARGET_X / 400) * trackWidth;
                var dist = Math.abs(pieceCenterX - scaledTarget);
                if (dist < 25) {
                    target.classList.add('near');
                } else {
                    target.classList.remove('near');
                }
            }

            function onStart(e) {
                if (solved) return;
                e.preventDefault();
                dragging = true;
                trajectory = [];
                piece.classList.remove('snapped');

                var clientX = e.touches ? e.touches[0].clientX : e.clientX;
                var clientY = e.touches ? e.touches[0].clientY : e.clientY;
                trackRect = track.getBoundingClientRect();
                startOffsetX = clientX - trackRect.left - getCurrentX();

                addPoint(clientX, clientY);
            }

            function onMove(e) {
                if (!dragging || solved) return;
                e.preventDefault();

                var clientX = e.touches ? e.touches[0].clientX : e.clientX;
                var clientY = e.touches ? e.touches[0].clientY : e.clientY;

                var newLeft = clientX - trackRect.left - startOffsetX;
                newLeft = Math.max(4, Math.min(newLeft, maxLeft));
                piece.style.left = newLeft + 'px';

                addPoint(clientX, clientY);
                checkNear();
            }

            function onEnd(e) {
                if (!dragging || solved) return;
                dragging = false;

                var clientX = e.changedTouches ? e.changedTouches[0].clientX : e.clientX;
                var clientY = e.changedTouches ? e.changedTouches[0].clientY : e.clientY;
                addPoint(clientX, clientY);

                // Calculate final position relative to track (scaled back to 400px)
                var pieceCenterX = getCurrentX() + pieceW / 2;
                var finalX = (pieceCenterX / trackWidth) * 400;

                // Check if close enough to submit
                if (Math.abs(finalX - TARGET_X) <= 20) {
                    // Snap piece to target
                    var scaledTarget = (TARGET_X / 400) * trackWidth;
                    piece.style.left = (scaledTarget - pieceW / 2) + 'px';
                    piece.classList.add('snapped');
                    target.classList.add('near');

                    submitChallenge(finalX);
                } else {
                    showFeedback('Move the piece closer to the target zone.', 'error');
                }
            }

            function submitChallenge(finalX) {
                if (solved) return;
                solved = true;
                showFeedback('Verifying...', 'loading');

                var xhr = new XMLHttpRequest();
                xhr.open('POST', '/challenge-unblock', true);
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.onreadystatechange = function() {
                    if (xhr.readyState !== 4) return;

                    try {
                        var resp = JSON.parse(xhr.responseText);
                    } catch(e) {
                        showFeedback('An error occurred. Refreshing...', 'error');
                        setTimeout(function() { location.reload(); }, 2000);
                        return;
                    }

                    if (xhr.status === 200 && resp.ok) {
                        showFeedback('Verified! Redirecting...', 'success');
                        setTimeout(function() {
                            window.location.href = resp.redirect || '/';
                        }, 800);
                    } else if (xhr.status === 429) {
                        showFeedback(resp.reason || 'Too many attempts.', 'error');
                    } else {
                        showFeedback(resp.reason || 'Verification failed. Try again.', 'error');
                        solved = false;
                        // Reset piece position
                        setTimeout(function() {
                            piece.style.left = '4px';
                            piece.classList.remove('snapped');
                            target.classList.remove('near');
                        }, 1500);
                    }
                };

                xhr.send(JSON.stringify({
                    token: TOKEN,
                    final_x: Math.round(finalX * 10) / 10,
                    trajectory: trajectory
                }));
            }

            function showFeedback(msg, type) {
                feedback.textContent = msg;
                feedback.className = 'challenge-feedback feedback-' + type;
            }

            // Bind events
            piece.addEventListener('mousedown', onStart);
            piece.addEventListener('touchstart', onStart, { passive: false });
            document.addEventListener('mousemove', onMove);
            document.addEventListener('touchmove', onMove, { passive: false });
            document.addEventListener('mouseup', onEnd);
            document.addEventListener('touchend', onEnd);
        })();
        </script>
            </div>
</body>
</html>
