Google Classroom Mod Menu

Mod Menu - Chaos Mode, Bouncing DVD, Custom Banner & Renaming.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Google Classroom Mod Menu
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Mod Menu - Chaos Mode, Bouncing DVD, Custom Banner & Renaming.
// @author       MuhammadUthman
// @match        https://classroom.google.com/*
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const state = {
        menuVisible: true,
        bannerType: null,
        bannerSrc: '',
        bannerScale: 1.0,
        bWidth: '100%',
        bHeight: '100%',
        bTop: '0px',
        bLeft: '0px',
        bannerMuted: true,
        spoofName: '',
        dvdEnabled: false,
        dvdMedia: '',
        dvdMediaType: 'image',
        dvdMultiplier: 1,
        dvdSpeed: 3,
        dvdScale: 1.0,
        dvdMuted: true,
        dvdInstances:[],
        fontDistortEnabled: false,
        fontDistortSpeed: 150,
        fontList: 'Comic Sans MS, Impact, Papyrus, Courier New, Times New Roman, Chiller, Brush Script MT, Jokerman, Arial Black, Wingdings',
        chaosEnabled: false
    };

    let isMediaDragging = false;
    let isMediaResizing = false;
    let isScrubbing = false;
    let fontDistortTimer = null;
    let chaosTimer = null;

    // Helper: Formats seconds into MM:SS
    function formatTime(seconds) {
        if (isNaN(seconds)) return "0:00";
        const m = Math.floor(seconds / 60);
        const s = Math.floor(seconds % 60).toString().padStart(2, '0');
        return `${m}:${s}`;
    }

    GM_addStyle(`
        /* Base Mod Menu Styles */
        #gc-mod-menu {
            position: fixed; top: 20px; right: 20px; width: 320px;
            background: #1e1e2e; color: #f8f8f2; border-radius: 12px;
            box-shadow: 0 15px 35px rgba(0,0,0,0.6); z-index: 999999;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            border: 1px solid #44475a; overflow: hidden; transition: opacity 0.3s;
        }
        #gc-mod-header {
            background: #282a36; padding: 12px 15px; cursor: move; font-weight: bold;
            display: flex; justify-content: space-between; align-items: center;
            border-bottom: 2px solid #bd93f9; user-select: none;
        }
        #gc-mod-body {
            padding: 15px; max-height: 500px; overflow-y: auto;
        }
        #gc-mod-body::-webkit-scrollbar { width: 8px; }
        #gc-mod-body::-webkit-scrollbar-thumb { background: #6272a4; border-radius: 4px; }

        .mod-section-title {
            font-size: 14px; color: #8be9fd; text-transform: uppercase;
            margin: 15px 0 10px 0; border-bottom: 1px solid #44475a; padding-bottom: 3px;
        }
        .mod-section-title:first-child { margin-top: 0; }

        .mod-btn {
            background: #44475a; color: #f8f8f2; border: none; border-radius: 6px;
            padding: 8px 12px; margin: 4px 0; width: 100%; cursor: pointer;
            transition: all 0.2s; text-align: left; font-size: 13px;
        }
        .mod-btn:hover { background: #6272a4; }
        .mod-btn.active { background: #50fa7b; color: #282a36; font-weight: bold; }

        .mod-input {
            width: 100%; background: #282a36; color: #f8f8f2;
            border: 1px solid #6272a4; border-radius: 6px; padding: 8px;
            margin-bottom: 8px; font-size: 13px; outline: none; box-sizing: border-box;
        }

        /* Custom Slider Styling */
        input[type="range"].mod-slider {
            -webkit-appearance: none; width: 100%; background: transparent; margin: 10px 0 15px 0;
        }
        input[type="range"].mod-slider::-webkit-slider-thumb {
            -webkit-appearance: none; height: 16px; width: 16px; border-radius: 50%;
            background: #50fa7b; cursor: pointer; margin-top: -6px;
        }
        input[type="range"].mod-slider::-webkit-slider-runnable-track {
            width: 100%; height: 4px; cursor: pointer; background: #6272a4; border-radius: 2px;
        }

        #gc-mod-toggle {
            position: fixed; top: 20px; right: 20px; width: 45px; height: 45px;
            border-radius: 50%; background: #bd93f9; color: #282a36; border: none;
            box-shadow: 0 5px 15px rgba(0,0,0,0.4); z-index: 999998; cursor: pointer;
            font-size: 24px; display: none; align-items: center; justify-content: center;
        }

        /* Banner Resizer Handles */
        .mod-handle {
            position: absolute; width: 18px; height: 18px; background: #50fa7b;
            border: 2px solid #282a36; border-radius: 50%; z-index: 10; opacity: 0;
            transition: opacity 0.2s, transform 0.2s;
        }
        .gc-mod-wrapper:hover .mod-handle { opacity: 0.7; }
        .mod-handle:hover { opacity: 1 !important; transform: scale(1.3); }

        .mod-handle-nw { top: -9px; left: -9px; cursor: nw-resize; }
        .mod-handle-ne { top: -9px; right: -9px; cursor: ne-resize; }
        .mod-handle-sw { bottom: -9px; left: -9px; cursor: sw-resize; }
        .mod-handle-se { bottom: -9px; right: -9px; cursor: se-resize; }
    `);

    function doFontGlitch() {
        let styleTag = document.getElementById('gc-mod-font-distort');
        if (!styleTag) {
            styleTag = document.createElement('style');
            styleTag.id = 'gc-mod-font-distort';
            document.head.appendChild(styleTag);
        }

        const fonts = state.fontList.split(',').map(f => f.trim()).filter(f => f);
        if (fonts.length > 0) {
            const randomFont = fonts[Math.floor(Math.random() * fonts.length)];
            const randomSpacing = (Math.random() * 4 - 2).toFixed(1) + 'px'; // -2px to 2px

            styleTag.textContent = `
                *:not([id^="gc-mod-"]):not([id^="gc-dvd-"]):not([id^="gc-mod-"] *):not([id^="gc-dvd-"] *) {
                    font-family: "${randomFont}" !important;
                    letter-spacing: ${randomSpacing} !important;
                }
            `;
        }
    }

    function startFontDistortion() {
        stopFontDistortion();
        state.fontDistortEnabled = true;
        fontDistortTimer = setInterval(doFontGlitch, state.fontDistortSpeed);
    }

    function stopFontDistortion() {
        state.fontDistortEnabled = false;
        if (fontDistortTimer) {
            clearInterval(fontDistortTimer);
            fontDistortTimer = null;
        }
        const styleTag = document.getElementById('gc-mod-font-distort');
        if (styleTag) styleTag.textContent = '';
    }

    function startChaos() {
        state.chaosEnabled = true;
        chaosTimer = setInterval(() => {
            const els = document.querySelectorAll('div, span, a, p, img, button, li');
            els.forEach(el => {
                if(el.closest('[id^="gc-mod-"]') || el.closest('[id^="gc-dvd-"]') || el.tagName === 'BODY' || el.tagName === 'HTML' || el.tagName === 'MAIN') return;

                if(Math.random() > 0.7) {
                    const x = (Math.random() - 0.5) * 200; // -100px to 100px
                    const y = (Math.random() - 0.5) * 200;
                    const rot = (Math.random() - 0.5) * 60; // -30deg to 30deg
                    el.style.transform = `translate(${x}px, ${y}px) rotate(${rot}deg)`;
                    el.style.transition = "transform 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55)";
                }
            });
        }, 200);
    }

    function stopChaos() {
        state.chaosEnabled = false;
        clearInterval(chaosTimer);
        const els = document.querySelectorAll('div, span, a, p, img, button, li');
        els.forEach(el => {
            if(el.closest('[id^="gc-mod-"]') || el.closest('[id^="gc-dvd-"]')) return;
            el.style.transform = '';
            el.style.transition = '';
        });
    }

    function spawnDVD(startX, startY, dx = null, dy = null) {
        const container = document.getElementById('gc-dvd-container');
        if (!container) return;

        let el;
        if (state.dvdMediaType === 'video') {
            el = document.createElement('video');
            el.src = state.dvdMedia;
            el.autoplay = true;
            el.loop = true;
            el.muted = state.dvdMuted;
            el.volume = 1.0;
            el.playsInline = true;
        } else {
            el = document.createElement('img');
            el.src = state.dvdMedia;
        }

        el.style.position = 'absolute';
        el.style.transformOrigin = 'top left';
        el.style.width = '150px';
        el.style.pointerEvents = 'none';

        container.appendChild(el);

        if (dx === null || dy === null) {
            let angle = Math.random() * Math.PI * 2;
            dx = Math.cos(angle);
            dy = Math.sin(angle);
        }

        state.dvdInstances.push({
            x: startX || window.innerWidth / 2,
            y: startY || window.innerHeight / 2,
            dx,
            dy,
            element: el
        });
    }

    function clearDVDs() {
        state.dvdInstances.forEach(d => d.element.remove());
        state.dvdInstances =[];
    }

    function animateDVD() {
        if (state.dvdEnabled) {
            const screenW = window.innerWidth;
            const screenH = window.innerHeight;
            let pendingSpawns =[];

            for (let i = 0; i < state.dvdInstances.length; i++) {
                let dvd = state.dvdInstances[i];
                let el = dvd.element;

                dvd.x += dvd.dx * state.dvdSpeed;
                dvd.y += dvd.dy * state.dvdSpeed;
                el.style.transform = `scale(${state.dvdScale})`;

                let rect = el.getBoundingClientRect();
                let width = rect.width;
                let height = rect.height;
                let bounced = false;

                if (dvd.x <= 0) { dvd.x = 0; dvd.dx *= -1; bounced = true; }
                else if (dvd.x + width >= screenW) { dvd.x = screenW - width; dvd.dx *= -1; bounced = true; }
                if (dvd.y <= 0) { dvd.y = 0; dvd.dy *= -1; bounced = true; }
                else if (dvd.y + height >= screenH) { dvd.y = screenH - height; dvd.dy *= -1; bounced = true; }

                if (bounced && state.dvdMultiplier > 1 && state.dvdInstances.length + pendingSpawns.length < 150) {
                    for (let m = 0; m < state.dvdMultiplier - 1; m++) {
                        let angle = Math.random() * Math.PI * 2;
                        pendingSpawns.push({ x: dvd.x, y: dvd.y, dx: Math.cos(angle), dy: Math.sin(angle) });
                    }
                }

                el.style.left = dvd.x + 'px';
                el.style.top = dvd.y + 'px';
            }

            pendingSpawns.forEach(s => {
                spawnDVD(s.x, s.y, s.dx, s.dy);
            });
        }
        requestAnimationFrame(animateDVD);
    }
    requestAnimationFrame(animateDVD);


    function buildMenu() {
        if (document.getElementById('gc-mod-menu')) return;

        const menu = document.createElement('div');
        menu.id = 'gc-mod-menu';
        menu.style.display = state.menuVisible ? 'block' : 'none';

        const toggleBtn = document.createElement('button');
        toggleBtn.id = 'gc-mod-toggle';
        toggleBtn.innerText = '⚙️';
        toggleBtn.style.display = state.menuVisible ? 'none' : 'flex';
        document.body.appendChild(toggleBtn);

        const header = document.createElement('div');
        header.id = 'gc-mod-header';

        const title = document.createElement('span');
        title.innerText = 'Google Classroom Mod Menu';
        header.appendChild(title);

        const ctrlGroup = document.createElement('div');
        const minBtn = document.createElement('button');
        minBtn.innerText = '➖';
        minBtn.style.cssText = 'background:none; border:none; cursor:pointer; font-size:16px; margin-right:5px; color:#f1fa8c;';
        ctrlGroup.appendChild(minBtn);

        const closeBtn = document.createElement('button');
        closeBtn.innerText = '✖';
        closeBtn.style.cssText = 'background:none; border:none; cursor:pointer; font-size:16px; color:#ff5555;';
        ctrlGroup.appendChild(closeBtn);

        header.appendChild(ctrlGroup);
        menu.appendChild(header);

        const body = document.createElement('div');
        body.id = 'gc-mod-body';

        function createTitle(text) {
            const el = document.createElement('div');
            el.className = 'mod-section-title';
            el.innerText = text;
            body.appendChild(el);
        }

        function createInput(id, placeholder, val) {
            const el = document.createElement('input');
            el.type = 'text'; el.id = id; el.className = 'mod-input'; el.placeholder = placeholder;
            if (val) el.value = val;
            body.appendChild(el);
            return el;
        }

        function createButton(text, onClick, extraStyle = '') {
            const el = document.createElement('button');
            el.className = 'mod-btn'; el.innerText = text;
            if(extraStyle) el.style.cssText = extraStyle;
            el.onclick = onClick;
            body.appendChild(el);
            return el;
        }

        createTitle('🖼️ Custom Banner');
        const inpBanner = createInput('inp-banner', 'Image/Video URL (mp4, gif, jpg)');
        createButton('▶ Set URL as Banner', () => {
            if(inpBanner.value) {
                state.bannerSrc = inpBanner.value;
                state.bannerType = inpBanner.value.match(/\.(mp4|webm|ogg)$/i) ? 'video' : 'image';
            }
        });

        const fileInput = document.createElement('input');
        fileInput.type = 'file'; fileInput.accept = 'video/*, image/*'; fileInput.style.display = 'none';
        fileInput.onchange = (e) => {
            const file = e.target.files[0];
            if(file) {
                state.bannerSrc = URL.createObjectURL(file);
                state.bannerType = file.type.startsWith('video') ? 'video' : 'image';
            }
            e.target.value = '';
        };
        body.appendChild(fileInput);
        createButton('📁 Upload Local File', () => fileInput.click());
      // Banner Audio Controls
const btnBannerMute = createButton(
    state.bannerMuted ? '🔇 Unmute Banner Audio' : '🔊 Mute Banner Audio',
    () => {
        state.bannerMuted = !state.bannerMuted;

        btnBannerMute.innerText =
            state.bannerMuted
                ? '🔇 Unmute Banner Audio'
                : '🔊 Mute Banner Audio';

        btnBannerMute.classList.toggle('active', !state.bannerMuted);

        document.querySelectorAll('.gc-mod-media').forEach(media => {
            if (media.tagName === 'VIDEO') {
                media.muted = state.bannerMuted;

                // Needed because browsers block autoplay audio
                media.play().catch(() => {});
            }
        });
    }
);

if (!state.bannerMuted) {
    btnBannerMute.classList.add('active');
}

state.bannerVolume = state.bannerVolume || 1.0;

const bannerVolumeLabel = document.createElement('label');
bannerVolumeLabel.innerText = `Banner Volume: ${Math.round(state.bannerVolume * 100)}%`;
bannerVolumeLabel.style.cssText =
    'font-size:12px;color:#8be9fd;margin-bottom:5px;display:block;';
body.appendChild(bannerVolumeLabel);

const inpBannerVolume = document.createElement('input');
inpBannerVolume.type = 'range';
inpBannerVolume.className = 'mod-slider';
inpBannerVolume.min = '0';
inpBannerVolume.max = '1';
inpBannerVolume.step = '0.01';
inpBannerVolume.value = state.bannerVolume;

inpBannerVolume.oninput = (e) => {
    state.bannerVolume = parseFloat(e.target.value);

    bannerVolumeLabel.innerText =
        `Banner Volume: ${Math.round(state.bannerVolume * 100)}%`;

    document.querySelectorAll('.gc-mod-media').forEach(media => {
        if (media.tagName === 'VIDEO') {
            media.volume = state.bannerVolume;
        }
    });
};

body.appendChild(inpBannerVolume);

        createTitle('🔍 Master Zoom & Layout');
        const scaleLabel = document.createElement('label');
        scaleLabel.id = 'lbl-scale';
        scaleLabel.innerText = `Uniform Scale: ${state.bannerScale}x`;
        scaleLabel.style.cssText = 'font-size: 12px; color: #8be9fd; margin-bottom: 5px; display: block;';
        body.appendChild(scaleLabel);

        const inpScale = document.createElement('input');
        inpScale.type = 'range'; inpScale.id = 'inp-scale'; inpScale.className = 'mod-slider';
        inpScale.min = '0.1'; inpScale.max = '4.0'; inpScale.step = '0.05'; inpScale.value = state.bannerScale;
        inpScale.oninput = (e) => {
            state.bannerScale = e.target.value;
            scaleLabel.innerText = `Uniform Scale: ${state.bannerScale}x`;
        };
        body.appendChild(inpScale);

        createButton('🔄 Reset Banner Layout', () => {
            state.bWidth = '100%'; state.bHeight = '100%';
            state.bTop = '0px'; state.bLeft = '0px';
            state.bannerScale = 1.0;
            inpScale.value = 1.0;
            scaleLabel.innerText = `Uniform Scale: 1x`;
        }, 'background: #ffb86c; color: #282a36; font-weight: bold;');

        createTitle('🔠 Font Distorter');
        const inpFonts = createInput('inp-fonts', 'Comma separated fonts...', state.fontList);
        inpFonts.onchange = (e) => { state.fontList = e.target.value; };

        const btnFontToggle = createButton(
            state.fontDistortEnabled ? '⏸ Stop Distortion' : '▶ Start Distortion',
            () => {
                if (!state.fontDistortEnabled) {
                    startFontDistortion();
                    btnFontToggle.innerText = '⏸ Stop Distortion';
                    btnFontToggle.classList.add('active');
                } else {
                    stopFontDistortion();
                    btnFontToggle.innerText = '▶ Start Distortion';
                    btnFontToggle.classList.remove('active');
                }
            }
        );
        if (state.fontDistortEnabled) btnFontToggle.classList.add('active');

        const fontSpeedLabel = document.createElement('label');
        fontSpeedLabel.innerText = `Speed: ${state.fontDistortSpeed}ms`;
        fontSpeedLabel.style.cssText = 'font-size: 12px; color: #8be9fd; margin-bottom: 5px; display: block;';
        body.appendChild(fontSpeedLabel);

        const inpFontSpeed = document.createElement('input');
        inpFontSpeed.type = 'range'; inpFontSpeed.className = 'mod-slider';
        inpFontSpeed.min = '10'; inpFontSpeed.max = '1000'; inpFontSpeed.step = '10'; inpFontSpeed.value = state.fontDistortSpeed;
        inpFontSpeed.oninput = (e) => {
            state.fontDistortSpeed = parseInt(e.target.value);
            fontSpeedLabel.innerText = `Speed: ${state.fontDistortSpeed}ms`;
            if (state.fontDistortEnabled) startFontDistortion();
        };
        body.appendChild(inpFontSpeed);

        createTitle('🤯 Chaos Mode');
        const btnChaos = createButton(
            state.chaosEnabled ? '⏸ Stop Chaos' : '🌪️ Enable Chaos Mode',
            () => {
                if (!state.chaosEnabled) {
                    startChaos();
                    btnChaos.innerText = '⏸ Stop Chaos';
                    btnChaos.classList.add('active');
                } else {
                    stopChaos();
                    btnChaos.innerText = '🌪️ Enable Chaos Mode';
                    btnChaos.classList.remove('active');
                }
            }
        );
        if (state.chaosEnabled) btnChaos.classList.add('active');

        createTitle('📀 Bouncing Multiplier');
        const inpDvd = createInput('inp-dvd', 'Image/GIF/Video URL...', state.dvdMedia);
        inpDvd.onchange = () => {
            if (!inpDvd.value) return;
            state.dvdMedia = inpDvd.value;
            state.dvdMediaType = inpDvd.value.match(/\.(mp4|webm|ogg)$/i) ? 'video' : 'image';
            clearDVDs();
            if (state.dvdEnabled) spawnDVD();
        };

        const dvdFileInput = document.createElement('input');
        dvdFileInput.type = 'file'; dvdFileInput.accept = 'image/*,video/*'; dvdFileInput.style.display = 'none';
        dvdFileInput.onchange = (e) => {
            const file = e.target.files[0];
            if (!file) return;
            state.dvdMedia = URL.createObjectURL(file);
            state.dvdMediaType = file.type.startsWith('video') ? 'video' : 'image';
            clearDVDs();
            if (state.dvdEnabled) spawnDVD();
            e.target.value = '';
        };
        body.appendChild(dvdFileInput);

        const btnDvdMute = createButton(
            state.dvdMuted ? '🔇 Unmute Bouncer Audio' : '🔊 Mute Bouncer Audio',
            () => {
                state.dvdMuted = !state.dvdMuted;
                btnDvdMute.innerText = state.dvdMuted ? '🔇 Unmute Bouncer Audio' : '🔊 Mute Bouncer Audio';
                btnDvdMute.classList.toggle('active', !state.dvdMuted);
                state.dvdInstances.forEach(dvd => {
                    if (dvd.element.tagName === 'VIDEO') {
                        dvd.element.muted = state.dvdMuted;
                        dvd.element.play().catch(() => {});
                    }
                });
            }
        );
        if (!state.dvdMuted) btnDvdMute.classList.add('active');

        const btnDvdUploadRow = document.createElement('div');
        btnDvdUploadRow.style.cssText = 'display:flex; gap:5px;';

        const btnDvdUpload = createButton('📁 Local Media', () => dvdFileInput.click());
        btnDvdUploadRow.appendChild(btnDvdUpload);
        btnDvdUploadRow.appendChild(btnDvdMute);
        body.appendChild(btnDvdUploadRow);

        const multiLabel = document.createElement('label');
        multiLabel.innerText = `Bounce Multiplier: ${state.dvdMultiplier}x`;
        multiLabel.style.cssText = 'font-size:12px;color:#8be9fd;margin-bottom:5px;display:block;';
        body.appendChild(multiLabel);

        const inpMulti = document.createElement('input');
        inpMulti.type = 'range'; inpMulti.className = 'mod-slider';
        inpMulti.min = '1'; inpMulti.max = '10'; inpMulti.step = '1'; inpMulti.value = state.dvdMultiplier;
        inpMulti.oninput = (e) => {
            state.dvdMultiplier = parseInt(e.target.value);
            multiLabel.innerText = `Bounce Multiplier: ${state.dvdMultiplier}x`;
        };
        body.appendChild(inpMulti);

        const btnDvdToggle = createButton('▶ Start Bouncing', () => {
            state.dvdEnabled = !state.dvdEnabled;
            btnDvdToggle.innerText = state.dvdEnabled ? '⏸ Pause Bouncing' : '▶ Start Bouncing';
            btnDvdToggle.classList.toggle('active', state.dvdEnabled);
            if (state.dvdEnabled && state.dvdInstances.length === 0) {
                spawnDVD();
            }
        });

        const speedLabel = document.createElement('label');
        speedLabel.innerText = `Speed: ${state.dvdSpeed}`;
        speedLabel.style.cssText = 'font-size: 12px; color: #8be9fd; margin-bottom: 5px; display: block;';
        body.appendChild(speedLabel);

        const inpSpeed = document.createElement('input');
        inpSpeed.type = 'range'; inpSpeed.className = 'mod-slider';
        inpSpeed.min = '1'; inpSpeed.max = '20'; inpSpeed.step = '1'; inpSpeed.value = state.dvdSpeed;
        inpSpeed.oninput = (e) => {
            state.dvdSpeed = parseFloat(e.target.value);
            speedLabel.innerText = `Speed: ${state.dvdSpeed}`;
        };
        body.appendChild(inpSpeed);

        const dvdScaleLabel = document.createElement('label');
        dvdScaleLabel.innerText = `Image Scale: ${state.dvdScale}x`;
        dvdScaleLabel.style.cssText = 'font-size: 12px; color: #8be9fd; margin-bottom: 5px; display: block;';
        body.appendChild(dvdScaleLabel);

        const inpDvdScale = document.createElement('input');
        inpDvdScale.type = 'range'; inpDvdScale.className = 'mod-slider';
        inpDvdScale.min = '0.1'; inpDvdScale.max = '3.0'; inpDvdScale.step = '0.1'; inpDvdScale.value = state.dvdScale;
        inpDvdScale.oninput = (e) => {
            state.dvdScale = parseFloat(e.target.value);
            dvdScaleLabel.innerText = `Image Scale: ${state.dvdScale}x`;
        };
        body.appendChild(inpDvdScale);

        createButton('🗑️ Clear All Images', () => {
            clearDVDs();
            if (state.dvdEnabled) spawnDVD(window.innerWidth / 2, window.innerHeight / 2);
        });

        createTitle('✏️ Class Settings');
        const inpClassname = createInput('inp-classname', 'New Class Name...');
        createButton('Apply New Class Name', () => { state.spoofName = inpClassname.value; });

        createButton('RESET ENTIRE MOD', () => location.reload(), 'background:#ff5555; color:#fff; text-align:center; margin-top: 15px;');

        menu.appendChild(body);
        document.body.appendChild(menu);

        let isDraggingMenu = false, offsetX, offsetY;
        header.addEventListener('mousedown', (e) => {
            isDraggingMenu = true;
            offsetX = e.clientX - menu.getBoundingClientRect().left;
            offsetY = e.clientY - menu.getBoundingClientRect().top;
        });
        document.addEventListener('mousemove', (e) => {
            if (!isDraggingMenu) return;
            menu.style.left = (e.clientX - offsetX) + 'px';
            menu.style.top = (e.clientY - offsetY) + 'px';
            menu.style.right = 'auto';
        });
        document.addEventListener('mouseup', () => isDraggingMenu = false);

        minBtn.onclick = () => {
            state.menuVisible = false;
            menu.style.display = 'none';
            toggleBtn.style.display = 'flex';
        };
        closeBtn.onclick = () => {
            state.menuVisible = false;
            menu.style.display = 'none';
        };
        toggleBtn.onclick = () => {
            state.menuVisible = true;
            menu.style.display = 'block';
            toggleBtn.style.display = 'none';
        };

        let iconDragging = false, iconX, iconY;
        toggleBtn.addEventListener('mousedown', (e) => {
            iconDragging = true;
            iconX = e.clientX - toggleBtn.getBoundingClientRect().left;
            iconY = e.clientY - toggleBtn.getBoundingClientRect().top;
        });
        document.addEventListener('mousemove', (e) => {
            if(!iconDragging) return;
            toggleBtn.style.left = (e.clientX - iconX) + 'px';
            toggleBtn.style.top = (e.clientY - iconY) + 'px';
            toggleBtn.style.right = 'auto';
        });
        document.addEventListener('mouseup', () => iconDragging = false);
    }

    function makeResizableAndDraggable(wrapper) {
        let currentHandle = null;
        let startX, startY, startW, startH, startL, startT;

        const handles =['nw', 'ne', 'sw', 'se'];
        handles.forEach(pos => {
            const h = document.createElement('div');
            h.className = `mod-handle mod-handle-${pos}`;

            h.onmousedown = (e) => {
                e.stopPropagation(); e.preventDefault();
                isMediaResizing = true;
                currentHandle = pos;
                startX = e.clientX; startY = e.clientY;
                startW = wrapper.offsetWidth; startH = wrapper.offsetHeight;
                startL = wrapper.offsetLeft; startT = wrapper.offsetTop;
            };
            wrapper.appendChild(h);
        });

        wrapper.style.cursor = 'move';
        wrapper.onmousedown = (e) => {
            if(e.target.classList.contains('mod-handle')) return;
            e.preventDefault();
            isMediaDragging = true;
            startX = e.clientX; startY = e.clientY;
            startL = wrapper.offsetLeft; startT = wrapper.offsetTop;
        };

        document.addEventListener('mousemove', (e) => {
            if (isMediaResizing) {
                const scale = parseFloat(state.bannerScale) || 1;
                const dx = (e.clientX - startX) / scale;
                const dy = (e.clientY - startY) / scale;

                let newW = startW, newH = startH, newL = startL, newT = startT;

                if (currentHandle.includes('e')) newW = startW + dx;
                if (currentHandle.includes('w')) { newW = startW - dx; newL = startL + dx; }
                if (currentHandle.includes('s')) newH = startH + dy;
                if (currentHandle.includes('n')) { newH = startH - dy; newT = startT + dy; }

                state.bWidth = newW + 'px'; state.bHeight = newH + 'px';
                state.bLeft = newL + 'px'; state.bTop = newT + 'px';

                wrapper.style.width = state.bWidth; wrapper.style.height = state.bHeight;
                wrapper.style.left = state.bLeft; wrapper.style.top = state.bTop;

            } else if (isMediaDragging) {
                const dx = (e.clientX - startX);
                const dy = (e.clientY - startY);

                state.bLeft = (startL + dx) + 'px';
                state.bTop = (startT + dy) + 'px';

                wrapper.style.left = state.bLeft;
                wrapper.style.top = state.bTop;
            }
        });

        document.addEventListener('mouseup', () => {
            isMediaResizing = false;
            isMediaDragging = false;
            currentHandle = null;
        });
    }

    setInterval(() => {
        buildMenu();

        if (!document.getElementById('gc-dvd-container')) {
            const dvdCont = document.createElement('div');
            dvdCont.id = 'gc-dvd-container';
            dvdCont.style.cssText = 'position:fixed; top:0; left:0; width:100%; height:100%; pointer-events:none; z-index:999995; overflow:hidden;';
            document.body.appendChild(dvdCont);
            state.dvdInstances.forEach(d => dvdCont.appendChild(d.element));
        }

        if (state.bannerSrc) {
            const banners = document.querySelectorAll('.qyN25');
            banners.forEach(banner => {

                const origImg = banner.querySelector('.PFLqgc');
                if (origImg) origImg.style.display = 'none';

                const textContainer = banner.querySelector('.T4tcpe');
                if(textContainer) {
                    textContainer.style.zIndex = '3';
                    textContainer.style.pointerEvents = 'none';
                }

                let wrapper = banner.querySelector('.gc-mod-wrapper');

                if (wrapper) {
                    const media = wrapper.querySelector('.gc-mod-media');
                    if (media) {
                        const isCurrentlyVideo = media.tagName === 'VIDEO';
                        const wantsVideo = state.bannerType === 'video';
                        if (isCurrentlyVideo !== wantsVideo) {
                            wrapper.remove();
                            wrapper = null;
                        }
                    }
                }

                if (!wrapper) {
                    wrapper = document.createElement('div');
                    wrapper.className = 'gc-mod-wrapper';
                    wrapper.style.cssText = 'position:absolute; z-index:0; transform-origin:center;';

                    let customElem;
                    if (state.bannerType === 'video') {
    customElem = document.createElement('video');

    customElem.autoplay = true;
    customElem.loop = true;
    customElem.playsInline = true;

    customElem.muted = state.bannerMuted;
    customElem.volume = state.bannerVolume || 1.0;

    customElem.play().catch(() => {});
} else {
                        customElem = document.createElement('img');
                    }
                    customElem.className = 'gc-mod-media';
                    customElem.style.cssText = 'width:100%; height:100%; object-fit:fill; pointer-events:none; border-radius:inherit; display:block;';
                    wrapper.appendChild(customElem);
                    banner.insertBefore(wrapper, banner.firstChild);

                    const overlay = document.createElement('div');
                    overlay.style.cssText = 'position:absolute; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.3); z-index:2; border-radius:inherit; pointer-events:none;';
                    banner.insertBefore(overlay, textContainer);

                    banner.style.backgroundColor = '#1e1e2e';

                    makeResizableAndDraggable(wrapper);
                }

                const media = wrapper.querySelector('.gc-mod-media');

                if (media.src !== state.bannerSrc) media.src = state.bannerSrc;

                if (!isMediaDragging && !isMediaResizing) {
                    wrapper.style.width = state.bWidth;
                    wrapper.style.height = state.bHeight;
                    wrapper.style.top = state.bTop;
                    wrapper.style.left = state.bLeft;
                    wrapper.style.transform = `scale(${state.bannerScale})`;
                }
            });
        }

        if (state.spoofName) {
            const titles = document.querySelectorAll('.tNGpbb, .YVvGBb');
            titles.forEach(title => {
                if (title.tagName === 'H1' || title.classList.contains('XL4gNd')) {
                    title.innerText = state.spoofName;
                }
            });
        }

    }, 500);

})();