Apex Learning Quiz Cheat

Highlights Correct Answers in Apex Learning Quiz Menus. Includes Image Support, AI Logic, Auto-Complete, and Keybind Controls

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

You will need to install an extension such as Tampermonkey to install this script.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         Apex Learning Quiz Cheat
// @namespace    https://github.com/paysonism
// @version      8.3
// @description  Highlights Correct Answers in Apex Learning Quiz Menus. Includes Image Support, AI Logic, Auto-Complete, and Keybind Controls
// @author       paysonism
// @match        https://course.apexlearning.com/public/activity/*
// @match        https://*.apexvs.com/public/activity/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      generativelanguage.googleapis.com
// @run-at       document-end
// @license      MIT
// ==/UserScript==

//      ====================================================
//     |  Keybinds - MENU WILL SHOW FOR 1S ON CHANGE        |
//     |  Ctrl+Shift+E - Toggle Enable/Disable Script       |
//     |  Ctrl+Shift+A - Toggle Auto-Complete Mode          |
//     |  Ctrl+Shift+R - Manual Reprocess Current Question  |
//      ====================================================

(function() {
    'use strict';

    // CONFIGURATION - MUST ADD API KEY!
    // ============================================
    const GEMINI_API_KEY = 'YOUR_API_KEY_HERE'; // Get a free key from: https://aistudio.google.com/app/apikey
    const DEBUG_MODE = false; // Set to true for console logging

    const MAX_IMAGE_WIDTH = 800;
    const MAX_IMAGE_HEIGHT = 800;
    const IMAGE_QUALITY = 0.85;

    // Auto Complete Delay Settings
    const AUTO_SELECT_DELAY = 500; // Delay before auto-selecting answer (ms)
    const AUTO_SUBMIT_DELAY = 1000; // Delay before auto-submitting (ms)
    const NEXT_QUESTION_DELAY = 1000; // Delay before clicking next question (ms)
    const VIEW_SUMMARY_DELAY = 500; // Delay before clicking view summary (ms)

    let lastQuestionText = '';
    let isProcessing = false;
    let progressInterval = null;
    let isEnabled = GM_getValue('scriptEnabled', true);
    let autoCompleteEnabled = GM_getValue('autoCompleteEnabled', false);
    let notificationTimeout = null;

    function log(...args) {
        if (DEBUG_MODE) {
            console.log(...args);
        }
    }

    function logError(...args) {
        if (DEBUG_MODE) {
            console.error(...args);
        }
    }

    // Show glassmorphism notification
    function showNotification(message, duration = 2000) {
        // Remove existing notification
        const existing = document.getElementById('apex-notification');
        if (existing) {
            existing.remove();
        }

        const notification = document.createElement('div');
        notification.id = 'apex-notification';
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: rgba(255, 255, 255, 0.15);
            backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px);
            border: 1px solid rgba(255, 255, 255, 0.25);
            color: white;
            padding: 20px 25px;
            border-radius: 16px;
            z-index: 999999;
            font-family: 'Bahnschrift', 'Segoe UI', Tahoma, sans-serif;
            font-size: 15px;
            font-weight: 300;
            letter-spacing: 0.5px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            animation: slideIn 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
            min-width: 200px;
        `;

        notification.innerHTML = `
            <style>
                @keyframes slideIn {
                    from {
                        transform: translateX(400px) scale(0.8);
                        opacity: 0;
                    }
                    to {
                        transform: translateX(0) scale(1);
                        opacity: 1;
                    }
                }
                @keyframes slideOut {
                    from {
                        transform: translateX(0) scale(1);
                        opacity: 1;
                    }
                    to {
                        transform: translateX(400px) scale(0.8);
                        opacity: 0;
                    }
                }
            </style>
            <div style="text-shadow: 0 2px 4px rgba(0,0,0,0.3);">${message}</div>
        `;

        document.body.appendChild(notification);

        if (notificationTimeout) {
            clearTimeout(notificationTimeout);
        }

        notificationTimeout = setTimeout(() => {
            notification.style.animation = 'slideOut 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)';
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.remove();
                }
            }, 300);
        }, duration);
    }

    function hasQuizContent() {
        const hasStem = document.querySelector('.sia-question-stem') !== null;
        const hasQuestion = document.querySelector('kp-sia-question') !== null;
        const hasDistractors = document.querySelectorAll('.sia-distractor').length > 0;
        return hasStem || hasQuestion || hasDistractors;
    }

    function extractQuestion() {
        const siaQuestion = document.querySelector('kp-sia-question');
        if (siaQuestion) {
            const kpContent = siaQuestion.querySelector('kp-content');
            if (kpContent) {
                const generated = kpContent.querySelector('[class*="kp-generated"]');
                if (generated) {
                    return generated.textContent.trim();
                }
                const text = kpContent.textContent.trim();
                if (text) return text;
            }
        }

        const questionStem = document.querySelector('.sia-question-stem');
        if (questionStem) {
            const allElements = questionStem.querySelectorAll('*');
            for (let el of allElements) {
                if (el.className && el.className.includes('kp-generated')) {
                    const text = el.textContent.trim();
                    if (text) return text;
                }
            }
            const text = questionStem.textContent.trim();
            if (text) return text;
        }

        return null;
    }

    function resizeAndCompressImage(img) {
        return new Promise((resolve, reject) => {
            try {
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');

                let width = img.naturalWidth || img.width;
                let height = img.naturalHeight || img.height;

                log(`Original image size: ${width}x${height}`);

                if (width > MAX_IMAGE_WIDTH || height > MAX_IMAGE_HEIGHT) {
                    const ratio = Math.min(MAX_IMAGE_WIDTH / width, MAX_IMAGE_HEIGHT / height);
                    width = Math.floor(width * ratio);
                    height = Math.floor(height * ratio);
                }

                log(`Resized to: ${width}x${height}`);

                canvas.width = width;
                canvas.height = height;
                ctx.drawImage(img, 0, 0, width, height);

                canvas.toBlob((blob) => {
                    if (!blob) {
                        reject(new Error('Failed to create blob'));
                        return;
                    }

                    const reader = new FileReader();
                    reader.onloadend = function() {
                        const base64data = reader.result.split(',')[1];
                        const originalSize = (base64data.length * 0.75 / 1024).toFixed(2);
                        log(`Compressed image size: ${originalSize} KB`);

                        resolve({
                            data: base64data,
                            mimeType: 'image/jpeg'
                        });
                    };
                    reader.onerror = () => reject(new Error('Failed to read blob'));
                    reader.readAsDataURL(blob);
                }, 'image/jpeg', IMAGE_QUALITY);

            } catch (e) {
                reject(e);
            }
        });
    }

    async function extractImages() {
        const images = [];
        const questionArea = document.querySelector('kp-sia-question');
        if (!questionArea) return images;

        const imgElements = questionArea.querySelectorAll('img');
        log(`Found ${imgElements.length} images in question`);

        for (let imgEl of imgElements) {
            try {
                const img = new Image();
                img.crossOrigin = 'anonymous';

                const imageLoadPromise = new Promise((resolve, reject) => {
                    img.onload = () => resolve(img);
                    img.onerror = () => reject(new Error('Failed to load image'));

                    if (imgEl.src) {
                        img.src = imgEl.src;
                    } else if (imgEl.dataset.src) {
                        img.src = imgEl.dataset.src;
                    } else {
                        reject(new Error('No image source found'));
                    }
                });

                await imageLoadPromise;
                const compressedImage = await resizeAndCompressImage(img);
                images.push(compressedImage);
                log('Image processed and compressed');

            } catch (error) {
                logError('Error processing image:', error);

                try {
                    if (imgEl.src && imgEl.src.startsWith('data:')) {
                        const base64Data = imgEl.src.split(',')[1];
                        const mimeType = imgEl.src.split(';')[0].split(':')[1];
                        images.push({
                            data: base64Data,
                            mimeType: mimeType
                        });
                        log('Used original base64 image (compression failed)');
                    }
                } catch (fallbackError) {
                    logError('Fallback also failed:', fallbackError);
                }
            }
        }

        return images;
    }

    function extractAnswers() {
        const answers = [];
        const distractors = document.querySelectorAll('.sia-distractor');

        distractors.forEach((distractor, index) => {
            const choiceLetter = distractor.querySelector('.sia-choice-letter')?.textContent.trim();
            let answerText = null;

            const kpContent = distractor.querySelector('kp-content');
            if (kpContent) {
                const generated = kpContent.querySelector('[class*="kp-generated"]');
                if (generated) {
                    answerText = generated.textContent.trim();
                } else {
                    answerText = kpContent.textContent.trim();
                }
            }

            if (!answerText) {
                const labelDiv = distractor.querySelector('.label');
                if (labelDiv) {
                    answerText = labelDiv.textContent.replace(choiceLetter || '', '').trim();
                }
            }

            if (answerText) {
                answers.push({
                    letter: choiceLetter || String.fromCharCode(65 + index) + '.',
                    text: answerText,
                    element: distractor
                });
            }
        });

        return answers;
    }

    function createProgressBar() {
        let progressBar = document.getElementById('gemini-progress-bar');

        if (!progressBar) {
            progressBar = document.createElement('div');
            progressBar.id = 'gemini-progress-bar';
            progressBar.style.cssText = `
                position: fixed;
                bottom: 25px;
                right: 25px;
                width: 200px;
                height: 6px;
                background: #e0e0e0;
                border-radius: 2px;
                overflow: hidden;
                z-index: 999999;
                opacity: 0;
                transition: opacity 0.3s ease;
            `;

            const progressFill = document.createElement('div');
            progressFill.id = 'gemini-progress-fill';
            progressFill.style.cssText = `
                height: 100%;
                width: 0%;
                background: linear-gradient(90deg, #4285f4, #34a853);
                border-radius: 2px;
                transition: width 0.1s linear;
            `;

            progressBar.appendChild(progressFill);
            document.body.appendChild(progressBar);
        }

        return progressBar;
    }

    function showProgress() {
        const progressBar = createProgressBar();
        const progressFill = document.getElementById('gemini-progress-fill');

        progressBar.style.opacity = '0.75';
        progressFill.style.width = '0%';

        let progress = 0;
        const duration = 3000;
        const interval = 50;
        const increment = (interval / duration) * 100;

        if (progressInterval) {
            clearInterval(progressInterval);
        }

        progressInterval = setInterval(() => {
            progress += increment;
            if (progress >= 95) {
                progress = 95;
            }
            progressFill.style.width = progress + '%';
        }, interval);
    }

    function hideProgress(success = true) {
        if (progressInterval) {
            clearInterval(progressInterval);
            progressInterval = null;
        }

        const progressBar = document.getElementById('gemini-progress-bar');
        const progressFill = document.getElementById('gemini-progress-fill');

        if (progressBar && progressFill) {
            if (success) {
                progressFill.style.width = '100%';
                setTimeout(() => {
                    progressBar.style.opacity = '0';
                    setTimeout(() => {
                        progressFill.style.width = '0%';
                    }, 300);
                }, 300);
            } else {
                progressFill.style.background = '#ea4335';
                setTimeout(() => {
                    progressBar.style.opacity = '0';
                    setTimeout(() => {
                        progressFill.style.width = '0%';
                        progressFill.style.background = 'linear-gradient(90deg, #4285f4, #34a853)';
                    }, 300);
                }, 500);
            }
        }
    }

    function queryGemini(question, answers, images) {
        return new Promise((resolve, reject) => {
            if (!GEMINI_API_KEY || GEMINI_API_KEY === 'YOUR_API_KEY_HERE') {
                reject(new Error('No API key configured'));
                return;
            }

            const answerList = answers.map(a => `${a.letter} ${a.text}`).join('\n');

            let prompt = `You are a knowledgeable assistant operating at a high school level. `;

            if (images.length > 0) {
                prompt += `Analyze the question carefully INCLUDING the provided image(s). The images may contain diagrams, charts, molecular structures, or other visual information needed to answer correctly. `;
            }

            prompt += `Provide ONLY the letter (A, B, C, or D) of the correct answer. Do not include any explanation or additional text - just the single letter.

Question: ${question}

Answer Options:
${answerList}

Think through the question logically and select the most accurate answer based on high school official correct answer trends. This is for a high school level quiz so use appropriate reasoning for that level.

Correct answer letter (A, B, C, or D only):`;

            const parts = [];

            if (images.length > 0) {
                log(`Including ${images.length} optimized image(s) in request`);
                images.forEach((img) => {
                    parts.push({
                        inline_data: {
                            mime_type: img.mimeType,
                            data: img.data
                        }
                    });
                });
            }

            parts.push({ text: prompt });

            const requestData = {
                contents: [{
                    parts: parts
                }]
            };

            const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-latest:generateContent?key=${GEMINI_API_KEY}`;

            log('Querying Gemini' + (images.length > 0 ? ' with vision' : ''));

            GM_xmlhttpRequest({
                method: 'POST',
                url: url,
                headers: {
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify(requestData),
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);

                        if (data.error) {
                            logError('API Error:', data.error);
                            reject(new Error(data.error.message));
                            return;
                        }

                        if (data.candidates && data.candidates.length > 0) {
                            const candidate = data.candidates[0];
                            let answer = null;

                            if (candidate.content && candidate.content.parts) {
                                if (Array.isArray(candidate.content.parts) && candidate.content.parts.length > 0) {
                                    const part = candidate.content.parts[0];
                                    if (part && part.text) {
                                        answer = part.text;
                                    }
                                }
                            }

                            if (answer) {
                                log('Full response text:', answer);

                                const letterMatch = answer.match(/\b[A-D]\b/i);
                                if (letterMatch) {
                                    const finalAnswer = letterMatch[0].toUpperCase();
                                    log('Extracted answer:', finalAnswer);
                                    resolve(finalAnswer);
                                } else {
                                    const anyLetter = answer.match(/[A-D]/i);
                                    if (anyLetter) {
                                        const finalAnswer = anyLetter[0].toUpperCase();
                                        log('Using first A-D found:', finalAnswer);
                                        resolve(finalAnswer);
                                    } else {
                                        reject(new Error('No A-D letter in response'));
                                    }
                                }
                            } else {
                                logError('No text in response');

                                if (candidate.finishReason === 'SAFETY') {
                                    reject(new Error('Response blocked by safety filter'));
                                } else if (candidate.finishReason === 'MAX_TOKENS') {
                                    reject(new Error('MAX_TOKENS issue'));
                                } else {
                                    reject(new Error(`No text (finish: ${candidate.finishReason})`));
                                }
                            }
                        } else {
                            reject(new Error('No candidates'));
                        }
                    } catch (e) {
                        logError('Parse error:', e);
                        reject(e);
                    }
                },
                onerror: function(error) {
                    logError('Request error:', error);
                    reject(error);
                }
            });
        });
    }

    function removeHighlights() {
        document.querySelectorAll('.sia-distractor').forEach(el => {
            const labelDiv = el.querySelector('.label');
            if (labelDiv) {
                labelDiv.style.color = '';
                labelDiv.style.fontWeight = '';
                labelDiv.style.opacity = '';
            }
        });
    }

    function highlightAnswer(answers, correctLetter) {
        const normalizedCorrect = correctLetter.replace(/[^A-D]/gi, '').trim().toUpperCase();
        log('Highlighting answer:', normalizedCorrect);

        answers.forEach(answer => {
            const normalizedAnswerLetter = answer.letter.replace(/[^A-D]/gi, '').trim().toUpperCase();

            if (normalizedAnswerLetter === normalizedCorrect) {
                const labelDiv = answer.element.querySelector('.label');
                if (labelDiv) {
                    labelDiv.style.color = '#1e7e34';
                    labelDiv.style.fontWeight = '600';
                    labelDiv.style.opacity = '0.65';
                }

                log(`Highlighted answer ${answer.letter}`);
            }
        });
    }

    function selectAnswer(answers, correctLetter) {
        const normalizedCorrect = correctLetter.replace(/[^A-D]/gi, '').trim().toUpperCase();

        for (let answer of answers) {
            const normalizedAnswerLetter = answer.letter.replace(/[^A-D]/gi, '').trim().toUpperCase();

            if (normalizedAnswerLetter === normalizedCorrect) {
                log('Auto-selecting answer:', normalizedCorrect);

                const radioButton = answer.element.querySelector('input[type="radio"]');
                if (radioButton) {
                    radioButton.checked = true;
                    radioButton.dispatchEvent(new Event('change', { bubbles: true }));
                    radioButton.dispatchEvent(new Event('click', { bubbles: true }));
                    return true;
                }

                answer.element.click();
                return true;
            }
        }

        return false;
    }

    function submitAnswer() {
        log('Attempting to submit answer');
        const submitSelectors = [
            'button[type="submit"]',
            'button.submit',
            'button.submit-button',
            'input[type="submit"]',
            '.submit-button',
            '[class*="submit"]'
        ];

        for (let selector of submitSelectors) {
            const buttons = document.querySelectorAll(selector);
            for (let button of buttons) {
                if (button.offsetParent !== null) {
                    const buttonText = button.textContent.trim().toUpperCase();
                    if (buttonText.includes('SUBMIT') || buttonText.includes('CHECK') ||
                        (buttonText.includes('ANSWER') && !buttonText.includes('NEXT'))) {
                        log('Found submit button:', buttonText);
                        button.click();
                        return true;
                    }
                }
            }
        }

        log('Submit button not found');
        return false;
    }

    function clickNextQuestion() {
    log('Attempting to click next question button');

    const nextSelectors = [
        'button.submit-button', // apex uses this one
        'button.next',
        '[class*="next"]',
        '[class*="continue"]'
    ];

    for (let selector of nextSelectors) {
        const buttons = document.querySelectorAll(selector);
        for (let button of buttons) {
            if (button.offsetParent !== null) {
                const buttonText = button.textContent.trim().toUpperCase();
                log('Found button with text:', buttonText);

                if (buttonText.includes('VIEW SUMMARY')) {
                    log('Found VIEW SUMMARY button - clicking and disabling auto-complete');
                    button.click();

                    autoCompleteEnabled = false;
                    GM_setValue('autoCompleteEnabled', false);

                    const message = `
                        <div style="font-size: 15px; font-weight: 400;"><b>Quiz Complete!<b></div>
                        <div style="font-size: 12px; opacity: 0.8; margin-top: 5px;">Auto-Complete: <span style="color: #f87171"><b>Disabled<b></span></div>
                    `;
                    showNotification(message, 3000);

                    return true;
                }

                if (buttonText.includes('NEXT') || buttonText.includes('CONTINUE')) {
                    log('Clicking next question button');
                    button.click();

                    setTimeout(() => {
                        lastQuestionText = '';
                    }, 500);

                    return true;
                }
            }
        }
    }

    log('Next question button not found');
    return false;
}


    async function processQuiz() {
        if (!isEnabled || isProcessing) return;

        if (!hasQuizContent()) {
            return;
        }

        const question = extractQuestion();
        if (!question) {
            return;
        }

        if (question === lastQuestionText) {
            return;
        }

        log('New question detected');
        lastQuestionText = question;
        isProcessing = true;

        removeHighlights();
        showProgress();

        try {
            const answers = extractAnswers();
            if (answers.length === 0) {
                log('No answers found');
                hideProgress(false);
                isProcessing = false;
                return;
            }

            const images = await extractImages();
            if (images.length > 0) {
                log(`Processed ${images.length} optimized image(s)`);
            }

            const correctAnswer = await queryGemini(question, answers, images);
            highlightAnswer(answers, correctAnswer);
            hideProgress(true);

            if (autoCompleteEnabled) {
                setTimeout(() => {
                    const selected = selectAnswer(answers, correctAnswer);
                    if (selected) {
                        log('Answer selected, waiting before submit');

                        setTimeout(() => {
                            const submitted = submitAnswer();

                            if (submitted) {
                                log('Answer submitted, waiting before clicking next');

                                setTimeout(() => {
                                    clickNextQuestion();
                                }, NEXT_QUESTION_DELAY);
                            }
                        }, AUTO_SUBMIT_DELAY);
                    }
                }, AUTO_SELECT_DELAY);
            }

        } catch (error) {
            logError('Error:', error.message);
            hideProgress(false);
        } finally {
            isProcessing = false;
        }
    }

    function startMonitoring() {
        if (!GEMINI_API_KEY || GEMINI_API_KEY === 'YOUR_API_KEY_HERE') {
            console.error('Apex Quiz Auto-Answer: No API key configured. Get one from https://aistudio.google.com/app/apikey');
            return;
        }

        log('Apex Quiz Auto-Answer Active');
        log('Images will be resized to max 800x800');

        setTimeout(processQuiz, 2000);

        const observer = new MutationObserver((mutations) => {
            const relevantChange = mutations.some(mutation => {
                return Array.from(mutation.addedNodes).some(node => {
                    if (node.nodeType === 1) {
                        return node.classList?.contains('sia-distractor') ||
                               node.classList?.contains('sia-question-stem') ||
                               node.querySelector?.('.sia-distractor') ||
                               node.querySelector?.('.sia-question-stem');
                    }
                    return false;
                });
            });

            if (relevantChange) {
                setTimeout(processQuiz, 500);
            }
        });

        const mainContent = document.querySelector('kp-main, main, .sia-content');
        if (mainContent) {
            observer.observe(mainContent, {
                childList: true,
                subtree: true
            });
        }

        setInterval(processQuiz, 3000);
    }

    function init() {
        startMonitoring();

        const statusMessage = `
            <div style="font-size: 16px; margin-bottom: 8px; font-weight: 400;">Apex Quiz Helper</div>
            <div style="font-size: 13px; opacity: 0.9;">Script: <span style="color: ${isEnabled ? '#4ade80' : '#f87171'}"><b>${isEnabled ? 'Enabled' : 'Disabled'}</b></span></div>
            <div style="font-size: 13px; opacity: 0.9;">Auto-Complete: <span style="color: ${autoCompleteEnabled ? '#4ade80' : '#f87171'}"><b>${autoCompleteEnabled ? 'ON' : 'OFF'}</b></span></div>
        `;
        showNotification(statusMessage, 3000);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    document.addEventListener('keydown', (e) => {
        if (e.ctrlKey && e.shiftKey && e.key === 'E') {
            e.preventDefault();
            isEnabled = !isEnabled;
            GM_setValue('scriptEnabled', isEnabled);
            const message = `
                <div style="font-size: 15px; font-weight: 400;">Script <b>${isEnabled ? 'Enabled' : 'Disabled'}</b></div>
                <div style="font-size: 12px; opacity: 0.8; margin-top: 5px;">Status: <span style="color: ${isEnabled ? '#4ade80' : '#f87171'}"><b>${isEnabled ? 'Active' : 'Inactive'}</b></span></div>
            `;
            showNotification(message);
            if (isEnabled) {
                processQuiz();
            } else {
                removeHighlights();
            }
        }

        if (e.ctrlKey && e.shiftKey && e.key === 'A') {
            e.preventDefault();
            autoCompleteEnabled = !autoCompleteEnabled;
            GM_setValue('autoCompleteEnabled', autoCompleteEnabled);
            const message = `
                <div style="font-size: 15px; font-weight: 400;">Auto-Complete <b>${autoCompleteEnabled ? 'Enabled' : 'Disabled'}</b></div>
                <div style="font-size: 12px; opacity: 0.8; margin-top: 5px;">Mode: <span style="color: ${autoCompleteEnabled ? '#4ade80' : '#f87171'}"><b>${autoCompleteEnabled ? 'Full Auto' : 'Highlight Only'}</b></span></div>
            `;
            showNotification(message);
        }

        if (e.ctrlKey && e.shiftKey && e.key === 'R') {
            e.preventDefault();
            lastQuestionText = '';
            isProcessing = false;
            removeHighlights();
            const message = `
                <div style="font-size: 15px; font-weight: 400;">Reprocessing Question</div>
                <div style="font-size: 12px; opacity: 0.8; margin-top: 5px;">Analyzing with Gemini...</div>
            `;
            showNotification(message, 1500);
            processQuiz();
        }
    });

})();