Bitcointalk Modern Theme

Modern light/dark/system theme for bitcointalk.org with separate customisable Main and Accent presets, plus an OFF mode. v2.9.2: Classic-first light palette and theme-aware light-thread post alternation.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Bitcointalk Modern Theme
// @namespace    bitcointalk-modern-theme
// @version      2.9.2
// @description  Modern light/dark/system theme for bitcointalk.org with separate customisable Main and Accent presets, plus an OFF mode. v2.9.2: Classic-first light palette and theme-aware light-thread post alternation.
// @license      MIT
// @match        *://*.bitcointalk.org/*
// @match        *://bitcointalk.org/*
// @run-at       document-start
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function () {
  'use strict';

  // ===========================================================================
  // Configuration
  // ===========================================================================

  const MAIN_PRESETS_DARK = {
    slate: { name: 'Slate (default)', base: '#15171D' },
    midnight: { name: 'Midnight', base: '#0F1424' },
    forest: { name: 'Forest', base: '#0E1A18' },
    plum: { name: 'Plum', base: '#1A0F1F' },
    charcoal: { name: 'Charcoal', base: '#141414' },
  };
  const MAIN_PRESETS_LIGHT = {
    // v2.8.3: Soft Sky remains the first/default light preset and is named
    // Classic. The old Pearl palette remains the second option.
    sky: { name: 'Classic (default)', base: '#EEF3F7' },
    pearl: { name: 'Pearl', base: '#F4F5F8' },
    cream: { name: 'Soft Cream', base: '#F4EFE6' },
    mint: { name: 'Soft Mint', base: '#EEF3EF' },
    rose: { name: 'Soft Rose', base: '#F5EEEE' },
  };

  const AUTO_ACCENT_MAP = {
    light: {
      sky:   '#47677F',  // classic muted steel blue
      pearl: '#3A3DAA',  // old pearl indigo
      cream: '#9A6842',  // muted rust
      mint:  '#4C735D',  // muted pine
      rose:  '#7B5662',  // muted plum
    },
    dark: {
      slate:    '#7F84D8', // muted periwinkle
      midnight: '#8E84CF', // muted lavender
      forest:   '#55B7A9', // muted aqua
      plum:     '#B779C2', // muted orchid
      charcoal: '#CC8E45', // muted amber
    },
  };

  const ACCENTS_DARK = {
    orange: { name: 'Bitcoin Orange', base: '#F7931A' },
  };
  const ACCENTS_LIGHT = {
    orange: { name: 'Bitcoin Orange', base: '#D97706' },
  };

  const DEFAULT_THEME = 'dark';
  const DEFAULT_ACCENT_DARK_KEY = 'orange';
  const DEFAULT_ACCENT_LIGHT_KEY = 'auto';
  const DEFAULT_MAIN_DARK_KEY = 'slate';
  const DEFAULT_MAIN_LIGHT_KEY = 'sky';
  const DEFAULT_CUSTOM_MAIN_DARK = '#15171D';
  const DEFAULT_CUSTOM_MAIN_LIGHT = '#F4F5F8';
  const DEFAULT_CUSTOM_ACCENT_DARK = '#F7931A';
  const DEFAULT_CUSTOM_ACCENT_LIGHT = '#5B7FA0';

  const KEY_THEME = 'bt-modern-theme';
  const KEY_THEME_PRIOR = 'bt-modern-theme-prior';
  const KEY_MAIN_DARK = 'bt-modern-main-dark';
  const KEY_MAIN_LIGHT = 'bt-modern-main-light';
  const KEY_ACCENT_DARK = 'bt-modern-accent-dark';
  const KEY_ACCENT_LIGHT = 'bt-modern-accent-light';
  const KEY_MAIN_DARK_CUSTOM = 'bt-modern-main-dark-custom';
  const KEY_MAIN_LIGHT_CUSTOM = 'bt-modern-main-light-custom';
  const KEY_ACCENT_DARK_CUSTOM = 'bt-modern-accent-dark-custom';
  const KEY_ACCENT_LIGHT_CUSTOM = 'bt-modern-accent-light-custom';

  const ALL_KEYS = [
    KEY_THEME,
    KEY_THEME_PRIOR,
    KEY_MAIN_DARK, KEY_MAIN_LIGHT,
    KEY_ACCENT_DARK, KEY_ACCENT_LIGHT,
    KEY_MAIN_DARK_CUSTOM, KEY_MAIN_LIGHT_CUSTOM,
    KEY_ACCENT_DARK_CUSTOM, KEY_ACCENT_LIGHT_CUSTOM,
  ];

  // Safari flash guard constants (integrated extreme-fast variant)
  const NAV_SELECTOR = '[class*="maintab_"] a, #main_menu a, .dropmenu a';
  const INCOMING_HOLD_STYLE_ID = 'bt-paint-hold';
  const OUTGOING_HOLD_STYLE_ID = 'bt-pre-nav-hold';
  const HOLD_REVEALED_ATTR = 'data-bt-revealed';
  const NAV_UNTIL_SESSION_KEY = 'bt-modern-nav-hold-until';
  const NAV_BG_SESSION_KEY = 'bt-modern-nav-hold-bg';
  const OUTGOING_CANCEL_RESTORE_MS = 120;
  const NAV_HOLD_SESSION_MS = 800;

  // ===========================================================================
  // Storage layer
  // ===========================================================================

  const hasGM = typeof GM_getValue === 'function' && typeof GM_setValue === 'function';

  function lsGet(key) {
    try { return localStorage.getItem(key); } catch (e) { return null; }
  }
  function lsSet(key, value) {
    try { localStorage.setItem(key, value); return true; } catch (e) { return false; }
  }
  function gmGet(key) {
    if (!hasGM) return null;
    try {
      const v = GM_getValue(key, null);
      return v == null ? null : String(v);
    } catch (e) { return null; }
  }
  function gmSet(key, value) {
    if (!hasGM) return false;
    try { GM_setValue(key, String(value)); return true; } catch (e) { return false; }
  }
  function ssGet(key) {
    try {
      const v = sessionStorage.getItem(key);
      return v == null || v === '' ? null : v;
    } catch (e) { return null; }
  }
  function ssSet(key, value) {
    try { sessionStorage.setItem(key, String(value)); } catch (e) {}
  }
  function ssRemove(key) {
    try { sessionStorage.removeItem(key); } catch (e) {}
  }

  function getPref(key, fallback) {
    let v = gmGet(key);
    if (v == null || v === '') v = lsGet(key);
    if (v == null || v === '') return fallback;
    return v;
  }

  function setPref(key, value) {
    const lsOk = lsSet(key, value);
    const gmOk = gmSet(key, value);
    return lsOk || gmOk;
  }

  function syncStores() {
    ALL_KEYS.forEach(k => {
      const ls = lsGet(k);
      const gm = gmGet(k);
      if (gm && (!ls || ls === '')) lsSet(k, gm);
      else if (ls && (!gm || gm === '') && hasGM) gmSet(k, ls);
    });
  }

  // ===========================================================================
  // Color helpers
  // ===========================================================================

  function hexToRgb(hex) {
    const c = String(hex || '').replace('#', '');
    const full = c.length === 3 ? c.split('').map(x => x + x).join('') : c;
    const n = parseInt(full, 16);
    return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
  }
  function clamp(v, min, max) { return Math.max(min, Math.min(max, v)); }
  function rgbToHex(r, g, b) {
    return '#' + [r, g, b]
      .map(x => clamp(Math.round(x), 0, 255).toString(16).padStart(2, '0'))
      .join('');
  }
  function lighten(hex, amt) {
    const { r, g, b } = hexToRgb(hex);
    return rgbToHex(r + (255 - r) * amt, g + (255 - g) * amt, b + (255 - b) * amt);
  }
  function darken(hex, amt) {
    const { r, g, b } = hexToRgb(hex);
    return rgbToHex(r * (1 - amt), g * (1 - amt), b * (1 - amt));
  }
  function rgbToHsl(r, g, b) {
    r /= 255; g /= 255; b /= 255;
    const max = Math.max(r, g, b), min = Math.min(r, g, b);
    let h, s; const l = (max + min) / 2;
    if (max === min) {
      h = 0; s = 0;
    } else {
      const d = max - min;
      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
      if (max === r) h = ((g - b) / d + (g < b ? 6 : 0));
      else if (max === g) h = (b - r) / d + 2;
      else h = (r - g) / d + 4;
      h /= 6;
    }
    return { h, s, l };
  }
  function hslToRgb(h, s, l) {
    let r, g, b;
    if (s === 0) {
      r = g = b = l;
    } else {
      const hue2rgb = (p, q, t) => {
        if (t < 0) t += 1;
        if (t > 1) t -= 1;
        if (t < 1 / 6) return p + (q - p) * 6 * t;
        if (t < 1 / 2) return q;
        if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
        return p;
      };
      const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
      const p = 2 * l - q;
      r = hue2rgb(p, q, h + 1 / 3);
      g = hue2rgb(p, q, h);
      b = hue2rgb(p, q, h - 1 / 3);
    }
    return { r: r * 255, g: g * 255, b: b * 255 };
  }
  function adjustHsl(hex, deltaL, deltaS) {
    const { r, g, b } = hexToRgb(hex);
    const hsl = rgbToHsl(r, g, b);
    const newL = clamp(hsl.l + deltaL, 0, 1);
    const newS = clamp(hsl.s + deltaS, 0, 1);
    const rgb = hslToRgb(hsl.h, newS, newL);
    return rgbToHex(rgb.r, rgb.g, rgb.b);
  }
  function relativeLuminance(hex) {
    const { r, g, b } = hexToRgb(hex);
    const [R, G, B] = [r, g, b].map(v => {
      v /= 255;
      return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
    });
    return 0.2126 * R + 0.7152 * G + 0.0722 * B;
  }
  function deriveAccent(hex) {
    return {
      base: hex,
      hover: lighten(hex, 0.15),
      active: darken(hex, 0.10),
      onText: relativeLuminance(hex) > 0.45 ? '#1A1D21' : '#FFFFFF',
    };
  }

  function deriveMainPalette(hex, theme) {
    if (theme === 'dark') {
      return {
        bg: hex,
        bgEnd: darken(hex, 0.06),
        surface1: lighten(hex, 0.06),
        surface2: lighten(hex, 0.12),
        surface3: lighten(hex, 0.20),
        postBg: lighten(hex, 0.055),
        postAltBg: lighten(hex, 0.085),
        posterBg: lighten(hex, 0.050),
        posterAltBg: lighten(hex, 0.075),
        inputBg: darken(hex, 0.06),
        quoteBg: lighten(hex, 0.04),
        codeBg: darken(hex, 0.06),
        border: 'rgba(255,255,255,0.07)',
        border2: 'rgba(255,255,255,0.14)',
        text: '#E3E3E8',
        text2: '#A8B0BA',
        text3: '#6B7480',
        iconFilter: 'invert(1) opacity(0.75)',
        shadow: '0 1px 0 rgba(0,0,0,0.2)',
        shadowLg: '0 12px 32px rgba(0,0,0,0.35)',
      };
    }

    // Light theme: all surfaces derive from the chosen main hex with hue
    // preserved (HSL adjust). v2.8.3 also derives post alternation colours
    // from the selected light theme, rather than hardcoding Classic/Sky.
    const navActiveBg = adjustHsl(hex, -0.38, 0.36);
    return {
      bg: hex,
      bgEnd: adjustHsl(hex, -0.035, 0.06),
      surface1: adjustHsl(hex, -0.055, 0.12),
      surface2: adjustHsl(hex, -0.12, 0.20),
      surface3: adjustHsl(hex, -0.20, 0.28),

      // Theme-aware thread alternation: Classic, Pearl, Cream, Mint and Rose
      // each receive their own two matching post tones.
      postBg: adjustHsl(hex, -0.010, 0.015),
      postAltBg: adjustHsl(hex, -0.045, 0.060),
      posterBg: adjustHsl(hex, -0.035, 0.045),
      posterAltBg: adjustHsl(hex, -0.070, 0.090),

      navActiveBg,
      navActiveText: relativeLuminance(navActiveBg) > 0.45 ? '#1A1D21' : '#FFFFFF',
      inputBg: '#FFFFFF',
      quoteBg: adjustHsl(hex, -0.02, 0.04),
      codeBg: adjustHsl(hex, -0.09, 0.18),
      border: 'rgba(0,0,0,0.08)',
      border2: 'rgba(0,0,0,0.16)',
      text: '#1A1D21',
      text2: '#4A5058',
      text3: '#7A8088',
      iconFilter: 'opacity(0.7)',
      shadow: '0 1px 0 rgba(0,0,0,0.04)',
      shadowLg: '0 12px 32px rgba(0,0,0,0.12)',
    };
  }

  function deriveAutoAccent(mainHex, theme, mainKey) {
    if (mainKey && AUTO_ACCENT_MAP[theme] && AUTO_ACCENT_MAP[theme][mainKey]) {
      return AUTO_ACCENT_MAP[theme][mainKey];
    }
    const { r, g, b } = hexToRgb(mainHex);
    const hsl = rgbToHsl(r, g, b);
    if (hsl.s < 0.05) {
      return theme === 'dark' ? '#E8A04A' : '#B5552B';
    }
    const newH = hsl.h;
    const newS = Math.min(0.65, Math.max(0.50, hsl.s + 0.25));
    const newL = theme === 'dark' ? 0.62 : 0.38;
    const rgb = hslToRgb(newH, newS, newL);
    return rgbToHex(rgb.r, rgb.g, rgb.b);
  }

  function toCssVar(name) {
    return '--bt-' + name
      .replace(/([A-Z]|\d+)/g, '-$1')
      .toLowerCase()
      .replace(/^-/, '');
  }

  // ===========================================================================
  // Theme application
  // ===========================================================================

  function getEffectiveTheme(pref) {
    if (pref === 'off') return 'off';
    if (pref === 'system') {
      return window.matchMedia &&
        window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark' : 'light';
    }
    return pref === 'light' ? 'light' : 'dark';
  }

  function getMainKey(theme) {
    const def = theme === 'dark' ? DEFAULT_MAIN_DARK_KEY : DEFAULT_MAIN_LIGHT_KEY;
    return getPref(theme === 'dark' ? KEY_MAIN_DARK : KEY_MAIN_LIGHT, def);
  }
  function getAccentKey(theme) {
    const def = theme === 'dark' ? DEFAULT_ACCENT_DARK_KEY : DEFAULT_ACCENT_LIGHT_KEY;
    return getPref(theme === 'dark' ? KEY_ACCENT_DARK : KEY_ACCENT_LIGHT, def);
  }
  function getActiveMainHex(theme) {
    const presets = theme === 'dark' ? MAIN_PRESETS_DARK : MAIN_PRESETS_LIGHT;
    const key = getMainKey(theme);
    if (key === 'custom') {
      const def = theme === 'dark' ? DEFAULT_CUSTOM_MAIN_DARK : DEFAULT_CUSTOM_MAIN_LIGHT;
      return getPref(theme === 'dark' ? KEY_MAIN_DARK_CUSTOM : KEY_MAIN_LIGHT_CUSTOM, def);
    }
    const fallbackKey = theme === 'dark' ? DEFAULT_MAIN_DARK_KEY : DEFAULT_MAIN_LIGHT_KEY;
    return (presets[key] || presets[fallbackKey]).base;
  }
  function getActiveAccentHex(theme) {
    const presets = theme === 'dark' ? ACCENTS_DARK : ACCENTS_LIGHT;
    const key = getAccentKey(theme);
    if (key === 'auto') {
      return deriveAutoAccent(getActiveMainHex(theme), theme, getMainKey(theme));
    }
    if (key === 'custom') {
      const def = theme === 'dark' ? DEFAULT_CUSTOM_ACCENT_DARK : DEFAULT_CUSTOM_ACCENT_LIGHT;
      return getPref(theme === 'dark' ? KEY_ACCENT_DARK_CUSTOM : KEY_ACCENT_LIGHT_CUSTOM, def);
    }
    if (presets[key]) {
      return presets[key].base;
    }
    return deriveAutoAccent(getActiveMainHex(theme), theme, getMainKey(theme));
  }

  function applyTheme() {
    const themePref = getPref(KEY_THEME, DEFAULT_THEME);
    const effective = getEffectiveTheme(themePref);
    const root = document.documentElement;

    if (effective === 'off') {
      root.setAttribute('data-bt-active', 'false');
      root.setAttribute('data-bt-theme-pref', themePref);
      if (themeStyleEl) themeStyleEl.disabled = true;
      root.style.colorScheme = '';
      updateSwitcherUI(themePref, effective, null, null, null, null);
      return;
    }

    if (themeStyleEl) themeStyleEl.disabled = false;

    const mainKey = getMainKey(effective);
    const accentKey = getAccentKey(effective);
    const mainHex = getActiveMainHex(effective);
    const accentHex = getActiveAccentHex(effective);
    const palette = deriveMainPalette(mainHex, effective);
    const accent = deriveAccent(accentHex);

    root.setAttribute('data-bt-active', 'true');
    root.setAttribute('data-bt-theme', effective);
    root.setAttribute('data-bt-theme-pref', themePref);
    root.setAttribute('data-bt-main', mainKey);
    root.setAttribute('data-bt-accent', accentKey);
    root.style.colorScheme = effective;

    Object.entries(palette).forEach(([k, v]) => root.style.setProperty(toCssVar(k), v));
    root.style.setProperty('--bt-accent', accent.base);
    root.style.setProperty('--bt-accent-h', accent.hover);
    root.style.setProperty('--bt-accent-a', accent.active);
    root.style.setProperty('--bt-on-accent', accent.onText);

    updateSwitcherUI(themePref, effective, mainKey, accentKey, mainHex, accentHex);
  }

  function updateSwitcherUI(themePref, effective, mainKey, accentKey, mainHex, accentHex) {
    const sw = document.getElementById('bt-switcher');
    if (!sw) return;

    const mainBtn = sw.querySelector('#bt-switcher-button');
    if (mainBtn) {
      if (themePref === 'off') {
        mainBtn.innerHTML = '<span class="bt-sw-on-text">ON</span>';
        mainBtn.title = 'Turn the theme back on';
        mainBtn.setAttribute('aria-label', 'Turn the theme back on');
      } else {
        mainBtn.innerHTML = ICONS.cog;
        mainBtn.title = 'Theme settings';
        mainBtn.setAttribute('aria-label', 'Theme settings');
      }
    }

    const customizeEl = sw.querySelector('.bt-sw-customize');
    if (customizeEl) {
      const hide = themePref === 'system' || themePref === 'off';
      customizeEl.style.display = hide ? 'none' : '';
    }
    const titleEl = sw.querySelector('#bt-sw-customize-title');
    if (titleEl && effective !== 'off') {
      titleEl.textContent = `Customise ${effective === 'dark' ? 'Dark' : 'Light'} Colours`;
    }

    sw.querySelectorAll('[data-theme]').forEach(b => {
      b.classList.toggle('selected', b.dataset.theme === themePref);
    });
    const offBtn = sw.querySelector('[data-theme="off"]');
    if (offBtn) {
      const lbl = offBtn.querySelector('.bt-sw-theme-label');
      if (lbl) lbl.textContent = themePref === 'off' ? 'ON' : 'OFF';
      offBtn.title = themePref === 'off' ? 'Turn the theme back on' : 'Turn the theme off';
    }

    if (effective !== 'off') {
      rebuildSwatches(sw, 'main', effective, mainKey, mainHex);
      rebuildSwatches(sw, 'accent', effective, accentKey, accentHex);
    }
  }

  function rebuildSwatches(sw, kind, effective, selectedKey, currentHex) {
    const row = sw.querySelector(`#bt-sw-${kind}-row`);
    if (!row) return;
    const presets = kind === 'main'
      ? (effective === 'dark' ? MAIN_PRESETS_DARK : MAIN_PRESETS_LIGHT)
      : (effective === 'dark' ? ACCENTS_DARK : ACCENTS_LIGHT);
    const customDef = kind === 'main'
      ? (effective === 'dark' ? DEFAULT_CUSTOM_MAIN_DARK : DEFAULT_CUSTOM_MAIN_LIGHT)
      : (effective === 'dark' ? DEFAULT_CUSTOM_ACCENT_DARK : DEFAULT_CUSTOM_ACCENT_LIGHT);
    const customStorageKey = kind === 'main'
      ? (effective === 'dark' ? KEY_MAIN_DARK_CUSTOM : KEY_MAIN_LIGHT_CUSTOM)
      : (effective === 'dark' ? KEY_ACCENT_DARK_CUSTOM : KEY_ACCENT_LIGHT_CUSTOM);
    const customHex = getPref(customStorageKey, customDef);
    const isCustomSelected = selectedKey === 'custom';
    const isAutoSelected = selectedKey === 'auto';

    const presetSwatches = Object.entries(presets).map(([key, p]) =>
      `<button type="button" class="bt-sw-swatch${key === selectedKey ? ' selected' : ''}" data-${kind}="${key}" title="${p.name}" style="background:${p.base}"></button>`
    ).join('');

    const autoSwatch = kind === 'accent'
      ? `<button type="button" class="bt-sw-swatch bt-sw-auto${isAutoSelected ? ' selected' : ''}" data-${kind}="auto" title="Auto (matches your Main)"></button>`
      : '';

    row.innerHTML = autoSwatch + presetSwatches + `
      <span class="bt-sw-custom-wrap${isCustomSelected ? ' selected' : ''}" data-target="${kind}" title="Custom ${kind} colour">
        <span class="bt-sw-custom-display"${isCustomSelected ? ` style="background:${currentHex}"` : ''}></span>
        <input type="color" data-target="${kind}" value="${customHex}" />
      </span>
    `;
  }

  // ===========================================================================
  // Maintab fix
  // ===========================================================================

  function fixMaintabCaps() {
    document.querySelectorAll('[class*="maintab"], [class*="mirrortab"]').forEach(el => {
      const text = (el.textContent || '').replace(/\s+/g, '');
      if (!text) el.style.cssText = 'display: none !important;';
    });
  }

  // ===========================================================================
  // BBCode icons
  // ===========================================================================

  const BBCODE_SVGS = {
    bold: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h7a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/><path d="M6 12h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/></svg>',
    italic: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="4" x2="10" y2="4"/><line x1="14" y1="20" x2="5" y2="20"/><line x1="15" y1="4" x2="9" y2="20"/></svg>',
    underline: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v8a6 6 0 0 0 12 0V3"/><line x1="4" y1="21" x2="20" y2="21"/></svg>',
    strike: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4H9a3 3 0 0 0-2.83 4M14 12a4 4 0 0 1 0 8H6"/><line x1="4" y1="12" x2="20" y2="12"/></svg>',
    pre: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>',
    code: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>',
    quote: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.75-2-2-2H4c-1.25 0-2 .75-2 2v6c0 1.25.75 2 2 2h1v1c0 1-1 2-2 2v3c0 1 0 1 1 1z"/><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.75-2-2-2h-4c-1.25 0-2 .75-2 2v6c0 1.25.75 2 2 2h1v1c0 1-1 2-2 2v3c0 1 0 1 1 1z"/></svg>',
    img: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>',
    url: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>',
    email: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><polyline points="22,6 12,13 2,6"/></svg>',
    ftp: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>',
    flash: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>',
    youtube: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z"/><polygon points="9.75 15.02 15.5 11.75 9.75 8.48 9.75 15.02"/></svg>',
    list: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><circle cx="3.5" cy="6" r="1"/><circle cx="3.5" cy="12" r="1"/><circle cx="3.5" cy="18" r="1"/></svg>',
    orderlist: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></svg>',
    left: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="17" y1="10" x2="3" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="17" y1="18" x2="3" y2="18"/></svg>',
    center: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="10" x2="6" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="18" y1="18" x2="6" y2="18"/></svg>',
    right: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="21" y1="10" x2="7" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="21" y1="18" x2="7" y2="18"/></svg>',
    hr: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"/></svg>',
    sub: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5l8 11"/><path d="M12 5L4 16"/><text x="14" y="22" font-size="9" fill="currentColor" stroke="none">2</text></svg>',
    sup: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 8l8 11"/><path d="M12 8L4 19"/><text x="14" y="9" font-size="9" fill="currentColor" stroke="none">2</text></svg>',
    tt: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"/><line x1="9" y1="20" x2="15" y2="20"/><line x1="12" y1="4" x2="12" y2="20"/></svg>',
    font: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"/><line x1="9" y1="20" x2="15" y2="20"/><line x1="12" y1="4" x2="12" y2="20"/></svg>',
    size: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7V4h18v3"/><path d="M8 20h8"/><path d="M12 4v16"/><path d="M18 14v6"/><path d="M15 14h6"/></svg>',
    color: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10c.93 0 1.69-.76 1.69-1.69 0-.43-.16-.83-.43-1.13-.27-.31-.43-.71-.43-1.13a1.69 1.69 0 0 1 1.69-1.69h1.99c3.04 0 5.49-2.45 5.49-5.49C22 6.04 17.52 2 12 2z"/><circle cx="6.5" cy="11.5" r="1.5"/><circle cx="9.5" cy="7.5" r="1.5"/><circle cx="14.5" cy="7.5" r="1.5"/><circle cx="17.5" cy="11.5" r="1.5"/></svg>',
    table: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/></svg>',
    glow: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>',
    shadow: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 3a9 9 0 0 1 0 18z" fill="currentColor"/></svg>',
    spoiler: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>',
    abbr: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>',
    bitcoin: '<svg viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M16.43 11.36c.5-.4.85-1 .85-1.74 0-1.6-1.27-2.66-3.06-2.84V5h-1.5v1.7H11V5H9.5v1.7H7v1.5h1.2V16H7v1.5h2.5V19H11v-1.5h1.72V19h1.5v-1.5c2.05 0 3.34-1.18 3.34-3 0-.93-.42-1.74-1.13-2.14zm-5.93-3.16h2.74c.74 0 1.3.42 1.3 1.2 0 .76-.56 1.2-1.3 1.2H10.5V8.2zm3.04 7.6H10.5v-2.6h3.04c.83 0 1.46.5 1.46 1.3 0 .8-.63 1.3-1.46 1.3z"/></svg>',
    trow: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><rect x="3" y="9" width="18" height="6" fill="currentColor" stroke="none" opacity="0.35"/></svg>',
    tcol: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/><rect x="9" y="3" width="6" height="18" fill="currentColor" stroke="none" opacity="0.35"/></svg>',
    trash: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"/></svg>',
    pencil: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"/></svg>',
  };

  const BBCODE_ALIASES = {
    italic: ['italicize'],
    bold: ['bolden'],
    strike: ['strikethrough', 'linethrough'],
    tt: ['teletype', 'monospace', 'tele'],
    font: ['fontface', 'fontname', 'face'],
    color: ['colour', 'fontcolour', 'fontcolor'],
    size: ['fontsize'],
    left: ['alignleft'],
    center: ['aligncenter'],
    right: ['alignright'],
    list: ['bullist'],
    orderlist: ['numlist', 'numberedlist'],
    img: ['image', 'picture'],
    url: ['link', 'hyperlink'],
    email: ['mail'],
    youtube: ['video', 'youtu'],
    hr: ['horizontalrule'],
    sub: ['subscript'],
    sup: ['superscript'],
    bitcoin: ['btc'],
    trow: ['tr'],
    tcol: ['td'],
    trash: ['delete', 'remove', 'del'],
    pencil: ['modify', 'edit', 'pen'],
  };
  Object.entries(BBCODE_ALIASES).forEach(([canon, aliases]) => {
    aliases.forEach(a => { BBCODE_SVGS[a] = BBCODE_SVGS[canon]; });
  });

  function modernizeBBCodeIcons() {
    const imgs = document.querySelectorAll(
      '#bbcBox_message img, .bbc_buttons img, [id^="bbc_"] img, ' +
      'img[src*="/bbc/"], img[src*="bbc_"], ' +
      'img[src*="/frostee/"], img[src*="frostee_"], ' +
      'img.reply_button, img.remove_button, img.modify_button, ' +
      'img[class$="_button"]'
    );
    imgs.forEach(img => {
      if (img.dataset.btReplaced === '1') return;
      const src = img.getAttribute('src') || '';
      const m = src.match(/\/(\w+)\.(?:gif|png)/i);
      const name = m ? m[1].toLowerCase().replace(/^(bbc|frostee|theme)_/, '') : '';

      const isPostAction = /\/frostee\//i.test(src) ||
                           img.classList.contains('reply_button') ||
                           img.classList.contains('modify_button') ||
                           img.classList.contains('remove_button');
      if (isPostAction) {
        const POST_ACTION_LABELS = {
          quote: 'Quote',
          edit: 'Edit',
          modify: 'Edit',
          delete: 'Delete',
          remove: 'Delete',
        };
        const label = POST_ACTION_LABELS[name];
        if (label) {
          const span = document.createElement('span');
          span.className = 'bt-post-action';
          span.title = img.alt || img.title || label;
          span.textContent = label;
          span.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            img.click();
          });
          img.dataset.btReplaced = '1';
          img.style.cssText = 'display: none !important;';
          img.parentNode.insertBefore(span, img);
          return;
        }
      }

      const svg = BBCODE_SVGS[name];
      if (!svg) return;

      const span = document.createElement('span');
      span.className = 'bt-bbc-icon';
      span.title = img.alt || img.title || name;
      span.setAttribute('aria-label', span.title);
      span.innerHTML = svg;
      span.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        img.click();
      });

      img.dataset.btReplaced = '1';
      img.style.cssText = 'display: none !important;';
      img.parentNode.insertBefore(span, img);
    });
  }

  // ===========================================================================
  // Smiley modernisation
  // ===========================================================================

  const SMILEYS = {
    smiley: '🙂', happy: '🙂',
    wink: '😉',
    cheesy: '😄', grin: '😀',
    sad: '🙁', cry: '😢',
    shocked: '😮', surprised: '😮',
    cool: '😎', sunglasses: '😎',
    huh: '🤔', confused: '😕', undecided: '😕',
    tongue: '😛',
    embarrassed: '😳',
    lipsrsealed: '🤐',
    angry: '😠', mad: '😡',
    kiss: '😘',
    rolleyes: '🙄',
    evil: '😈',
    azn: '😏',
    afro: '🕺',
    laugh: '😆', lol: '😂',
    police: '👮',
    wassat: '🤨',
    chocked: '😱',
    skeptical: '🤨',
    facepalm: '🤦',
    thumbsup: '👍', thumbup: '👍',
    thumbsdown: '👎', thumbdown: '👎',
    heart: '❤️',
    star: '⭐',
    fire: '🔥',
    check: '✅', tick: '✅',
    cross: '❌',
  };

  function stylePostMetaButtons() {
    document.querySelectorAll('a').forEach(a => {
      if (a.dataset.btPostMeta === '1') return;
      const text = (a.textContent || '').trim();
      const href = a.getAttribute('href') || '';
      const isMerit = /^\+\s*merit\b/i.test(text);
      const isMsgNum = /^#\d+$/.test(text) &&
        /(topic=|#msg|action=display|action=profile)/i.test(href);
      if (isMerit || isMsgNum) {
        a.classList.add('bt-post-action');
        a.dataset.btPostMeta = '1';
      }
    });
  }

  function modernizeSmileys() {
    const imgs = document.querySelectorAll(
      'img[src*="Smileys/"], img[src*="/smileys/"], img.smiley'
    );
    imgs.forEach(img => {
      if (img.dataset.btSmiley === '1') return;
      const src = img.getAttribute('src') || '';
      if (!/(Smileys|smileys|smiley)/i.test(src) && !img.classList.contains('smiley')) return;
      const m = src.match(/\/(\w+)\.(?:gif|png|jpg)/i);
      const name = m ? m[1].toLowerCase() : '';
      const emoji = SMILEYS[name];
      if (!emoji) return;

      const span = document.createElement('span');
      span.className = 'bt-smiley';
      span.textContent = emoji;
      span.title = img.alt || img.title || name;

      img.dataset.btSmiley = '1';
      img.style.cssText = 'display: none !important;';
      img.parentNode.insertBefore(span, img);
    });
  }

  // ===========================================================================
  // CSS
  // ===========================================================================

  const css = `
    :root[data-bt-theme="dark"] {
      --bt-bg: #1A1D21;
      --bt-surface-1: #22262B;
      --bt-surface-2: #2A2F35;
      --bt-surface-3: #343A41;
      --bt-border: rgba(255,255,255,0.07);
      --bt-border-2: rgba(255,255,255,0.14);
      --bt-text: #E3E3E8;
      --bt-text-2: #A8B0BA;
      --bt-text-3: #6B7480;
      --bt-input-bg: #14171B;
      --bt-quote-bg: #1F2328;
      --bt-code-bg: #14171B;
      --bt-bg-end: #17191D;
      --bt-icon-filter: invert(1) opacity(0.75);
      --bt-shadow: 0 1px 0 rgba(0,0,0,0.2);
      --bt-shadow-lg: 0 12px 32px rgba(0,0,0,0.35);
    }
    :root[data-bt-theme="light"] {
      --bt-bg: #F2F4F7;
      --bt-surface-1: #E3E6EA;
      --bt-surface-2: #D7DAE0;
      --bt-surface-3: #C5C8CD;
      --bt-post-bg: #EEF3F7;
      --bt-post-alt-bg: #E3EBF1;
      --bt-poster-bg: #E8EEF3;
      --bt-poster-alt-bg: #DCE7EE;
      --bt-border: rgba(0,0,0,0.08);
      --bt-border-2: rgba(0,0,0,0.16);
      --bt-text: #1A1D21;
      --bt-text-2: #4A5058;
      --bt-text-3: #7A8088;
      --bt-input-bg: #FFFFFF;
      --bt-quote-bg: #E1E4E8;
      --bt-code-bg: #DBDEE3;
      --bt-bg-end: #E9ECEF;
      --bt-icon-filter: opacity(0.7);
      --bt-shadow: 0 1px 0 rgba(0,0,0,0.04);
      --bt-shadow-lg: 0 12px 32px rgba(0,0,0,0.12);
    }
    :root {
      --bt-radius: 10px;
      --bt-radius-sm: 6px;
      --bt-radius-lg: 14px;
      --bt-font: 'Source Sans 3', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      --bt-mono: 'Cascadia Code', 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;
      --bt-trans: 150ms ease;
      --bt-danger: #EF4444;
      --bt-accent: #F7931A;
      --bt-accent-h: #FFA733;
      --bt-accent-a: #E08410;
      --bt-on-accent: #1A1D21;
    }

    /*-- BT_ALWAYS_ON_START --*/
    :root[data-bt-active="false"] .bt-bbc-icon,
    :root[data-bt-active="false"] .bt-smiley,
    :root[data-bt-active="false"] .bt-post-action {
      display: none !important;
    }
    :root[data-bt-active="false"] img[data-bt-replaced="1"],
    :root[data-bt-active="false"] img[data-bt-smiley="1"] {
      display: inline !important;
    }
    [data-bt-no-transitions] *,
    [data-bt-no-transitions] *::before,
    [data-bt-no-transitions] *::after {
      transition: none !important;
      animation-duration: 0s !important;
    }
    /*-- BT_ALWAYS_ON_END --*/

    html,
    body {
      background: var(--bt-bg) !important;
      color: var(--bt-text) !important;
      font-family: var(--bt-font) !important;
      font-size: 14px !important;
      -webkit-font-smoothing: antialiased;
      text-rendering: optimizeLegibility;
    }

    body {
      background:
        radial-gradient(140% 100% at 15% -10%, color-mix(in srgb, var(--bt-accent) 6%, transparent) 0%, transparent 55%),
        radial-gradient(120% 100% at 90% -5%,  color-mix(in srgb, var(--bt-accent) 3%, transparent) 0%, transparent 60%),
        linear-gradient(180deg, var(--bt-bg) 0%, var(--bt-bg-end) 100%) !important;
      background-attachment: fixed !important;
    }

    body, td, th, tr { color: var(--bt-text) !important; }
    h1, h2, h3, h4, h5, h6 {
      color: var(--bt-text) !important;
      font-weight: 600 !important;
      letter-spacing: -0.005em;
    }

    a, a:link, a:visited {
      color: var(--bt-accent) !important;
      text-decoration: none !important;
      transition: color var(--bt-trans) !important;
    }
    a:hover, a:active, a:focus {
      color: var(--bt-accent-h) !important;
      text-decoration: none !important;
    }

    #upper_section, #header, #wrapper, #content_section, #main_content_section,
    #footer_section, .frame, #bodyarea, .navigate_section, .roundframe,
    #content {
      background: transparent !important;
      color: var(--bt-text) !important;
    }

    table.bordercolor,
    table.table_list,
    table.table_grid,
    .tborder {
      background: var(--bt-surface-1) !important;
      border: 1px solid var(--bt-border-2) !important;
      border-radius: var(--bt-radius) !important;
      overflow: hidden !important;
      border-spacing: 0 !important;
      box-shadow: var(--bt-shadow);
    }

    [class*="windowbg"],
    td[class*="windowbg"],
    tr[class*="windowbg"] > td {
      background-color: var(--bt-surface-1) !important;
      background-image: none !important;
      color: var(--bt-text) !important;
      border-color: var(--bt-border) !important;
      border-bottom: 1px solid var(--bt-border) !important;
    }
    tr.windowbg:hover > td,
    tr.windowbg2:hover > td,
    tr.windowbg3:hover > td {
      background-color: var(--bt-surface-2) !important;
    }

    /* v2.8.1: restore the classic-looking post alternation on light-theme
       thread pages. The previous attempt only caught a narrow header row on
       some thread layouts (the "Report to moderator" strip), because the
       actual post body/sidebar wrappers are often .td_headerandpost, .post,
       .poster and .poster_info rather than the row cell that carries
       windowbg/windowbg2 itself.

       We therefore paint BOTH the row cells and the common wrappers inside
       them, so the entire post block alternates again like classic
       bitcointalk/SMF. */
    :root[data-bt-theme="light"] tr.windowbg > td,
    :root[data-bt-theme="light"] td.windowbg,
    :root[data-bt-theme="light"] tr.windowbg td.td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg.td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg td.post,
    :root[data-bt-theme="light"] td.windowbg.post,
    :root[data-bt-theme="light"] tr.windowbg td.poster,
    :root[data-bt-theme="light"] tr.windowbg td.poster_info,
    :root[data-bt-theme="light"] td.windowbg.poster,
    :root[data-bt-theme="light"] td.windowbg.poster_info {
      background-color: #e9f0f7 !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg2 > td,
    :root[data-bt-theme="light"] td.windowbg2,
    :root[data-bt-theme="light"] tr.windowbg2 td.td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg2.td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg2 td.post,
    :root[data-bt-theme="light"] td.windowbg2.post,
    :root[data-bt-theme="light"] tr.windowbg2 td.poster,
    :root[data-bt-theme="light"] tr.windowbg2 td.poster_info,
    :root[data-bt-theme="light"] td.windowbg2.poster,
    :root[data-bt-theme="light"] td.windowbg2.poster_info {
      background-color: #dfe9f3 !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg3 > td,
    :root[data-bt-theme="light"] td.windowbg3,
    :root[data-bt-theme="light"] tr.windowbg3 td.td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg3.td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg3 td.post,
    :root[data-bt-theme="light"] td.windowbg3.post,
    :root[data-bt-theme="light"] tr.windowbg3 td.poster,
    :root[data-bt-theme="light"] tr.windowbg3 td.poster_info,
    :root[data-bt-theme="light"] td.windowbg3.poster,
    :root[data-bt-theme="light"] td.windowbg3.poster_info {
      background-color: #e9f0f7 !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg:hover > td,
    :root[data-bt-theme="light"] tr.windowbg:hover td.td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg:hover td.post,
    :root[data-bt-theme="light"] tr.windowbg:hover td.poster,
    :root[data-bt-theme="light"] tr.windowbg:hover td.poster_info,
    :root[data-bt-theme="light"] tr.windowbg2:hover > td,
    :root[data-bt-theme="light"] tr.windowbg2:hover td.td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg2:hover td.post,
    :root[data-bt-theme="light"] tr.windowbg2:hover td.poster,
    :root[data-bt-theme="light"] tr.windowbg2:hover td.poster_info,
    :root[data-bt-theme="light"] tr.windowbg3:hover > td,
    :root[data-bt-theme="light"] tr.windowbg3:hover td.td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg3:hover td.post,
    :root[data-bt-theme="light"] tr.windowbg3:hover td.poster,
    :root[data-bt-theme="light"] tr.windowbg3:hover td.poster_info {
      background-color: #d7e3ef !important;
      background-image: none !important;
    }

    .poster, td.poster, .poster_info, td.poster_info, [id*="poster"] {
      background-color: var(--bt-surface-1) !important;
      background-image: none !important;
      color: var(--bt-text) !important;
    }
    :root[data-bt-theme="dark"] td.poster_info *,
    :root[data-bt-theme="dark"] td.poster *,
    :root[data-bt-theme="dark"] .poster_info * {
      color: var(--bt-text-2) !important;
    }
    :root[data-bt-theme="dark"] td.poster_info b a,
    :root[data-bt-theme="dark"] td.poster_info h4 a,
    :root[data-bt-theme="dark"] .poster_info b a,
    :root[data-bt-theme="dark"] .poster_info h4 a {
      color: var(--bt-text) !important;
      font-weight: 600 !important;
    }
    :root[data-bt-theme="dark"] td.poster_info b a:hover,
    :root[data-bt-theme="dark"] td.poster_info h4 a:hover,
    :root[data-bt-theme="dark"] .poster_info b a:hover,
    :root[data-bt-theme="dark"] .poster_info h4 a:hover {
      color: var(--bt-accent) !important;
    }
    :root[data-bt-theme="dark"] td.poster_info a,
    :root[data-bt-theme="dark"] .poster_info a {
      color: var(--bt-accent) !important;
    }
    :root[data-bt-theme="dark"] td.poster_info a:hover,
    :root[data-bt-theme="dark"] .poster_info a:hover {
      color: var(--bt-accent-h) !important;
    }
    :root[data-bt-theme="dark"] td.poster_info img,
    :root[data-bt-theme="dark"] .poster_info img { color: initial !important; }

    table.bordercolor tr[style] > td,
    table.bordercolor td[style],
    .tborder tr[style] > td,
    .tborder td[style] {
      background-color: var(--bt-surface-1) !important;
      background-image: none !important;
    }

    [class*="catbg"], [class*="titlebg"], td[class*="catbg"], td[class*="titlebg"],
    th[class*="catbg"], th[class*="titlebg"], tr[class*="catbg"] > td,
    tr[class*="catbg"] > th, tr[class*="catbg"] td, tr[class*="catbg"] th,
    tr[class*="titlebg"] > td, tr[class*="titlebg"] > th, tr[class*="titlebg"] td,
    tr[class*="titlebg"] th, h3[class*="catbg"], h4[class*="catbg"],
    h3[class*="titlebg"], h4[class*="titlebg"] {
      background-color: var(--bt-surface-2) !important;
      background-image: none !important;
      color: var(--bt-text) !important;
      border-bottom: 1px solid var(--bt-border-2) !important;
      font-weight: 600 !important;
      letter-spacing: 0.01em;
      text-shadow: none !important;
    }
    [class*="catbg"] a, [class*="titlebg"] a, tr[class*="catbg"] a, tr[class*="titlebg"] a {
      color: var(--bt-text) !important;
    }
    [class*="catbg"] a:hover, [class*="titlebg"] a:hover, tr[class*="catbg"] a:hover, tr[class*="titlebg"] a:hover {
      color: var(--bt-accent) !important;
    }

    th {
      background-color: var(--bt-surface-2) !important;
      background-image: none !important;
      color: var(--bt-text) !important;
    }

    .post, td.post, #preview_body, #preview_section, #preview_section td,
    #preview_section table, .personalmessage, td.personalmessage {
      background-color: var(--bt-surface-1) !important;
      background-image: none !important;
      color: var(--bt-text) !important;
    }
    .post { line-height: 1.6 !important; font-size: 14px !important; }
    .signature {
      color: var(--bt-text-3) !important;
      border-top: 1px solid var(--bt-border) !important;
      padding-top: 8px !important;
      margin-top: 12px !important;
      font-size: 12px !important;
    }
    .smalltext, .middletext, .small_header, .nav, a.nav, .navPages, .prevnext,
    .lastpostcol, .ignored_topic, .utusers, .utusers a {
      color: var(--bt-text-2) !important;
    }
    .smalltext a, .middletext a, .small_header a, .lastpostcol a {
      color: var(--bt-accent) !important;
    }

    .quoteheader, .codeheader {
      background: var(--bt-surface-3) !important;
      color: var(--bt-text-2) !important;
      border: 1px solid var(--bt-border) !important;
      border-bottom: none !important;
      border-radius: var(--bt-radius-sm) var(--bt-radius-sm) 0 0 !important;
      padding: 6px 10px !important;
      font-size: 12px !important;
      font-weight: 500 !important;
    }
    .quote {
      background: var(--bt-quote-bg) !important;
      color: var(--bt-text-2) !important;
      border: 1px solid var(--bt-border) !important;
      border-left: 3px solid var(--bt-accent) !important;
      border-radius: 0 var(--bt-radius-sm) var(--bt-radius-sm) var(--bt-radius-sm) !important;
      padding: 10px 14px !important;
      margin: 6px 0 12px !important;
    }
    .code {
      background: var(--bt-code-bg) !important;
      color: var(--bt-text) !important;
      font-family: var(--bt-mono) !important;
      border: 1px solid var(--bt-border) !important;
      border-radius: 0 0 var(--bt-radius-sm) var(--bt-radius-sm) !important;
      padding: 10px 14px !important;
    }

    .button_submit, .button_reset, input[type="submit"], input[type="button"],
    input[type="reset"], button:not([id^="bt-"]):not([class^="bt-sw-"]),
    .button:not([id^="bt-"]) {
      background: var(--bt-accent) !important;
      color: var(--bt-on-accent) !important;
      border: 1px solid var(--bt-accent) !important;
      border-radius: var(--bt-radius-sm) !important;
      padding: 8px 14px !important;
      font-family: var(--bt-font) !important;
      font-weight: 600 !important;
      font-size: 13px !important;
      cursor: pointer !important;
      transition: background var(--bt-trans), transform var(--bt-trans), box-shadow var(--bt-trans) !important;
      box-shadow: none !important;
      text-shadow: none !important;
    }
    .button_submit:hover, .button_reset:hover, input[type="submit"]:hover,
    input[type="button"]:hover, input[type="reset"]:hover,
    button:not([id^="bt-"]):not([class^="bt-sw-"]):hover,
    .button:not([id^="bt-"]):hover {
      background: var(--bt-accent-h) !important;
      border-color: var(--bt-accent-h) !important;
      box-shadow: 0 2px 12px color-mix(in srgb, var(--bt-accent) 30%, transparent) !important;
      transform: translateY(-1px);
      color: var(--bt-on-accent) !important;
    }
    .button_submit:active, input[type="submit"]:active {
      background: var(--bt-accent-a) !important;
      transform: translateY(0) !important;
    }

    a.button {
      background: transparent !important;
      color: var(--bt-text) !important;
      border: 1px solid var(--bt-border-2) !important;
    }
    a.button:hover {
      border-color: var(--bt-accent) !important;
      color: var(--bt-accent) !important;
      background: color-mix(in srgb, var(--bt-accent) 10%, transparent) !important;
      box-shadow: none !important;
      transform: none !important;
    }

    a.quotebutton, a.replybutton, a.modifybutton, a.removebutton, a.reportbutton,
    a.splitbutton, a.notifybutton, a.markreadbutton, a.unwatchbutton,
    a.printbutton, a.archivebutton {
      display: inline-block !important;
      background: transparent !important;
      color: var(--bt-text-2) !important;
      border: 1px solid var(--bt-border-2) !important;
      border-radius: var(--bt-radius-sm) !important;
      padding: 4px 10px !important;
      margin: 0 4px 0 0 !important;
      font-family: var(--bt-font) !important;
      font-weight: 500 !important;
      font-size: 11px !important;
      text-transform: uppercase !important;
      letter-spacing: 0.04em !important;
      text-decoration: none !important;
      box-shadow: none !important;
      text-shadow: none !important;
      transition: background var(--bt-trans), color var(--bt-trans), border-color var(--bt-trans) !important;
      cursor: pointer !important;
    }
    a.quotebutton:hover, a.replybutton:hover, a.modifybutton:hover,
    a.removebutton:hover, a.reportbutton:hover, a.splitbutton:hover,
    a.notifybutton:hover, a.markreadbutton:hover, a.unwatchbutton:hover,
    a.printbutton:hover, a.archivebutton:hover {
      background: var(--bt-accent) !important;
      color: var(--bt-on-accent) !important;
      border-color: var(--bt-accent) !important;
      transform: none !important;
      box-shadow: none !important;
    }

    .bt-post-action {
      display: inline-block !important;
      padding: 4px 10px !important;
      margin: 0 4px 0 0 !important;
      background: transparent !important;
      color: var(--bt-text-2) !important;
      border: 1px solid var(--bt-border-2) !important;
      border-radius: var(--bt-radius-sm) !important;
      font-family: var(--bt-font) !important;
      font-weight: 500 !important;
      font-size: 11px !important;
      text-transform: uppercase !important;
      letter-spacing: 0.04em !important;
      cursor: pointer !important;
      vertical-align: middle !important;
      transition: background var(--bt-trans), color var(--bt-trans), border-color var(--bt-trans) !important;
    }
    .bt-post-action:hover {
      background: var(--bt-accent) !important;
      color: var(--bt-on-accent) !important;
      border-color: var(--bt-accent) !important;
      text-decoration: none !important;
    }
    a.bt-post-action, a.bt-post-action:link, a.bt-post-action:visited {
      color: var(--bt-text-2) !important;
    }
    a.bt-post-action:hover { color: var(--bt-on-accent) !important; }
    span[title="Quote to clipboard"] { display: none !important; }

    input[type="text"], input[type="password"], input[type="email"],
    input[type="search"], input[type="url"], input[type="number"],
    textarea, select {
      background: var(--bt-input-bg) !important;
      color: var(--bt-text) !important;
      border: 1px solid var(--bt-border-2) !important;
      border-radius: var(--bt-radius-sm) !important;
      padding: 8px 10px !important;
      font-family: var(--bt-font) !important;
      font-size: 13px !important;
      transition: border-color var(--bt-trans), box-shadow var(--bt-trans) !important;
      outline: none !important;
    }
    input[type="text"]:focus, input[type="password"]:focus,
    input[type="email"]:focus, input[type="search"]:focus,
    textarea:focus, select:focus {
      border-color: var(--bt-accent) !important;
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--bt-accent) 20%, transparent) !important;
    }
    textarea {
      min-height: 120px !important;
      line-height: 1.5 !important;
      font-family: var(--bt-mono) !important;
    }

    #bbcBox_message, .bbc_buttons, #post_modify, .post_buttons {
      background: var(--bt-surface-2) !important;
      border: 1px solid var(--bt-border) !important;
      border-radius: var(--bt-radius-sm) !important;
      padding: 6px !important;
    }
    #bbcBox_message img, .bbc_buttons img {
      filter: var(--bt-icon-filter) !important;
      transition: filter var(--bt-trans) !important;
    }
    #bbcBox_message img:hover, .bbc_buttons img:hover { filter: none !important; }

    .bt-bbc-icon {
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      width: 26px !important;
      height: 26px !important;
      margin: 1px !important;
      padding: 4px !important;
      border-radius: var(--bt-radius-sm) !important;
      color: var(--bt-text-2) !important;
      background: transparent !important;
      cursor: pointer !important;
      vertical-align: middle !important;
      transition: background var(--bt-trans), color var(--bt-trans) !important;
      box-sizing: border-box !important;
    }
    .bt-bbc-icon svg {
      width: 100% !important;
      height: 100% !important;
      display: block !important;
    }
    .bt-bbc-icon:hover {
      background: color-mix(in srgb, var(--bt-accent) 18%, transparent) !important;
      color: var(--bt-accent) !important;
    }

    .bt-smiley {
      display: inline-block !important;
      font-size: 1.15em !important;
      line-height: 1 !important;
      vertical-align: -0.12em !important;
      font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji",
                   "Twemoji Mozilla", sans-serif !important;
    }

    [class*="maintab_"],
    [class*="mirrortab_"] {
      display: inline-block !important;
      margin: 0 !important;
      padding: 0 !important;
      border-radius: 0 !important;
      background-color: var(--bt-surface-2) !important;
      background-image: none !important;
      border: 1px solid var(--bt-border) !important;
      border-left: none !important;
      box-shadow: none !important;
      text-shadow: none !important;
      transition: background-color var(--bt-trans), border-color var(--bt-trans) !important;
      vertical-align: middle !important;
      line-height: 1 !important;
      width: auto !important;
      min-width: 0 !important;
      height: auto !important;
    }
    .maintab_first,
    .mirrortab_first,
    .maintab_active_first + .maintab_active_back,
    .mirrortab_active_first + .mirrortab_active_back {
      border-left: 1px solid var(--bt-border) !important;
      border-top-left-radius: var(--bt-radius-sm) !important;
      border-bottom-left-radius: var(--bt-radius-sm) !important;
    }
    .maintab_last,
    .mirrortab_last,
    .maintab_active_back + .maintab_active_last,
    .mirrortab_active_back + .mirrortab_active_last {
      border-top-right-radius: var(--bt-radius-sm) !important;
      border-bottom-right-radius: var(--bt-radius-sm) !important;
    }
    [class*="maintab_"] a,
    [class*="maintab_"] a:link,
    [class*="maintab_"] a:visited,
    [class*="mirrortab_"] a,
    [class*="mirrortab_"] a:link,
    [class*="mirrortab_"] a:visited {
      display: inline-block !important;
      padding: 6px 14px !important;
      margin: 0 !important;
      color: var(--bt-text-2) !important;
      font-family: var(--bt-font) !important;
      font-weight: 500 !important;
      font-size: 12px !important;
      text-transform: uppercase !important;
      letter-spacing: 0.05em !important;
      transition: color var(--bt-trans) !important;
      background: transparent !important;
      background-image: none !important;
      border: none !important;
      box-shadow: none !important;
      text-shadow: none !important;
      line-height: 1 !important;
    }
    .maintab_first:hover, .maintab_back:hover, .maintab_last:hover {
      background-color: var(--bt-surface-3) !important;
      border-color: var(--bt-border-2) !important;
    }
    .maintab_first:hover a, .maintab_back:hover a, .maintab_last:hover a {
      color: var(--bt-text) !important;
    }
    .maintab_active_back,
    .mirrortab_active_back {
      background-color: var(--bt-accent) !important;
      border-color: var(--bt-accent) !important;
    }
    .maintab_active_back a,
    .maintab_active_back a:hover,
    .mirrortab_active_back a,
    .mirrortab_active_back a:hover {
      color: var(--bt-on-accent) !important;
      font-weight: 600 !important;
    }

    /* v2.7.15: In LIGHT themes, selected main/mirror tabs use a
       theme-derived extrapolated colour: it continues from Main -> surface3
       by the same interval again. In other words, if surface3 is the
       "intermediate/illuminated" tone, the active tab doubles that HSL move. */
    :root[data-bt-theme="light"] .maintab_active_back,
    :root[data-bt-theme="light"] .mirrortab_active_back {
      background-color: var(--bt-nav-active-bg, var(--bt-surface-3)) !important;
      border-color: var(--bt-nav-active-bg, var(--bt-border-2)) !important;
    }
    :root[data-bt-theme="light"] .maintab_active_back a,
    :root[data-bt-theme="light"] .maintab_active_back a:hover,
    :root[data-bt-theme="light"] .mirrortab_active_back a,
    :root[data-bt-theme="light"] .mirrortab_active_back a:hover {
      color: var(--bt-nav-active-text, var(--bt-text)) !important;
      font-weight: 600 !important;
    }
    .maintab_active_first.maintab_active_first,
    .maintab_active_last.maintab_active_last,
    .mirrortab_active_first.mirrortab_active_first,
    .mirrortab_active_last.mirrortab_active_last {
      display: none !important;
    }

    #main_menu, .dropmenu {
      background: transparent !important;
      border: none !important;
    }
    #main_menu li, .dropmenu li {
      background: var(--bt-surface-2) !important;
      border: 1px solid var(--bt-border) !important;
      border-radius: var(--bt-radius-sm) !important;
      margin-right: 4px !important;
    }
    #main_menu li.chosen, .dropmenu li.chosen,
    #main_menu li.active, .dropmenu li.active {
      background: var(--bt-accent) !important;
      border-color: var(--bt-accent) !important;
    }
    #main_menu li a, .dropmenu li a {
      color: var(--bt-text-2) !important;
      padding: 6px 14px !important;
      font-size: 12px !important;
      text-transform: uppercase !important;
      letter-spacing: 0.05em !important;
    }
    #main_menu li.chosen a, .dropmenu li.chosen a,
    #main_menu li.active a, .dropmenu li.active a {
      color: var(--bt-on-accent) !important;
      font-weight: 600 !important;
    }

    #upper_section {
      border-bottom: 1px solid var(--bt-border) !important;
      position: relative !important;
    }
    #top_section, #upshrink_header, .navigate_section ul, .navigate_section {
      background: transparent !important;
      color: var(--bt-text-2) !important;
    }
    .navigate_section a, .navigate_section a:link, .navigate_section a:visited {
      color: var(--bt-text-2) !important;
    }
    .navigate_section a:hover { color: var(--bt-accent) !important; }
    .navigate_section .last a, .navigate_section li:last-child a {
      color: var(--bt-text) !important;
      font-weight: 600 !important;
    }
    #header img, #logo { filter: brightness(1.05) !important; }

    hr {
      border: none !important;
      border-top: 1px solid var(--bt-border) !important;
      margin: 16px 0 !important;
    }

    #footer_section, .copywrite {
      background: transparent !important;
      color: var(--bt-text-3) !important;
      border-top: 1px solid var(--bt-border) !important;
    }
    #footer_section a, .copywrite a { color: var(--bt-text-2) !important; }
    #footer_section a:hover, .copywrite a:hover { color: var(--bt-accent) !important; }

    .information, .descbox, .infobox {
      background: var(--bt-surface-2) !important;
      color: var(--bt-text-2) !important;
      border: 1px solid var(--bt-border) !important;
      border-radius: var(--bt-radius-sm) !important;
      padding: 10px 12px !important;
    }
    .errorbox, .noticebox {
      background: color-mix(in srgb, var(--bt-danger) 12%, transparent) !important;
      border: 1px solid color-mix(in srgb, var(--bt-danger) 40%, transparent) !important;
      color: var(--bt-danger) !important;
      border-radius: var(--bt-radius-sm) !important;
      padding: 10px 12px !important;
    }

    .pagelinks { color: var(--bt-text-2) !important; }
    .pagelinks a, .pagelinks a:link, .pagelinks a:visited {
      color: var(--bt-text-2) !important;
      padding: 4px 8px !important;
      border-radius: var(--bt-radius-sm) !important;
      transition: background var(--bt-trans), color var(--bt-trans) !important;
    }
    .pagelinks a:hover {
      background: color-mix(in srgb, var(--bt-accent) 12%, transparent) !important;
      color: var(--bt-accent) !important;
    }
    .pagelinks strong {
      background: var(--bt-accent) !important;
      color: var(--bt-on-accent) !important;
      padding: 4px 8px !important;
      border-radius: var(--bt-radius-sm) !important;
    }

    .poster h4 a, .poster h4 a:link, .poster h4 a:visited {
      color: var(--bt-text) !important;
      font-weight: 600 !important;
    }
    .poster h4 a:hover { color: var(--bt-accent) !important; }
    .poster ul, .poster li {
      color: var(--bt-text-3) !important;
      font-size: 12px !important;
    }
    .avatar, img.avatar {
      border-radius: var(--bt-radius-sm) !important;
      border: 1px solid var(--bt-border) !important;
    }

    * { scrollbar-width: thin; scrollbar-color: var(--bt-surface-3) var(--bt-bg); }
    *::-webkit-scrollbar { width: 10px; height: 10px; }
    *::-webkit-scrollbar-track { background: var(--bt-bg); }
    *::-webkit-scrollbar-thumb {
      background: var(--bt-surface-3);
      border-radius: 5px;
      border: 2px solid var(--bt-bg);
    }
    *::-webkit-scrollbar-thumb:hover { background: var(--bt-accent); }

    ::selection {
      background: color-mix(in srgb, var(--bt-accent) 35%, transparent);
      color: var(--bt-text);
    }

    img[src*="bullet"], img[src*="off"], img[src*="on"] { opacity: 0.85; }

    select {
      appearance: none !important;
      -webkit-appearance: none !important;
      background-image:
        linear-gradient(45deg, transparent 50%, var(--bt-text-2) 50%),
        linear-gradient(135deg, var(--bt-text-2) 50%, transparent 50%) !important;
      background-position: calc(100% - 14px) 50%, calc(100% - 9px) 50% !important;
      background-size: 5px 5px, 5px 5px !important;
      background-repeat: no-repeat !important;
      padding-right: 28px !important;
    }

    /*-- BT_ALWAYS_ON_START --*/
    #bt-switcher {
      position: absolute !important;
      top: 8px !important;
      right: 8px !important;
      z-index: 10000 !important;
      font-family: var(--bt-font) !important;
      font-size: 13px !important;
      color: var(--bt-text, #1A1D21) !important;
      line-height: 1 !important;
    }
    #bt-switcher-button {
      display: flex !important;
      align-items: center !important;
      justify-content: center !important;
      width: 32px !important;
      height: 32px !important;
      padding: 0 !important;
      margin: 0 !important;
      border-radius: 50% !important;
      background: var(--bt-surface-2, #2A2F35) !important;
      color: var(--bt-text-2, #A8B0BA) !important;
      border: 1px solid var(--bt-border-2, rgba(255,255,255,0.14)) !important;
      cursor: pointer !important;
      transition: background var(--bt-trans), color var(--bt-trans), transform 200ms ease !important;
      box-shadow: var(--bt-shadow, 0 1px 0 rgba(0,0,0,0.2)) !important;
      text-shadow: none !important;
      font: inherit !important;
      text-transform: none !important;
      letter-spacing: 0 !important;
    }
    #bt-switcher-button:hover {
      background: var(--bt-surface-3, #343A41) !important;
      color: var(--bt-text, #E3E3E8) !important;
      transform: rotate(20deg);
    }
    #bt-switcher-button svg { width: 18px; height: 18px; }

    :root[data-bt-active="false"] #bt-switcher-button {
      width: auto !important;
      min-width: 44px !important;
      padding: 0 12px !important;
      border-radius: 14px !important;
      background: #2A2F35 !important;
      color: #FFFFFF !important;
      border: 1px solid #4ADE80 !important;
      font-weight: 700 !important;
      font-size: 11px !important;
      text-transform: uppercase !important;
      letter-spacing: 0.08em !important;
      box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.4) !important;
      animation: bt-pulse-on 2.4s ease-in-out infinite;
    }
    :root[data-bt-active="false"] #bt-switcher-button:hover {
      background: #4ADE80 !important;
      color: #1A1D21 !important;
      transform: none !important;
      animation: none;
    }
    .bt-sw-on-text { display: inline-block; line-height: 1; }
    @keyframes bt-pulse-on {
      0%, 100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.0); }
      50%      { box-shadow: 0 0 0 4px rgba(74, 222, 128, 0.18); }
    }

    #bt-switcher-panel {
      position: absolute !important;
      top: 40px !important;
      right: 0 !important;
      min-width: 300px !important;
      background: var(--bt-surface-1, #22262B) !important;
      border: 1px solid var(--bt-border-2, rgba(255,255,255,0.14)) !important;
      border-radius: var(--bt-radius, 10px) !important;
      padding: 14px !important;
      box-shadow: var(--bt-shadow-lg, 0 12px 32px rgba(0,0,0,0.35)) !important;
      display: none !important;
      color: var(--bt-text, #E3E3E8) !important;
    }
    #bt-switcher.open #bt-switcher-panel { display: block !important; }
    .bt-sw-section { margin-bottom: 14px; }
    .bt-sw-section:last-child { margin-bottom: 0; }
    .bt-sw-label {
      display: block !important;
      font-size: 10px !important;
      font-weight: 600 !important;
      text-transform: uppercase !important;
      letter-spacing: 0.08em !important;
      color: var(--bt-text-3, #6B7480) !important;
      margin-bottom: 8px !important;
    }
    .bt-sw-row {
      display: flex !important;
      gap: 6px !important;
      align-items: center !important;
      flex-wrap: wrap !important;
    }
    .bt-sw-theme-btn {
      flex: 1 !important;
      min-width: 0 !important;
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      gap: 5px !important;
      padding: 8px 6px !important;
      margin: 0 !important;
      background: var(--bt-surface-2, #2A2F35) !important;
      color: var(--bt-text-2, #A8B0BA) !important;
      border: 1px solid var(--bt-border, rgba(255,255,255,0.07)) !important;
      border-radius: var(--bt-radius-sm, 6px) !important;
      cursor: pointer !important;
      font-family: var(--bt-font) !important;
      font-size: 11px !important;
      font-weight: 500 !important;
      text-transform: none !important;
      letter-spacing: 0 !important;
      text-shadow: none !important;
      box-shadow: none !important;
      transition: background var(--bt-trans), color var(--bt-trans), border-color var(--bt-trans) !important;
      line-height: 1 !important;
    }
    .bt-sw-theme-btn:hover {
      background: var(--bt-surface-3, #343A41) !important;
      color: var(--bt-text, #E3E3E8) !important;
      transform: none !important;
    }
    .bt-sw-theme-btn.selected {
      background: var(--bt-accent, #F7931A) !important;
      color: var(--bt-on-accent, #1A1D21) !important;
      border-color: var(--bt-accent, #F7931A) !important;
    }
    .bt-sw-theme-btn svg { width: 14px; height: 14px; }
    .bt-sw-theme-btn[data-theme="off"].selected {
      background: var(--bt-danger, #EF4444) !important;
      color: #FFFFFF !important;
      border-color: var(--bt-danger, #EF4444) !important;
    }

    .bt-sw-customize {
      margin-top: 14px;
      padding-top: 14px;
      border-top: 1px solid var(--bt-border, rgba(255,255,255,0.07));
    }
    .bt-sw-customize-title {
      display: block;
      text-align: center;
      font-size: 11px;
      font-weight: 600;
      letter-spacing: 0.05em;
      color: var(--bt-text, #E3E3E8);
      margin-bottom: 12px;
    }

    .bt-sw-swatch {
      width: 26px !important;
      height: 26px !important;
      padding: 0 !important;
      margin: 0 !important;
      border-radius: 50% !important;
      border: 2px solid transparent !important;
      cursor: pointer !important;
      transition: transform var(--bt-trans), border-color var(--bt-trans) !important;
      box-shadow: inset 0 0 0 1px rgba(0,0,0,0.15) !important;
      font-size: 0 !important;
      text-shadow: none !important;
    }
    .bt-sw-swatch:hover { transform: scale(1.12) !important; }
    .bt-sw-swatch.selected { border-color: var(--bt-text, #E3E3E8) !important; }

    .bt-sw-auto {
      width: auto !important;
      min-width: 44px !important;
      padding: 0 8px !important;
      height: 26px !important;
      border-radius: 13px !important;
      background: conic-gradient(#ef4444, #f59e0b, #10b981, #3b82f6, #8b5cf6, #ef4444) !important;
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      color: #FFFFFF !important;
      font-weight: 700 !important;
      font-size: 9px !important;
      letter-spacing: 0.06em !important;
      line-height: 1 !important;
      text-shadow: 0 1px 2px rgba(0,0,0,0.6) !important;
      font-family: var(--bt-font) !important;
    }
    .bt-sw-auto::before { content: 'AUTO'; }

    .bt-sw-custom-wrap {
      position: relative;
      display: inline-block;
      width: 26px;
      height: 26px;
    }
    .bt-sw-custom-wrap input[type="color"] {
      position: absolute !important;
      inset: 0 !important;
      width: 100% !important;
      height: 100% !important;
      padding: 0 !important;
      margin: 0 !important;
      border: 0 !important;
      border-radius: 50% !important;
      background: transparent !important;
      cursor: pointer !important;
      opacity: 0 !important;
      box-shadow: none !important;
    }
    .bt-sw-custom-display {
      width: 26px;
      height: 26px;
      border-radius: 50%;
      border: 2px solid transparent;
      pointer-events: none;
      box-shadow: inset 0 0 0 1px rgba(0,0,0,0.15);
      transition: border-color var(--bt-trans);
      background: conic-gradient(#ef4444, #f59e0b, #10b981, #3b82f6, #8b5cf6, #ef4444);
      display: flex;
      align-items: center;
      justify-content: center;
      color: #FFFFFF;
      font-weight: 700;
      font-size: 14px;
      line-height: 1;
      text-shadow: 0 1px 2px rgba(0,0,0,0.5);
    }
    .bt-sw-custom-display::before { content: '+'; }
    .bt-sw-custom-wrap.selected .bt-sw-custom-display::before { content: ''; }
    .bt-sw-custom-wrap.selected .bt-sw-custom-display {
      border-color: var(--bt-text, #E3E3E8);
    }
    /*-- BT_ALWAYS_ON_END --*/


    /* ============================================================
       v2.8.3 — LIGHT THREAD POST ALTERNATION, FINAL OVERRIDE

       Theme-aware version. The post colours come from the active light
       palette, not from Classic hardcoded blue:
         --bt-post-bg
         --bt-post-alt-bg
         --bt-poster-bg
         --bt-poster-alt-bg

       So Classic, Pearl, Cream, Mint and Rose each get their own matching
       alternation. This block deliberately sits at the END of the theme CSS
       so it wins over broad rules like .post, .poster_info and td[style].
       ============================================================ */

    :root[data-bt-theme="light"] tr.windowbg,
    :root[data-bt-theme="light"] td.windowbg,
    :root[data-bt-theme="light"] tr.windowbg > td,
    :root[data-bt-theme="light"] table.bordercolor tr.windowbg > td,
    :root[data-bt-theme="light"] table.bordercolor td.windowbg,
    :root[data-bt-theme="light"] .tborder tr.windowbg > td,
    :root[data-bt-theme="light"] .tborder td.windowbg {
      background-color: var(--bt-post-bg, var(--bt-surface-1)) !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg2,
    :root[data-bt-theme="light"] td.windowbg2,
    :root[data-bt-theme="light"] tr.windowbg2 > td,
    :root[data-bt-theme="light"] table.bordercolor tr.windowbg2 > td,
    :root[data-bt-theme="light"] table.bordercolor td.windowbg2,
    :root[data-bt-theme="light"] .tborder tr.windowbg2 > td,
    :root[data-bt-theme="light"] .tborder td.windowbg2 {
      background-color: var(--bt-post-alt-bg, var(--bt-surface-2)) !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg3,
    :root[data-bt-theme="light"] td.windowbg3,
    :root[data-bt-theme="light"] tr.windowbg3 > td,
    :root[data-bt-theme="light"] table.bordercolor tr.windowbg3 > td,
    :root[data-bt-theme="light"] table.bordercolor td.windowbg3,
    :root[data-bt-theme="light"] .tborder tr.windowbg3 > td,
    :root[data-bt-theme="light"] .tborder td.windowbg3 {
      background-color: var(--bt-post-bg, var(--bt-surface-1)) !important;
      background-image: none !important;
    }

    /* Visible post body/wrapper. */
    :root[data-bt-theme="light"] tr.windowbg .td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg.td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg .td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg .post,
    :root[data-bt-theme="light"] td.windowbg .post,
    :root[data-bt-theme="light"] tr.windowbg td.post,
    :root[data-bt-theme="light"] td.windowbg.post,
    :root[data-bt-theme="light"] tr.windowbg td[style],
    :root[data-bt-theme="light"] td.windowbg td[style] {
      background-color: var(--bt-post-bg, var(--bt-surface-1)) !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg2 .td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg2.td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg2 .td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg2 .post,
    :root[data-bt-theme="light"] td.windowbg2 .post,
    :root[data-bt-theme="light"] tr.windowbg2 td.post,
    :root[data-bt-theme="light"] td.windowbg2.post,
    :root[data-bt-theme="light"] tr.windowbg2 td[style],
    :root[data-bt-theme="light"] td.windowbg2 td[style] {
      background-color: var(--bt-post-alt-bg, var(--bt-surface-2)) !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg3 .td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg3.td_headerandpost,
    :root[data-bt-theme="light"] td.windowbg3 .td_headerandpost,
    :root[data-bt-theme="light"] tr.windowbg3 .post,
    :root[data-bt-theme="light"] td.windowbg3 .post,
    :root[data-bt-theme="light"] tr.windowbg3 td.post,
    :root[data-bt-theme="light"] td.windowbg3.post,
    :root[data-bt-theme="light"] tr.windowbg3 td[style],
    :root[data-bt-theme="light"] td.windowbg3 td[style] {
      background-color: var(--bt-post-bg, var(--bt-surface-1)) !important;
      background-image: none !important;
    }

    /* Poster/sidebar column: same theme family, slightly deeper for separation. */
    :root[data-bt-theme="light"] tr.windowbg .poster,
    :root[data-bt-theme="light"] tr.windowbg .poster_info,
    :root[data-bt-theme="light"] td.windowbg.poster,
    :root[data-bt-theme="light"] td.windowbg.poster_info {
      background-color: var(--bt-poster-bg, var(--bt-post-bg)) !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg2 .poster,
    :root[data-bt-theme="light"] tr.windowbg2 .poster_info,
    :root[data-bt-theme="light"] td.windowbg2.poster,
    :root[data-bt-theme="light"] td.windowbg2.poster_info {
      background-color: var(--bt-poster-alt-bg, var(--bt-post-alt-bg)) !important;
      background-image: none !important;
    }

    :root[data-bt-theme="light"] tr.windowbg3 .poster,
    :root[data-bt-theme="light"] tr.windowbg3 .poster_info,
    :root[data-bt-theme="light"] td.windowbg3.poster,
    :root[data-bt-theme="light"] td.windowbg3.poster_info {
      background-color: var(--bt-poster-bg, var(--bt-post-bg)) !important;
      background-image: none !important;
    }

    /* Keep quote/code/input blocks distinct inside alternating posts. */
    :root[data-bt-theme="light"] tr.windowbg .quote,
    :root[data-bt-theme="light"] tr.windowbg2 .quote,
    :root[data-bt-theme="light"] tr.windowbg3 .quote,
    :root[data-bt-theme="light"] td.windowbg .quote,
    :root[data-bt-theme="light"] td.windowbg2 .quote,
    :root[data-bt-theme="light"] td.windowbg3 .quote {
      background-color: var(--bt-quote-bg) !important;
      border-left-color: var(--bt-accent) !important;
    }

    :root[data-bt-theme="light"] tr.windowbg .code,
    :root[data-bt-theme="light"] tr.windowbg2 .code,
    :root[data-bt-theme="light"] tr.windowbg3 .code,
    :root[data-bt-theme="light"] td.windowbg .code,
    :root[data-bt-theme="light"] td.windowbg2 .code,
    :root[data-bt-theme="light"] td.windowbg3 .code {
      background-color: var(--bt-code-bg) !important;
    }

    :root[data-bt-theme="light"] tr.windowbg input,
    :root[data-bt-theme="light"] tr.windowbg2 input,
    :root[data-bt-theme="light"] tr.windowbg3 input,
    :root[data-bt-theme="light"] tr.windowbg textarea,
    :root[data-bt-theme="light"] tr.windowbg2 textarea,
    :root[data-bt-theme="light"] tr.windowbg3 textarea,
    :root[data-bt-theme="light"] tr.windowbg select,
    :root[data-bt-theme="light"] tr.windowbg2 select,
    :root[data-bt-theme="light"] tr.windowbg3 select {
      background-color: var(--bt-input-bg) !important;
    }

  `;

  // ===========================================================================
  // CSS injection
  // ===========================================================================

  function splitCss(src) {
    const startMarker = '/*-- BT_ALWAYS_ON_START --*/';
    const endMarker = '/*-- BT_ALWAYS_ON_END --*/';
    let theme = '';
    let always = '';
    let i = 0;
    while (i < src.length) {
      const startIdx = src.indexOf(startMarker, i);
      if (startIdx === -1) {
        theme += src.slice(i);
        break;
      }
      theme += src.slice(i, startIdx);
      const after = startIdx + startMarker.length;
      const endIdx = src.indexOf(endMarker, after);
      if (endIdx === -1) {
        always += src.slice(after);
        break;
      }
      always += src.slice(after, endIdx);
      i = endIdx + endMarker.length;
    }
    return { theme, always };
  }

  let themeStyleEl = null;
  let alwaysStyleEl = null;

  function injectCSS() {
    const { theme, always } = splitCss(css);
    themeStyleEl = document.createElement('style');
    themeStyleEl.id = 'bt-theme-css';
    themeStyleEl.textContent = theme;
    (document.head || document.documentElement).appendChild(themeStyleEl);

    alwaysStyleEl = document.createElement('style');
    alwaysStyleEl.id = 'bt-always-css';
    alwaysStyleEl.textContent = always;
    (document.head || document.documentElement).appendChild(alwaysStyleEl);

    if (!document.getElementById('bt-fonts')) {
      const link = document.createElement('link');
      link.id = 'bt-fonts';
      link.rel = 'stylesheet';
      link.href =
        'https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@400;500;600;700' +
        '&family=JetBrains+Mono:wght@400;500&display=swap';
      (document.head || document.documentElement).appendChild(link);
    }
  }

  // ===========================================================================
  // Switcher UI
  // ===========================================================================

  const ICONS = {
    cog: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',
    sun: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>',
    moon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>',
    monitor: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/></svg>',
    power: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18.36 6.64a9 9 0 1 1-12.73 0"/><line x1="12" y1="2" x2="12" y2="12"/></svg>',
  };

  function buildSwitcher(host) {
    if (document.getElementById('bt-switcher')) return;

    const container = document.createElement('div');
    container.id = 'bt-switcher';
    container.innerHTML = `
      <button id="bt-switcher-button" type="button" title="Theme settings" aria-label="Theme settings">
        ${ICONS.cog}
      </button>
      <div id="bt-switcher-panel" role="dialog" aria-label="Theme settings">
        <div class="bt-sw-section">
          <span class="bt-sw-label">Mode</span>
          <div class="bt-sw-row">
            <button type="button" class="bt-sw-theme-btn" data-theme="light" title="Light">
              ${ICONS.sun}<span class="bt-sw-theme-label">Light</span>
            </button>
            <button type="button" class="bt-sw-theme-btn" data-theme="dark" title="Dark">
              ${ICONS.moon}<span class="bt-sw-theme-label">Dark</span>
            </button>
            <button type="button" class="bt-sw-theme-btn" data-theme="system" title="Follow system">
              ${ICONS.monitor}<span class="bt-sw-theme-label">Auto</span>
            </button>
            <button type="button" class="bt-sw-theme-btn" data-theme="off" title="Turn the theme off">
              ${ICONS.power}<span class="bt-sw-theme-label">OFF</span>
            </button>
          </div>
        </div>
        <div class="bt-sw-customize">
          <span class="bt-sw-customize-title" id="bt-sw-customize-title">Customise Colours</span>
          <div class="bt-sw-section">
            <span class="bt-sw-label">Main</span>
            <div class="bt-sw-row" id="bt-sw-main-row"></div>
          </div>
          <div class="bt-sw-section">
            <span class="bt-sw-label">Accent</span>
            <div class="bt-sw-row" id="bt-sw-accent-row"></div>
          </div>
        </div>
      </div>
    `;
    host.appendChild(container);

    const btn = container.querySelector('#bt-switcher-button');
    btn.addEventListener('click', (e) => {
      e.stopPropagation();
      const currentPref = getPref(KEY_THEME, DEFAULT_THEME);
      if (currentPref === 'off') {
        const prior = getPref(KEY_THEME_PRIOR, 'dark');
        setPref(KEY_THEME, prior);
        applyTheme();
        return;
      }
      container.classList.toggle('open');
    });
    document.addEventListener('click', (e) => {
      if (!container.contains(e.target)) container.classList.remove('open');
    });
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') container.classList.remove('open');
    });

    container.querySelectorAll('.bt-sw-theme-btn').forEach(b => {
      b.addEventListener('click', () => {
        const choice = b.dataset.theme;
        if (choice === 'off') {
          const current = getPref(KEY_THEME, DEFAULT_THEME);
          if (current === 'off') {
            const prior = getPref(KEY_THEME_PRIOR, 'dark');
            setPref(KEY_THEME, prior);
          } else {
            setPref(KEY_THEME_PRIOR, current);
            setPref(KEY_THEME, 'off');
          }
          container.classList.remove('open');
        } else {
          setPref(KEY_THEME, choice);
        }
        applyTheme();
      });
    });

    function handleSwatchClick(kind) {
      return (e) => {
        const swatch = e.target.closest(`[data-${kind}]`);
        if (!swatch || swatch.tagName === 'INPUT') return;
        const themeNow = getEffectiveTheme(getPref(KEY_THEME, DEFAULT_THEME));
        if (themeNow === 'off') return;
        const storageKey = kind === 'main'
          ? (themeNow === 'dark' ? KEY_MAIN_DARK : KEY_MAIN_LIGHT)
          : (themeNow === 'dark' ? KEY_ACCENT_DARK : KEY_ACCENT_LIGHT);
        setPref(storageKey, swatch.dataset[kind]);
        applyTheme();
      };
    }
    container.querySelector('#bt-sw-main-row').addEventListener('click', handleSwatchClick('main'));
    container.querySelector('#bt-sw-accent-row').addEventListener('click', handleSwatchClick('accent'));

    function handleColorInput(kind) {
      return (e) => {
        if (!e.target.matches(`input[type="color"][data-target="${kind}"]`)) return;
        const themeNow = getEffectiveTheme(getPref(KEY_THEME, DEFAULT_THEME));
        if (themeNow === 'off') return;
        const storageKey = kind === 'main'
          ? (themeNow === 'dark' ? KEY_MAIN_DARK : KEY_MAIN_LIGHT)
          : (themeNow === 'dark' ? KEY_ACCENT_DARK : KEY_ACCENT_LIGHT);
        const customStorageKey = kind === 'main'
          ? (themeNow === 'dark' ? KEY_MAIN_DARK_CUSTOM : KEY_MAIN_LIGHT_CUSTOM)
          : (themeNow === 'dark' ? KEY_ACCENT_DARK_CUSTOM : KEY_ACCENT_LIGHT_CUSTOM);
        setPref(customStorageKey, e.target.value);
        setPref(storageKey, 'custom');
        applyTheme();
      };
    }
    container.querySelector('#bt-sw-main-row').addEventListener('input', handleColorInput('main'));
    container.querySelector('#bt-sw-accent-row').addEventListener('input', handleColorInput('accent'));

    applyTheme();
  }

  function injectSwitcher() {
    const host =
      document.getElementById('upper_section') ||
      document.getElementById('header') ||
      document.body;
    if (host) buildSwitcher(host);
  }

  // ===========================================================================
  // Integrated Safari flash guard
  // ===========================================================================

  function getHoldBackground() {
    const fromSession = ssGet(NAV_BG_SESSION_KEY);
    if (fromSession) return fromSession;
    const pref = getPref(KEY_THEME, DEFAULT_THEME);
    const effective = getEffectiveTheme(pref);
    if (effective === 'off') return null;
    return getActiveMainHex(effective) || DEFAULT_CUSTOM_MAIN_DARK;
  }

  function getCurrentThemeBackground() {
    const root = document.documentElement;
    try {
      const inlineVar = root && root.style ? root.style.getPropertyValue('--bt-bg').trim() : '';
      if (inlineVar) return inlineVar;
    } catch (e) {}
    try {
      const computedVar = getComputedStyle(root).getPropertyValue('--bt-bg').trim();
      if (computedVar) return computedVar;
    } catch (e) {}
    return getHoldBackground() || DEFAULT_CUSTOM_MAIN_DARK;
  }

  function holdCss(bg, revealedSelector) {
    const scheme = getEffectiveTheme(getPref(KEY_THEME, DEFAULT_THEME)) === 'light' ? 'light' : 'dark';
    return `
      html${revealedSelector} {
        background: ${bg} !important;
        color-scheme: ${scheme} !important;
      }
      html${revealedSelector}::before {
        content: '' !important;
        position: fixed !important;
        inset: 0 !important;
        width: 100vw !important;
        height: 100vh !important;
        background: ${bg} !important;
        z-index: 2147483647 !important;
        pointer-events: none !important;
      }
      html${revealedSelector} body {
        visibility: hidden !important;
        opacity: 0 !important;
        background: ${bg} !important;
      }
    `;
  }

  function injectTransientStyle(id, cssText) {
    let style = document.getElementById(id);
    if (!style) {
      style = document.createElement('style');
      style.id = id;
      (document.documentElement || document.head || document.body).appendChild(style);
    }
    style.textContent = cssText;
    return style;
  }

  function removeTransientStyle(id) {
    const style = document.getElementById(id);
    if (style) style.remove();
  }

  function holdPaint() {
    if (document.readyState === 'complete') return false;
    const bg = getHoldBackground();
    if (!bg) return false;

    const root = document.documentElement;
    const holdStyle = injectTransientStyle(
      INCOMING_HOLD_STYLE_ID,
      holdCss(bg, `:not([${HOLD_REVEALED_ATTR}])`)
    );

    if (typeof MutationObserver !== 'undefined') {
      const observer = new MutationObserver(() => {
        if (!document.getElementById(INCOMING_HOLD_STYLE_ID)) {
          try { document.documentElement.appendChild(holdStyle); } catch (e) {}
        }
      });
      try {
        observer.observe(root, { childList: true });
        holdStyle._btObserver = observer;
      } catch (e) {}
    }

    setTimeout(() => revealNow(), 1500);
    return true;
  }

  function revealNow() {
    document.documentElement.setAttribute(HOLD_REVEALED_ATTR, '');
    const holdStyle = document.getElementById(INCOMING_HOLD_STYLE_ID);
    if (holdStyle && holdStyle._btObserver) {
      try { holdStyle._btObserver.disconnect(); } catch (e) {}
    }
    ssRemove(NAV_UNTIL_SESSION_KEY);
  }

  function releasePaint() {
    revealNow();
  }

  function markNavigationHold(bg) {
    ssSet(NAV_UNTIL_SESSION_KEY, String(Date.now() + NAV_HOLD_SESSION_MS));
    ssSet(NAV_BG_SESSION_KEY, bg);
  }

  function applyOutgoingHold() {
    if (getPref(KEY_THEME, DEFAULT_THEME) === 'off') return;
    const bg = getCurrentThemeBackground();
    markNavigationHold(bg);
    injectTransientStyle(OUTGOING_HOLD_STYLE_ID, holdCss(bg, ''));
    setTimeout(() => removeTransientStyle(OUTGOING_HOLD_STYLE_ID), OUTGOING_CANCEL_RESTORE_MS);
  }

  function isPlainPrimaryActivation(e) {
    if (e.defaultPrevented) return false;
    if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return false;
    if (typeof e.button === 'number' && e.button !== 0) return false;
    return true;
  }

  function shouldHoldForLink(a, e) {
    if (!a || !isPlainPrimaryActivation(e)) return false;
    if (a.target && a.target !== '_self') return false;
    if (a.hasAttribute('download')) return false;

    const href = a.getAttribute('href') || '';
    if (!href) return false;
    if (href.startsWith('#')) return false;
    if (/^\s*javascript:/i.test(href)) return false;

    let url;
    try {
      url = new URL(href, window.location.href);
    } catch (e2) {
      return false;
    }

    if (
      url.origin === window.location.origin &&
      url.pathname === window.location.pathname &&
      url.search === window.location.search &&
      url.hash
    ) {
      return false;
    }
    return true;
  }

  function targetLinkFromEvent(e) {
    const target = e.target;
    return target && target.closest ? target.closest(NAV_SELECTOR) : null;
  }

  function installPreNavigationHold() {
    ['pointerdown', 'mousedown', 'touchstart', 'click'].forEach((type) => {
      document.addEventListener(type, (e) => {
        const a = targetLinkFromEvent(e);
        if (!shouldHoldForLink(a, e)) return;
        applyOutgoingHold();
      }, true);
    });

    document.addEventListener('keydown', (e) => {
      if (e.key !== 'Enter' && e.key !== ' ') return;
      const active = document.activeElement;
      const a = active && active.closest ? active.closest(NAV_SELECTOR) : null;
      if (!shouldHoldForLink(a, e)) return;
      applyOutgoingHold();
    }, true);

    window.addEventListener('beforeunload', () => {
      if (getPref(KEY_THEME, DEFAULT_THEME) !== 'off') applyOutgoingHold();
    });
    window.addEventListener('pagehide', () => {
      if (getPref(KEY_THEME, DEFAULT_THEME) !== 'off') applyOutgoingHold();
    });
    window.addEventListener('pageshow', () => {
      removeTransientStyle(OUTGOING_HOLD_STYLE_ID);
      document.documentElement.setAttribute(HOLD_REVEALED_ATTR, '');
    });
  }

  // ===========================================================================
  // Init
  // ===========================================================================

  function setupRootAttributes() {
    let pref = null;
    if (hasGM) {
      try {
        const v = GM_getValue(KEY_THEME, null);
        if (v != null && v !== '') pref = String(v);
      } catch (e) {}
    }
    if (!pref) {
      try {
        const v = localStorage.getItem(KEY_THEME);
        if (v != null && v !== '') pref = v;
      } catch (e) {}
    }
    if (!pref) pref = DEFAULT_THEME;

    const effective = getEffectiveTheme(pref);
    const root = document.documentElement;
    root.setAttribute('data-bt-no-transitions', '');

    if (effective === 'off') {
      root.setAttribute('data-bt-active', 'false');
      return;
    }

    root.setAttribute('data-bt-active', 'true');
    root.setAttribute('data-bt-theme', effective);
    root.style.colorScheme = effective;
  }

  const paintHeld = false; // disabled: separate early guard handles paint
  setupRootAttributes();
  syncStores();
  injectCSS();
  applyTheme();
  if (paintHeld) releasePaint();
  // // // // installPreNavigationHold(); // disabled: separate 000 early guard handles Safari navigation flash // disabled: separate early guard handles Safari navigation flash // disabled: readable-bootstrap guard handles Safari navigation flash // disabled: bootstrap guard handles Safari navigation flash

  function enableTransitions() {
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        document.documentElement.removeAttribute('data-bt-no-transitions');
      });
    });
  }
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', enableTransitions, { once: true });
  } else {
    enableTransitions();
  }

  window.addEventListener('storage', (e) => {
    if (e && e.key && ALL_KEYS.indexOf(e.key) !== -1) {
      applyTheme();
    }
  });

  let modernizeTimer = null;
  function scheduleModernize() {
    if (modernizeTimer) return;
    modernizeTimer = setTimeout(() => {
      modernizeTimer = null;
      modernizeBBCodeIcons();
      modernizeSmileys();
      stylePostMetaButtons();
      fixMaintabCaps();
    }, 50);
  }

  function runInitialPasses() {
    fixMaintabCaps();
    modernizeBBCodeIcons();
    modernizeSmileys();
    stylePostMetaButtons();
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => {
      applyTheme();
      injectSwitcher();
      runInitialPasses();
    }, { once: true });
  } else {
    injectSwitcher();
    runInitialPasses();
  }

  if (typeof MutationObserver !== 'undefined') {
    const obs = new MutationObserver((mutations) => {
      for (const m of mutations) {
        if (m.addedNodes && m.addedNodes.length > 0) {
          scheduleModernize();
          return;
        }
      }
    });
    if (document.body) {
      obs.observe(document.body, { childList: true, subtree: true });
    } else {
      document.addEventListener('DOMContentLoaded', () => {
        obs.observe(document.body, { childList: true, subtree: true });
      }, { once: true });
    }
  }

  if (window.matchMedia) {
    const mq = window.matchMedia('(prefers-color-scheme: dark)');
    const reapply = () => {
      if (getPref(KEY_THEME, DEFAULT_THEME) === 'system') applyTheme();
    };
    if (mq.addEventListener) mq.addEventListener('change', reapply);
    else if (mq.addListener) mq.addListener(reapply);
  }
})();