Drawaria Physics Engine Volleyball🏐

Advanced volleyball physics with professional FIVB court and spike system!

// ==UserScript==
// @name         Drawaria Physics Engine Volleyball🏐
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  Advanced volleyball physics with professional FIVB court and spike system!
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @grant        none
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function() {
    'use strict';

    /* ---------- SHARED SYSTEM COMPONENTS ---------- */
    let drawariaSocket = null;
    let drawariaCanvas = null;
    let drawariaCtx = null;

    // Optimized command queue
    const commandQueue = [];
    let batchProcessor = null;
    const BATCH_SIZE = 16;
    const BATCH_INTERVAL = 38;

    const positionCache = new Map();
    const MOVEMENT_THRESHOLD = 2;

    // ✅ COLORES OFICIALES DE VOLLEYBALL FIVB
    const VOLLEYBALL_COLORS = {
        courtColor: '#FF8C69',      // Naranja cancha interior
        floorColor: '#DEB887',      // Piso beige alrededor
        lineColor: '#FFFFFF',       // Líneas blancas oficiales (5cm ancho)
        netColor: '#000000',        // Red negra
        postColor: '#8B4513',       // Postes marrones
        attackLineColor: '#FFFF00', // Línea de ataque amarilla
        textColor: '#FFFFFF',       // Texto blanco
        zoneColor: '#FFE4B5'        // Zonas de saque
    };

    // Volleyball physics constants[1][2]
    const VOLLEYBALL_PHYSICS = {
        GRAVITY: 250,               // Gravedad reducida para rallies largos
        BALL_MASS: 0.08,           // Pelota muy liviana
        BALL_RADIUS: 18,           // Tamaño medio de volleyball
        TIMESTEP: 1/60,
        MAX_VELOCITY: 700,         // Velocidad alta para spikes
        AIR_RESISTANCE: 0.008,     // Más resistencia para flotación
        RESTITUTION_BALL: 0.9,     // Rebote alto característico
        RESTITUTION_NET: 0.2,      // Rebote bajo en la red
        RESTITUTION_FLOOR: 0.85,   // Rebote alto en el piso
        FRICTION_COURT: 0.7,       // Fricción media
        PLAYER_INTERACTION_FORCE: 400,
        PLAYER_PUSH_MULTIPLIER: 2.5,

        // Volleyball specific[3]
        SPIKE_FORCE: 500,
        SET_FORCE: 200,
        SERVE_FORCE: 350,
        BALL_COLOR: '#FFFFE0',     // Amarillo claro como pidió
        NET_HEIGHT_MALE: 80,       // 2.43m convertido a pixels
        NET_HEIGHT_FEMALE: 75,     // 2.24m convertido a pixels
        ATTACK_LINE_DISTANCE: 0.33, // 3m de 9m = 1/3
        TOUCH_LIMIT: 3             // Máximo 3 toques por equipo
    };

    const VOLLEYBALL_GAME = {
        POINTS_TO_WIN: 25,
        SETS_TO_WIN: 3,
        MIN_POINT_DIFFERENCE: 2,
        MAX_TOUCHES_PER_TEAM: 3
    };

    let isDrawing = false;
    let isStopped = false;

    // WebSocket interception
    const originalWebSocketSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function (...args) {
        if (!drawariaSocket && this.url && this.url.includes('drawaria')) {
            drawariaSocket = this;
            console.log('🔗 Drawaria WebSocket captured for volleyball engine.');
            startBatchProcessor();
        }
        return originalWebSocketSend.apply(this, args);
    };

    function startBatchProcessor() {
        if (batchProcessor) return;
        batchProcessor = setInterval(() => {
            if (!drawariaSocket || drawariaSocket.readyState !== WebSocket.OPEN || commandQueue.length === 0) {
                return;
            }
            const batch = commandQueue.splice(0, BATCH_SIZE);
            batch.forEach(cmd => {
                try { drawariaSocket.send(cmd); } catch (e) { console.warn('Failed to send command:', e); }
            });
        }, BATCH_INTERVAL);
    }

    function enqueueDrawCommand(x1, y1, x2, y2, color, thickness) {
        if (!drawariaCanvas || !drawariaSocket) return;

        const normX1 = (x1 / drawariaCanvas.width).toFixed(4);
        const normY1 = (y1 / drawariaCanvas.height).toFixed(4);
        const normX2 = (x2 / drawariaCanvas.width).toFixed(4);
        const normY2 = (y2 / drawariaCanvas.height).toFixed(4);

        const cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${-Math.abs(thickness)},"${color}",0,0,{}]]`;
        commandQueue.push(cmd);

        if (drawariaCtx) {
            drawariaCtx.strokeStyle = color;
            drawariaCtx.lineWidth = thickness;
            drawariaCtx.lineCap = 'round';
            drawariaCtx.lineJoin = 'round';
            drawariaCtx.beginPath();
            drawariaCtx.moveTo(x1, y1);
            drawariaCtx.lineTo(x2, y2);
            drawariaCtx.stroke();
        }
    }

    // Helper functions
    function clamp(value, min, max) { return Math.min(Math.max(value, min), max); }
    function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }

    // ✅ SISTEMA DE COORDENADAS DE VOLLEYBALL PROFESIONAL
    function getCanvasSize() {
        return {
            width: drawariaCanvas.width,
            height: drawariaCanvas.height
        };
    }

    function calculateVolleyballCoordinates() {
        const size = getCanvasSize();

        // Cancha oficial: 18m x 9m (proporción 2:1)[1][2]
        const courtWidth = Math.floor(size.width * 0.8);
        const courtHeight = Math.floor(courtWidth * 0.5); // Mantener proporción 2:1
        const courtX = (size.width - courtWidth) / 2;
        const courtY = (size.height - courtHeight) / 2;

        const coords = {
            // Cancha principal (18m x 9m)
            court: {
                x: courtX,
                y: courtY,
                width: courtWidth,
                height: courtHeight
            },

            // Red central[3]
            net: {
                x: courtX + courtWidth / 2,
                y1: courtY,
                y2: courtY + courtHeight,
                height: VOLLEYBALL_PHYSICS.NET_HEIGHT_MALE,
                width: 4
            },

            // Postes de la red
            netPosts: {
                left: {
                    x: courtX + courtWidth / 2 - 2,
                    y: courtY - 30,
                    width: 4,
                    height: 30 + VOLLEYBALL_PHYSICS.NET_HEIGHT_MALE
                },
                right: {
                    x: courtX + courtWidth / 2 - 2,
                    y: courtY + courtHeight,
                    width: 4,
                    height: 30 + VOLLEYBALL_PHYSICS.NET_HEIGHT_MALE
                }
            },

            // Líneas de ataque (3 metros de la red)[1]
            attackLines: {
                left: {
                    x: courtX + courtWidth * (0.5 - VOLLEYBALL_PHYSICS.ATTACK_LINE_DISTANCE),
                    y1: courtY,
                    y2: courtY + courtHeight
                },
                right: {
                    x: courtX + courtWidth * (0.5 + VOLLEYBALL_PHYSICS.ATTACK_LINE_DISTANCE),
                    y1: courtY,
                    y2: courtY + courtHeight
                }
            },

            // Zonas de juego (cada lado 9m x 9m)
            zones: {
                leftSide: {
                    x: courtX,
                    y: courtY,
                    width: courtWidth / 2,
                    height: courtHeight
                },
                rightSide: {
                    x: courtX + courtWidth / 2,
                    y: courtY,
                    width: courtWidth / 2,
                    height: courtHeight
                }
            },

            // Áreas de saque
            serveAreas: {
                leftServe: {
                    x: courtX - 20,
                    y: courtY + courtHeight * 0.8,
                    width: 20,
                    height: courtHeight * 0.2
                },
                rightServe: {
                    x: courtX + courtWidth,
                    y: courtY + courtHeight * 0.8,
                    width: 20,
                    height: courtHeight * 0.2
                }
            },

            // Texto
            text: {
                x: Math.floor(size.width * 0.5),
                y: Math.floor(size.height * 0.05),
                pixelSize: Math.max(2, Math.floor(size.width * 0.004))
            }
        };

        return coords;
    }

    function sendDrawCommand(x, y, x2, y2, color, thickness) {
        if (!drawariaSocket || !drawariaCanvas) return;

        const normX = (x / drawariaCanvas.width).toFixed(4);
        const normY = (y / drawariaCanvas.height).toFixed(4);
        const normX2 = (x2 / drawariaCanvas.width).toFixed(4);
        const normY2 = (y2 / drawariaCanvas.height).toFixed(4);

        const command = `42["drawcmd",0,[${normX},${normY},${normX2},${normY2},false,${0 - thickness},"${color}",0,0,{}]]`;
        drawariaSocket.send(command);
    }

    async function drawLineLocalAndServer(startX, startY, endX, endY, color, thickness, delay = 40) {
        if (isStopped) {
            isDrawing = false;
            return;
        }

        const canvasSize = getCanvasSize();
        startX = clamp(startX, -50, canvasSize.width + 50);
        startY = clamp(startY, 0, canvasSize.height);
        endX = clamp(endX, -50, canvasSize.width + 50);
        endY = clamp(endY, 0, canvasSize.height);

        if (drawariaCtx && startX >= 0 && startX <= canvasSize.width && startY >= 0 && startY <= canvasSize.height) {
            drawariaCtx.strokeStyle = color;
            drawariaCtx.lineWidth = thickness;
            drawariaCtx.lineCap = 'round';
            drawariaCtx.lineJoin = 'round';
            drawariaCtx.beginPath();
            drawariaCtx.moveTo(startX, startY);
            drawariaCtx.lineTo(endX, endY);
            drawariaCtx.stroke();
        }

        sendDrawCommand(startX, startY, endX, endY, color, thickness);
        await sleep(delay);
    }

    async function drawPixel(x, y, color, size = 2) {
        if (isStopped) return;

        const canvasSize = getCanvasSize();
        x = clamp(x, 0, canvasSize.width - size);
        y = clamp(y, 0, canvasSize.height - size);

        if (drawariaCtx) {
            drawariaCtx.fillStyle = color;
            drawariaCtx.fillRect(x, y, size, size);
        }

        sendDrawCommand(x, y, x + 1, y + 1, color, size);
        await sleep(10);
    }

    // ✅ FUNCIONES DE DIBUJO DE CANCHA DE VOLLEYBALL
    async function drawVolleyballCourt() {
        if (isStopped) return;

        updateStatus(document.getElementById('volleyball-status'), "🏐 Dibujando cancha oficial FIVB...", VOLLEYBALL_COLORS.courtColor);

        const coords = calculateVolleyballCoordinates();

        // Piso alrededor de la cancha
        const canvasSize = getCanvasSize();
        for (let y = 20; y < canvasSize.height - 20; y += 5) {
            await drawLineLocalAndServer(20, y, canvasSize.width - 20, y, VOLLEYBALL_COLORS.floorColor, 2, 15);
            if (isStopped) break;
        }

        // Superficie de la cancha (18m x 9m)
        for (let y = coords.court.y; y < coords.court.y + coords.court.height; y += 4) {
            await drawLineLocalAndServer(coords.court.x, y, coords.court.x + coords.court.width, y, VOLLEYBALL_COLORS.courtColor, 2, 20);
            if (isStopped) break;
        }
    }

    async function drawVolleyballLines(coords) {
        if (isStopped) return;

        updateStatus(document.getElementById('volleyball-status'), "⚪ Dibujando líneas oficiales FIVB...", VOLLEYBALL_COLORS.lineColor);

        // Grosor oficial de líneas: 5cm[1]
        const lineThickness = Math.max(4, Math.floor(drawariaCanvas.width * 0.008));

        // Perímetro de la cancha (18m x 9m)
        await drawRectangleOutline(coords.court, VOLLEYBALL_COLORS.lineColor, lineThickness);

        // Línea central (divide la cancha en dos partes iguales)
        await drawLineLocalAndServer(
            coords.net.x, coords.court.y,
            coords.net.x, coords.court.y + coords.court.height,
            VOLLEYBALL_COLORS.lineColor, lineThickness, 60
        );

        // Líneas de ataque (3 metros de la red en cada lado)[1]
        await drawLineLocalAndServer(
            coords.attackLines.left.x, coords.attackLines.left.y1,
            coords.attackLines.left.x, coords.attackLines.left.y2,
            VOLLEYBALL_COLORS.attackLineColor, lineThickness, 70
        );

        await drawLineLocalAndServer(
            coords.attackLines.right.x, coords.attackLines.right.y1,
            coords.attackLines.right.x, coords.attackLines.right.y2,
            VOLLEYBALL_COLORS.attackLineColor, lineThickness, 70
        );
    }

    async function drawVolleyballNet(coords) {
        if (isStopped) return;

        updateStatus(document.getElementById('volleyball-status'), "🕸️ Instalando red de volleyball...", VOLLEYBALL_COLORS.netColor);

        // Postes de la red
        await drawRectangleOutline(coords.netPosts.left, VOLLEYBALL_COLORS.postColor, 4);
        await drawRectangleOutline(coords.netPosts.right, VOLLEYBALL_COLORS.postColor, 4);

        // Rellenar postes
        await fillRectangle(coords.netPosts.left, VOLLEYBALL_COLORS.postColor);
        await fillRectangle(coords.netPosts.right, VOLLEYBALL_COLORS.postColor);

        // Red vertical (1 metro de ancho)[2][3]
        const netDensity = 16;
        for (let i = 0; i < netDensity; i++) {
            const netY = coords.net.y1 + (i * (coords.net.y2 - coords.net.y1) / netDensity);
            await drawLineLocalAndServer(
                coords.net.x, netY,
                coords.net.x, netY + (coords.net.y2 - coords.net.y1) / netDensity,
                VOLLEYBALL_COLORS.netColor, 2, 25
            );
            if (isStopped) break;
        }

        // Líneas horizontales de la red
        const horizontalNetLines = 12;
        for (let i = 0; i < horizontalNetLines; i++) {
            const netX = coords.net.x - 1 + (i * 0.2);
            await drawLineLocalAndServer(
                netX, coords.net.y1,
                netX, coords.net.y2,
                VOLLEYBALL_COLORS.netColor, 1, 20
            );
            if (isStopped) break;
        }

        // Borde superior de la red (más grueso)
        await drawLineLocalAndServer(
            coords.net.x - 2, coords.net.y1,
            coords.net.x + 2, coords.net.y1,
            VOLLEYBALL_COLORS.netColor, 6, 50
        );
    }

    async function drawVolleyballZones(coords) {
        if (isStopped) return;

        updateStatus(document.getElementById('volleyball-status'), "🎯 Marcando zonas de juego...", VOLLEYBALL_COLORS.zoneColor);

        // Zonas de saque
        await drawRectangleOutline(coords.serveAreas.leftServe, VOLLEYBALL_COLORS.zoneColor, 3);
        await drawRectangleOutline(coords.serveAreas.rightServe, VOLLEYBALL_COLORS.zoneColor, 3);

        // Marcar zonas de ataque y defensa con líneas punteadas
        await drawDottedZones(coords);
    }

    async function drawDottedZones(coords) {
        // Zona de ataque izquierda (frontal)
        for (let x = coords.court.x; x < coords.attackLines.left.x; x += 15) {
            await drawLineLocalAndServer(x, coords.court.y + 10, x + 8, coords.court.y + 10, VOLLEYBALL_COLORS.zoneColor, 2, 15);
            if (isStopped) break;
        }

        // Zona de ataque derecha (frontal)
        for (let x = coords.attackLines.right.x; x < coords.court.x + coords.court.width; x += 15) {
            await drawLineLocalAndServer(x, coords.court.y + 10, x + 8, coords.court.y + 10, VOLLEYBALL_COLORS.zoneColor, 2, 15);
            if (isStopped) break;
        }
    }

    // ✅ FUNCIONES GEOMÉTRICAS
    async function drawRectangleOutline(rectCoords, color, thickness) {
        await drawLineLocalAndServer(rectCoords.x, rectCoords.y,
            rectCoords.x + rectCoords.width, rectCoords.y, color, thickness, 35);
        await drawLineLocalAndServer(rectCoords.x + rectCoords.width, rectCoords.y,
            rectCoords.x + rectCoords.width, rectCoords.y + rectCoords.height, color, thickness, 35);
        await drawLineLocalAndServer(rectCoords.x + rectCoords.width, rectCoords.y + rectCoords.height,
            rectCoords.x, rectCoords.y + rectCoords.height, color, thickness, 35);
        await drawLineLocalAndServer(rectCoords.x, rectCoords.y + rectCoords.height,
            rectCoords.x, rectCoords.y, color, thickness, 35);
    }

    async function fillRectangle(rectCoords, color) {
        const steps = Math.floor(rectCoords.height / 3);
        for (let i = 0; i < steps; i++) {
            const y = rectCoords.y + (i * 3);
            await drawLineLocalAndServer(rectCoords.x + 1, y, rectCoords.x + rectCoords.width - 1, y, color, 2, 12);
            if (isStopped) break;
        }
    }

    // ✅ TEXTO VOLLEYBALL EN PIXEL ART
    const VOLLEYBALL_LETTERS = {
        'V': [[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[0,1,0,1,0],[0,0,1,0,0]],
        'O': [[1,1,1,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,1,1]],
        'L': [[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,1,1,1]],
        'E': [[1,1,1,1],[1,0,0,0],[1,1,1,0],[1,0,0,0],[1,1,1,1]],
        'Y': [[1,0,0,0,1],[1,0,0,0,1],[0,1,0,1,0],[0,0,1,0,0],[0,0,1,0,0]],
        'B': [[1,1,1,1],[1,0,0,1],[1,1,1,1],[1,0,0,1],[1,1,1,1]],
        'A': [[0,1,1,0],[1,0,0,1],[1,1,1,1],[1,0,0,1],[1,0,0,1]],
        'R': [[1,1,1,0],[1,0,0,1],[1,1,1,0],[1,0,1,0],[1,0,0,1]]
    };

    async function drawVolleyballPixelText(text, coords) {
        if (isStopped) return;

        const letterSpacing = coords.text.pixelSize * 6;
        const textWidth = text.length * letterSpacing;
        let currentX = coords.text.x - (textWidth / 2);

        for (let i = 0; i < text.length; i++) {
            if (isStopped) break;

            const letter = text[i].toUpperCase();
            if (letter === ' ') {
                currentX += letterSpacing;
                continue;
            }

            const pattern = VOLLEYBALL_LETTERS[letter];
            if (!pattern) continue;

            for (let row = 0; row < pattern.length; row++) {
                for (let col = 0; col < pattern[row].length; col++) {
                    if (pattern[row][col] === 1) {
                        const pixelX = currentX + (col * coords.text.pixelSize);
                        const pixelY = coords.text.y + (row * coords.text.pixelSize);

                        const canvasSize = getCanvasSize();
                        if (pixelX >= 0 && pixelX < canvasSize.width && pixelY >= 0 && pixelY < canvasSize.height) {
                            await drawPixel(pixelX, pixelY, VOLLEYBALL_COLORS.textColor, coords.text.pixelSize);
                        }
                    }
                }
            }

            currentX += letterSpacing;
            await sleep(80);
        }
    }

    // ✅ FUNCIÓN PRINCIPAL: CANCHA DE VOLLEYBALL COMPLETA
    async function drawCompleteVolleyballCourt() {
        if (isDrawing) {
            alert('Ya está en curso un dibujo. Presiona "Parar" para cancelar.');
            return;
        }

        if (!drawariaSocket || !drawariaCanvas || !drawariaCtx) {
            alert('No se detectó conexión o canvas. Asegúrate de estar en una sala de juego.');
            return;
        }

        isDrawing = true;
        isStopped = false;
        const statusDiv = document.getElementById('volleyball-status') || createStatusDiv();

        try {
            const coords = calculateVolleyballCoordinates();
            const canvasSize = getCanvasSize();

            console.log(`🏐 Cancha de volleyball FIVB iniciada:`);
            console.log(`📏 Canvas: ${canvasSize.width}x${canvasSize.height}`);

            updateStatus(statusDiv, `🏐 CANCHA VOLLEYBALL FIVB: ${canvasSize.width}x${canvasSize.height}`, "#FF8C69");
            await sleep(800);

            // FASE 1: SUPERFICIE DE CANCHA
            updateStatus(statusDiv, "🏐 FASE 1: Superficie oficial FIVB...", VOLLEYBALL_COLORS.courtColor);
            await drawVolleyballCourt();
            await sleep(300);
            if (isStopped) return;

            // FASE 2: LÍNEAS OFICIALES
            updateStatus(statusDiv, "⚪ FASE 2: Líneas oficiales (5cm ancho)...", VOLLEYBALL_COLORS.lineColor);
            await drawVolleyballLines(coords);
            await sleep(300);
            if (isStopped) return;

            // FASE 3: RED Y POSTES
            updateStatus(statusDiv, "🕸️ FASE 3: Red y postes oficiales...", VOLLEYBALL_COLORS.netColor);
            await drawVolleyballNet(coords);
            await sleep(300);
            if (isStopped) return;

            // FASE 4: ZONAS DE JUEGO
            updateStatus(statusDiv, "🎯 FASE 4: Zonas de ataque y saque...", VOLLEYBALL_COLORS.zoneColor);
            await drawVolleyballZones(coords);
            await sleep(300);
            if (isStopped) return;

            // FASE 5: TEXTO VOLLEYBALL
            updateStatus(statusDiv, "🎮 FASE 5: Texto blanco 'VOLLEYBALL'...", VOLLEYBALL_COLORS.textColor);
            await drawVolleyballPixelText("VOLLEYBALL", coords);

            // CANCHA COMPLETA
            updateStatus(statusDiv, "🏆 ¡CANCHA DE VOLLEYBALL FIVB COMPLETA! 🏐🏆", "#006400");

            setTimeout(() => {
                if (statusDiv && statusDiv.parentNode) {
                    statusDiv.style.opacity = 0;
                    setTimeout(() => statusDiv.remove(), 500);
                }
            }, 4000);

        } catch (error) {
            console.error("Error en cancha de volleyball:", error);
            updateStatus(statusDiv, `❌ Error: ${error.message}`, "#B22222");
        } finally {
            isDrawing = false;
        }
    }

    function createStatusDiv() {
        const statusDiv = document.createElement('div');
        statusDiv.id = 'volleyball-status';
        statusDiv.style.cssText = `
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: linear-gradient(135deg, #FF8C69 0%, #FFE4B5 100%);
            color: white;
            padding: 20px 45px;
            border-radius: 35px;
            font-weight: bold;
            z-index: 10000;
            transition: opacity 0.5s;
            text-align: center;
            min-width: 500px;
            box-shadow: 0 15px 35px rgba(0,0,0,0.5);
            text-shadow: 1px 1px 3px rgba(0,0,0,0.4);
            border: 2px solid #FFFFFF;
        `;
        document.body.appendChild(statusDiv);
        return statusDiv;
    }

    function updateStatus(statusDiv, message, color) {
        if (!statusDiv) return;
        statusDiv.textContent = message;
        if (color) {
            statusDiv.style.background = color;
        }
        statusDiv.style.opacity = 1;
    }

    /* ---------- ADVANCED VOLLEYBALL PHYSICS ENGINE ---------- */
    class AdvancedDrawariaVolleyball {
        constructor() {
            this.initialized = false;
            this.isActive = false;
            this.physicsObjects = new Map();
            this.objectIdCounter = 0;
            this.lastRenderTime = 0;
            this.renderInterval = 1000 / 30;

            // Sistema de toques de volleyball[4][5]
            this.touchSystem = {
                teamTouches: { left: 0, right: 0 },
                lastTouchTeam: null,
                maxTouches: VOLLEYBALL_GAME.MAX_TOUCHES_PER_TEAM,
                touchCooldown: 200
            };

            // Volleyball game state
            this.volleyballGame = {
                active: false,
                sets: { p1: 0, p2: 0 },
                points: { p1: 0, p2: 0 },
                serving: 'p1',
                netHeight: VOLLEYBALL_PHYSICS.NET_HEIGHT_MALE,
                currentSet: 1
            };

            this.gameStats = {
                totalSpikes: 0,
                totalBlocks: 0,
                totalSets: 0,
                aces: 0,
                maxVelocityReached: 0,
                ballsCreated: 0,
                ralliesPlayed: 0
            };

            this.controls = {
                showDebug: false,
                defaultBallColor: VOLLEYBALL_PHYSICS.BALL_COLOR,
                netHeight: 'male', // male or female
                gameMode: 'rally'
            };

            this.playerTracker = {
                players: new Map(),
                detectionRadius: VOLLEYBALL_PHYSICS.BALL_RADIUS * 2.5,
                lastUpdateTime: 0
            };

            this.init();
        }

        init() {
            if (this.initialized) return;

            const checkGameReady = () => {
                const gameCanvas = document.getElementById('canvas');
                if (gameCanvas) {
                    this.canvasElement = gameCanvas;
                    drawariaCanvas = gameCanvas;
                    this.canvasContext = gameCanvas.getContext('2d');
                    drawariaCtx = gameCanvas.getContext('2d');

                    this.initialized = true;
                    this.createVolleyballPanel();
                    console.log('✅ Advanced Volleyball Physics Engine v1.0 initialized');
                } else {
                    setTimeout(checkGameReady, 100);
                }
            };
            checkGameReady();
        }

        createVolleyballPanel() {
            const existingPanel = document.getElementById('volleyball-physics-panel');
            if (existingPanel) existingPanel.remove();

            const panel = document.createElement('div');
            panel.id = 'volleyball-physics-panel';
            panel.style.cssText = `
                position: fixed !important;
                top: 20px !important;
                right: 20px !important;
                width: 400px !important;
                z-index: 2147483647 !important;
                background: linear-gradient(135deg, #2f1f0f, #4a3a1a) !important;
                border: 2px solid #FF8C69 !important;
                border-radius: 15px !important;
                color: white !important;
                font-family: 'Segoe UI', Arial, sans-serif !important;
                overflow: hidden !important;
                box-shadow: 0 0 30px rgba(255,140,105,0.4) !important;
            `;

            panel.innerHTML = `
                <!-- HEADER -->
                <div id="volleyball-panel-header" style="
                    background: linear-gradient(45deg, #FF8C69, #FFE4B5);
                    padding: 12px 20px;
                    font-weight: bold;
                    text-align: center;
                    font-size: 14px;
                    cursor: move;
                    user-select: none;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                ">
                    <div style="flex: 1;">🏐 FIVB VOLLEYBALL ENGINE v1.0</div>
                    <div style="display: flex; gap: 8px;">
                        <button id="volleyball-minimize-btn" style="
                            width: 25px; height: 25px;
                            background: rgba(255,255,255,0.2);
                            border: none; border-radius: 4px;
                            color: white; cursor: pointer;
                            font-size: 16px; line-height: 1; padding: 0;
                        ">−</button>
                        <button id="volleyball-close-btn" style="
                            width: 25px; height: 25px;
                            background: rgba(255,0,0,0.6);
                            border: none; border-radius: 4px;
                            color: white; cursor: pointer;
                            font-size: 18px; line-height: 1; padding: 0;
                        ">×</button>
                    </div>
                </div>

                <!-- CONTENT -->
                <div id="volleyball-panel-content" style="padding: 20px;">
                    <!-- CREATE VOLLEYBALL COURT -->
                    <div style="margin-bottom: 15px; text-align: center;">
                        <button id="create-volleyball-court-btn" style="
                            width: 100%;
                            padding: 12px;
                            background: linear-gradient(135deg, #FF8C69, #FFE4B5);
                            color: white;
                            border: none;
                            border-radius: 8px;
                            cursor: pointer;
                            font-size: 14px;
                            font-weight: bold;
                            margin-bottom: 10px;
                            box-shadow: 0 4px 15px rgba(255,140,105,0.3);
                        ">🏐 Create FIVB Volleyball Court</button>
                    </div>

                    <!-- LAUNCH VOLLEYBALL ENGINE -->
                    <div style="margin-bottom: 15px; text-align: center;">
                        <button id="toggle-volleyball-physics" style="
                            width: 100%;
                            padding: 12px;
                            background: linear-gradient(135deg, #FFFFE0, #FFD700);
                            color: #333;
                            border: none;
                            border-radius: 8px;
                            cursor: pointer;
                            font-size: 14px;
                            font-weight: bold;
                        ">🚀 Launch Volleyball Engine</button>
                    </div>

                    <!-- VOLLEYBALL ACTIONS -->
                    <div style="display: flex; gap: 8px; margin-bottom: 15px;">
                        <button id="add-volleyball-btn" style="
                            flex: 1;
                            padding: 8px;
                            background: linear-gradient(135deg, #FFFFE0, #FFD700);
                            color: #333;
                            border: none;
                            border-radius: 6px;
                            cursor: pointer;
                            font-size: 12px;
                            font-weight: bold;
                        ">🏐 Add Ball</button>
                        <button id="spike-ball-btn" style="
                            flex: 1;
                            padding: 8px;
                            background: linear-gradient(135deg, #FF6347, #FF4500);
                            color: white;
                            border: none;
                            border-radius: 6px;
                            cursor: pointer;
                            font-size: 12px;
                            font-weight: bold;
                        ">💥 Spike</button>
                        <button id="serve-volleyball-btn" style="
                            flex: 1;
                            padding: 8px;
                            background: linear-gradient(135deg, #32CD32, #228B22);
                            color: white;
                            border: none;
                            border-radius: 6px;
                            cursor: pointer;
                            font-size: 12px;
                            font-weight: bold;
                        ">🏆 Serve</button>
                    </div>

                    <!-- NET HEIGHT SELECTION -->
                    <div style="margin-bottom: 15px;">
                        <label style="display: block; margin-bottom: 5px; font-size: 12px; color: #FFE4B5;">
                            📏 Net Height:
                        </label>
                        <select id="net-height" style="
                            width: 100%;
                            padding: 8px;
                            border: 1px solid #FF8C69;
                            border-radius: 6px;
                            background: #4a3a1a;
                            color: white;
                            font-size: 12px;
                        ">
                            <option value="male">👨 Male (2.43m)</option>
                            <option value="female">👩 Female (2.24m)</option>
                        </select>
                    </div>

                    <!-- ACTION BUTTONS -->
                    <div style="display: flex; gap: 8px; margin-bottom: 15px;">
                        <button id="reset-volleyball-btn" style="
                            flex: 1;
                            padding: 8px;
                            background: linear-gradient(135deg, #74b9ff, #0984e3);
                            color: white;
                            border: none;
                            border-radius: 6px;
                            cursor: pointer;
                            font-weight: bold;
                            font-size: 11px;
                        ">🔄 Reset</button>
                        <button id="stop-volleyball-court-btn" style="
                            flex: 1;
                            padding: 8px;
                            background: linear-gradient(135deg, #e74c3c, #c0392b);
                            color: white;
                            border: none;
                            border-radius: 6px;
                            cursor: pointer;
                            font-weight: bold;
                            font-size: 11px;
                        ">⛔ Stop Court</button>
                    </div>

                    <!-- VOLLEYBALL MODES -->
                    <div style="margin-bottom: 15px;">
                        <h4 style="margin: 0 0 10px 0; font-size: 13px; color: #FFE4B5; text-align: center;">🌟 Volleyball Modes</h4>
                        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;">
                            <button id="volleyball-match-toggle" class="volleyball-mode-toggle" style="
                                                                padding: 8px;
                                background: linear-gradient(135deg, #444, #666);
                                color: white;
                                border: none;
                                border-radius: 6px;
                                cursor: pointer;
                                font-size: 10px;
                                font-weight: bold;
                            ">🏆 Match Mode</button>
                            <button id="clean-volleyball-canvas-btn" style="
                                padding: 8px;
                                background: linear-gradient(135deg, #e17055, #d63031);
                                color: white;
                                border: none;
                                border-radius: 6px;
                                cursor: pointer;
                                font-size: 10px;
                                font-weight: bold;
                            ">🧹 Clean Court</button>
                        </div>
                    </div>

                    <!-- CLEAR ALL -->
                    <div style="margin-bottom: 15px;">
                        <button id="clear-volleyballs-btn" style="
                            width: 100%;
                            padding: 10px;
                            background: linear-gradient(135deg, #990000, #cc0000);
                            color: white;
                            border: none;
                            border-radius: 8px;
                            cursor: pointer;
                            font-weight: bold;
                        ">🗑️ Clear All Volleyballs</button>
                    </div>

                    <!-- VOLLEYBALL SCOREBOARD -->
                    <div id="volleyball-scoreboard" style="
                        display: none;
                        background: rgba(0,0,0,0.4);
                        padding: 15px;
                        border-radius: 8px;
                        text-align: center;
                        margin-bottom: 15px;
                        border: 2px solid #FFD700;
                    ">
                        <h4 style="margin: 0 0 10px 0; color: #FFD700; font-size: 14px;">🏐 FIVB SCOREBOARD</h4>
                        <div style="display: flex; justify-content: space-between; font-size: 14px; font-weight: bold; margin-bottom: 10px;">
                            <div style="color: #ff6b6b;">
                                Team A: <span id="volleyball-score-a">0</span>
                                <br><small>Sets: <span id="volleyball-sets-a">0</span></small>
                            </div>
                            <div style="color: #FFD700; font-size: 12px;">
                                Set: <span id="current-set">1</span>
                                <br>Serving: <span id="serving-team">A</span>
                            </div>
                            <div style="color: #74b9ff;">
                                Team B: <span id="volleyball-score-b">0</span>
                                <br><small>Sets: <span id="volleyball-sets-b">0</span></small>
                            </div>
                        </div>
                        <div style="display: flex; justify-content: space-between; font-size: 11px; color: #FFFFE0;">
                            <div>Touches A: <span id="touches-a">0</span>/3</div>
                            <div style="color: #FF6347;">Rally: <span id="rally-count">0</span></div>
                            <div>Touches B: <span id="touches-b">0</span>/3</div>
                        </div>
                    </div>

                    <!-- VOLLEYBALL STATS -->
                    <div id="volleyball-stats" style="
                        background: rgba(0,0,0,0.3);
                        padding: 10px;
                        border-radius: 6px;
                        font-size: 10px;
                        text-align: center;
                        border: 1px solid rgba(255,140,105,0.3);
                    ">
                        <div>Volleyballs: <span id="volleyball-count">0</span> | Spikes: <span id="spikes-count">0</span></div>
                        <div>Blocks: <span id="blocks-count">0</span> | Aces: <span id="volleyball-aces-count">0</span></div>
                        <div>Max Speed: <span id="volleyball-max-speed">0</span> km/h</div>
                        <div>Net: <span id="net-height-info">Male (2.43m)</span></div>
                    </div>

                    <!-- HELP TEXT -->
                    <div style="
                        text-align: center;
                        margin-top: 15px;
                        font-size: 9px;
                        color: rgba(255,255,255,0.6);
                        border-top: 1px solid rgba(255,255,255,0.1);
                        padding-top: 10px;
                    ">
                        Professional FIVB Court • Volleyball Physics<br>
                        <span style="color: #FFFFE0;">3-touch system • Net collision • Spike mechanics</span>
                    </div>
                </div>
            `;

            document.body.appendChild(panel);

            this.makeVolleyballPanelDraggable();
            this.setupVolleyballPanelButtons();
            this.setupVolleyballEventListeners();
            this.startVolleyballStatsMonitoring();
        }

        setupVolleyballEventListeners() {
            // Volleyball court controls
            document.getElementById('create-volleyball-court-btn')?.addEventListener('click', () => drawCompleteVolleyballCourt());
            document.getElementById('toggle-volleyball-physics')?.addEventListener('click', () => this.toggleVolleyballPhysics());
            document.getElementById('stop-volleyball-court-btn')?.addEventListener('click', () => this.stopVolleyballCourtDrawing());

            // Volleyball creation and actions
            document.getElementById('add-volleyball-btn')?.addEventListener('click', () => this.addRandomVolleyball());
            document.getElementById('spike-ball-btn')?.addEventListener('click', () => this.spikeVolleyball());
            document.getElementById('serve-volleyball-btn')?.addEventListener('click', () => this.serveVolleyball());

            // Actions
            document.getElementById('reset-volleyball-btn')?.addEventListener('click', () => this.resetAllVolleyballs());
            document.getElementById('clear-volleyballs-btn')?.addEventListener('click', () => this.clearAllVolleyballs());
            document.getElementById('volleyball-match-toggle')?.addEventListener('click', () => this.toggleVolleyballMatch());
            document.getElementById('clean-volleyball-canvas-btn')?.addEventListener('click', () => this.cleanVolleyballCourt());

            // Net height selection
            document.getElementById('net-height')?.addEventListener('change', (e) => {
                this.updateNetHeight(e.target.value);
                this.showVolleyballFeedback(`📏 Net Height: ${e.target.options[e.target.selectedIndex].text}`, '#FFE4B5');
            });

            // Canvas click for volleyball
            if (this.canvasElement) {
                this.canvasElement.addEventListener('click', (e) => this.createVolleyball(e.clientX - this.canvasElement.getBoundingClientRect().left, e.clientY - this.canvasElement.getBoundingClientRect().top));
            }
        }

        stopVolleyballCourtDrawing() {
            isStopped = true;
            const statusDiv = document.getElementById('volleyball-status');
            if (statusDiv) {
                updateStatus(statusDiv, "⛔ Dibujo de cancha detenido", "#B22222");
            }
            this.showVolleyballFeedback('⛔ Volleyball court drawing stopped', '#B22222');
        }

        /* ---------- VOLLEYBALL PHYSICS ENGINE ---------- */
        toggleVolleyballPhysics() {
            const toggleBtn = document.getElementById('toggle-volleyball-physics');
            if (!this.isActive) {
                this.startVolleyballPhysics();
                if (toggleBtn) {
                    toggleBtn.textContent = '🛑 Stop Volleyball Engine';
                    toggleBtn.style.background = 'linear-gradient(135deg, #f56565, #e53e3e)';
                    toggleBtn.style.color = 'white';
                }
            } else {
                this.stopVolleyballPhysics();
                if (toggleBtn) {
                    toggleBtn.textContent = '🚀 Launch Volleyball Engine';
                    toggleBtn.style.background = 'linear-gradient(135deg, #FFFFE0, #FFD700)';
                    toggleBtn.style.color = '#333';
                }
            }
        }

        startVolleyballPhysics() {
            if (this.isActive) return;
            this.isActive = true;
            this.startVolleyballGameLoop();
            this.showVolleyballFeedback('🚀 FIVB Volleyball Engine Started!', '#FFD700');
        }

        stopVolleyballPhysics() {
            this.isActive = false;
            this.showVolleyballFeedback('🛑 Volleyball Engine Stopped', '#f56565');
        }

        startVolleyballGameLoop() {
            if (!this.isActive) return;
            const currentTime = performance.now();
            if (currentTime - this.lastRenderTime >= this.renderInterval) {
                this.updateVolleyballPhysics();
                this.renderVolleyballs();
                this.lastRenderTime = currentTime;
            }
            requestAnimationFrame(() => this.startVolleyballGameLoop());
        }

        updateVolleyballPhysics() {
            const dt = VOLLEYBALL_PHYSICS.TIMESTEP;

            // Update volleyballs with specific physics[1][2]
            this.physicsObjects.forEach(ball => {
                if (ball.type !== 'volleyball') return;

                // Apply air resistance (more pronounced for volleyball float)
                ball.vx *= (1 - VOLLEYBALL_PHYSICS.AIR_RESISTANCE * dt);
                ball.vy *= (1 - VOLLEYBALL_PHYSICS.AIR_RESISTANCE * dt);

                // Apply gravity (reduced for longer rallies)
                ball.vy += VOLLEYBALL_PHYSICS.GRAVITY * dt;

                // Apply volleyball float effect
                if (Math.abs(ball.vx) < 50 && Math.abs(ball.vy) < 100) {
                    // Pelota "flotando" - pequeñas turbulencias
                    ball.vx += (Math.random() - 0.5) * 10;
                    ball.vy += (Math.random() - 0.5) * 5;
                }

                // Update position
                ball.x += ball.vx * dt;
                ball.y += ball.vy * dt;

                this.handleVolleyballBoundaryCollisions(ball);
                this.handleVolleyballNetCollision(ball);

                // Velocity tracking for stats
                const speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
                if (speed > this.gameStats.maxVelocityReached) {
                    this.gameStats.maxVelocityReached = speed;
                }

                if (speed > VOLLEYBALL_PHYSICS.MAX_VELOCITY) {
                    ball.vx = (ball.vx / speed) * VOLLEYBALL_PHYSICS.MAX_VELOCITY;
                    ball.vy = (ball.vy / speed) * VOLLEYBALL_PHYSICS.MAX_VELOCITY;
                }
            });

            this.handleVolleyballCollisions();
            this.handleVolleyballPlayerActions();

            if (this.volleyballGame.active) {
                this.checkVolleyballScoring();
            }
        }

        updateNetHeight(heightType) {
            this.controls.netHeight = heightType;
            this.volleyballGame.netHeight = heightType === 'male' ?
                VOLLEYBALL_PHYSICS.NET_HEIGHT_MALE :
                VOLLEYBALL_PHYSICS.NET_HEIGHT_FEMALE;

            const heightText = heightType === 'male' ? 'Male (2.43m)' : 'Female (2.24m)';
            document.getElementById('net-height-info').textContent = heightText;
        }

        /* ---------- VOLLEYBALL CREATION ---------- */
        addRandomVolleyball() {
            if (!this.canvasElement) return;

            const coords = calculateVolleyballCoordinates();

            // Spawn en el centro de uno de los lados
            const side = Math.random() > 0.5 ? 'left' : 'right';
            const x = side === 'left' ?
                coords.zones.leftSide.x + coords.zones.leftSide.width * 0.5 :
                coords.zones.rightSide.x + coords.zones.rightSide.width * 0.5;
            const y = coords.court.y + coords.court.height * 0.7;

            this.createVolleyball(x, y);
        }

        spikeVolleyball() {
            if (!this.canvasElement) return;

            const coords = calculateVolleyballCoordinates();

            // Spike desde zona de ataque
            const x = coords.attackLines.left.x + 50;
            const y = coords.court.y + 30;

            const ball = this.createVolleyball(x, y);

            // Aplicar fuerza de spike (hacia abajo y hacia adelante)
            ball.vx = VOLLEYBALL_PHYSICS.SPIKE_FORCE * 0.8;
            ball.vy = VOLLEYBALL_PHYSICS.SPIKE_FORCE * 0.6;

            this.gameStats.totalSpikes++;
            this.showVolleyballFeedback('💥 SPIKE ATTACK!', '#FF6347');
        }

        serveVolleyball() {
            if (!this.canvasElement) return;

            const coords = calculateVolleyballCoordinates();

            // Serve desde área de saque
            const isTeamA = this.volleyballGame.serving === 'a';
            const serveArea = isTeamA ? coords.serveAreas.leftServe : coords.serveAreas.rightServe;

            const ball = this.createVolleyball(
                serveArea.x + serveArea.width / 2,
                serveArea.y + serveArea.height / 2
            );

            // Aplicar fuerza de saque
            const direction = isTeamA ? 1 : -1;
            ball.vx = VOLLEYBALL_PHYSICS.SERVE_FORCE * direction * 0.7;
            ball.vy = -VOLLEYBALL_PHYSICS.SERVE_FORCE * 0.5; // Hacia arriba y adelante

            this.showVolleyballFeedback(`🏐 TEAM ${this.volleyballGame.serving.toUpperCase()} SERVES!`, '#32CD32');
        }

        createVolleyball(x, y) {
            const id = `volleyball_${this.objectIdCounter++}`;
            const ball = {
                id: id,
                type: 'volleyball',
                x: x, y: y, vx: 0, vy: 0,
                radius: VOLLEYBALL_PHYSICS.BALL_RADIUS,
                color: VOLLEYBALL_PHYSICS.BALL_COLOR,
                mass: VOLLEYBALL_PHYSICS.BALL_MASS,
                restitution: VOLLEYBALL_PHYSICS.RESTITUTION_BALL,
                friction: VOLLEYBALL_PHYSICS.FRICTION_COURT,
                lastRenderX: -9999, lastRenderY: -9999,
                creationTime: performance.now(),
                lastCollisionTime: 0,

                // Volleyball specific properties
                lastTouchTime: 0,
                lastTouchTeam: null,
                bounceCount: 0,
                isInPlay: true,
                sideOfCourt: null, // 'left' or 'right'
                floatEffect: Math.random() * 0.1
            };

            this.physicsObjects.set(id, ball);
            this.gameStats.ballsCreated++;
            return ball;
        }

        /* ---------- VOLLEYBALL COLLISION HANDLING ---------- */
        handleVolleyballBoundaryCollisions(ball) {
            if (!this.canvasElement) return;

            const coords = calculateVolleyballCoordinates();
            const ballHalfSize = ball.radius;

            // Límites de la cancha oficial (18m x 9m)[1][2]
            const boundaries = {
                left: coords.court.x + ballHalfSize,
                right: coords.court.x + coords.court.width - ballHalfSize,
                top: coords.court.y + ballHalfSize,
                bottom: coords.court.y + coords.court.height - ballHalfSize
            };

            // Colisiones laterales (fuera de bounds)
            if (ball.x < boundaries.left || ball.x > boundaries.right) {
                ball.x = ball.x < boundaries.left ? boundaries.left : boundaries.right;
                ball.vx = -ball.vx * VOLLEYBALL_PHYSICS.RESTITUTION_FLOOR;
                ball.isInPlay = false; // Fuera de la cancha

                if (this.volleyballGame.active) {
                    this.handleVolleyballOut(ball);
                }
            }

            // Colisión con el techo (rebote suave)
            if (ball.y < boundaries.top) {
                ball.y = boundaries.top;
                ball.vy = -ball.vy * 0.3; // Rebote muy suave en el techo
            }

            // Colisión con el piso (rebote alto característico de volleyball)
            if (ball.y > boundaries.bottom) {
                ball.y = boundaries.bottom;
                ball.vy = -ball.vy * ball.restitution;
                ball.vx *= ball.friction;

                ball.bounceCount++;

                // Determinar lado de la cancha
                ball.sideOfCourt = ball.x < coords.net.x ? 'left' : 'right';

                if (this.volleyballGame.active) {
                    this.checkVolleyballBounce(ball);
                }
            }
        }

        handleVolleyballNetCollision(ball) {
            const coords = calculateVolleyballCoordinates();
            const netX = coords.net.x;
            const netTop = coords.net.y1;
            const netBottom = coords.net.y2;
            const netHeight = this.volleyballGame.netHeight;

            // Verificar colisión con la red (área vertical)[3]
            if (Math.abs(ball.x - netX) < ball.radius + coords.net.width/2 &&
                ball.y > netTop && ball.y < netBottom &&
                ball.y > netBottom - netHeight) {

                // La pelota golpea la red
                ball.vx = -ball.vx * VOLLEYBALL_PHYSICS.RESTITUTION_NET;
                ball.vy *= 0.3; // Pierde mucha velocidad vertical

                // Posicionar fuera de la red
                if (ball.x < netX) {
                    ball.x = netX - ball.radius - coords.net.width/2;
                } else {
                    ball.x = netX + ball.radius + coords.net.width/2;
                }

                this.showVolleyballFeedback('🕸️ NET VIOLATION!', '#ff4757');

                if (this.volleyballGame.active) {
                    this.handleNetViolation(ball);
                }
            }
        }

        handleVolleyballCollisions() {
            const ballsArray = Array.from(this.physicsObjects.values()).filter(obj => obj.type === 'volleyball');

            for (let i = 0; i < ballsArray.length; i++) {
                const ballA = ballsArray[i];
                for (let j = i + 1; j < ballsArray.length; j++) {
                    const ballB = ballsArray[j];

                    const dx = ballB.x - ballA.x;
                    const dy = ballB.y - ballA.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const minDistance = ballA.radius + ballB.radius;

                    if (distance < minDistance && distance !== 0) {
                        // Separar pelotas
                        const normalX = dx / distance;
                        const normalY = dy / distance;
                        const overlap = minDistance - distance;

                        ballA.x -= normalX * overlap * 0.5;
                        ballA.y -= normalY * overlap * 0.5;
                        ballB.x += normalX * overlap * 0.5;
                        ballB.y += normalY * overlap * 0.5;

                        // Rebote elástico suave (característico de volleyball)
                        const tempVx = ballA.vx;
                        const tempVy = ballA.vy;
                        ballA.vx = ballB.vx * 0.95;
                        ballA.vy = ballB.vy * 0.95;
                        ballB.vx = tempVx * 0.95;
                        ballB.vy = tempVy * 0.95;
                    }
                }
            }
        }

        /* ---------- SISTEMA DE TOQUES DE VOLLEYBALL ---------- */
        handleVolleyballPlayerActions() {
            const players = this.getVolleyballPlayerPositions();
            if (players.length === 0) return;

            this.physicsObjects.forEach(ball => {
                if (ball.type !== 'volleyball') return;

                players.forEach(player => {
                    const dx = ball.x - player.x;
                    const dy = ball.y - player.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const reachDistance = 50; // Alcance para tocar el volleyball

                    if (distance < reachDistance && distance > 0) {
                        const currentTime = performance.now();

                        if (currentTime - ball.lastTouchTime > this.touchSystem.touchCooldown) {
                            this.executeVolleyballTouch(ball, player, dx, dy, distance);
                            ball.lastTouchTime = currentTime;
                        }
                    }
                });
            });
        }

        executeVolleyballTouch(ball, player, dx, dy, distance) {
            const coords = calculateVolleyballCoordinates();

            // Determinar equipo basado en posición del jugador
            const playerTeam = player.x < coords.net.x ? 'left' : 'right';
            const teamKey = playerTeam === 'left' ? 'a' : 'b';

            // Verificar límite de toques por equipo[4][5]
            if (ball.lastTouchTeam !== teamKey) {
                // Nuevo equipo toca la pelota - resetear contador
                this.touchSystem.teamTouches.a = 0;
                this.touchSystem.teamTouches.b = 0;
                this.touchSystem.teamTouches[teamKey] = 1;
                ball.lastTouchTeam = teamKey;
            } else {
                // Mismo equipo - incrementar contador
                this.touchSystem.teamTouches[teamKey]++;

                if (this.touchSystem.teamTouches[teamKey] > this.touchSystem.maxTouches) {
                    this.handleTouchViolation(ball, teamKey);
                    return;
                }
            }

            // Ejecutar el toque
            const normalX = dx / distance;
            const normalY = dy / distance;

            // Tipo de toque basado en posición
            const touchType = this.determineVolleyballTouchType(ball, player, coords);
            const force = this.getVolleyballTouchForce(touchType);

            // Aplicar fuerza del toque
            ball.vx += normalX * force * VOLLEYBALL_PHYSICS.TIMESTEP * 2;
            ball.vy += normalY * force * VOLLEYBALL_PHYSICS.TIMESTEP * 2;

            // Aplicar velocidad del jugador
            if (player.vx || player.vy) {
                ball.vx += (player.vx || 0) * 0.6;
                ball.vy += (player.vy || 0) * 0.6;
            }

            // Mostrar feedback del toque
            this.showVolleyballTouchFeedback(touchType, teamKey, this.touchSystem.teamTouches[teamKey]);

            // Actualizar UI de toques
            this.updateTouchDisplay();
        }

        determineVolleyballTouchType(ball, player, coords) {
            const playerHeight = player.y;
            const ballHeight = ball.y;
            const netY = coords.net.y1;

            // Determinar tipo de acción basado en posición
            if (ballHeight < netY + 30 && playerHeight < netY + 40) {
                return 'spike'; // Remate
            } else if (ballHeight > netY + 60) {
                return 'dig'; // Defensa baja
            } else if (Math.abs(ball.vy) < 50) {
                return 'set'; // Colocación
            } else {
                return 'pass'; // Pase normal
            }
        }

        getVolleyballTouchForce(touchType) {
            switch (touchType) {
                case 'spike': return VOLLEYBALL_PHYSICS.SPIKE_FORCE;
                case 'set': return VOLLEYBALL_PHYSICS.SET_FORCE;
                case 'dig': return VOLLEYBALL_PHYSICS.PLAYER_INTERACTION_FORCE * 0.6;
                case 'pass':
                default: return VOLLEYBALL_PHYSICS.PLAYER_INTERACTION_FORCE;
            }
        }

        showVolleyballTouchFeedback(touchType, team, touchCount) {
            const actionNames = {
                'spike': '💥 SPIKE',
                'set': '🙌 SET',
                'dig': '🤲 DIG',
                'pass': '🏐 PASS'
            };

            const teamName = team.toUpperCase();
            const actionName = actionNames[touchType] || '🏐 TOUCH';

            this.showVolleyballFeedback(`${actionName} - Team ${teamName} (${touchCount}/3)`, '#FFD700');

            // Actualizar estadísticas
            if (touchType === 'spike') {
                this.gameStats.totalSpikes++;
            }
        }

        handleTouchViolation(ball, team) {
            ball.isInPlay = false;

            // El equipo contrario obtiene el punto
            const oppositeTeam = team === 'a' ? 'b' : 'a';
            this.volleyballGame.points[oppositeTeam]++;

            this.showVolleyballFeedback(`❌ 4-TOUCH VIOLATION! Point to Team ${oppositeTeam.toUpperCase()}`, '#ff4757');

            this.updateVolleyballScore();
            this.resetTouchCounts();

            setTimeout(() => {
                this.clearAllVolleyballs(false);
                if (this.volleyballGame.active) {
                    this.serveVolleyball();
                }
            }, 2000);
        }

        updateTouchDisplay() {
            document.getElementById('touches-a').textContent = this.touchSystem.teamTouches.a || 0;
            document.getElementById('touches-b').textContent = this.touchSystem.teamTouches.b || 0;
        }

        resetTouchCounts() {
            this.touchSystem.teamTouches = { a: 0, b: 0 };
            this.updateTouchDisplay();
        }

        getVolleyballPlayerPositions() {
            const players = [];
            if (!drawariaCanvas) return players;

            const canvasRect = drawariaCanvas.getBoundingClientRect();

            // Self player
            const selfPlayer = document.querySelector('div.spawnedavatar.spawnedavatar-self');
            if (selfPlayer) {
                const rect = selfPlayer.getBoundingClientRect();
                players.push({
                    type: 'self',
                    id: 'self',
                    x: rect.left - canvasRect.left + rect.width / 2,
                    y: rect.top - canvasRect.top + rect.height / 2,
                    radius: Math.max(rect.width, rect.height) / 2,
                    vx: 0, vy: 0
                });
            }

            // Other players
            const otherPlayers = document.querySelectorAll('div.spawnedavatar.spawnedavatar-otherplayer');
            otherPlayers.forEach((player, index) => {
                const rect = player.getBoundingClientRect();
                players.push({
                    type: 'other',
                    id: `other_${index}`,
                    x: rect.left - canvasRect.left + rect.width / 2,
                    y: rect.top - canvasRect.top + rect.height / 2,
                    radius: Math.max(rect.width, rect.height) / 2,
                    vx: 0, vy: 0
                });
            });

            return players;
        }

        /* ---------- VOLLEYBALL SCORING SYSTEM ---------- */
        checkVolleyballScoring() {
            if (!this.volleyballGame.active) return;

            this.physicsObjects.forEach(ball => {
                if (ball.type !== 'volleyball' || !ball.isInPlay) return;

                // Verificar si la pelota tocó el piso dentro de la cancha
                if (ball.bounceCount > 0 && ball.sideOfCourt) {
                    this.scoreVolleyballPoint(ball);
                }
            });
        }

        checkVolleyballBounce(ball) {
            const coords = calculateVolleyballCoordinates();

            // Verificar en qué lado de la cancha rebotó
            if (ball.x >= coords.court.x && ball.x <= coords.court.x + coords.court.width) {
                // Rebotó dentro de la cancha - punto para el equipo contrario
                const scoringTeam = ball.sideOfCourt === 'left' ? 'b' : 'a';
                this.volleyballGame.points[scoringTeam]++;

                this.showVolleyballFeedback(`🏐 POINT! Team ${scoringTeam.toUpperCase()} scores!`, '#32CD32');
                this.updateVolleyballScore();
                this.endCurrentRally();
            }
        }

        handleVolleyballOut(ball) {
            // Pelota salió fuera - punto para el equipo que NO tocó último
            const scoringTeam = ball.lastTouchTeam === 'a' ? 'b' : 'a';
            this.volleyballGame.points[scoringTeam]++;

            this.showVolleyballFeedback(`📍 OUT! Point to Team ${scoringTeam.toUpperCase()}`, '#FFA500');
            this.updateVolleyballScore();
            this.endCurrentRally();
        }

        handleNetViolation(ball) {
            // Violación de red - punto para el equipo contrario
            const scoringTeam = ball.lastTouchTeam === 'a' ? 'b' : 'a';
            this.volleyballGame.points[scoringTeam]++;

            this.showVolleyballFeedback(`🕸️ NET VIOLATION! Point to Team ${scoringTeam.toUpperCase()}`, '#ff4757');
            this.updateVolleyballScore();
            this.endCurrentRally();
        }

        async scoreVolleyballPoint(ball) {
            ball.isInPlay = false;
            this.endCurrentRally();
        }

        endCurrentRally() {
            this.gameStats.ralliesPlayed++;
            this.resetTouchCounts();

            setTimeout(() => {
                this.clearAllVolleyballs(false);
                if (this.volleyballGame.active) {
                    this.checkSetWon();
                    this.serveVolleyball();
                }
            }, 2000);
        }

        /* ---------- VOLLEYBALL MATCH MODE ---------- */
        toggleVolleyballMatch() {
            const button = document.getElementById('volleyball-match-toggle');
            const scoreboard = document.getElementById('volleyball-scoreboard');

            this.volleyballGame.active = !this.volleyballGame.active;

            if (this.volleyballGame.active) {
                button.style.background = 'linear-gradient(135deg, #FFD700, #FFA500)';
                button.setAttribute('data-active', 'true');
                scoreboard.style.display = 'block';
                this.setupVolleyballMatch();
                this.showVolleyballFeedback('🏆 FIVB MATCH MODE ACTIVATED!', '#FFD700');
            } else {
                button.style.background = 'linear-gradient(135deg, #444, #666)';
                button.removeAttribute('data-active');
                scoreboard.style.display = 'none';
                this.resetVolleyballMatch();
                this.showVolleyballFeedback('🏆 Match Mode Deactivated', '#666');
            }
        }

        async setupVolleyballMatch() {
            await drawCompleteVolleyballCourt();
            this.resetVolleyballGameScores();
            await this.updateVolleyballScore();

            setTimeout(() => {
                this.serveVolleyball();
            }, 2000);
        }

        resetVolleyballGameScores() {
            this.volleyballGame = {
                active: true,
                sets: { a: 0, b: 0 },
                points: { a: 0, b: 0 },
                serving: 'a',
                netHeight: this.controls.netHeight === 'male' ?
                    VOLLEYBALL_PHYSICS.NET_HEIGHT_MALE :
                    VOLLEYBALL_PHYSICS.NET_HEIGHT_FEMALE,
                currentSet: 1
            };
            this.resetTouchCounts();
        }

        async updateVolleyballScore() {
            document.getElementById('volleyball-score-a').textContent = this.volleyballGame.points.a;
            document.getElementById('volleyball-score-b').textContent = this.volleyballGame.points.b;
            document.getElementById('volleyball-sets-a').textContent = this.volleyballGame.sets.a;
            document.getElementById('volleyball-sets-b').textContent = this.volleyballGame.sets.b;
            document.getElementById('current-set').textContent = this.volleyballGame.currentSet;
            document.getElementById('serving-team').textContent = this.volleyballGame.serving.toUpperCase();
            document.getElementById('rally-count').textContent = this.gameStats.ralliesPlayed;
        }

        checkSetWon() {
            const pointsA = this.volleyballGame.points.a;
            const pointsB = this.volleyballGame.points.b;

            // Verificar si alguien ganó el set (25 puntos + 2 de diferencia)[4][5]
            if ((pointsA >= VOLLEYBALL_GAME.POINTS_TO_WIN && pointsA - pointsB >= VOLLEYBALL_GAME.MIN_POINT_DIFFERENCE) ||
                (pointsB >= VOLLEYBALL_GAME.POINTS_TO_WIN && pointsB - pointsA >= VOLLEYBALL_GAME.MIN_POINT_DIFFERENCE)) {

                // Determinar ganador del set
                const setWinner = pointsA > pointsB ? 'a' : 'b';
                this.volleyballGame.sets[setWinner]++;

                this.showVolleyballFeedback(`🏐 SET ${this.volleyballGame.currentSet} WON BY TEAM ${setWinner.toUpperCase()}!`, '#FFD700');

                // Verificar si alguien ganó el match (mejor de 5 sets)
                if (this.volleyballGame.sets[setWinner] >= VOLLEYBALL_GAME.SETS_TO_WIN) {
                    this.endVolleyballMatch(setWinner);
                } else {
                    this.startNewSet();
                }
            }
        }

        startNewSet() {
            this.volleyballGame.currentSet++;
            this.volleyballGame.points = { a: 0, b: 0 };

            // Alternar saque
            this.volleyballGame.serving = this.volleyballGame.serving === 'a' ? 'b' : 'a';

            this.showVolleyballFeedback(`🏐 SET ${this.volleyballGame.currentSet} BEGINS!`, '#87CEEB');
            this.updateVolleyballScore();
        }

        async endVolleyballMatch(winner) {
            const finalSets = `${this.volleyballGame.sets.a}-${this.volleyballGame.sets.b}`;
            this.showVolleyballFeedback(`🏆 TEAM ${winner.toUpperCase()} WINS THE MATCH ${finalSets}!`, '#FFD700');

            setTimeout(() => {
                this.resetVolleyballMatch();
            }, 5000);
        }

        resetVolleyballMatch() {
            this.resetVolleyballGameScores();
            if (this.volleyballGame.active) {
                this.clearAllVolleyballs(false);
                setTimeout(() => {
                    drawCompleteVolleyballCourt().then(() => {
                        this.serveVolleyball();
                    });
                }, 500);
            }
        }

        /* ---------- RENDERING ---------- */
        renderVolleyballs() {
            this.physicsObjects.forEach(obj => {
                if (obj.type !== 'volleyball') return;

                const dx = Math.abs(obj.x - obj.lastRenderX);
                const dy = Math.abs(obj.y - obj.lastRenderY);

                const needsServerRedraw = dx > MOVEMENT_THRESHOLD || dy > MOVEMENT_THRESHOLD;

                if (needsServerRedraw) {
                    // Borrar posición anterior
                    if (obj.lastRenderX !== -9999 || obj.lastRenderY !== -9999) {
                        this.drawVolleyball(obj.lastRenderX, obj.lastRenderY, obj.radius, '#FFFFFF');
                    }

                    // Dibujar en nueva posición
                    this.drawVolleyball(obj.x, obj.y, obj.radius, obj.color);

                    obj.lastRenderX = obj.x;
                    obj.lastRenderY = obj.y;
                }
            });
        }

        drawVolleyball(x, y, radius, color) {
            const effectiveThickness = radius * 2.3; // Tamaño medio de volleyball
            enqueueDrawCommand(x, y, x + 0.1, y + 0.1, color, effectiveThickness);
        }

        /* ---------- UTILITY FUNCTIONS ---------- */
        clearAllVolleyballs(showFeedback = true) {
            this.physicsObjects.clear();
            positionCache.clear();
            this.resetTouchCounts();

            if (drawariaCtx && drawariaCanvas) {
                drawariaCtx.clearRect(0, 0, drawariaCanvas.width, drawariaCanvas.height);
            }
            if (showFeedback) {
                this.showVolleyballFeedback('🗑️ ALL VOLLEYBALLS CLEARED!', '#cc0000');
            }
        }

        resetAllVolleyballs() {
            if (this.canvasElement) {
                const coords = calculateVolleyballCoordinates();

                this.physicsObjects.forEach(obj => {
                    obj.x = coords.net.x + (Math.random() - 0.5) * 100;
                    obj.y = coords.court.y + coords.court.height * 0.5;
                    obj.vx = 0; obj.vy = 0;
                    obj.lastRenderX = -9999; obj.lastRenderY = -9999;
                    obj.bounceCount = 0;
                    obj.isInPlay = true;
                    obj.sideOfCourt = null;
                    obj.lastTouchTeam = null;
                });

                this.resetTouchCounts();
                this.showVolleyballFeedback('🔄 All volleyballs reset to center court!', '#74b9ff');
            }
        }

        async cleanVolleyballCourt() {
            if (!drawariaCanvas) return;

            this.showVolleyballFeedback('🧹 Cleaning FIVB Court...', '#e17055');

            const canvasWidth = drawariaCanvas.width;
            const canvasHeight = drawariaCanvas.height;

            for (let y = 0; y < canvasHeight; y += 60) {
                for (let x = 0; x < canvasWidth; x += 60) {
                    const width = Math.min(60, canvasWidth - x);
                    const height = Math.min(60, canvasHeight - y);
                    enqueueDrawCommand(x, y, x + width, y + height, '#FFFFFF', Math.max(width, height));
                    await sleep(2);
                }
            }

            if (drawariaCtx) {
                drawariaCtx.clearRect(0, 0, canvasWidth, canvasHeight);
            }

            this.showVolleyballFeedback('🧹 FIVB Court Cleaned!', '#00d084');
        }

        /* ---------- PANEL FUNCTIONALITY ---------- */
        makeVolleyballPanelDraggable() {
            const panel = document.getElementById('volleyball-physics-panel');
            const header = document.getElementById('volleyball-panel-header');

            let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;

            if (header) {
                header.onmousedown = dragMouseDown;
            }

            function dragMouseDown(e) {
                e = e || window.event;
                e.preventDefault();
                pos3 = e.clientX;
                pos4 = e.clientY;
                document.onmouseup = closeDragElement;
                document.onmousemove = elementDrag;
            }

            function elementDrag(e) {
                e = e || window.event;
                e.preventDefault();
                pos1 = pos3 - e.clientX;
                pos2 = pos4 - e.clientY;
                pos3 = e.clientX;
                pos4 = e.clientY;

                const newTop = panel.offsetTop - pos2;
                const newLeft = panel.offsetLeft - pos1;

                panel.style.top = Math.max(0, newTop) + "px";
                panel.style.left = Math.max(0, newLeft) + "px";
                panel.style.right = 'auto';
            }

            function closeDragElement() {
                document.onmouseup = null;
                document.onmousemove = null;
            }
        }

        setupVolleyballPanelButtons() {
            const minimizeBtn = document.getElementById('volleyball-minimize-btn');
            const closeBtn = document.getElementById('volleyball-close-btn');
            const content = document.getElementById('volleyball-panel-content');
            const panel = document.getElementById('volleyball-physics-panel');

            let isMinimized = false;

            minimizeBtn?.addEventListener('click', (e) => {
                e.stopPropagation();
                if (!isMinimized) {
                    content.style.display = 'none';
                    minimizeBtn.innerHTML = '+';
                    isMinimized = true;
                } else {
                    content.style.display = 'block';
                    minimizeBtn.innerHTML = '−';
                    isMinimized = false;
                }
            });

            closeBtn?.addEventListener('click', (e) => {
                e.stopPropagation();
                if (confirm('¿Cerrar el motor de volleyball?')) {
                    if (this.isActive) this.stopVolleyballPhysics();
                    isStopped = true;
                    panel.remove();
                    this.showVolleyballFeedback('❌ Volleyball Engine Closed', '#ff4757');
                }
            });
        }

        startVolleyballStatsMonitoring() {
            setInterval(() => {
                document.getElementById('volleyball-count').textContent = this.physicsObjects.size;
                document.getElementById('spikes-count').textContent = this.gameStats.totalSpikes;
                document.getElementById('blocks-count').textContent = this.gameStats.totalBlocks;
                document.getElementById('volleyball-aces-count').textContent = this.gameStats.aces;
                document.getElementById('volleyball-max-speed').textContent = Math.round(this.gameStats.maxVelocityReached * 3.6); // Convert to km/h
            }, 1000);
        }

        showVolleyballFeedback(message, color) {
            const feedback = document.createElement('div');
            feedback.style.cssText = `
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background: ${color};
                color: white;
                padding: 15px 25px;
                border-radius: 10px;
                font-weight: bold;
                z-index: 2147483648;
                font-size: 16px;
                box-shadow: 0 4px 20px rgba(0,0,0,0.3);
                opacity: 0;
                transition: opacity 0.3s ease-in-out;
                text-shadow: 1px 1px 3px rgba(0,0,0,0.5);
                border: 2px solid #FFD700;
            `;
            feedback.innerHTML = message;

            document.body.appendChild(feedback);
            setTimeout(() => feedback.style.opacity = '1', 10);
            setTimeout(() => feedback.style.opacity = '0', 2500);
            setTimeout(() => feedback.remove(), 2800);
        }
    }

    /* ---------- GLOBAL INITIALIZATION ---------- */
    let volleyballEngine = null;

    const initVolleyballEngine = () => {
        if (!volleyballEngine) {
            console.log('🏐 Initializing FIVB Volleyball Physics Engine v1.0...');
            volleyballEngine = new AdvancedDrawariaVolleyball();

            setTimeout(() => {
                const confirmMsg = document.createElement('div');
                confirmMsg.style.cssText = `
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: linear-gradient(45deg, #FF8C69, #FFE4B5);
                    color: white;
                    padding: 25px 35px;
                    border-radius: 20px;
                    font-size: 16px;
                    font-weight: bold;
                    z-index: 2147483648;
                    text-align: center;
                    box-shadow: 0 0 40px rgba(255,140,105,0.6);
                    opacity: 0;
                    transition: opacity 0.3s ease-in-out;
                    border: 3px solid #FFD700;
                `;
                confirmMsg.innerHTML = `
                    🏐 FIVB VOLLEYBALL ENGINE v1.0 LOADED! 🏐<br>
                    <div style="font-size: 12px; margin-top: 10px; color: #FFF8DC;">
                        ✅ Professional FIVB Court • Volleyball Physics • 3-Touch System<br>
                        ✅ Net Collision Detection • Match Mode • Spike/Set/Dig Mechanics<br>
                        ✅ Official Scoring • Rally System • Realistic Ball Physics
                    </div>
                `;

                document.body.appendChild(confirmMsg);
                setTimeout(() => confirmMsg.style.opacity = '1', 10);
                setTimeout(() => confirmMsg.style.opacity = '0', 4000);
                setTimeout(() => confirmMsg.remove(), 4300);
            }, 1000);
        }
    };

    // Enhanced CSS for Volleyball styling
    const volleyballStyle = document.createElement('style');
    volleyballStyle.textContent = `
        @keyframes volleyball-float {
            0% { transform: translateY(0) scale(1); }
            50% { transform: translateY(-8px) scale(1.05); }
            100% { transform: translateY(0) scale(1); }
        }

        @keyframes court-glow {
            0% { box-shadow: 0 0 15px rgba(255, 140, 105, 0.3); }
            50% { box-shadow: 0 0 25px rgba(255, 228, 181, 0.6); }
            100% { box-shadow: 0 0 15px rgba(255, 140, 105, 0.3); }
        }

        .volleyball-mode-toggle[data-active="true"] {
            animation: court-glow 2s infinite;
        }

        #volleyball-physics-panel {
            transition: none !important;
        }

        #volleyball-panel-header:hover {
            background: linear-gradient(45deg, #FF8C69, #FFE4B5) !important;
        }

        /* Volleyball specific styling */
        .fivb-court {
            background: linear-gradient(45deg, #FF8C69, #FFE4B5);
        }

        .volleyball-floating {
            animation: volleyball-float 1.5s infinite ease-in-out;
        }

        /* Spike animation */
        @keyframes volleyball-spike {
            0% { transform: translateY(-10px) scale(1.2); }
            100% { transform: translateY(0) scale(1); }
        }

        .volleyball-spike-effect {
            animation: volleyball-spike 0.3s ease-out;
        }

        /* Net collision effect */
        @keyframes net-collision {
            0% { opacity: 1; }
            50% { opacity: 0.5; transform: scale(1.1); }
            100% { opacity: 1; transform: scale(1); }
        }

        .volleyball-net-hit {
            animation: net-collision 0.4s ease-out;
        }

        /* Status div volleyball styling */
        #volleyball-status {
            font-family: 'Arial Black', Arial, sans-serif !important;
            animation: court-glow 3s infinite;
        }

        /* Volleyball color scheme */
        .volleyball-orange { color: #FF8C69; }
        .volleyball-yellow { color: #FFFFE0; }
        .volleyball-white { color: #FFFFFF; }
        .volleyball-beige { color: #FFE4B5; }
        .volleyball-brown { color: #8B4513; }

        /* Touch counter styling */
        .touch-warning {
            color: #ff4757 !important;
            font-weight: bold !important;
        }

        .touch-normal {
            color: #32CD32 !important;
        }

        /* Rally counter animation */
        @keyframes rally-pulse {
            0%, 100% { transform: scale(1); }
            50% { transform: scale(1.1); }
        }

        .rally-active {
            animation: rally-pulse 1s infinite;
        }
    `;
    document.head.appendChild(volleyballStyle);

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initVolleyballEngine);
    } else {
        initVolleyballEngine();
    }
    setTimeout(initVolleyballEngine, 2000);

    console.log('🏐 Advanced FIVB Volleyball Physics Engine v1.0 loaded successfully! 🏐');
    console.log('🏟️ Features: Professional FIVB Court • 3-Touch System • Net Physics • Rally Scoring');
    console.log('🏆 Ready for FIVB-style volleyball matches in Drawaria!');

})();