Полный редизайн Black Russia Forum — обои, темы, эффекты, 91 сервер, навбар
// ==UserScript==
// @name 🎨 BR Pro Ultimate
// @namespace http://tampermonkey.net/
// @version 5.1.0
// @description Полный редизайн Black Russia Forum — обои, темы, эффекты, 91 сервер, навбар
// @author Akzholch1k
// @match https://forum.blackrussia.online/*
// @grant none
// @license MIT
// @run-at document-start
// ==/UserScript==
(function () {
'use strict';
/* ══════════ ХРАНИЛИЩЕ ══════════ */
const KEY = 'br5';
const DEF = {
theme: 'dark', font: 'Rajdhani', size: 15,
wp: '', wpa: 80, wpb: 0, wpcat: '📱 GIF Телефон',
fx: 'none', fxn: 65, tab: 'wp',
clock: true, prog: true, bnav: true, navstyle: 'glass',
};
let S = {};
const ld = () => { try { S = { ...DEF, ...JSON.parse(localStorage.getItem(KEY) || '{}') }; } catch (_) { S = { ...DEF }; } };
const sv = () => { try { localStorage.setItem(KEY, JSON.stringify(S)); } catch (_) {} };
ld();
/* ══════════ ТЕМЫ ══════════ */
const TH = {
dark: { n:'🌑 Тёмная', bg:'#0a0a1c', gr:'135deg,#0a0a1c,#111128,#0a0a1c', ac:'#7c4dff', tx:'#dde0ff', mu:'#5a5a90', pn:'rgba(8,8,20,.96)', cd:'rgba(124,77,255,.10)', bd:'rgba(124,77,255,.22)', ip:'rgba(255,255,255,.07)', hv:'rgba(124,77,255,.16)' },
light: { n:'☀️ Светлая', bg:'#eef1ff', gr:'135deg,#eef1ff,#f2eaff,#e8eeff', ac:'#5530cc', tx:'#1a1040', mu:'#6060a0', pn:'rgba(240,238,255,.97)', cd:'rgba(85,48,204,.07)', bd:'rgba(85,48,204,.18)', ip:'rgba(0,0,0,.06)', hv:'rgba(85,48,204,.13)' },
sakura: { n:'🌸 Сакура', bg:'#160412', gr:'135deg,#160412,#280c1c,#160412', ac:'#ff4d8d', tx:'#ffd4e6', mu:'#a06080', pn:'rgba(13,3,11,.96)', cd:'rgba(255,77,141,.10)', bd:'rgba(255,77,141,.22)', ip:'rgba(255,77,141,.07)', hv:'rgba(255,77,141,.16)' },
neon: { n:'⚡ Неон', bg:'#00030f', gr:'135deg,#00030f,#01031a,#00030f', ac:'#00ffcc', tx:'#00ffcc', mu:'#008866', pn:'rgba(0,2,13,.96)', cd:'rgba(0,255,200,.07)', bd:'rgba(0,255,200,.20)', ip:'rgba(0,255,200,.06)', hv:'rgba(0,255,200,.13)' },
nature: { n:'🌿 Природа', bg:'#050f05', gr:'135deg,#050f05,#0b1c0b,#050f05', ac:'#3dbe3d', tx:'#b8f0b8', mu:'#50a050', pn:'rgba(3,10,3,.96)', cd:'rgba(61,190,61,.08)', bd:'rgba(61,190,61,.20)', ip:'rgba(61,190,61,.07)', hv:'rgba(61,190,61,.14)' },
sunset: { n:'🌅 Закат', bg:'#180707', gr:'135deg,#180707,#2a0f0f,#180707', ac:'#ff7c42', tx:'#ffe0cc', mu:'#c07060', pn:'rgba(17,5,4,.96)', cd:'rgba(255,124,66,.10)', bd:'rgba(255,124,66,.22)', ip:'rgba(255,124,66,.07)', hv:'rgba(255,124,66,.16)' },
ocean: { n:'🌊 Океан', bg:'#020c18', gr:'135deg,#020c18,#04182e,#020c18', ac:'#00aaff', tx:'#c8e8ff', mu:'#3870a0', pn:'rgba(1,8,18,.96)', cd:'rgba(0,170,255,.08)', bd:'rgba(0,170,255,.20)', ip:'rgba(0,170,255,.06)', hv:'rgba(0,170,255,.13)' },
rose: { n:'🥀 Роза', bg:'#140a0a', gr:'135deg,#140a0a,#240f0f,#140a0a', ac:'#e0305a', tx:'#ffc8d0', mu:'#906070', pn:'rgba(13,6,6,.96)', cd:'rgba(224,48,90,.10)', bd:'rgba(224,48,90,.22)', ip:'rgba(224,48,90,.07)', hv:'rgba(224,48,90,.16)' },
};
/* ══════════ ШРИФТЫ ══════════ */
const FN = [
{ id:'Rajdhani', f:'"Rajdhani",sans-serif' },
{ id:'Orbitron', f:'"Orbitron",sans-serif' },
{ id:'Exo 2', f:'"Exo 2",sans-serif' },
{ id:'Montserrat', f:'"Montserrat",sans-serif' },
{ id:'Roboto', f:'"Roboto",sans-serif' },
{ id:'Системный', f:'system-ui,sans-serif' },
];
/* ══════════ ГАЛЕРЕЯ ══════════ */
const GAL = {
'📱 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',
],
};
/* ══════════ 91 СЕРВЕР ══════════ */
const SRV = 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`,
}));
/* ══════════ CANVAS ЭФФЕКТЫ ══════════ */
let CV, CX, PT=[], AF=null;
const cR = () => { if(!CV)return; CV.width=window.innerWidth; CV.height=window.innerHeight; };
function mkP(rnd=false) {
const w=CV.width, h=CV.height, p={x:Math.random()*w, y:rnd?Math.random()*h:-30};
if(S.fx==='sakura') return {...p, r:3+Math.random()*5, vy:.7+Math.random()*1.4, vx:(Math.random()-.5)*.8, sw:Math.random()*6.28, rot:Math.random()*6.28, rv:(Math.random()-.5)*.05, al:.5+Math.random()*.5, hue:340+Math.random()*30};
if(S.fx==='snow') return {...p, r:1.5+Math.random()*4, vy:.5+Math.random()*1.2, vx:(Math.random()-.5)*.4, sw:Math.random()*6.28, al:.5+Math.random()*.5};
if(S.fx==='rain') return {...p, len:14+Math.random()*22, vy:10+Math.random()*8, vx:-2.5, al:.2+Math.random()*.4};
if(S.fx==='stars') return {x:Math.random()*w, y:Math.random()*h, r:.4+Math.random()*2, al:Math.random(), ad:(Math.random()>.5?1:-1)*(.006+Math.random()*.014), vy:-.04-Math.random()*.08, vx:(Math.random()-.5)*.04};
if(S.fx==='firefly') return {x:Math.random()*w, y:Math.random()*h, r:1.5+Math.random()*3, al:Math.random(), ad:(Math.random()>.5?1:-1)*.014, ang:Math.random()*6.28, sp:.3+Math.random()*.6, hue:50+Math.random()*70};
if(S.fx==='bubbles') return {...p, y:h+20, r:4+Math.random()*16, vy:-.5-Math.random()*.9, vx:(Math.random()-.5)*.3, al:.15+Math.random()*.3, sw:Math.random()*6.28, hue:Math.random()*360};
return p;
}
function drawFx() {
AF = requestAnimationFrame(drawFx);
const c=CX, w=CV.width, h=CV.height;
c.clearRect(0,0,w,h);
PT.forEach((p,i) => {
c.save();
if(S.fx==='sakura') {
p.sw+=.022; p.y+=p.vy; p.x+=p.vx+Math.sin(p.sw)*.55; p.rot+=p.rv;
c.translate(p.x,p.y); c.rotate(p.rot); c.globalAlpha=p.al;
const g=c.createRadialGradient(0,0,0,0,0,p.r);
g.addColorStop(0,`hsl(${p.hue},90%,82%)`); g.addColorStop(1,`hsla(${p.hue},90%,75%,0)`);
c.fillStyle=g; c.beginPath(); c.ellipse(0,0,p.r,p.r*.55,0,0,6.28); c.fill();
if(p.y>h+30) PT[i]=mkP();
} else if(S.fx==='snow') {
p.sw+=.018; p.y+=p.vy; p.x+=p.vx+Math.sin(p.sw)*.35;
c.globalAlpha=p.al;
const g=c.createRadialGradient(p.x,p.y,0,p.x,p.y,p.r);
g.addColorStop(0,'#fff'); g.addColorStop(1,'rgba(255,255,255,0)');
c.fillStyle=g; c.beginPath(); c.arc(p.x,p.y,p.r,0,6.28); c.fill();
if(p.y>h+15) PT[i]=mkP();
} else if(S.fx==='rain') {
p.y+=p.vy; p.x+=p.vx;
c.globalAlpha=p.al; c.strokeStyle='#8fc8ff'; c.lineWidth=.85;
c.beginPath(); c.moveTo(p.x,p.y); c.lineTo(p.x+p.vx*2.5,p.y+p.len); c.stroke();
if(p.y>h+40) PT[i]=mkP();
} else if(S.fx==='stars') {
p.y+=p.vy; p.x+=p.vx; p.al+=p.ad;
if(p.al<.05||p.al>1) p.ad*=-1;
c.globalAlpha=Math.max(.05,Math.min(1,p.al));
c.fillStyle='#fff'; c.beginPath(); c.arc(p.x,p.y,p.r,0,6.28); c.fill();
if(p.y<-5) p.y=h; if(p.y>h+5) p.y=0; if(p.x<-5) p.x=w; if(p.x>w+5) p.x=0;
} else if(S.fx==='firefly') {
p.ang+=.02; p.x+=Math.cos(p.ang)*p.sp; p.y+=Math.sin(p.ang)*p.sp;
p.al+=p.ad; if(p.al<.05||p.al>1) p.ad*=-1;
c.globalAlpha=Math.max(.05,Math.min(1,p.al));
const g=c.createRadialGradient(p.x,p.y,0,p.x,p.y,p.r*3);
g.addColorStop(0,`hsl(${p.hue},100%,82%)`); g.addColorStop(1,'transparent');
c.fillStyle=g; c.beginPath(); c.arc(p.x,p.y,p.r*3,0,6.28); c.fill();
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));}
} else if(S.fx==='bubbles') {
p.sw+=.02; p.y+=p.vy; p.x+=p.vx+Math.sin(p.sw)*.5;
c.globalAlpha=p.al; c.strokeStyle=`hsl(${p.hue},70%,70%)`; c.lineWidth=1.2;
c.beginPath(); c.arc(p.x,p.y,p.r,0,6.28); c.stroke();
if(p.y<-p.r*2) PT[i]=mkP();
}
c.restore();
});
CX.globalAlpha=1;
}
function startFx() {
cancelAnimationFrame(AF); AF=null; PT=[];
if(CX) CX.clearRect(0,0,CV.width,CV.height);
if(S.fx==='none'||!CV) return;
for(let i=0; i<Math.max(10,Math.min(200,S.fxn)); i++) PT.push(mkP(true));
drawFx();
}
/* ══════════════════════════════════════════════
ПОЛНЫЙ ЗАХВАТ CSS ФОРУМА
— html/body прозрачные
— фон идёт через фиксированный #brbg
— ВСЕ блоки, карточки, посты перекрашены
══════════════════════════════════════════════ */
function buildCSS() {
const t = TH[S.theme]||TH.dark;
const fc = (FN.find(f=>f.id===S.font)||FN[0]).f;
const sz = S.size;
return `
/* ── ПРОЗРАЧНЫЙ БАЗОВЫЙ ФОН ── */
html { background: transparent !important; }
body {
background: transparent !important;
background-color: transparent !important;
background-image: none !important;
color: ${t.tx} !important;
font-family: ${fc} !important;
font-size: ${sz}px !important;
}
/* Все обёртки страницы — прозрачные */
.p-body, .p-body-inner, .p-body-pageContent,
.p-pageWrapper, .p-bodyWrap, .pageContent,
#content, .p-body-pageContent > * {
background: transparent !important;
background-color: transparent !important;
}
/* ── ХЕДЕР ── */
.p-header, .p-header-inner, .p-nav, .p-nav-inner,
header, .headerMast, .p-header-logo {
background: ${t.pn} !important;
border-bottom: 1px solid ${t.bd} !important;
backdrop-filter: blur(20px) !important;
-webkit-backdrop-filter: blur(20px) !important;
box-shadow: 0 2px 20px rgba(0,0,0,.5) !important;
}
.p-nav-list .p-nav-link, .p-nav-list > li > a {
color: ${t.tx} !important;
font-family: ${fc} !important;
}
.p-nav-list .p-nav-link:hover {
color: ${t.ac} !important;
background: ${t.cd} !important;
border-radius: 8px !important;
}
.p-navEl.is-selected > .p-navEl-link {
color: ${t.ac} !important;
border-bottom: 2px solid ${t.ac} !important;
}
/* ── ВСЕ БЛОКИ (ноды серверов, виджеты) ── */
.block, .p-widget, .node, .node-list .node {
background: ${t.pn} !important;
border: 1px solid ${t.bd} !important;
border-radius: 14px !important;
box-shadow: 0 4px 22px rgba(0,0,0,.35) !important;
overflow: hidden !important;
margin-bottom: 10px !important;
}
.block-header, .block-titleBar {
background: ${t.cd} !important;
border-bottom: 1px solid ${t.bd} !important;
border-radius: 14px 14px 0 0 !important;
padding: 12px 16px !important;
}
.block-header .block-title, .block-titleBar h2,
.block-header h2, .block-title {
color: ${t.ac} !important;
font-family: ${fc} !important;
font-weight: 700 !important;
}
.block-body, .block-row {
background: transparent !important;
}
/* ── КАРТОЧКИ СЕРВЕРОВ (ноды) ── */
.node-body {
background: transparent !important;
padding: 10px 12px !important;
}
.node-title a {
color: ${t.tx} !important;
font-family: ${fc} !important;
font-weight: 700 !important;
text-decoration: none !important;
}
.node-title a:hover,
.node--category > .node-body > .node-title > a {
color: ${t.ac} !important;
}
.node-meta, .node-statItem, .node-description,
.node-statItem .pairs-value, .node-statItem .pairs-key {
color: ${t.mu} !important;
font-family: ${fc} !important;
}
.node-stats { color: ${t.mu} !important; }
/* ── СТРОКИ ТЕМ ── */
.structItem, .structItem--thread {
background: transparent !important;
border: none !important;
border-bottom: 1px solid ${t.bd} !important;
padding: 9px 12px !important;
transition: background .14s !important;
}
.structItem:hover { background: ${t.hv} !important; border-radius: 10px !important; }
.structItem:last-child { border-bottom: none !important; }
.structItem-title a {
color: ${t.tx} !important;
font-family: ${fc} !important;
font-weight: 600 !important;
text-decoration: none !important;
}
.structItem-title a:hover { color: ${t.ac} !important; }
.structItem-cell--icon .structItem-iconContainer { color: ${t.ac} !important; }
.structItem-parts .username, .structItem-parts a { color: ${t.ac} !important; font-weight: 600 !important; }
.structItem-minor, .structItem-cell--meta { color: ${t.mu} !important; }
/* ── ПОСТЫ ── */
.message, .message--post {
background: ${t.pn} !important;
border: 1px solid ${t.bd} !important;
border-radius: 14px !important;
box-shadow: 0 3px 14px rgba(0,0,0,.28) !important;
margin-bottom: 10px !important;
overflow: hidden !important;
}
.message-cell--user {
background: ${t.cd} !important;
border-right: 1px solid ${t.bd} !important;
}
.message-attribution {
background: ${t.cd} !important;
border-bottom: 1px solid ${t.bd} !important;
padding: 8px 16px !important;
}
.message-userDetails .username, .message-name .username {
color: ${t.ac} !important;
font-weight: 700 !important;
}
.message-body .bbWrapper {
color: ${t.tx} !important;
font-family: ${fc} !important;
font-size: ${sz}px !important;
}
/* ── КНОПКИ ── */
.button--primary, .button--cta {
background: ${t.ac} !important;
color: #fff !important;
border: none !important;
border-radius: 10px !important;
font-family: ${fc} !important;
font-weight: 700 !important;
transition: opacity .16s, transform .12s !important;
}
.button--primary:hover { opacity: .86 !important; }
.button--primary:active { transform: scale(.95) !important; }
.button, .button--secondary, .button--plain {
background: ${t.cd} !important;
color: ${t.tx} !important;
border: 1px solid ${t.bd} !important;
border-radius: 10px !important;
font-family: ${fc} !important;
}
/* ── РЕДАКТОР ── */
.fr-box, .fr-wrapper, .fr-element, .fr-toolbar {
background: ${t.ip} !important;
color: ${t.tx} !important;
border: 1px solid ${t.bd} !important;
border-radius: 10px !important;
font-family: ${fc} !important;
}
.fr-toolbar { border-radius: 10px 10px 0 0 !important; background: ${t.cd} !important; }
.fr-element { border-radius: 0 0 10px 10px !important; }
/* ── ФОРМЫ ── */
input[type=text], input[type=email], input[type=password],
input[type=search], input[type=number], input[type=url],
textarea, select {
background: ${t.ip} !important;
color: ${t.tx} !important;
border: 1px solid ${t.bd} !important;
border-radius: 10px !important;
font-family: ${fc} !important;
font-size: ${sz}px !important;
outline: none !important;
}
input::placeholder, textarea::placeholder { color: ${t.mu} !important; }
input:focus, textarea:focus {
border-color: ${t.ac} !important;
box-shadow: 0 0 0 3px ${t.cd} !important;
}
/* ── ПАГИНАЦИЯ ── */
.pageNav-page a, .pageNav-page span {
background: ${t.cd} !important;
color: ${t.tx} !important;
border: 1px solid ${t.bd} !important;
border-radius: 8px !important;
}
.pageNav-page.is-active a {
background: ${t.ac} !important;
color: #fff !important;
border-color: ${t.ac} !important;
}
/* ── МЕНЮ ── */
.menu, .menu-content {
background: ${t.pn} !important;
border: 1px solid ${t.bd} !important;
border-radius: 14px !important;
box-shadow: 0 8px 30px rgba(0,0,0,.55) !important;
backdrop-filter: blur(20px) !important;
-webkit-backdrop-filter: blur(20px) !important;
}
.menu-linkRow { color: ${t.tx} !important; border-radius: 8px !important; }
.menu-linkRow:hover { background: ${t.hv} !important; color: ${t.ac} !important; }
.menu-separator { border-color: ${t.bd} !important; }
/* ── АВАТАРЫ ── */
.avatar img, .avatar-u img {
border: 2px solid ${t.ac} !important;
border-radius: 50% !important;
}
.avatar--online::after {
background: ${t.ac} !important;
box-shadow: 0 0 0 2px ${t.pn} !important;
}
/* ── ССЫЛКИ ── */
a { color: ${t.ac} !important; transition: opacity .14s !important; }
a:hover { opacity: .8 !important; text-decoration: none !important; }
/* ── СКРОЛЛ ── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: ${t.ac}; border-radius: 5px; }
/* ── ТЕГИ И ЛЕЙБЛЫ ── */
.tagItem, .tag, .label {
background: ${t.cd} !important;
color: ${t.ac} !important;
border: 1px solid ${t.bd} !important;
border-radius: 20px !important;
}
/* ── ПРОФИЛЬ ── */
.memberHeader {
background: ${t.pn} !important;
border-bottom: 1px solid ${t.bd} !important;
}
.memberHeader-name .username {
color: ${t.ac} !important;
font-size: 22px !important;
font-weight: 700 !important;
}
/* ── МЕЛКИЙ ТЕКСТ И РАЗДЕЛИТЕЛИ ── */
.u-muted, small, .pairs-key, .message-attribution time { color: ${t.mu} !important; }
hr { border-color: ${t.bd} !important; }
.notice, .blockMessage {
background: ${t.cd} !important;
border: 1px solid ${t.bd} !important;
border-radius: 12px !important;
color: ${t.tx} !important;
}
.p-breadcrumbs a { color: ${t.mu} !important; }
.p-breadcrumbs a:hover { color: ${t.ac} !important; }
`;
}
/* ══════════ СТИЛИ ПАНЕЛИ ══════════ */
const PCSS = `
@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 */
#brfab {
position:fixed; bottom:20px; right:14px; z-index:9990;
width:50px; height:50px; border-radius:50%;
border:none; color:#fff; font-size:21px; cursor:pointer;
display:flex; align-items:center; justify-content:center;
box-shadow:0 4px 22px rgba(0,0,0,.6);
transition:transform .15s;
-webkit-tap-highlight-color:transparent;
}
#brfab:active { transform:scale(.84); }
/* ОВЕРЛЕЙ */
#brov {
position:fixed; inset:0; z-index:9991;
background:rgba(0,0,0,.6);
backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
opacity:0; pointer-events:none; transition:opacity .25s;
}
#brov.on { opacity:1; pointer-events:all; }
/* ПАНЕЛЬ — снизу */
#brpnl {
position:fixed; left:0; right:0; bottom:0; z-index:9992;
height:90vh; border-radius:22px 22px 0 0;
background:var(--p);
display:flex; flex-direction:column;
color:var(--t); overflow:hidden;
transform:translateY(100%);
transition:transform .3s cubic-bezier(.32,.72,0,1);
}
#brpnl.on { transform:translateY(0); }
/* Ручка свайпа */
#brhnd {
width:38px; height:4px; border-radius:4px;
background:var(--b); margin:12px auto 0; flex-shrink:0; cursor:grab;
}
/* Шапка */
#brhdr {
display:flex; align-items:center; justify-content:space-between;
padding:10px 18px 0; flex-shrink:0;
}
#brlgo { font-size:16px; font-weight:700; color:var(--a); }
#brver { font-size:10px; color:var(--m); margin-left:4px; }
#brx {
background:none; border:1px solid var(--b); color:var(--t);
border-radius:50%; width:30px; height:30px;
display:flex; align-items:center; justify-content:center;
font-size:13px; cursor:pointer; flex-shrink:0;
-webkit-tap-highlight-color:transparent;
}
/* ТАБЫ */
#brtbs {
display:flex; gap:4px; padding:10px 14px 0;
overflow-x:auto; flex-shrink:0; scrollbar-width:none;
}
#brtbs::-webkit-scrollbar { display:none; }
.bt {
flex:0 0 auto; padding:6px 12px;
border:1px solid var(--b); border-radius:20px;
background:var(--d); color:var(--m);
font-size:12px; font-weight:700; cursor:pointer;
white-space:nowrap; transition:all .15s; font-family:inherit;
-webkit-tap-highlight-color:transparent;
display:flex; align-items:center; gap:4px;
}
.bt .ic { font-size:14px; }
.bt.on { background:var(--a); color:#fff; border-color:var(--a); }
/* ТЕЛО */
#brbdy { flex:1; overflow-y:auto; padding:12px 16px 28px; overscroll-behavior:contain; }
#brbdy::-webkit-scrollbar { width:3px; }
#brbdy::-webkit-scrollbar-thumb { background:var(--a); border-radius:4px; }
/* Секция */
.sc { font-size:10px; font-weight:700; color:var(--m); text-transform:uppercase; letter-spacing:2px; margin:16px 0 8px; }
.sc:first-child { margin-top:0; }
/* Инпут */
.inp { width:100%; box-sizing:border-box; padding:11px 14px; border-radius:12px; border:1px solid var(--b); background:var(--i); color:var(--t); font-size:14px; outline:none; font-family:inherit; -webkit-appearance:none; }
.inp::placeholder { color:var(--m); }
.inp:focus { border-color:var(--a); }
.rw { display:flex; align-items:center; gap:8px; margin-bottom:7px; }
.bsm { padding:10px 14px; border:1px solid var(--b); border-radius:10px; background:var(--d); color:var(--t); cursor:pointer; font-size:13px; font-family:inherit; font-weight:600; -webkit-tap-highlight-color:transparent; }
.bsm.ac { background:var(--a); color:#fff; border-color:var(--a); }
.bsm:active { opacity:.7; }
.bwd { width:100%; padding:13px; border:1px solid var(--b); border-radius:12px; background:var(--d); color:var(--t); cursor:pointer; font-size:14px; font-family:inherit; text-align:center; margin-top:6px; font-weight:600; -webkit-tap-highlight-color:transparent; }
.bwd:active { opacity:.7; }
.sl { flex:1; -webkit-appearance:none; appearance:none; height:4px; border-radius:4px; background:var(--b); outline:none; }
.sl::-webkit-slider-thumb { -webkit-appearance:none; width:22px; height:22px; border-radius:50%; background:var(--a); cursor:pointer; box-shadow:0 2px 8px rgba(0,0,0,.4); }
.sv { font-size:13px; font-weight:700; color:var(--a); min-width:36px; text-align:right; }
.lb { font-size:12px; color:var(--m); font-weight:600; }
/* Категории */
#brcts { display:flex; gap:6px; overflow-x:auto; padding-bottom:4px; scrollbar-width:none; margin-bottom:10px; }
#brcts::-webkit-scrollbar { display:none; }
.ct { flex:0 0 auto; padding:6px 12px; border:1px solid var(--b); border-radius:20px; background:var(--d); color:var(--m); font-size:12px; cursor:pointer; white-space:nowrap; font-family:inherit; transition:all .14s; -webkit-tap-highlight-color:transparent; }
.ct.on { background:var(--a); color:#fff; border-color:var(--a); }
/* Галерея */
#brgal { display:grid; grid-template-columns:repeat(3,1fr); gap:7px; }
.wpt { height:78px; border-radius:11px; background-size:cover; background-position:center; cursor:pointer; border:2.5px solid transparent; transition:transform .13s, border-color .13s; -webkit-tap-highlight-color:transparent; position:relative; }
.wpt:active { transform:scale(.91); }
.wpt.on { border-color:var(--a); }
.wpt.on::after { content:'✓'; position:absolute; top:4px; right:6px; color:#fff; font-size:13px; font-weight:700; text-shadow:0 1px 4px rgba(0,0,0,.7); }
.g2 { display:grid; grid-template-columns:1fr 1fr; gap:7px; }
.g3 { display:grid; grid-template-columns:1fr 1fr 1fr; gap:7px; }
.op { padding:11px 6px; border:1px solid var(--b); border-radius:11px; background:var(--d); color:var(--t); cursor:pointer; font-size:12px; text-align:center; font-family:inherit; transition:all .14s; -webkit-tap-highlight-color:transparent; font-weight:600; }
.op.on { background:var(--a); color:#fff; border-color:var(--a); }
.thc { padding:13px 6px; border-radius:12px; border:2.5px solid transparent; cursor:pointer; text-align:center; font-size:12px; font-weight:700; transition:all .17s; font-family:inherit; -webkit-tap-highlight-color:transparent; }
.thc.on { box-shadow:0 0 0 2.5px var(--a), 0 4px 14px rgba(0,0,0,.4); }
/* Серверы */
#brsrv { display:grid; grid-template-columns:repeat(3,1fr); gap:7px; margin-top:10px; }
.sa { display:flex; flex-direction:column; align-items:center; padding:11px 4px; background:var(--d); border:1px solid var(--b); border-radius:12px; text-decoration:none; color:inherit; transition:background .13s, transform .13s; -webkit-tap-highlight-color:transparent; }
.sa:active { transform:scale(.91); }
.sn { font-size:18px; font-weight:700; color:var(--a); line-height:1; }
.sl2 { font-size:9px; color:var(--m); margin-top:2px; font-weight:700; letter-spacing:.5px; }
/* Переключатели */
.swr { display:flex; align-items:center; justify-content:space-between; padding:12px 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:44px; height:26px; flex-shrink:0; }
.sw input { opacity:0; width:0; height:0; position:absolute; }
.swb { position:absolute; inset:0; border-radius:13px; background:var(--b); cursor:pointer; transition:background .2s; }
.sw input:checked + .swb { background:var(--a); }
.swb::after { content:''; position:absolute; width:20px; height:20px; left:3px; top:3px; border-radius:50%; background:#fff; transition:transform .2s; box-shadow:0 1px 4px rgba(0,0,0,.3); }
.sw input:checked + .swb::after { transform:translateX(18px); }
.info { padding:11px 13px; border-radius:12px; background:var(--d); border:1px solid var(--b); font-size:12px; color:var(--m); line-height:1.65; margin-top:8px; }
/* НИЖНИЙ НАВБАР — базовые стили */
#brnav {
position:fixed; left:0; right:0; bottom:0; z-index:9980;
height:56px; display:flex; align-items:center; justify-content:space-around;
padding:0 4px; transition:transform .28s ease;
}
#brnav.gone { transform:translateY(100%); }
/* glass */
#brnav.ns-glass {
background:var(--p,rgba(8,8,20,.96));
backdrop-filter:blur(22px); -webkit-backdrop-filter:blur(22px);
border-top:1px solid var(--b,rgba(124,77,255,.22));
}
/* solid */
#brnav.ns-solid {
background:var(--bg,#0a0a1c);
border-top:2px solid var(--a,#7c4dff);
}
/* pill — floating */
#brnav.ns-pill {
background:transparent;
border:none;
bottom:10px; left:10px; right:10px;
height:auto;
}
#brnav.ns-pill::before {
content:'';
position:absolute; inset:0;
background:var(--p,rgba(8,8,20,.96));
backdrop-filter:blur(22px); -webkit-backdrop-filter:blur(22px);
border:1px solid var(--b,rgba(124,77,255,.22));
border-radius:30px;
box-shadow:0 4px 24px rgba(0,0,0,.5);
}
/* glow */
#brnav.ns-glow {
background:var(--p,rgba(8,8,20,.96));
backdrop-filter:blur(22px); -webkit-backdrop-filter:blur(22px);
border-top:2px solid var(--a,#7c4dff);
box-shadow:0 -4px 24px color-mix(in srgb, var(--a,#7c4dff) 35%, transparent);
}
/* minimal */
#brnav.ns-minimal {
background:transparent;
border-top:1px solid var(--b,rgba(124,77,255,.22));
}
/* Пункты навбара */
.bna {
position:relative; z-index:1;
display:flex; flex-direction:column; align-items:center; gap:1px;
padding:6px 8px; color:var(--m,#5a5a90);
text-decoration:none; font-size:9px; font-weight:700;
border-radius:12px; cursor:pointer; min-width:44px;
transition:color .14s, background .14s;
-webkit-tap-highlight-color:transparent; letter-spacing:.3px;
background:transparent; border:none; font-family:inherit;
}
.bna .bi { font-size:19px; line-height:1.2; }
.bna:active { background:var(--d,rgba(124,77,255,.1)); }
.bna.cur { color:var(--a,#7c4dff); }
/* Активная точка */
.bna.cur::after {
content:'';
position:absolute; bottom:2px; left:50%; transform:translateX(-50%);
width:4px; height:4px; border-radius:50%; background:var(--a,#7c4dff);
}
/* FAB — выше навбара когда он есть */
#brfab { transition:transform .15s, bottom .3s; }
/* ТОСТ — выше навбара */
#brtst { bottom:72px; }
#brclk { position:fixed; top:8px; left:50%; transform:translateX(-50%); z-index:9985; pointer-events:none; font-size:12px; font-weight:700; letter-spacing:1.5px; padding:3px 13px; border-radius:20px; backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); border:1px solid; white-space:nowrap; }
/* ПРОГРЕСС */
#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 .1s linear; }
/* ТОСТ */
#brtst { position:fixed; bottom:80px; left:50%; transform:translateX(-50%); z-index:9998; pointer-events:none; display:flex; flex-direction:column; align-items:center; gap:6px; }
.ts { padding:8px 18px; border-radius:20px; font-size:13px; font-weight:700; backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px); border:1px solid; white-space:nowrap; animation:tsi .2s ease, tso .25s ease 2s forwards; font-family:inherit; }
@keyframes tsi { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }
@keyframes tso { to{opacity:0} }
`;
/* ══════════ DOM ══════════ */
let BG, FAB, OV, PNL, CLK, PRG, TST, NAV;
let SF, SP;
const gT = () => TH[S.theme] || TH.dark;
const gF = () => (FN.find(f => f.id === S.font) || FN[0]).f;
function setVars(el) {
if (!el) return;
const t = gT();
el.style.setProperty('--a', t.ac);
el.style.setProperty('--t', t.tx);
el.style.setProperty('--m', t.mu);
el.style.setProperty('--p', t.pn);
el.style.setProperty('--d', t.cd);
el.style.setProperty('--b', t.bd);
el.style.setProperty('--i', t.ip);
el.style.fontFamily = gF();
}
function applyForum() { if (SF) SF.textContent = buildCSS(); }
function applyWP() {
if (!BG) return;
if (S.wp) {
BG.style.backgroundImage = `url('${S.wp}')`;
BG.style.opacity = S.wpa / 100;
BG.style.filter = S.wpb > 0 ? `blur(${S.wpb}px)` : '';
} else {
BG.style.backgroundImage = '';
BG.style.opacity = '1';
BG.style.filter = '';
}
}
function applyAll() {
applyForum(); applyWP(); startFx(); setVars(PNL);
const t = gT();
if (FAB) FAB.style.background = t.ac;
if (CLK) { CLK.style.color = t.ac; CLK.style.borderColor = t.bd; CLK.style.background = t.pn; CLK.style.fontFamily = gF(); }
if (PRG) PRG.style.background = t.ac;
updateWidgets();
}
function updateWidgets() {
if (CLK) CLK.style.display = S.clock ? '' : 'none';
if (PRG) PRG.style.display = S.prog ? '' : 'none';
updateNav();
applyForum();
}
/* ══════════ НАВБАР ══════════ */
const NAVLINKS = [
{ ic:'🏠', l:'Главная', u:'https://forum.blackrussia.online/' },
{ ic:'🆕', l:'Новое', u:'https://forum.blackrussia.online/whats-new/posts/' },
{ ic:'👥', l:'Онлайн', u:'https://forum.blackrussia.online/online/' },
{ ic:'🔔', l:'Уведомл', u:'https://forum.blackrussia.online/account/alerts/' },
{ ic:'👤', l:'Профиль', u:'https://forum.blackrussia.online/account/' },
];
function buildNav() {
NAV = document.createElement('nav');
NAV.id = 'brnav';
document.body.appendChild(NAV);
updateNav();
}
function updateNav() {
if (!NAV) return;
const t = gT();
// Показать/скрыть
NAV.style.display = S.bnav ? 'flex' : 'none';
// CSS vars
NAV.style.setProperty('--a', t.ac);
NAV.style.setProperty('--t', t.tx);
NAV.style.setProperty('--m', t.mu);
NAV.style.setProperty('--p', t.pn);
NAV.style.setProperty('--d', t.cd);
NAV.style.setProperty('--b', t.bd);
NAV.style.setProperty('--bg', t.bg);
NAV.style.fontFamily = gF();
// Стиль
NAV.className = `ns-${S.navstyle||'glass'}`;
// Пункты
NAV.innerHTML = NAVLINKS.map(n => `
<a class="bna${location.href.startsWith(n.u)?' cur':''}" href="${n.u}">
<span class="bi">${n.ic}</span>${n.l}
</a>`).join('');
// FAB выше навбара
if (FAB) FAB.style.bottom = S.bnav ? '66px' : '20px';
}
/* ══════════ ТОСТ ══════════ */
function toast(msg) {
if (!TST) return;
const t = gT();
const el = document.createElement('div');
el.className = 'ts'; el.textContent = msg;
el.style.background = t.pn; el.style.borderColor = t.bd; el.style.color = t.tx;
TST.appendChild(el);
setTimeout(() => el.remove(), 2400);
}
/* ══════════ ОТКРЫТЬ / ЗАКРЫТЬ ══════════ */
function openPanel() { render(); PNL.classList.add('on'); OV.classList.add('on'); }
function closePanel() { PNL.classList.remove('on'); OV.classList.remove('on'); }
function initSwipe() {
const hnd = document.getElementById('brhnd');
if (!hnd) return;
let sy = 0, dy = 0, on = false;
hnd.addEventListener('touchstart', e => { sy = e.touches[0].clientY; on = true; }, { passive: true });
window.addEventListener('touchmove', e => { if (!on) return; dy = e.touches[0].clientY - sy; if (dy > 0) PNL.style.transform = `translateY(${dy}px)`; }, { passive: true });
window.addEventListener('touchend', () => { if (!on) return; on = false; PNL.style.transform = ''; if (dy > 90) closePanel(); dy = 0; }, { passive: true });
}
/* ══════════ РЕНДЕР ══════════ */
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:'Прочее' },
{ id:'nav', ic:'🧭', l:'Навбар' },
];
function render() {
setVars(PNL);
PNL.innerHTML = `
<div id="brhnd"></div>
<div id="brhdr">
<div style="display:flex;align-items:baseline">
<span id="brlgo">🎨 BR Pro</span><span id="brver"> v5.1</span>
</div>
<button id="brx">✕</button>
</div>
<div id="brtbs">${TABS.map(t => `<button class="bt${S.tab === t.id ? ' on' : ''}" data-t="${t.id}"><span class="ic">${t.ic}</span>${t.l}</button>`).join('')}</div>
<div id="brbdy">${getContent()}</div>`;
bindAll(); initSwipe();
}
function getContent() {
if (S.tab === 'wp') return tabWP();
if (S.tab === 'srv') return tabSRV();
if (S.tab === 'fx') return tabFX();
if (S.tab === 'th') return tabTH();
if (S.tab === 'fn') return tabFN();
if (S.tab === 'opt') return tabOPT();
if (S.tab === 'nav') return tabNAV();
return '';
}
function tabWP() { return `
<div class="sc">Своя ссылка</div>
<div class="rw"><input class="inp" id="wurl" type="url" placeholder="https://... картинка или gif" value="${S.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="${S.wpa}"><span class="lb">🔆</span><span class="sv" id="wpav">${S.wpa}%</span></div>
<div class="sc">Размытие фона</div>
<div class="rw"><input type="range" class="sl" id="wpb" min="0" max="20" value="${S.wpb}"><span class="sv" id="wpbv">${S.wpb}px</span></div>
<div class="sc">Галерея</div>
<div id="brcts">${Object.keys(GAL).map(k => `<button class="ct${S.wpcat === k ? ' on' : ''}" data-c="${k}">${k}</button>`).join('')}</div>
<div id="brgal">${galHTML(S.wpcat)}</div>`; }
function galHTML(cat) {
return (GAL[cat] || []).map(u => `<div class="wpt${S.wp === u ? ' on' : ''}" data-u="${u}" style="background-image:url('${u}')"></div>`).join('');
}
function tabSRV() { return `
<div class="sc">Поиск</div>
<input class="inp" id="srch" type="text" inputmode="numeric" placeholder="🔍 Номер 1–91..." autocomplete="off">
<div id="brsrv">${SRV.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>`; }
function tabFX() {
const FXS = [{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">${FXS.map(e => `<button class="op${S.fx === e.id ? ' on' : ''}" data-fx="${e.id}">${e.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="${S.fxn}"><span class="lb">Больше</span><span class="sv" id="fxnv">${S.fxn}</span></div>`; }
function tabTH() { return `
<div class="sc">Тема</div>
<div class="g2">${Object.entries(TH).map(([id, t]) => `<button class="thc${S.theme === id ? ' on' : ''}" style="background:${t.bg};color:${t.tx};" data-th="${id}">${t.n}</button>`).join('')}</div>`; }
function tabFN() { return `
<div class="sc">Шрифт</div>
<div class="g2">${FN.map(f => `<button class="op${S.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:11px;font-weight:700">A</span><input type="range" class="sl" id="fsz" min="12" max="20" step="1" value="${S.size}"><span class="lb" style="font-size:18px;font-weight:700">A</span><span class="sv" id="fszv">${S.size}px</span></div>`; }
function tabOPT() { return `
<div class="sc">Виджеты</div>
${mkSW('clock','⏰ Часы','Время вверху страницы')}
${mkSW('prog','📊 Прогресс скролла','Цветная полоса сверху страницы')}
${mkSW('bnav','🧭 Навигация','Нижний навбар')}
<div class="sc">Сброс</div>
<button class="bwd" id="rst">🗑️ Сбросить все настройки</button>
<div class="info">🎨 BR Pro Ultimate v5.1<br>Автор: Akzholch1k</div>`; }
function tabNAV() {
const styles = [
{ id:'glass', l:'🌊 Стекло', desc:'Blur + прозрачность' },
{ id:'solid', l:'🟦 Сплошной', desc:'Чёткий фон темы' },
{ id:'pill', l:'💊 Пилюля', desc:'Плавающий закруглённый' },
{ id:'glow', l:'✨ Свечение', desc:'Цветная подсветка' },
{ id:'minimal',l:'🔲 Минимал', desc:'Тонкая линия сверху' },
];
return `
<div class="sc">Включить навбар</div>
<div class="rw" style="justify-content:space-between;padding:4px 0">
<span style="font-size:14px;color:var(--t);font-weight:600">Нижняя навигация</span>
<label class="sw"><input type="checkbox" data-sw="bnav" ${S.bnav?'checked':''}><span class="swb"></span></label>
</div>
<div class="sc">Стиль навбара</div>
<div class="g2">
${styles.map(s => `
<button class="nav-style-btn op${S.navstyle===s.id?' on':''}" data-ns="${s.id}">
<div style="font-size:16px">${s.l.split(' ')[0]}</div>
<div style="font-size:11px;margin-top:2px;font-weight:700">${s.l.split(' ').slice(1).join(' ')}</div>
<div style="font-size:10px;color:var(--m);margin-top:1px;font-weight:400">${s.desc}</div>
</button>`).join('')}
</div>
<div class="sc">Предпросмотр</div>
<div id="nav-preview" style="position:relative;height:64px;border-radius:14px;overflow:hidden;border:1px solid var(--b);">
${navPreviewHTML()}
</div>
<div class="info">💡 Навбар скрывается при скролле вниз и появляется при скролле вверх.</div>`; }
function navPreviewHTML() {
const t = gT();
const NL = [
{ic:'🏠',l:'Главная'},{ic:'🆕',l:'Новое'},
{ic:'👥',l:'Онлайн'},{ic:'🔔',l:'Уведомл'},{ic:'👤',l:'Профиль'},
];
let bg = '';
if(S.navstyle==='glass') bg = `background:${t.pn};backdrop-filter:blur(20px);border-top:1px solid ${t.bd};`;
if(S.navstyle==='solid') bg = `background:${t.bg};border-top:2px solid ${t.ac};`;
if(S.navstyle==='pill') bg = `background:transparent;`;
if(S.navstyle==='glow') bg = `background:${t.pn};border-top:2px solid ${t.ac};box-shadow:0 -4px 20px ${t.ac}44;`;
if(S.navstyle==='minimal') bg = `background:transparent;border-top:1px solid ${t.bd};`;
const items = NL.map((n,i) => `
<div style="display:flex;flex-direction:column;align-items:center;gap:1px;padding:5px 8px;color:${i===0?t.ac:t.mu};font-size:9px;font-weight:700;min-width:40px;letter-spacing:.3px">
<span style="font-size:18px;line-height:1.2">${n.ic}</span>${n.l}
</div>`).join('');
if(S.navstyle==='pill') {
return `<div style="position:absolute;left:10px;right:10px;bottom:8px;display:flex;align-items:center;justify-content:space-around;${bg}background:${t.pn};border-radius:30px;border:1px solid ${t.bd};padding:4px 0;box-shadow:0 4px 20px rgba(0,0,0,.4)">${items}</div>`;
}
return `<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:space-around;${bg}padding:0 4px">${items}</div>`;
}
function mkSW(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}" ${S[k] ? 'checked' : ''}><span class="swb"></span></label></div>`;
}
/* ══════════ БИНДЫ ══════════ */
function bindAll() {
const $ = id => document.getElementById(id);
const QA = s => PNL.querySelectorAll(s);
$('brx').onclick = closePanel;
QA('.bt').forEach(el => el.onclick = () => { S.tab = el.dataset.t; sv(); render(); });
/* Обои */
const wu = $('wurl');
$('wset') && ($('wset').onclick = () => {
const v = (wu?.value || '').trim();
if (!v) { toast('⚠️ Введи ссылку!'); return; }
S.wp = v; sv(); applyWP(); toast('✅ Обои применены!');
QA('.wpt').forEach(e => e.classList.toggle('on', e.dataset.u === v));
});
$('wclr') && ($('wclr').onclick = () => { S.wp = ''; sv(); applyWP(); toast('🗑️ Убрано'); render(); });
const wpa = $('wpa');
if (wpa) wpa.oninput = () => { S.wpa = +wpa.value; $('wpav').textContent = S.wpa + '%'; sv(); applyWP(); };
const wpb = $('wpb');
if (wpb) wpb.oninput = () => { S.wpb = +wpb.value; $('wpbv').textContent = S.wpb + 'px'; sv(); applyWP(); };
QA('.ct').forEach(el => el.onclick = () => {
S.wpcat = el.dataset.c; sv();
QA('.ct').forEach(e => e.classList.remove('on')); el.classList.add('on');
$('brgal').innerHTML = galHTML(S.wpcat); bindThumbs();
});
bindThumbs();
const sr = $('srch');
if (sr) sr.oninput = () => {
const q = sr.value.trim();
QA('.sa').forEach(el => { el.style.display = (!q || el.querySelector('.sn').textContent.includes(q)) ? '' : 'none'; });
};
QA('[data-fx]').forEach(el => el.onclick = () => { S.fx = el.dataset.fx; sv(); startFx(); toast(`✨ ${el.textContent}`); render(); });
const fxn = $('fxn');
if (fxn) fxn.oninput = () => { S.fxn = +fxn.value; $('fxnv').textContent = S.fxn; sv(); startFx(); };
QA('[data-th]').forEach(el => el.onclick = () => { S.theme = el.dataset.th; sv(); applyAll(); toast(`🎨 ${TH[S.theme].n}`); render(); });
QA('[data-fn]').forEach(el => el.onclick = () => { S.font = el.dataset.fn; sv(); applyAll(); render(); });
const fsz = $('fsz');
if (fsz) fsz.oninput = () => { S.size = +fsz.value; $('fszv').textContent = S.size + 'px'; sv(); applyForum(); };
QA('[data-sw]').forEach(el => el.onchange = () => { S[el.dataset.sw] = el.checked; sv(); updateWidgets(); if(el.dataset.sw==='bnav') render(); });
/* Стиль навбара */
QA('[data-ns]').forEach(el => el.onclick = () => {
S.navstyle = el.dataset.ns; sv(); updateNav();
QA('[data-ns]').forEach(e => e.classList.toggle('on', e.dataset.ns === S.navstyle));
document.getElementById('nav-preview') && (document.getElementById('nav-preview').innerHTML = navPreviewHTML());
});
const rst = $('rst');
if (rst) rst.onclick = () => {
if (confirm('Сбросить все настройки?')) { Object.assign(S, DEF); sv(); applyAll(); toast('✅ Сброшено'); render(); }
};
}
function bindThumbs() {
PNL.querySelectorAll('.wpt').forEach(el => el.onclick = () => {
S.wp = el.dataset.u; sv(); applyWP();
PNL.querySelectorAll('.wpt').forEach(e => e.classList.toggle('on', e.dataset.u === el.dataset.u));
toast('🖼️ Выбрано!');
});
}
let lastScrollY = 0;
function onScroll() {
if (PRG && S.prog) {
const sc = window.scrollY, tot = document.documentElement.scrollHeight - window.innerHeight;
PRG.style.width = tot > 0 ? ((sc / tot) * 100) + '%' : '0%';
}
if (NAV && S.bnav) {
if (window.scrollY > lastScrollY + 30 && window.scrollY > 80) NAV.classList.add('gone');
else if (window.scrollY < lastScrollY - 10) NAV.classList.remove('gone');
}
lastScrollY = window.scrollY;
}
/* ══════════ ЧАСЫ ══════════ */
let clockTimer = null;
function startClock() {
if (clockTimer) clearInterval(clockTimer);
const tick = () => {
if (!CLK) return;
const n = new Date(), p = x => String(x).padStart(2, '0');
CLK.textContent = `${p(n.getHours())}:${p(n.getMinutes())}:${p(n.getSeconds())}`;
};
tick(); clockTimer = setInterval(tick, 1000);
}
/* ══════════ INIT ══════════ */
function init() {
/* Шрифты */
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);
/* Стили */
SF = document.createElement('style'); SF.id = 'brsf'; document.head.appendChild(SF);
SP = document.createElement('style'); SP.id = 'brsp'; SP.textContent = PCSS; document.head.appendChild(SP);
/* Фон — позади всего, z-index:0 */
BG = document.createElement('div'); BG.id = 'brbg';
BG.style.cssText = 'position:fixed;inset:0;z-index:0;pointer-events:none;background-size:cover;background-position:center;background-repeat:no-repeat;transition:opacity .5s,filter .5s;';
document.body.prepend(BG);
/* Канвас эффектов — z-index:1 */
CV = document.createElement('canvas'); CV.id = 'brcv';
CV.style.cssText = 'position:fixed;inset:0;z-index:1;pointer-events:none;';
document.body.appendChild(CV);
CX = CV.getContext('2d'); cR();
window.addEventListener('resize', cR, { passive: true });
/* Прогресс */
PRG = document.createElement('div'); PRG.id = 'brprg'; document.body.appendChild(PRG);
/* Часы */
CLK = document.createElement('div'); CLK.id = 'brclk'; document.body.appendChild(CLK);
startClock();
/* Тосты */
TST = document.createElement('div'); TST.id = 'brtst'; document.body.appendChild(TST);
/* Оверлей */
OV = document.createElement('div'); OV.id = 'brov'; OV.onclick = closePanel; document.body.appendChild(OV);
/* Панель */
PNL = document.createElement('div'); PNL.id = 'brpnl'; document.body.appendChild(PNL);
/* FAB — только одна кнопка настроек */
FAB = document.createElement('button'); FAB.id = 'brfab'; FAB.innerHTML = '⚙️'; FAB.title = 'BR Pro';
document.body.appendChild(FAB);
FAB.onclick = openPanel;
/* Навбар */
buildNav();
/* Скролл */
window.addEventListener('scroll', onScroll, { passive: true });
/* Применить */
applyAll();
if (!localStorage.getItem('br5hi')) {
setTimeout(() => toast('🎨 BR Pro v5 активен!'), 600);
localStorage.setItem('br5hi', '1');
}
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
else init();
})();