// ==UserScript== // @name MOG Speech Bubble // console.log('MOG Speech Bubble script loaded'); document.addEventListener('DOMContentLoaded', () => { setTimeout(() => { const mogElement = document.getElementById('mog'); if (mogElement) { const speechBubble = document.createElement('div'); speechBubble.textContent = "Having performance issues? Triple click me to freeze the cards!"; speechBubble.style.position = 'absolute'; speechBubble.style.background = '#fff'; speechBubble.style.color = '#000'; speechBubble.style.padding = '4px'; // Reduced padding speechBubble.style.border = '.5px solid #000'; // Reduced border size speechBubble.style.borderRadius = '0'; // Remove rounded corners for a pixelated look speechBubble.style.boxShadow = '0 2px 3px rgba(0, 0, 0, 0.3)'; // Reduced shadow speechBubble.style.fontSize = '12px'; // Reduced font size speechBubble.style.fontFamily = '"Tiny5", sans-serif'; // Use a pixel-style font speechBubble.style.zIndex = '2147483647'; speechBubble.style.whiteSpace = 'nowrap'; speechBubble.style.transition = 'opacity 0.5s ease'; speechBubble.style.opacity = '0'; speechBubble.style.animation = 'float 3s ease-in-out infinite'; // Add floating animation // Add a triangular pointer to the speech bubble const pointer = document.createElement('div'); pointer.style.position = 'absolute'; pointer.style.width = '0'; pointer.style.height = '0'; pointer.style.borderLeft = '4px solid transparent'; // Reduced pointer size pointer.style.borderRight = '4px solid transparent'; // Reduced pointer size pointer.style.borderTop = '4px solid #fff'; // Match the speech bubble background pointer.style.borderBottom = '.5px solid #000'; // Add border to the bottom edge pointer.style.bottom = '-5px'; // Adjust position below the bubble pointer.style.left = '5px'; // Align to the bottom left corner pointer.style.zIndex = '-1'; // Place behind the bubble border speechBubble.appendChild(pointer); // Append the speech bubble to the body document.body.appendChild(speechBubble); const updatePosition = () => { const mogRect = mogElement.getBoundingClientRect(); speechBubble.style.left = `${mogRect.left + mogRect.width - 17}px`; // Adjusted for smaller size speechBubble.style.top = `${mogRect.top - 30}px`; // Adjusted for smaller size }; // Initialize the speech bubble position updatePosition(); // Continuously update the position every 1ms const positionInterval = setInterval(updatePosition, 1); // Fade in the speech bubble setTimeout(() => { speechBubble.style.opacity = '1'; }, 100); // Remove the speech bubble after 10 seconds setTimeout(() => { clearInterval(positionInterval); // Stop updating position speechBubble.style.opacity = '0'; setTimeout(() => speechBubble.remove(), 600); }, 12000); // Add dragging logic to make the speech bubble follow mog let isDragging = false; mogElement.addEventListener('mousedown', (e) => { isDragging = true; const offsetX = e.clientX - mogElement.offsetLeft; const offsetY = e.clientY - mogElement.offsetTop; const onMouseMove = (event) => { if (!isDragging) return; mogElement.style.position = 'absolute'; mogElement.style.left = `${event.clientX - offsetX}px`; mogElement.style.top = `${event.clientY - offsetY}px`; }; const onMouseUp = () => { isDragging = false; window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); }; window.addEventListener('mousemove', onMouseMove); window.addEventListener('mouseup', onMouseUp); }); } }, 15000); // 15 second delay }); // Add floating animation keyframes const style = document.createElement('style'); style.textContent = ` @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } } `; document.head.appendChild(style);