Полный редизайн: идеальная прозрачность, современный стиль, рабочая кнопка настроек
// ==UserScript==
// @name 🎨 BR Pro Ultimate | Modern Glass
// @namespace http://tampermonkey.net/
// @version 5.3.0
// @description Полный редизайн: идеальная прозрачность, современный стиль, рабочая кнопка настроек
// @author Akzholch1k
// @match https://forum.blackrussia.online/*
// @license MIT
// @grant none
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
/* ══════════ ️ CONFIG ══════════ */
const CONFIG = {
KEY: 'br5',
VERSION: '5.2.0',
DEFAULTS: {
theme: 'dark',
font: 'Rajdhani',
size: 15,
wp: '',
wpa: 85,
wpb: 1,
wpcat: '📱 GIF Телефон',
fx: 'none',
fxn: 70,
tab: 'wp',
clock: true,
prog: true,
blockAlpha: 88,
reducedMotion: false
}
};
/* ══════════ 🗄️ STATE ══════════ */
let State = { ...CONFIG.DEFAULTS };
let $ = {}; // DOM cache
let canvas, ctx, particles = [], animId = null;
// 🔐 Safe storage
const load = () => {
try {
const raw = localStorage.getItem(CONFIG.KEY);
if (raw) {
const parsed = JSON.parse(raw);
Object.entries(parsed).forEach(([k, v]) => {
if (k in CONFIG.DEFAULTS && typeof v === typeof CONFIG.DEFAULTS[k]) State[k] = v;
});
}
} catch (e) { console.warn('[BR] Load err:', e); }
};
const save = () => {
try { localStorage.setItem(CONFIG.KEY, JSON.stringify(State)); }
catch (e) { console.warn('[BR] Save err:', e); }
};
load();
/* ══════════ 🎨 MODERN THEMES ══════════ */
const THEMES = {
dark: {
name: ' Midnight',
bg: '#0f0f1a',
accent: '#8b5cf6',
text: '#f0f4ff',
muted: '#8888aa',
panel: 'rgba(20, 20, 35, 0.72)',
card: 'rgba(139, 92, 246, 0.10)',
border: 'rgba(139, 92, 246, 0.28)',
input: 'rgba(255, 255, 255, 0.05)',
hover: 'rgba(139, 92, 246, 0.14)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.5)',
glow: '0 0 20px rgba(139, 92, 246, 0.3)'
},
light: {
name: '️ Daylight',
bg: '#f8fafc',
accent: '#6366f1',
text: '#1e293b',
muted: '#64748b',
panel: 'rgba(255, 255, 255, 0.78)',
card: 'rgba(99, 102, 241, 0.08)',
border: 'rgba(99, 102, 241, 0.22)',
input: 'rgba(0, 0, 0, 0.04)',
hover: 'rgba(99, 102, 241, 0.10)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.12)',
glow: '0 0 20px rgba(99, 102, 241, 0.25)'
},
sakura: {
name: '🌸 Sakura Dream',
bg: '#1a0a14',
accent: '#f472b6',
text: '#fff0f6',
muted: '#c084a0',
panel: 'rgba(30, 12, 24, 0.72)',
card: 'rgba(244, 114, 182, 0.10)',
border: 'rgba(244, 114, 182, 0.28)',
input: 'rgba(255, 200, 220, 0.06)',
hover: 'rgba(244, 114, 182, 0.14)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.45)',
glow: '0 0 20px rgba(244, 114, 182, 0.3)'
},
neon: {
name: '⚡ Cyber Neon',
bg: '#030712',
accent: '#06b6d4',
text: '#cffafe',
muted: '#22d3ee',
panel: 'rgba(3, 7, 18, 0.75)',
card: 'rgba(6, 182, 212, 0.10)',
border: 'rgba(6, 182, 212, 0.32)',
input: 'rgba(6, 182, 212, 0.06)',
hover: 'rgba(6, 182, 212, 0.13)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.6)',
glow: '0 0 25px rgba(6, 182, 212, 0.4)'
},
nature: {
name: '🌿 Forest Mist',
bg: '#051008',
accent: '#22c55e',
text: '#dcfce7',
muted: '#4ade80',
panel: 'rgba(6, 18, 10, 0.72)',
card: 'rgba(34, 197, 94, 0.10)',
border: 'rgba(34, 197, 94, 0.26)',
input: 'rgba(34, 197, 94, 0.06)',
hover: 'rgba(34, 197, 94, 0.13)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.45)',
glow: '0 0 20px rgba(34, 197, 94, 0.3)'
},
sunset: {
name: '🌅 Golden Hour',
bg: '#1c0f0a',
accent: '#f97316',
text: '#ffedd5',
muted: '#fb923c',
panel: 'rgba(30, 15, 12, 0.72)',
card: 'rgba(249, 115, 22, 0.10)',
border: 'rgba(249, 115, 22, 0.28)',
input: 'rgba(249, 115, 22, 0.06)',
hover: 'rgba(249, 115, 22, 0.14)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.5)',
glow: '0 0 20px rgba(249, 115, 22, 0.35)'
},
ocean: {
name: '🌊 Deep Ocean',
bg: '#020c1a',
accent: '#38bdf8',
text: '#e0f2fe',
muted: '#7dd3fc',
panel: 'rgba(2, 12, 26, 0.72)',
card: 'rgba(56, 189, 248, 0.10)',
border: 'rgba(56, 189, 248, 0.26)',
input: 'rgba(56, 189, 248, 0.06)',
hover: 'rgba(56, 189, 248, 0.13)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.5)',
glow: '0 0 20px rgba(56, 189, 248, 0.3)'
},
rose: {
name: '🥀 Velvet Rose',
bg: '#140a0e',
accent: '#ec4899',
text: '#fce7f3',
muted: '#f472b6',
panel: 'rgba(24, 12, 18, 0.72)',
card: 'rgba(236, 72, 153, 0.10)',
border: 'rgba(236, 72, 153, 0.28)',
input: 'rgba(236, 72, 153, 0.06)',
hover: 'rgba(236, 72, 153, 0.14)',
shadow: '0 8px 32px rgba(0, 0, 0, 0.48)',
glow: '0 0 20px rgba(236, 72, 153, 0.32)'
}
};
const FONTS = [
{ id: 'Rajdhani', f: '"Rajdhani", system-ui, sans-serif' },
{ id: 'Orbitron', f: '"Orbitron", system-ui, sans-serif' },
{ id: 'Exo 2', f: '"Exo 2", system-ui, sans-serif' },
{ id: 'Montserrat', f: '"Montserrat", system-ui, sans-serif' },
{ id: 'Roboto', f: '"Roboto", system-ui, sans-serif' },
{ id: 'Системный', f: 'system-ui, -apple-system, sans-serif' }
];
const GALLERY = {
'📱 GIF Телефон': [
'https://i.postimg.cc/Wz78xbdj/aesthetic.gif','https://i.postimg.cc/cLzmpzLq/chill-japan.gif',
'https://i.postimg.cc/WzSmXWys/idk.gif','https://i.postimg.cc/Dw4sXw7n/gif-chill.gif',
'https://i.postimg.cc/nrL9cH3R/moon-planet.gif','https://i.postimg.cc/c42t0GfH/honkai-impact.gif',
'https://i.postimg.cc/L8y92zcF/live-wallpaper.gif','https://i.postimg.cc/MT5tFpMX/vibe.gif',
'https://i.postimg.cc/cJMcvLcQ/wallpaper.gif','https://i.postimg.cc/Z5PNcDvL/cyberpunk.gif',
'https://i.postimg.cc/50D5GQ45/lofi-anime.gif','https://i.postimg.cc/TPwr3Jh4/haikyuu-hinata.gif',
'https://i.postimg.cc/zGfLCX5q/zerotwo.gif','https://i.postimg.cc/tg5hXmX4/honkai-impact-(1).gif',
'https://i.postimg.cc/V6WHPFhD/happy-birthday.gif','https://i.postimg.cc/pTmyg0y9/te-amo-feliz-cumpleanos.gif',
],
'️ GIF ПК': [
'https://i.postimg.cc/xTVHr2Q3/hug.gif','https://i.postimg.cc/5NXwq0nB/babako.gif',
'https://i.postimg.cc/vTY4BQZ2/nezuko.gif','https://i.postimg.cc/90kchVRc/waifu.gif',
'https://i.postimg.cc/SRnpV5Tp/osaka-lofi-banner.gif','https://i.postimg.cc/Vk8kLfZk/cherry.gif',
'https://i.postimg.cc/ncvn58Vs/kirokaze.gif','https://i.postimg.cc/fbgsXDCP/kirokaze-(1).gif',
'https://i.postimg.cc/90dsxhdJ/pokemon.gif','https://i.postimg.cc/sgX0WSNH/background-kereta.gif',
'https://i.postimg.cc/j57jSDTn/adventure-time.gif','https://i.postimg.cc/L6Rsm4bP/cat-kedi.gif',
'https://i.postimg.cc/pd8T29RX/rust-oil-rig.gif','https://i.postimg.cc/q79kSpKc/shinobu.gif',
],
'✨ Разное': [
'https://i.postimg.cc/Kz7vXdxc/2b1790a454afdb18da1ac7c459330b05.gif',
'https://i.postimg.cc/mrHgjPn1/54963f909932467ce747f9dc25cd2c6e.gif',
'https://i.postimg.cc/4dRNSJCp/72bdbd20d38ab581aba4eac36a94ffae.gif',
'https://i.postimg.cc/TwvY4R8g/747140ce3b513f2b39cfae161e56b4dd.gif',
'https://i.postimg.cc/B6fQVqWP/fdfe94c7bdd0bf4afdd830e0b2c515e9-(1).gif',
'https://i.postimg.cc/9f7QbDkF/0bd00269d46d7a3dd09eb273c7da02ee.jpg',
'https://i.postimg.cc/0Nwynz4S/145b85f6ea6b21515ff3b308a0ee4a2a.jpg',
'https://i.postimg.cc/GpymK4fC/8eb01fb47d1e21f8db58cef9dbce93a7.jpg',
'https://i.postimg.cc/W4k18dyr/96bd7eb39ac874247723bcf5e8aa06bc.jpg',
'https://i.postimg.cc/FKLHpY6J/fa202ee1d6b40e48f3698ca2a2f517c4.jpg',
],
' Природа': [
'https://i.postimg.cc/fThHC5J9/0185acd4ab82d25d60eef415adf19a2f.jpg',
'https://i.postimg.cc/BQGhpNX4/30028eb3ab96fa9fa4c361a1481f4952.jpg',
'https://i.postimg.cc/YqwXR8hv/7bd2995d3f3cb531afd718b714426ac9.jpg',
'https://i.postimg.cc/wTdW2F7y/b3a35bba489d6306b454d8b089e1e4bd.jpg',
'https://i.postimg.cc/8kfmfYmC/2d332406197d20278a6add33a10c7507.jpg',
'https://i.postimg.cc/zDHFHQF5/f5a524b0d731a3a15e5700316b1c4cbd.jpg',
'https://i.postimg.cc/7Pp8Spvg/64de71a19c72c32c4cbcbbb0a08dad13.jpg',
'https://i.postimg.cc/WbgR8Xj6/77ffa189c556187d1aca079e0248c473.jpg',
],
'🏙️ Город': [
'https://i.postimg.cc/50Ljb8LG/15020ac296aa3ab8b8da46db65777710-(1).jpg',
'https://i.postimg.cc/j5PCtyPv/182f03ba7db4be84edda6fdc52f5b6a7.jpg',
'https://i.postimg.cc/JnZtMjZ2/5b10b689b889be48a61e419c7534ad40.jpg',
'https://i.postimg.cc/tTW7pFWw/5e22910a69edb226b865bbafa18a285c.jpg',
'https://i.postimg.cc/vBfDb5f3/802a726c4e09ef60773b6e9b5d334da7.jpg',
'https://i.postimg.cc/k4KDqWKs/c57fd23ca8031721d6c176afbb9f7182.jpg',
],
'❄️ Зима/НГ': [
'https://i.postimg.cc/6qx2vMtP/358a87e9957fb2f8ca9dfd6a5fe67851.jpg',
'https://i.postimg.cc/d3cky5JQ/42fc33a3f381c0d828b89c70d95fca04.jpg',
'https://i.postimg.cc/brfDtmqX/51c5feacfee4e9f4a2a1792f9db8cd91.jpg',
'https://i.postimg.cc/C1qn53py/87d19b7e6d86e5133303770fe46dc9e1.jpg',
'https://i.postimg.cc/sxCQhT3D/a5bc068f9e5010308334d36411147583.jpg',
'https://i.postimg.cc/hvRzd2cH/a9de41f2b5e45a873b1327ce1b37ef28.jpg',
'https://i.postimg.cc/90HR7LCN/dbcf6265bb574a238ca1da34513de917.jpg',
'https://i.postimg.cc/NFv9HdBZ/dfc77c71895d4f004c0687bf3c4d4801.jpg',
],
};
const SERVERS = Array.from({ length: 91 }, (_, i) => ({
n: i + 1,
url: `https://forum.blackrussia.online/search/?q=%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0+${i + 1}&o=date`
}));
/* ══════════ 🎭 PARTICLES — FIXED ══════════ */
const FX = {
init() {
if (!canvas) return;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
},
create() {
const w = canvas.width, h = canvas.height;
const base = { x: Math.random() * w, y: Math.random() * h };
switch (State.fx) {
case 'sakura':
return { ...base, r: 3 + Math.random() * 4, vy: 0.5 + Math.random() * 1, vx: (Math.random() - 0.5) * 0.5, sway: Math.random() * 6.28, rot: Math.random() * 6.28, rs: (Math.random() - 0.5) * 0.03, a: 0.4 + Math.random() * 0.4, hue: 330 + Math.random() * 40, t: 'sakura' };
case 'snow':
return { ...base, r: 1.5 + Math.random() * 2.5, vy: 0.3 + Math.random() * 0.8, vx: (Math.random() - 0.5) * 0.25, sway: Math.random() * 6.28, a: 0.5 + Math.random() * 0.4, t: 'snow' };
case 'rain':
return { ...base, y: -15, len: 10 + Math.random() * 15, vy: 7 + Math.random() * 5, vx: -1.8, a: 0.2 + Math.random() * 0.25, t: 'rain' };
case 'stars':
return { ...base, r: 0.4 + Math.random() * 1.2, a: Math.random(), ad: (Math.random() > 0.5 ? 1 : -1) * (0.003 + Math.random() * 0.008), vy: -0.02 - Math.random() * 0.04, vx: (Math.random() - 0.5) * 0.025, t: 'stars' };
case 'firefly':
return { ...base, r: 1.2 + Math.random() * 2, a: Math.random(), ad: (Math.random() > 0.5 ? 1 : -1) * 0.01, ang: Math.random() * 6.28, sp: 0.2 + Math.random() * 0.3, hue: 45 + Math.random() * 75, t: 'firefly' };
case 'bubbles':
return { ...base, y: h + 15, r: 2.5 + Math.random() * 10, vy: -0.3 - Math.random() * 0.6, vx: (Math.random() - 0.5) * 0.2, a: 0.1 + Math.random() * 0.2, sway: Math.random() * 6.28, hue: Math.random() * 360, t: 'bubbles' };
default: return null;
}
},
update(p) {
const w = canvas.width, h = canvas.height;
switch (p.t) {
case 'sakura': p.sway += 0.015; p.y += p.vy; p.x += p.vx + Math.sin(p.sway) * 0.4; p.rot += p.rs; if (p.y > h + 25) return this.create(); break;
case 'snow': p.sway += 0.012; p.y += p.vy; p.x += p.vx + Math.sin(p.sway) * 0.25; if (p.y > h + 12) return this.create(); break;
case 'rain': p.y += p.vy; p.x += p.vx; if (p.y > h + 20) return this.create(); break;
case 'stars': p.y += p.vy; p.x += p.vx; p.a += p.ad; if (p.a < 0.05 || p.a > 1) p.ad *= -1; if (p.y < -3) p.y = h; if (p.y > h + 3) p.y = 0; if (p.x < -3) p.x = w; if (p.x > w + 3) p.x = 0; break;
case 'firefly': p.ang += 0.012; p.x += Math.cos(p.ang) * p.sp; p.y += Math.sin(p.ang) * p.sp; p.a += p.ad; if (p.a < 0.05 || p.a > 1) p.ad *= -1; if (p.x < 0 || p.x > w) { p.ang = Math.PI - p.ang; p.x = Math.max(0, Math.min(w, p.x)); } if (p.y < 0 || p.y > h) { p.ang = -p.ang; p.y = Math.max(0, Math.min(h, p.y)); } break;
case 'bubbles': p.sway += 0.012; p.y += p.vy; p.x += p.vx + Math.sin(p.sway) * 0.3; if (p.y < -p.r * 2) return this.create(); break;
}
return p;
},
draw(p) {
if (!ctx) return;
ctx.save();
const t = THEMES[State.theme];
switch (p.t) {
case 'sakura':
ctx.translate(p.x, p.y); ctx.rotate(p.rot); ctx.globalAlpha = p.a;
const g1 = ctx.createRadialGradient(0, 0, 0, 0, 0, p.r);
g1.addColorStop(0, `hsl(${p.hue}, 85%, 82%)`); g1.addColorStop(1, 'transparent');
ctx.fillStyle = g1; ctx.beginPath(); ctx.ellipse(0, 0, p.r, p.r * 0.55, 0, 0, 6.28); ctx.fill();
break;
case 'snow':
ctx.globalAlpha = p.a;
const g2 = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r);
g2.addColorStop(0, 'rgba(255,255,255,0.95)'); g2.addColorStop(1, 'transparent');
ctx.fillStyle = g2; ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, 6.28); ctx.fill();
break;
case 'rain':
ctx.globalAlpha = p.a; ctx.strokeStyle = 'rgba(150, 200, 255, 0.5)'; ctx.lineWidth = 0.7;
ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(p.x + p.vx * 2, p.y + p.len); ctx.stroke();
break;
case 'stars':
ctx.globalAlpha = Math.max(0.05, Math.min(1, p.a)); ctx.fillStyle = '#fff';
ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, 6.28); ctx.fill();
break;
case 'firefly':
ctx.globalAlpha = Math.max(0.05, Math.min(1, p.a));
const g3 = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r * 3);
g3.addColorStop(0, `hsla(${p.hue}, 100%, 78%, 0.9)`); g3.addColorStop(0.5, `hsla(${p.hue}, 100%, 70%, 0.25)`); g3.addColorStop(1, 'transparent');
ctx.fillStyle = g3; ctx.beginPath(); ctx.arc(p.x, p.y, p.r * 3, 0, 6.28); ctx.fill();
break;
case 'bubbles':
ctx.globalAlpha = p.a; ctx.strokeStyle = `hsla(${p.hue}, 75%, 80%, 0.75)`; ctx.lineWidth = 0.9;
ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, 6.28); ctx.stroke();
break;
}
ctx.restore();
},
start() {
this.stop();
if (State.fx === 'none' || !canvas || State.reducedMotion) return;
const isLow = navigator.hardwareConcurrency <= 4 || /Android|iPhone|iPad/i.test(navigator.userAgent);
const lim = isLow ? 40 : navigator.hardwareConcurrency <= 8 ? 80 : 140;
const cnt = Math.min(lim, Math.max(10, State.fxn));
particles = [];
for (let i = 0; i < cnt; i++) { const p = this.create(); if (p) particles.push(p); }
this.loop();
},
loop() {
if (!ctx || State.fx === 'none' || State.reducedMotion) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < particles.length; i++) { particles[i] = this.update(particles[i]); this.draw(particles[i]); }
animId = requestAnimationFrame(() => this.loop());
},
stop() { if (animId) cancelAnimationFrame(animId); animId = null; if (ctx) ctx.clearRect(0, 0, canvas.width, canvas.height); particles = []; }
};
/* ══════════ 🎨 GLASSMORPHISM CSS ══════════ */
function genCSS() {
const t = THEMES[State.theme] || THEMES.dark;
const f = (FONTS.find(x => x.id === State.font) || FONTS[0]).f;
const sz = State.size;
const al = State.blockAlpha / 100;
const pa = c => { const m = c.match(/([\d.]+)\)$/); return m ? c.replace(/[\d.]+\)$/, `${(parseFloat(m[1]) * al).toFixed(2)})`) : c; };
const pn = pa(t.panel), cd = pa(t.card), ip = pa(t.input);
return `
/* 🌐 Base */
:root { --a:${t.accent}; --t:${t.text}; --m:${t.muted}; --p:${t.panel}; --d:${t.card}; --b:${t.border}; --i:${t.input}; --h:${t.hover}; --s:${t.shadow}; --g:${t.glow}; }
html, body { background: transparent !important; }
body { color: ${t.text} !important; font-family: ${f} !important; font-size: ${sz}px !important; line-height: 1.55 !important; }
/* 🖼️ Background Layer */
#brbg { position: fixed !important; inset: 0 !important; z-index: -1000 !important; pointer-events: none !important; background-size: cover !important; background-position: center !important; background-repeat: no-repeat !important; transition: opacity 0.35s ease, filter 0.35s ease !important; }
/* 🎭 Canvas */
#brcv { position: fixed !important; inset: 0 !important; z-index: -999 !important; pointer-events: none !important; }
/* 🧱 Forum Containers — Full Transparency */
.p-body, .p-body-inner, .p-body-pageContent, .p-pageWrapper, .p-bodyWrap, .pageContent, #content, .p-body-content, .block-container, .block-body, .node-list, .structItem-container { background: transparent !important; background-image: none !important; box-shadow: none !important; }
/* 🗂️ Blocks / Nodes — Glassmorphism */
.block, .p-widget, .node, .node-list .node, .node-body, .node-container, .node-inner, .block-body, .block-minor, .block-footer { background: ${pn} !important; border: 1px solid ${t.border} !important; border-radius: 16px !important; box-shadow: ${t.shadow} !important; backdrop-filter: blur(16px) !important; -webkit-backdrop-filter: blur(16px) !important; background-image: none !important; margin-bottom: 10px !important; }
.block::before, .block::after, .node::before, .node::after, .message::before, .message::after { display: none !important; }
.block-container, .node-body, .message-cell, .message-user, .message-content { background: transparent !important; }
/* 💬 Posts */
.message, .message--post, .message--simple { background: ${pn} !important; border: 1px solid ${t.border} !important; border-radius: 16px !important; box-shadow: ${t.shadow} !important; backdrop-filter: blur(16px) !important; -webkit-backdrop-filter: blur(16px) !important; margin-bottom: 10px !important; }
/* 🗂️ Thread Rows */
.structItem, .structItem--thread, .structItem--post { background: transparent !important; border-bottom: 1px solid ${t.border} !important; padding: 10px 14px !important; transition: background 0.15s ease !important; }
.structItem:hover { background: ${t.hover} !important; border-radius: 10px !important; }
.structItem:last-child { border-bottom: none !important; }
.structItem-title a { color: ${t.text} !important; font-family: ${f} !important; font-weight: 600 !important; text-decoration: none !important; }
.structItem-title a:hover { color: ${t.accent} !important; }
.structItem-minor, .structItem-cell--meta { color: ${t.muted} !important; }
.structItem-parts .username, .structItem-parts a { color: ${t.accent} !important; font-weight: 600 !important; }
/* 🔗 Links */
a { color: ${t.accent} !important; transition: opacity 0.15s ease !important; text-decoration: none !important; }
a:hover { opacity: 0.85 !important; }
/* 🔘 Buttons — Modern */
.button--primary, .button--cta { background: ${t.accent} !important; color: #fff !important; border: none !important; border-radius: 12px !important; font-family: ${f} !important; font-weight: 700 !important; transition: opacity 0.15s, transform 0.1s, box-shadow 0.15s !important; box-shadow: ${t.glow} !important; }
.button--primary:hover { opacity: 0.92 !important; transform: translateY(-1px) !important; }
.button--primary:active { transform: scale(0.98) !important; }
.button, .button--secondary, .button--plain { background: ${cd} !important; color: ${t.text} !important; border: 1px solid ${t.border} !important; border-radius: 12px !important; font-family: ${f} !important; transition: background 0.15s !important; }
.button:hover { background: ${t.hover} !important; }
/* ✏️ Editor */
.fr-box, .fr-wrapper, .fr-element, .fr-toolbar { background: ${ip} !important; color: ${t.text} !important; border: 1px solid ${t.border} !important; border-radius: 12px !important; font-family: ${f} !important; }
.fr-toolbar { border-radius: 12px 12px 0 0 !important; background: ${cd} !important; }
.fr-element { border-radius: 0 0 12px 12px !important; min-height: 150px !important; }
/* 📝 Forms */
input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="number"], input[type="url"], textarea, select { background: ${ip} !important; color: ${t.text} !important; border: 1px solid ${t.border} !important; border-radius: 12px !important; font-family: ${f} !important; font-size: ${sz}px !important; outline: none !important; transition: border-color 0.15s, box-shadow 0.15s !important; }
input::placeholder, textarea::placeholder { color: ${t.muted} !important; opacity: 0.85; }
input:focus, textarea:focus { border-color: ${t.accent} !important; box-shadow: 0 0 0 3px ${cd} !important; }
/* 📄 Pagination */
.pageNav-page a, .pageNav-page span { background: ${cd} !important; color: ${t.text} !important; border: 1px solid ${t.border} !important; border-radius: 10px !important; transition: all 0.15s !important; }
.pageNav-page a:hover { background: ${t.hover} !important; }
.pageNav-page.is-active a { background: ${t.accent} !important; color: #fff !important; border-color: ${t.accent} !important; }
/* Menus — Glass */
.menu, .menu-content { background: ${pn} !important; border: 1px solid ${t.border} !important; border-radius: 16px !important; box-shadow: ${t.shadow} !important; backdrop-filter: blur(20px) !important; -webkit-backdrop-filter: blur(20px) !important; }
.menu-linkRow { color: ${t.text} !important; border-radius: 10px !important; transition: background 0.15s !important; }
.menu-linkRow:hover { background: ${t.hover} !important; color: ${t.accent} !important; }
.menu-separator { border-color: ${t.border} !important; }
/* 👤 Avatars */
.avatar img, .avatar-u img { border: 2.5px solid ${t.accent} !important; border-radius: 50% !important; box-shadow: 0 3px 12px ${t.shadow} !important; transition: transform 0.15s !important; }
.avatar img:hover { transform: scale(1.03) !important; }
.avatar--online::after { background: #22c55e !important; box-shadow: 0 0 0 2.5px ${pn} !important; }
/* 👤 Profile */
.memberHeader { background: ${pn} !important; border-bottom: 1px solid ${t.border} !important; }
.memberHeader-name .username { color: ${t.accent} !important; font-size: 22px !important; font-weight: 700 !important; }
/* 🏷️ Tags */
.tagItem, .tag, .label { background: ${cd} !important; color: ${t.accent} !important; border: 1px solid ${t.border} !important; border-radius: 22px !important; font-weight: 600 !important; padding: 3px 10px !important; }
/* 🔔 Notices */
.notice, .blockMessage { background: ${cd} !important; border: 1px solid ${t.border} !important; border-radius: 14px !important; color: ${t.text} !important; }
/* 🧭 Breadcrumbs */
.p-breadcrumbs a { color: ${t.muted} !important; transition: color 0.15s !important; }
.p-breadcrumbs a:hover { color: ${t.accent} !important; }
/* 🔤 Small Text */
.u-muted, small, .pairs-key, .message-attribution time { color: ${t.muted} !important; }
hr { border-color: ${t.border} !important; }
/* 📜 Scrollbar — Modern */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: ${t.accent}; border-radius: 4px; opacity: 0.7; transition: opacity 0.15s; }
::-webkit-scrollbar-thumb:hover { opacity: 1; }
/* 🎭 Animations — Respect reduced-motion */
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } #brcv { display: none !important; } }
/* ♿ Accessibility */
*:focus-visible { outline: 2px solid ${t.accent} !important; outline-offset: 2px !important; }
`;
}
const PANEL_CSS = `
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Rajdhani:wght@400;600;700&family=Exo+2:wght@400;600;700&family=Montserrat:wght@400;600;700&family=Roboto:wght@400;500;700&display=swap');
/* ✨ FAB Button — Modern Pulse */
#brfab {
position: fixed; bottom: 22px; right: 22px; z-index: 9990;
width: 56px; height: 56px; border-radius: 50%;
border: none; color: #fff; font-size: 24px; cursor: pointer;
display: flex; align-items: center; justify-content: center;
background: var(--a); box-shadow: var(--g), 0 4px 20px rgba(0,0,0,0.4);
transition: transform 0.18s ease, box-shadow 0.18s ease;
-webkit-tap-highlight-color: transparent; will-change: transform;
}
#brfab:hover { transform: scale(1.08); box-shadow: var(--g), 0 6px 28px rgba(0,0,0,0.5); }
#brfab:active { transform: scale(0.94); }
#brfab::after { content: ''; position: absolute; inset: -3px; border-radius: 50%; border: 2px solid var(--a); opacity: 0; animation: pulse 2s infinite; }
@keyframes pulse { 0% { opacity: 0.6; transform: scale(0.9); } 50% { opacity: 0; transform: scale(1.3); } 100% { opacity: 0; transform: scale(0.9); } }
/* 🌫️ Overlay */
#brov { position: fixed; inset: 0; z-index: 9991; background: rgba(0,0,0,0.52); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); opacity: 0; pointer-events: none; transition: opacity 0.22s ease; }
#brov.on { opacity: 1; pointer-events: all; }
/* 🪟 Panel — Bottom Sheet Glass */
#brpnl {
position: fixed; left: 0; right: 0; bottom: 0; z-index: 9992;
height: 86vh; max-height: 680px; border-radius: 26px 26px 0 0;
background: var(--p); border: 1px solid var(--b);
display: flex; flex-direction: column; color: var(--t); overflow: hidden;
transform: translateY(100%); transition: transform 0.3s cubic-bezier(0.32,0.72,0,1);
box-shadow: 0 -4px 40px rgba(0,0,0,0.45); will-change: transform;
}
#brpnl.on { transform: translateY(0); }
/* 🎯 Handle */
#brhnd { width: 46px; height: 5px; border-radius: 4px; background: var(--b); margin: 16px auto 0; flex-shrink: 0; cursor: grab; touch-action: pan-y; transition: background 0.15s; }
#brhnd:hover { background: var(--a); }
#brhnd:active { cursor: grabbing; }
/* 📌 Header */
#brhdr { display: flex; align-items: center; justify-content: space-between; padding: 14px 22px 0; flex-shrink: 0; }
#brlgo { font-size: 18px; font-weight: 800; color: var(--a); letter-spacing: -0.3px; }
#brver { font-size: 11px; color: var(--m); margin-left: 5px; font-weight: 600; }
#brx { background: none; border: 1.5px solid var(--b); color: var(--t); border-radius: 50%; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center; font-size: 15px; cursor: pointer; flex-shrink: 0; transition: all 0.15s; -webkit-tap-highlight-color: transparent; }
#brx:hover { background: var(--d); border-color: var(--a); color: var(--a); transform: rotate(90deg); }
/* ️ Tabs */
#brtbs { display: flex; gap: 7px; padding: 14px 18px 0; overflow-x: auto; flex-shrink: 0; scrollbar-width: none; }
#brtbs::-webkit-scrollbar { display: none; }
.bt { flex: 0 0 auto; padding: 8px 16px; border: 1.5px solid var(--b); border-radius: 24px; background: var(--d); color: var(--m); font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; transition: all 0.16s ease; font-family: inherit; -webkit-tap-highlight-color: transparent; display: flex; align-items: center; gap: 6px; }
.bt .ic { font-size: 16px; }
.bt:hover { background: var(--b); color: var(--t); }
.bt.on { background: var(--a); color: #fff; border-color: var(--a); box-shadow: var(--g); }
/* 📜 Body */
#brbdy { flex: 1; overflow-y: auto; padding: 16px 20px 32px; overscroll-behavior: contain; scroll-behavior: smooth; }
#brbdy::-webkit-scrollbar { width: 4px; }
#brbdy::-webkit-scrollbar-thumb { background: var(--a); border-radius: 4px; }
/* Section */
.sc { font-size: 11px; font-weight: 800; color: var(--m); text-transform: uppercase; letter-spacing: 2.8px; margin: 20px 0 12px; padding-bottom: 7px; border-bottom: 1px solid var(--b); display: flex; align-items: center; gap: 7px; }
.sc:first-child { margin-top: 0; }
.sc::before { content: ''; width: 3px; height: 14px; background: var(--a); border-radius: 2px; }
/* 🔤 Input */
.inp { width: 100%; box-sizing: border-box; padding: 13px 17px; border-radius: 14px; border: 1.5px solid var(--b); background: var(--i); color: var(--t); font-size: 14px; outline: none; font-family: inherit; -webkit-appearance: none; transition: border-color 0.16s, box-shadow 0.16s; }
.inp::placeholder { color: var(--m); opacity: 0.8; }
.inp:focus { border-color: var(--a); box-shadow: 0 0 0 3px var(--d); }
/* 🔘 Buttons */
.rw { display: flex; align-items: center; gap: 11px; margin-bottom: 9px; }
.bsm { padding: 11px 18px; border: 1.5px solid var(--b); border-radius: 12px; background: var(--d); color: var(--t); cursor: pointer; font-size: 13px; font-family: inherit; font-weight: 650; transition: all 0.15s; -webkit-tap-highlight-color: transparent; display: flex; align-items: center; gap: 6px; }
.bsm.ac { background: var(--a); color: #fff; border-color: var(--a); box-shadow: var(--g); }
.bsm:hover { transform: translateY(-1px); }
.bsm:active { transform: scale(0.98); opacity: 0.95; }
.bwd { width: 100%; padding: 15px; border: 1.5px solid var(--b); border-radius: 14px; background: var(--d); color: var(--t); cursor: pointer; font-size: 14px; font-family: inherit; text-align: center; margin-top: 9px; font-weight: 650; transition: all 0.15s; -webkit-tap-highlight-color: transparent; }
.bwd:hover { background: var(--b); }
.bwd:active { transform: scale(0.99); }
/* 🎚️ Slider */
.sl { flex: 1; -webkit-appearance: none; appearance: none; height: 5px; border-radius: 4px; background: var(--b); outline: none; cursor: pointer; transition: background 0.15s; }
.sl:hover { background: var(--a); }
.sl::-webkit-slider-thumb { -webkit-appearance: none; width: 21px; height: 21px; border-radius: 50%; background: var(--a); cursor: pointer; box-shadow: 0 2px 10px rgba(0,0,0,0.35); transition: transform 0.12s; border: 2px solid #fff; }
.sl::-webkit-slider-thumb:hover { transform: scale(1.12); }
.sv { font-size: 13px; font-weight: 700; color: var(--a); min-width: 42px; text-align: right; }
.lb { font-size: 12px; color: var(--m); font-weight: 600; }
/* 🗂️ Categories */
#brcts { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 7px; scrollbar-width: none; margin-bottom: 13px; }
#brcts::-webkit-scrollbar { display: none; }
.ct { flex: 0 0 auto; padding: 8px 15px; border: 1.5px solid var(--b); border-radius: 24px; background: var(--d); color: var(--m); font-size: 12px; cursor: pointer; white-space: nowrap; font-family: inherit; transition: all 0.16s ease; -webkit-tap-highlight-color: transparent; font-weight: 600; }
.ct:hover { background: var(--b); color: var(--t); }
.ct.on { background: var(--a); color: #fff; border-color: var(--a); box-shadow: var(--g); }
/* 🖼️ Gallery */
#brgal { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
.wpt { height: 86px; border-radius: 14px; background-size: cover; background-position: center; cursor: pointer; border: 2.5px solid transparent; transition: all 0.16s ease; -webkit-tap-highlight-color: transparent; position: relative; overflow: hidden; }
.wpt::before { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgba(0,0,0,0.35), transparent 60%); opacity: 0; transition: opacity 0.16s; }
.wpt:hover::before { opacity: 1; }
.wpt:hover { transform: translateY(-2px); }
.wpt:active { transform: scale(0.96); }
.wpt.on { border-color: var(--a); box-shadow: 0 0 0 2px var(--a), var(--g); }
.wpt.on::after { content: '✓'; position: absolute; top: 6px; right: 8px; color: #fff; font-size: 14px; font-weight: 800; text-shadow: 0 1px 5px rgba(0,0,0,0.85); background: var(--a); border-radius: 50%; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 8px rgba(0,0,0,0.3); }
/* 🔲 Grids */
.g2 { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.g3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
/* ⚙️ Options */
.op { padding: 13px 9px; border: 1.5px solid var(--b); border-radius: 14px; background: var(--d); color: var(--t); cursor: pointer; font-size: 12px; text-align: center; font-family: inherit; transition: all 0.16s ease; -webkit-tap-highlight-color: transparent; font-weight: 600; }
.op:hover { background: var(--b); transform: translateY(-1px); }
.op.on { background: var(--a); color: #fff; border-color: var(--a); box-shadow: var(--g); }
/* Themes */
.thc { padding: 15px 9px; border-radius: 14px; border: 2.5px solid transparent; cursor: pointer; text-align: center; font-size: 12px; font-weight: 700; transition: all 0.19s ease; font-family: inherit; -webkit-tap-highlight-color: transparent; }
.thc:hover { transform: translateY(-2px); box-shadow: 0 5px 20px rgba(0,0,0,0.35); }
.thc.on { box-shadow: 0 0 0 2.5px var(--a), 0 7px 25px rgba(0,0,0,0.5); }
/* 🗺️ Servers */
#brsrv { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; margin-top: 13px; }
.sa { display: flex; flex-direction: column; align-items: center; padding: 13px 7px; background: var(--d); border: 1.5px solid var(--b); border-radius: 14px; text-decoration: none; color: inherit; transition: all 0.16s ease; -webkit-tap-highlight-color: transparent; }
.sa:hover { background: var(--b); transform: translateY(-1px); }
.sa:active { transform: scale(0.96); }
.sn { font-size: 20px; font-weight: 800; color: var(--a); line-height: 1; }
.sl2 { font-size: 10px; color: var(--m); margin-top: 3px; font-weight: 700; letter-spacing: 0.6px; }
/* 🔀 Toggle Switch */
.swr { display: flex; align-items: center; justify-content: space-between; padding: 14px 0; border-bottom: 1px solid var(--b); }
.swr:last-child { border-bottom: none; }
.swl { font-size: 14px; color: var(--t); font-weight: 600; }
.swd { font-size: 11px; color: var(--m); margin-top: 2px; }
.sw { position: relative; width: 48px; height: 28px; flex-shrink: 0; }
.sw input { opacity: 0; width: 0; height: 0; position: absolute; }
.swb { position: absolute; inset: 0; border-radius: 14px; background: var(--b); cursor: pointer; transition: background 0.22s; }
.sw input:checked + .swb { background: var(--a); }
.swb::after { content: ''; position: absolute; width: 22px; height: 22px; left: 3px; top: 3px; border-radius: 50%; background: #fff; transition: transform 0.22s ease; box-shadow: 0 2px 7px rgba(0,0,0,0.35); }
.sw input:checked + .swb::after { transform: translateX(20px); }
/* ℹ️ Info */
.info { padding: 13px 17px; border-radius: 14px; background: var(--d); border: 1.5px solid var(--b); font-size: 12px; color: var(--m); line-height: 1.75; margin-top: 11px; }
.info b { color: var(--a); font-weight: 700; }
/* ⏰ Clock */
#brclk { position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 9985; pointer-events: none; font-size: 13px; font-weight: 700; letter-spacing: 2.2px; padding: 5px 18px; border-radius: 24px; backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); border: 1.5px solid var(--b); white-space: nowrap; background: var(--p); color: var(--a); box-shadow: var(--g); transition: opacity 0.2s; }
/* 📊 Progress */
#brprg { position: fixed; top: 0; left: 0; z-index: 9999; height: 3px; width: 0; border-radius: 0 3px 3px 0; pointer-events: none; transition: width 0.07s linear; background: var(--a); box-shadow: 0 0 12px var(--a); }
/* 🔔 Toast */
#brtst { position: fixed; bottom: 90px; left: 50%; transform: translateX(-50%); z-index: 9998; pointer-events: none; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.ts { padding: 10px 22px; border-radius: 24px; font-size: 13px; font-weight: 700; backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1.5px solid var(--b); white-space: nowrap; background: var(--p); color: var(--t); animation: tsi 0.16s ease, tso 0.2s ease 2.2s forwards; font-family: inherit; box-shadow: var(--g); }
@keyframes tsi { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@keyframes tso { to { opacity: 0; transform: translateY(-6px); } }
`;
/* ══════════ 🧩 DOM & UTILS ══════════ */
const getT = () => THEMES[State.theme] || THEMES.dark;
const getF = () => (FONTS.find(x => x.id === State.font) || FONTS[0]).f;
const applyVars = el => { if (!el) return; const t = getT(); el.style.setProperty('--a', t.accent); el.style.setProperty('--t', t.text); el.style.setProperty('--m', t.muted); el.style.setProperty('--p', t.panel); el.style.setProperty('--d', t.card); el.style.setProperty('--b', t.border); el.style.setProperty('--i', t.input); el.style.setProperty('--h', t.hover); el.style.setProperty('--s', t.shadow); el.style.setProperty('--g', t.glow); el.style.fontFamily = getF(); };
const debounce = (fn, ms) => { let t; return (...a) => { clearTimeout(t); t = setTimeout(() => fn.apply(this, a), ms); }; };
/* ══════════ 🎨 APPLY ══════════ */
function applyForum() { if ($.forumStyle) $.forumStyle.textContent = genCSS(); }
function applyWP() { if (!$.bg) return; if (State.wp) { $.bg.style.backgroundImage = `url('${State.wp}')`; $.bg.style.opacity = State.wpa / 100; $.bg.style.filter = State.wpb > 0 ? `blur(${State.wpb}px)` : 'none'; } else { $.bg.style.backgroundImage = ''; $.bg.style.opacity = '1'; $.bg.style.filter = 'none'; } }
function applyAll() { applyForum(); applyWP(); FX.start(); applyVars($.panel); const t = getT(); if ($.fab) $.fab.style.background = t.accent; if ($.clock) { $.clock.style.color = t.accent; $.clock.style.borderColor = t.border; $.clock.style.background = t.panel; $.clock.style.fontFamily = getF(); } if ($.prog) $.prog.style.background = t.accent; updateWidgets(); }
function updateWidgets() { if ($.clock) $.clock.style.display = State.clock ? '' : 'none'; if ($.prog) $.prog.style.display = State.prog ? '' : 'none'; applyForum(); }
function toast(msg) { if (!$.toast) return; const el = document.createElement('div'); el.className = 'ts'; el.textContent = msg; $.toast.appendChild(el); setTimeout(() => { el.style.opacity = '0'; setTimeout(() => el.remove(), 200); }, 2200); }
/* ══════════ 🔄 PANEL ══════════ */
function openPanel() { renderPanel(); $.overlay?.classList.add('on'); $.panel?.classList.add('on'); document.body.style.overflow = 'hidden'; }
function closePanel() { $.overlay?.classList.remove('on'); $.panel?.classList.remove('on'); document.body.style.overflow = ''; }
function initSwipe() {
const h = $.panel?.querySelector('#brhnd'); if (!h) return;
let sy = 0, dy = 0, drag = false;
const onS = e => { sy = e.type === 'touchstart' ? e.touches[0].clientY : e.clientY; drag = true; h.style.transition = 'none'; };
const onM = e => { if (!drag) return; dy = (e.type === 'touchmove' ? e.touches[0].clientY : e.clientY) - sy; if (dy > 0) $.panel.style.transform = `translateY(${Math.min(dy, 100)}px)`; };
const onE = () => { if (!drag) return; drag = false; h.style.transition = ''; $.panel.style.transition = 'transform 0.3s cubic-bezier(0.32,0.72,0,1)'; if (dy > 85) closePanel(); else $.panel.style.transform = ''; dy = 0; };
h.addEventListener('touchstart', onS, { passive: true }); h.addEventListener('mousedown', onS);
window.addEventListener('touchmove', onM, { passive: true }); window.addEventListener('mousemove', onM);
window.addEventListener('touchend', onE); window.addEventListener('mouseup', onE);
}
/* ══════════ 🎨 RENDER PANEL ══════════ */
const TABS = [{ id:'wp', ic:'🖼️', l:'Обои' }, { id:'srv', ic:'🗺️', l:'Серверы' }, { id:'fx', ic:'✨', l:'Эффекты' }, { id:'th', ic:'🎨', l:'Тема' }, { id:'fn', ic:'✍️', l:'Шрифт' }, { id:'opt', ic:'⚙️', l:'Прочее' }];
function renderPanel() {
applyVars($.panel); if (!$.panel) return;
$.panel.innerHTML = `
<div id="brhnd"></div>
<div id="brhdr"><div style="display:flex;align-items:baseline"><span id="brlgo">🎨 BR Pro</span><span id="brver">v${CONFIG.VERSION}</span></div><button id="brx" title="Закрыть">✕</button></div>
<div id="brtbs">${TABS.map(t => `<button class="bt${State.tab === t.id ? ' on' : ''}" data-t="${t.id}"><span class="ic">${t.ic}</span>${t.l}</button>`).join('')}</div>
<div id="brbdy">${getTab()}</div>`;
bindEvents(); initSwipe();
}
function getTab() {
if (State.tab === 'wp') return `
<div class="sc"> Своя ссылка</div><div class="rw"><input class="inp" id="wurl" type="url" placeholder="https://... картинка или GIF" value="${State.wp || ''}"></div>
<div class="rw"><button class="bsm ac" id="wset">✓ Применить</button><button class="bsm" id="wclr">✕ Убрать</button></div>
<div class="sc">🔆 Яркость</div><div class="rw"><span class="lb">🌑</span><input type="range" class="sl" id="wpa" min="20" max="100" value="${State.wpa}"><span class="lb">☀️</span><span class="sv" id="wpav">${State.wpa}%</span></div>
<div class="sc">🌫️ Размытие</div><div class="rw"><input type="range" class="sl" id="wpb" min="0" max="25" value="${State.wpb}"><span class="sv" id="wpbv">${State.wpb}px</span></div>
<div class="sc">🖼️ Галерея</div><div id="brcts">${Object.keys(GALLERY).map(c => `<button class="ct${State.wpcat === c ? ' on' : ''}" data-c="${c}">${c}</button>`).join('')}</div><div id="brgal">${galHTML(State.wpcat)}</div>`;
if (State.tab === 'srv') return `<div class="sc">🔍 Поиск</div><input class="inp" id="srch" type="text" inputmode="numeric" placeholder="Номер сервера 1–91..." autocomplete="off"><div id="brsrv">${SERVERS.map(s => `<a class="sa" href="${s.url}" target="_blank" rel="noopener"><span class="sn">${s.n}</span><span class="sl2">ПРАВИЛА</span></a>`).join('')}</div>`;
if (State.tab === 'fx') { const fx = [{id:'none',l:'❌ Выкл'},{id:'sakura',l:'🌸 Сакура'},{id:'snow',l:'❄️ Снег'},{id:'rain',l:'🌧️ Дождь'},{id:'stars',l:'⭐ Звёзды'},{id:'firefly',l:' Светлячки'},{id:'bubbles',l:'🫧 Пузыри'}]; return `<div class="sc">✨ Эффект</div><div class="g3">${fx.map(f => `<button class="op${State.fx === f.id ? ' on' : ''}" data-fx="${f.id}">${f.l}</button>`).join('')}</div><div class="sc">🔢 Количество</div><div class="rw"><span class="lb">Мин</span><input type="range" class="sl" id="fxn" min="10" max="180" step="5" value="${State.fxn}"><span class="lb">Макс</span><span class="sv" id="fxnv">${State.fxn}</span></div><div class="info">💡 На слабых устройствах количество снижается автоматически</div>`; }
if (State.tab === 'th') return `<div class="sc"> Тема</div><div class="g2">${Object.entries(THEMES).map(([id,t]) => `<button class="thc${State.theme === id ? ' on' : ''}" style="background:${t.bg};color:${t.text};" data-th="${id}">${t.name}</button>`).join('')}</div>`;
if (State.tab === 'fn') return `<div class="sc">🔤 Шрифт</div><div class="g2">${FONTS.map(f => `<button class="op${State.font === f.id ? ' on' : ''}" style="font-family:${f.f};" data-fn="${f.id}">${f.id}</button>`).join('')}</div><div class="sc">📏 Размер</div><div class="rw"><span class="lb" style="font-size:12px;font-weight:700">A</span><input type="range" class="sl" id="fsz" min="12" max="20" step="1" value="${State.size}"><span class="lb" style="font-size:19px;font-weight:700">A</span><span class="sv" id="fszv">${State.size}px</span></div>`;
if (State.tab === 'opt') return `<div class="sc">🧩 Виджеты</div>${sw('clock','⏰ Часы','Время вверху')} ${sw('prog','📊 Прогресс','Полоса прокрутки')} ${sw('reducedMotion','🚫 Анимации','Отключить эффекты')}
<div class="sc">🔲 Прозрачность блоков</div><div class="rw"><span class="lb">Мягко</span><input type="range" class="sl" id="blkA" min="40" max="100" value="${State.blockAlpha}"><span class="lb">Плотно</span><span class="sv" id="blkAV">${State.blockAlpha}%</span></div>
<div class="sc">️ Сброс</div><button class="bwd" id="rst">🔄 Сбросить настройки</button><div class="info">🎨 BR Pro Ultimate <b>v${CONFIG.VERSION}</b><br>Автор: Akzholch1k | Modern UI by AI</div>`;
return '';
}
function galHTML(cat) { return (GALLERY[cat] || []).map(u => `<div class="wpt${State.wp === u ? ' on' : ''}" data-u="${u}" style="background-image:url('${u}')"></div>`).join(''); }
function sw(k, l, d) { return `<div class="swr"><div><div class="swl">${l}</div><div class="swd">${d}</div></div><label class="sw"><input type="checkbox" data-sw="${k}" ${State[k] ? 'checked' : ''}><span class="swb"></span></label></div>`; }
/* ══════════ 🔗 EVENTS — FIXED BUTTON ══════════ */
function bindEvents() {
// ✅ КНОПКА ЗАКРЫТИЯ
const closeBtn = $.panel?.querySelector('#brx');
if (closeBtn) closeBtn.onclick = closePanel;
// ✅ ТАБЫ
$.panel?.querySelectorAll('.bt').forEach(btn => {
btn.onclick = () => { State.tab = btn.dataset.t; save(); renderPanel(); };
});
// ✅ ОБОИ
const wurl = $.panel?.querySelector('#wurl');
$.panel?.querySelector('#wset')?.addEventListener('click', () => {
const v = (wurl?.value || '').trim();
if (!v) { toast('⚠️ Введите ссылку!'); return; }
State.wp = v; save(); applyWP(); toast('✅ Обои применены!');
$.panel?.querySelectorAll('.wpt').forEach(el => el.classList.toggle('on', el.dataset.u === v));
});
$.panel?.querySelector('#wclr')?.addEventListener('click', () => { State.wp = ''; save(); applyWP(); toast('🗑️ Убрано'); renderPanel(); });
const wpa = $.panel?.querySelector('#wpa');
if (wpa) wpa.oninput = () => { State.wpa = +wpa.value; const el = $.panel?.querySelector('#wpav'); if (el) el.textContent = State.wpa + '%'; save(); applyWP(); };
const wpb = $.panel?.querySelector('#wpb');
if (wpb) wpb.oninput = () => { State.wpb = +wpb.value; const el = $.panel?.querySelector('#wpbv'); if (el) el.textContent = State.wpb + 'px'; save(); applyWP(); };
$.panel?.querySelectorAll('.ct').forEach(btn => {
btn.onclick = () => { State.wpcat = btn.dataset.c; save(); $.panel?.querySelectorAll('.ct').forEach(b => b.classList.remove('on')); btn.classList.add('on'); const gal = $.panel?.querySelector('#brgal'); if (gal) gal.innerHTML = galHTML(State.wpcat); bindThumbs(); };
});
bindThumbs();
// ✅ СЕРВЕРЫ — ПОИСК
const srch = $.panel?.querySelector('#srch');
if (srch) srch.oninput = debounce(() => { const q = srch.value.trim(); $.panel?.querySelectorAll('.sa').forEach(el => { const n = el.querySelector('.sn')?.textContent; el.style.display = (!q || n?.includes(q)) ? '' : 'none'; }); }, CONFIG.DEFAULTS.input);
// ✅ ЭФФЕКТЫ
$.panel?.querySelectorAll('[data-fx]').forEach(btn => { btn.onclick = () => { State.fx = btn.dataset.fx; save(); FX.start(); toast(`✨ ${btn.textContent.trim()}`); renderPanel(); }; });
const fxn = $.panel?.querySelector('#fxn');
if (fxn) fxn.oninput = () => { State.fxn = +fxn.value; const el = $.panel?.querySelector('#fxnv'); if (el) el.textContent = State.fxn; save(); FX.start(); };
// ✅ ТЕМЫ
$.panel?.querySelectorAll('[data-th]').forEach(btn => { btn.onclick = () => { State.theme = btn.dataset.th; save(); applyAll(); toast(`🎨 ${THEMES[State.theme].name}`); renderPanel(); }; });
// ✅ ШРИФТЫ
$.panel?.querySelectorAll('[data-fn]').forEach(btn => { btn.onclick = () => { State.font = btn.dataset.fn; save(); applyAll(); renderPanel(); }; });
const fsz = $.panel?.querySelector('#fsz');
if (fsz) fsz.oninput = () => { State.size = +fsz.value; const el = $.panel?.querySelector('#fszv'); if (el) el.textContent = State.size + 'px'; save(); applyForum(); };
// ✅ ПЕРЕКЛЮЧАТЕЛИ
$.panel?.querySelectorAll('[data-sw]').forEach(tg => { tg.onchange = () => { State[tg.dataset.sw] = tg.checked; save(); updateWidgets(); if (tg.dataset.sw === 'reducedMotion') FX.start(); }; });
// ✅ ПРОЗРАЧНОСТЬ БЛОКОВ
const blkA = $.panel?.querySelector('#blkA');
if (blkA) blkA.oninput = () => { State.blockAlpha = +blkA.value; const el = $.panel?.querySelector('#blkAV'); if (el) el.textContent = State.blockAlpha + '%'; save(); applyForum(); };
// ✅ СБРОС
$.panel?.querySelector('#rst')?.addEventListener('click', () => { if (confirm('Сбросить ВСЕ настройки?')) { Object.assign(State, CONFIG.DEFAULTS); save(); applyAll(); toast('✅ Сброшено'); renderPanel(); } });
}
function bindThumbs() { $.panel?.querySelectorAll('.wpt').forEach(el => { el.onclick = () => { State.wp = el.dataset.u; save(); applyWP(); $.panel?.querySelectorAll('.wpt').forEach(e => e.classList.toggle('on', e.dataset.u === State.wp)); toast('🖼️ Выбрано!'); }; }); }
/* ══════════ 📜 SCROLL & CLOCK ══════════ */
function onScroll() { if ($.prog && State.prog) { const sc = window.scrollY, tot = document.documentElement.scrollHeight - window.innerHeight; $.prog.style.width = tot > 0 ? ((sc / tot) * 100) + '%' : '0%'; } }
let clockT = null;
function startClock() { if (clockT) clearInterval(clockT); const tick = () => { if (!$.clock) return; const n = new Date(), p = x => String(x).padStart(2, '0'); $.clock.textContent = `${p(n.getHours())}:${p(n.getMinutes())}:${p(n.getSeconds())}`; }; tick(); clockT = setInterval(tick, 1000); }
/* ══════════ 🚀 INIT — BUTTON FIXED ══════════ */
function init() {
// 🔹 Fonts
const lk = document.createElement('link'); lk.rel = 'stylesheet'; lk.href = 'https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Rajdhani:wght@400;600;700&family=Exo+2:wght@400;600;700&family=Montserrat:wght@400;600;700&family=Roboto:wght@400;500;700&display=swap'; document.head.appendChild(lk);
// 🔹 Styles
$.forumStyle = document.createElement('style'); $.forumStyle.id = 'brsf'; document.head.appendChild($.forumStyle);
const pStyle = document.createElement('style'); pStyle.id = 'brsp'; pStyle.textContent = PANEL_CSS; document.head.appendChild(pStyle);
// 🔹 Background (z-index: -1000 — BELOW everything)
$.bg = document.createElement('div'); $.bg.id = 'brbg'; $.bg.style.cssText = 'position:fixed;inset:0;z-index:-1000;pointer-events:none;background-size:cover;background-position:center;background-repeat:no-repeat;transition:opacity 0.35s ease,filter 0.35s ease;'; document.body.prepend($.bg);
// 🔹 Canvas (z-index: -999 — above bg, below content)
canvas = document.createElement('canvas'); canvas.id = 'brcv'; canvas.style.cssText = 'position:fixed;inset:0;z-index:-999;pointer-events:none;'; document.body.appendChild(canvas); ctx = canvas.getContext('2d'); FX.init();
// Progress
$.prog = document.createElement('div'); $.prog.id = 'brprg'; document.body.appendChild($.prog);
// 🔹 Clock
$.clock = document.createElement('div'); $.clock.id = 'brclk'; document.body.appendChild($.clock); startClock();
// 🔹 Toast
$.toast = document.createElement('div'); $.toast.id = 'brtst'; document.body.appendChild($.toast);
// Overlay
$.overlay = document.createElement('div'); $.overlay.id = 'brov'; $.overlay.onclick = closePanel; document.body.appendChild($.overlay);
// 🔹 Panel
$.panel = document.createElement('div'); $.panel.id = 'brpnl'; document.body.appendChild($.panel);
// 🔹 ✅ FAB BUTTON — FIXED & WORKING
$.fab = document.createElement('button'); $.fab.id = 'brfab'; $.fab.innerHTML = '⚙️'; $.fab.title = 'BR Pro Ultimate — Настройки'; $.fab.style.cssText = 'position:fixed;bottom:22px;right:22px;z-index:9990;width:56px;height:56px;border-radius:50%;border:none;color:#fff;font-size:24px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform 0.18s;';
document.body.appendChild($.fab);
// ✅ ПРЯМОЕ НАЗНАЧЕНИЕ ОБРАБОТЧИКА — ГАРАНТИРОВАННО РАБОТАЕТ
$.fab.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); openPanel(); }, { passive: true });
// ✅ ДУБЛИРУЕМ ДЛЯ НАДЁЖНОСТИ
$.fab.onclick = (e) => { e?.preventDefault(); openPanel(); };
// 🔹 Events
window.addEventListener('scroll', debounce(onScroll, CONFIG.DEFAULTS.scroll), { passive: true });
window.addEventListener('resize', debounce(() => { FX.init(); FX.start(); }, CONFIG.DEFAULTS.resize), { passive: true });
// 🔹 Apply
applyAll();
// 🔹 Welcome
if (!localStorage.getItem(`${CONFIG.KEY}_hi`)) { setTimeout(() => toast(`🎨 BR Pro v${CONFIG.VERSION} • Кнопка ️ работает!`), 800); localStorage.setItem(`${CONFIG.KEY}_hi`, '1'); }
// 🔹 Auto-theme on first run
if (!localStorage.getItem(CONFIG.KEY)) { const isLight = document.body.classList.contains('theme-light') || getComputedStyle(document.body).backgroundColor === 'rgb(255, 255, 255)'; State.theme = isLight && THEMES.light ? 'light' : 'dark'; save(); applyAll(); }
}
// 🔹 Launch
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
else init();
})();