AnimeStars Full Black Theme (v2.0)

Чёрная тема

// ==UserScript==
// @name         AnimeStars Full Black Theme (v2.0)
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Чёрная тема
// @author       VladLIO
// @match        https://animestars.org/*
// @match        *://asstars.tv/*
// @match        *://astars.club/*
// @match        *://asstars.online/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
  'use strict';

  /* ========= НАСТРОЙКИ ========= */
  const SAFE_SIDE_GAP         = 16;
  const MIN_TITLE_WIDTH       = 240;
  const MAX_Z                 = 2147483647;

  const BANNER_ANCHOR         = 'poster'; // 'poster' | 'header'
  const BANNER_TOP_OFFSET     = 8;
  const POSTER_TOP_OFFSET     = 56;
  const BOTTOM_GAP            = 6;

  const MAX_HEADER_PADDING    = 260;
  const MAX_BANNER_TOP        = 220;
  const MIN_BANNER_TOP        = 6;

  const ALIGN_TO_POSTER_LEFT  = true;
  const TITLE_MAX_LINES       = 2;
  const AUTO_FIT_ONE_LINE     = true;
  const MIN_FONT_PX           = 22;
  const MAX_FONT_PX           = 64;

  /* ========= СТИЛИ ========= */
  const CSS = `
  :root{
    --asbm-title-size: clamp(32px, 3.2vw, 52px);
    --asbm-title-shadow: 0 3px 10px rgba(0,0,0,.75), 0 0 2px rgba(0,0,0,.9);
    --asbm-info-pad: 16px;
    --asbm-info-radius: 0px;
    --asbm-info2-shift: 120px;
    --asbm-line-clamp: 1;
  }

  /* Базовая заливка */
  #asbm_bar, #asbm_container,
  header.header, header.header.hbg,
  aside.col-side, .col-side,
  .anime-cards, .anime-cards.anime-cards--full-page,
  .nclub__top-carou, .nclub__sect, .nclub__sect .sect__header, .nclub__sect .sect__content,
  .remelt, .remelt__inner, .remelt__inventory,
  .card-filter-list, .card-stars-list,
  .ncard__menu-content, .ncard__users-toplist,
  .ncard__shop-content, .ncard__shop-content-list, .ncard__shop-content-header,
  .dpm-container-empty, .dpm-dialog, .dpm-ignore-content, .dpm-overlay,
  .dpm-editor-wrapper, .dpm-dialog-editor-place,
  .menus,
  #anime-player__controls, .pmovie_player-controls, .pmovie__player-controls,
  .tabs-block__select, .b-translators__block,
  .trade__main-items, .trade_inventory, .trade_inventory-list,
  .trade_main, .trade_main_user, .trade_controls, .trade__container, .trade__wrapper,
  .trade__main, .trade__main-user, .trade__main-divider, .trade_main-items, .trade_main-divider,
  .history,
  .noffer__bg{
    background:#000!important; background-image:none!important; box-shadow:none!important; border-color:transparent!important;
  }

  /* --- ФИКС ПОЛОСОК В САЙДБАРЕ --- */
  aside.col-side, .col-side{
    background:#000!important;
    background-image:none!important;
    box-shadow:none!important;
    border-color:transparent!important;
    filter:none!important; mix-blend-mode:normal!important;
  }
  aside.col-side::before, aside.col-side::after,
  .col-side::before, .col-side::after{
    content:none!important; background:none!important; background-image:none!important;
    -webkit-mask-image:none!important; mask-image:none!important;
    filter:none!important; box-shadow:none!important; pointer-events:none!important;
  }
  .col-side .side_block, .col-side .side-block, .col-side .side_block_menu, .col-side .side-block_menu,
  .col-side .aside__menu, .col-side .aside__header, .col-side .aside__footer, .col-side .aside__wrap,
  .col-side .aside__list, .col-side .side_block_menu *, .col-side .side-block *{
    background:#000!important; background-image:none!important; box-shadow:none!important; border-color:transparent!important;
  }

  /* --- Шапка карточки тайтла --- */
  .pcoln__header, .pcoln_header{
    position:relative!important; z-index:${MAX_Z}!important; background:transparent!important;
    overflow:visible!important; min-height:180px!important;
  }
  .pcoln_header .blurred-bg, .pcoln_header .bg, .pcoln_header .poster_overlay,
  .pcoln_header .pcoln__overlay, .pcoln_header .pcoln__curtain, .pcoln_header .pcoln__mask,
  .pcoln_header .pcoln__fog, .pcoln_header .pcoln__shadow, .pcoln_header .pcoln__dark,
  .pcoln_header .pcoln__canvas, .pcoln_header .pcoln__vignette,
  .pcoln_header::before, .pcoln_header::after{
    opacity:0!important; background:transparent!important; background-image:none!important;
    filter:none!important; backdrop-filter:none!important; -webkit-backdrop-filter:none!important;
    mix-blend-mode:normal!important; -webkit-mask-image:none!important; mask-image:none!important;
    pointer-events:none!important; z-index:0!important; box-shadow:none!important; border:0!important;
  }

  /* Баннер заголовка */
  .asbm-title-banner{
    position:absolute!important; left:0; right:0; z-index:${MAX_Z}!important;
    background:transparent!important; pointer-events:none!important;
  }
  .asbm-title-box{
    display:block!important; margin:0!important; text-align:left!important;
    font-weight:800!important; font-size:var(--asbm-title-size)!important; line-height:1.15!important;
    color:#fff!important; -webkit-text-fill-color:#fff!important; text-shadow:var(--asbm-title-shadow)!important;
    white-space:nowrap!important; overflow:hidden!important; text-overflow:clip!important;
    padding:0 4px!important; pointer-events:none!important;
  }
  .asbm-title-box.asbm-ml{
    white-space:normal!important;
    display:-webkit-box!important;
    -webkit-box-orient:vertical!important;
    -webkit-line-clamp:var(--asbm-line-clamp)!important;
    overflow:hidden!important; text-overflow:ellipsis!important;
    line-height:1.12!important;
  }
  h1[itemprop="name"], .pmovie__original-title, .movie__original-title{
    position:static!important; opacity:0!important; visibility:hidden!important; height:0!important; overflow:hidden!important; pointer-events:none!important;
  }

  /* Правая инфо-панель */
  .pcoln__info2{
    position:relative!important; z-index:3!important;
    display:flex!important; flex-direction:column!important; gap:10px!important;
    padding:var(--asbm-info-pad)!important; border-radius:var(--asbm-info-radius)!important;
    background:transparent!important; box-shadow:none!important; border:0!important;
    mix-blend-mode:normal!important; backdrop-filter:none!important; -webkit-backdrop-filter:none!important;
    overflow:visible!important; -webkit-mask-image:none!important; mask-image:none!important;
    margin-top: var(--asbm-info2-shift)!important; align-self:flex-start!important;
  }
  .pcoln__info2, .pcoln__info2 *{ color:#fff!important; text-shadow:none!important; opacity:1!important; visibility:visible!important; }

  @media (max-width:1200px){ :root { --asbm-info2-shift: 90px; } }
  @media (max-width:900px) { :root { --asbm-info2-shift: 60px; } }

  /* --- Фильтр по жанрам / облако тегов --- */
  nav.filter-blockcat,
  nav.filter-blockcat *,
  ul.flex-row-cat,
  ul.flex-row-cat li,
  nav.filter-blockcat + div,
  nav.filter-blockcat ~ div{
    background:#000!important; background-image:none!important; box-shadow:none!important; border-color:transparent!important;
  }
  nav.filter-blockcat + div{ border-top:0!important; border:0!important; }

  /* --- Trade inventory (чёрный фон) --- */
  .trade_inventory,
  .trade_inventory-list,
  .trade__inventory,
  .trade__inventory-list{
    background:#000!important;
    background-color:#000!important;
    background-image:none!important;
    box-shadow:none!important;
    border-color:transparent!important;
    filter:none!important;
    mix-blend-mode:normal!important;
  }
  `;

  const early = document.createElement('style');
  early.textContent = CSS;
  (document.head || document.documentElement).appendChild(early);
  addEventListener('load', () => {
    const late = document.createElement('style'); late.textContent = CSS; document.head.appendChild(late);
  });

  /* ========= УТИЛИТЫ ========= */
  const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));

  function findTitleText(root=document){
    const cand =
      root.querySelector('h1[itemprop="name"]') ||
      root.querySelector('.movie__original-title') ||
      root.querySelector('.pmovie__original-title');
    const t = cand?.textContent?.trim();
    if (t) return t;
    const meta = root.querySelector('meta[itemprop="name"][content]');
    return meta?.getAttribute('content')?.trim() || '';
  }

  function ensureTitleBanner(root=document){
    const header = root.querySelector('.pcoln__header, .pcoln_header');
    if (!header) return;
    const text = findTitleText(root);
    if (!text) return;

    let banner = header.querySelector('.asbm-title-banner');
    if (!banner){
      banner = document.createElement('div');
      banner.className = 'asbm-title-banner';
      header.prepend(banner);
    }
    let box = banner.querySelector('.asbm-title-box');
    if (!box){
      box = document.createElement('div');
      box.className = 'asbm-title-box';
      banner.appendChild(box);
    }
    if (box.textContent !== text) box.textContent = text;

    positionBanner(header, banner, box, root);
  }

  function autoFitOneLine(box){
    box.style.fontSize = '';
    const cs = getComputedStyle(box);
    let size = Math.min(parseFloat(cs.fontSize) || 44, MAX_FONT_PX);
    box.style.fontSize = size + 'px';

    let guard = 80;
    while (box.scrollWidth > box.clientWidth && size > MIN_FONT_PX && guard-- > 0) {
      size -= 1;
      box.style.fontSize = size + 'px';
    }
  }

  function positionBanner(header, banner, box, root=document){
    try{
      header.style.overflow = 'visible';
      header.style.minHeight = '180px';

      const hdr = header.getBoundingClientRect();
      const poster = header.querySelector('.pcoln__poster, .pcoln__img, .pcoln__left, .pcoln__poster img') || header;

      let left = SAFE_SIDE_GAP;
      if (ALIGN_TO_POSTER_LEFT && poster){
        const pr = poster.getBoundingClientRect();
        left = clamp(Math.round(pr.left - hdr.left), SAFE_SIDE_GAP, hdr.width - MIN_TITLE_WIDTH - SAFE_SIDE_GAP);
      }
      banner.style.left = `${left}px`;

      let maxWidth = hdr.width - left - SAFE_SIDE_GAP;
      const info = header.querySelector('.pcoln__info2');
      if (info){
        const ir = info.getBoundingClientRect();
        const safeW = Math.round(ir.left - hdr.left) - left - SAFE_SIDE_GAP;
        if (safeW > MIN_TITLE_WIDTH) maxWidth = Math.min(maxWidth, safeW);
      }
      box.style.maxWidth = `${Math.max(MIN_TITLE_WIDTH, maxWidth)}px`;

      const pr = poster.getBoundingClientRect();
      const bannerTopRaw = (BANNER_ANCHOR === 'poster' && poster)
        ? (pr.top - hdr.top) + POSTER_TOP_OFFSET
        : BANNER_TOP_OFFSET;
      const top = clamp(bannerTopRaw, MIN_BANNER_TOP, MAX_BANNER_TOP);
      banner.style.top = `${top}px`;

      box.classList.remove('asbm-ml');
      box.style.setProperty('--asbm-line-clamp', '1');
      box.style.whiteSpace = 'nowrap';
      box.style.fontSize = '';

      requestAnimationFrame(() => {
        if (box.scrollWidth > box.clientWidth){
          if (TITLE_MAX_LINES > 1){
            box.classList.add('asbm-ml');
            box.style.setProperty('--asbm-line-clamp', String(TITLE_MAX_LINES));
          } else if (AUTO_FIT_ONE_LINE){
            autoFitOneLine(box);
          }
        }

        const bh = banner.getBoundingClientRect().height || 0;
        const pad = Math.min(Math.max(top + bh + BOTTOM_GAP, 0), MAX_HEADER_PADDING);
        header.style.paddingTop = `${pad}px`;
      });
    }catch(_){}
  }

  /* ========= ОКРАШИВАНИЕ + SPA ========= */
  const BLACK = [
    'body', '.wrapper-as', '.wrapper-main', 'footer', '.page-padding',
    '.ncards', '.carou', '.sect__header', '.content', 'main',
    '.sect', '.footer', '.menu', '.desc', '.page__content', '.sect__padding',
    'aside.col-side', '.col-side',
    'header.header',
    '.anime-cards', '.anime-cards.anime-cards--full-page',
    '.nclub__top-carou', '.nclub__sect', '.sect__content',
    '.remelt', '.remelt__inner', '.remelt__inventory',
    '.card-filter-list', '.card-stars-list',
    '.ncard__menu-content', '.ncard__users-toplist',
    '.ncard__shop-content', '.ncard__shop-content-list', '.ncard__shop-content-header',
    '.dpm-container-empty', '.dpm-dialog', '.dpm-ignore-content', '.dpm-overlay',
    '.dpm-editor-wrapper', '.dpm-dialog-editor-place',
    '#alertsDropdownList', '.menus',
    '#anime-player__controls', '.pmovie_player-controls', '.pmovie__player-controls',
    '.tabs-block__select', '.b-translators__block',
    '.trade__main-items', '.trade_inventory', '.trade_inventory-list',
    '.trade_main', '.trade_main_user', '.trade_controls', '.trade__container', '.trade__wrapper',
    '.trade__main', '.trade__main-user', '.trade__main-divider', '.trade_main-items', '.trade_main-divider',
    '.history', '.noffer__bg',
    'nav.filter-blockcat', '.flex-row-cat'
  ].join(',');

  const TRANSPARENT = [
    '#asbm_bar', '#asbm_container', '.speedbar',
    'header + .page-padding', '.topline', '.breadcrumbs', '.toolbar',
    '.pcoln__header', '.pcoln_header'
  ].join(',');

  function paint(el){
    if(!el || el.nodeType!==1 || el.dataset.asbmDarkApplied==='1') return;
    el.style.setProperty('background','#000','important');
    el.style.setProperty('background-color','#000','important');
    el.style.setProperty('background-image','none','important');
    el.dataset.asbmDarkApplied='1';
  }
  function transparent(el){
    if(!el || el.nodeType!==1) return;
    el.style.setProperty('background','transparent','important');
    el.style.setProperty('background-color','transparent','important');
    el.style.setProperty('background-image','none','important');
    el.style.setProperty('box-shadow','none','important');
    el.style.setProperty('border-color','transparent','important');
    el.dataset.asbmDarkApplied='1';
  }

  function applyIn(root){
    try{ if(root.matches && root.matches(TRANSPARENT)) transparent(root); }catch(_){}
    root.querySelectorAll?.(TRANSPARENT).forEach(transparent);
    try{ if(root.matches && root.matches(BLACK)) paint(root); }catch(_){}
    root.querySelectorAll?.(BLACK).forEach(paint);

    // рамка у блока тегов
    root.querySelectorAll?.('nav.filter-blockcat + div').forEach(div=>{
      div.style.setProperty('border','0','important');
      div.style.setProperty('border-top','0','important');
      div.style.setProperty('background','#000','important');
      div.style.setProperty('background-image','none','important');
    });

    ensureTitleBanner(root);
  }

  applyIn(document);

  // rAF-батчинг для SPA
  const queue = new Set();
  let scheduled = false;
  const flush = () => { scheduled=false; queue.forEach(n=>applyIn(n)); queue.clear(); };

  const mo = new MutationObserver(muts => {
    for (const m of muts) for (const n of m.addedNodes)
      if (n && n.nodeType===1) queue.add(n);
    if (!scheduled){ scheduled=true; requestAnimationFrame(flush); }
  });
  mo.observe(document.documentElement, { childList:true, subtree:true });

  addEventListener('resize', () => {
    const header = document.querySelector('.pcoln__header, .pcoln_header');
    const banner = header?.querySelector?.('.asbm-title-banner');
    const box    = banner?.querySelector?.('.asbm-title-box');
    if (header && banner && box) positionBanner(header, banner, box, document);
  });

  addEventListener('popstate', () => requestAnimationFrame(() => applyIn(document)));
  addEventListener('pageshow',  () => requestAnimationFrame(() => applyIn(document)));
})();