RGBTorn (v2.61)

RGBTorn. 2.61- patched with more comprehensive heading class search, exceptions added. Emoji (WIP). Responsive buttons

// ==UserScript==
// @name         RGBTorn (v2.61)
// @namespace    http://tampermonkey.net/
// @version      2.61
// @description  RGBTorn. 2.61- patched with more comprehensive heading class search, exceptions added. Emoji (WIP). Responsive buttons
// @match        https://www.torn.com/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
  'use strict';

  /* --------------------
     Default settings
     -------------------- */
  const defaults = {
    text: {
      scheme: 'vivid',       // vivid | pastel | dark | light
      speed: 30,             // seconds
      brightness: 1,         // multiplier
      saturation: 1,         // multiplier
      glow: true
    },
    background: {
      scheme: 'vivid',
      speed: 12,             // seconds
      opacity: 0.35,         // whole overlay opacity
      blend: 'overlay',      // overlay | screen | multiply | lighten | soft-light
      position: 'behind'     // 'behind' or 'over' (behind = tries to sit under content, over = on top)
    },
    visible: true
  };

 const SCHEMES = {
 vivid: ['red','orange','yellow','green','cyan','violet','red'],
pastel: ['#ffb3ba','#ffdfba','#ffffba','#baffc9','#bae1ff','#e1baff','#ffb3ba'],
dark: ['#ff4d4d','#ff944d','#ffff66','#66ff66','#66ffff','#b366ff','#ff4d4d'],
light: ['#ff6666','#ffb366','#ffff99','#99ff99','#99ffff','#cc99ff','#ff6666'],

// New ones
poison: ['#6a0dad','#32cd32','#39ff14','#6a0dad'],
sunset: ['#ff4500','#ff6a6a','#ff1493','#8a2be2'],
ocean: ['#20b2aa','#00ced1','#1e90ff','#000080'],
fire: ['#ff0000','#ff7f00','#ffff00','#ffffff'],
candy: ['#ff69b4','#dda0dd','#7fffd4','#98ff98'],
neon: ['#ff00ff','#39ff14','#00ffff','#ff00ff'],
royal: ['#6a0dad','#4b0082','#ffd700'],
bloodlust: ['#8b0000','#b22222','#000000'],

// Holiday / seasonal themes
jollyholly: ['#ff0000','#00ff00','#ffffff','#ffcccc'], // Christmas-y, festive
spookyshadows: ['#000000','#4b0082','#8b0000','#ff8c00'], // Halloween, dark and eerie
frostedpine: ['#e0f7fa','#a7ffeb','#00bfa5','#004d40'], // Winter/Christmas cold greens & blues
pumpkinspice: ['#ff7518','#ffb347','#8b4513','#f5deb3'], // Halloween autumnal vibes
candycane: ['#ff0000','#ffffff','#ffcccc','#ffe6e6'], // Sweet Christmas stripes

// Extra fun themes
aurora: ['#ff00ff','#00ffff','#00ff00','#ff4500'], // Northern Lights inspired
sunriseblush: ['#ffb6c1','#ff7f50','#ffd700','#ffa07a'], // Soft morning hues
volcanic: ['#ff4500','#ff6347','#8b0000','#4b0082'], // Hot molten lava feel
moonlitnight: ['#191970','#000080','#483d8b','#708090'], // Night sky vibes
tropicalrain: ['#00fa9a','#00ff7f','#7fffd4','#00ced1'], // Fresh tropical feel
galactic: ['#8a2be2','#4b0082','#00ffff','#ff1493'], // Spacey, neon galaxy feel
strawberryfields: ['#ff007f','#ff66a3','#ffb6c1','#ffe6f0'], // Sweet berry tones

};


  // storage
  let settings = JSON.parse(localStorage.getItem('rgbtorn_settings_v2')) || defaults;

  /* --------------------
     Helpers
     -------------------- */
  function saveSettings() {
    localStorage.setItem('rgbtorn_settings_v2', JSON.stringify(settings));
  }

  function cssGradientFromScheme(schemeName) {
    const arr = SCHEMES[schemeName] || SCHEMES.vivid;
    return `linear-gradient(270deg, ${arr.join(',')})`;
  }

  /* --------------------
     Overlay element
     -------------------- */
  let overlay = null;
  function ensureOverlay() {
    if (!overlay) {
      overlay = document.getElementById('rgbtorn-overlay-v2');
      if (!overlay) {
        overlay = document.createElement('div');
        overlay.id = 'rgbtorn-overlay-v2';
        // insert as first child so it's before most other nodes (we control stacking via z-index)
        document.body.insertBefore(overlay, document.body.firstChild);
      }
    }
  }

    /* --------------------
   Ensure emoji overlay exists
   -------------------- */
let emojiOverlay = null;
function ensureEmojiOverlay() {
  if (!emojiOverlay) {
    emojiOverlay = document.getElementById('rgbtorn-emoji-overlay');
    if (!emojiOverlay) {
      emojiOverlay = document.createElement('div');
      emojiOverlay.id = 'rgbtorn-emoji-overlay';
      emojiOverlay.style.cssText = `
        position: fixed;
        inset: 0;
        pointer-events: none;
        z-index: 1; /* above rainbow overlay, below content */
        overflow: hidden;
      `;
      document.body.insertBefore(emojiOverlay, document.body.firstChild.nextSibling);
    }
  }
}

/* --------------------
   Extend defaults for emoji overlay
   -------------------- */
if (!settings.emojiOverlay) {
  settings.emojiOverlay = {
    enabled: false,
    type: 'money',  // money | snow | cobwebs | hearts | stars
    density: 30,    // number of emojis
    speed: 1.5      // pixels per frame
  };
}

  /* --------------------
     Stacking control (for 'behind' mode)
     -------------------- */
  const stackSelector = '#mainContainer, .content-wrapper, #react-root, .main-layout';
  function adoptStackingAboveOverlay() {
    const els = Array.from(document.querySelectorAll(stackSelector));
    els.forEach(el => {
      try {
        if (el.dataset.rgbOrigPos === undefined) {
          el.dataset.rgbOrigPos = el.style.position || '';
          el.dataset.rgbOrigZ = el.style.zIndex || '';
        }
        const computed = window.getComputedStyle(el);
        if (computed.position === 'static') el.style.position = 'relative';
        el.style.zIndex = 1;
      } catch (e) {/* ignore */}
    });
  }
  function revertStackingChanges() {
    const els = Array.from(document.querySelectorAll(stackSelector));
    els.forEach(el => {
      try {
        if (el.dataset.rgbOrigPos !== undefined) {
          el.style.position = el.dataset.rgbOrigPos;
          el.style.zIndex = el.dataset.rgbOrigZ;
          delete el.dataset.rgbOrigPos;
          delete el.dataset.rgbOrigZ;
        }
      } catch (e) {/* ignore */}
    });
  }

  /* --------------------
     Apply styles (live preview + save)
     -------------------- */
  function applyStyles() {
    ensureOverlay();

    // remove old style tag then recreate
    const existing = document.getElementById('rgbtorn-style-v2');
    if (existing) existing.remove();

    const style = document.createElement('style');
    style.id = 'rgbtorn-style-v2';

    // Title gradient CSS
    const titleGradient = cssGradientFromScheme(settings.text.scheme);
    const textAnimSec = Math.max(1, Number(settings.text.speed) || defaults.text.speed);
    const textFilter = `brightness(${settings.text.brightness}) saturate(${settings.text.saturation})`;
    const glowCss = settings.text.glow ? 'text-shadow: 0 0 8px rgba(255,255,255,0.6);' : 'text-shadow: none;';

    style.textContent = `
      @keyframes rgbtornTextFlow {
        0% { background-position: 0% 50% }
        50% { background-position: 100% 50% }
        100% { background-position: 0% 50% }
      }
      @keyframes rgbtornBgFlow {
        0% { background-position: 0% 50% }
        50% { background-position: 100% 50% }
        100% { background-position: 0% 50% }
      }
    /* Titles and headings */
.content-title h1, .content-title h2, .content-title h3, .content-title h4, .content-title h5, .content-title h6,
h1[class*="title"]:not(.title___XfwKa),
h2[class*="title"]:not(.title___XfwKa),
h3[class*="title"]:not(.title___XfwKa),
h4[class*="title"]:not(.title___XfwKa),
h5[class*="title"]:not(.title___XfwKa),
h6[class*="title"]:not(.title___XfwKa),
h1[class^="heading___"],
h2[class^="heading___"],
h3[class^="heading___"],
h4[class^="heading___"],
h6[class^="heading___"] {
    background: ${titleGradient};
    background-size: 400% 400%;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    -moz-background-clip: text;
    -moz-text-fill-color: transparent;
    color: transparent;
    animation: rgbtornTextFlow ${textAnimSec}s linear infinite;
    -webkit-animation: rgbtornTextFlow ${textAnimSec}s linear infinite;
    -moz-animation: rgbtornTextFlow ${textAnimSec}s linear infinite;
    filter: ${textFilter};
    -webkit-filter: ${textFilter};
    ${glowCss}
}


      /* keep the overlay element basic (dynamic properties below will be applied inline) */
      #rgbtorn-overlay-v2 {
        position: fixed;
        inset: 0;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        pointer-events: none;
        background-size: 400% 400%;
        animation: rgbtornBgFlow ${Math.max(2, Number(settings.background.speed) || defaults.background.speed)}s linear infinite;
        -webkit-animation: rgbtornBgFlow ${Math.max(2, Number(settings.background.speed) || defaults.background.speed)}s linear infinite;
        -moz-animation: rgbtornBgFlow ${Math.max(2, Number(settings.background.speed) || defaults.background.speed)}s linear infinite;
        transition: opacity 220ms linear;
        -webkit-transition: opacity 220ms linear;
        -moz-transition: opacity 220ms linear;
      }
    `;
    document.head.appendChild(style);

    // configure overlay inline style
    overlay.style.backgroundImage = cssGradientFromScheme(settings.background.scheme);
    overlay.style.mixBlendMode = settings.background.blend;
    overlay.style.opacity = settings.background.opacity;
    if (settings.background.position === 'behind') {
      overlay.style.zIndex = 0;
      adoptStackingAboveOverlay();
    } else {
      overlay.style.zIndex = 9998;
      revertStackingChanges();
    }

    overlay.style.display = settings.visible ? 'block' : 'none';
  }
/* --------------------
   Emoji overlay logic
   -------------------- */
let emojis = [];

function createEmojis() {
  ensureEmojiOverlay();
  emojiOverlay.innerHTML = '';

  if (!settings.emojiOverlay.enabled) return;

  const types = {
    money: '💸',
    snow: '❄️',
    cobwebs: '🕸️',
    hearts: '❤️',
    stars: '⭐'
  };

  const emoji = types[settings.emojiOverlay.type] || '✨';
  const count = settings.emojiOverlay.density || 30;

  for (let i = 0; i < count; i++) {
    const span = document.createElement('span');
    span.textContent = emoji;
    span.className = 'rgbtorn-emoji';
    span.style.cssText = `
      position: absolute;
      top: 0;
      left: 0;
      font-size: ${Math.random() * 20 + 10}px;
      opacity: ${Math.random() * 0.8 + 0.2};
      transform: translate(${Math.random() * window.innerWidth}px, ${Math.random() * window.innerHeight}px);
      pointer-events: none;
      user-select: none;
    `;
    span.dataset.x = Math.random() * window.innerWidth;
    span.dataset.y = Math.random() * window.innerHeight;
    span.dataset.r = Math.random() * 360;
    emojiOverlay.appendChild(span);
  }
}


function animateEmojis() {
  if (!settings.emojiOverlay.enabled || !emojiOverlay) return;

  const speed = settings.emojiOverlay.speed || 1.5;
  const emojis = emojiOverlay.querySelectorAll('.rgbtorn-emoji');
  const screenHeight = window.innerHeight;

  function loop() {
    if (!settings.emojiOverlay.enabled) return;

    emojis.forEach(emoji => {
      const y = parseFloat(emoji.dataset.y) + speed;
      emoji.dataset.y = y;
      emoji.style.transform = `translate(${emoji.dataset.x}px, ${y}px) rotate(${emoji.dataset.r}deg)`;

      // reset if past bottom
      if (y > screenHeight + 50) {
        // reset to top at random X, Y, rotation, and size
        emoji.dataset.x = Math.random() * window.innerWidth;
        emoji.dataset.y = -Math.random() * 200;
        emoji.dataset.r = Math.random() * 360;
        emoji.style.transform = `translate(${emoji.dataset.x}px, ${emoji.dataset.y}px) rotate(${emoji.dataset.r}deg)`;
      }
    });

    requestAnimationFrame(loop);
  }

  requestAnimationFrame(loop);
}


  /* --------------------
     Build settings panel (items page only)
     Live preview on input; Save persists to localStorage
     Collapsible via toggle button; Save & Reset
     -------------------- */
function buildPanel() {
  if (!location.pathname.includes('item.php')) return; // items page only
  if (document.getElementById('rgbtorn-panel')) return;

  ensureOverlay();

  // --- Create overlay ---
  const overlay = document.createElement('div');
  overlay.id = 'rgbtorn-overlay';
  overlay.style.cssText = `
    position: fixed; inset: 0; background: rgba(0,0,0,0.6);
    display: none; z-index: 10000;
  `;
  document.body.appendChild(overlay);

  // --- Panel wrapper ---
  const panel = document.createElement('div');
  panel.id = 'rgbtorn-panel';
  panel.style.cssText = `
    position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 90%; max-width: 320px; max-height: 80%;
    background: rgba(12,12,12,0.96); color: #fff;
    padding: 10px 12px; border-radius: 10px;
    z-index: 10001; font-family: Arial, sans-serif; font-size: 13px;
    display: none; overflow: hidden;
    box-shadow: 0 0 12px rgba(0,0,0,0.6);
  `;

  // --- Scrollable inner content ---
  const inner = document.createElement('div');
  inner.id = 'rgbtorn-panel-inner';
  inner.style.cssText = `
    overflow-y: auto;
    max-height: calc(80vh - 60px);
    padding-right: 6px;
  `;

  // --- Panel header with close button ---
  const header = `
    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;">
      <strong style="font-size:15px">🌈 RGBTorn</strong>
      <button id="rgbtorn-close" style="background:none;border:none;color:#fff;font-size:16px;cursor:pointer;">✖️</button>
    </div>
    <div style="display:flex;gap:8px;margin-bottom:8px;align-items:center;">
      <button id="rgbtorn-save-btn" style="flex:1; color:#fff; background:#222; border:1px solid #444; border-radius:4px; padding:5px 0; cursor:pointer; transition:all 0.15s ease;">Save</button>
      <button id="rgbtorn-reset-btn" style="flex:1; color:#fff; background:#222; border:1px solid #444; border-radius:4px; padding:5px 0; cursor:pointer; transition:all 0.15s ease;">Reset</button>
    </div>
    <div id="rgbtorn-feedback" style="font-size:12px; text-align:center; min-height:16px; opacity:0; transition:opacity 0.3s ease;"></div>
  `;

  // --- Settings sections ---
  const content = `
    <div style="margin-bottom:6px"><strong>Titles</strong></div>
    <label style="display:block;margin-bottom:6px">Scheme:
      <select id="rgbtorn-text-scheme" style="width:100%">
        <option value="vivid">Vivid</option>
        <option value="pastel">Pastel</option>
        <option value="dark">Dark</option>
        <option value="light">Light</option>
        <option value="poison">Poison (purple/green)</option>
        <option value="sunset">Sunset (orange/pink/purple)</option>
        <option value="ocean">Ocean (teal/blue)</option>
        <option value="fire">Fire (red/orange/yellow)</option>
        <option value="candy">Candy (pink/pastel)</option>
        <option value="neon">Neon (bright)</option>
        <option value="royal">Royal (purple/gold)</option>
        <option value="bloodlust">Bloodlust (red/black)</option>
        <option value="jollyholly">Jolly Holly (Christmas)</option>
        <option value="spookyshadows">Spooky Shadows (Halloween)</option>
        <option value="frostedpine">Frosted Pine (winter)</option>
        <option value="pumpkinspice">Pumpkin Spice (Halloween)</option>
        <option value="candycane">Candy Cane (Christmas)</option>
        <option value="aurora">Aurora (Northern Lights)</option>
        <option value="sunriseblush">Sunrise Blush</option>
        <option value="volcanic">Volcanic</option>
        <option value="moonlitnight">Moonlit Night</option>
        <option value="tropicalrain">Tropical Rain</option>
        <option value="galactic">Galactic</option>
        <option value="strawberryfields">Strawberry Fields</option>
      </select>
    </label>
    <label style="display:block;margin-bottom:6px">Text Speed:
      <input id="rgbtorn-text-speed" type="number" min="1" max="60" style="width:72px"> s
    </label>
    <label style="display:block;margin-bottom:6px">Brightness:
      <input id="rgbtorn-text-bright" type="range" min="0.5" max="2" step="0.1" style="width:140px">
    </label>
    <label style="display:block;margin-bottom:6px">Saturation:
      <input id="rgbtorn-text-sat" type="range" min="0.5" max="2" step="0.1" style="width:140px">
    </label>
    <label style="display:block;margin-bottom:6px"><input id="rgbtorn-text-glow" type="checkbox"> Glow</label>

    <hr style="border:0;border-top:1px solid rgba(255,255,255,0.06);margin:8px 0">

    <div style="margin-bottom:6px"><strong>Background</strong></div>
    <label style="display:block;margin-bottom:6px">Scheme:
      <select id="rgbtorn-bg-scheme" style="width:100%">
        <option value="vivid">Vivid</option>
        <option value="pastel">Pastel</option>
        <option value="dark">Dark</option>
        <option value="light">Light</option>
        <option value="poison">Poison (purple/green)</option>
        <option value="sunset">Sunset (orange/pink/purple)</option>
        <option value="ocean">Ocean (teal/blue)</option>
        <option value="fire">Fire (red/orange/yellow)</option>
        <option value="candy">Candy (pink/pastel)</option>
        <option value="neon">Neon (bright)</option>
        <option value="royal">Royal (purple/gold)</option>
        <option value="bloodlust">Bloodlust (red/black)</option>
        <option value="jollyholly">Jolly Holly (Christmas)</option>
        <option value="spookyshadows">Spooky Shadows (Halloween)</option>
        <option value="frostedpine">Frosted Pine (winter)</option>
        <option value="pumpkinspice">Pumpkin Spice (Halloween)</option>
        <option value="candycane">Candy Cane (Christmas)</option>
        <option value="aurora">Aurora (Northern Lights)</option>
        <option value="sunriseblush">Sunrise Blush</option>
        <option value="volcanic">Volcanic</option>
        <option value="moonlitnight">Moonlit Night</option>
        <option value="tropicalrain">Tropical Rain</option>
        <option value="galactic">Galactic</option>
        <option value="strawberryfields">Strawberry Fields</option>
      </select>
    </label>
    <label style="display:block;margin-bottom:6px">BG Speed:
      <input id="rgbtorn-bg-speed" type="number" min="1" max="60" style="width:72px"> s
    </label>
    <label style="display:block;margin-bottom:6px">Opacity:
      <input id="rgbtorn-bg-opacity" type="range" min="0" max="1" step="0.05" style="width:140px">
    </label>
    <label style="display:block;margin-bottom:6px">Blend Mode:
      <select id="rgbtorn-bg-blend" style="width:100%">
        <option value="overlay">overlay</option>
        <option value="screen">screen</option>
        <option value="multiply">multiply</option>
        <option value="lighten">lighten</option>
        <option value="soft-light">soft-light</option>
      </select>
    </label>
    <label style="display:block;margin-bottom:6px">Position:
      <select id="rgbtorn-bg-pos" style="width:100%">
        <option value="behind">behind (try to sit under content)</option>
        <option value="over">over (on top of content)</option>
      </select>
    </label>

    <div style="font-size:11px;opacity:0.85;margin-top:8px">Changes preview as you move controls. Save to persist.</div>
  `;

  inner.innerHTML = content;
  panel.innerHTML = header;
  panel.appendChild(inner);
  document.body.appendChild(panel);

  // --- Floating toggle button ---
  const toggle = document.createElement('button');
  toggle.id = 'rgbtorn-toggle';
  toggle.title = 'RGBTorn settings';
  toggle.style.cssText = `
    position: fixed; bottom: 500px; right: 20px;
    width:50px;height:50px;border-radius:50%;
    border:none;background:#111;color:#fff;z-index:10002;cursor:pointer;font-size:22px;
  `;
  toggle.textContent = '🌈';
  toggle.addEventListener('click', () => {
    const isVisible = panel.style.display === 'block';
    panel.style.display = isVisible ? 'none' : 'block';
    overlay.style.display = isVisible ? 'none' : 'block';
  });
  document.body.appendChild(toggle);

  document.getElementById('rgbtorn-close').addEventListener('click', () => {
    panel.style.display = 'none';
    overlay.style.display = 'none';
  });

  overlay.addEventListener('click', () => {
    panel.style.display = 'none';
    overlay.style.display = 'none';
  });

  // --- Populate and attach events ---
  (id => document.getElementById(id).value = settings.text.scheme)('rgbtorn-text-scheme');
  (id => document.getElementById(id).value = settings.text.speed)('rgbtorn-text-speed');
  (id => document.getElementById(id).value = settings.text.brightness)('rgbtorn-text-bright');
  (id => document.getElementById(id).value = settings.text.saturation)('rgbtorn-text-sat');
  document.getElementById('rgbtorn-text-glow').checked = !!settings.text.glow;

  (id => document.getElementById(id).value = settings.background.scheme)('rgbtorn-bg-scheme');
  (id => document.getElementById(id).value = settings.background.speed)('rgbtorn-bg-speed');
  (id => document.getElementById(id).value = settings.background.opacity)('rgbtorn-bg-opacity');
  (id => document.getElementById(id).value = settings.background.blend)('rgbtorn-bg-blend');
  (id => document.getElementById(id).value = settings.background.position)('rgbtorn-bg-pos');

  function previewUpdate() {
    settings.text.scheme = document.getElementById('rgbtorn-text-scheme').value;
    settings.text.speed = Number(document.getElementById('rgbtorn-text-speed').value) || defaults.text.speed;
    settings.text.brightness = Number(document.getElementById('rgbtorn-text-bright').value) || defaults.text.brightness;
    settings.text.saturation = Number(document.getElementById('rgbtorn-text-sat').value) || defaults.text.saturation;
    settings.text.glow = !!document.getElementById('rgbtorn-text-glow').checked;

    settings.background.scheme = document.getElementById('rgbtorn-bg-scheme').value;
    settings.background.speed = Number(document.getElementById('rgbtorn-bg-speed').value) || defaults.background.speed;
    settings.background.opacity = Number(document.getElementById('rgbtorn-bg-opacity').value);
    settings.background.blend = document.getElementById('rgbtorn-bg-blend').value;
    settings.background.position = document.getElementById('rgbtorn-bg-pos').value;

    applyStyles();
  }

  const inputs = panel.querySelectorAll('input, select');
  inputs.forEach(inp => inp.addEventListener('input', previewUpdate));

  const feedback = document.getElementById('rgbtorn-feedback');
  const saveBtn = document.getElementById('rgbtorn-save-btn');
  const resetBtn = document.getElementById('rgbtorn-reset-btn');

  function showFeedback(text, color) {
    feedback.textContent = text;
    feedback.style.color = color;
    feedback.style.opacity = '1';
    setTimeout(() => feedback.style.opacity = '0', 1000);
  }

  function buttonFlash(btn, color) {
    btn.style.transform = 'scale(0.96)';
    btn.style.background = color;
    setTimeout(() => {
      btn.style.transform = '';
      btn.style.background = '#222';
    }, 200);
  }

  saveBtn.addEventListener('click', () => {
    saveSettings();
    buttonFlash(saveBtn, '#228B22');
    showFeedback('Saved!', '#32CD32');
  });

  resetBtn.addEventListener('click', () => {
    settings = JSON.parse(JSON.stringify(defaults));
    document.getElementById('rgbtorn-text-scheme').value = settings.text.scheme;
    document.getElementById('rgbtorn-text-speed').value = settings.text.speed;
    document.getElementById('rgbtorn-text-bright').value = settings.text.brightness;
    document.getElementById('rgbtorn-text-sat').value = settings.text.saturation;
    document.getElementById('rgbtorn-text-glow').checked = settings.text.glow;
    document.getElementById('rgbtorn-bg-scheme').value = settings.background.scheme;
    document.getElementById('rgbtorn-bg-speed').value = settings.background.speed;
    document.getElementById('rgbtorn-bg-opacity').value = settings.background.opacity;
    document.getElementById('rgbtorn-bg-blend').value = settings.background.blend;
    document.getElementById('rgbtorn-bg-pos').value = settings.background.position;
    applyStyles();
    saveSettings();
    buttonFlash(resetBtn, '#8B0000');
    showFeedback('Reset!', '#FF5555');
  });

  previewUpdate();
  extendPanelWithEmojiOptions(panel);
}


/* --------------------
   Extend settings panel with emoji controls
   -------------------- */
function extendPanelWithEmojiOptions(panel) {
  const emojiHTML = [
    '<hr style="border:0;border-top:1px solid rgba(255,255,255,0.06);margin:8px 0">',
    '<div style="margin-bottom:6px"><strong>Emoji Overlay</strong></div>',
    '<label style="display:block;margin-bottom:6px"><input id="rgbtorn-emoji-enable" type="checkbox"> Enable Overlay</label>',
    '<label style="display:block;margin-bottom:6px">Type:',
      '<select id="rgbtorn-emoji-type" style="width:100%">',
        '<option value="money">💸 Money</option>',
        '<option value="snow">❄️ Snow</option>',
        '<option value="cobwebs">🕸️ Cobwebs</option>',
        '<option value="hearts">❤️ Hearts</option>',
        '<option value="stars">⭐ Stars</option>',
      '</select>',
    '</label>',
    '<label style="display:block;margin-bottom:6px">Density:',
      '<input id="rgbtorn-emoji-density" type="number" min="5" max="200" style="width:72px">',
    '</label>',
    '<label style="display:block;margin-bottom:6px">Speed:',
      '<input id="rgbtorn-emoji-speed" type="number" min="0.1" max="5" step="0.1" style="width:72px"> px/frame',
    '</label>'
  ];
  panel.insertAdjacentHTML('beforeend', emojiHTML.join(''));

  // Populate current settings
  document.getElementById('rgbtorn-emoji-enable').checked = !!settings.emojiOverlay.enabled;
  document.getElementById('rgbtorn-emoji-type').value = settings.emojiOverlay.type;
  document.getElementById('rgbtorn-emoji-density').value = settings.emojiOverlay.density;
  document.getElementById('rgbtorn-emoji-speed').value = settings.emojiOverlay.speed;

  function emojiPreviewUpdate() {
  settings.emojiOverlay.enabled =
    document.getElementById('rgbtorn-emoji-enable').checked;
  settings.emojiOverlay.type =
    document.getElementById('rgbtorn-emoji-type').value;
  settings.emojiOverlay.density =
    Number(document.getElementById('rgbtorn-emoji-density').value) || 30;
  settings.emojiOverlay.speed =
    Number(document.getElementById('rgbtorn-emoji-speed').value) || 1.5;

  // apply instantly
  createEmojis();   // rebuild emoji elements
  animateEmojis();  // restart animation loop
}


  ['rgbtorn-emoji-enable','rgbtorn-emoji-type','rgbtorn-emoji-density','rgbtorn-emoji-speed']
    .forEach(id => document.getElementById(id).addEventListener('input', emojiPreviewUpdate));
}

/* --------------------
   Emoji overlay hotkey
   -------------------- */
document.addEventListener('keydown', (e) => {
  const tag = (document.activeElement && document.activeElement.tagName) || '';
  if (tag === 'INPUT' || tag === 'TEXTAREA' || document.activeElement.isContentEditable) return;
  if (e.key === 'e' || e.key === 'E') {
    settings.emojiOverlay.enabled = !settings.emojiOverlay.enabled;
    saveSettings();
    createEmojis();
    animateEmojis();
  }
});

  /* --------------------
     Hotkey: R toggles overlay on/off
     -------------------- */
  document.addEventListener('keydown', (e) => {
    const tag = (document.activeElement && document.activeElement.tagName) || '';
    if (tag === 'INPUT' || tag === 'TEXTAREA' || document.activeElement.isContentEditable) return;
    if (e.key === 'r' || e.key === 'R') {
      settings.visible = !settings.visible;
      saveSettings();
      applyStyles();
    }
  });

  /* --------------------
     Init
     -------------------- */
  try {
  ensureOverlay();
  applyStyles();
  buildPanel();
  overlay.style.display = settings.visible ? 'block' : 'none';

  // 🔹 Emoji overlay setup
  ensureEmojiOverlay();
  createEmojis();
  animateEmojis();

} catch (err) {
  console.error('RGBTorn init error', err);
}


})();