JanitorAI Context Maker with Nested Groups

Adds a Location and Character System to JanitorAI with nested grouping functionality

נכון ליום 27-09-2024. ראה הגרסה האחרונה.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

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

(I already have a user script manager, let me install it!)

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.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         JanitorAI Context Maker with Nested Groups
// @namespace    http://tampermonkey.net/
// @version      3.2
// @license MIT
// @description  Adds a Location and Character System to JanitorAI with nested grouping functionality
// @match        https://janitorai.com/chats/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=https://janitorai.com/
// @grant        GM.setValue
// @grant        GM.getValue
// ==/UserScript==

(async function() {
    'use strict';

    // Define Themes
    const themes = {
        dark: {
            '--bg-color': 'rgba(34, 34, 34, var(--ui-transparency))',
            '--text-color': '#ffffff',
            '--border-color': 'rgba(68, 68, 68, var(--ui-transparency))',
            '--button-bg-color': 'rgba(0, 123, 255, var(--ui-transparency))',
            '--active-char-color': 'rgba(173, 216, 230, var(--ui-transparency))',
            '--success-bg-color': 'rgba(40, 167, 69, var(--ui-transparency))',
            '--info-bg-color': 'rgba(23, 162, 184, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(255, 193, 7, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(108, 117, 125, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(220, 53, 69, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.5)',
            '--link-color': '#8cb3ff',
            '--code-bg-color': 'rgba(0, 0, 0, 0.3)',
            '--code-text-color': '#ff9d00'
        },
        light: {
            '--bg-color': 'rgba(255, 255, 255, var(--ui-transparency))',
            '--text-color': '#000000',
            '--border-color': 'rgba(204, 204, 204, var(--ui-transparency))',
            '--button-bg-color': 'rgba(0, 123, 255, var(--ui-transparency))',
            '--active-char-color': 'rgba(173, 216, 230, var(--ui-transparency))',
            '--success-bg-color': 'rgba(40, 167, 69, var(--ui-transparency))',
            '--info-bg-color': 'rgba(23, 162, 184, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(255, 193, 7, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(108, 117, 125, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(220, 53, 69, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.1)',
            '--link-color': '#007bff',
            '--code-bg-color': 'rgba(0, 0, 0, 0.05)',
            '--code-text-color': '#d63384'
        },
        sepia_light: {
            '--bg-color': 'rgba(244, 232, 208, var(--ui-transparency))',
            '--text-color': '#2e241c',
            '--border-color': 'rgba(193, 154, 107, var(--ui-transparency))',
            '--button-bg-color': 'rgba(160, 82, 45, var(--ui-transparency))',
            '--active-char-color': 'rgba(210, 180, 140, var(--ui-transparency))',
            '--success-bg-color': 'rgba(107, 68, 35, var(--ui-transparency))',
            '--info-bg-color': 'rgba(194, 148, 110, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(215, 172, 116, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(160, 130, 94, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(168, 96, 50, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.3)',
            '--link-color': '#6c757d',
            '--code-bg-color': 'rgba(0, 0, 0, 0.1)',
            '--code-text-color': '#a0522d'
        },
        sepia_dark: {
            '--bg-color': 'rgba(60, 45, 31, var(--ui-transparency))',
            '--text-color': '#d8c6b2',
            '--border-color': 'rgba(102, 75, 50, var(--ui-transparency))',
            '--button-bg-color': 'rgba(139, 69, 19, var(--ui-transparency))',
            '--active-char-color': 'rgba(210, 180, 140, var(--ui-transparency))',
            '--success-bg-color': 'rgba(107, 68, 35, var(--ui-transparency))',
            '--info-bg-color': 'rgba(139, 101, 68, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(205, 133, 63, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(122, 91, 62, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(165, 42, 42, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.6)',
            '--link-color': '#d2b48c',
            '--code-bg-color': 'rgba(0, 0, 0, 0.3)',
            '--code-text-color': '#deb887'
        },
        solarized_light: {
            '--bg-color': 'rgba(253, 246, 227, var(--ui-transparency))',
            '--text-color': '#47565c',
            '--border-color': 'rgba(238, 232, 213, var(--ui-transparency))',
            '--button-bg-color': 'rgba(38, 139, 210, var(--ui-transparency))',
            '--active-char-color': 'rgba(133, 153, 0, var(--ui-transparency))',
            '--success-bg-color': 'rgba(133, 153, 0, var(--ui-transparency))',
            '--info-bg-color': 'rgba(38, 139, 210, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(181, 137, 0, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(147, 161, 161, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(220, 50, 47, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.2)',
            '--link-color': '#2aa198',
            '--code-bg-color': 'rgba(0, 43, 54, 0.7)',
            '--code-text-color': '#cb4b16'
        },
        solarized_dark: {
            '--bg-color': 'rgba(0, 43, 54, var(--ui-transparency))',
            '--text-color': '#eee8d5',
            '--border-color': 'rgba(7, 54, 66, var(--ui-transparency))',
            '--button-bg-color': 'rgba(38, 139, 210, var(--ui-transparency))',
            '--active-char-color': 'rgba(133, 153, 0, var(--ui-transparency))',
            '--success-bg-color': 'rgba(133, 153, 0, var(--ui-transparency))',
            '--info-bg-color': 'rgba(38, 139, 210, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(181, 137, 0, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(88, 110, 117, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(220, 50, 47, var(--ui-transparency))',
            '--shadow-color': 'rgba(0, 0, 0, 0.4)',
            '--link-color': '#2aa198',
            '--code-bg-color': 'rgba(253, 246, 227, 0.1)',
            '--code-text-color': '#cb4b16'
        },
        forest_light: {
            '--bg-color': 'rgba(233, 245, 233, var(--ui-transparency))',
            '--text-color': '#2f4f2f',
            '--border-color': 'rgba(209, 230, 209, var(--ui-transparency))',
            '--button-bg-color': 'rgba(60, 179, 113, var(--ui-transparency))',
            '--active-char-color': 'rgba(34, 139, 34, var(--ui-transparency))',
            '--success-bg-color': 'rgba(144, 238, 144, var(--ui-transparency))',
            '--info-bg-color': 'rgba(60, 179, 113, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(240, 230, 140, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(152, 251, 152, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(205, 92, 92, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.2)',
            '--link-color': '#3cb371',
            '--code-bg-color': 'rgba(0, 0, 0, 0.1)',
            '--code-text-color': '#8b4513'
        },
        forest_dark: {
            '--bg-color': 'rgba(34, 49, 34, var(--ui-transparency))',
            '--text-color': '#e0f7e9',
            '--border-color': 'rgba(46, 61, 46, var(--ui-transparency))',
            '--button-bg-color': 'rgba(60, 179, 113, var(--ui-transparency))',
            '--active-char-color': 'rgba(144, 238, 144, var(--ui-transparency))',
            '--success-bg-color': 'rgba(34, 139, 34, var(--ui-transparency))',
            '--info-bg-color': 'rgba(144, 238, 144, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(189, 183, 107, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(85, 107, 47, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(139, 69, 19, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.4)',
            '--link-color': '#8fbc8f',
            '--code-bg-color': 'rgba(0, 0, 0, 0.3)',
            '--code-text-color': '#ffd700'
        },
        ocean_light: {
            '--bg-color': 'rgba(28, 107, 160, var(--ui-transparency))',
            '--text-color': '#ffffff',
            '--border-color': 'rgba(54, 144, 192, var(--ui-transparency))',
            '--button-bg-color': 'rgba(0, 123, 255, var(--ui-transparency))',
            '--active-char-color': 'rgba(173, 216, 230, var(--ui-transparency))',
            '--success-bg-color': 'rgba(60, 179, 113, var(--ui-transparency))',
            '--info-bg-color': 'rgba(23, 162, 184, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(255, 193, 7, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(108, 117, 125, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(220, 53, 69, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.3)',
            '--link-color': '#00ffff',
            '--code-bg-color': 'rgba(0, 0, 0, 0.2)',
            '--code-text-color': '#ff7f50'
        },
        ocean_dark: {
            '--bg-color': 'rgba(0, 30, 60, var(--ui-transparency))',
            '--text-color': '#ffffff',
            '--border-color': 'rgba(0, 53, 102, var(--ui-transparency))',
            '--button-bg-color': 'rgba(0, 123, 255, var(--ui-transparency))',
            '--active-char-color': 'rgba(135, 206, 235, var(--ui-transparency))',
            '--success-bg-color': 'rgba(46, 139, 87, var(--ui-transparency))',
            '--info-bg-color': 'rgba(0, 96, 100, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(255, 140, 0, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(47, 79, 79, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(139, 0, 0, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.5)',
            '--link-color': '#00ffff',
            '--code-bg-color': 'rgba(0, 0, 0, 0.4)',
            '--code-text-color': '#ff7f50'
        },
        terminal: {
            '--bg-color': 'rgba(0, 0, 0, var(--ui-transparency))',
            '--text-color': '#00ff00',
            '--border-color': 'rgba(0, 200, 0, var(--ui-transparency))',
            '--button-bg-color': 'rgba(0, 125, 0, var(--ui-transparency))',
            '--active-char-color': 'rgba(0, 75, 0, var(--ui-transparency))',
            '--success-bg-color': 'rgba(0, 128, 0, var(--ui-transparency))',
            '--info-bg-color': 'rgba(0, 125, 0, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(100, 125, 0, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(0, 128, 0, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(100, 0, 0, var(--ui-transparency))',
            '--shadow-color': 'rgba(0, 50, 0, 0.5)',
            '--link-color': '#00ffff',
            '--code-bg-color': 'rgba(0, 0, 0, 0.8)',
            '--code-text-color': '#7fff00'
        },
        retro: {
            '--bg-color': 'rgba(196, 182, 187, var(--ui-transparency))',
            '--text-color': '#191919',
            '--border-color': 'rgba(128, 128, 128, var(--ui-transparency))',
            '--button-bg-color': 'rgba(255, 105, 180, var(--ui-transparency))',
            '--active-char-color': 'rgba(255, 255, 0, var(--ui-transparency))',
            '--success-bg-color': 'rgba(50, 205, 50, var(--ui-transparency))',
            '--info-bg-color': 'rgba(135, 206, 235, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(255, 165, 0, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(128, 128, 128, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(255, 0, 0, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.3)',
            '--link-color': '#1e90ff',
            '--code-bg-color': 'rgba(0, 0, 0, 0.1)',
            '--code-text-color': '#ff1493'
        },
        neon: {
            '--bg-color': 'rgba(0, 0, 0, var(--ui-transparency))',
            '--text-color': '#ffffff',
            '--border-color': 'rgba(0, 255, 255, var(--ui-transparency))',
            '--button-bg-color': 'rgba(255, 0, 255, var(--ui-transparency))',
            '--active-char-color': 'rgba(0, 255, 0, var(--ui-transparency))',
            '--success-bg-color': 'rgba(0, 255, 0, var(--ui-transparency))',
            '--info-bg-color': 'rgba(0, 255, 255, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(255, 255, 0, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(255, 0, 255, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(255, 0, 0, var(--ui-transparency))',
            '--shadow-color': 'rgba(0, 255, 255, 0.5)',
            '--link-color': '#ff00ff',
            '--code-bg-color': 'rgba(0, 0, 0, 0.8)',
            '--code-text-color': '#00ffff'
        },
        vintage: {
            '--bg-color': 'rgba(240, 230, 140, var(--ui-transparency))',
            '--text-color': '#360505',
            '--border-color': 'rgba(139, 69, 19, var(--ui-transparency))',
            '--button-bg-color': 'rgba(128, 0, 0, var(--ui-transparency))',
            '--active-char-color': 'rgba(255, 215, 0, var(--ui-transparency))',
            '--success-bg-color': 'rgba(50, 205, 50, var(--ui-transparency))',
            '--info-bg-color': 'rgba(70, 130, 180, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(218, 165, 32, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(128, 128, 0, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(178, 34, 34, var(--ui-transparency))',
            '--shadow-color': 'rgba(139, 69, 19, 0.5)',
            '--link-color': '#8b0000',
            '--code-bg-color': 'rgba(245, 222, 179, 0.5)',
            '--code-text-color': '#8b0000'
        },
        pastel: {
            '--bg-color': 'rgba(255, 228, 225, var(--ui-transparency))',
            '--text-color': '#4d4d4d',
            '--border-color': 'rgba(255, 192, 203, var(--ui-transparency))',
            '--button-bg-color': 'rgba(135, 206, 235, var(--ui-transparency))',
            '--active-char-color': 'rgba(175, 238, 238, var(--ui-transparency))',
            '--success-bg-color': 'rgba(152, 251, 152, var(--ui-transparency))',
            '--info-bg-color': 'rgba(135, 206, 235, var(--ui-transparency))',
            '--warning-bg-color': 'rgba(255, 228, 181, var(--ui-transparency))',
            '--muted-bg-color': 'rgba(238, 130, 238, var(--ui-transparency))',
            '--danger-bg-color': 'rgba(240, 128, 128, var(--ui-transparency))',
            '--shadow-color': 'rgba(0,0,0,0.1)',
            '--link-color': '#ff69b4',
            '--code-bg-color': 'rgba(255, 250, 205, 0.8)',
            '--code-text-color': '#dc143c'
        }
    };

    // Initialize CSS variables
    function setTheme(themeName) {
        const theme = themes[themeName];
        Object.keys(theme).forEach(key => {
            document.documentElement.style.setProperty(key, theme[key]);
        });
    }

    // Retrieve saved settings or set defaults
    const defaultTransparency = await GM.getValue('transparency', '0.9');
    const defaultTheme = await GM.getValue('theme', 'dark');

    // Initialize transparency and theme
    document.documentElement.style.setProperty('--ui-transparency', defaultTransparency);
    setTheme(defaultTheme);

    // Add placeholder styles
    const style = document.createElement('style');
    style.innerHTML = `
    input::placeholder, textarea::placeholder {
        color: var(--text-color);
    }
    input:-ms-input-placeholder, textarea:-ms-input-placeholder {
        color: var(--text-color);
    }
    input::-ms-input-placeholder, textarea::-ms-input-placeholder {
        color: var(--text-color);
    }
    input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
        color: var(--text-color);
    }
    `;
    document.head.appendChild(style);

    // --- Context Menu and Tool Buttons ---
    const menuButtonsContainer = document.createElement('div');
    menuButtonsContainer.style.cssText = `
        position: fixed;
        top: 10px;
        left: 50%;
        transform: translateX(-50%);
        display: flex;
        justify-content: center;
        z-index: 10000;
    `;
    document.body.appendChild(menuButtonsContainer);

    const contextMenuButton = document.createElement('button');
    contextMenuButton.textContent = '⚙️';
    contextMenuButton.title = 'Menu';
    contextMenuButton.style.cssText = `
        width: 40px;
        height: 40px;
        margin-right: 5px;
        padding: 0;
        border: none;
        background-color: var(--button-bg-color);
        color: var(--text-color);
        border-radius: 50%;
        font-size: 24px;
        cursor: pointer;
        z-index: 10000;
    `;
    menuButtonsContainer.appendChild(contextMenuButton);

    const toolButtonsData = [
        { emoji: '🧮', title: 'Calculator', iframeSrc: 'https://www.desmos.com/fourfunction', id: 'calculator' },
        { emoji: '🎲', title: 'Dice Roller', iframeSrc: '', id: 'dice' },
        { emoji: '🎮', title: 'Game', iframeSrc: 'https://freepacman.org/', id: 'game' },
    ];

    toolButtonsData.forEach(tool => {
        const button = document.createElement('button');
        button.textContent = tool.emoji;
        button.title = tool.title;
        button.style.cssText = `
            width: 40px;
            height: 40px;
            margin-right: 5px;
            padding: 0;
            border: none;
            background-color: var(--button-bg-color);
            color: var(--text-color);
            border-radius: 50%;
            font-size: 24px;
            cursor: pointer;
        `;
        button.addEventListener('click', () => {
            openToolWindow(tool);
        });
        menuButtonsContainer.appendChild(button);
    });

    const openWindows = new Set();

    function openToolWindow(tool) {
        if (openWindows.has(tool.id)) {
            return;
        }

        // Create the window container
        const windowContainer = document.createElement('div');
        windowContainer.style.cssText = `
        position: fixed;
        top: 100px;
        left: 100px;
        width: 500px;
        height: 400px;
        background-color: var(--bg-color);
        border: 1px solid var(--border-color);
        box-shadow: 0 0 10px var(--shadow-color);
        border-radius: 5px;
        z-index: 10002;
        display: flex;
        flex-direction: column;
    `;

        // Add a header with the title and close button
        const header = document.createElement('div');
        header.style.cssText = `
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 5px;
        background-color: var(--button-bg-color);
        color: var(--text-color);
        cursor: move;
    `;
        const title = document.createElement('span');
        title.textContent = tool.title;
        header.appendChild(title);
        const closeButton = document.createElement('button');
        closeButton.textContent = '✖️';
        closeButton.style.cssText = `
        background: none;
        border: none;
        color: var(--text-color);
        cursor: pointer;
    `;
        closeButton.addEventListener('click', () => {
            document.body.removeChild(windowContainer);
            openWindows.delete(tool.id);
        });
        header.appendChild(closeButton);

        windowContainer.appendChild(header);

        // Add iframe
        const iframe = document.createElement('iframe');
        iframe.style.cssText = `
    flex-grow: 1;
    width: 100%;
    border: none;
    background-color: var(--bg-color);
    color: var(--text-color);
`;
        let src = tool.iframeSrc;

        // Adjust dice URL based on theme
        if (tool.id === 'dice') {
            const dicehex = getComputedHexValue('--button-bg-color').slice(1);
            const chromahex = getComputedHexValue('--bg-color').slice(1);
            const labelhex = getComputedHexValue('--text-color').slice(1);
            src = `https://dice.bee.ac/?dicehex=${dicehex}&chromahex=${chromahex}&labelhex=${labelhex}`;
        }

        // Adjust calculator URL based on theme
        if (tool.id === 'calculator') {
            const bgColor = getComputedHexValue('--bg-color').slice(1);
            const textColor = getComputedHexValue('--text-color').slice(1);
            const buttonBgColor = getComputedHexValue('--button-bg-color').slice(1);
            src = `https://www.desmos.com/fourfunction?backgroundColor=${bgColor}&textColor=${textColor}&buttonBackgroundColor=${buttonBgColor}`;
        }

        iframe.src = src;
        windowContainer.appendChild(iframe);

        // Make window draggable
        makeElementDraggable(windowContainer, header);

        document.body.appendChild(windowContainer);
        openWindows.add(tool.id);

        document.body.appendChild(windowContainer);
        openWindows.add(tool.id);
    }

    function getComputedHexValue(variableName) {
        const computedStyle = getComputedStyle(document.documentElement);
        const colorValue = computedStyle.getPropertyValue(variableName).trim();

        // Create a temporary div to get the computed color
        const tempDiv = document.createElement('div');
        tempDiv.style.color = colorValue;
        document.body.appendChild(tempDiv);
        const computedColor = getComputedStyle(tempDiv).color;
        document.body.removeChild(tempDiv);

        // Now computedColor is in 'rgb(r, g, b)' or 'rgba(r, g, b, a)' format
        const rgba = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);

        if (rgba) {
            const r = parseInt(rgba[1]).toString(16).padStart(2, '0');
            const g = parseInt(rgba[2]).toString(16).padStart(2, '0');
            const b = parseInt(rgba[3]).toString(16).padStart(2, '0');
            return `#${r}${g}${b}`;
        } else {
            // Fallback to default
            return '#FFFFFF';
        }
    }

    function makeElementDraggable(elmnt, handle) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        if (handle) {
            handle.onmousedown = dragMouseDown;
        } else {
            elmnt.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;
            elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
            elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
        }

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

    // Helper functions for tooltip
    let tooltipElement = null;

    function showTooltip(event, content, set) {
        hideTooltip(); // Remove existing tooltip if any

        // Create new tooltip element
        tooltipElement = document.createElement('div');
        tooltipElement.style.cssText = `
        position: absolute;
        z-index: 10000;
        background-color: var(--bg-color);
        color: var(--text-color);
        border: 1px solid var(--border-color);
        padding: 5px;
        border-radius: 5px;
        font-size: 12px;
        max-width: 800px;
        white-space: pre-wrap;
        box-shadow: 0 0 10px var(--shadow-color);
    `;
        tooltipElement.innerHTML = content;

        // Append the tooltip to the body first to get its size
        document.body.appendChild(tooltipElement);

        // Position the tooltip near the element
        const rect = event.currentTarget.getBoundingClientRect();

        if (!set) {
            // Tooltip to the right of the element
            tooltipElement.style.left = `${rect.right + 125}px`;
            tooltipElement.style.top = `${rect.top - 10}px`;
        } else {
            // Tooltip to the left of the element
            const tooltipWidth = tooltipElement.offsetWidth; // Get the tooltip width after it's appended
            tooltipElement.style.left = `${rect.left - tooltipWidth - 72}px`; // Adjust to the left
            tooltipElement.style.top = `${rect.top - 10}px`;
        }

        // Adjust position if the tooltip goes off screen
        const tooltipRect = tooltipElement.getBoundingClientRect();
        if (tooltipRect.right > window.innerWidth) {
            tooltipElement.style.left = `${window.innerWidth - tooltipRect.width - 10}px`;
        }
        if (tooltipRect.left < 0) {
            tooltipElement.style.left = `10px`; // Move it a bit to the right if it goes off screen on the left
        }
        if (tooltipRect.bottom > window.innerHeight) {
            tooltipElement.style.top = `${window.innerHeight - tooltipRect.height - 10}px`;
        }
    }

    function hideTooltip() {
        if (tooltipElement && tooltipElement.parentNode) {
            tooltipElement.parentNode.removeChild(tooltipElement);
            tooltipElement = null; // Set to null after removing
        }
    }

    // --- Context Panel ---
    const contextPanel = document.createElement('div');
    contextPanel.id = 'context-panel';
    contextPanel.style.cssText = `
    position: fixed; /* Keep position fixed to center the panel */
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 400px;
    padding: 20px;
    background-color: var(--bg-color);
    border: 1px solid var(--border-color);
    box-shadow: 0 0 10px var(--shadow-color);
    border-radius: 5px;
    display: none;
    z-index: 10001;
    /* Remove position: relative; */
`;
    document.body.appendChild(contextPanel);

    // Add close button to contextPanel
    const contextCloseButton = document.createElement('button');
    contextCloseButton.textContent = '✖️';
    contextCloseButton.style.cssText = `
        position: absolute;
        top: 10px;
        right: 10px;
        background: none;
        border: none;
        font-size: 20px;
        cursor: pointer;
        color: var(--text-color);
    `;
    contextCloseButton.addEventListener('click', () => {
        contextPanel.style.display = 'none';
    });
    contextPanel.appendChild(contextCloseButton);

    const transparencyLabel = document.createElement('label');
    transparencyLabel.textContent = 'UI Transparency';
    transparencyLabel.style.cssText = `
        color: var(--text-color);
        display: block;
        margin-bottom: 5px;
    `;
    contextPanel.appendChild(transparencyLabel);

    const transparencySlider = document.createElement('input');
    transparencySlider.type = 'range';
    transparencySlider.min = '0.1';
    transparencySlider.max = '1';
    transparencySlider.step = '0.1';
    transparencySlider.value = defaultTransparency;
    transparencySlider.style.cssText = `
        width: 100%;
        margin-bottom: 10px;
    `;
    transparencySlider.addEventListener('input', () => {
        document.documentElement.style.setProperty('--ui-transparency', transparencySlider.value);
        // Re-apply current theme to update transparency
        setTheme(themeDropdown.value);
        GM.setValue('transparency', transparencySlider.value);
    });
    contextPanel.appendChild(transparencySlider);

    const dropperLabel = document.createElement('label');
    dropperLabel.textContent = 'UI Theme';
    dropperLabel.style.cssText = `
        color: var(--text-color);
        display: block;
        margin-bottom: 5px;
    `;
    contextPanel.appendChild(dropperLabel);

    const themeDropdown = document.createElement('select');
    themeDropdown.style.cssText = `
        width: 100%;
        padding: 5px;
        margin-bottom: 10px;
        border: 1px solid var(--border-color);
        border-radius: 5px;
        background-color: var(--bg-color);
        color: var(--text-color);
    `;
    Object.keys(themes).forEach(theme => {
        const option = document.createElement('option');
        option.value = theme;
        option.textContent = theme.charAt(0).toUpperCase() + theme.slice(1);
        themeDropdown.appendChild(option);
    });

    themeDropdown.value = defaultTheme;

    themeDropdown.addEventListener('change', () => {
        setTheme(themeDropdown.value);
        GM.setValue('theme', themeDropdown.value);
    });
    contextPanel.appendChild(themeDropdown);

    // Add divider
    const divider = document.createElement('hr');
    divider.style.cssText = `
        border: none;
        border-top: 1px solid var(--border-color);
        margin: 10px 0;
    `;
    contextPanel.appendChild(divider);

    const contextLabel = document.createElement('label');
    contextLabel.textContent = 'Primary Context';
    contextLabel.style.cssText = `
        color: var(--text-color);
        display: block;
        margin-bottom: 5px;
    `;
    contextPanel.appendChild(contextLabel);

    const primaryContextInput = document.createElement('textarea');
    primaryContextInput.placeholder = 'Primary context goes here...';
    primaryContextInput.style.cssText = `
        width: 100%;
        height: 100px;
        margin-bottom: 10px;
        padding: 10px;
        border: 1px solid var(--border-color);
        border-radius: 5px;
        box-sizing: border-box;
        background-color: var(--bg-color);
        color: var(--text-color);
    `;
    contextPanel.appendChild(primaryContextInput);

    // Define the sleep function
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    const updateContextButton = document.createElement('button');
    updateContextButton.textContent = 'Update Context';
    updateContextButton.style.cssText = `
        width: 100%;
        padding: 10px;
        border: none;
        background-color: var(--success-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;

    updateContextButton.addEventListener('click', async () => {
        const primaryContext = primaryContextInput.value;
        var fullContext = `Context;\n"` + primaryContext + `"\n`;
        fullContext += `\n` + window.getContext();
        console.log("setting context; " + fullContext);

        window.manuClick('//*[@id="menu-button-:rb:"]');
        await sleep(250);

        window.manuClick('//*[@id="menu-list-:rb:-menuitem-:ru:"]');
        await sleep(250);

        window.manuWrite("/html/body/div[9]/div[3]/div/section/div/textarea", fullContext);
        await sleep(250);

        window.manuClick("/html/body/div[9]/div[3]/div/section/footer/button[2]");
    });

    window.manuWrite = function(xpath, text) {
        var result = document.evaluate(
            xpath,
            document,
            null,
            XPathResult.FIRST_ORDERED_NODE_TYPE,
            null
        );

        var node = result.singleNodeValue;

        if (node) {
            node.focus();

            // Since the node is an HTMLTextAreaElement, get the value setter from its prototype
            const nativeTextAreaValueSetter = Object.getOwnPropertyDescriptor(
                window.HTMLTextAreaElement.prototype,
                'value'
            ).set;

            nativeTextAreaValueSetter.call(node, text);

            // Dispatch the 'input' event to simulate user input
            var event = new Event('input', { bubbles: true });
            node.dispatchEvent(event);

        } else {
            console.error("Node not found for XPath:", xpath);
        }
    }

    window.manuClick = function(xpath) {
        var result = document.evaluate(
            xpath,
            document,
            null,
            XPathResult.FIRST_ORDERED_NODE_TYPE,
            null
        );

        var node = result.singleNodeValue;

        if (node) {
            node.click();
        }
    }

    contextPanel.appendChild(updateContextButton);

    contextMenuButton.addEventListener('click', () => {
        contextPanel.style.display = contextPanel.style.display === 'none' ? 'block' : 'none';
    });

    // Helper function to find the active location recursively
    function findActiveLocation(items) {
        for (const item of items) {
            if (item.active) {
                return item;
            }
            if (item.children && item.children.length > 0) {
                const activeChild = findActiveLocation(item.children);
                if (activeChild) {
                    return activeChild;
                }
            }
        }
        return null;
    }

    // Helper function to collect all active characters recursively
    function collectActiveCharacters(items, result = []) {
        for (const item of items) {
            if (item.active) {
                result.push(item);
            }
            if (item.children && item.children.length > 0) {
                collectActiveCharacters(item.children, result);
            }
        }
        return result;
    }

    // Modify the getContext function to utilize the helper functions
    window.getContext = function() {
        const activeLocation = findActiveLocation(locationGroups.flatMap(g => g.items));
        if (!activeLocation) return '';

        let context = ``;

        if (plotInput && plotInput.value.trim() !== '') {
            context += `Plot:\n"${plotInput.value}"\n`;
        } else {
            context += `Plot:\n"No specific plot."\n`;
        }

        context += `\nSetting;\n"${activeLocation.name}" (${timeInput.value}, ${weatherInput.value}):\n`
        context += `\u0009"${activeLocation.description}"\n`;

        context += `\n{{user}}'s characters;\n`;

        const activeUserCharacters = collectActiveCharacters(characterGroups.flatMap(g => g.items)).filter(char => char.userControlled);

        activeUserCharacters.forEach(char => {
            context += `"${char.name}" (${char.sex}, ${char.species}, ${char.age}, ${char.bodyType}, ${char.personality}):\n`;
            context += `\u0009"${char.bio}"\n`;
        });

        context += `\n{{char}}'s characters;\n`;

        const activeCharCharacters = collectActiveCharacters(characterGroups.flatMap(g => g.items)).filter(char => !char.userControlled);

        activeCharCharacters.forEach(char => {
            context += `"${char.name}" (${char.sex}, ${char.species}, ${char.age}, ${char.bodyType}, ${char.personality}):\n`;
            context += `\u0009"${char.bio}"\n`;
        });

        return context;
    };

    // --- Character Sidebar with Groups and Nested Characters ---
    const characterSidebar = document.createElement('div');
    characterSidebar.id = 'character-sheet-sidebar';
    characterSidebar.style.cssText = `
        position: fixed;
        top: 0;
        right: -350px;
        width: 350px;
        height: 100%;
        display: flex;
        flex-direction: column;
        background-color: var(--bg-color);
        border-left: 2px solid var(--border-color);
        box-shadow: -2px 0 5px var(--shadow-color);
        box-sizing: border-box;
        transition: right 0.3s;
        z-index: 9999;
    `;
    document.body.appendChild(characterSidebar);

    const characterToggleButton = document.createElement('button');
    characterToggleButton.textContent = '☰';
    characterToggleButton.style.cssText = `
        position: fixed;
        top: 10px;
        right: 10px;
        padding: 5px 10px;
        border: none;
        background-color: var(--button-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
        transition: right 0.3s;
        z-index: 10000;
    `;
    characterToggleButton.addEventListener('click', () => {
        const isOpen = characterSidebar.style.right === '0px';
        characterSidebar.style.right = isOpen ? '-350px' : '0';
        characterToggleButton.style.right = isOpen ? '10px' : '360px';
    });
    document.body.appendChild(characterToggleButton);

    const characterHeader = document.createElement('div');
    characterHeader.style.cssText = `
        padding: 10px;
        background-color: var(--border-color);
        text-align: center;
        font-weight: bold;
        color: var(--text-color);
    `;
    characterHeader.textContent = 'Characters';
    characterSidebar.appendChild(characterHeader);

    const characterButtonBox = document.createElement('div');
    characterButtonBox.style.cssText = `
        display: flex;
        justify-content: space-between;
        padding: 10px;
        background-color: var(--bg-color);
        flex-shrink: 0;
    `;
    characterSidebar.appendChild(characterButtonBox);

    // New Character Button
    const newCharacterButton = document.createElement('button');
    newCharacterButton.textContent = 'New';
    newCharacterButton.title = 'Create New Character';
    newCharacterButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--success-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    newCharacterButton.addEventListener('click', () => {
        createNewCharacter();
    });
    characterButtonBox.appendChild(newCharacterButton);

    // Load Character Button
    const loadCharacterButton = document.createElement('button');
    loadCharacterButton.textContent = 'Load';
    loadCharacterButton.title = 'Load a Character';
    loadCharacterButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--info-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    loadCharacterButton.addEventListener('click', () => {
        loadCharacter();
    });
    characterButtonBox.appendChild(loadCharacterButton);

    // Group Character Button
    const groupCharacterButton = document.createElement('button');
    groupCharacterButton.textContent = 'Group';
    groupCharacterButton.title = 'Create New Group';
    groupCharacterButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--info-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    groupCharacterButton.addEventListener('click', () => {
        createNewCharacterGroup();
    });
    characterButtonBox.appendChild(groupCharacterButton);

    // Import Character Button
    const importCharacterButton = document.createElement('button');
    importCharacterButton.textContent = 'Import';
    importCharacterButton.title = 'Import Characters';
    importCharacterButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--warning-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    importCharacterButton.addEventListener('click', () => {
        importCharacters();
    });
    characterButtonBox.appendChild(importCharacterButton);

    // Export Character Button
    const exportCharacterButton = document.createElement('button');
    exportCharacterButton.textContent = 'Export';
    exportCharacterButton.title = 'Export Characters';
    exportCharacterButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--muted-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    exportCharacterButton.addEventListener('click', () => {
        exportCharacters();
    });
    characterButtonBox.appendChild(exportCharacterButton);

    // Add fifth button: "Load" for Character
    function loadCharacter() {
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = '.json';
        fileInput.addEventListener('change', async (event) => {
            const file = event.target.files[0];
            const reader = new FileReader();
            reader.onload = (e) => {
                try {
                    const character = JSON.parse(e.target.result);
                    if (character && character.id) {
                        // Add to Ungrouped
                        const ungrouped = characterGroups.find(g => g.name === 'Ungrouped');
                        if (ungrouped) {
                            ungrouped.items.push(character);
                        } else {
                            characterGroups[0].items.push(character);
                        }
                        renderCharacterGroups();
                    } else {
                        alert('Invalid character format.');
                    }
                } catch (error) {
                    alert('Failed to load character: ' + error.message);
                }
            };
            reader.readAsText(file);
        });
        fileInput.click();
    }

    const characterGroupList = document.createElement('div');
    characterGroupList.id = 'character-group-list';
    characterGroupList.style.cssText = `
        flex-grow: 1;
        overflow-y: auto;
        padding: 10px;
    `;
    characterSidebar.appendChild(characterGroupList);

    // Initialize Character Groups
    let characterGroups = [
        { name: 'Ungrouped', items: [], collapsed: false }
    ];

    // Function to create a new Character
    function createNewCharacter() {
        const newCharacter = {
            id: generateId(),
            active: true,
            emoji: '😀',
            name: 'New Character',
            sex: '',
            species: '',
            age: '',
            bodyType: '',
            personality: '',
            bio: '',
            userControlled: false,
            children: [],
            collapsed: false
        };
        // Add to Ungrouped
        const ungrouped = characterGroups.find(g => g.name === 'Ungrouped');
        if (ungrouped) {
            ungrouped.items.push(newCharacter);
        } else {
            characterGroups[0].items.push(newCharacter);
        }
        renderCharacterGroups();
    }

    // Function to create a new Character Group
    function createNewCharacterGroup() {
        const groupName = prompt('Enter group name:', `Group ${characterGroups.length}`);
        if (groupName && groupName.trim() !== '') {
            characterGroups.push({ name: groupName.trim(), items: [], collapsed: false });
            renderCharacterGroups();
        }
    }

    // Function to render Character Groups and Items
    function renderCharacterGroups() {
        characterGroupList.innerHTML = '';

        characterGroups.forEach((group, groupIndex) => {
            // Sort items alphabetically by name
            group.items.sort((a, b) => a.name.localeCompare(b.name));

            const groupContainer = document.createElement('div');
            groupContainer.className = 'character-group';
            groupContainer.style.cssText = `
                margin-bottom: 10px;
                border: 1px solid var(--border-color);
                border-radius: 5px;
                background-color: var(--active-char-color);
            `;

            const groupHeader = document.createElement('div');
            groupHeader.style.cssText = `
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 5px 10px;
                background-color: var(--button-bg-color);
                color: var(--text-color);
                cursor: pointer;
                user-select: none;
                position: relative;
            `;
            groupHeader.textContent = group.name;
            groupHeader.addEventListener('click', () => {
                group.collapsed = !group.collapsed;
                renderCharacterGroups();
            });

            const groupActions = document.createElement('div');
            groupActions.style.cssText = `
                display: flex;
                align-items: center;
            `;

            // Activate/Deactivate All Button
            const toggleAllButton = document.createElement('button');
            toggleAllButton.title = 'Activate/Deactivate All';
            toggleAllButton.style.cssText = `
                background: none;
                border: none;
                color: var(--text-color);
                cursor: pointer;
                margin-right: 3px;
                font-size: 16px;
            `;
            updateToggleAllButton(toggleAllButton, group);
            toggleAllButton.addEventListener('click', (e) => {
                e.stopPropagation();
                toggleAllGroupCharacters(group);
                updateToggleAllButton(toggleAllButton, group);
                renderCharacterGroups();
            });
            groupActions.appendChild(toggleAllButton);

            // Rename Group Button
            const renameGroupButton = document.createElement('button');
            renameGroupButton.textContent = '✏️';
            renameGroupButton.title = 'Rename Group';
            renameGroupButton.style.cssText = `
                background: none;
                border: none;
                color: var(--text-color);
                cursor: pointer;
                margin-right: 2px;
            `;
            renameGroupButton.addEventListener('click', (e) => {
                e.stopPropagation();
                renameGroup(groupIndex);
            });
            groupActions.appendChild(renameGroupButton);

            // Delete Group Button
            const deleteGroupButton = document.createElement('button');
            deleteGroupButton.textContent = '🗑️';
            deleteGroupButton.title = 'Delete Group';
            deleteGroupButton.style.cssText = `
                background: none;
                border: none;
                color: var(--text-color);
                cursor: pointer;
            `;
            deleteGroupButton.addEventListener('click', (e) => {
                e.stopPropagation();
                deleteGroup(groupIndex);
            });
            groupActions.appendChild(deleteGroupButton);

            groupHeader.appendChild(groupActions);
            groupContainer.appendChild(groupHeader);

            if (!group.collapsed) {
                const itemsContainer = document.createElement('div');
                itemsContainer.style.cssText = `
                    padding: 5px 10px;
                    display: block;
                `;
                if (group.items.length === 0) {
                    const emptyInfo = document.createElement('div');
                    emptyInfo.className = 'character-slot';
                    emptyInfo.style.cssText = `
                        display: flex;
                        align-items: center;
                        padding: 10px;
                        border: 1px solid var(--border-color);
                        border-radius: 0px;
                        height: 20px;
                        margin-bottom: 5px;
                        background-color: var(--bg-color);
                        cursor: default;
                    `;

                    const infoText = document.createElement('span');
                    infoText.textContent = `Group is empty`;
                    infoText.style.cssText = `
                        color: var(--text-color);
                    `;

                    emptyInfo.appendChild(infoText);
                    itemsContainer.appendChild(emptyInfo);
                } else {
                    group.items.forEach((character, charIndex) => {
                        const characterSlot = createCharacterSlot(character, groupIndex);
                        itemsContainer.appendChild(characterSlot);
                    });
                }
                groupContainer.appendChild(itemsContainer);
            } else {
                const collapsedInfo = document.createElement('div');
                collapsedInfo.className = 'character-slot';
                collapsedInfo.style.cssText = `
                    display: flex;
                    align-items: center;
                    padding: 10px;
                    margin-bottom: 10px;
                    border: 1px solid var(--border-color);
                    border-radius: 5px;
                    height: 20px;
                    margin-top: 5px;
                    background-color: var(--bg-color);
                    cursor: default;
                    margin-left: 10px;
                    margin-right: 10px;
                `;
                const infoText = document.createElement('span');
                infoText.textContent = `${group.items.length} items hidden`;
                infoText.style.cssText = `
                    color: var(--text-color);
                `;
                collapsedInfo.appendChild(infoText);
                groupContainer.appendChild(collapsedInfo);
            }

            // Add dragover and drop events for grouping
            groupContainer.addEventListener('dragover', (e) => {
                e.preventDefault();
                groupContainer.style.border = `2px dashed var(--info-bg-color)`;
            });

            groupContainer.addEventListener('dragleave', (e) => {
                groupContainer.style.border = `1px solid var(--border-color)`;
            });

            groupContainer.addEventListener('drop', (e) => {
                e.preventDefault();
                groupContainer.style.border = `1px solid var(--border-color)`;
                const data = e.dataTransfer.getData('text/plain');
                const { type, id } = JSON.parse(data);
                if (type === 'character') {
                    moveCharacterToGroup(id, groupIndex);
                }
            });

            characterGroupList.appendChild(groupContainer);
        });

        // Ensure at least one group exists
        if (characterGroups.length === 0) {
            characterGroups.push({ name: 'Ungrouped', items: [], collapsed: false });
            renderCharacterGroups();
        }
    }

    // Function to update the Toggle All Button appearance
    function updateToggleAllButton(button, group) {
        const activeCount = countActiveCharacters(group.items);
        const totalCount = countTotalCharacters(group.items);
        if (activeCount === totalCount && totalCount > 0) {
            // All active
            button.textContent = '🟢';
        } else if (activeCount === 0) {
            // All inactive
            button.textContent = '🔴';
        } else {
            // Mixed
            button.textContent = '🟡';
        }
    }

    function countActiveCharacters(items) {
        let count = 0;
        items.forEach(item => {
            if (item.active) count++;
            if (item.children && item.children.length > 0) {
                count += countActiveCharacters(item.children);
            }
        });
        return count;
    }

    function countTotalCharacters(items) {
        let count = items.length;
        items.forEach(item => {
            if (item.children && item.children.length > 0) {
                count += countTotalCharacters(item.children);
            }
        });
        return count;
    }

    // Function to toggle all characters in a group
    function toggleAllGroupCharacters(group) {
        const allActive = countActiveCharacters(group.items) === countTotalCharacters(group.items);
        toggleCharacters(group.items, !allActive);
    }

    function toggleCharacters(items, state) {
        items.forEach(item => {
            item.active = state;
            if (item.children && item.children.length > 0) {
                toggleCharacters(item.children, state);
            }
        });
    }

    // Function to generate tooltip content for a character
    function getCharacterTooltipContent(character) {
        let content = `<strong>"${character.name}"</strong> <small>(${character.sex || 'Unknown'}, ${character.species || 'Unknown'}, ${character.age || 'Unknown'}, ${character.bodyType || 'Unknown'}, ${character.personality || 'Unknown'}):</small><br><em>"${character.bio || 'No bio available.'}"</em>`;
        return content;
    }

    // Function to create a Character Slot DOM element (recursive)
    function createCharacterSlot(character, groupIndex, parent = null, level = 0) {
        const characterSlot = document.createElement('div');
        characterSlot.className = 'character-slot';
        characterSlot.draggable = true;
        characterSlot.dataset.id = character.id;
        characterSlot.style.cssText = `
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 5px;
            margin-bottom: 5px;
            border: 1px solid var(--border-color);
            border-radius: 5px;
            background-color: ${character.userControlled ? 'var(--active-char-color)' : 'var(--bg-color)'};
            cursor: grab;
            margin-left: ${level * 20}px;
        `;

        // Drag events
        characterSlot.addEventListener('dragstart', (e) => {
            e.stopPropagation();
            e.dataTransfer.setData('text/plain', JSON.stringify({ type: 'character', id: character.id }));
            e.currentTarget.style.opacity = '0.5';
        });

        characterSlot.addEventListener('dragend', (e) => {
            e.currentTarget.style.opacity = '1';
        });

        // Click event for collapsing/expanding
        if (character.children && character.children.length > 0) {
            characterSlot.style.cursor = 'pointer';
            characterSlot.addEventListener('click', (e) => {
                e.stopPropagation();
                character.collapsed = !character.collapsed;
                renderCharacterGroups();
            });
        }

        // Left Div (Active Toggle, Emoji, Name)
        const leftDiv = document.createElement('div');
        leftDiv.style.cssText = `
            display: flex;
            align-items: center;
            flex-grow: 1;
            overflow: hidden;
        `;

        // Remove Collapse/Expand Button
        // (Not needed as per new requirement)

        const activeButton = document.createElement('button');
        activeButton.textContent = character.active ? '🟢' : '🔴';
        activeButton.title = 'Toggle Active';
        activeButton.style.cssText = `
            padding: 3px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
            margin-right: 5px;
        `;
        activeButton.addEventListener('click', (e) => {
            e.stopPropagation();
            character.active = !character.active;
            updateAllToggleButtons();
            renderCharacterGroups();
        });
        leftDiv.appendChild(activeButton);

        const emojiSpan = document.createElement('span');
        emojiSpan.textContent = character.emoji;
        emojiSpan.style.marginRight = '5px';
        leftDiv.appendChild(emojiSpan);

        const nameSpan = document.createElement('span');
        nameSpan.textContent = character.name;
        nameSpan.style.cssText = `
            flex-grow: 1;
            min-width: 0;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
            color: var(--text-color);
        `;

        // Add tooltip event listeners
        nameSpan.addEventListener('mouseenter', (e) => {
            showTooltip(e, getCharacterTooltipContent(character), true);
        });
        nameSpan.addEventListener('mouseleave', hideTooltip);
        nameSpan.addEventListener('dragover', hideTooltip);

        leftDiv.appendChild(nameSpan);

        characterSlot.appendChild(leftDiv);

        // Right Div (Edit, Delete, Export)
        const rightDiv = document.createElement('div');
        rightDiv.style.display = 'flex';
        rightDiv.style.alignItems = 'center';

        const editButton = document.createElement('button');
        editButton.textContent = '✏️';
        editButton.title = 'Edit Character';
        editButton.style.cssText = `
            padding: 0px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
            margin-right: 2px;
        `;
        editButton.addEventListener('click', (e) => {
            e.stopPropagation();
            editCharacter(character);
        });
        rightDiv.appendChild(editButton);

        const deleteButton = document.createElement('button');
        deleteButton.textContent = '🗑️';
        deleteButton.title = 'Delete Character';
        deleteButton.style.cssText = `
            padding: 0px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
            margin-right: 2px;
        `;
        deleteButton.addEventListener('click', (e) => {
            e.stopPropagation();
            deleteCharacter(character.id);
        });
        rightDiv.appendChild(deleteButton);

        const exportButton = document.createElement('button');
        exportButton.textContent = '⬇️';
        exportButton.title = 'Export Character';
        exportButton.style.cssText = `
            padding: 0px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
        `;
        exportButton.addEventListener('click', (e) => {
            e.stopPropagation();
            exportCharacter(character);
        });
        rightDiv.appendChild(exportButton);

        characterSlot.appendChild(rightDiv);

        // Dragover and Drop events
        characterSlot.addEventListener('dragover', (e) => {
            e.preventDefault();
            e.stopPropagation();
            characterSlot.style.border = `2px dashed var(--info-bg-color)`;
        });

        characterSlot.addEventListener('dragleave', (e) => {
            characterSlot.style.border = `1px solid var(--border-color)`;
        });

        characterSlot.addEventListener('drop', (e) => {
            e.preventDefault();
            e.stopPropagation();
            characterSlot.style.border = `1px solid var(--border-color)`;
            const data = e.dataTransfer.getData('text/plain');
            const { type, id } = JSON.parse(data);
            if (type === 'character' && id !== character.id) {
                moveCharacterToParent(id, character);
            }
        });

        // Prevent click on buttons from triggering slot collapse/expand
        activeButton.addEventListener('click', (e) => e.stopPropagation());
        editButton.addEventListener('click', (e) => e.stopPropagation());
        deleteButton.addEventListener('click', (e) => e.stopPropagation());
        exportButton.addEventListener('click', (e) => e.stopPropagation());

        // Recursive rendering of children
        const container = document.createElement('div');
        container.appendChild(characterSlot);

        if (character.children && character.children.length > 0) {
            if (!character.collapsed) {
                character.children.forEach(child => {
                    const childSlot = createCharacterSlot(child, groupIndex, character, level + 1);
                    container.appendChild(childSlot);
                });
            } else {
                const collapsedInfo = document.createElement('div');
                collapsedInfo.className = 'character-slot';
                collapsedInfo.style.cssText = `
                    display: flex;
                    align-items: center;
                    padding: 10px;
                    margin-bottom: 5px;
                    border: 1px solid var(--border-color);
                    border-radius: 5px;
                    background-color: var(--bg-color);
                    height: 20px;
                    cursor: default;
                    margin-left: ${(level + 1) * 20}px;
                `;

                const infoText = document.createElement('span');
                infoText.textContent = `${character.children.length} items hidden`;
                infoText.style.cssText = `
                    color: var(--text-color);
                `;

                collapsedInfo.appendChild(infoText);
                container.appendChild(collapsedInfo);
            }
        }

        return container;
    }

    function updateAllToggleButtons() {
        characterGroups.forEach((group, groupIndex) => {
            const toggleAllButton = toggleAllButtonForGroup(groupIndex);
            if (toggleAllButton) {
                updateToggleAllButton(toggleAllButton, group);
            }
        });
    }

    // Function to get the toggle all button for a group
    function toggleAllButtonForGroup(groupIndex) {
        const groupContainer = characterGroupList.children[groupIndex];
        if (groupContainer) {
            const toggleAllButton = groupContainer.querySelector('button[title="Activate/Deactivate All"]');
            return toggleAllButton;
        }
        return null;
    }

    // Function to rename a group
    function renameGroup(groupIndex) {
        const newName = prompt('Enter new group name:', characterGroups[groupIndex].name);
        if (newName && newName.trim() !== '') {
            characterGroups[groupIndex].name = newName.trim();
            renderCharacterGroups();
        }
    }

    // Function to delete a group
    function deleteGroup(groupIndex) {
        if (characterGroups.length === 1) {
            alert('At least one group must exist.');
            return;
        }
        if (confirm(`Are you sure you want to delete the group "${characterGroups[groupIndex].name}"? All characters in this group will be moved to "Ungrouped".`)) {
            const group = characterGroups.splice(groupIndex, 1)[0];
            const ungrouped = characterGroups.find(g => g.name === 'Ungrouped');
            if (ungrouped) {
                ungrouped.items = ungrouped.items.concat(group.items);
            } else {
                characterGroups.unshift({ name: 'Ungrouped', items: group.items, collapsed: false });
            }
            renderCharacterGroups();
        }
    }

    // Function to edit a character
    function editCharacter(character) {
        const editForm = document.createElement('form');
        editForm.innerHTML = `
            <div style="width: 100%; min-width: 500px; margin: 0 auto;">
                <label style="color: var(--text-color); font-size: 12px;">Emoji: <input type="text" name="emoji" value="${character.emoji}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Name: <input type="text" name="name" value="${character.name}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Sex: <input type="text" name="sex" value="${character.sex}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Species: <input type="text" name="species" value="${character.species}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Age: <input type="text" name="age" value="${character.age}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Body Type: <input type="text" name="bodyType" value="${character.bodyType}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Personality: <input type="text" name="personality" value="${character.personality}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Bio: <textarea name="bio" autocomplete="off" rows="4" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;">${character.bio}</textarea></label><br>
                <label style="color: var(--text-color); font-size: 12px;">User Controlled: <input type="checkbox" name="userControlled" ${character.userControlled ? 'checked' : ''}></label><br>
                <button type="submit" style="background-color: var(--button-bg-color); color: var(--text-color); border: none; padding: 5px; border-radius: 5px; width: 100%; text-align: center; margin-top: 10px;">Save</button>
            </div>
        `;
        const modal = createModal('Edit Character', editForm);
        editForm.addEventListener('submit', (e) => {
            e.preventDefault();
            character.emoji = editForm.emoji.value;
            character.name = editForm.name.value;
            character.sex = editForm.sex.value;
            character.species = editForm.species.value;
            character.age = editForm.age.value;
            character.bodyType = editForm.bodyType.value;
            character.personality = editForm.personality.value;
            character.bio = editForm.bio.value;
            character.userControlled = editForm.userControlled.checked;
            renderCharacterGroups();
            closeModal(modal);
        });
    }

    // Function to delete a character
    function deleteCharacter(characterId) {
        if (confirm('Are you sure you want to delete this character?')) {
            characterGroups.forEach(group => {
                group.items = deleteCharacterRecursive(group.items, characterId);
            });
            renderCharacterGroups();
        }
    }

    function deleteCharacterRecursive(items, characterId) {
        return items.filter(item => {
            if (item.id === characterId) {
                return false;
            }
            if (item.children && item.children.length > 0) {
                item.children = deleteCharacterRecursive(item.children, characterId);
            }
            return true;
        });
    }

    // Function to export all characters with groups
    function exportCharacters() {
        const data = characterGroups;
        const json = JSON.stringify(data, null, 2);
        const blob = new Blob([json], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = `all_characters_with_groups.json`;
        link.click();
    }

    // Function to import characters with groups
    function importCharacters() {
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = '.json';
        fileInput.addEventListener('change', async (event) => {
            const file = event.target.files[0];
            const reader = new FileReader();
            reader.onload = (e) => {
                try {
                    const importedGroups = JSON.parse(e.target.result);
                    if (Array.isArray(importedGroups)) {
                        characterGroups = importedGroups;
                        renderCharacterGroups();
                    } else {
                        alert('Invalid format for characters import.');
                    }
                } catch (error) {
                    alert('Failed to import characters: ' + error.message);
                }
            };
            reader.readAsText(file);
        });
        fileInput.click();
    }

    // Function to export a single character
    function exportCharacter(character) {
        const json = JSON.stringify(character, null, 2);
        const blob = new Blob([json], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = `${character.name}.json`;
        link.click();
    }

    // Function to move character to a group (uncoupling from parent)
    function moveCharacterToGroup(characterId, targetGroupIndex) {
        let character = null;
        // Remove character from current group or parent
        characterGroups.forEach(group => {
            group.items = removeCharacterRecursive(group.items, characterId, (item) => {
                character = item;
            });
        });
        // Add to target group
        if (character) {
            characterGroups[targetGroupIndex].items.push(character);
            renderCharacterGroups();
        }
    }

    function removeCharacterRecursive(items, characterId, callback) {
        return items.filter(item => {
            if (item.id === characterId) {
                callback(item);
                return false;
            }
            if (item.children && item.children.length > 0) {
                item.children = removeCharacterRecursive(item.children, characterId, callback);
            }
            return true;
        });
    }

    // Function to move character under another character (nesting)
    function moveCharacterToParent(characterId, parentCharacter) {
        let character = null;
        // Remove character from current group or parent
        characterGroups.forEach(group => {
            group.items = removeCharacterRecursive(group.items, characterId, (item) => {
                character = item;
            });
        });
        if (character) {
            parentCharacter.children.push(character);
            renderCharacterGroups();
        }
    }

    // Utility function to generate unique IDs
    function generateId() {
        return '_' + Math.random().toString(36).substr(2, 9);
    }

    // --- Location Sidebar with Groups and Nested Locations ---
    const locationSidebar = document.createElement('div');
    locationSidebar.id = 'location-sheet-sidebar';
    locationSidebar.style.cssText = `
        position: fixed;
        top: 0;
        left: -350px;
        width: 350px;
        height: 100%;
        display: flex;
        flex-direction: column;
        background-color: var(--bg-color);
        border-right: 2px solid var(--border-color);
        box-shadow: 2px 0 5px var(--shadow-color);
        box-sizing: border-box;
        transition: left 0.3s;
        z-index: 9999;
    `;
    document.body.appendChild(locationSidebar);

    const locationToggleButton = document.createElement('button');
    locationToggleButton.textContent = '☰';
    locationToggleButton.style.cssText = `
        position: fixed;
        top: 10px;
        left: 10px;
        padding: 5px 10px;
        border: none;
        background-color: var(--button-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
        transition: left 0.3s;
        z-index: 10000;
    `;
    locationToggleButton.addEventListener('click', () => {
        const isOpen = locationSidebar.style.left === '0px';
        locationSidebar.style.left = isOpen ? '-350px' : '0';
        locationToggleButton.style.left = isOpen ? '10px' : '360px';
    });
    document.body.appendChild(locationToggleButton);

    const locationHeader = document.createElement('div');
    locationHeader.style.cssText = `
        padding: 10px;
        background-color: var(--border-color);
        text-align: center;
        font-weight: bold;
        color: var(--text-color);
    `;
    locationHeader.textContent = 'Locations';
    locationSidebar.appendChild(locationHeader);

    const locationButtonBox = document.createElement('div');
    locationButtonBox.style.cssText = `
        display: flex;
        justify-content: space-between;
        padding: 10px;
        background-color: var(--bg-color);
        flex-shrink: 0;
    `;
    locationSidebar.appendChild(locationButtonBox);

    // New Location Button
    const newLocationButton = document.createElement('button');
    newLocationButton.textContent = 'New';
    newLocationButton.title = 'Create New Location';
    newLocationButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--success-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    newLocationButton.addEventListener('click', () => {
        createNewLocation();
    });
    locationButtonBox.appendChild(newLocationButton);

    // Load Location Button
    const loadLocationButton = document.createElement('button');
    loadLocationButton.textContent = 'Load';
    loadLocationButton.title = 'Load a Location';
    loadLocationButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--info-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    loadLocationButton.addEventListener('click', () => {
        loadLocation();
    });
    locationButtonBox.appendChild(loadLocationButton);

    // Group Location Button
    const groupLocationButton = document.createElement('button');
    groupLocationButton.textContent = 'Group';
    groupLocationButton.title = 'Create New Group';
    groupLocationButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--info-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    groupLocationButton.addEventListener('click', () => {
        createNewLocationGroup();
    });
    locationButtonBox.appendChild(groupLocationButton);

    // Import Location Button
    const importLocationButton = document.createElement('button');
    importLocationButton.textContent = 'Import';
    importLocationButton.title = 'Import Locations';
    importLocationButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--warning-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    importLocationButton.addEventListener('click', () => {
        importLocations();
    });
    locationButtonBox.appendChild(importLocationButton);

    // Export Location Button
    const exportLocationButton = document.createElement('button');
    exportLocationButton.textContent = 'Export';
    exportLocationButton.title = 'Export Locations';
    exportLocationButton.style.cssText = `
        padding: 5px 10px;
        border: none;
        background-color: var(--muted-bg-color);
        color: var(--text-color);
        border-radius: 5px;
        cursor: pointer;
    `;
    exportLocationButton.addEventListener('click', () => {
        exportLocations();
    });
    locationButtonBox.appendChild(exportLocationButton);

    // Add fifth button: "Load" for Location
    function loadLocation() {
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = '.json';
        fileInput.addEventListener('change', async (event) => {
            const file = event.target.files[0];
            const reader = new FileReader();
            reader.onload = (e) => {
                try {
                    const location = JSON.parse(e.target.result);
                    if (location && location.id) {
                        // Add to Ungrouped
                        const ungrouped = locationGroups.find(g => g.name === 'Ungrouped');
                        if (ungrouped) {
                            ungrouped.items.push(location);
                        } else {
                            locationGroups[0].items.push(location);
                        }
                        renderLocationGroups();
                        ensureActiveLocation();
                    } else {
                        alert('Invalid location format.');
                    }
                } catch (error) {
                    alert('Failed to load location: ' + error.message);
                }
            };
            reader.readAsText(file);
        });
        fileInput.click();
    }

    const locationGroupList = document.createElement('div');
    locationGroupList.id = 'location-group-list';
    locationGroupList.style.cssText = `
        flex-grow: 1;
        overflow-y: auto;
        padding: 10px;
    `;
    locationSidebar.appendChild(locationGroupList);

    // Initialize Location Groups with a single default location
    let locationGroups = [
        {
            name: 'Ungrouped',
            items: [
                {
                    id: generateId(),
                    active: true,
                    emoji: '📍',
                    name: 'Default Location',
                    description: 'Description of the default location.',
                    children: [],
                    collapsed: false
                }
            ],
            collapsed: false
        }
    ];

    // Function to create a new Location
    function createNewLocation() {
        const newLocation = {
            id: generateId(),
            active: false,
            emoji: '📍',
            name: 'New Location',
            description: '',
            children: [],
            collapsed: false
        };
        // Add to Ungrouped
        const ungrouped = locationGroups.find(g => g.name === 'Ungrouped');
        if (ungrouped) {
            ungrouped.items.push(newLocation);
        } else {
            locationGroups[0].items.push(newLocation);
        }
        renderLocationGroups();
        ensureActiveLocation();
    }

    // Function to create a new Location Group
    function createNewLocationGroup() {
        const groupName = prompt('Enter group name:', `Group ${locationGroups.length}`);
        if (groupName && groupName.trim() !== '') {
            locationGroups.push({ name: groupName.trim(), items: [], collapsed: false });
            renderLocationGroups();
        }
    }

    // Function to render Location Groups and Items
    function renderLocationGroups() {
        locationGroupList.innerHTML = '';

        locationGroups.forEach((group, groupIndex) => {
            // Sort items alphabetically by name
            group.items.sort((a, b) => a.name.localeCompare(b.name));

            const groupContainer = document.createElement('div');
            groupContainer.className = 'location-group';
            groupContainer.style.cssText = `
                margin-bottom: 10px;
                border: 1px solid var(--border-color);
                border-radius: 5px;
                background-color: var(--active-char-color);
            `;

            const groupHeader = document.createElement('div');
            groupHeader.style.cssText = `
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 5px 10px;
                background-color: var(--button-bg-color);
                color: var(--text-color);
                cursor: pointer;
                user-select: none;
                position: relative;
            `;
            groupHeader.textContent = group.name;
            groupHeader.addEventListener('click', () => {
                group.collapsed = !group.collapsed;
                renderLocationGroups();
            });

            const groupActions = document.createElement('div');
            groupActions.style.cssText = `
                display: flex;
                align-items: center;
            `;

            // Rename Group Button
            const renameGroupButton = document.createElement('button');
            renameGroupButton.textContent = '✏️';
            renameGroupButton.title = 'Rename Group';
            renameGroupButton.style.cssText = `
                background: none;
                border: none;
                color: var(--text-color);
                cursor: pointer;
                margin-right: 2px;
            `;
            renameGroupButton.addEventListener('click', (e) => {
                e.stopPropagation();
                renameLocationGroup(groupIndex);
            });
            groupActions.appendChild(renameGroupButton);

            // Delete Group Button
            const deleteGroupButton = document.createElement('button');
            deleteGroupButton.textContent = '🗑️';
            deleteGroupButton.title = 'Delete Group';
            deleteGroupButton.style.cssText = `
                background: none;
                border: none;
                color: var(--text-color);
                cursor: pointer;
            `;
            deleteGroupButton.addEventListener('click', (e) => {
                e.stopPropagation();
                deleteLocationGroup(groupIndex);
            });
            groupActions.appendChild(deleteGroupButton);

            groupHeader.appendChild(groupActions);
            groupContainer.appendChild(groupHeader);

            if (!group.collapsed) {
                const itemsContainer = document.createElement('div');
                itemsContainer.style.cssText = `
                    padding: 5px 10px;
                    display: block;
                `;
                if (group.items.length === 0) {
                    const emptyInfo = document.createElement('div');
                    emptyInfo.className = 'location-slot';
                    emptyInfo.style.cssText = `
                        display: flex;
                        align-items: center;
                        padding: 10px;
                        margin-bottom: 5px;
                        border: 1px solid var(--border-color);
                        border-radius: 5px;
                        height: 20px;
                        background-color: var(--bg-color);
                        cursor: default;
                    `;

                    const infoText = document.createElement('span');
                    infoText.textContent = `Group is empty`;
                    infoText.style.cssText = `
                        color: var(--text-color);
                    `;

                    emptyInfo.appendChild(infoText);
                    itemsContainer.appendChild(emptyInfo);
                } else {
                    group.items.forEach((location) => {
                        const locationSlot = createLocationSlot(location, groupIndex);
                        itemsContainer.appendChild(locationSlot);
                    });
                }
                groupContainer.appendChild(itemsContainer);
            } else {
                const collapsedInfo = document.createElement('div');
                collapsedInfo.className = 'location-slot';
                collapsedInfo.style.cssText = `
                    display: flex;
                    align-items: center;
                    padding: 10px;
                    margin-bottom: 10px;
                    border: 1px solid var(--border-color);
                    border-radius: 5px;
                    height: 20px;
                    margin-top: 5px;
                    background-color: var(--bg-color);
                    cursor: default;
                    margin-left: 10px;
                    margin-right: 10px;
                `;
                const infoText = document.createElement('span');
                infoText.textContent = `${group.items.length} items hidden`;
                infoText.style.cssText = `
                    color: var(--text-color);
                `;
                collapsedInfo.appendChild(infoText);
                groupContainer.appendChild(collapsedInfo);
            }

            // Add dragover and drop events for grouping
            groupContainer.addEventListener('dragover', (e) => {
                e.preventDefault();
                groupContainer.style.border = `2px dashed var(--info-bg-color)`;
            });

            groupContainer.addEventListener('dragleave', (e) => {
                groupContainer.style.border = `1px solid var(--border-color)`;
            });

            groupContainer.addEventListener('drop', (e) => {
                e.preventDefault();
                groupContainer.style.border = `1px solid var(--border-color)`;
                const data = e.dataTransfer.getData('text/plain');
                const { type, id } = JSON.parse(data);
                if (type === 'location') {
                    moveLocationToGroup(id, groupIndex);
                }
            });

            locationGroupList.appendChild(groupContainer);
        });

        // Ensure at least one group exists
        if (locationGroups.length === 0) {
            locationGroups.push({ name: 'Ungrouped', items: [], collapsed: false });
            renderLocationGroups();
        }

        // Ensure at least one location is active
        ensureActiveLocation();
    }

    // Function to generate tooltip content for a location
    function getLocationTooltipContent(location) {
        let content = `<strong>"${location.name}"</strong>:<br><em>"${location.description || 'No description available.'}"</em>`;
        return content;
    }

    // Function to create a Location Slot DOM element (recursive)
    function createLocationSlot(location, groupIndex, parent = null, level = 0) {
        const locationSlot = document.createElement('div');
        locationSlot.className = 'location-slot';
        locationSlot.draggable = true;
        locationSlot.dataset.id = location.id;
        locationSlot.style.cssText = `
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 5px;
            margin-bottom: 5px;
            border: 1px solid var(--border-color);
            border-radius: 5px;
            background-color: var(--bg-color);
            cursor: grab;
            margin-left: ${level * 20}px;
        `;

        // Drag events
        locationSlot.addEventListener('dragstart', (e) => {
            e.stopPropagation();
            e.dataTransfer.setData('text/plain', JSON.stringify({ type: 'location', id: location.id }));
            e.currentTarget.style.opacity = '0.5';
        });

        locationSlot.addEventListener('dragend', (e) => {
            e.currentTarget.style.opacity = '1';
        });

        // Click event for collapsing/expanding
        if (location.children && location.children.length > 0) {
            locationSlot.style.cursor = 'pointer';
            locationSlot.addEventListener('click', (e) => {
                e.stopPropagation();
                location.collapsed = !location.collapsed;
                renderLocationGroups();
            });
        }

        // Left Div (Active Toggle, Emoji, Name)
        const leftDiv = document.createElement('div');
        leftDiv.style.cssText = `
            display: flex;
            align-items: center;
            flex-grow: 1;
            overflow: hidden;
        `;

        // Remove Collapse/Expand Button
        // (Not needed as per new requirement)

        const activeButton = document.createElement('button');
        activeButton.textContent = location.active ? '🟢' : '🔴';
        activeButton.title = 'Toggle Active';
        activeButton.style.cssText = `
            padding: 3px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
            margin-right: 5px;
        `;
        activeButton.addEventListener('click', (e) => {
            e.stopPropagation();
            // Since only one active location is allowed, deactivate others
            locationGroups.forEach(group => {
                group.items.forEach(loc => {
                    deactivateLocationRecursive(loc);
                });
            });
            location.active = !location.active;
            renderLocationGroups();
        });
        leftDiv.appendChild(activeButton);

        const emojiSpan = document.createElement('span');
        emojiSpan.textContent = location.emoji;
        emojiSpan.style.marginRight = '5px';
        leftDiv.appendChild(emojiSpan);

        const nameSpan = document.createElement('span');
        nameSpan.textContent = location.name;
        nameSpan.style.cssText = `
            flex-grow: 1;
            min-width: 0;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
            color: var(--text-color);
        `;

        // Add tooltip event listeners
        nameSpan.addEventListener('mouseenter', (e) => {
            showTooltip(e, getLocationTooltipContent(location));
        });
        nameSpan.addEventListener('mouseleave', hideTooltip);
        nameSpan.addEventListener('dragover', hideTooltip);

        leftDiv.appendChild(nameSpan);

        locationSlot.appendChild(leftDiv);

        // Right Div (Edit, Delete, Export)
        const rightDiv = document.createElement('div');
        rightDiv.style.display = 'flex';
        rightDiv.style.alignItems = 'center';

        const editButton = document.createElement('button');
        editButton.textContent = '✏️';
        editButton.title = 'Edit Location';
        editButton.style.cssText = `
            padding: 0px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
            margin-right: 2px;
        `;
        editButton.addEventListener('click', (e) => {
            e.stopPropagation();
            editLocation(location);
        });
        rightDiv.appendChild(editButton);

        const deleteButton = document.createElement('button');
        deleteButton.textContent = '🗑️';
        deleteButton.title = 'Delete Location';
        deleteButton.style.cssText = `
            padding: 0px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
            margin-right: 2px;
        `;
        deleteButton.addEventListener('click', (e) => {
            e.stopPropagation();
            deleteLocation(location.id);
        });
        rightDiv.appendChild(deleteButton);

        const exportButton = document.createElement('button');
        exportButton.textContent = '⬇️';
        exportButton.title = 'Export Location';
        exportButton.style.cssText = `
            padding: 0px;
            border: none;
            background: none;
            cursor: pointer;
            color: var(--text-color);
        `;
        exportButton.addEventListener('click', (e) => {
            e.stopPropagation();
            exportLocation(location);
        });
        rightDiv.appendChild(exportButton);

        locationSlot.appendChild(rightDiv);

        // Dragover and Drop events
        locationSlot.addEventListener('dragover', (e) => {
            e.preventDefault();
            e.stopPropagation();
            locationSlot.style.border = `2px dashed var(--info-bg-color)`;
        });

        locationSlot.addEventListener('dragleave', (e) => {
            locationSlot.style.border = `1px solid var(--border-color)`;
        });

        locationSlot.addEventListener('drop', (e) => {
            e.preventDefault();
            e.stopPropagation();
            locationSlot.style.border = `1px solid var(--border-color)`;
            const data = e.dataTransfer.getData('text/plain');
            const { type, id } = JSON.parse(data);
            if (type === 'location' && id !== location.id) {
                moveLocationToParent(id, location);
            }
        });

        // Prevent click on buttons from triggering slot collapse/expand
        activeButton.addEventListener('click', (e) => e.stopPropagation());
        editButton.addEventListener('click', (e) => e.stopPropagation());
        deleteButton.addEventListener('click', (e) => e.stopPropagation());
        exportButton.addEventListener('click', (e) => e.stopPropagation());

        // Recursive rendering of children
        const container = document.createElement('div');
        container.appendChild(locationSlot);

        if (location.children && location.children.length > 0) {
            if (!location.collapsed) {
                location.children.forEach(child => {
                    const childSlot = createLocationSlot(child, groupIndex, location, level + 1);
                    container.appendChild(childSlot);
                });
            } else {
                const collapsedInfo = document.createElement('div');
                collapsedInfo.className = 'location-slot';
                collapsedInfo.style.cssText = `
                    display: flex;
                    align-items: center;
                    padding: 10px;
                    margin-bottom: 5px;
                    border: 1px solid var(--border-color);
                    border-radius: 5px;
                    background-color: var(--bg-color);
                    height: 20px;
                    cursor: default;
                    margin-left: ${(level + 1) * 20}px;
                `;

                const infoText = document.createElement('span');
                infoText.textContent = `${location.children.length} items hidden`;
                infoText.style.cssText = `
                    color: var(--text-color);
                `;

                collapsedInfo.appendChild(infoText);
                container.appendChild(collapsedInfo);
            }
        }

        return container;
    }

    function deactivateLocationRecursive(location) {
        location.active = false;
        if (location.children && location.children.length > 0) {
            location.children.forEach(child => {
                deactivateLocationRecursive(child);
            });
        }
    }

    // Function to rename a location group
    function renameLocationGroup(groupIndex) {
        const newName = prompt('Enter new group name:', locationGroups[groupIndex].name);
        if (newName && newName.trim() !== '') {
            locationGroups[groupIndex].name = newName.trim();
            renderLocationGroups();
        }
    }

    // Function to delete a location group
    function deleteLocationGroup(groupIndex) {
        if (locationGroups.length === 1) {
            alert('At least one group must exist.');
            return;
        }
        if (confirm(`Are you sure you want to delete the group "${locationGroups[groupIndex].name}"? All locations in this group will be moved to "Ungrouped".`)) {
            const group = locationGroups.splice(groupIndex, 1)[0];
            const ungrouped = locationGroups.find(g => g.name === 'Ungrouped');
            if (ungrouped) {
                ungrouped.items = ungrouped.items.concat(group.items);
            } else {
                locationGroups.unshift({ name: 'Ungrouped', items: group.items, collapsed: false });
            }
            renderLocationGroups();
        }
    }

    // Function to edit a location
    function editLocation(location) {
        const editForm = document.createElement('form');
        editForm.innerHTML = `
            <div style="width: 100%; min-width: 500px; margin: 0 auto;">
                <label style="color: var(--text-color); font-size: 12px;">Emoji: <input type="text" name="emoji" value="${location.emoji}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Name: <input type="text" name="name" value="${location.name}" autocomplete="off" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;"></label><br>
                <label style="color: var(--text-color); font-size: 12px;">Description: <textarea name="description" autocomplete="off" rows="4" style="background-color: var(--bg-color); color: var(--text-color); border: 1px solid var(--border-color); border-radius: 5px; padding: 5px; width: 100%; box-sizing: border-box;">${location.description}</textarea></label><br>
                <button type="submit" style="background-color: var(--button-bg-color); color: var(--text-color); border: none; padding: 5px; border-radius: 5px; width: 100%; text-align: center; margin-top: 10px;">Save</button>
            </div>
        `;
        const modal = createModal('Edit Location', editForm);
        editForm.addEventListener('submit', (e) => {
            e.preventDefault();
            location.emoji = editForm.emoji.value;
            location.name = editForm.name.value;
            location.description = editForm.description.value;
            renderLocationGroups();
            ensureActiveLocation();
            closeModal(modal);
        });
    }

    // Function to delete a location
    function deleteLocation(locationId) {
        if (confirm('Are you sure you want to delete this location?')) {
            locationGroups.forEach(group => {
                group.items = deleteLocationRecursive(group.items, locationId);
            });
            renderLocationGroups();
            ensureActiveLocation();
        }
    }

    function deleteLocationRecursive(items, locationId) {
        return items.filter(item => {
            if (item.id === locationId) {
                return false;
            }
            if (item.children && item.children.length > 0) {
                item.children = deleteLocationRecursive(item.children, locationId);
            }
            return true;
        });
    }

    // Function to export all locations with groups
    function exportLocations() {
        const data = locationGroups;
        const json = JSON.stringify(data, null, 2);
        const blob = new Blob([json], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = `all_locations_with_groups.json`;
        link.click();
    }

    // Function to import locations with groups
    function importLocations() {
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = '.json';
        fileInput.addEventListener('change', async (event) => {
            const file = event.target.files[0];
            const reader = new FileReader();
            reader.onload = (e) => {
                try {
                    const importedGroups = JSON.parse(e.target.result);
                    if (Array.isArray(importedGroups)) {
                        locationGroups = importedGroups;
                        renderLocationGroups();
                        ensureActiveLocation();
                    } else {
                        alert('Invalid format for locations import.');
                    }
                } catch (error) {
                    alert('Failed to import locations: ' + error.message);
                }
            };
            reader.readAsText(file);
        });
        fileInput.click();
    }

    // Function to export a single location
    function exportLocation(location) {
        const json = JSON.stringify(location, null, 2);
        const blob = new Blob([json], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = `${location.name}.json`;
        link.click();
    }

    // Function to move location to a group (uncoupling from parent)
    function moveLocationToGroup(locationId, targetGroupIndex) {
        let location = null;
        // Remove location from current group or parent
        locationGroups.forEach(group => {
            group.items = removeLocationRecursive(group.items, locationId, (item) => {
                location = item;
            });
        });
        // Add to target group
        if (location) {
            locationGroups[targetGroupIndex].items.push(location);
            renderLocationGroups();
            ensureActiveLocation();
        }
    }

    function removeLocationRecursive(items, locationId, callback) {
        return items.filter(item => {
            if (item.id === locationId) {
                callback(item);
                return false;
            }
            if (item.children && item.children.length > 0) {
                item.children = removeLocationRecursive(item.children, locationId, callback);
            }
            return true;
        });
    }

    // Function to move location under another location (nesting)
    function moveLocationToParent(locationId, parentLocation) {
        let location = null;
        // Remove location from current group or parent
        locationGroups.forEach(group => {
            group.items = removeLocationRecursive(group.items, locationId, (item) => {
                location = item;
            });
        });
        if (location) {
            if(parentLocation.children == undefined){
               parentLocation.children = [];
            }
            parentLocation.children.push(location);
            renderLocationGroups();
            ensureActiveLocation();
        }
    }

    // Function to create a modal
    function createModal(title, content) {
        const modalOverlay = document.createElement('div');
        modalOverlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10002;
        `;

        const modalBox = document.createElement('div');
        modalBox.style.cssText = `
            background-color: var(--bg-color);
            padding: 20px;
            border: 1px solid var(--border-color);
            border-radius: 5px;
            width: fit-content;
            min-width: 500px;
            max-width: 90%;
            box-shadow: 0 0 10px var(--shadow-color);
            position: relative;
        `;

        const modalTitle = document.createElement('h2');
        modalTitle.textContent = title;
        modalTitle.style.cssText = `
            margin-top: 0;
            color: var(--text-color);
        `;
        modalBox.appendChild(modalTitle);

        const closeButton = document.createElement('button');
        closeButton.textContent = '✖️';
        closeButton.style.cssText = `
            position: absolute;
            top: 15px;
            right: 20px;
            background: none;
            border: none;
            font-size: 20px;
            cursor: pointer;
            color: var(--text-color);
        `;
        closeButton.addEventListener('click', () => {
            closeModal(modalOverlay);
        });
        modalBox.appendChild(closeButton);

        modalBox.appendChild(content);
        modalOverlay.appendChild(modalBox);
        document.body.appendChild(modalOverlay);

        return modalOverlay;
    }

    // Function to close a modal
    function closeModal(modal) {
        if (modal && modal.parentNode) {
            modal.parentNode.removeChild(modal);
        }
    }

    // Function to ensure at least one location is active
    function ensureActiveLocation() {
        const activeLocations = [];
        locationGroups.forEach(group => {
            group.items.forEach(loc => {
                collectActiveLocations(loc, activeLocations);
            });
        });
        if (activeLocations.length === 0 && locationGroups.flatMap(g => g.items).length > 0) {
            locationGroups[0].items[0].active = true;
        }
    }

    function collectActiveLocations(location, activeLocations) {
        if (location.active) {
            activeLocations.push(location);
        }
        if (location.children && location.children.length > 0) {
            location.children.forEach(child => {
                collectActiveLocations(child, activeLocations);
            });
        }
    }

    // Initial render of Character and Location Groups
    renderCharacterGroups();
    renderLocationGroups();

    // --- Plot Field ---
    const plotDiv = document.createElement('div');
    plotDiv.style.cssText = `
        display: flex;
        justify-content: space-between;
        padding: 10px;
        background-color: var(--bg-color);
        border-top: 1px solid var(--border-color);
        flex-shrink: 0;
    `;
    const plotInput = document.createElement('input');
    plotInput.type = 'text';
    plotInput.placeholder = 'Plot';
    plotInput.style.cssText = `
        width: 100%;
        padding: 5px;
        border: 1px solid var(--border-color);
        border-radius: 5px;
        background-color: var(--bg-color);
        color: var(--text-color);
        box-sizing: border-box;
    `;
    plotDiv.appendChild(plotInput);
    characterSidebar.appendChild(plotDiv);

    // --- Location Context Inputs ---
    const globalInputs = document.createElement('div');
    globalInputs.style.cssText = `
        display: flex;
        justify-content: space-between;
        padding: 10px;
        background-color: var(--bg-color);
        border-top: 1px solid var(--border-color);
        flex-shrink: 0;
    `;
    locationSidebar.appendChild(globalInputs);

    const timeInput = document.createElement('input');
    timeInput.type = 'text';
    timeInput.placeholder = 'Time';
    timeInput.style.cssText = `
        width: calc(50% - 5px);
        padding: 5px;
        border: 1px solid var(--border-color);
        border-radius: 5px;
        background-color: var(--bg-color);
        color: var(--text-color);
    `;
    globalInputs.appendChild(timeInput);

    const weatherInput = document.createElement('input');
    weatherInput.type = 'text';
    weatherInput.placeholder = 'Weather';
    weatherInput.style.cssText = `
        width: calc(50% - 5px);
        padding: 5px;
        border: 1px solid var(--border-color);
        border-radius: 5px;
        background-color: var(--bg-color);
        color: var(--text-color);
    `;
    globalInputs.appendChild(weatherInput);

    // Initial render of transparency and theme settings
    transparencySlider.value = defaultTransparency;
    themeDropdown.value = defaultTheme;

})();