// Terminal reference - set when terminal is created in the server rack
let activeTerminal = null;

// Create the interactive terminal in the first rack unit
function createTerminal(face) {
    // Terminal display
    const terminal = document.createElement('div');
    terminal.className = 'terminal-display';
    terminal.setAttribute('tabindex', '0');

    const mobileInput = document.createElement('input');
    mobileInput.type = 'text';
    mobileInput.style.opacity = '0';
    mobileInput.style.position = 'absolute';
    mobileInput.style.width = '1px';
    mobileInput.style.height = '1px';
    mobileInput.style.padding = '0';
    mobileInput.style.border = '0';
    mobileInput.style.outline = 'none';
    mobileInput.style.background = 'transparent';
    mobileInput.setAttribute('autocorrect', 'off');
    mobileInput.setAttribute('spellcheck', 'false');
    mobileInput.setAttribute('autocomplete', 'off');
    mobileInput.setAttribute('autocapitalize', 'off');
    mobileInput.autocapitalize = 'off';
    terminal.appendChild(mobileInput);
    terminal._mobileInput = mobileInput;

    const content = document.createElement('div');
    content.className = 'terminal-content';

    const line1 = document.createElement('div');
    line1.innerHTML = '<span class="terminal-prompt">$</span> uptime';
    content.appendChild(line1);

    const line2 = document.createElement('div');
    line2.textContent = 'optional';
    content.appendChild(line2);

    const line3 = document.createElement('div');
    line3.innerHTML = '<span class="terminal-prompt">$</span> ';
    content.appendChild(line3);

    const cursor = document.createElement('span');
    cursor.className = 'terminal-cursor';
    line3.appendChild(cursor);

    terminal.appendChild(content);
    face.appendChild(terminal);

    activeTerminal = terminal;

    terminal.addEventListener('click', () => {
        mobileInput.focus();
    });

    const commandHistory = [];
    let historyIndex = -1;
    let isRoot = false;
    let isLoginScreen = false;
    let tabCycleIndex = -1;
    let tabMatches = [];
    let tabBaseInput = '';
    let isTabCompleting = false;
    let inVimMode = false;

    const allCommands = [
        'ls', 'ss', 'clear', 'exit', 'rm -rf /', 'sudo su -', 'sudo -i',
        'pwd', 'whoami', 'hostname', 'date', 'uname', 'uname -a', 'uptime',
        'id', 'cat /etc/os-release', 'cat ~/.ssh/id_ed25519.pub',
        'docker ps', 'docker ls', 'docker container ls',
        'podman ps', 'podman ls', 'podman container ls',
        'systemctl list-units', 'systemctl list-units --type=service --state=running --no-pager',
        'ip addr show', 'df -h', 'free -h',
        'ps aux', 'ps aux --sort=-%mem | head -10',
        'neofetch', 'sl', 'help', 'echo', 'curl', 'wget', 'apt', 'dnf', 'vim'
    ];

    function updateDisplay(text) {
        const lastLine = content.lastElementChild;
        if (!lastLine) return;
        const cursorEl = lastLine.querySelector('.terminal-cursor');
        if (cursorEl) cursorEl.remove();
        lastLine.textContent = '';
        const promptSpan = document.createElement('span');
        promptSpan.className = 'terminal-prompt';
        promptSpan.textContent = isRoot ? '#' : '$';
        lastLine.appendChild(promptSpan);
        lastLine.appendChild(document.createTextNode(' '));
        lastLine.appendChild(document.createTextNode(text));
        const newCursor = document.createElement('span');
        newCursor.className = 'terminal-cursor' + (isRoot ? ' red' : '');
        lastLine.appendChild(newCursor);
    }

    const commands = {
        'pwd': '/home/reese/portfolio',
        'whoami': 'reese',
        'hostname': 'homelab',
        'date': new Date().toString(),
        'uname': 'Linux homelab 7.0.0 #1 SMP x86_64 GNU/Linux',
        'uname -a': 'Linux homelab 6.8.0 #1 SMP x86_64 GNU/Linux',
        'uptime': ' 14:30:00 up 42 days, 3:15, 1 user, load average: 0.42, 0.38, 0.35',
        'id': 'uid=1000(reese) gid=1000(reese) groups=1000(reese),985(podman)',
        'cat /etc/os-release': 'PRETTY_NAME="Fedora Linux 69 (Workstation Edition)"\nNAME="Fedora Linux"\nVERSION_ID="69"\nVERSION="69 (Workstation Edition)"\nID=fedora\nVARIANT=Workstation Edition\nVARIANT_ID=workstation\nLOGO=fedora-logo-icon\nCPE_NAME="cpe:/o:fedoralinux:fedora:69"\nDEFAULT_HOSTNAME="fedora"\nHOME_URL="https://fedoraproject.org/"\nDOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f69/system-administrators-guide/"\nSUPPORT_URL="https://ask.fedoraproject.org/"\nBUG_REPORT_URL="https://bugzilla.redhat.com/"\nREDHAT_BUGZILLA_PRODUCT="Fedora"\nREDHAT_BUGZILLA_PRODUCT_VERSION=69\nREDHAT_SUPPORT_PRODUCT="Fedora"\nREDHAT_SUPPORT_PRODUCT_VERSION=69',
        'cat ~/.ssh/id_ed25519.pub': 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpFmKLqRKzMwRe3WkqJvQrN5mHjF2pRn8sT6yUvWxRe reese@homelab',
        'docker ps': 'NAMES              STATUS              PORTS\nborg             Up 42 days        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp\ngitea            Up 42 days        0.0.0.0:222->22/tcp, 0.0.0.0:3000->3000/tcp\nnextcloud        Up 42 days        0.0.0.0:8080->80/tcp\nimmich           Up 42 days        0.0.0.0:3001->3000/tcp, 0.0.0.0:3002->3001/tcp\nopen-webui       Up 42 days        0.0.0.0:8081->8080/tcp\njellyfin         Up 42 days        0.0.0.0:8096->8096/tcp\nslopbox          Up 42 days        0.0.0.0:9090->80/tcp',
        'docker ls': 'NAMES              STATUS              PORTS\nborg             Up 42 days        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp\ngitea            Up 42 days        0.0.0.0:222->22/tcp, 0.0.0.0:3000->3000/tcp\nnextcloud        Up 42 days        0.0.0.0:8080->80/tcp\nimmich           Up 42 days        0.0.0.0:3001->3000/tcp, 0.0.0.0:3002->3001/tcp\nopen-webui       Up 42 days        0.0.0.0:8081->8080/tcp\njellyfin         Up 42 days        0.0.0.0:8096->8096/tcp\nslopbox          Up 42 days        0.0.0.0:9090->80/tcp',
        'docker container ls': 'NAMES              STATUS              PORTS\nborg             Up 42 days        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp\ngitea            Up 42 days        0.0.0.0:222->22/tcp, 0.0.0.0:3000->3000/tcp\nnextcloud        Up 42 days        0.0.0.0:8080->80/tcp\nimmich           Up 42 days        0.0.0.0:3001->3000/tcp, 0.0.0.0:3002->3001/tcp\nopen-webui       Up 42 days        0.0.0.0:8081->8080/tcp\njellyfin         Up 42 days        0.0.0.0:8096->8096/tcp\nslopbox          Up 42 days        0.0.0.0:9090->80/tcp',
        'podman ps': 'NAMES              STATUS\nhomepage         Up 5 hours\nllama            Up 42 days',
        'podman ls': 'NAMES              STATUS\nhomepage         Up 5 hours\nllama            Up 42 days',
        'podman container ls': 'NAMES              STATUS\nhomepage         Up 5 hours\nllama            Up 42 days',
        'systemctl list-units': 'UNIT                    LOAD   ACTIVE SUB     DESCRIPTION\nborg.service            loaded active running Borg Backup Service\ngitea.service           loaded active running Gitea\ndocker.service          loaded active running Docker Application Container Engine\nnextcloud.service       loaded active running Nextcloud\nimmich.service          loaded active running Immich\nopen-webui.service      loaded active running Open WebUI\njellyfin.service        loaded active running Jellyfin Media Server\nslopbox.service         loaded active running Slopbox\nhomepage.service        loaded active running Homepage Container',
        'systemctl list-units --type=service --state=running --no-pager': 'UNIT                    LOAD   ACTIVE SUB     DESCRIPTION\nborg.service            loaded active running Borg Backup Service\ngitea.service           loaded active running Gitea\ndocker.service          loaded active running Docker Application Container Engine\nnextcloud.service       loaded active running Nextcloud\nimmich.service          loaded active running Immich\nopen-webui.service      loaded active running Open WebUI\njellyfin.service        loaded active running Jellyfin Media Server\nslopbox.service         loaded active running Slopbox\nhomepage.service        loaded active running Homepage Container',
        'ss': 'Netid  State   Recv-Q  Send-Q   Local Address:Port    Peer Address:Port\ntcp  LISTEN  0       128      0.0.0.0:22           0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:80           0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:443          0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:222          0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3000         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3001         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3002         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8080         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8081         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8096         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:9090         0.0.0.0:*\ntcp  LISTEN  0       128      [::]:22              [::]:*',
        'ip addr show': '1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN\n    inet 127.0.0.1/8 scope host lo\n    inet6 ::1/128 scope host\n2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP\n    inet 192.168.1.42/24 brd 192.168.1.255 scope global dynamic eth0\n    inet6 fe80::1/64 scope link',
        'df -h': 'Filesystem      Size  Used Avail Use% Mounted on\n/dev/sda2       465G  182G  258G  42% /\nudev            16G     0   16G   0% /dev\ntmpfs           16G  2.1M   16G   1% /dev/shm\n/dev/sda1       511M  6.6M  505M   2% /boot/efi\n/dev/sdb1       1.8T  945G  793G  55% /mnt/data\noverlay         1.8T  945G  793G  55% /var/lib/docker/overlay2',
        'free -h': '              total        used        free      shared  buff/cache   available\nMem:           31Gi       8.2Gi       12Gi       512Mi       11Gi        22Gi\nSwap:         2.0Gi          0B       2.0Gi',
        'ps aux': 'USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\nreese        1242  2.1 12.4 4285632 3932160 ?    Sl   May15  42:18 /opt/llama.cpp/build/bin/llama-server --model /models/Qwen3-30B-A3B.Q4_K_M.gguf --port 8082\ndocker       2341  1.2  6.8 8562348 2156032 ?     Sl   May15  28:45 /usr/bin/dockerd -H fd://\nreese        3456  0.8  3.2 2845632 1015808 ?    Sl   May15  18:22 /opt/open-webui/server\nreese        4567  0.5  2.1 1562348 665600 ?     Sl   May15  12:34 /usr/bin/python3 /opt/borg/borgmatic\nroot         5678  0.3  1.4 945632 448000 ?       Ssl  May15   8:12 /usr/bin/docker-proxy -p tcp:0.0.0.0:80:80\nreese        6789  0.2  1.1 745632 348000 ?       Ssl  May15   5:45 /usr/bin/podman run --name homepage\nroot         7890  0.1  0.8 545632 256000 ?       Ssl  May15   3:22 /usr/bin/docker-proxy -p tcp:0.0.0.0:443:443',
        'ps aux --sort=-%mem | head -10': 'USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\nreese        1242  2.1 12.4 4285632 3932160 ?    Sl   May15  42:18 /opt/llama.cpp/build/bin/llama-server --model /models/Qwen3-30B-A3B.Q4_K_M.gguf --port 8082\ndocker       2341  1.2  6.8 8562348 2156032 ?     Sl   May15  28:45 /usr/bin/dockerd -H fd://\nreese        3456  0.8  3.2 2845632 1015808 ?    Sl   May15  18:22 /opt/open-webui/server\nreese        4567  0.5  2.1 1562348 665600 ?     Sl   May15  12:34 /usr/bin/python3 /opt/borg/borgmatic\nroot         5678  0.3  1.4 945632 448000 ?       Ssl  May15   8:12 /usr/bin/docker-proxy -p tcp:0.0.0.0:80:80\nreese        6789  0.2  1.1 745632 348000 ?       Ssl  May15   5:45 /usr/bin/podman run --name homepage\nroot         7890  0.1  0.8 545632 256000 ?       Ssl  May15   3:22 /usr/bin/docker-proxy -p tcp:0.0.0.0:443:443',
        'neofetch': `                    'c.          reese@homelab\n                 ,xNMM.          ----------------------\n                                     .OMMMMo           OS: Fedora Linux 69 (Workstation Edition) x86_64\n               OMMM0,            Host: custom-build\n     .;loddo:' loolloddol;.      Kernel: 6.8.0\n   cKMMMMMMMMMMNWMMMMMMMMMM0:    Uptime: 42 days, 3 hours\n .KMMMMMMMMMMMMMMMMMMMMMMMWd.    Packages: 2847 (dnf)\n XMMMMMMMMMMMMMMMMMMMMMMMX.      Shell: bash 5.2.26\n;MMMMMMMMMMMMMMMMMMMMMMMM:       Resolution: 2560x1440\n:MMMMMMMMMMMMMMMMMMMMMMMM:       DE: GNOME 46.1\n.MMMMMMMMMMMMMMMMMMMMMMMMX.      WM: Mutter\n kMMMMMMMMMMMMMMMMMMMMMMMMWd.    Terminal: /dev/pts/0\n .XMMMMMMMMMMMMMMMMMMMMMMMMMMk   CPU: AMD Ryzen 9 7900X (24) @ 5.6GHz\n  .XMMMMMMMMMMMMMMMMMMMMMMK.     GPU: NVIDIA GeForce RTX 4090\n    kMMMMMMMMMMMMMMMMMMMMd       GPU: AMD Ryzen Built-in\n     ;KMMMMMMMWXXWMMMMMMMk.      Memory: 8.2Gi / 31Gi\n       .cooc,.    .,coo:.\n\n<span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span>`,
        'sl': '____\n|DD|____T_\n|_ |_____|<\n  @-@-@-oo\\',
        'vim': 'vim: Enter the terminal text editor. Type :q to quit.',
        'help': 'Available commands:\n  ls          List directory contents\n  pwd         Print working directory\n  whoami      Print current user\n  hostname    Print hostname\n  date        Print current date/time\n  uname       Print system information\n  uptime      Print system uptime\n  id          Print user identity\n  cat         Print file contents (try: cat /etc/os-release)\n  docker      List running containers\n  podman      List running pods\n  systemctl   List running systemd services\n  ss          Show listening ports\n  ip          Show network interfaces\n  df          Show disk usage\n  free        Show memory usage\n  ps          Show running processes\n  vim         Terminal text editor (try: vim or vim filename)\n  neofetch    System info display\n  sl          Steam locomotive\n  help        Show this help message',
    };

    terminal.addEventListener('keydown', (e) => {
        if (inVimMode) return;
        if (e.key === 'ArrowUp') {
            e.preventDefault();
            if (historyIndex < commandHistory.length - 1) {
                historyIndex++;
                const cmdLine = commandHistory[historyIndex];
                const lastLine = content.lastElementChild;
                lastLine.innerHTML = '<span class="terminal-prompt">$</span> ' + cmdLine + ' ';
                const newCursor = document.createElement('span');
                newCursor.className = 'terminal-cursor';
                lastLine.appendChild(newCursor);
            }
            return;
        }

        if (e.key === 'ArrowDown') {
            e.preventDefault();
            if (historyIndex > 0) {
                historyIndex--;
                const cmdLine = commandHistory[historyIndex];
                const lastLine = content.lastElementChild;
                lastLine.innerHTML = '<span class="terminal-prompt">$</span> ' + cmdLine + ' ';
                const newCursor = document.createElement('span');
                newCursor.className = 'terminal-cursor';
                lastLine.appendChild(newCursor);
            } else {
                historyIndex = -1;
                const lastLine = content.lastElementChild;
                lastLine.innerHTML = '<span class="terminal-prompt">$</span> ';
                const newCursor = document.createElement('span');
                newCursor.className = 'terminal-cursor';
                lastLine.appendChild(newCursor);
            }
            return;
        }

        if (e.key === 'Enter') {
            e.preventDefault();
            mobileInput.value = '';
            lastInputValue = '';
            const lastLine = content.lastElementChild;
            const oldCursor = lastLine?.querySelector('.terminal-cursor');
            if (oldCursor) oldCursor.remove();

            const cmdText = lastLine.textContent.replace(/^[\$#]\s*/, '').trim();

            if (cmdText) {
                commandHistory.unshift(cmdText);
                historyIndex = -1;
            }

            if (cmdText.startsWith('ls')) {
                const output = [
                    'total 20K',
                    'drwxr-xr-x  5 reese reese 4.0K May 28 14:30 .',
                    'drwx------ 42 reese reese 4.0K May 28 10:15 ..',
                    '-rw-r--r--  1 reese reese  245 May 27 09:00 .gitignore',
                    '-rw-r--r--  1 reese reese 1.2K May 27 11:45 Dockerfile',
                    '-rw-r--r--  1 reese reese 4.8K May 28 13:50 index.html',
                    '-rw-r--r--  1 reese reese  680 May 27 09:00 nginx.conf',
                    '-rw-r--r--  1 reese reese  32K May 28 14:28 profile.jpeg',
                    '-rw-r--r--  1 reese reese  14K May 28 12:00 script.js',
                    '-rw-r--r--  1 reese reese  42K May 28 14:25 style.css',
                    'drwxr-xr-x  2 reese reese 4.0K May 27 09:00 src'
                ].join('\n');

                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.style.color = '#ccc';
                outLine.textContent = output;
                content.appendChild(outLine);
            }

            if (cmdText.startsWith('ss')) {
                const output = 'Netid  State   Recv-Q  Send-Q   Local Address:Port    Peer Address:Port\ntcp  LISTEN  0       128      0.0.0.0:22           0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:80           0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:443          0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:222          0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3000         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3001         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3002         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8080         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8081         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8096         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:9090         0.0.0.0:*\ntcp  LISTEN  0       128      [::]:22              [::]:*';
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.style.color = '#ccc';
                outLine.textContent = output;
                content.appendChild(outLine);
            }

            if (cmdText === 'clear') {
                content.innerHTML = '';
            }

             if (cmdText.startsWith('vim')) {
                 const filename = cmdText.split(' ').slice(1).join(' ') || '';
                 let vimBuffer = ['Welcome to vim (simulated)!'];
                 let vimLineNum = 0;
                 let scrollOffset = 0;
                 let vimStatus = '~';
                 let vimCol = 0;
                 let showSplash = false;
                 inVimMode = true;

                 // Hide the mobile input so it doesn't intercept vim keystrokes
                 mobileInput.style.display = 'none';

                 // Create a full-screen vim overlay
                 const vimOverlay = document.createElement('div');
                 vimOverlay.style.position = 'fixed';
                 vimOverlay.style.inset = '0';
                 vimOverlay.style.background = '#0a0a0c';
                 vimOverlay.style.fontFamily = "'SF Mono', 'Fira Code', 'Cascadia Code', monospace";
                 vimOverlay.style.fontSize = '0.85rem';
                 vimOverlay.style.lineHeight = '1.5';
                 vimOverlay.style.color = '#22c55e';
                 vimOverlay.style.display = 'flex';
                 vimOverlay.style.flexDirection = 'column';
                 vimOverlay.style.zIndex = '10000';
                 vimOverlay.style.padding = '12px 24px';
                 vimOverlay.style.overflow = 'hidden';

          document.body.appendChild(vimOverlay);

                 const lineNums = [];
                 const lineTexts = [];
                 const vimLines = [];
                 const linesContainer = document.createElement('div');
                 linesContainer.style.flexGrow = '1';
                 linesContainer.style.minHeight = '0';
                 linesContainer.style.overflowY = 'auto';
                 linesContainer.style.display = 'flex';
                 linesContainer.style.flexDirection = 'column';
                 linesContainer.style.scrollbarWidth = 'none';
                 linesContainer.style.msOverflowStyle = 'none';

                 function createLineElement() {
                     const line = document.createElement('div');
                     line.style.whiteSpace = 'pre';
                     line.style.flexShrink = '0';
                     const numSpan = document.createElement('span');
                     numSpan.style.color = '#666';
                     numSpan.style.marginRight = '8px';
                     numSpan.style.userSelect = 'none';
                     numSpan.style.display = 'inline-block';
                     numSpan.style.width = '3ch';
                     const textSpan = document.createElement('span');
                     line.appendChild(numSpan);
                     line.appendChild(textSpan);
                     return line;
                 }

                 function createSplashLine(text) {
                     const line = document.createElement('div');
                     line.style.whiteSpace = 'pre';
                     line.style.flexShrink = '0';
                     const textSpan = document.createElement('span');
                     line.appendChild(textSpan);
                     return { line, textSpan };
                 }

                 if (!filename) {
                     showSplash = true;
                     const splashText = [
                         '',
                         '    VIM - Vi sIgnificantly worse M',
                         '',
                         '    version 0.0.0-alpha',
                         '    by disappointed programmers et al.',
                         '    Modified by https://www.reddit.com/r/vim/',
                         '    Vim is open source and you will figure it out',
                         '',
                         '    Please send help.',
                         '',
                         '    type :q<Enter> to escape this regret',
                         '    type :help<Enter> or <F1> for on-line help',
                         '    type :help version0<Enter> for version info',
                         '',
                     ];

                     for (const text of splashText) {
                         const { line, textSpan } = createSplashLine(text);
                         linesContainer.appendChild(line);
                         lineTexts.push(textSpan);
                         vimLines.push(line);
                     }

                     vimBuffer = splashText;
                     vimLineNum = 0;
                     vimCol = 0;
                 } else {
                     const line = createLineElement();
                     linesContainer.appendChild(line);
                     lineNums.push(line.children[0]);
                     lineTexts.push(line.children[1]);
                     vimLines.push(line);
                     vimBuffer = ['Welcome to ' + filename + '!'];
                     vimLineNum = 0;
                     vimCol = 0;
                 }

                 vimOverlay.appendChild(linesContainer);

                 // Status bar at the bottom
                 const statusLine = document.createElement('div');
                 statusLine.style.marginTop = 'auto';
                 statusLine.style.borderTop = '1px solid #444';
                 statusLine.style.paddingTop = '4px';
                 statusLine.style.color = '#ccc';
                 statusLine.style.flexShrink = '0';
                 vimOverlay.appendChild(statusLine);

                 // File info at the very bottom
                 const fileInfo = document.createElement('div');
                 fileInfo.style.color = '#888';
                 fileInfo.style.flexShrink = '0';
                 vimOverlay.appendChild(fileInfo);

                 function escapeHtml(str) {
                     const div = document.createElement('div');
                     div.textContent = str;
                     return div.innerHTML;
                 }

                 function vimRender() {
                      // Ensure we have enough line elements
                      while (vimLines.length < vimBuffer.length) {
                          let newLine;
                          if (showSplash) {
                              const { line, textSpan } = createSplashLine('');
                              newLine = line;
                              linesContainer.appendChild(line);
                              lineTexts.push(textSpan);
                          } else {
                              newLine = createLineElement();
                              linesContainer.appendChild(newLine);
                              lineNums.push(newLine.children[0]);
                              lineTexts.push(newLine.children[1]);
                          }
                          vimLines.push(newLine);
                      }

                     // Update all visible lines
                     for (let i = 0; i < vimBuffer.length; i++) {
                         if (showSplash) {
                             lineTexts[i].textContent = vimBuffer[i] || '';
                         } else {
                             lineNums[i].textContent = (i + 1);
                             const lineText = vimBuffer[i] || '';
                             if (i === vimLineNum && (vimStatus === '-- INSERT --' || vimStatus === '~')) {
                                 const col = vimCol;
                                 const before = lineText.slice(0, col);
                                 const after = lineText.slice(col);
                                 if (after.length > 0) {
                                     const cursorChar = after.charAt(0);
                                     lineTexts[i].innerHTML = escapeHtml(before) + '<span class="vim-block-cursor">' + escapeHtml(cursorChar) + '</span>' + escapeHtml(after.slice(1));
                                 } else {
                                     lineTexts[i].innerHTML = escapeHtml(before) + '<span class="vim-block-cursor">&nbsp;</span>';
                                 }
                             } else {
                                 lineTexts[i].textContent = lineText;
                             }
                         }
                         vimLines[i].style.display = '';
                     }

                     // Hide unused line elements
                     for (let i = vimBuffer.length; i < vimLines.length; i++) {
                         vimLines[i].style.display = 'none';
                     }

                    // Auto-scroll when line is above or below the viewport
                    const lineEl = vimLines[vimLineNum];
                    if (lineEl && lineEl.style.display !== 'none') {
                        const lineBottom = lineEl.offsetTop + lineEl.offsetHeight;
                        const lineTop = lineEl.offsetTop;
                        if (lineBottom > linesContainer.scrollTop + linesContainer.clientHeight) {
                            linesContainer.scrollTop = lineBottom - linesContainer.clientHeight;
                        } else if (lineTop < linesContainer.scrollTop + 12) {
                            linesContainer.scrollTop = lineTop - 12;
                        }
                    }

                     if (showSplash) {
                         statusLine.textContent = '';
                         fileInfo.textContent = '"VIM - Vi sIgnificantly worse M"';
                     } else {
                         statusLine.textContent = vimStatus;
                         fileInfo.textContent = '"' + filename + '"';
                     }
                 }

                 function vimExit(message) {
                     document.removeEventListener('keydown', vimHandler);
                     inVimMode = false;
                     mobileInput.style.display = '';
                     vimOverlay.remove();
                     content.innerHTML = '';
                     if (message) {
                         const msgLine = document.createElement('div');
                         msgLine.style.whiteSpace = 'pre-wrap';
                         msgLine.style.color = '#ccc';
                         msgLine.textContent = message;
                         content.appendChild(msgLine);
                     }
                     const newLine = document.createElement('div');
                     newLine.innerHTML = '<span class="terminal-prompt">$</span> ';
                     content.appendChild(newLine);
                     const newCursor = document.createElement('span');
                     newCursor.className = 'terminal-cursor';
                     newLine.appendChild(newCursor);
                     content.scrollTop = content.scrollHeight;
                     terminal.focus();
                 }

                 const vimHandler = (e) => {
                     e.preventDefault();

                     if (showSplash) {
                         if (e.key === 'q' && e.shiftKey) {
                             vimExit();
                             return;
                         }
                         if (e.key === 'Escape' || e.key === 'q') {
                             vimExit();
                             return;
                         }
                         vimRender();
                         return;
                     }

                     if (vimStatus.startsWith(':')) {
                         if (e.key === 'Enter') {
                             const cmd = vimStatus.slice(1).trim();
                             if (cmd === 'q' || cmd === 'q!') {
                                 vimExit();
                                 return;
                             }
                             if (cmd === 'wq' || cmd === 'x') {
                                 vimExit('File saved (simulated).');
                                 return;
                             }
                             if (cmd === 'w') {
                                 vimStatus = 'File written (simulated).';
                                 vimRender();
                                 setTimeout(() => { vimStatus = ':'; vimRender(); }, 1000);
                                 return;
                             }
                             if (cmd.startsWith('%s/')) {
                                 vimStatus = 'Pattern not found (simulated).';
                                 vimRender();
                                 setTimeout(() => { vimStatus = ':'; vimRender(); }, 1000);
                                 return;
                             }
                             if (cmd === 'help') {
                                 vimStatus = ':q quit  :w save  :wq save & quit  :q! force quit  dd delete line  i insert  o open line';
                                 vimRender();
                                 setTimeout(() => { vimStatus = ':'; vimRender(); }, 3000);
                                 return;
                             }
                             vimStatus = 'Unknown command: ' + cmd;
                             vimRender();
                             setTimeout(() => { vimStatus = ':'; vimRender(); }, 2000);
                             return;
                         }
                         if (e.key === 'Escape') {
                             vimStatus = '~';
                             vimRender();
                             return;
                         }
                         if (e.key === 'Backspace') {
                             vimStatus = vimStatus.slice(0, -1);
                             vimRender();
                             return;
                         }
                         if (e.key.length === 1) {
                             vimStatus += e.key;
                             vimRender();
                         }
                         return;
                     }

                     if (vimStatus === '-- INSERT --') {
                         if (e.key === 'Escape') {
                             vimStatus = '~';
                             vimRender();
                             return;
                         }
                         if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
                             vimBuffer[vimLineNum] = vimBuffer[vimLineNum].slice(0, vimCol) + e.key + vimBuffer[vimLineNum].slice(vimCol);
                             vimCol++;
                             vimRender();
                             return;
                         }
                         if (e.key === 'Enter') {
                             vimBuffer.splice(vimLineNum + 1, 0, '');
                             vimLineNum++;
                             vimCol = 0;
                             vimRender();
                             return;
                         }
                         if (e.key === 'Backspace') {
                             if (vimCol > 0) {
                                 vimCol--;
                                 vimBuffer[vimLineNum] = vimBuffer[vimLineNum].slice(0, vimCol) + vimBuffer[vimLineNum].slice(vimCol + 1);
                             }
                             vimRender();
                             return;
                         }
                         if (e.key === 'ArrowUp') {
                             if (vimLineNum > 0) { vimLineNum--; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
                             return;
                         }
                         if (e.key === 'ArrowDown') {
                             if (vimLineNum < vimBuffer.length - 1) { vimLineNum++; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
                             return;
                         }
                         if (e.key === 'ArrowLeft') {
                             if (vimCol > 0) { vimCol--; vimRender(); }
                             return;
                         }
                         if (e.key === 'ArrowRight') {
                             const maxCol = (vimBuffer[vimLineNum] || '').length;
                             if (vimCol < maxCol) { vimCol++; vimRender(); }
                             return;
                         }
                         vimRender();
                         return;
                     }

                     // Normal mode (~)
                     if (e.key === 'Escape') {
                         vimStatus = '~';
                         vimRender();
                         return;
                     }
                     if (e.key === 'i') {
                         vimStatus = '-- INSERT --';
                         vimRender();
                         return;
                     }
                     if (e.key === 'I') {
                         vimCol = 0;
                         vimStatus = '-- INSERT --';
                         vimRender();
                         return;
                     }
                     if (e.key === 'a') {
                         vimCol = Math.min(vimCol + 1, (vimBuffer[vimLineNum] || '').length);
                         vimStatus = '-- INSERT --';
                         vimRender();
                         return;
                     }
                     if (e.key === 'A') {
                         vimCol = (vimBuffer[vimLineNum] || '').length;
                         vimStatus = '-- INSERT --';
                         vimRender();
                         return;
                     }
                     if (e.key === 'o') {
                         vimBuffer.splice(vimLineNum + 1, 0, '');
                         vimLineNum++;
                         vimCol = 0;
                         vimStatus = '-- INSERT --';
                         vimRender();
                         return;
                     }
                     if (e.key === 'O') {
                         vimBuffer.splice(vimLineNum, 0, '');
                         vimLineNum++;
                         vimCol = 0;
                         vimStatus = '-- INSERT --';
                         vimRender();
                         return;
                     }
                     if (e.key === 'x') {
                         if (vimBuffer[vimLineNum]) {
                             vimBuffer[vimLineNum] = vimBuffer[vimLineNum].slice(0, -1);
                         }
                         vimRender();
                         return;
                     }
                     if (e.key === 'd' && e.altKey) {
                         if (vimLineNum < vimBuffer.length - 1) {
                             vimBuffer.splice(vimLineNum, 1);
                             if (vimLineNum >= vimBuffer.length) vimLineNum = vimBuffer.length - 1;
                         }
                         vimRender();
                         return;
                     }
                     if (e.key === 'd' && e.shiftKey) {
                         if (vimLineNum < vimBuffer.length - 1) {
                             vimBuffer.splice(vimLineNum, 1);
                             if (vimLineNum >= vimBuffer.length) vimLineNum = vimBuffer.length - 1;
                         }
                         vimRender();
                         return;
                     }
                     if (e.key === 'ArrowUp') {
                         if (vimLineNum > 0) { vimLineNum--; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
                         return;
                     }
                     if (e.key === 'ArrowDown') {
                         if (vimLineNum < vimBuffer.length - 1) { vimLineNum++; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
                         return;
                     }
                     if (e.key === 'ArrowLeft') {
                         if (vimCol > 0) { vimCol--; vimRender(); }
                         return;
                     }
                     if (e.key === 'ArrowRight') {
                         const maxCol = (vimBuffer[vimLineNum] || '').length;
                         if (vimCol < maxCol) { vimCol++; vimRender(); }
                         return;
                     }
                     if (e.key === 'G') {
                         vimLineNum = vimBuffer.length - 1;
                         vimRender();
                         return;
                     }
                     if (e.key === 'g') {
                         vimLineNum = 0;
                         vimRender();
                         return;
                     }
                     if (e.key === ':') {
                         vimStatus = ':';
                         vimRender();
                         return;
                     }
                     vimRender();
                 };

                 document.addEventListener('keydown', vimHandler);

                  const newAchievements = checkAchievements(cmdText, isRoot);
                  if (newAchievements.length > 0) {
                      revealAchievements();
                      newAchievements.forEach(a => showToast(a));
                  }

                  return;
              }

            if (cmdText === 'exit') {
                if (!isRoot) {
                    const newAchievements = checkAchievements(cmdText, false);
                    if (newAchievements.length > 0) {
                        revealAchievements();
                        newAchievements.forEach(a => showToast(a));
                    }

                    isLoginScreen = true;
                    document.body.innerHTML = '';
                    document.body.style.background = '#000';
                    document.body.style.color = '#fff';
                    document.body.style.fontFamily = 'monospace';
                    document.body.style.padding = '20px';
                    document.body.style.minHeight = '100vh';
                    document.body.style.margin = '0';
                    document.body.style.lineHeight = '1.6';

                    const loginContainer = document.createElement('div');
                    loginContainer.style.marginBottom = '10px';
                    loginContainer.textContent = 'homelab tty1';
                    document.body.appendChild(loginContainer);

                    const loginInput = document.createElement('input');
                    loginInput.type = 'text';
                    loginInput.style.background = 'transparent';
                    loginInput.style.border = 'none';
                    loginInput.style.outline = 'none';
                    loginInput.style.color = '#fff';
                    loginInput.style.fontFamily = 'monospace';
                    loginInput.style.fontSize = '14px';
                    loginInput.style.width = '300px';
                    loginInput.style.caretColor = '#fff';
                    loginInput.autofocus = true;

                    const loginLine = document.createElement('div');
                    loginLine.style.marginBottom = '20px';
                    loginLine.appendChild(document.createTextNode('homelab login: '));
                    loginLine.appendChild(loginInput);

                    document.body.appendChild(loginLine);

                    loginInput.focus();

                    const handleLogin = (e) => {
                        if (e.key === 'Enter') {
                            const deniedLine = document.createElement('div');
                            deniedLine.textContent = 'Access denied';
                            deniedLine.style.marginTop = '10px';
                            document.body.appendChild(deniedLine);

                            const newLoginLine = document.createElement('div');
                            newLoginLine.style.marginTop = '10px';
                            const newInput = document.createElement('input');
                            newInput.type = 'text';
                            newInput.style.background = 'transparent';
                            newInput.style.border = 'none';
                            newInput.style.outline = 'none';
                            newInput.style.color = '#fff';
                            newInput.style.fontFamily = 'monospace';
                            newInput.style.fontSize = '14px';
                            newInput.style.width = '300px';
                            newInput.style.caretColor = '#fff';
                            newInput.autofocus = true;
                            newLoginLine.appendChild(document.createTextNode('homelab login: '));
                            newLoginLine.appendChild(newInput);

                            document.body.appendChild(newLoginLine);

                            loginInput.remove();
                            newInput.focus();

                            newInput.addEventListener('keydown', handleLogin);
                        }
                    };

                    loginInput.addEventListener('keydown', handleLogin);

                    return;
                } else {
                    isRoot = false;
                }

                const newLine = document.createElement('div');
                newLine.innerHTML = '<span class="terminal-prompt">$</span> ';
                content.appendChild(newLine);
                const newCursor = document.createElement('span');
                newCursor.className = 'terminal-cursor';
                newLine.appendChild(newCursor);
                content.scrollTop = content.scrollHeight;

                return;
            }

            if (cmdText === 'rm -rf /') {
                if (!isRoot) {
                    const outLine = document.createElement('div');
                    outLine.style.whiteSpace = 'pre-wrap';
                    outLine.style.color = '#ef4444';
                    outLine.textContent = 'nice try';
                    content.appendChild(outLine);
                } else {
                    const outLine = document.createElement('div');
                    outLine.style.whiteSpace = 'pre-wrap';
                    outLine.style.color = '#ef4444';
                    outLine.textContent = 'System destruction initiated...';
                    content.appendChild(outLine);
                    setTimeout(() => {
                        document.body.innerHTML = '';
                        document.title = '';
                    }, 500);
                }

                const newLine = document.createElement('div');
                if (isRoot) {
                    newLine.innerHTML = '<span class="terminal-prompt">#</span> ';
                    newLine.style.color = '#ef4444';
                } else {
                    newLine.innerHTML = '<span class="terminal-prompt">$</span> ';
                }
                content.appendChild(newLine);
                const newCursor = document.createElement('span');
                newCursor.className = 'terminal-cursor' + (isRoot ? ' red' : '');
                newLine.appendChild(newCursor);
                content.scrollTop = content.scrollHeight;

                const newAchievements = checkAchievements(cmdText, isRoot);
                if (newAchievements.length > 0) {
                    revealAchievements();
                    newAchievements.forEach(a => showToast(a));
                }

                return;
            }

            if (cmdText === 'sudo su -' || cmdText === 'sudo -i') {
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.style.color = '#ef4444';
                outLine.textContent = 'I hope you know what you\'re doing';
                content.appendChild(outLine);

                isRoot = true;

                const newLine = document.createElement('div');
                newLine.innerHTML = '<span class="terminal-prompt">#</span> ';
                newLine.style.color = '#ef4444';
                content.appendChild(newLine);
                const newCursor = document.createElement('span');
                newCursor.className = 'terminal-cursor red';
                newLine.appendChild(newCursor);
                content.scrollTop = content.scrollHeight;

                const newAchievements = checkAchievements(cmdText, isRoot);
                if (newAchievements.length > 0) {
                    revealAchievements();
                    newAchievements.forEach(a => showToast(a));
                }

                return;
            }

            const commands = {
                'pwd': '/home/reese/portfolio',
                'whoami': 'reese',
                'hostname': 'homelab',
                'date': new Date().toString(),
                'uname': 'Linux homelab 7.0.0 #1 SMP x86_64 GNU/Linux',
                'uname -a': 'Linux homelab 6.8.0 #1 SMP x86_64 GNU/Linux',
                'uptime': ' 14:30:00 up 42 days, 3:15, 1 user, load average: 0.42, 0.38, 0.35',
                'id': 'uid=1000(reese) gid=1000(reese) groups=1000(reese),985(podman)',
                'cat /etc/os-release': 'PRETTY_NAME="Fedora Linux 69 (Workstation Edition)"\nNAME="Fedora Linux"\nVERSION_ID="69"\nVERSION="69 (Workstation Edition)"\nID=fedora\nVARIANT=Workstation Edition\nVARIANT_ID=workstation\nLOGO=fedora-logo-icon\nCPE_NAME="cpe:/o:fedoralinux:fedora:69"\nDEFAULT_HOSTNAME="fedora"\nHOME_URL="https://fedoraproject.org/"\nDOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f69/system-administrators-guide/"\nSUPPORT_URL="https://ask.fedoraproject.org/"\nBUG_REPORT_URL="https://bugzilla.redhat.com/"\nREDHAT_BUGZILLA_PRODUCT="Fedora"\nREDHAT_BUGZILLA_PRODUCT_VERSION=69\nREDHAT_SUPPORT_PRODUCT="Fedora"\nREDHAT_SUPPORT_PRODUCT_VERSION=69',
                'cat ~/.ssh/id_ed25519.pub': 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpFmKLqRKzMwRe3WkqJvQrN5mHjF2pRn8sT6yUvWxRe reese@homelab',
                'docker ps': 'NAMES              STATUS              PORTS\nborg             Up 42 days        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp\ngitea            Up 42 days        0.0.0.0:222->22/tcp, 0.0.0.0:3000->3000/tcp\nnextcloud        Up 42 days        0.0.0.0:8080->80/tcp\nimmich           Up 42 days        0.0.0.0:3001->3000/tcp, 0.0.0.0:3002->3001/tcp\nopen-webui       Up 42 days        0.0.0.0:8081->8080/tcp\njellyfin         Up 42 days        0.0.0.0:8096->8096/tcp\nslopbox          Up 42 days        0.0.0.0:9090->80/tcp',
                'docker ls': 'NAMES              STATUS              PORTS\nborg             Up 42 days        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp\ngitea            Up 42 days        0.0.0.0:222->22/tcp, 0.0.0.0:3000->3000/tcp\nnextcloud        Up 42 days        0.0.0.0:8080->80/tcp\nimmich           Up 42 days        0.0.0.0:3001->3000/tcp, 0.0.0.0:3002->3001/tcp\nopen-webui       Up 42 days        0.0.0.0:8081->8080/tcp\njellyfin         Up 42 days        0.0.0.0:8096->8096/tcp\nslopbox          Up 42 days        0.0.0.0:9090->80/tcp',
                'docker container ls': 'NAMES              STATUS              PORTS\nborg             Up 42 days        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp\ngitea            Up 42 days        0.0.0.0:222->22/tcp, 0.0.0.0:3000->3000/tcp\nnextcloud        Up 42 days        0.0.0.0:8080->80/tcp\nimmich           Up 42 days        0.0.0.0:3001->3000/tcp, 0.0.0.0:3002->3001/tcp\nopen-webui       Up 42 days        0.0.0.0:8081->8080/tcp\njellyfin         Up 42 days        0.0.0.0:8096->8096/tcp\nslopbox          Up 42 days        0.0.0.0:9090->80/tcp',
                'podman ps': 'NAMES              STATUS\nhomepage         Up 5 hours\nllama            Up 42 days',
                'podman ls': 'NAMES              STATUS\nhomepage         Up 5 hours\nllama            Up 42 days',
                'podman container ls': 'NAMES              STATUS\nhomepage         Up 5 hours\nllama            Up 42 days',
                'systemctl list-units': 'UNIT                    LOAD   ACTIVE SUB     DESCRIPTION\nborg.service            loaded active running Borg Backup Service\ngitea.service           loaded active running Gitea\ndocker.service          loaded active running Docker Application Container Engine\nnextcloud.service       loaded active running Nextcloud\nimmich.service          loaded active running Immich\nopen-webui.service      loaded active running Open WebUI\njellyfin.service        loaded active running Jellyfin Media Server\nslopbox.service         loaded active running Slopbox\nhomepage.service        loaded active running Homepage Container',
                'systemctl list-units --type=service --state=running --no-pager': 'UNIT                    LOAD   ACTIVE SUB     DESCRIPTION\nborg.service            loaded active running Borg Backup Service\ngitea.service           loaded active running Gitea\ndocker.service          loaded active running Docker Application Container Engine\nnextcloud.service       loaded active running Nextcloud\nimmich.service          loaded active running Immich\nopen-webui.service      loaded active running Open WebUI\njellyfin.service        loaded active running Jellyfin Media Server\nslopbox.service         loaded active running Slopbox\nhomepage.service        loaded active running Homepage Container',
                'ss': 'Netid  State   Recv-Q  Send-Q   Local Address:Port    Peer Address:Port\ntcp  LISTEN  0       128      0.0.0.0:22           0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:80           0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:443          0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:222          0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3000         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3001         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:3002         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8080         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8081         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:8096         0.0.0.0:*\ntcp  LISTEN  0       128      0.0.0.0:9090         0.0.0.0:*\ntcp  LISTEN  0       128      [::]:22              [::]:*',
                'ip addr show': '1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN\n    inet 127.0.0.1/8 scope host lo\n    inet6 ::1/128 scope host\n2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP\n    inet 192.168.1.42/24 brd 192.168.1.255 scope global dynamic eth0\n    inet6 fe80::1/64 scope link',
                'df -h': 'Filesystem      Size  Used Avail Use% Mounted on\n/dev/sda2       465G  182G  258G  42% /\nudev            16G     0   16G   0% /dev\ntmpfs           16G  2.1M   16G   1% /dev/shm\n/dev/sda1       511M  6.6M  505M   2% /boot/efi\n/dev/sdb1       1.8T  945G  793G  55% /mnt/data\noverlay         1.8T  945G  793G  55% /var/lib/docker/overlay2',
                'free -h': '              total        used        free      shared  buff/cache   available\nMem:           31Gi       8.2Gi       12Gi       512Mi       11Gi        22Gi\nSwap:         2.0Gi          0B       2.0Gi',
                'ps aux': 'USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\nreese        1242  2.1 12.4 4285632 3932160 ?    Sl   May15  42:18 /opt/llama.cpp/build/bin/llama-server --model /models/Qwen3-30B-A3B.Q4_K_M.gguf --port 8082\ndocker       2341  1.2  6.8 8562348 2156032 ?     Sl   May15  28:45 /usr/bin/dockerd -H fd://\nreese        3456  0.8  3.2 2845632 1015808 ?    Sl   May15  18:22 /opt/open-webui/server\nreese        4567  0.5  2.1 1562348 665600 ?     Sl   May15  12:34 /usr/bin/python3 /opt/borg/borgmatic\nroot         5678  0.3  1.4 945632 448000 ?       Ssl  May15   8:12 /usr/bin/docker-proxy -p tcp:0.0.0.0:80:80\nreese        6789  0.2  1.1 745632 348000 ?       Ssl  May15   5:45 /usr/bin/podman run --name homepage\nroot         7890  0.1  0.8 545632 256000 ?       Ssl  May15   3:22 /usr/bin/docker-proxy -p tcp:0.0.0.0:443:443',
                'ps aux --sort=-%mem | head -10': 'USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\nreese        1242  2.1 12.4 4285632 3932160 ?    Sl   May15  42:18 /opt/llama.cpp/build/bin/llama-server --model /models/Qwen3-30B-A3B.Q4_K_M.gguf --port 8082\ndocker       2341  1.2  6.8 8562348 2156032 ?     Sl   May15  28:45 /usr/bin/dockerd -H fd://\nreese        3456  0.8  3.2 2845632 1015808 ?    Sl   May15  18:22 /opt/open-webui/server\nreese        4567  0.5  2.1 1562348 665600 ?     Sl   May15  12:34 /usr/bin/python3 /opt/borg/borgmatic\nroot         5678  0.3  1.4 945632 448000 ?       Ssl  May15   8:12 /usr/bin/docker-proxy -p tcp:0.0.0.0:80:80\nreese        6789  0.2  1.1 745632 348000 ?       Ssl  May15   5:45 /usr/bin/podman run --name homepage\nroot         7890  0.1  0.8 545632 256000 ?       Ssl  May15   3:22 /usr/bin/docker-proxy -p tcp:0.0.0.0:443:443',
                'neofetch': `                    'c.          reese@homelab\n                 ,xNMM.          ----------------------\n                                     .OMMMMo           OS: Fedora Linux 69 (Workstation Edition) x86_64\n               OMMM0,            Host: custom-build\n     .;loddo:' loolloddol;.      Kernel: 6.8.0\n   cKMMMMMMMMMMNWMMMMMMMMMM0:    Uptime: 42 days, 3 hours\n .KMMMMMMMMMMMMMMMMMMMMMMMWd.    Packages: 2847 (dnf)\n XMMMMMMMMMMMMMMMMMMMMMMMX.      Shell: bash 5.2.26\n;MMMMMMMMMMMMMMMMMMMMMMMM:       Resolution: 2560x1440\n:MMMMMMMMMMMMMMMMMMMMMMMM:       DE: GNOME 46.1\n.MMMMMMMMMMMMMMMMMMMMMMMMX.      WM: Mutter\n kMMMMMMMMMMMMMMMMMMMMMMMMWd.    Terminal: /dev/pts/0\n .XMMMMMMMMMMMMMMMMMMMMMMMMMMk   CPU: AMD Ryzen 9 7900X (24) @ 5.6GHz\n  .XMMMMMMMMMMMMMMMMMMMMMMK.     GPU: NVIDIA GeForce RTX 4090\n    kMMMMMMMMMMMMMMMMMMMMd       GPU: AMD Ryzen Built-in\n     ;KMMMMMMMWXXWMMMMMMMk.      Memory: 8.2Gi / 31Gi\n       .cooc,.    .,coo:.\n\n<span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span>`,
                'sl': '____\n|DD|____T_\n|_ |_____|<\n  @-@-@-oo\\',
'help': 'Available commands:\n  ls          List directory contents\n  pwd         Print working directory\n  whoami      Print current user\n  hostname    Print hostname\n  date        Print current date/time\n  uname       Print system information\n  uptime      Print system uptime\n  id          Print user identity\n  cat         Print file contents\n  docker      List running containers\n  podman      List running pods\n  systemctl   List running systemd services\n  ss          Show listening ports\n  ip          Show network interfaces\n  df          Show disk usage\n  free        Show memory usage\n  ps          Show running processes\n  apt         Package manager (update, install)\n  curl        Fetch a webpage\n  wget        Fetch a webpage\n  vim         Terminal text editor (try: vim or vim filename)\n  neofetch    System info display\n  sl          Steam locomotive\n  clear       Clear the terminal\n  exit        Exit to login screen\n  sudo        Gain root access\n  rm          Remove files\n  echo        Print text\n  help        Show this help message',
            };

            if (cmdText.startsWith('echo ')) {
                const output = cmdText.replace(/^echo\s+/, '');
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.textContent = output;
                outLine.style.color = '#ccc';
                content.appendChild(outLine);
            } else if (cmdText.startsWith('curl ')) {
                const url = cmdText.replace(/^curl\s+(?:-s\s+)?/, '');
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.style.color = '#ccc';
                outLine.textContent = 'Downloading...';
                content.appendChild(outLine);
                fetch(url)
                    .then(r => r.text())
                    .then(data => {
                        outLine.textContent = data;
                        content.scrollTop = content.scrollHeight;
                    })
                    .catch(err => {
                        outLine.textContent = 'curl: error fetching ' + url + ': ' + err.message;
                        content.scrollTop = content.scrollHeight;
                    });
            } else if (cmdText.startsWith('wget ') || cmdText.startsWith('wget ')) {
                const url = cmdText.replace(/^wget\s+(?:-O\s+\S+\s+)?/, '');
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.style.color = '#ccc';
                outLine.textContent = 'Downloading...';
                content.appendChild(outLine);
                fetch(url)
                    .then(r => r.text())
                    .then(data => {
                        outLine.textContent = data;
                        content.scrollTop = content.scrollHeight;
                    })
                    .catch(err => {
                        outLine.textContent = 'wget: error fetching ' + url + ': ' + err.message;
                        content.scrollTop = content.scrollHeight;
                    });
            } else if (cmdText.startsWith('apt ')) {
                const pkg = cmdText.replace(/^apt\s+/, '');
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.style.color = '#ccc';
                content.appendChild(outLine);

                if (pkg === 'update' || pkg.startsWith('update ')) {
                    outLine.textContent = 'Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]\nGet:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [128 kB]\nGet:3 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages [1,234 kB]\nGet:4 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [987 kB]\nFetched 2,478 kB in 3s (921 kB/s)\nReading package lists... Done\nBuilding dependency tree... Done\nReading state information... Done\nAll packages are up to date.';
                } else if (pkg.startsWith('install ')) {
                    const packageName = pkg.replace(/^install\s+/, '');
                    const installOutput = [
                        'Reading package lists... Done',
                        'Building dependency tree... Done',
                        'Reading state information... Done',
                        'The following NEW packages will be installed:',
                        '  ' + packageName,
                        '0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.',
                        'Need to get ' + Math.floor(Math.random() * 5000 + 500) + ' kB of archives.',
                        'After this operation, ' + Math.floor(Math.random() * 50 + 10) + ' MB of additional disk space will be used.',
                        'Get:1 http://archive.ubuntu.com/ubuntu jammy/main amd64 ' + packageName + ' amd64 ' + Math.random().toFixed(2) + ' [1,234 kB]',
                        'Fetched 1,234 kB in 1s (1,567 kB/s)',
                        'Selecting previously unselected package ' + packageName + '.',
                        'Preparing to unpack .../' + packageName + '_amd64.deb ...',
                        'Unpacking ' + packageName + ' (1.0.0) ...',
                        'Setting up ' + packageName + ' (1.0.0) ...',
                        'Processing triggers for man-db (2.10.2-1) ...'
                    ].join('\n');
                    outLine.textContent = installOutput;
                } else {
                    outLine.textContent = 'Usage: apt <command>\nCommands:\n  update    Update package lists\n  install   Install packages';
                }
            } else if (cmdText.startsWith('dnf ')) {
                const pkg = cmdText.replace(/^dnf\s+/, '');
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                outLine.style.color = '#ccc';
                content.appendChild(outLine);

                if (pkg === 'update' || pkg.startsWith('update ')) {
                    outLine.textContent = 'Fedora Linux 42 - x86_64\nFedora Linux 42 - x86_64 - Updates\nDependencies resolved.\n================================================================================\n Package          Architecture    Version            Repository        Size\n================================================================================\nUpdating:\n systemd          x86_64         256.4-1.fc42       fedora           4.2 M\n dbus             x86_64         1.16.0-1.fc42      fedora-updates   756 k\n\nTransaction Summary\n================================================================================\nUpgrade  2 Packages\n\nTotal download size: 5.0 M\nIs this ok [y/N]: Yes\nDownloading Packages:\n(1/2): systemd-256.4-1.fc42.x86_64.rpm        1.2 MB/s | 4.2 MB     00:03\n(2/2): dbus-1.16.0-1.fc42.x86_64.rpm          890 kB/s | 756 kB     00:00\n--------------------------------------------------------------------------------\nTotal                                           3.5 MB/s | 5.0 MB     00:01\nRunning transaction check\nTransaction check succeeded.\nRunning transaction test\nTransaction test succeeded.\nRunning transaction\n  Preparing        :                                                1/1\n  Updating         : systemd-256.4-1.fc42.x86_64                   1/4\n  Running scriptlet: systemd-256.4-1.fc42.x86_64                   1/4\n  Updating         : dbus-1.16.0-1.fc42.x86_64                     2/4\n  Running scriptlet: dbus-1.16.0-1.fc42.x86_64                     2/4\n  Cleanup          : dbus-1.16.0-1.fc42.x86_64                     3/4\n  Cleanup          : systemd-256.3-1.fc42.x86_64                   4/4\n  Running scriptlet: systemd-256.3-1.fc42.x86_64                   4/4\n  Verifying        : dbus-1.16.0-1.fc42.x86_64                     1/4\n  Verifying        : systemd-256.4-1.fc42.x86_64                   2/4\n\nUpdated:\n  systemd-256.4-1.fc42.x86_64    dbus-1.16.0-1.fc42.x86_64\n\nComplete!';
                } else if (pkg.startsWith('install ')) {
                    const packageName = pkg.replace(/^install\s+/, '');
                    const installOutput = [
                        'Last metadata expiration check: 0:15:32 ago on Sun May 31 14:30:00 2026.',
                        'Dependencies resolved.',
                        '================================================================================',
                        ' Package              Architecture    Version              Repository       Size',
                        '================================================================================',
                        'Installing:',
                        ' ' + packageName + '          x86_64         1.0.0-1.fc42         fedora          1.2 M',
                        '',
                        'Transaction Summary',
                        '================================================================================',
                        'Install  1 Package',
                        '',
                        'Total download size: 1.2 M',
                        'Installed size: 3.5 M',
                        'Is this ok [y/N]: Yes',
                        'Downloading Packages:',
                        '(' + packageName + ').rpm                                2.1 MB/s | 1.2 MB     00:00',
                        '--------------------------------------------------------------------------------',
                        'Total                                              1.8 MB/s | 1.2 MB     00:00',
                        'Running transaction check',
                        'Transaction check succeeded.',
                        'Running transaction test',
                        'Transaction test succeeded.',
                        'Running transaction',
                        '  Preparing        :                                                1/1',
                        '  Installing       : ' + packageName + '                                1/1',
                        '  Running scriptlet: ' + packageName + '                                1/1',
                        '  Verifying        : ' + packageName + '                                1/1',
                        '',
                        'Installed:',
                        '  ' + packageName + '-1.0.0-1.fc42.x86_64',
                        '',
                        'Complete!'
                    ].join('\n');
                    outLine.textContent = installOutput;
                } else {
                    outLine.textContent = 'Usage: dnf <command>\nCommands:\n  update    Update packages\n  install   Install packages';
                }
            } else if (commands[cmdText] !== undefined) {
                const output = commands[cmdText];
                const outLine = document.createElement('div');
                outLine.style.whiteSpace = 'pre-wrap';
                if (cmdText === 'neofetch') {
                    outLine.innerHTML = output;
                } else {
                    outLine.textContent = output;
                    outLine.style.color = '#ccc';
                }
                content.appendChild(outLine);
            }

            const newAchievements = checkAchievements(cmdText, isRoot);
            if (newAchievements.length > 0) {
                revealAchievements();
                newAchievements.forEach(a => showToast(a));
            }

            const newLine = document.createElement('div');
            if (isRoot) {
                newLine.innerHTML = '<span class="terminal-prompt">#</span> ';
                newLine.style.color = '#ef4444';
            } else {
                newLine.innerHTML = '<span class="terminal-prompt">$</span> ';
            }
            content.appendChild(newLine);
            const newCursor = document.createElement('span');
            newCursor.className = 'terminal-cursor' + (isRoot ? ' red' : '');
            newLine.appendChild(newCursor);
            content.scrollTop = content.scrollHeight;
        } else if (e.key === 'Backspace') {
            const lastLine = content.lastElementChild;
            if (lastLine) {
                e.preventDefault();
                mobileInput.value = mobileInput.value.slice(0, -1);
                lastInputValue = mobileInput.value;
                const cursorEl = lastLine.querySelector('.terminal-cursor');
                if (cursorEl) cursorEl.remove();
                lastLine.textContent = '';
                const promptSpan = document.createElement('span');
                promptSpan.className = 'terminal-prompt';
                promptSpan.textContent = isRoot ? '#' : '$';
                lastLine.appendChild(promptSpan);
                lastLine.appendChild(document.createTextNode(' '));
                lastLine.appendChild(document.createTextNode(mobileInput.value));
                const newCursor = document.createElement('span');
                newCursor.className = 'terminal-cursor' + (isRoot ? ' red' : '');
                lastLine.appendChild(newCursor);
            }
        }

        if (e.key === 'Tab') {
            e.preventDefault();
            const inputVal = mobileInput.value;
            if (!inputVal) return;

            function arraysEqual(a, b) {
                if (a.length !== b.length) return false;
                for (let i = 0; i < a.length; i++) {
                    if (a[i] !== b[i]) return false;
                }
                return true;
            }

            isTabCompleting = true;

            const matchSource = tabBaseInput || inputVal;
            const matches = allCommands.filter(cmd => cmd.startsWith(matchSource));

            if (matches.length === 0) {
                isTabCompleting = false;
                return;
            }

            if (matches.length === 1) {
                tabCycleIndex = -1;
                tabMatches = [];
                tabBaseInput = '';
                mobileInput.value = matches[0];
                lastInputValue = matches[0];
                updateDisplay(mobileInput.value);
            } else if (!arraysEqual(tabMatches, matches) || tabBaseInput !== matchSource) {
                tabMatches = matches;
                tabBaseInput = matchSource;
                tabCycleIndex = 0;
                mobileInput.value = matches[0];
                lastInputValue = matches[0];
                updateDisplay(matches[0]);
            } else {
                tabCycleIndex = (tabCycleIndex + 1) % matches.length;
                mobileInput.value = matches[tabCycleIndex];
                lastInputValue = matches[tabCycleIndex];
                updateDisplay(matches[tabCycleIndex]);
            }
            isTabCompleting = false;
        }
    });

    terminal.addEventListener('focus', () => {
        mobileInput.focus();
        terminal.style.boxShadow = '0 0 8px rgba(234, 179, 8, 0.3), inset 0 0 20px rgba(34, 197, 94, 0.1)';
        terminal.style.borderColor = '#eab308';
        terminal.classList.add('grown');
        terminal.classList.add('opaque');
        const face = terminal.closest('.server-face');
        const unit = face?.closest('.rack-unit');
        face?.classList.add('grown');
        unit?.classList.add('grown');
        document.getElementById('hero').classList.add('shifted');
        document.querySelector('.rack-container')?.classList.add('opaque');
    });

    terminal.addEventListener('blur', () => {
        if (heroMouseDown) return;
        terminal.style.boxShadow = '';
        terminal.style.borderColor = '#2a2a2e';
        terminal.classList.remove('grown');
        terminal.classList.remove('opaque');
        const face = terminal.closest('.server-face');
        const unit = face?.closest('.rack-unit');
        face?.classList.remove('grown');
        unit?.classList.remove('grown');
        document.getElementById('hero').classList.remove('shifted');
        document.querySelector('.rack-container')?.classList.remove('opaque');
    });

  mobileInput.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') {
            if (inVimMode) return;
            mobileInput.blur();
        }
    });

    mobileInput.addEventListener('blur', () => {
        if (heroMouseDown) return;
        terminal.style.boxShadow = '';
        terminal.style.borderColor = '#2a2a2e';
        terminal.classList.remove('grown');
        terminal.classList.remove('opaque');
        const face = terminal.closest('.server-face');
        const unit = face?.closest('.rack-unit');
        face?.classList.remove('grown');
        unit?.classList.remove('grown');
        document.getElementById('hero').classList.remove('shifted');
        document.querySelector('.rack-container')?.classList.remove('opaque');
    });

    let lastInputValue = '';

    mobileInput.addEventListener('input', () => {
        if (isTabCompleting) return;
        tabCycleIndex = -1;
        tabMatches = [];
        tabBaseInput = '';
        const lastLine = content.lastElementChild;
        if (!lastLine) return;

        const inputText = mobileInput.value;
        const addedText = inputText.slice(lastInputValue.length);

        if (addedText) {
            const cursorEl = lastLine.querySelector('.terminal-cursor');
            if (cursorEl) cursorEl.remove();
            lastLine.insertAdjacentText('beforeend', addedText);
            const newCursor = document.createElement('span');
            newCursor.className = 'terminal-cursor' + (isRoot ? ' red' : '');
            lastLine.appendChild(newCursor);
        }

        lastInputValue = inputText;
    });

    return terminal;
}


// Achievement System
const ACHIEVEMENTS_STORAGE_KEY = 'reese-terminal-achievements';

const ACHIEVEMENTS = {
    time_flies: { name: 'Time Flies', desc: 'Check the system uptime', icon: '⏱️', cmd: 'uptime' },
    curious: { name: 'Curious', desc: 'List directory contents', icon: '📁', cmd: 'ls', prefix: true },
    port_scanner: { name: 'Port Scanner', desc: 'Check listening ports', icon: '🔍', cmd: 'ss', prefix: true },
    password_reset: { name: 'Password Reset Request', desc: 'Submit a SNOW request', icon: '🚪', cmd: 'exit' },
    power_user: { name: 'Power User', desc: 'Gain root access', icon: '👑', cmd: 'sudo su -' },
    nice_try: { name: 'Nice Try', desc: 'Attempt rm -rf / as a normal user', icon: '😏', cmd: 'rm -rf /' },
    restore_backup: { name: 'Restore from Backup', desc: 'Actually destroy the system as root', icon: '💥', cmd: 'rm -rf / root' },
    where_am_i: { name: 'Where Am I?', desc: 'Print working directory', icon: '📍', cmd: 'pwd' },
    self_aware: { name: 'Self-Aware', desc: 'Print current user', icon: '🪞', cmd: 'whoami' },
    identity: { name: 'Identity Crisis', desc: 'Print hostname', icon: '🖥️', cmd: 'hostname' },
    time_keeper: { name: 'Time Keeper', desc: 'Print current date', icon: '📅', cmd: 'date' },
    system_explorer: { name: 'System Explorer', desc: 'Print system information', icon: '🔧', cmd: 'uname' },
    access_granted: { name: 'Access Granted', desc: 'Check user identity', icon: '🆔', cmd: 'id' },
    os_detective: { name: 'OS Detective', desc: 'Read the OS release file', icon: '🐧', cmd: 'cat /etc/os-release' },
    ssh_explorer: { name: 'SSH Explorer', desc: 'View SSH public key', icon: '🔑', cmd: 'cat ~/.ssh/id_ed25519.pub' },
    container_watcher: { name: 'Container Watcher', desc: 'List Docker containers', icon: '🐳', cmd: 'docker ps', prefix: true },
    docker_confused: { name: 'Docker Confused', desc: 'Use wrong Docker command', icon: '🤔', cmd: 'docker ls', prefix: true },
    container_pro: { name: 'Container Pro', desc: 'Use correct container command', icon: '✅', cmd: 'docker container ls', prefix: true },
    podman_fan: { name: 'Podman Fan', desc: 'List Podman containers', icon: '📦', cmd: 'podman ps', prefix: true },
    podman_confused: { name: 'Podman Confused', desc: 'Use wrong Podman command', icon: '🤔', cmd: 'podman ls', prefix: true },
    podman_pro: { name: 'Podman Pro', desc: 'Use correct Podman command', icon: '✅', cmd: 'podman container ls', prefix: true },
    service_hunter: { name: 'Service Hunter', desc: 'List systemd units', icon: '🔎', cmd: 'systemctl list-units', prefix: true },
    service_filter: { name: 'Service Filter', desc: 'Filter running services', icon: '🎯', cmd: 'systemctl list-units --type=service --state=running --no-pager' },
    network_ninja: { name: 'Network Ninja', desc: 'Show network interfaces', icon: '🌐', cmd: 'ip addr show', prefix: true },
    disk_detective: { name: 'Disk Detective', desc: 'Check disk usage', icon: '💾', cmd: 'df -h' },
    memory_minded: { name: 'Memory Minded', desc: 'Check memory usage', icon: '🧠', cmd: 'free -h' },
    process_watcher: { name: 'Process Watcher', desc: 'List running processes', icon: '👁️', cmd: 'ps aux', prefix: true },
    memory_hog: { name: 'Memory Hog', desc: 'Find top memory consumers', icon: '🐗', cmd: 'ps aux --sort=-%mem | head -10' },
    aesthetic_mode: { name: 'Aesthetic Mode', desc: 'Display system info with style', icon: '✨', cmd: 'neofetch' },
    help_seeker: { name: 'Help Seeker', desc: 'Look up available commands', icon: '📖', cmd: 'help' },
    clean_slate: { name: 'Clean Slate', desc: 'Clear the terminal', icon: '🧹', cmd: 'clear' },
    train_spotter: { name: 'Train Spotter', desc: 'Run the steam locomotive', icon: '🚂', cmd: 'sl' },
    tain: { name: 'I like trains', desc: 'Choo chooooooo', icon: '🧹', cmd: 'sl' },
    web_navigator: { name: 'Web Navigator', desc: 'Fetch a webpage using curl or wget', icon: '🌐', cmd: 'curl', prefix: true },
    package_manager: { name: 'Package Manager', desc: 'Update package lists with apt', icon: '📦', cmd: 'apt update' },
    software_installer: { name: 'Software Installer', desc: 'Install a package with apt', icon: '🔧', cmd: 'apt install', prefix: true },
    fedora_updater: { name: 'Fedora Updater', desc: 'Update packages with dnf', icon: '🎯', cmd: 'dnf update' },
    fedora_installer: { name: 'Fedora Installer', desc: 'Install a package with dnf', icon: '📀', cmd: 'dnf install', prefix: true },
    vim_splash: { name: 'Vi sIgnificantly worse M', desc: 'Open vim without a filename', icon: '📝', cmd: 'vim' },
    vim_edit: { name: 'Actually Editing', desc: 'Open vim with a filename', icon: '✏️', cmd: 'vim ', prefix: true },
};

// Load unlocked achievement keys from localStorage
function loadAchievements() {
    try {
        const saved = localStorage.getItem(ACHIEVEMENTS_STORAGE_KEY);
        return saved ? JSON.parse(saved) : [];
    } catch {
        return [];
    }
}

// Persist unlocked achievement keys to localStorage
function saveAchievements(achieved) {
    localStorage.setItem(ACHIEVEMENTS_STORAGE_KEY, JSON.stringify(achieved));
}

// Check if the given command triggers any new achievements; returns unlocked achievement objects
function checkAchievements(cmdText, isRoot) {
    const achieved = loadAchievements();
    const newAchievements = [];

    for (const [key, achievement] of Object.entries(ACHIEVEMENTS)) {
        if (achieved.includes(key)) continue;

        if (key === 'restore_backup' && cmdText === 'rm -rf /' && isRoot) {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (key === 'power_user' && (cmdText === 'sudo su -' || cmdText === 'sudo -i')) {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (key === 'password_reset' && cmdText === 'exit' && !isRoot) {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (key === 'nice_try' && cmdText === 'rm -rf /' && !isRoot) {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (key === 'system_explorer' && (cmdText === 'uname' || cmdText === 'uname -a')) {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (key === 'docker_confused' && cmdText === 'docker ls') {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (key === 'podman_confused' && cmdText === 'podman ls') {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (key === 'web_navigator' && (cmdText.startsWith('curl ') || cmdText.startsWith('wget '))) {
            achieved.push(key);
            newAchievements.push(achievement);
        } else if (achievement.prefix ? cmdText.startsWith(achievement.cmd) : achievement.cmd === cmdText) {
            if ((key === 'nice_try' && isRoot) || (key === 'restore_backup' && !isRoot)) {
                continue;
            }
            achieved.push(key);
            newAchievements.push(achievement);
        }
    }

    if (newAchievements.length > 0) {
        saveAchievements(achieved);
    }

    return newAchievements;
}

// Display a toast notification for a newly unlocked achievement
function showToast(achievement) {
    const container = document.getElementById('toast-container') || createToastContainer();
    const toast = document.createElement('div');
    toast.className = 'toast';
    toast.innerHTML = `
        <div class="toast-icon">${achievement.icon}</div>
        <div class="toast-content">
            <div class="toast-label">Achievement Unlocked</div>
            <div class="toast-title">${achievement.name}</div>
        </div>
    `;
    container.appendChild(toast);

    setTimeout(() => {
        toast.classList.add('removing');
        setTimeout(() => toast.remove(), 300);
    }, 4000);
}

// Create the toast notification container element if it doesn't exist
function createToastContainer() {
    const container = document.createElement('div');
    container.id = 'toast-container';
    container.className = 'toast-container';
    document.body.appendChild(container);
    return container;
}

// Reveal the hidden achievements section and add it to the nav if needed
function revealAchievements() {
    const section = document.getElementById('achievements');
    if (section.style.display === 'none' || !section.style.display) {
        section.style.display = 'block';
        section.classList.add('fade-in');
        setTimeout(() => section.classList.add('visible'), 50);
        addAchievementsNav();
    }
    renderAchievements();
}

// Render all achievement cards (unlocked and locked) into the achievements grid
function renderAchievements() {
    const achieved = loadAchievements();
    const total = Object.keys(ACHIEVEMENTS).length;
    const count = achieved.length;

    const countEl = document.getElementById('achievements-count');
    countEl.textContent = `${count} / ${total} achievements unlocked`;

    const grid = document.getElementById('achievements-grid');
    grid.innerHTML = '';

    for (const [key, achievement] of Object.entries(ACHIEVEMENTS)) {
        const isUnlocked = achieved.includes(key);
        const card = document.createElement('div');
        card.className = `achievement-card ${isUnlocked ? 'unlocked' : 'locked'}`;
        card.innerHTML = `
            <div class="achievement-icon">${achievement.icon}</div>
            <div class="achievement-info">
                <h3>${isUnlocked ? achievement.name : '???'}</h3>
                <p>${isUnlocked ? achievement.desc : 'Keep exploring the terminal...'}</p>
            </div>
        `;
        grid.appendChild(card);
    }
}

// Add an "Achievements" link to the main navigation if achievements have been unlocked
function addAchievementsNav() {
    const navLinks = document.getElementById('navLinks');
    const existing = document.getElementById('nav-achievements');
    if (!existing && loadAchievements().length > 0) {
        const li = document.createElement('li');
        li.id = 'nav-achievements';
        li.innerHTML = '<a href="#achievements">Achievements</a>';
        navLinks.appendChild(li);
    }
}

// Restore previously unlocked achievements on page load
(function initAchievements() {
    const achieved = loadAchievements();
    if (achieved.length > 0) {
        revealAchievements();
        addAchievementsNav();
    }
})();
