⚒ BETA Wizardebop 3.00 ⚒

Acellus.com Adding final things slowly, but almost done!

// ==UserScript==
// @name         ⚒ BETA Wizardebop 3.00 ⚒
// @author       Type Stuff
// @description  Acellus.com Adding final things slowly, but almost done!
// @version      0.1
// @match        https://admin192a.acellus.com/student/*
// @match        https://admin192c.acellus.com/student/*
// @run-at       document-start
// @license      GNU GPLv3
// @grant        none
// @namespace    https://greasyfork.org/users/1394549
// @icon         https://img.freepik.com/free-vector/halloween-witch-hat-isolated-illustration_18591-83719.jpg
// ==/UserScript==

(function() {
  'use strict';

  /* ------------------
     1) SETTINGS & STATE
     ------------------ */
  const STORAGE = {
    wallpaper:   'wizardebop-wallpaper',
    unpause:     'wizardebop-unpause',
    pasteFast:   'wizardebop-paste',
    btnBg:       'wizardebop-btn-bg',
    btnHover:    'wizardebop-btn-hover',
    btnRadius:   'wizardebop-btn-radius',
    btnFont:     'wizardebop-btn-font',
    btnPad:      'wizardebop-btn-pad',
    animDur:     'wizardebop-anim-duration',
    password:    'wizardebop-password',
    keybind:     'wizardebop-keybind',
    notes:       'wizardebop-notes',
    todos:       'wizardebop-todos',
    showTimer:   'wizardebop-show-timer'
  };

  let autoUnpause       = localStorage.getItem(STORAGE.unpause) === 'true';
  let pasteFast         = localStorage.getItem(STORAGE.pasteFast) === 'true';
  let userPass          = localStorage.getItem(STORAGE.password) || '';
  let toggleKey         = localStorage.getItem(STORAGE.keybind) || 'F2';
  let savedNotes        = localStorage.getItem(STORAGE.notes) || '';
  let todoList          = JSON.parse(localStorage.getItem(STORAGE.todos) || '[]');
  let showTimerOnScreen = localStorage.getItem(STORAGE.showTimer) === 'true';

  const BTN = {
    bg:     localStorage.getItem(STORAGE.btnBg)     || 'rgba(128,128,128,0.5)',
    hover:  localStorage.getItem(STORAGE.btnHover)  || 'rgba(255,255,255,0.3)',
    radius: localStorage.getItem(STORAGE.btnRadius) || '6px',
    font:   localStorage.getItem(STORAGE.btnFont)   || '14px',
    pad:    localStorage.getItem(STORAGE.btnPad)    || '6px 12px'
  };
  const ANIM = {
    gradDur: +localStorage.getItem(STORAGE.animDur) || 12
  };

  // Timer state for General tab
  let timerInterval    = null;
  let timerElapsed     = 0;

  // Pomodoro state
  let pomoInterval     = null;
  let pomoRemaining    = 25 * 60;
  let pomoPhase        = 'work'; // 'work' or 'break'
  let pomoCycleCount   = 0;

  function save(k, v) { localStorage.setItem(k, v); }
  function saveTodos() { save(STORAGE.todos, JSON.stringify(todoList)); }

  /* -------------------
     2) AUTO-UNPAUSE
     ------------------- */
  function enableUnpause(){
    Object.defineProperty(document,'hidden',{get:()=>false});
    Object.defineProperty(document,'visibilityState',{get:()=> 'visible'});
    document.addEventListener('visibilitychange',e=>e.stopImmediatePropagation(),true);
  }
  if(autoUnpause) enableUnpause();
  new MutationObserver(()=>{ if(autoUnpause) enableUnpause(); })
    .observe(document,{childList:true,subtree:true});

  /* -------------------
     3) WALLPAPER HELPERS
     ------------------- */
  function loadWP(){ try { return JSON.parse(localStorage.getItem(STORAGE.wallpaper)); } catch { return null; } }
  function saveWP(type,val){ localStorage.setItem(STORAGE.wallpaper, JSON.stringify({ type, val })); }
  function createWP(){
    let el = document.getElementById('global-wallpaper');
    if(!el){ el = document.createElement('div'); el.id = 'global-wallpaper'; document.body.prepend(el); }
    return el;
  }
  function changeWP(type,val,saveFlag=true){
    const w = createWP();
    Object.assign(w.style,{
      position:'fixed', top:'0', left:'0',
      width:'100vw', height:'100vh',
      zIndex:'-1', pointerEvents:'none', animation:''
    });
    if(type==='gradient'){
      w.style.background = 'linear-gradient(135deg,rgba(255,182,193,0.6),rgba(176,224,230,0.6),rgba(221,160,221,0.6),rgba(255,228,181,0.6))';
      w.style.backgroundSize = '200% 200%';
      w.style.animation = `pastelGradient ${ANIM.gradDur}s ease infinite`;
    } else if(type.startsWith('ai_')){
      const topic = type.split('_')[1];
      w.style.background = `url('https://source.unsplash.com/1600x900/?ai-art,${topic}') no-repeat center/cover`;
    } else if(type==='custom'){
      w.style.background = val;
    } else if(type==='upload'){
      w.style.background = `url('${val}') no-repeat center/cover`;
    }
    if(saveFlag) saveWP(type,val);
  }

  /* -------------------
     4) PASTE-ESSAYS GUI
     ------------------- */
  function setupPaste(){
    let last = null;
    const overlay = document.createElement('div');
    overlay.id = 'pasteOverlay';
    overlay.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);' +
      'background:rgba(0,0,0,0.7);padding:20px;border-radius:8px;z-index:10003;display:none;';
    overlay.innerHTML =
      `<div style='display:flex;flex-direction:column;gap:10px;'>
         <h3 style='margin:0;color:#000'>✎ Paste Anything</h3>
         <textarea id='pasteText' style='width:300px;height:100px;padding:8px;border-radius:4px;border:none;color:#000'></textarea>
         <div style='display:flex;justify-content:space-between;'>
           <button id='pasteNow' style='padding:6px 12px;border:none;border-radius:4px;cursor:pointer;background:${BTN.bg};color:#000;transition:background 0.3s;'>Paste</button>
           <button id='closePaste' style='padding:6px 12px;border:none;border-radius:4px;cursor:pointer;background:${BTN.bg};color:#000;transition:background 0.3s;'>Close</button>
         </div>
       </div>`;
    document.body.appendChild(overlay);

    overlay.querySelector('#pasteNow').addEventListener('click',()=>{
      const txt = overlay.querySelector('#pasteText').value;
      if(last){
        last.focus();
        let i=0, ev=new Event('input',{bubbles:true});
        const iv=setInterval(()=>{
          if(last.isContentEditable) last.textContent += txt[i];
          else last.value += txt[i];
          last.dispatchEvent(ev);
          if(++i>=txt.length) clearInterval(iv);
        },5);
      }
      overlay.style.display='none';
    });
    overlay.querySelector('#closePaste').addEventListener('click',()=>overlay.style.display='none');
    document.addEventListener('click', e=>{
      if(!pasteFast) return;
      const t = e.target;
      if(document.getElementById('settings-menu')?.contains(t)) return;
      if(overlay.contains(t)) return;
      if(t.isContentEditable || t.nodeName==='TEXTAREA' || (t.nodeName==='INPUT'&&t.type==='text')){
        last = t; overlay.style.display='block';
      }
    }, true);
  }

  /* -------------------
     5) STYLE INJECTION
     ------------------- */
  const styleEl = document.createElement('style');
  styleEl.textContent = `
    @keyframes pastelGradient {0%{background-position:0% 0%}50%{background-position:100% 100%}100%{background-position:0% 0%}}
    #settings-overlay {position:fixed;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.2);backdrop-filter:blur(4px);z-index:10000;display:none}
    #settings-menu {position:fixed;top:50%;left:50%;transform:translate(-50%,-50%) scale(0.8);width:760px;height:420px;background:rgba(255,255,255,0.8);backdrop-filter:blur(6px);border-radius:12px;box-shadow:0 0 20px rgba(0,0,0,0.5);display:none;flex-direction:row;z-index:10001;opacity:0;transition:opacity 0.3s ease,transform 0.3s ease}
    #settings-menu.visible {display:flex;opacity:1;transform:translate(-50%,-50%) scale(1)}
    #settings-button {position:fixed;bottom:20px;right:20px;background:rgba(128,128,128,0.5);color:#000;border:none;border-radius:6px;padding:6px;font-size:18px;cursor:pointer;z-index:10002;backdrop-filter:blur(4px);transition:transform 0.2s}
    #settings-button:hover {transform:scale(1.1)}
    .settings-categories {width:20%;background:rgba(0,0,0,0.1);display:flex;flex-direction:column;padding:10px;overflow-y:auto}
    .settings-categories button {background:rgba(255,255,255,0.5);color:#000;border:none;margin:4px 0;padding:6px;border-radius:6px;cursor:pointer;transition:background 0.3s,transform 0.2s;text-align:left;font-size:14px}
    .settings-categories button:hover {background:rgba(200,200,200,0.6);transform:translateX(4px)}
    .settings-categories button.active {background:rgba(200,200,200,0.8);color:#000}
    .settings-details {width:80%;padding:20px;overflow-y:auto;color:#000;position:relative}
    .category-menu {display:none}
    .category-menu.active {display:block}
    .category-menu h3 {margin-top:0;color:#000;font-size:18px}
    .category-menu h4 {margin:12px 0 4px;color:#000;font-size:16px}
    .category-menu label {display:block;margin:8px 0;font-size:14px;color:#000}
    .category-menu input.wm-input {width:90%;margin:4px 0;padding:4px;border-radius:4px;border:1px solid #ccc;color:#000}
    button.wm-button {margin:6px 4px;padding:${BTN.pad};background:${BTN.bg};border:none;border-radius:${BTN.radius};color:#000;font-size:${BTN.font};cursor:pointer;transition:background 0.3s}
    button.wm-button:hover {background:${BTN.hover}}
    #close-x {position:absolute;top:8px;right:8px;background:transparent;border:none;font-size:20px;cursor:pointer}
    /* On-screen timer */
    #screen-timer {
      position:absolute; top:100px; left:100px;
      background:rgba(0,0,0,0.7); color:#fff;
      padding:8px 12px; border-radius:4px;
      font-size:16px; cursor:move;
      z-index:10005; display:none; user-select:none;
    }
  `;
  document.head.appendChild(styleEl);

  /* -------------------
     6) CREATE ON-SCREEN TIMER
     ------------------- */
  let screenTimerEl;
  function createScreenTimer() {
    if (screenTimerEl) return;
    screenTimerEl = document.createElement('div');
    screenTimerEl.id = 'screen-timer';
    screenTimerEl.textContent = '00:00:00';
    document.body.appendChild(screenTimerEl);

    let dragging = false, offsetX = 0, offsetY = 0;
    screenTimerEl.addEventListener('mousedown', e => {
      dragging = true;
      offsetX = e.clientX - screenTimerEl.offsetLeft;
      offsetY = e.clientY - screenTimerEl.offsetTop;
      e.preventDefault();
    });
    document.addEventListener('mousemove', e => {
      if (dragging) {
        screenTimerEl.style.left = `${e.clientX - offsetX}px`;
        screenTimerEl.style.top  = `${e.clientY - offsetY}px`;
      }
    });
    document.addEventListener('mouseup', () => {
      dragging = false;
    });
    // initial visibility
    screenTimerEl.style.display = showTimerOnScreen ? 'block' : 'none';
  }

  /* -------------------
     7) BUILD SETTINGS MENU
     ------------------- */
  function buildMenu() {
    const overlay = document.createElement('div'); overlay.id = 'settings-overlay';
    document.body.appendChild(overlay);

    const btn = document.createElement('button'); btn.id = 'settings-button'; btn.textContent = '⚙️';
    document.body.appendChild(btn);

    const menu = document.createElement('div'); menu.id = 'settings-menu';
    menu.innerHTML =
      `<button id='close-x'>×</button>` +
      `<div class='settings-categories'>` +
        `<button class='cat-btn active' data-cat='wallpaper'>Wallpaper</button>` +
        `<button class='cat-btn' data-cat='general'>General</button>` +
        `<button class='cat-btn' data-cat='buttons'>Buttons</button>` +
        `<button class='cat-btn' data-cat='animations'>Animations</button>` +
        `<button class='cat-btn' data-cat='notes'>Notes</button>` +
        `<button class='cat-btn' data-cat='todo'>To-Do</button>` +
        `<button class='cat-btn' data-cat='pomodoro'>Pomodoro</button>` +
        `<button class='cat-btn' data-cat='extras'>Extras</button>` +
      `</div>` +
      `<div class='settings-details'>` +
        // Wallpaper
        `<div class='category-menu active' id='wallpaper'>` +
          `<h3>Wallpaper</h3>` +
          `<button class='wm-button' data-wallpaper='gradient'>Gradient</button>` +
          `<button class='wm-button' data-wallpaper='ai_nature'>AI Nature</button>` +
          `<button class='wm-button' data-wallpaper='ai_cityscape'>AI Cityscape</button>` +
          `<button class='wm-button' data-wallpaper='ai_abstract'>AI Abstract</button>` +
          `<button class='wm-button' data-wallpaper='custom'>Custom Color</button>` +
          `<button class='wm-button' id='upload-wallpaper'>Upload</button>` +
          `<input type='file' id='upload-input' accept='image/*'>` +
        `</div>` +
        // General w/ Timer and on-screen toggle
        `<div class='category-menu' id='general'>` +
          `<h3>General</h3>` +
          `<label><input type='checkbox' id='chk-unpause' ${autoUnpause?'checked':''}/> Auto-Unpause</label>` +
          `<label><input type='checkbox' id='chk-paste' ${pasteFast?'checked':''}/> Paste Fast</label>` +
          `<label>Password: <input type='password' id='menu-pass' class='wm-input' value='${userPass}'></label>` +
          `<label>Keybind: <button id='keybind-btn' class='wm-button'>${toggleKey===' ' ? 'Space' : toggleKey}</button></label>` +
          `<h4>Timer</h4>` +
          `<span id='timer-display-general'>00:00:00</span>` +
          `<label><input type='checkbox' id='chk-show-screen' ${showTimerOnScreen?'checked':''}/> Show timer on screen</label><br>` +
          `<button id='timer-toggle-general' class='wm-button'>Start</button>` +
          `<button id='timer-reset-general' class='wm-button'>Reset</button>` +
          `<button class='wm-button' id='apply-general'>Apply</button>` +
        `</div>` +
        // Buttons
        `<div class='category-menu' id='buttons'>` +
          `<h3>Buttons</h3>` +
          `<label>BG:<br><input id='btn-bg' class='wm-input' value='${BTN.bg}'></label>` +
          `<label>Hover BG:<br><input id='btn-hover' class='wm-input' value='${BTN.hover}'></label>` +
          `<label>Radius:<br><input id='btn-radius' class='wm-input' value='${BTN.radius}'></label>` +
          `<label>Font Size:<br><input id='btn-font' class='wm-input' value='${BTN.font}'></label>` +
          `<label>Padding:<br><input id='btn-pad' class='wm-input' value='${BTN.pad}'></label>` +
          `<button class='wm-button' id='apply-buttons'>Apply</button>` +
        `</div>` +
        // Animations
        `<div class='category-menu' id='animations'>` +
          `<h3>Animations</h3>` +
          `<label>Gradient Duration (s):<br><input type='number' id='anim-duration' class='wm-input' value='${ANIM.gradDur}' min='1'></label>` +
          `<button class='wm-button' id='apply-animations'>Apply</button>` +
        `</div>` +
        // Notes
        `<div class='category-menu' id='notes'>` +
          `<h3>Notes</h3>` +
          `<textarea id='notes-text' style='width:100%;height:200px;padding:8px;border:1px solid #ccc;border-radius:4px;'>${savedNotes}</textarea>` +
          `<button id='save-notes' class='wm-button'>Save Notes</button>` +
        `</div>` +
        // To-Do
        `<div class='category-menu' id='todo'>` +
          `<h3>To-Do List</h3>` +
          `<input id='todo-input' placeholder='New task...'><button id='add-todo' class='wm-button'>Add</button>` +
          `<ul id='todo-list'></ul>` +
        `</div>` +
        // Pomodoro
        `<div class='category-menu' id='pomodoro'>` +
          `<h3>Pomodoro Timer</h3>` +
          `<div id='pomodoro-cycle'>Cycle: ${pomoCycleCount}</div>` +
          `<div id='pomodoro-display'>25:00</div>` +
          `<button id='pomodoro-start' class='wm-button'>Start</button>` +
          `<button id='pomodoro-stop' class='wm-button'>Stop</button>` +
          `<button id='pomodoro-reset' class='wm-button'>Reset</button>` +
        `</div>` +
        // Extras
        `<div class='category-menu' id='extras'><h3>Extras</h3><p>More coming soon…</p></div>` +
      `</div>`;
    document.body.appendChild(menu);

    // Category tabs
    menu.querySelectorAll('.cat-btn').forEach(b=>{
      b.addEventListener('click', ()=>{
        menu.querySelectorAll('.cat-btn').forEach(x=>x.classList.remove('active'));
        menu.querySelectorAll('.category-menu').forEach(x=>x.classList.remove('active'));
        b.classList.add('active');
        menu.querySelector('#'+b.dataset.cat).classList.add('active');
      });
    });

    const showMenu = ()=>{ overlay.style.display='block'; menu.classList.add('visible'); };
    const hideMenu = ()=>{
      menu.classList.remove('visible');
      overlay.style.display='none';
    };

    // Open/Close handlers
    btn.addEventListener('click', ()=>{
      if(userPass){
        const p=prompt('Enter password:');
        if(p!==userPass) return;
      }
      showMenu();
    });
    document.addEventListener('keydown',e=>{
      if(e.key===toggleKey){
        if(menu.classList.contains('visible')) hideMenu();
        else {
          if(userPass){
            const p=prompt('Enter password:');
            if(p!==userPass) return;
          }
          showMenu();
        }
      }
    });
    menu.querySelector('#close-x').addEventListener('click', hideMenu);
    overlay.addEventListener('click', hideMenu);

    /* Wallpaper handlers */
    menu.querySelectorAll('[data-wallpaper]').forEach(b=>{
      b.addEventListener('click', ()=>{
        const t = b.dataset.wallpaper;
        if(t==='custom'){
          const c = prompt('Enter CSS color:', '#000000');
          if(c) changeWP('custom',c);
        } else changeWP(t,null);
      });
    });
    menu.querySelector('#upload-wallpaper').addEventListener('click', ()=> menu.querySelector('#upload-input').click());
    menu.querySelector('#upload-input').addEventListener('change',e=>{
      const f=e.target.files[0];
      if(f){
        const r=new FileReader();
        r.onload=ev=>changeWP('upload',ev.target.result);
        r.readAsDataURL(f);
      }
      e.target.value='';
    });

    /* General Apply & Timer */
    menu.querySelector('#apply-general').addEventListener('click', ()=>{
      autoUnpause = menu.querySelector('#chk-unpause').checked;
      pasteFast   = menu.querySelector('#chk-paste').checked;
      userPass    = menu.querySelector('#menu-pass').value;
      showTimerOnScreen = menu.querySelector('#chk-show-screen').checked;
      save(STORAGE.unpause,autoUnpause);
      save(STORAGE.pasteFast,pasteFast);
      save(STORAGE.password,userPass);
      save(STORAGE.keybind,toggleKey);
      save(STORAGE.showTimer, showTimerOnScreen);
      if(autoUnpause) enableUnpause();
      // toggle on-screen timer visibility
      if(screenTimerEl) screenTimerEl.style.display = showTimerOnScreen ? 'block' : 'none';
      hideMenu();
    });

    // General timer controls
    const dispG = menu.querySelector('#timer-display-general');
    const btnTG = menu.querySelector('#timer-toggle-general');
    const btnRG = menu.querySelector('#timer-reset-general');
    function updateGeneral(){
      const h=Math.floor(timerElapsed/3600).toString().padStart(2,'0'),
            m=Math.floor((timerElapsed%3600)/60).toString().padStart(2,'0'),
            s=(timerElapsed%60).toString().padStart(2,'0');
      dispG.textContent = `${h}:${m}:${s}`;
      if(showTimerOnScreen && screenTimerEl){
        screenTimerEl.textContent = dispG.textContent;
      }
    }
    btnTG.addEventListener('click', ()=>{
      if(timerInterval){
        clearInterval(timerInterval);
        timerInterval = null;
        btnTG.textContent = 'Start';
      } else {
        createScreenTimer();
        if(showTimerOnScreen) screenTimerEl.style.display = 'block';
        timerInterval = setInterval(()=>{
          timerElapsed++;
          updateGeneral();
        },1000);
        btnTG.textContent = 'Stop';
      }
    });
    btnRG.addEventListener('click', ()=>{
      clearInterval(timerInterval);
      timerInterval = null;
      timerElapsed = 0;
      updateGeneral();
      btnTG.textContent = 'Start';
    });

    /* Buttons Apply */
    menu.querySelector('#apply-buttons').addEventListener('click', ()=>{
      const bg=menu.querySelector('#btn-bg').value,
            ho=menu.querySelector('#btn-hover').value,
            rd=menu.querySelector('#btn-radius').value,
            fn=menu.querySelector('#btn-font').value,
            pd=menu.querySelector('#btn-pad').value;
      save(STORAGE.btnBg,bg);
      save(STORAGE.btnHover,ho);
      save(STORAGE.btnRadius,rd);
      save(STORAGE.btnFont,fn);
      save(STORAGE.btnPad,pd);
      document.querySelectorAll('.wm-button').forEach(bc=>{
        Object.assign(bc.style,{background:bg,borderRadius:rd,fontSize:fn,padding:pd});
        bc.onmouseover=()=>bc.style.background=ho;
        bc.onmouseout =()=>bc.style.background=bg;
      });
    });

    /* Animations Apply */
    menu.querySelector('#apply-animations').addEventListener('click', ()=>{
      const d=+menu.querySelector('#anim-duration').value||12;
      ANIM.gradDur=d; save(STORAGE.animDur,d);
      const cur=loadWP();
      if(cur&&cur.type==='gradient') changeWP('gradient',null,false);
    });

    /* Notes Save */
    menu.querySelector('#save-notes').addEventListener('click', ()=>{
      const txt=menu.querySelector('#notes-text').value;
      save(STORAGE.notes,txt);
      alert('Notes saved');
    });

    /* To-Do List Logic */
    const todoInput = menu.querySelector('#todo-input');
    const todoUl    = menu.querySelector('#todo-list');
    function renderTodos(){
      todoUl.innerHTML='';
      todoList.forEach((t,i)=>{
        const li = document.createElement('li');
        li.className = 'todo-item'+(t.done?' completed':'');
        li.innerHTML =
          `<label><input type='checkbox' data-i='${i}' ${t.done?'checked':''}> <span>${t.text}</span></label>`+
          `<button data-i='${i}' class='wm-button'>✕</button>`;
        todoUl.appendChild(li);
      });
    }
    menu.querySelector('#add-todo').addEventListener('click', ()=>{
      const txt=todoInput.value.trim();
      if(!txt) return;
      todoList.push({ text:txt, done:false });
      todoInput.value=''; saveTodos(); renderTodos();
    });
    todoUl.addEventListener('click', e=>{
      const i=+e.target.dataset.i;
      if(e.target.tagName==='INPUT'){
        todoList[i].done=e.target.checked; saveTodos(); renderTodos();
      } else if(e.target.textContent==='✕'){
        todoList.splice(i,1); saveTodos(); renderTodos();
      }
    });
    renderTodos();

    /* Pomodoro Logic */
    const dispP  = menu.querySelector('#pomodoro-display');
    const cycleP = menu.querySelector('#pomodoro-cycle');
    const btnPS  = menu.querySelector('#pomodoro-start');
    const btnPP  = menu.querySelector('#pomodoro-stop');
    const btnPR  = menu.querySelector('#pomodoro-reset');
    function updatePomodoro(){
      const m=Math.floor(pomoRemaining/60).toString().padStart(2,'0'),
            s=(pomoRemaining%60).toString().padStart(2,'0');
      dispP.textContent=`${m}:${s}`;
      cycleP.textContent=`Cycle: ${pomoCycleCount}`;
    }
    btnPS.addEventListener('click', ()=>{
      if(pomoInterval) return;
      pomoInterval=setInterval(()=>{
        if(pomoRemaining>0){
          pomoRemaining--; updatePomodoro();
        } else {
          clearInterval(pomoInterval); pomoInterval=null;
          if(pomoPhase==='work'){
            pomoPhase='break'; pomoRemaining=5*60;
            alert('Work session done! Time for a 5-minute break.');
          } else {
            pomoPhase='work'; pomoRemaining=25*60; pomoCycleCount++;
            alert('Break over! Back to work.');
          }
          updatePomodoro();
        }
      },1000);
    });
    btnPP.addEventListener('click', ()=>{
      clearInterval(pomoInterval); pomoInterval=null;
    });
    btnPR.addEventListener('click', ()=>{
      clearInterval(pomoInterval); pomoInterval=null;
      pomoPhase='work'; pomoRemaining=25*60; pomoCycleCount=0; updatePomodoro();
    });
    updatePomodoro();

    /* Keybind Capture */
    const bindBtn = menu.querySelector('#keybind-btn');
    bindBtn.addEventListener('click', e=>{
      e.stopPropagation();
      bindBtn.textContent='Press any key…';
      const handler=ev=>{
        ev.preventDefault();
        toggleKey=ev.key; save(STORAGE.keybind,toggleKey);
        bindBtn.textContent=toggleKey===' ' ? 'Space' : toggleKey;
        document.removeEventListener('keydown', handler, true);
      };
      document.addEventListener('keydown', handler, true);
    });
  }

  /* -------------------
     8) INIT
     ------------------- */
  function init(){
    setupPaste();
    buildMenu();
    createScreenTimer();
  }
  if(document.readyState==='loading') document.addEventListener('DOMContentLoaded', init);
  else init();

  // Restore wallpaper
  const wp=loadWP();
  if(wp) window.addEventListener('DOMContentLoaded', ()=>changeWP(wp.type,wp.val,false));

})();