Miglioramento avanzato di GreasyFork e SleazyFork: interfaccia moderna, preferiti con un clic, anteprima dettagliata degli script, barra di modifica avanzata, pulsante di installazione diretta, tema chiaro/scuro, navigazione ottimizzata e molto altro.
// ==UserScript==
// @name GreasyFork Premium
// @name:zh-CN GreasyFork 高级版
// @name:zh-TW GreasyFork 高級版
// @name:hi GreasyFork प्रीमियम
// @name:es GreasyFork Premium
// @name:ar GreasyFork بريميوم
// @name:fr GreasyFork Premium
// @name:bn GreasyFork প্রিমিয়াম
// @name:pt GreasyFork Premium
// @name:ru GreasyFork Premium
// @name:ja GreasyFork プレミアム
// @name:ur GreasyFork پریمیم
// @name:ml GreasyFork പ്രീമിയം
// @name:tr GreasyFork Premium
// @name:it GreasyFork Premium
// @name:th GreasyFork Premium
// @name:de GreasyFork Premium
// @name:ko GreasyFork 프리미엄
// @name:pl GreasyFork Premium
// @name:nl GreasyFork Premium
// @name:sv GreasyFork Premium
// @name:ro GreasyFork Premium
// @name:vi GreasyFork Premium
// @name:id GreasyFork Premium
// @name:ms GreasyFork Premium
// @description Advanced GreasyFork and SleazyFork enhancement: modern UI, one-click favorites, direct install button, detailed script previews, enhanced editor toolbar, light/dark theme, optimized navigation, and much more.
// @description:zh-CN GreasyFork 和 SleazyFork 高级增强:现代化界面、一键收藏、直接安装按钮、脚本详细预览、增强编辑工具栏、浅色/深色主题、优化导航等更多功能。
// @description:zh-TW GreasyFork 和 SleazyFork 高級強化:現代化介面、一鍵收藏、直接安裝按鈕、腳本詳細預覽、增強編輯工具列、淺色/深色主題、最佳化導航及更多功能。
// @description:hi GreasyFork और SleazyFork के लिए उन्नत सुधार: आधुनिक इंटरफ़ेस, एक-क्लिक पसंदीदा, सीधे इंस्टॉल बटन, विस्तृत स्क्रिप्ट पूर्वावलोकन, उन्नत संपादन टूलबार, लाइट/डार्क थीम, अनुकूलित नेविगेशन और बहुत कुछ।
// @description:es Mejora avanzada de GreasyFork y SleazyFork: interfaz moderna, favoritos en un clic, botón de instalación directa, vista previa detallada de scripts, barra de edición mejorada, tema claro/oscuro, navegación optimizada y mucho más.
// @description:ar تحسين متقدم لـ GreasyFork وSleazyFork: واجهة حديثة، مفضلة بنقرة واحدة، زر تثبيت مباشر، معاينة مفصلة للسكربتات، شريط تحرير محسّن، وضع فاتح/داكن، تنقل محسن وأكثر من ذلك.
// @description:fr Amélioration avancée de GreasyFork et SleazyFork : interface modernisée, favoris en un clic, bouton d’installation direct, aperçu détaillé des scripts, barre d’édition enrichie, thème clair/sombre, navigation optimisée et bien plus encore.
// @description:bn GreasyFork এবং SleazyFork-এর উন্নত সংস্করণ: আধুনিক ইন্টারফেস, এক-ক্লিক ফেভারিট, বিস্তারিত স্ক্রিপ্ট প্রিভিউ, উন্নত এডিটর টুলবার, সরাসরি ইনস্টল বাটন, লাইট/ডার্ক থিম, অপ্টিমাইজড নেভিগেশন এবং আরও অনেক কিছু।
// @description:pt Melhoria avançada do GreasyFork e SleazyFork: interface moderna, favoritos com um clique, botão de instalação direta, pré-visualização detalhada de scripts, barra de edição aprimorada, tema claro/escuro, navegação otimizada e muito mais.
// @description:ru Расширенное улучшение GreasyFork и SleazyFork: современный интерфейс, избранное в один клик, подробный просмотр скриптов, улучшенная панель редактирования, кнопка быстрой установки, светлая/тёмная тема, оптимизированная навигация и многое другое.
// @description:ja GreasyFork と SleazyFork の高度な改善:モダンなUI、ワンクリックお気に入り、詳細なスクリプトプレビュー、強化された編集ツールバー、直接インストールボタン、ライト/ダークテーマ、最適化されたナビゲーションなど多数。
// @description:ur GreasyFork اور SleazyFork کے لیے جدید بہتری: ماڈرن انٹرفیس، ایک کلک فیورٹس، تفصیلی اسکرپٹ پیش نظارہ، بہتر ایڈیٹر ٹول بار، ڈائریکٹ انسٹال بٹن، لائٹ/ڈارک تھیم، بہتر نیویگیشن اور بہت کچھ۔
// @description:ml GreasyFork, SleazyFork എന്നിവയ്ക്കായുള്ള മെച്ചപ്പെട്ട പതിപ്പ്: ആധുനിക UI, ഒറ്റ ക്ലിക്ക് ഫേവറിറ്റുകൾ, വിശദമായ സ്ക്രിപ്റ്റ് പ്രിവ്യൂ, മെച്ചപ്പെടുത്തിയ എഡിറ്റർ ടൂൾബാർ, നേരിട്ടുള്ള ഇൻസ്റ്റാൾ ബട്ടൺ, ലൈറ്റ്/ഡാർക്ക് തീം, മെച്ചപ്പെടുത്തിയ നാവിഗേഷൻ എന്നിവയും കൂടുതൽ സൗകര്യങ്ങളും.
// @description:tr GreasyFork ve SleazyFork için gelişmiş geliştirme: modern arayüz, tek tık favoriler, ayrıntılı betik önizlemeleri, geliştirilmiş düzenleme araç çubuğu, doğrudan yükleme butonu, açık/koyu tema, optimize edilmiş gezinme ve çok daha fazlası.
// @description:it Miglioramento avanzato di GreasyFork e SleazyFork: interfaccia moderna, preferiti con un clic, anteprima dettagliata degli script, barra di modifica avanzata, pulsante di installazione diretta, tema chiaro/scuro, navigazione ottimizzata e molto altro.
// @description:th การปรับปรุง GreasyFork และ SleazyFork ขั้นสูง: อินเทอร์เฟซทันสมัย รายการโปรดคลิกเดียว ดูตัวอย่างสคริปต์แบบละเอียด แถบเครื่องมือแก้ไขที่ปรับปรุง ปุ่มติดตั้งทันที โหมดสว่าง/มืด การนำทางที่ปรับให้เหมาะสม และอีกมากมาย
// @description:de Erweiterte Verbesserung für GreasyFork und SleazyFork: moderne Benutzeroberfläche, Favoriten mit einem Klick, detaillierte Skriptvorschau, erweiterte Bearbeitungsleiste, direkter Installationsbutton, Hell/Dunkel-Modus, optimierte Navigation und vieles mehr.
// @description:ko GreasyFork 및 SleazyFork 고급 개선: 현대적인 UI, 원클릭 즐겨찾기, 상세 스크립트 미리보기, 향상된 편집 도구 모음, 직접 설치 버튼, 라이트/다크 테마, 최적화된 탐색 및 다양한 추가 기능.
// @description:pl Zaawansowane ulepszenie GreasyFork i SleazyFork: nowoczesny interfejs, ulubione jednym kliknięciem, szczegółowy podgląd skryptów, ulepszony pasek edycji, przycisk bezpośredniej instalacji, tryb jasny/ciemny, zoptymalizowana nawigacja i wiele więcej.
// @description:nl Geavanceerde verbetering voor GreasyFork en SleazyFork: moderne interface, favorieten met één klik, gedetailleerde scriptvoorbeelden, verbeterde bewerkingsbalk, directe installatieknop, licht/donker thema, geoptimaliseerde navigatie en nog veel meer.
// @description:sv Avancerad förbättring för GreasyFork och SleazyFork: modernt gränssnitt, favoriter med ett klick, detaljerad skriptförhandsvisning, förbättrat redigeringsverktygsfält, direkt installationsknapp, ljust/mörkt tema, optimerad navigering och mycket mer.
// @description:ro Îmbunătățire avansată pentru GreasyFork și SleazyFork: interfață modernă, favorite cu un singur clic, previzualizare detaliată a scripturilor, bară de editare îmbunătățită, buton de instalare directă, temă deschis/închis, navigare optimizată și multe altele.
// @description:vi Nâng cấp nâng cao cho GreasyFork và SleazyFork: giao diện hiện đại, yêu thích một lần nhấp, xem trước chi tiết tập lệnh, thanh công cụ chỉnh sửa nâng cao, nút cài đặt trực tiếp, chế độ sáng/tối, điều hướng tối ưu và nhiều hơn nữa.
// @description:id Peningkatan lanjutan untuk GreasyFork dan SleazyFork: antarmuka modern, favorit sekali klik, pratinjau skrip terperinci, bilah alat editor yang ditingkatkan, tombol instal langsung, tema terang/gelap, navigasi yang dioptimalkan, dan banyak lagi.
// @description:ms Penambahbaikan lanjutan untuk GreasyFork dan SleazyFork: antara muka moden, kegemaran satu klik, pratonton skrip terperinci, bar alat editor yang dipertingkatkan, butang pemasangan terus, tema terang/gelap, navigasi dioptimumkan dan banyak lagi.
// @icon https://raw.githubusercontent.com/DREwX-code/greasyfork-premium/refs/heads/main/assets/icon/logo-greasyfork-premium.png
// @namespace https://github.com/DREwX-code/greasyfork-premium
// @version 1.2.0
// @author Dℝ∃wX
// @copyright 2026 DℝᴇwX
// @license Apache-2.0
// @tag Productivity
// @match https://greasyfork.org/*
// @match https://sleazyfork.org/*
// @run-at document-start
// @grant none
// ==/UserScript==
/*
Copyright 2026 Dℝ∃wX
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
---
Third-Party Libraries:
This project uses Highlight.js for syntax highlighting.
Website: https://highlightjs.org/
Source code: https://github.com/highlightjs/highlight.js
License: BSD 3-Clause
---
*/
(function () {
'use strict';
if (window.top !== window.self) {
return;
}
const STORAGE_KEY = 'gfplus-theme';
const SIDEBAR_GROUP_STATE_KEY = 'gfplus-sidebar-group-states';
const LOADING_ATTR = 'data-gfplus-loading';
const INTERNAL_NAV_FLAG_KEY = 'gfplus-internal-nav';
const INTERNAL_LOADING_ATTR = 'data-gfplus-internal-loading';
const HANDHELD_ATTR = 'data-gfplus-handheld';
const BOOTSTRAP_THEME_SCRIPT_ID = 'gfplus-bootstrap-theme';
const NO_TRANSITION_STYLE_ID = 'gfplus-no-transition';
const THEME_STYLE_ID = 'gfplus-theme-style';
const DARK_THEME_STYLE_ID = 'gfplus-theme-style-dark';
const THEME_MOTION_STYLE_ID = 'gfplus-theme-motion-style';
const THEME_MOTION_ATTR = 'data-gfplus-theme-motion';
const THEME_FALLBACK_MOTION_ATTR = 'data-gfplus-theme-fallback-motion';
const SAFARI_ATTR = 'data-gfplus-safari';
const LIGHTBOX_SCROLL_LOCK_CLASS = 'gfplus-lightbox-open';
const THEME_MOTION_DURATION = 380;
let currentTheme = localStorage.getItem(STORAGE_KEY) || 'light';
let internalNavigation = false;
let themeMotionTimer = 0;
const root = document.documentElement;
const THEME_COLORS = {
light: {
background: '#f5f7fb',
text: '#111827',
chartBackground: '#61a5fa',
chartBorder: '#61a5fa',
chartGrid: '#dbe4f0',
chartText: '#334155'
},
dark: {
background: '#0b111a',
text: '#e5e7eb',
chartBackground: '#61a5fa',
chartBorder: '#61a5fa',
chartGrid: '#263449',
chartText: '#cbd5e1'
}
};
const isSafariBrowser = () => {
const userAgent = navigator.userAgent || '';
return /Safari/i.test(userAgent) && !/Chrome|Chromium|CriOS|FxiOS|Edg|OPR|Opera|Android/i.test(userAgent);
};
if (root && isSafariBrowser()) {
root.setAttribute(SAFARI_ATTR, 'true');
}
const applyRootTheme = (theme) => {
if (!root) {
return;
}
const colors = THEME_COLORS[theme] || THEME_COLORS.light;
root.setAttribute('data-theme', theme);
root.style.colorScheme = theme;
root.style.backgroundColor = colors.background;
root.style.color = colors.text;
root.style.setProperty('--gfplus-preload-bg', colors.background);
root.style.setProperty('--gfplus-preload-text', colors.text);
root.style.setProperty('--chart-background-color', colors.chartBackground);
root.style.setProperty('--chart-border-color', colors.chartBorder);
root.style.setProperty('--install-stats-bar-color', colors.chartBackground);
root.style.setProperty('--install-stats-bar-hover-color', colors.chartBorder);
root.style.setProperty('--install-stats-grid-color', colors.chartGrid);
root.style.setProperty('--install-stats-text-color', colors.chartText);
};
const isPhoneDevice = () => {
if (navigator.userAgentData?.mobile) {
return true;
}
const userAgent = navigator.userAgent || '';
return /Android.+Mobile|iPhone|iPod|Windows Phone|webOS|BlackBerry|Opera Mini|Mobile Firefox/i.test(userAgent);
};
const syncHandheldMode = () => {
if (!root) {
return;
}
if (isPhoneDevice()) {
root.setAttribute(HANDHELD_ATTR, 'true');
} else {
root.removeAttribute(HANDHELD_ATTR);
}
};
const appendStyle = (styleEl) => {
const target = document.head || root;
target.appendChild(styleEl);
};
const prependCriticalStyle = (styleEl) => {
if (!root) {
appendStyle(styleEl);
return;
}
root.prepend(styleEl);
};
const buildThemeMotionCss = () => `
html[${THEME_MOTION_ATTR}]::view-transition-group(root) {
animation-duration: 360ms;
animation-timing-function: cubic-bezier(.22, 1, .36, 1);
}
html[${THEME_MOTION_ATTR}]::view-transition-old(root),
html[${THEME_MOTION_ATTR}]::view-transition-new(root) {
mix-blend-mode: normal;
}
html[${THEME_FALLBACK_MOTION_ATTR}],
html[${THEME_FALLBACK_MOTION_ATTR}] body,
html[${THEME_FALLBACK_MOTION_ATTR}] body *,
html[${THEME_FALLBACK_MOTION_ATTR}] body *::before,
html[${THEME_FALLBACK_MOTION_ATTR}] body *::after {
transition-property: background, background-color, color, border-color, box-shadow, text-decoration-color, fill, stroke, outline-color !important;
transition-duration: 340ms !important;
transition-delay: 0ms !important;
transition-timing-function: cubic-bezier(.22, 1, .36, 1) !important;
}
@media (prefers-reduced-motion: reduce) {
html[${THEME_MOTION_ATTR}]::view-transition-group(root) {
animation-duration: .01ms;
}
html[${THEME_FALLBACK_MOTION_ATTR}],
html[${THEME_FALLBACK_MOTION_ATTR}] body,
html[${THEME_FALLBACK_MOTION_ATTR}] body *,
html[${THEME_FALLBACK_MOTION_ATTR}] body *::before,
html[${THEME_FALLBACK_MOTION_ATTR}] body *::after {
transition-duration: .01ms !important;
}
}
`;
const buildCriticalLoadingCss = () => `
html[${LOADING_ATTR}] {
background: var(--gfplus-preload-bg, #f5f7fb) !important;
color: var(--gfplus-preload-text, #111827) !important;
}
html[${LOADING_ATTR}] body {
background: transparent !important;
color: inherit !important;
}
html[${LOADING_ATTR}] *,
html[${LOADING_ATTR}] *::before,
html[${LOADING_ATTR}] *::after {
transition: none !important;
animation: none !important;
}
html[${LOADING_ATTR}] body > :not(#main-header):not(script):not(style) {
visibility: hidden !important;
opacity: 0 !important;
}
html[${LOADING_ATTR}][${HANDHELD_ATTR}] body,
html[${LOADING_ATTR}][${HANDHELD_ATTR}] body > :not(script):not(style),
html[${LOADING_ATTR}][${HANDHELD_ATTR}][${INTERNAL_LOADING_ATTR}] body,
html[${LOADING_ATTR}][${HANDHELD_ATTR}][${INTERNAL_LOADING_ATTR}] body > :not(script):not(style) {
visibility: hidden !important;
opacity: 0 !important;
}
`;
applyRootTheme(currentTheme);
syncHandheldMode();
if (root) {
root.setAttribute(LOADING_ATTR, 'true');
}
const noTransitionStyle = document.createElement('style');
noTransitionStyle.id = NO_TRANSITION_STYLE_ID;
noTransitionStyle.textContent = buildCriticalLoadingCss();
prependCriticalStyle(noTransitionStyle);
const themeMotionStyle = document.createElement('style');
themeMotionStyle.id = THEME_MOTION_STYLE_ID;
themeMotionStyle.textContent = buildThemeMotionCss();
appendStyle(themeMotionStyle);
try {
internalNavigation = sessionStorage.getItem(INTERNAL_NAV_FLAG_KEY) === '1';
if (internalNavigation) {
sessionStorage.removeItem(INTERNAL_NAV_FLAG_KEY);
root.setAttribute(INTERNAL_LOADING_ATTR, 'true');
}
} catch (error) {
internalNavigation = false;
}
const bootstrapThemeScript = document.createElement('script');
bootstrapThemeScript.id = BOOTSTRAP_THEME_SCRIPT_ID;
bootstrapThemeScript.textContent = `
(() => {
try {
const theme = localStorage.getItem(${JSON.stringify(STORAGE_KEY)}) || 'light';
const root = document.documentElement;
if (!root) return;
const colors = theme === 'dark'
? {
background: '#0b111a',
text: '#e5e7eb',
chartBackground: '#61a5fa',
chartBorder: '#61a5fa',
chartGrid: '#263449',
chartText: '#cbd5e1'
}
: {
background: '#f5f7fb',
text: '#111827',
chartBackground: '#61a5fa',
chartBorder: '#61a5fa',
chartGrid: '#dbe4f0',
chartText: '#334155'
};
root.setAttribute('data-theme', theme);
root.style.colorScheme = theme;
root.style.backgroundColor = colors.background;
root.style.color = colors.text;
root.style.setProperty('--gfplus-preload-bg', colors.background);
root.style.setProperty('--gfplus-preload-text', colors.text);
root.style.setProperty('--chart-background-color', colors.chartBackground);
root.style.setProperty('--chart-border-color', colors.chartBorder);
root.style.setProperty('--install-stats-bar-color', colors.chartBackground);
root.style.setProperty('--install-stats-bar-hover-color', colors.chartBorder);
root.style.setProperty('--install-stats-grid-color', colors.chartGrid);
root.style.setProperty('--install-stats-text-color', colors.chartText);
} catch (error) {}
})();
`;
(root || document.head).prepend(bootstrapThemeScript);
bootstrapThemeScript.remove();
const rootThemeObserver = new MutationObserver(() => {
if (root.getAttribute('data-theme') !== currentTheme) {
applyRootTheme(currentTheme);
}
});
rootThemeObserver.observe(root, {
attributes: true,
attributeFilter: ['data-theme']
});
window.addEventListener('resize', syncHandheldMode, { passive: true });
const markInternalNavigation = () => {
internalNavigation = true;
root.setAttribute(LOADING_ATTR, 'true');
root.setAttribute(INTERNAL_LOADING_ATTR, 'true');
applyRootTheme(currentTheme);
try {
sessionStorage.setItem(INTERNAL_NAV_FLAG_KEY, '1');
} catch (error) { }
};
const isInternalPageNavigation = (href) => {
try {
const destination = new URL(href, window.location.href);
if (!/^https?:$/.test(destination.protocol)) {
return false;
}
if (destination.origin !== window.location.origin) {
return false;
}
const onlyHashChange = destination.pathname === window.location.pathname
&& destination.search === window.location.search
&& destination.hash
&& destination.hash !== window.location.hash;
return !onlyHashChange;
} catch (error) {
return false;
}
};
document.addEventListener('click', (event) => {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
return;
}
const link = event.target.closest('a[href]');
if (!link) {
return;
}
const href = link.getAttribute('href');
if (!href || href.startsWith('#') || href.startsWith('javascript:')) {
return;
}
if (link.target && link.target !== '_self') {
return;
}
if (isInternalPageNavigation(link.href)) {
markInternalNavigation();
}
}, true);
// ============================================================================
// Light Theme
// ============================================================================
const LIGHT_CSS = `
:root {
color-scheme: light;
--font-family-base: "Inter", "Open Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-family-monospace: "JetBrains Mono", "Fira Code", "Source Code Pro", monospace;
--overall-background-color: #f5f7fb;
--overall-text-color: #111827;
--link-color: #4f46e5;
--link-visited-color: #4338ca;
--texty-link-visited-color: #4b5563;
--content-background-color: #ffffff;
--content-border-color: #e2e8f0;
--content-box-shadow-color: rgba(15, 23, 42, 0.08);
--content-separator-color: #edf1f7;
--tab-active-background-color: rgba(79, 70, 229, 0.12);
--tab-active-box-shadow-color: rgba(79, 70, 229, 0.18);
--tab-active-top-border-color: #4f46e5;
--inactive-item-background-color: #f3f4f6;
--code-background-color: #f4f2ff;
--user-content-background-color-gradient-1: #f8fafc;
--user-content-background-color-gradient-2: #ffffff;
--user-content-border-left-color: #e2e8f0;
--list-option-background-color-gradient-1: #ffffff;
--list-option-background-color-gradient-2: #f5f7fb;
--list-option-hover-background-color-gradient-1: #f4f7ff;
--list-option-hover-background-color-gradient-2: #e1e7ff;
--list-option-hover-box-shadow-top: rgba(15, 23, 42, 0.06);
--list-option-hover-box-shadow-bottom: rgba(79, 70, 229, 0.1);
--notice-background-color: #e0f2fe;
--notice-border-color: #0284c7;
--notice-text-color: #0f172a;
--alert-background-color: #fef3c7;
--alert-border-color: #f59e0b;
--alert-text-color: #78350f;
--chart-background-color: #61a5fa;
--chart-border-color: #61a5fa;
--install-stats-bar-color: #61a5fa;
--install-stats-bar-hover-color: #61a5fa;
--install-stats-grid-color: #dbe4f0;
--install-stats-text-color: #334155;
--highlight-background-color: #fef9c3;
--rating-icon-good-border-color: #16a34a;
--rating-icon-good-background-color: rgba(22, 163, 74, 0.12);
--rating-icon-good-color: #166534;
--rating-icon-ok-border-color: #ca8a04;
--rating-icon-ok-background-color: rgba(202, 138, 4, 0.14);
--rating-icon-ok-color: #92400e;
--rating-icon-bad-border-color: #dc2626;
--rating-icon-bad-background-color: rgba(220, 38, 38, 0.12);
--rating-icon-bad-color: #7f1d1d;
--expander-color: #4f46e5;
--expander-background-color: rgba(79, 70, 229, 0.08);
--pagination-background-color: rgba(79, 70, 229, 0.08);
--pagination-hover-background-color: rgba(79, 70, 229, 0.18);
--diff-del-background: #fee2e2;
--diff-del-color: #b91c1c;
--diff-ins-background: #dcfce7;
--diff-ins-color: #047857;
--diff-del-strong-background: #fecaca;
--diff-ins-strong-background: #bbf7d0;
--diff-block-info: #64748b;
--list-option-button-background-color: #ffffff;
--list-option-button-color: #0f172a;
--list-option-button-border-color: #d0d5dd;
--list-option-button-background-color-gradient-1: #ffffff;
--list-option-button-background-color-gradient-2: #f5f7fb;
--code-container-border-color: #e2e8f0;
--prettyprint-background-color: #ffffff;
--prettyprint-color: #111827;
--sidebar-background: #ffffff;
--close-sidebar-background: #f1f5f9;
--close-sidebar-border-bottom: #cbd5f5;
--border-radius-small: 6px;
--border-radius-medium: 12px;
--border-radius-large: 18px;
--shadow-soft: 0 6px 20px rgba(15, 23, 42, 0.07);
--shadow-hover: 0 8px 24px rgba(15, 23, 42, 0.1);
--container-glow-stroke: rgba(79, 70, 229, 0.24);
--container-glow-color: rgba(79, 70, 229, 0.08);
--hljs-bg: #ffffff;
--hljs-bg-alt: #f4f7fb;
--hljs-line-height: 24px;
--hljs-font-size: 14px;
--hljs-border: #e2e8f0;
--hljs-text: #0f172a;
--hljs-line-number: #94a3b8;
--hljs-comment: #64748b;
--hljs-keyword: #6d28d9;
--hljs-number: #b45309;
--hljs-string: #15803d;
--hljs-title: #1d4ed8;
--hljs-attr: #c2410c;
--hljs-tag: #0f766e;
--hljs-meta: #475569;
--hljs-add-bg: #dcfce7;
--hljs-add-text: #14532d;
--hljs-del-bg: #fee2e2;
--hljs-del-text: #7f1d1d;
--focus-ring-color: rgba(79, 70, 229, 0.45);
--transition-base: 160ms ease;
}
/* Light mode scrollbar styling only */
:root {
scrollbar-color: #c7d2fe #f5f7fb;
}
::-webkit-scrollbar {
width: 12px;
height: 12px;
}
::-webkit-scrollbar-track {
background: linear-gradient(180deg, #f5f7fb, #eef2ff);
border-radius: 999px;
}
::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #a5b4fc, #6366f1);
border-radius: 999px;
border: 3px solid #f5f7fb;
box-shadow: inset 0 0 0 1px rgba(79, 70, 229, 0.3);
}
::-webkit-scrollbar-thumb:hover {
background: linear-gradient(180deg, #818cf8, #4f46e5);
}
*,*::before,*::after {
box-sizing: border-box;
}
::selection {
background-color: #B4D8FF;
}
@media (prefers-reduced-motion: reduce) {
*,*::before,*::after {
animation-duration: .01ms!important;
animation-iteration-count: 1!important;
transition-duration: .01ms!important;
scroll-behavior: auto!important;
}
}
html {
overflow-y: scroll;
scroll-behavior: smooth;
background-color: var(--overall-background-color);
}
body {
margin: 0;
min-height: 100vh;
background: var(--overall-background-color);
color: var(--overall-text-color);
line-height: 1.6;
font-size: 16px;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
transition: background-color var(--transition-base), color var(--transition-base);
}
body,select,input {
font-family: var(--font-family-base);
letter-spacing: .01em;
transition: color var(--transition-base), background-color var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base);
}
body:lang(zh-CN),select:lang(zh-CN),input:lang(zh-CN) {
font-family: "Noto Sans SC","Microsoft YaHei UI",var(--font-family-base)
}
body:lang(zh-TW),select:lang(zh-TW),input:lang(zh-TW) {
font-family: "Noto Sans TC","Microsoft JHengHei UI",var(--font-family-base)
}
pre,code {
direction: ltr!important;
font-family: var(--font-family-monospace)
}
code {
background-color: var(--code-background-color);
border-radius: var(--border-radius-small);
padding: .15em .4em
}
pre {
margin: 0;
padding: 1em;
background-color: var(--code-background-color);
border-radius: var(--border-radius-medium);
box-shadow: inset 0 0 0 1px rgba(79, 70, 229, .08);
overflow-x: auto
}
pre code {
background-color: transparent;
padding: 0
}
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=image]):not([type=file]),select,textarea {
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
padding: .6em .7em;
font: inherit;
box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
transition: border-color var(--transition-base), box-shadow var(--transition-base), background-color var(--transition-base);
}
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=image]):not([type=file]):focus,select:focus,textarea:focus {
border-color: var(--link-color);
box-shadow: 0 0 0 0 rgba(79, 70, 229, .15);
outline: none;
}
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=image]):not([type=file]):focus-visible,select:focus-visible,textarea:focus-visible {
outline: none;
border-color: var(--link-visited-color);
box-shadow: 0 0 0 0 var(--focus-ring-color);
}
input[disabled],select[disabled],textarea[disabled] {
background-color: rgba(148, 163, 184, .15);
cursor: not-allowed;
opacity: .7
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button),input[type=submit]:not(.search-submit),input[type=submit].search-submit:not([value="🔎"]),input[type=button],.button {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 2.45rem;
max-width: 100%;
margin: .25rem .35rem .25rem 0;
margin-inline: 0 .35rem;
border: 1px solid rgba(79, 70, 229, .35);
border-radius: 8px;
padding: .64em 1.05em;
background: linear-gradient(180deg, #6366f1, #4f46e5);
color: #ffffff;
font-weight: 700;
line-height: 1.2;
letter-spacing: .01em;
cursor: pointer;
box-shadow: none;
text-decoration: none;
white-space: normal;
transition: transform var(--transition-base), box-shadow var(--transition-base), background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):hover,input[type=submit]:not(.search-submit):hover,input[type=submit].search-submit:not([value="🔎"]):hover,input[type=button]:hover,.button:hover,button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):focus,input[type=submit]:not(.search-submit):focus,input[type=submit].search-submit:not([value="🔎"]):focus,input[type=button]:focus,.button:focus {
background: linear-gradient(180deg, #7c83ff, #4338ca);
border-color: rgba(67, 56, 202, .55);
box-shadow: none;
transform: translateY(-1px);
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):active,input[type=submit]:not(.search-submit):active,input[type=submit].search-submit:not([value="🔎"]):active,input[type=button]:active,.button:active {
transform: translateY(0);
box-shadow: 0 7px 18px rgba(79, 70, 229, .2), inset 0 1px 2px rgba(15, 23, 42, .2);
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):disabled,input[type=submit]:not(.search-submit):disabled,input[type=submit].search-submit:not([value="🔎"]):disabled,input[type=button]:disabled,.button:disabled {
opacity: .65;
box-shadow: none;
cursor: not-allowed;
transform: none
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):focus-visible,input[type=submit]:not(.search-submit):focus-visible,input[type=submit].search-submit:not([value="🔎"]):focus-visible,input[type=button]:focus-visible,.button:focus-visible {
outline: 2px solid var(--focus-ring-color);
outline-offset: 3px
}
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button),
.form-control input[type=submit]:not(.search-submit),
.form-control input[type=button] {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 2.55rem;
width: fit-content;
max-width: 100%;
margin: .25rem 0 0;
padding: .68rem 1.05rem;
border: 1px solid rgba(79, 70, 229, .35);
border-radius: 8px;
background: linear-gradient(180deg, #6366f1, #4f46e5);
color: #ffffff;
font-weight: 700;
line-height: 1.2;
letter-spacing: .01em;
box-shadow: none;
text-decoration: none;
white-space: normal
}
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):hover,
.form-control input[type=submit]:not(.search-submit):hover,
.form-control input[type=button]:hover,
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):focus,
.form-control input[type=submit]:not(.search-submit):focus,
.form-control input[type=button]:focus {
background: linear-gradient(180deg, #7c83ff, #4338ca);
border-color: rgba(67, 56, 202, .55);
box-shadow: none;
transform: translateY(-1px)
}
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):active,
.form-control input[type=submit]:not(.search-submit):active,
.form-control input[type=button]:active {
transform: translateY(0);
box-shadow: 0 7px 18px rgba(79, 70, 229, .2), inset 0 1px 2px rgba(15, 23, 42, .2)
}
input.search-submit[value="🔎"] {
color: transparent;
-webkit-text-fill-color: transparent;
text-shadow: none;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23111827' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><line x1='21' y1='21' x2='16.65' y2='16.65'/></svg>") !important;
background-repeat: no-repeat;
background-position: center;
background-size: 16px 16px;
cursor: pointer;
opacity: 1 !important;
}
textarea {
resize: vertical;
min-height: 6em;
background-color: var(--content-background-color)
}
a {
color: var(--link-color);
font-weight: 600;
text-decoration: none;
text-underline-offset: 4px;
text-decoration-thickness: 2px;
transition: color var(--transition-base), text-decoration-color var(--transition-base), opacity var(--transition-base);
}
a:visited {
color: var(--link-visited-color)
}
a:hover,a:focus {
color: var(--link-visited-color);
text-decoration: underline;
text-decoration-color: currentColor
}
a:focus-visible {
outline: 2px solid var(--focus-ring-color);
outline-offset: 3px;
border-radius: var(--border-radius-small)
}
input[type=checkbox],input[type=radio] {
vertical-align: middle;
accent-color: var(--link-color)
}
.form-control input[type=checkbox],
.form-control input[type=radio] {
inline-size: 1rem;
block-size: 1rem;
margin: 0 .45em 0 0;
margin-inline: 0 .45em;
vertical-align: -0.14em;
accent-color: var(--link-color)
}
.form-control input[type=checkbox] + label.radio-label,
.form-control input[type=checkbox] + label.checkbox-label,
.form-control input[type=radio] + label.radio-label,
.form-control input[type=radio] + label.checkbox-label,
.form-control input[type=radio] + label {
display: inline;
margin: 0;
line-height: 1.45;
vertical-align: baseline;
font-size: inherit;
font-weight: 400
}
.width-constraint {
margin: auto;
max-width: 1200px;
width: min(96%, 1200px);
}
@media screen and (max-width: 1228px) {
.width-constraint {
margin:auto 1.2vw;
padding-inline: clamp(.8rem, 4vw, 1.5rem)
}
}
@media screen and (max-width: 400px) {
.width-constraint {
margin:auto 0;
padding-inline: 0
}
}
.inline-list,.block-list {
padding-left: 0;
padding-right: 0;
list-style: none
}
.inline-list {
display: inline
}
.block-list {
display: block;
margin: 0
}
.inline-list li,.block-list li {
display: inline
}
.inline-list li:after,.block-list li:after {
content: ", "
}
body:lang(he) .inline-list li:after,body:lang(he) .block-list li:after,body:lang(ar) .inline-list li:after,body:lang(ar) .block-list li:after,body:lang(ug) .inline-list li:after,body:lang(ug) .block-list li:after,body:lang(ckb) .inline-list li:after,body:lang(ckb) .block-list li:after {
content: "،"
}
.inline-list li:last-child:after,.block-list li:last-child:after {
content: ""
}
dt[title]>span {
border-bottom: 1px dotted black
}
.form-section {
margin-bottom: 2em
}
.form-control {
margin-bottom: 1.4em;
flex-direction: column;
gap: .4em
}
.form-control textarea,#ace-editor {
width: 100%;
box-sizing: border-box;
margin-top: 1px;
margin-bottom: 1px
}
.form-control textarea:not([rows]),#ace-editor {
height: 20em
}
#ace-editor {
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
background-color: var(--content-background-color);
box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
resize: vertical;
transition: border-color var(--transition-base), box-shadow var(--transition-base), background-color var(--transition-base)
}
#ace-editor.ace-tm {
background-color: #ffffff !important;
color: #111827 !important;
border-color: var(--content-border-color) !important;
}
#ace-editor.ace-tm .ace_scroller,
#ace-editor.ace-tm .ace_content {
background-color: #ffffff !important;
}
#ace-editor.ace-tm .ace_gutter {
background: #f8fafc !important;
color: #64748b !important;
border-right: 1px solid #e2e8f0;
}
#ace-editor.ace-tm .ace_print-margin {
display: none !important;
visibility: hidden !important;
}
#ace-editor.ace-tm .ace_cursor {
color: #111827 !important;
}
#ace-editor.ace-tm .ace_marker-layer .ace_active-line,
#ace-editor.ace-tm .ace_gutter-active-line {
background: rgba(79, 70, 229, .08) !important;
}
#ace-editor.ace-tm .ace_marker-layer .ace_selection {
background: rgba(79, 70, 229, .22) !important;
}
#ace-editor.ace-tm .ace_marker-layer .ace_selected-word {
background: rgba(79, 70, 229, .12) !important;
border: 1px solid rgba(79, 70, 229, .35) !important;
}
#ace-editor.ace-tm .ace_fold {
background-color: #4f46e5 !important;
}
#ace-editor.ace-tm .ace_invisible {
color: #cbd5e1 !important;
}
#ace-editor.ace-tm .ace_storage,
#ace-editor.ace-tm .ace_keyword {
color: #6d28d9 !important;
}
#ace-editor.ace-tm .ace_constant,
#ace-editor.ace-tm .ace_constant.ace_numeric {
color: #b45309 !important;
}
#ace-editor.ace-tm .ace_string {
color: #15803d !important;
}
#ace-editor.ace-tm .ace_comment {
color: #64748b !important;
}
#ace-editor.ace-tm .ace_variable,
#ace-editor.ace-tm .ace_support.ace_function,
#ace-editor.ace-tm .ace_entity.ace_name.ace_function {
color: #1d4ed8 !important;
}
#ace-editor.ace-tm .ace_keyword.ace_operator,
#ace-editor.ace-tm .ace_paren,
#ace-editor.ace-tm .ace_punctuation {
color: #334155 !important;
}
#ace-editor.ace-tm .ace_invalid {
background-color: rgba(220, 38, 38, .12) !important;
color: #b91c1c !important;
}
.form-control input:not([type=radio]):not([type=file]):not([type=checkbox]):not([type=search]):not([type=submit]):not([size]) {
box-sizing: border-box;
width: 100%
}
.radio-group input[type=radio] {
inline-size: 1rem;
block-size: 1rem;
margin: 0 .45em 0 1em;
margin-inline: 1em .45em;
vertical-align: -0.14em;
accent-color: var(--link-color)
}
.radio-group input[type=radio] + label {
display: inline;
line-height: 1.45;
vertical-align: baseline
}
.form-control label {
font-weight: 600;
color: var(--overall-text-color);
display: inline-block;
margin-bottom: .4em;
letter-spacing: .01em
}
.form-control label.radio-label,.form-control label.checkbox-label {
font-weight: 400
}
.form-control .enable-source-editor + label.checkbox-label {
display: inline;
margin: 0;
line-height: 1.25;
vertical-align: middle;
}
.form-control .label-note .enable-source-editor {
margin: 0 .35em 0 0;
vertical-align: middle;
}
.form-control select[name*="[additional_info]"][name$="[locale]"] {
width: auto;
max-width: min(100%, 18rem);
padding: .35em .65em;
font-size: .92rem;
}
.form-control textarea[name="script_version[code]"],
textarea[name="script_version[changelog]"],
textarea.comment-entry,
.form-control textarea[name*="[additional_info]"][name$="[attribute_value]"] {
background-color: #f8fafc;
box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08), 0 0 0 1px rgba(79, 70, 229, .04);
}
.form-control textarea[name*="[additional_info]"][name$="[attribute_value]"] {
border-top-left-radius: 0;
}
textarea.comment-entry {
border-top-left-radius: 0;
}
.previewable[data-markup-option-name="script_version[changelog_markup]"] textarea,
.previewable[data-markup-option-name="script_version[changelog_markup]"] .preview-results {
border-top-left-radius: 0;
}
label.subselection-radio-title {
font-weight: 400;
font-size: small;
display: block;
margin-left: 3px
}
.field_with_errors textarea,.field_with_errors input {
background-color: rgba(220, 38, 38, .12);
border-color: var(--rating-icon-bad-border-color);
box-shadow: 0 0 0 0 rgba(220, 38, 38, .12)
}
.label-note {
font-size: smaller;
color: var(--texty-link-visited-color)
}
.label-note.markup-options > a:first-child {
margin-inline-end: .75em
}
.label-note.markup-options label.radio-label {
margin-inline-end: .65em
}
.screenshots-controls>*:not(label) {
padding-left: 1em
}
.add-screenshot-control,.screenshot-control {
clear: left
}
.screenshot-control>* {
vertical-align: middle
}
.screenshot-control a {
float: left;
min-width: 150px;
text-align: center
}
#script-info,.user-list,.text-content,.discussion-list,.notification-list {
padding: clamp(1rem, 2.4vw, 1.5rem)
}
#script-info>*:last-child,.user-list>*:last-child,.text-content>*:last-child,.discussion-list>*:last-child,.notification-list>*:last-child {
margin-bottom: 0
}
.script-list {
padding: 0;
border-radius: var(--border-radius-medium);
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
box-shadow: var(--shadow-soft);
box-sizing: border-box;
margin: 18px 0;
overflow: hidden;
transition: box-shadow var(--transition-base), border-color var(--transition-base), background-color var(--transition-base), transform var(--transition-base)
}
.user-list,.text-content,.discussion-list,.notification-list {
list-style-type: none;
box-shadow: var(--shadow-soft);
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-sizing: border-box;
margin: 18px 0;
padding: clamp(1.15rem, 2vw, 1.6rem);
display: flex;
flex-direction: column;
transition: box-shadow var(--transition-base), border-color var(--transition-base), background-color var(--transition-base), transform var(--transition-base)
}
.script-list:hover,.user-list:hover,.text-content:hover,.discussion-list:hover,.notification-list:hover {
border-color: var(--container-glow-stroke);
box-shadow: var(--shadow-hover);
transform: none
}
.text-content:last-child {
margin-bottom: 0
}
.text-content.text-content-compact {
padding: clamp(.85rem, 1.5vw, 1.2rem);
}
html[data-gfplus-set-editor-page] .text-content > p:first-of-type {
font-size: 1.3rem;
line-height: 1.72;
margin-top: 0;
}
.user-list {
background-image: none
}
.script-link,.script-description,.user-link {
unicode-bidi: isolate
}
.gf-script-logo {
width: 26px;
height: 26px;
aspect-ratio: 1 / 1;
min-width: 26px;
min-height: 26px;
max-width: 26px;
max-height: 26px;
flex: 0 0 26px;
border-radius: 6px;
display: inline-flex;
align-items: center;
justify-content: center;
margin-right: 8px;
vertical-align: text-bottom;
border: 0;
background: transparent;
box-shadow: none;
overflow: hidden;
line-height: 0;
}
img.gf-script-logo {
width: 100%;
height: 100%;
display: block;
object-fit: contain;
object-position: center;
max-width: 100%;
max-height: 100%;
filter: none;
mix-blend-mode: normal;
image-rendering: auto;
}
.gf-script-logo--title {
width: 34px;
height: 34px;
min-width: 34px;
min-height: 34px;
max-width: 34px;
max-height: 34px;
flex-basis: 34px;
margin-right: 10px;
}
.gf-script-logo--fallback {
color: var(--link-color);
}
.gf-script-logo--fallback svg {
width: 16px;
height: 16px;
stroke: currentColor;
}
#script-info header h2,
#script-info > h2 {
display: flex;
align-items: center;
gap: 10px;
}
#script-info header h2 .gf-script-logo,
#script-info > h2 .gf-script-logo {
margin-right: 0;
}
#script-info header h2 .gf-script-logo--fallback svg,
#script-info > h2 .gf-script-logo--fallback svg {
width: 18px;
height: 18px;
}
.list-option-groups~ol {
width: calc(960px - 14em)
}
.text-content .list-option-groups~ol {
width: calc(960px - 16em)
}
@media screen and (max-width: 960px) {
#script-info,.user-list,.text-content {
padding: clamp(.9rem, 4vw, 1.2rem)
}
}
@media screen and (max-width: 400px) {
.script-list,.user-list,.text-content,.discussion-list,.notification-list {
border-left:0;
border-right: 0
}
.user-list,.text-content,.discussion-list,.notification-list,.script-list-description {
padding-left: 1rem;
padding-right: 1rem
}
.discussion-list-header,.user-list-header,.library-list-header {
padding-left: 1em;
padding-right: 1em;
margin-top: 15px;
margin-bottom: 10px
}
#script-info {
padding-left: 1em;
padding-right: 1em
}
#script-links {
margin-left: -1em;
margin-right: -1em;
padding: 0
}
#additional-info {
margin-left: -1em;
margin-right: -1em
}
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) {
border-bottom: 1px solid var(--content-separator-color);
padding: clamp(1rem, 2.5vw, 1.6rem);
display: grid;
min-width: 0;
max-width: 100%;
box-sizing: border-box;
list-style-type: none;
gap: .55rem;
background: linear-gradient(180deg, rgba(79, 70, 229, .02), transparent);
transition: background-color var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):hover {
background: linear-gradient(180deg, rgba(79, 70, 229, .045), rgba(79, 70, 229, .018));
box-shadow: inset 0 0 0 1px rgba(79, 70, 229, .08);
transform: translateY(-1px);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):has(.gf-script-star-button[data-active="true"]) {
background: linear-gradient(90deg, rgba(244, 180, 0, .07), rgba(244, 180, 0, .015) 42%, transparent);
box-shadow: inset 3px 0 rgba(202, 138, 4, .72);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):has(.gf-script-star-button[data-active="true"]):hover {
background: linear-gradient(90deg, rgba(244, 180, 0, .11), rgba(244, 180, 0, .025) 48%, transparent);
box-shadow: inset 3px 0 rgba(202, 138, 4, .9), inset 0 0 0 1px rgba(202, 138, 4, .12);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):last-child {
border-bottom: none
}
.script-list .cf-wrapper {
margin: 0!important
}
@media screen and (max-width: 960px) {
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) {
padding: clamp(.9rem, 4vw, 1.3rem)
}
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 {
margin: 0;
font-size: 1.25rem;
line-height: 1.35;
letter-spacing: .01em;
color: var(--overall-text-color);
display: flex;
flex-wrap: wrap;
align-items: center;
column-gap: 8px;
row-gap: .35em;
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 .gf-script-logo {
flex: 0 0 26px;
margin-right: 0;
align-self: center;
vertical-align: middle;
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 .gf-script-title-content {
display: block;
flex: 1 1 0;
min-width: 0;
max-width: calc(100% - 34px);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 > .script-link,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 .gf-script-title-content .script-link {
min-width: 0;
max-width: 100%;
overflow-wrap: anywhere;
word-break: normal;
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > p {
margin: 0
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > footer {
margin-top: .35em;
display: flex;
flex-wrap: wrap;
gap: .6rem;
font-size: .875rem;
color: var(--texty-link-visited-color)
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > footer a {
font-weight: 500
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article {
min-width: 0;
max-width: 100%;
}
.list-current,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 {
font-weight: 700
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article .description {
font-weight: 400;
display: block;
flex: 0 0 100%;
margin: .5em 0;
font-size: .95rem;
color: var(--texty-link-visited-color)
}
.gf-script-extra-info {
display: none;
min-width: 0;
max-width: 100%;
margin-top: .8rem;
padding-top: .8rem;
border-top: 1px solid var(--content-separator-color);
}
.gf-script-extra-info[data-open="true"] {
display: block;
}
.gf-script-extra-info .user-content ul,
.gf-script-extra-info .user-content ol {
margin-top: .35em;
margin-bottom: .45em;
padding-left: 1.45em;
}
.gf-script-extra-info .user-content li {
display: list-item;
margin: 0;
padding: 0;
border-bottom: 0;
background: transparent;
box-shadow: none;
transform: none;
transition: none;
}
.gf-script-extra-info .user-content li > ul,
.gf-script-extra-info .user-content li > ol {
margin-top: .2em;
margin-bottom: .2em;
}
.gf-script-extra-status {
display: inline-flex;
align-items: center;
gap: .6rem;
min-height: 40px;
max-width: 100%;
box-sizing: border-box;
padding: .65rem .85rem;
border: 1px solid rgba(79, 70, 229, .16);
border-radius: var(--border-radius-small);
background: linear-gradient(180deg, rgba(79, 70, 229, .075), rgba(79, 70, 229, .025));
color: var(--texty-link-visited-color);
font-size: .9rem;
font-weight: 600;
}
.gf-script-extra-status::before {
content: "";
width: 14px;
height: 14px;
flex: 0 0 14px;
border: 2px solid currentColor;
border-right-color: transparent;
border-radius: 999px;
opacity: .72;
animation: gf-script-extra-spin .8s linear infinite;
}
.gf-script-extra-info[data-gfplus-extra-info="loaded"] .gf-script-extra-status::before,
.gf-script-extra-info[data-gfplus-extra-info="error"] .gf-script-extra-status::before {
display: none;
}
@keyframes gf-script-extra-spin {
to {
transform: rotate(360deg);
}
}
.script-list .name-description-separator {
display: none
}
#script-description,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 > a,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article .description {
word-wrap: break-word
}
@media screen and (max-width: 720px) {
.script-list,#script-content {
margin-left:unset
}
}
.pagination,.script-list+.pagination,.user-list+.pagination {
font-size: 1rem;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: .6rem;
background-color: transparent;
padding: 1.1rem 0;
margin: 0;
border-radius: var(--border-radius-small)
}
.pagination>*,.script-list+.pagination>*,.user-list+.pagination>* {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2.6rem;
background-color: var(--pagination-background-color);
padding: .55em .95em;
border-radius: var(--border-radius-small);
text-decoration: none;
border: 1px solid transparent;
color: var(--overall-text-color);
font-weight: 600;
transition: background-color var(--transition-base), color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base)
}
.pagination .disabled {
display: none
}
.pagination .current {
font-style: normal;
font-weight: 700
}
.pagination .current,.pagination .gap {
background-color: transparent;
color: var(--texty-link-visited-color)
}
.pagination .current {
border-color: var(--link-color);
color: var(--link-color);
box-shadow: inset 0 0 0 1px var(--link-color);
background-color: rgba(79, 70, 229, .08)
}
.pagination>a:hover,.pagination>a:focus {
background-color: var(--pagination-hover-background-color);
color: var(--overall-text-color);
transform: translateY(-1px);
box-shadow: 0 10px 20px rgba(79, 70, 229, .18)
}
.pagination>a:focus-visible {
outline: 2px solid var(--focus-ring-color);
outline-offset: 2px
}
@media screen and (max-width: 400px) {
.pagination,.script-list+.pagination,.user-list+.pagination {
padding-left: 1rem;
padding-right: 1rem
}
}
.good-rating-count,.ok-rating-count,.bad-rating-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2.5em;
text-align: center;
padding: .1em .5em;
border-radius: 999px;
font-weight: 600;
font-size: .85rem;
border: 1px solid transparent;
transition: transform var(--transition-base), box-shadow var(--transition-base)
}
.good-rating-count {
background-color: var(--rating-icon-good-background-color);
border-color: var(--rating-icon-good-border-color);
color: var(--rating-icon-good-color)
}
.ok-rating-count {
background-color: var(--rating-icon-ok-background-color);
border-color: var(--rating-icon-ok-border-color);
color: var(--rating-icon-ok-color)
}
.bad-rating-count {
background-color: var(--rating-icon-bad-background-color);
border-color: var(--rating-icon-bad-border-color);
color: var(--rating-icon-bad-color)
}
.select-all,.select-none {
display: none
}
#help-allowed-elements,#help-allowed-styles {
column-width: 20em
}
#help-allowed-elements li,#help-allowed-styles li {
padding-right: 1em
}
#by-site-list {
list-style-type: none;
padding: 0
}
#by-site-list li {
display: inline;
vertical-align: middle
}
#user_profile {
width: 100%;
height: 10em
}
.preview-result {
display: none;
background-color: #ffa;
padding: .5em
}
.failed-sync {
background-color: #fcc
}
.alert {
font-style: normal;
background-color: var(--alert-background-color);
border: 1px solid rgba(245, 158, 11, .25);
border-left: 6px solid var(--alert-border-color);
padding: 1rem 1.1rem;
color: var(--alert-text-color);
border-radius: var(--border-radius-small);
box-shadow: 0 12px 20px rgba(120, 53, 15, .12)
}
.notice,.validation-errors {
background-color: var(--notice-background-color);
border: 1px solid rgba(2, 132, 199, .2);
border-left: 6px solid var(--notice-border-color);
padding: 1rem 1.1rem;
color: var(--notice-text-color);
border-radius: var(--border-radius-small);
box-shadow: 0 12px 20px rgba(15, 23, 42, .08)
}
.validation-errors {
margin: .5em 0
}
.validation-errors>p:first-child {
margin-top: 0
}
.validation-errors>p:last-child {
margin-bottom: 0
}
.alert p,.notice p,.validation-errors p {
margin: 0
}
.alert p+p,.notice p+p,.validation-errors p+p {
margin-top: .6rem
}
#install-stats-chart {
width: 100%;
height: 400px;
background: var(--content-background-color) !important;
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
overflow: hidden
}
#install-stats-chart-container,
#weekly-install-stats-chart-container,
#update-check-stats-chart-container {
width: 100%;
min-height: 320px;
background: var(--content-background-color) !important;
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
overflow: hidden
}
#install-stats-chart-container canvas,
#weekly-install-stats-chart-container canvas,
#update-check-stats-chart-container canvas {
display: block;
max-width: 100%;
}
#install-stats-chart svg text {
fill: var(--install-stats-text-color) !important
}
#install-stats-chart svg line[stroke],
#install-stats-chart svg path[stroke="#cccccc"],
#install-stats-chart svg path[stroke="#e6e6e6"],
#install-stats-chart svg path[stroke="#d9d9d9"] {
stroke: var(--install-stats-grid-color) !important
}
#install-stats-chart svg rect[fill="#ffffff"],
#install-stats-chart svg rect[fill="white"] {
fill: var(--content-background-color) !important
}
.stats-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
overflow: hidden;
box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .04)
}
.stats-table th,.stats-table td {
border: 1px solid var(--content-border-color);
padding: .75rem 1rem;
text-align: left
}
.stats-table th {
background: linear-gradient(180deg, rgba(79, 70, 229, .08), rgba(79, 70, 229, .02));
font-weight: 600;
color: var(--overall-text-color)
}
.stats-table thead tr:first-child th:first-child {
border-start-start-radius: 5px;
overflow: hidden
}
.stats-table thead tr:first-child th:last-child {
border-start-end-radius: 5px;
overflow: hidden
}
.stats-table tbody tr:last-child > * {
border-block-end: 1px solid var(--content-border-color) !important;
border-bottom: 1px solid var(--content-border-color) !important;
background-clip: padding-box
}
.stats-table tbody tr:last-child > *:first-child {
border-inline-start: 1px solid var(--content-border-color) !important;
border-bottom-left-radius: 5px;
border-end-start-radius: 5px;
overflow: hidden
}
.stats-table tbody tr:last-child > *:last-child {
border-inline-end: 1px solid var(--content-border-color) !important;
border-bottom-right-radius: 5px;
border-end-end-radius: 5px;
overflow: hidden
}
body:lang(ar) .stats-table tbody tr:last-child > *:first-child,
body:lang(he) .stats-table tbody tr:last-child > *:first-child,
body:lang(ug) .stats-table tbody tr:last-child > *:first-child,
body:lang(ckb) .stats-table tbody tr:last-child > *:first-child {
border-bottom-left-radius: 0;
border-bottom-right-radius: 5px
}
body:lang(ar) .stats-table tbody tr:last-child > *:last-child,
body:lang(he) .stats-table tbody tr:last-child > *:last-child,
body:lang(ug) .stats-table tbody tr:last-child > *:last-child,
body:lang(ckb) .stats-table tbody tr:last-child > *:last-child {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 0
}
.stats-table tbody tr:hover {
background-color: rgba(79, 70, 229, .06)
}
td.numeric,th.numeric {
text-align: right
}
.translation_missing {
outline: dashed red
}
#edit_user>div {
margin-bottom: .5em
}
#edit_user>div>label:first-child {
font-weight: 700
}
.inline-form {
display: inline
}
a.self-link,a.self-link:visited {
text-decoration: none;
color: #000;
opacity: .2
}
.indented {
padding-left: 1em
}
.external-login {
display: inline-flex !important;
align-items: center;
justify-content: center;
min-height: 2.45rem;
max-width: 100%;
margin: .25rem .35rem .25rem 0;
padding: .64em 1.05em .64em 2.35em;
border: 1px solid rgba(79, 70, 229, .35);
border-radius: 8px;
background-color: #5f5fee;
background-repeat: no-repeat;
background-size: 16px 16px;
background-position: .82em center;
color: #ffffff;
font-weight: 700;
line-height: 1.2;
letter-spacing: .01em;
cursor: pointer;
box-shadow: none;
text-decoration: none;
white-space: normal;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
transform: none !important;
}
.external-login:hover,
.external-login:focus,
.external-login:active {
border-color: rgba(67, 56, 202, .55);
background-color: #4338ca;
background-repeat: no-repeat !important;
background-size: 16px 16px !important;
background-position: .82em center !important;
color: #ffffff;
transform: none !important;
}
.external-login.github-login,
.external-login.gitlab-login,
.external-login.google_oauth2-login,
.external-login.github-login:hover,
.external-login.gitlab-login:hover,
.external-login.google_oauth2-login:hover,
.external-login.github-login:focus,
.external-login.gitlab-login:focus,
.external-login.google_oauth2-login:focus,
.external-login.github-login:active,
.external-login.gitlab-login:active,
.external-login.google_oauth2-login:active {
box-shadow: none !important;
}
.external-login-container {
display: inline-block;
vertical-align: top
}
.external-login-container * {
text-align: center;
display: block
}
.external-login-container .external-login {
display: inline-flex !important
}
.external-login-container>*:not(button) {
font-size: smaller
}
.external-login-container:not(:last-child) {
margin-right: 5px
}
.external-login-container .github-login {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNTE3OEEyQTk5QTAxMUUyOUExNUJDMTA0NkE4OTA0RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNTE3OEEyQjk5QTAxMUUyOUExNUJDMTA0NkE4OTA0RCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU1MTc4QTI4OTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU1MTc4QTI5OTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+m4QGuQAAAyRJREFUeNrEl21ojWEYx895TDPbMNlBK46IUiNmPvHBSUjaqc0H8pF5+aDUKPEBqU2NhRQpX5Rv5jWlDIWlMCv7MMSWsWwmb3tpXub4XXWdPHvc9/Gc41nu+nedc7/8r/99PffLdYdDPsvkwsgkTBwsA/PADJCnzX2gHTwBt8Hl7p537/3whn04XoDZDcpBlk+9P8AFcAghzRkJwPF4zGGw0Y9QS0mAM2AnQj77FqCzrtcwB1Hk81SYojHK4DyGuQ6mhIIrBWB9Xm7ug/6B/nZrBHBegrkFxoVGpnwBMSLR9EcEcC4qb8pP14BWcBcUgewMnF3T34VqhWMFkThLJAalwnENOAKiHpJq1FZgI2AT6HZtuxZwR9GidSHtI30jOrbawxlVX78/AbNfhHlomEUJJI89O2MqeE79T8/nk8nMBm/dK576hZgmA3cp/R4l9/UeSxiHLVIlNm4nFfT0bxyuIj7LHRTKai+zdJobwMKzcZSJb0ePV5PKN+BqAAKE47UlMnERELMM3EdYP/yrd+XYb2mOiYBiQ8OQnoRBlXrl9JZix7D1pHTazu4MoyBcnYamqAjIMTR8G4FT8LuhLsexXYYjICBiqhQBvYb6fLZIJCjPypVvaOoVAW2WcasCnL2Nq82xHJNSqlCeFcDshaPK0twkAhosjZL31QYw+1rlMpWGMArl23SBsZZO58F2tlJXmjOXS+s4WGvpMiBJT/I2PInZ6lIs9/hBsNS1hS6BG0DSqmYEDRlCXQrmy50P1oDRKTSegmNbUsA0zDMwRhPJXeCE3vWLPQMvan6X8AgIa1vcR4AkGZkDR4ejJ1UHpsaVI0g2LInpOsNFUud1rhxSV+fzC9Woz2EZkWQuja7/B+jUrgtIMpy9YCW4n4K41YfzRneW5E1KJTe4B2Zq1Q5EHEtj4U3AfEzR5SVY4l7QYQPJdN2as7RKBF0BPZqqH4VgMAMBL8Byxr7y8zCZiDlnOcEKIPmUpgB5Z2ww5RdOiiRiNajUmWda5IG6WbhsyY2fx6m8gLcoJDJFkH219M3We1+cnda93pfycZpIJEL/s/wSYADmOAwAQgdpBAAAAABJRU5ErkJggg==)
}
.external-login-container .gitlab-login {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAACoUlEQVRYhc3WzW+UVRQG8N/MtKKYsEFMmpo27DUEFgSiSIHSsDAxsYr6L4Cs+AMkMWiMCwgB2lQMhIWJ0Rip7owbXbhjhekGTFBQkC9rTCxBWxb3vpkzb2Y6H+00PsnN3Hve8zznzL3nfvA/xQRm8Qk2rUBnU9aYxf5OSevxF5ZyO7eCBM4Fnb/xVCekyUBawl0M9BB8EPdLWq92Qvy0RFrCvh4SmGiic7EdaZ3G6S/aVA8JzDTR+RNPLEd6JTi/h19z/zZqXQQfwB+Zex3Hg+6B5Yjng+MWnAzjl7tIYE/gncDWMP64FSkWzVVUsCsQT3WRwOnAeylr/ZzHd7Qo6v2B9GG21XAr226i2kHwKn7LnN8D56Ogv6cZcTo4bA/2qWDf2UECLwb/s8G+I9jPFMZK/q3lrJ+VCm80O8I4vs39RRxtk8CJ0B/Hd7lfxS8YlmbmuawHxjQWTcSgdBiVt1S71uwAOxW+7yqygteD05cl0iNcaPl/W+MC/i3Zvgj9g6QlqOIGhqSCGxamJqOKbXiyw+ALuNxEpyYt8ZB0tgyTCqtZ0fQLcRn2VqXLp0B5+vuBz0L/TbiWs7knFVy/UVU/4u9QP7Pn5crsM8bVl+AfeDcY/svjXu7/dhjAMY1b9Trpejxf+vA9RlYx+Ah+KMX4HBui09vSMhQO9/HaKgSfxIOgO4+3Wjlvxo+lTKeld2K3WK/xflnK2pvbEQelB8RiIF7B810EfwE/Bf5i1uxql+1Vv1aLij2kfoE1QwWHpZOw4N3MWj3hGXytcRq/wsYmvhtxqeQ7mzVWhAqO4GEQvoHdwWcs24rvC3jH8rPVNbZgTuO6vo8PNNbLXPbtC56WHpWt3gAz2afveEN64xeBH2h8U6wJRvFNbqNrHXzV8BjO7vx8x02KpQAAAABJRU5ErkJggg==)
}
.external-login-container .google_oauth2-login {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAnFJREFUOI2FU11Ik1EYfs75zvZ9c35buAKpaWaSSVZoiheBKVmYdWF1ERi7kMhFUeqNFxLURRAhFKvhTcHMioQiCBG8iOgH8QfFKZj4M81ES0fONfe5tW87XcQncw17rs7znud5f87LIUgCn8u1jQaWL2MtWMTBGZGkKUgpLvPVxolELYkn3if3ZP38ytvQ8EAZCa6RzUoK4WDBrJiXey61rtH9T4LVx86cWF/PsPp1OjVZVxpo+q6wpfSUTOz2CAAwAIg5HOJqf89QvFnI3KNQa6ab6vTB2Ir3QGRsdCeMqVw8WmbTzBsJFPNSmzo7bfpbgkI6UeWSm25dIgDXhAHn/YtgRJWvNLza1BLnIOHPWZFwVyVfrizhvjvNXVuNkAimTjVV0PADBnEBpuYiVRnfXRMvaOkMOaOcpyUz7zDgJiPRtRKtTyrBn2a3++NFg7NqnTcAXbIE1UWsjwJkY07ON6/1v4hBYlxn6tP4SHS7yTH5zFS/z/ZLix3OEDrDUVg0PjSjlioRQgBA1GGSsb1334cXsyMd5Liudd7HKuB9CeC0Zmg+azivnR92h6qVCDkGAAYd53pB7KaEgLeJ1147F1YQ4xzv5nurbvc/eoqEcZwfh0r7PWqHxvOtwlhtOQkRAHBMOsQBz9zShH/OrAky5PT1LKN1lDG6/nPdnzPu81gPyeWYGbkAA2P8zBF9YV256N6o0jr6IvvT4qB7evWbvNW75Znzo8VCU8ONk0YnkPCZWtztRp+y/Kb3x0hF4LdC4+8oIci37P9eYMmtuV5g+6DFk66txd1uRFStDarBYnAuiYLkSREMz+sLbV8StX8AjxDtgxiuzNwAAAAASUVORK5CYII=)
}
.centered-sections h2,.centered-sections h3 {
text-align: center
}
form.external-login-form {
position: relative;
display: table;
margin: 0 auto;
padding: 1em;
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: 5px;
text-align: center
}
form.external-login-form .remember-me {
margin-top: 12px
}
form.new_user {
position: relative;
width: 340px;
margin: 0 auto;
padding: 1em;
background-color: var(--content-background-color);
border: 1px solid content(--content-border-color);
border-radius: 5px;
text-align: start
}
@media screen and (max-width: 440px) {
form.new_user {
width:unset
}
}
form.new_user label,form.new_user em {
display: block;
font-size: small
}
form.new_user br {
display: none
}
form.new_user input[type=text],form.new_user input[type=email],form.new_user input[type=password] {
display: block;
width: 100%;
min-height: 34px;
box-sizing: border-box;
margin-top: .2em;
margin-bottom: .5em;
padding: 6px 8px;
font-size: 14px;
line-height: 20px;
vertical-align: middle;
border: 1px solid #ddd;
border-radius: 3px;
outline: none;
box-shadow: inset 0 1px 2px #0000001a
}
form input[type=checkbox],input[type=checkbox]+label,form input[type=radio],input[type=radio]+label {
display: inline-block;
font-size: small
}
.radio-note {
font-size: small;
margin-top: 5px
}
@media screen and (max-width: 440px) {
form input[type=checkbox]+label {
display:unset;
word-wrap: break-word
}
}
form.new_user input[type=submit] {
display: block;
width: 100%;
min-height: 34px;
box-sizing: border-box;
margin: .5em 0 0;
padding: 6px 8px;
font-size: 14px;
font-weight: 700;
line-height: 20px;
text-align: center;
vertical-align: middle;
color: #fff;
background-color: #670000;
background-image: linear-gradient(#900,#670000);
border: 0px solid #ddd;
box-shadow: none;
border-radius: 3px;
white-space: normal
}
form.new_user~br {
display: none
}
form.new_user~a {
width: 340px;
display: block;
margin: 0 auto 2em;
font-size: small
}
form.new_user+a {
width: 340px;
display: block;
margin: 0 auto
}
.qr-code {
max-width: 400px;
background-color: #fff
}
.sidebar-search,.home-search,
#library-search,#user-search,#code-search {
position: relative;
vertical-align: middle
}
.sidebar-search input[type=search],.home-search input[type=search],
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
padding: .6em 78px .6em .8em;
}
.sidebar-search input[type=search]::-webkit-search-cancel-button,
.home-search input[type=search]::-webkit-search-cancel-button,
#library-search input[type=search]::-webkit-search-cancel-button,
#user-search input[type=search]::-webkit-search-cancel-button,
#code-search input[type=search]::-webkit-search-cancel-button {
margin-right: 38px;
}
.sidebar-search input[type=search],
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
width: 100%;
margin: 0 0 16px;
}
.sidebar-search input.search-submit[value="🔎"],.home-search input.search-submit[value="🔎"],
#library-search input.search-submit[value="🔎"],
#user-search input.search-submit[value="🔎"],
#code-search input.search-submit[value="🔎"] {
position: absolute;
-moz-appearance: none;
-webkit-appearance: none;
inset-inline-end: 1px;
top: 1px;
bottom: 1px;
width: 38px;
border: 0;
border-inline-start: 1px solid var(--content-border-color);
border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;
padding: 0;
margin-left: 0;
margin-right: 0;
background-color: var(--content-background-color) !important;
box-shadow: none;
opacity: 1;
transform: none
}
.sidebar-search input.search-submit[value="🔎"] {
bottom: 17px;
}
.sidebar-search input.search-submit[value="🔎"]:hover,.sidebar-search input.search-submit[value="🔎"]:focus,.sidebar-search input.search-submit[value="🔎"]:active,
.home-search input.search-submit[value="🔎"]:hover,.home-search input.search-submit[value="🔎"]:focus,.home-search input.search-submit[value="🔎"]:active,
#library-search input.search-submit[value="🔎"]:hover,#library-search input.search-submit[value="🔎"]:focus,#library-search input.search-submit[value="🔎"]:active,
#user-search input.search-submit[value="🔎"]:hover,#user-search input.search-submit[value="🔎"]:focus,#user-search input.search-submit[value="🔎"]:active,
#code-search input.search-submit[value="🔎"]:hover,#code-search input.search-submit[value="🔎"]:focus,#code-search input.search-submit[value="🔎"]:active {
background-color: var(--content-background-color) !important;
box-shadow: none;
transform: none
}
#library-search,
#user-search,
#code-search {
display: grid;
grid-template-columns: minmax(0, 1fr) 38px;
align-items: stretch
}
#library-search > h3,
#library-search > p,
#user-search > h3,
#user-search > p,
#code-search > h3,
#code-search > p {
grid-column: 1 / -1
}
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
grid-column: 1;
margin: 0 0 16px;
padding: .6em 34px .6em .8em;
border-start-end-radius: 0;
border-end-end-radius: 0
}
#library-search input[type=search]::-webkit-search-cancel-button,
#user-search input[type=search]::-webkit-search-cancel-button,
#code-search input[type=search]::-webkit-search-cancel-button {
margin-right: 8px
}
#library-search input.search-submit[value="🔎"],
#user-search input.search-submit[value="🔎"],
#code-search input.search-submit[value="🔎"] {
position: static;
grid-column: 2;
align-self: stretch;
width: 38px;
min-height: auto;
margin: 0 0 16px;
border: 1px solid var(--content-border-color);
border-inline-start: 0;
border-start-start-radius: 0;
border-end-start-radius: 0;
border-start-end-radius: var(--border-radius-small);
border-end-end-radius: var(--border-radius-small);
background-color: var(--content-background-color) !important
}
@media screen and (max-width: 680px) {
.sidebar-search input[type=search],.home-search input[type=search],
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
font-size:unset
}
}
figure {
padding: 5px;
box-shadow: 0 4px 8px #00000026,0 6px 10px #00000026;
border-radius: 5px
}
figcaption {
font-size: smaller;
text-align: center
}
.multiform-page:not(:first-child) {
margin-top: 30px
}
.multiform-page:not(:last-child) {
padding-bottom: 30px;
border-bottom: 1px solid lightgray
}
summary {
cursor: pointer
}
@media screen and (max-width: 400px) {
.user-list {
padding-top:1em;
padding-bottom: 1em
}
}
.blocked-script-codes {
font-size: smaller;
border-collapse: collapse;
width: 100%;
text-align: left
}
.blocked-script-codes .pattern-row code {
font-size: medium
}
.blocked-script-codes .pattern-row {
border-top: 1px solid gray
}
.blocked-script-codes .info-row td:first-child {
width: 2em
}
.ad {
margin-top: 1em;
margin-bottom: 1em
}
.script-list-cd-entry {
border-bottom: 1px solid #DDDDDD
}
#script-list-cd,#discussion-show-cd {
width: 300px;
margin-left: auto;
margin-right: auto
}
#script-list-cd {
padding: 1em
}
.ethical-ads-text .ea-placement {
position: relative
}
.ethical-ads-text .ea-callout {
position: absolute;
bottom: 0;
right: 0
}
.ethical-ads-text:empty {
min-height: 46px
}
.ethical-ads.text-content-top-ad {
margin: 0 calc(-1em - 1px);
border-radius: 5px 5px 0 0
}
@media screen and (max-width: 960px) {
.ethical-ads.text-content-top-ad {
margin:0 calc(-1.2vw - 1px)
}
}
@media screen and (max-width: 400px) {
.ethical-ads.text-content-top-ad {
margin:0 calc(-1em - 1px);
border-radius: 5px 5px 0 0
}
}
@media screen and (max-width: 400px) {
.script-list li.ad-entry {
padding:0
}
}
#script-info .ethical-ads-text {
margin: 0 calc(-1em - 1px)
}
#script-info .ethical-ads-text .ea-content {
border-radius: 0!important
}
@media screen and (max-width: 960px) {
#script-info .ethical-ads-text {
margin:0 calc(-1.2vw - 1px)
}
}
.after-radio-chosen {
display: none;
margin-left: 29px
}
input[type=radio]:checked~.after-radio-chosen {
display: block
}
.announcement {
margin: 14px 0;
text-align: center;
font-size: smaller
}
.announcement form {
display: inline
}
.announcement input {
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
border: 0;
background: none;
margin: 0 0 0 4px;
padding: 0;
cursor: pointer
}
.announcement,.announcement input {
font-size: 12px
}
.badge {
margin-left: 1ex;
border-radius: 10%/25%;
font-size: 70%;
padding: 0 .5ex;
text-transform: uppercase;
position: relative;
top: -.2ex
}
.badge-banned,.badge-deleted {
background-color: #ff0000e6;
color: #fff
}
.badge-deleted {
margin-left: 0;
border-color: #ff0000e6
}
.badge-moderator {
background-color: #1a1da8e6;
color: #fff
}
.badge-author {
background-color: #1e971ee6;
color: #fff
}
.badge-js {
background-color: #efd81d;
color: #000
}
.badge-css {
background-color: #254bdd;
color: #fff
}
.badge-js,.badge-css {
display: none
}
.showing-all-languages .badge-js,.showing-all-languages .badge-css {
display: inline
}
code {
background-color: var(--code-background-color)
}
pre code {
background: none;
border: 0
}
pre,code {
border-radius: 2px
}
pre {
padding: 1em
}
.prettyprint {
min-width: calc(100% - 6px);
background-color: var(--prettyprint-background-color);
color: var(--prettyprint-color)
}
.prettyprint.wrap {
white-space: pre-wrap;
line-break: anywhere
}
.prettyprint:not(.wrap) {
width: max-content
}
.code-container {
max-height: calc(100vh - 54px);
overflow-x: auto;
border-radius: 2px;
border: 1px solid var(--code-container-border-color)
}
.code-container pre {
border: 0;
margin: 0
}
li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9 {
list-style-type: decimal!important
}
@media screen and (max-width: 440px) {
#code-container {
font-size:small
}
}
.diff_options input[type=number] {
width: 10ch
}
.diff {
overflow: auto
}
.diff ul {
background: #fff;
overflow: auto;
font-size: 13px;
list-style: none;
margin: 0;
padding: 0;
display: table;
width: 100%
}
.diff del,.diff ins {
display: block;
text-decoration: none
}
.diff li {
padding: 0;
display: table-row;
margin: 0;
height: 1em
}
.diff li.ins {
background: var(--diff-ins-background);
color: var(--diff-ins-color)
}
.diff li.del {
background: var(--diff-del-background);
color: var(--diff-del-color)
}
.diff li:hover {
background: #ffc
}
.diff del,.diff ins,.diff span {
white-space: pre;
font-family: courier
}
.diff del strong {
font-weight: 400;
background: var(--diff-del-strong-background)
}
.diff ins strong {
font-weight: 400;
background: var(--diff-ins-strong-background)
}
.diff li.diff-comment {
display: none
}
.diff li.diff-block-info {
background: none repeat scroll 0 0 var(--diff-block-info)
}
.diff del,.diff ins,.diff span {
font-family: monospace
}
.diff {
max-height: calc(100vh - 54px);
overflow-y: auto
}
.report-diff .diff {
max-height: 75vh
}
.report-diff form {
display: inline
}
.diff ul {
background-color: var(--content-background-color);
color: var(--overall-text-color)
}
.diff {
border: 2px solid var(--content-border-color)
}
.diff li:hover {
background: var(--highlight-background-color)
}
.ea-content,.ea-callout {
margin: 0!important
}
#about-user .ethical-ads {
margin: 0 calc(-1em - 5px)
}
@media screen and (max-width: 960px) {
#about-user .ethical-ads {
margin:0 -1.2vw
}
}
@media screen and (max-width: 400px) {
#about-user .ethical-ads {
margin:0 -1em
}
}
#user-show-ea+.report-link {
top: 65px
}
.expander {
cursor: pointer;
display: block;
color: var(--expander-color);
border-radius: 3px;
background-color: var(--expander-background-color);
position: absolute;
width: 20px;
height: 20px;
text-align: center;
inset-inline-end: -22px;
bottom: 0
}
.expanded {
overflow: auto
}
.collapsed {
overflow: hidden
}
.comment {
margin-bottom: 20px
}
.comment-entry {
width: 100%;
height: 10em
}
.discussion-meta,.comment-meta,.notification-meta {
display: flex;
align-items: flex-end
}
.discussion-meta,.notification-meta {
font-size: 11px
}
.comment-meta {
font-size: smaller;
margin-bottom: 2px
}
.comment-meta-item-main {
font-size: medium;
font-weight: 700
}
.comment-meta-item+.comment-meta-item {
margin-left: 15px
}
.discussion-meta-item,.notification-meta-item {
flex: 1;
text-align: left
}
.discussion-meta-item:not(:first-child) {
margin-left: 8px
}
.discussion-meta-item:not(:last-child) {
margin-right: 8px
}
.discussion-meta-item:last-child {
text-align: right
}
.comment-meta-spacer {
flex: 1
}
.post-reply {
margin-top: 20px
}
.post-reply h3,.edit-comment-form h3 {
margin-bottom: 0
}
.post-reply input[type=submit],.edit-comment-form input[type=submit] {
margin-top: 5px
}
.discussion-up-level {
font-size: smaller;
margin-top: 0
}
.edit-comment-form {
display: none
}
.edit-comment-mode .edit-comment-form {
display: block
}
.edit-comment-mode .user-content,.edit-comment-mode .comment-meta {
display: none
}
.discussion-rating {
margin-top: 10px
}
.discussion-list,.notification-list {
padding-bottom: 0
}
.discussion-list-item,.notification-list-item {
padding-top: 10px;
border-top: 1px solid var(--content-separator-color)
}
.discussion-list-container:first-child .discussion-list-item {
border-top: 0
}
.discussion-list-logged-in .discussion-read,.notification-read {
background-color: var(--inactive-item-background-color);
margin-left: -16px;
margin-right: -16px;
padding-left: 16px;
padding-right: 16px
}
.script-discussion-list .discussion-list-item:last-child {
border-bottom: 1px solid var(--content-separator-color)
}
a.discussion-title,.notification-list-item a {
display: block;
text-decoration: none;
color: var(--overall-text-color);
padding: 4px 0 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis
}
.discussion-title,.notification-list-item a {
vertical-align: middle
}
.discussion-title:hover,.notification-list-item a {
color: var(--texty-link-visited-color)
}
.rating-icon,.badge-deleted {
border: 2px solid black;
border-radius: 5px;
font-size: 12px;
text-transform: uppercase;
font-weight: 800;
padding: 2px 5px;
margin-right: 5px;
display: inline-block;
text-align: center;
min-width: 45px;
position: relative;
top: -1px
}
.rating-icon-good {
border-color: var(--rating-icon-good-border-color);
background-color: var(--rating-icon-good-background-color);
color: var(--rating-icon-good-color)
}
.rating-icon-ok {
border-color: var(--rating-icon-ok-border-color);
background-color: var(--rating-icon-ok-background-color);
color: var(--rating-icon-ok-color)
}
.rating-icon-bad {
border-color: var(--rating-icon-bad-border-color);
background-color: var(--rating-icon-bad-background-color);
color: var(--rating-icon-bad-color)
}
.discussion-meta-item-script-name {
overflow: hidden
}
.discussion-meta-item-script-name a {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: block
}
.comment .user-content>*:first-child {
margin-top: 0
}
.comment-screenshot-control {
font-size: smaller;
padding: .5em 0
}
.discussion-header,.discussion-list-header,.notification-list-header {
display: flex;
margin-top: 30px;
margin-bottom: 20px
}
@media screen and (max-width: 400px) {
.discussion-header,.discussion-list-header,.notification-list-header,.user-list-header {
margin-top:15px;
margin-bottom: 10px
}
}
.discussion-header-no-script {
margin-top: 16px
}
.discussion-header>*:first-child,.discussion-list-header h2,.notification-list-header>*:first-child {
flex: 1;
margin: 0!important
}
.discussion-header h2,.discussion-header .discussion-up-level,.notification-list-header h2 {
margin: 0
}
.discussion-header .badge {
vertical-align: middle
}
.discussion-actions,.notification-actions {
font-size: smaller
}
.discussion-subscribed .discussion-subscribe,.discussion-not-subscribed .discussion-unsubscribe {
display: none
}
.post-discussion label:not(.radio-label),.post-reply label:not(.radio-label),.post-discussion .form-note,.post-reply .form-note {
font-size: smaller
}
#main-header {
background-color: #670000;
background-image: linear-gradient(#670000,#900);
box-shadow: 0 0 15px 2px #00000080;
padding: .25em 0
}
#main-header .width-constraint {
padding: 0 0 .25em;
position: relative
}
#site-name img {
vertical-align: bottom
}
#site-name-text {
display: inline-block;
vertical-align: top
}
#site-name-text h1 {
line-height: 1.1em
}
#main-header,#main-header a,#main-header a:visited,#main-header a:active {
color: #fff
}
#main-header h1 {
font-size: 72px;
margin: 0;
letter-spacing: -2px
}
#main-header h1 a {
text-decoration: none
}
#main-header .subtitle {
margin: -8px 0 0 10px;
font-size: .7em;
text-shadow: -1px -1px 0px #670000,1px -1px 0px #670000,-1px 1px 0px #670000,1px 1px 0px #670000
}
#site-nav>nav,#nav-user-info {
text-align: end;
position: absolute;
right: 0
}
#site-nav>nav {
bottom: 0
}
#nav-user-info {
top: 0
}
#site-nav>nav a:hover {
color: #fff
}
#site-nav>nav {
padding: 0
}
#site-nav>nav>li {
list-style-type: none;
display: inline-block
}
#site-nav>nav>li+li {
margin-left: .5em
}
#script-search,.language-selector {
display: inline
}
#nav-user-info {
font-size: small
}
#nav-user-info select,#nav-user-info input {
font-size: 11px
}
nav nav {
position: absolute;
right: 0;
background-color: #900;
min-width: 100%;
display: none;
padding: 5px 0;
z-index: 10
}
nav nav li {
white-space: nowrap;
margin: 0
}
nav nav li a {
display: block;
padding: 5px 15px
}
nav a:hover+nav,nav nav:hover,nav a:focus+nav {
display: block
}
.with-submenu {
position: relative;
padding-right: 15px
}
nav .with-submenu>a:after {
content: " ▾"
}
@media screen and (max-width: 920px) {
#site-name img {
max-width:96px;
max-height: 96px;
width: 12%;
height: 12%
}
#site-name-text {
margin-top: 1.15vw;
margin-bottom: 1.15vw
}
#main-header h1 {
font-size: 8.3vw
}
#main-header .subtitle {
margin: -.8em 0 0 10px;
font-size: 2vw
}
#site-nav {
margin-top: -1vw
}
#site-nav>nav,#nav-user-info {
display: block;
position: unset;
right: unset;
padding-top: .3em
}
#site-nav>nav {
bottom: unset
}
#nav-user-info {
top: unset;
font-size: unset;
width: 100%
}
#nav-user-info .sign-in-link {
padding-right: .7em
}
#script-search,.language-selector {
display: unset
}
}
#mobile-nav {
display: none
}
.mobile-nav-opener {
cursor: pointer;
position: absolute;
right: 0;
top: 0;
font-size: 8.3vw;
padding: 0 2vw
}
#mobile-nav .collapsed {
display: none
}
#mobile-nav nav {
text-align: end;
position: absolute;
top: calc(100% + 4px);
right: calc((100vw - 100%) / -2);
width: min(22rem, calc(100vw - 0.8rem));
max-width: calc(100vw - 0.8rem);
max-height: calc(100vh - 0.75rem);
box-sizing: border-box;
overflow-x: hidden;
overflow-y: auto;
background-color: #900;
z-index: 1000;
border-radius: 0 0 0 5px;
font-size: 24px
}
#mobile-nav nav li {
list-style-type: none
}
#mobile-nav nav li>a {
display: block;
padding: 10px 15px
}
#mobile-nav nav select {
margin: 10px 15px;
width: calc(100% - 30px);
max-width: calc(100% - 30px);
font: -webkit-small-control;
box-sizing: border-box
}
#mobile-nav nav select.language-selector-locale {
font-size: .92rem;
min-height: 2rem;
padding: .15rem .35rem;
}
#mobile-nav nav li.multi-link-nav {
padding: 10px 15px
}
#mobile-nav nav li.multi-link-nav > a {
display: inline;
padding: 0
}
.gf-mobile-sign-out-icon {
display: inline-flex !important;
margin-top: 0;
padding: 0 !important;
}
.gf-user-icon.gf-mobile-sign-out-icon svg {
stroke-width: 3;
}
#mobile-nav .gf-user-icon.gf-mobile-edit-icon svg {
stroke-width: 3;
}
#gf-mobile-primary-nav {
display: flex;
align-items: center;
gap: 0.9rem;
padding: 0.7rem 0.85rem 0.55rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}
#gf-mobile-primary-nav > a {
display: inline-flex !important;
align-items: center;
justify-content: flex-start;
flex: 0 1 auto;
min-width: 0;
padding: 0 !important;
color: inherit;
text-decoration: none;
font-size: 1.16rem;
font-weight: 700;
line-height: 1.2;
min-height: 50px;
}
#gf-mobile-primary-nav-toggle {
all: unset;
display: inline-flex;
align-items: center;
justify-content: center;
width: auto;
height: auto;
color: inherit;
font-size: 1.32rem;
font-weight: 700;
cursor: pointer;
flex: none;
margin-left: auto;
}
#gf-mobile-secondary-nav {
padding: 0 0.85rem 0.45rem;
}
#gf-mobile-secondary-nav.collapsed {
display: none;
}
.gf-mobile-secondary-divider {
display: none;
}
#gf-mobile-secondary-nav > li > a {
display: block !important;
font-size: 1.04rem;
line-height: 1.2;
}
#gf-mobile-user-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.2rem 0 0;
}
#gf-mobile-user-row .user-profile-link a {
display: inline-block;
padding: 0;
font-weight: 700;
}
#gf-mobile-user-meta {
display: inline-flex;
align-items: center;
gap: 0.45rem;
min-width: 0;
}
#gf-mobile-user-actions {
display: inline-flex;
align-items: center;
gap: 0.45rem;
flex: none;
}
#gf-mobile-user-actions .gf-user-icon {
width: 30px;
height: 30px;
}
#gf-mobile-user-actions .gf-user-icon[data-panel] {
cursor: pointer;
}
.gf-mobile-user-panel {
position: static;
display: none;
opacity: 1;
transform: none;
min-width: 0;
margin-top: 0.7rem;
}
.gf-mobile-user-panel.active {
display: block !important;
position: relative;
z-index: 1;
}
.gf-mobile-user-panel a {
display: block !important;
padding: 0.75em 1.25em !important;
}
@media screen and (max-width: 920px) {
#site-nav {
display:none
}
#main-header,
#main-header .width-constraint,
#mobile-nav {
overflow: visible;
}
#mobile-nav {
display: block
}
.width-constraint {
margin-inline: auto;
padding-inline: 0;
width: calc(100% - 0.7rem);
}
#main-header .width-constraint {
width: calc(100% - 0.8rem);
padding-inline: 0.4rem;
}
}
@media screen and (max-width: 400px) {
#site-name {
margin-left:1em
}
}
#test-require-result-ok,#test-require-result-not-ok {
display: none;
font-weight: 700
}
#test-require-result-ok {
color: green
}
#test-require-result-not-ok {
color: red
}
#home-script-nav {
max-width: 700px;
margin: 0 auto 15px;
padding-bottom: 20px;
border-bottom: 1px solid #BBBBBB
}
.home-search input {
font-size: large
}
.home-search input[type=search] {
width: 100%
}
#home-top-sites {
overflow: hidden;
margin-top: 5px
}
#home-top-sites a {
margin: 0 5px
}
#home-step-1,#home-step-2,#home-step-3 {
overflow: auto
}
#home-step-1 figure {
float: right;
max-width: 50%;
margin-inline-end:10px;margin-top: 0
}
#home-step-2 figure {
float: left;
max-width: 50%;
margin-inline-start:7px;margin-top: 0
}
#home-step-2 li {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis
}
@media screen and (max-width: 680px) {
#home-step-1 figure,#home-step-2 figure,#home-step-3 figure {
float:unset;
max-width: unset;
width: fit-content;
margin: 0 auto
}
[id^=home-step-] figure img {
width: 100%;
height: auto
}
}
.super-title {
text-align: center
}
.browser-list {
display: none
}
#desktop-browser-list {
display: block
}
.browser-list-selector:not(.browser-list-selector-active) {
text-decoration: underline;
cursor: pointer
}
.browser-list-selector-active {
font-weight: 700
}
.browser-list-selector:not(:last-child) {
margin-right: 1em
}
.highlight {
background-color: #ff0
}
#install-area {
margin-bottom: 1em;
display: flex;
align-items: center;
flex-wrap: wrap
}
#install-area .install-link:hover,#install-area .install-link:focus,#install-area .install-help-link:hover,#install-area .install-help-link:focus {
transition: box-shadow .2s;
box-shadow: 0 8px 16px #0003,0 6px 20px #00000030
}
.install-link,.install-link:visited,.install-link:active,.install-link:hover,.install-help-link {
transition: box-shadow .2s;
display: inline-block;
background-color: #005200;
padding: .5em 1em;
color: #fff;
text-decoration: none;
border-radius: .25rem 0 0 .25rem
}
.install-help-link,.install-help-link:visited,.install-help-link:active,.install-help-link:hover {
background-color: #1e971e;
color: #fff;
border-radius: 0 .25rem .25rem 0;
text-decoration: none;
}
.installation-instructions-modal-content-firefox,.installation-instructions-modal-content-chrome,.installation-instructions-modal-content-opera,.installation-instructions-modal-content-safari,.installation-instructions-modal-content-edge,.installation-instructions-modal-content-other {
display: none
}
.installation-instructions-modal-firefox .installation-instructions-modal-content-firefox,.installation-instructions-modal-chrome .installation-instructions-modal-content-chrome,.installation-instructions-modal-opera .installation-instructions-modal-content-opera,.installation-instructions-modal-safari .installation-instructions-modal-content-safari,.installation-instructions-modal-edge .installation-instructions-modal-content-edge,.installation-instructions-modal-other .installation-instructions-modal-content-other {
display: block
}
.installation-instructions-modal-content-bypass,.list-option-groups {
font-size: smaller
}
.list-option-group {
margin-bottom: 1em
}
.list-option-group ul {
margin: .5em 0 0;
list-style-type: none;
padding: 1em 0;
box-shadow: 0 0 5px var(--content-box-shadow-color);
border: 1px solid var(--content-border-color);
border-radius: 5px;
background-color: var(--content-background-color)
}
.list-option-group[data-gfplus-collapsed="true"] > ul > :not(.list-current) {
display: none;
}
.list-option-group .gf-list-option-toggle-row {
display: flex;
justify-content: center;
position: relative;
z-index: 2;
height: 14px;
margin-top: -14px;
margin-bottom: .55rem;
}
.sidebar button.gf-list-option-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
min-width: 28px;
height: 28px;
min-height: 28px;
margin: 0;
padding: 0;
border: 1px solid var(--content-border-color);
border-radius: 50%;
background: var(--content-background-color) !important;
color: var(--overall-text-color) !important;
box-shadow: none !important;
cursor: pointer;
transform: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base), transform var(--transition-base);
}
.sidebar button.gf-list-option-toggle:hover,
.sidebar button.gf-list-option-toggle:focus-visible {
background: var(--inactive-item-background-color);
border-color: var(--link-color);
color: var(--link-color) !important;
box-shadow: none !important;
outline: none;
transform: scale(1.06) !important;
}
.sidebar button.gf-list-option-toggle:focus {
box-shadow: none !important;
outline: none;
}
.sidebar button.gf-list-option-toggle svg {
width: 15px;
height: 15px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.list-option-group a {
padding: .35em 1em;
display: block
}
.list-option-group a:hover,.list-option-group a:focus {
background: linear-gradient(var(--list-option-hover-background-color-gradient-1),var(--list-option-hover-background-color-gradient-2));
text-decoration: none;
box-shadow: inset 0 -1px var(--list-option-hover-box-shadow-top),inset 0 1px var(--list-option-hover-box-shadow-bottom)
}
.list-option-group .list-current {
border-left: 7px solid #800;
box-shadow: inset 0 1px #0000001a,inset 0 -1px #0000001a;
margin: 0 0 0 -4px;
padding: .4em 1em .4em calc(1em - 3px);
background: linear-gradient(var(--list-option-background-color-gradient-1),var(--list-option-background-color-gradient-2))
}
@media screen and (min-width: 440px) and (max-width: 960px) {
.list-option-group a,.list-option-group .list-current {
padding-left:1.2vw;
padding-right: 1.2vw
}
}
.list-option-button {
display: block;
background-color: var(--list-option-button-background-color);
text-align: center;
text-decoration: none;
color: var(--list-option-button-color)!important;
border: 1px solid var(--list-option-button-border-color);
padding: .5em;
font-weight: 700
}
.list-option-button:hover,.list-option-button:focus {
background: linear-gradient(var(--list-option-button-background-color-gradient-1),var(--list-option-button-background-color-gradient-2));
text-decoration: none
}
.list-option:not(.list-current) select {
width: calc(100% - 1.4em + 3px);
margin: .4em 1em .4em calc(1em - 3px)
}
.list-option.list-current select,.log-table {
width: 100%
}
.log-table th {
text-align: left
}
.log-table td,.log-table th {
padding: 0 5px
}
.log-table td .possibly-long-text {
max-width: 500px;
overflow-wrap: break-word
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content {
display: table;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content thead {
display: table-header-group;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content tbody {
display: table-row-group;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content tr {
display: table-row;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content th,
html[data-gfplus-moderator-actions-page] table.log-table.text-content td {
display: table-cell;
vertical-align: top;
}
@media screen and (max-width: 820px) {
html[data-gfplus-moderator-actions-page] .width-constraint {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
padding-bottom: .25rem;
}
html[data-gfplus-moderator-actions-page] .width-constraint > .log-table {
min-width: 48rem;
}
}
.modal__overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #0009;
display: flex;
justify-content: center;
align-items: center;
z-index: 100
}
.modal__container {
background-color: #fff;
padding: 30px;
max-width: 500px;
max-height: 100vh;
border-radius: 4px;
overflow-y: auto;
box-sizing: border-box
}
.modal__header {
display: flex;
justify-content: space-between;
align-items: center
}
.modal__title {
margin-top: 0!important;
margin-bottom: 0;
font-weight: 600;
font-size: 1rem;
line-height: 1.25;
box-sizing: border-box
}
.modal__close {
background: transparent;
border: 0
}
.modal__header .modal__close:before {
content: "✕"
}
.modal__content {
margin-bottom: 2rem
}
.modal__content q {
font-style: italic
}
.modal__btn {
font-size: .875rem;
padding: .5rem 1rem;
background-color: #e6e6e6;
color: #000c;
border-radius: .25rem;
border-style: none;
border-width: 0;
cursor: pointer;
-webkit-appearance: button;
text-transform: none;
overflow: visible;
line-height: 1.15;
margin: 0 0 0 .5rem;
will-change: transform;
-moz-osx-font-smoothing: grayscale;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transform: translateZ(0);
transform: translateZ(0);
transition: -webkit-transform .25s ease-out;
transition: transform .25s ease-out;
transition: transform .25s ease-out,-webkit-transform .25s ease-out
}
.modal__btn:focus,.modal__btn:hover {
-webkit-transform: scale(1.05);
transform: scale(1.05)
}
.modal__btn-primary {
background-color: #005200;
color: #fff
}
.modal__footer {
text-align: right
}
@keyframes mmfadeIn {
0% {
opacity: 0
}
to {
opacity: 1
}
}
@keyframes mmfadeOut {
0% {
opacity: 1
}
to {
opacity: 0
}
}
@keyframes mmslideIn {
0% {
transform: translateY(15%)
}
to {
transform: translateY(0)
}
}
@keyframes mmslideOut {
0% {
transform: translateY(0)
}
to {
transform: translateY(-10%)
}
}
.micromodal-slide {
display: none
}
.micromodal-slide.is-open {
display: block
}
.micromodal-slide[aria-hidden=false] .modal__overlay {
animation: mmfadeIn .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide[aria-hidden=false] .modal__container {
animation: mmslideIn .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide[aria-hidden=true] .modal__overlay {
animation: mmfadeOut .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide[aria-hidden=true] .modal__container {
animation: mmslideOut .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide .modal__container,.micromodal-slide .modal__overlay {
will-change: transform
}
.notification-widget {
display: inline-block;
width: 1em;
height: 1em;
text-align: center;
line-height: 1em;
padding: 2px;
background-color: #31708f;
border-radius: 50%;
color: #fff;
text-decoration: none
}
.notification-type-consecutive_bad_ratings a {
white-space: normal
}
.post-install {
margin: 1em 0;
border-radius: 2px;
padding: 5px;
max-width: 600px;
display: none;
align-items: center;
background-color: #c4e3ed;
border: 1px solid #c4e3ed;
position: relative
}
.post-install-label {
font-size: xx-small;
position: absolute;
top: -2px;
left: 2px;
opacity: .5
}
.post-install-text {
text-align: center;
align-items: center;
flex: 1
}
.post-install-text p {
margin: 0;
padding: 0
}
.post-install-button {
text-align: center;
margin-left: 10px;
white-space: nowrap
}
.preview-results {
border: 1px solid var(--content-border-color);
border-left: 1px solid var(--content-border-color) !important;
border-radius: 0 0 var(--border-radius-small) var(--border-radius-small);
background: var(--content-background-color) !important;
overflow: auto;
box-sizing: border-box;
margin: 0;
padding: 16px
}
.previewable .preview-results.user-content {
border-left: 1px solid var(--content-border-color) !important;
border-radius: 0 0 var(--border-radius-small) var(--border-radius-small);
background: var(--content-background-color) !important;
}
.preview-results>p:first-child {
margin-top: 0
}
.preview-results>p:last-child {
margin-bottom: 0
}
.previewable textarea {
margin: 0
}
.previewable .tabs {
margin-top: 10px;
margin-bottom: -4px
}
.gf-editor-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: .3rem;
padding: .42rem;
margin: 0;
background: color-mix(in srgb, var(--content-background-color) 88%, #4f46e5 12%);
border: 1px solid var(--content-border-color);
border-bottom: 0;
border-radius: 0 10px 0 0;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55), 0 8px 18px rgba(15, 23, 42, .04)
}
.gf-editor-toolbar + textarea,
.gf-editor-toolbar + .field_with_errors textarea,
.gf-editor-toolbar ~ .preview-results {
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button {
all: unset;
box-sizing: border-box !important;
inline-size: 34px !important;
block-size: 34px !important;
min-inline-size: 34px !important;
min-block-size: 34px !important;
position: relative !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0 !important;
margin: 0 !important;
border: 1px solid rgba(79, 70, 229, .16) !important;
border-radius: 9px !important;
background: rgba(255, 255, 255, .72) !important;
color: var(--overall-text-color) !important;
cursor: pointer !important;
line-height: 1 !important;
box-shadow: none !important;
transform: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base) !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button:hover,
.gf-editor-toolbar button.gf-editor-toolbar-button:focus-visible {
background: rgba(79, 70, 229, .12) !important;
border-color: rgba(79, 70, 229, .34) !important;
color: var(--link-color) !important;
transform: none !important;
box-shadow: 0 6px 14px rgba(79, 70, 229, .1) !important;
outline: none !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button:active {
transform: none !important;
box-shadow: none !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button svg {
inline-size: 17px;
block-size: 17px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round
}
.gf-editor-toolbar button.gf-editor-toolbar-button--text {
font-size: .8rem !important;
font-weight: 800;
font-family: var(--font-family-base);
}
.gf-editor-toolbar-color-tool {
display: inline-flex;
align-items: center;
position: relative;
margin: 0;
}
.gf-editor-toolbar-heading-tool {
display: inline-flex;
align-items: center;
margin: 0;
}
.gf-editor-toolbar-heading-tool button.gf-editor-toolbar-button {
inline-size: 31px !important;
min-inline-size: 31px !important;
border-start-end-radius: 0 !important;
border-end-end-radius: 0 !important;
border-inline-end: 0 !important;
}
.gf-editor-toolbar select.gf-editor-toolbar-heading-select {
appearance: none !important;
-webkit-appearance: none !important;
box-sizing: border-box !important;
inline-size: 42px !important;
block-size: 34px !important;
min-inline-size: 42px !important;
min-block-size: 34px !important;
padding: 0 16px 0 8px !important;
margin: 0 !important;
border: 1px solid rgba(79, 70, 229, .16) !important;
border-start-start-radius: 0 !important;
border-end-start-radius: 0 !important;
border-start-end-radius: 9px !important;
border-end-end-radius: 9px !important;
background: rgba(255, 255, 255, .56) !important;
color: var(--overall-text-color) !important;
font: 800 .75rem/1 var(--font-family-base) !important;
cursor: pointer !important;
box-shadow: none !important;
background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%) !important;
background-position: calc(100% - 10px) 14px, calc(100% - 6px) 14px !important;
background-size: 4px 4px, 4px 4px !important;
background-repeat: no-repeat !important;
}
.gf-editor-toolbar select.gf-editor-toolbar-heading-select:hover,
.gf-editor-toolbar select.gf-editor-toolbar-heading-select:focus-visible {
background-color: rgba(79, 70, 229, .1) !important;
border-color: rgba(79, 70, 229, .34) !important;
color: var(--link-color) !important;
outline: none !important;
}
.gf-editor-toolbar-color-tool button.gf-editor-toolbar-button {
inline-size: 31px !important;
min-inline-size: 31px !important;
border-start-end-radius: 0 !important;
border-end-end-radius: 0 !important;
border-inline-end: 0 !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-color-swatch-button {
all: unset;
box-sizing: border-box !important;
inline-size: 20px !important;
block-size: 34px !important;
min-inline-size: 20px !important;
min-block-size: 34px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0 !important;
margin: 0 !important;
border: 1px solid rgba(79, 70, 229, .16) !important;
border-start-start-radius: 0 !important;
border-end-start-radius: 0 !important;
border-start-end-radius: 9px !important;
border-end-end-radius: 9px !important;
background: rgba(255, 255, 255, .56) !important;
cursor: pointer !important;
box-shadow: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base) !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-color-swatch-button:hover,
.gf-editor-toolbar button.gf-editor-toolbar-color-swatch-button:focus-visible,
.gf-editor-toolbar-color-tool:hover button.gf-editor-toolbar-color-swatch-button,
.gf-editor-toolbar-color-tool:focus-within button.gf-editor-toolbar-color-swatch-button {
background: rgba(79, 70, 229, .1) !important;
border-color: rgba(79, 70, 229, .34) !important;
transform: none !important;
outline: none !important;
box-shadow: 0 6px 14px rgba(79, 70, 229, .08) !important;
}
.gf-editor-toolbar-color-input {
position: absolute !important;
inset-block-start: 0 !important;
inset-inline-end: 0 !important;
inline-size: 20px !important;
block-size: 34px !important;
opacity: 0 !important;
cursor: pointer !important;
pointer-events: auto !important;
z-index: 2 !important;
padding: 0 !important;
margin: 0 !important;
border: 0 !important;
}
.gf-editor-toolbar-color-swatch {
inline-size: 12px;
block-size: 22px;
border-radius: 999px;
border: 1px solid rgba(15, 23, 42, .22);
box-shadow: 0 0 0 1px rgba(255, 255, 255, .7);
}
#report_explanation {
width: 100%;
height: 10em
}
.reportable {
position: relative
}
.report-link-abs {
position: absolute;
top: 0;
right: 0;
font-size: smaller;
margin-right: 16px;
margin-top: 8px
}
.report-list-item:not(:last-child) {
padding-bottom: 20px;
border-bottom: 1px solid gray;
margin-bottom: 20px
}
.report-list-item .inline-form {
margin-right: 5px
}
.report-resolution-options {
display: inline-block;
vertical-align: top;
min-width: 30%
}
.report-resolution-options+.report-resolution-options {
margin-left: 1em
}
.report-resolution-options input[type=submit] {
margin-top: .5em
}
.report-resolution-options textarea {
width: 100%
}
.report-screenshot-control {
font-size: smaller;
padding: .5em 0
}
.unauthorized-code-comparison th {
text-align: left
}
.unauthorized-code-comparison th,.unauthorized-code-comparison td {
padding-right: 1em
}
body:lang(he),body:lang(ar),body:lang(ug),body:lang(ckb) {
direction: rtl
}
:not(:lang(he)):not(:lang(ar)):not(:lang(ug)):not(:lang(ckb)) {
direction: ltr
}
body:lang(he) #main-header,body:lang(ar) #main-header,body:lang(ug) #main-header,body:lang(ckb) #main-header {
direction: ltr
}
:lang(ar) #home-step-1 figure,:lang(he) #home-step-1 figure,:lang(ug) #home-step-1 figure,:lang(ckb) #home-step-1 figure {
float: left
}
:lang(ar) #home-step-2 figure,:lang(he) #home-step-2 figure,:lang(ug) #home-step-2 figure,:lang(ckb) #home-step-2 figure {
float: right
}
#script-info {
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
clear: left;
background-color: var(--content-background-color);
margin: 1.5em 0 0;
box-shadow: var(--shadow-soft);
display: grid;
gap: 1.1rem;
overflow-x: hidden;
overflow-wrap: anywhere;
word-break: break-word;
transition: box-shadow var(--transition-base), border-color var(--transition-base), background-color var(--transition-base)
}
#script-info>* {
min-width: 0
}
#script-info:hover {
border-color: var(--container-glow-stroke);
box-shadow: var(--shadow-hover)
}
#script-content {
margin-top: 1.5em
}
#script-content>*:first-child {
margin-top: 0
}
#script-info header h2 {
margin: .2em 0 0;
font-size: clamp(1.75rem, 2.8vw, 2.4rem);
line-height: 1.15;
font-weight: 700;
letter-spacing: .01em;
overflow-wrap: anywhere
}
#script-description {
margin: 0
}
#version-note,#reported-note,#deleted-note {
font-style: italic;
background-color: var(--alert-background-color);
border: 2px dotted var(--alert-border-color);
color: var(--alert-text-color);
padding: .5em
}
#script-feedback-suggestion {
margin: .75em 0
}
#script-content h3 {
margin-top: 30px
}
.checkup-list {
padding-inline-start:1em}
.checkup-list li {
list-style-type: "✗";
padding-inline-start:.5em}
.checkup-list li::marker {
color: red
}
.checkup-list li.good-check {
list-style-type: "✓"
}
.checkup-list li.good-check::marker {
color: green
}
.script-meta-block {
max-width: 600px;
column-count: 2
}
.script-meta-block>*:last-child {
margin-bottom: 1em
}
.gf-script-card-actions {
display: flex;
justify-content: flex-end;
align-items: center;
flex-wrap: wrap;
gap: 0.55rem;
margin-top: 0.9rem;
}
#install-area .gf-script-card-actions,
#script-links .gf-script-card-actions {
justify-content: flex-start;
margin-top: 0.75rem;
}
#install-area > .gf-script-star-button {
margin-left: .45rem;
min-width: 2.4rem;
min-height: 2.4rem;
}
#install-area > .gf-script-star-button svg {
width: 24px;
height: 24px;
}
.gf-script-install-button,
.gf-script-detail-button,
.gf-script-star-button {
display: inline-flex;
align-items: center;
justify-content: center;
height: 2.2rem;
border-radius: 999px;
border: 1px solid var(--content-border-color);
background: linear-gradient(180deg, rgba(79, 70, 229, 0.12), rgba(79, 70, 229, 0.06));
color: var(--overall-text-color) !important;
text-decoration: none;
box-sizing: border-box;
transition: transform var(--transition-base), background-color var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base), color var(--transition-base);
}
.gf-script-install-button,
.gf-script-install-button:visited,
.gf-script-install-button:hover,
.gf-script-install-button:focus-visible,
.gf-script-detail-button,
.gf-script-detail-button:visited,
.gf-script-detail-button:hover,
.gf-script-detail-button:focus-visible {
text-decoration: none !important;
}
.gf-script-install-button {
gap: 0.45rem;
padding: 0 0.95rem;
font-size: 0.92rem;
font-weight: 700;
letter-spacing: 0.01em;
}
.gf-script-detail-button {
width: 2.2rem;
min-width: 2.2rem;
padding: 0;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
}
.gf-script-star-button {
width: auto;
height: auto;
padding: 0;
margin-left: 0;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
border: none;
background: transparent;
color: var(--overall-text-color) !important;
box-shadow: none;
line-height: 0;
transform: none;
transition: color var(--transition-base);
}
.gf-script-install-button svg,
.gf-script-detail-button svg,
.gf-script-star-button svg {
width: 19px;
height: 19px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
flex: none;
transition: fill var(--transition-base), stroke var(--transition-base), stroke-width var(--transition-base), transform var(--transition-base);
}
.gf-script-install-button:hover,
.gf-script-install-button:focus-visible,
.gf-script-detail-button:hover,
.gf-script-detail-button:focus-visible,
.gf-script-detail-button[data-expanded="true"] {
border-color: var(--link-color);
color: var(--link-color) !important;
box-shadow: none;
outline: none;
}
.gf-script-detail-button[data-expanded="true"] svg {
transform: rotate(45deg);
}
.gf-script-star-button:hover,
.gf-script-star-button:focus,
.gf-script-star-button:focus-visible,
.gf-script-star-button[data-active="true"],
.gf-script-star-button[data-active="true"]:hover,
.gf-script-star-button[data-active="true"]:focus,
.gf-script-star-button[data-active="true"]:focus-visible {
background: transparent !important;
border-color: transparent !important;
box-shadow: none !important;
outline: none !important;
transform: none !important;
}
.gf-script-star-button:hover,
.gf-script-star-button:focus,
.gf-script-star-button:focus-visible {
color: var(--overall-text-color) !important;
}
.gf-script-star-button:hover svg,
.gf-script-star-button:focus-visible svg {
fill: none;
stroke: currentColor;
stroke-width: 2.55;
transform: scale(1.06);
}
.gf-script-star-button[data-active="true"] {
color: #f4b400 !important;
}
.gf-script-star-button[data-active="true"] svg {
stroke: #f4b400;
fill: rgba(244, 180, 0, 0.18);
stroke-width: 2.1;
width: 21px;
height: 21px;
}
.gf-script-star-button[data-active="true"]:hover svg,
.gf-script-star-button[data-active="true"]:focus-visible svg {
stroke-width: 2.65;
transform: scale(1.06);
}
.gf-script-star-button[data-active="true"]:hover,
.gf-script-star-button[data-active="true"]:focus,
.gf-script-star-button[data-active="true"]:focus-visible {
color: #f4b400 !important;
}
.inline-script-stats {
align-items: center;
}
.inline-script-stats dd span relative-time {
white-space: nowrap !important;
display: inline-block !important;
line-height: 1.3;
vertical-align: middle;
}
.inline-script-stats,.inline-script-stats dt,.inline-script-stats dd {
vertical-align: top;
padding: 0;
font-size: small;
}
.inline-script-stats dt,.inline-script-stats dd {
box-sizing: border-box;
overflow-wrap: break-word;
margin: 1px 0
}
.inline-script-stats dt {
font-weight: 700;
text-align: end;
padding-inline-end:1em}
html[data-gfplus-safari] .script-meta-block {
column-count: initial;
}
html[data-gfplus-safari] .inline-script-stats {
display: grid;
grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr);
column-gap: 1.4rem;
row-gap: .32rem;
margin: 0;
}
html[data-gfplus-safari] .inline-script-stats dt,
html[data-gfplus-safari] .inline-script-stats dd {
margin: 0;
break-inside: avoid;
-webkit-column-break-inside: avoid;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(-n+3) {
grid-column: 1;
}
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(-n+3) {
grid-column: 2;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(n+4) {
grid-column: 3;
}
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(n+4) {
grid-column: 4;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(1),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(1),
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(4),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(4) {
grid-row: 1;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(2),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(2),
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(5),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(5) {
grid-row: 2;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(3),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(3),
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(6),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(6) {
grid-row: 3;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(-n+5) {
grid-column: 1;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(-n+5) {
grid-column: 2;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(n+6) {
grid-column: 3;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(n+6) {
grid-column: 4;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(1),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(1),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(6),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(6) {
grid-row: 1;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(2),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(2),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(7),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(7) {
grid-row: 2;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(3),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(3),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(8),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(8) {
grid-row: 3;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(4),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(4),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(9),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(9) {
grid-row: 4;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(5),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(5),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(10),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(10) {
grid-row: 5;
}
dd.script-list-ratings {
margin-top: 0;
margin-bottom: 0;
display: flex !important;
align-items: center !important;
gap: 6px !important;
overflow: visible;
overflow-wrap: normal;
word-break: normal;
white-space: nowrap;
}
dd.script-list-ratings > span {
display: inline-flex !important;
align-items: center !important;
gap: 4px !important;
overflow: visible;
flex-wrap: nowrap !important;
overflow-wrap: normal;
word-break: normal;
white-space: nowrap;
}
dd.script-list-ratings span.good-rating-count,
dd.script-list-ratings span.ok-rating-count,
dd.script-list-ratings span.bad-rating-count {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
flex: 0 0 auto !important;
min-width: 2.8em !important;
box-sizing: border-box !important;
margin: 0 !important;
padding: .1em .5em !important;
line-height: 1.1 !important;
overflow-wrap: normal !important;
word-break: normal !important;
white-space: nowrap !important;
}
dd.script-list-ratings span.good-rating-count { color: #4CAF50 !important; }
dd.script-list-ratings span.ok-rating-count { color: #FFC107 !important; }
dd.script-list-ratings span.bad-rating-count { color: #F44336 !important; }
@media screen and (max-width: 600px) {
.script-meta-block {
max-width: 100%;
column-count: initial;
}
.inline-script-stats,
html[data-gfplus-safari] .inline-script-stats,
html[data-gfplus-safari] #script-stats.inline-script-stats {
display: grid;
grid-template-columns: minmax(6.8rem, 42%) minmax(0, 1fr);
column-gap: .75rem;
row-gap: .34rem;
align-items: start;
margin: 0;
}
.inline-script-stats dt,
.inline-script-stats dd,
html[data-gfplus-safari] .inline-script-stats dt,
html[data-gfplus-safari] .inline-script-stats dd,
html[data-gfplus-safari] #script-stats.inline-script-stats dt,
html[data-gfplus-safari] #script-stats.inline-script-stats dd {
grid-column: auto !important;
grid-row: auto !important;
min-width: 0;
margin: 0;
break-inside: auto;
-webkit-column-break-inside: auto;
}
.inline-script-stats dt {
grid-column: 1 !important;
text-align: start;
padding-inline-end: .35rem;
}
.inline-script-stats dd {
grid-column: 2 !important;
overflow-wrap: anywhere;
}
dd.script-list-ratings {
justify-content: flex-start !important;
white-space: normal !important;
}
dd.script-list-ratings > span {
flex-wrap: wrap !important;
gap: 3px !important;
white-space: normal !important;
}
dd.script-list-ratings span.good-rating-count,
dd.script-list-ratings span.ok-rating-count,
dd.script-list-ratings span.bad-rating-count {
min-width: 2.65em !important;
padding: .08em .38em !important;
}
}
.script-antifeatures span[title] {
text-decoration: underline;
text-decoration-style: dotted
}
.script-show-compatibility {
vertical-align: bottom
}
.browser-compatible,.browser-incompatible,.browser-incompatible-marker {
width: 16px;
height: 16px
}
.browser-incompatible {
opacity: .5
}
.browser-incompatible-marker {
position: absolute
}
.script-lock-appeal-actions form {
display: inline-block;
margin-top: 1em
}
.change-script-set section {
border-bottom: 1px solid #DDDDDD;
padding-bottom: 1em
}
.change-script-set textarea {
height: 5em
}
.change-script-set .selection-box {
width: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: 1em
}
@media screen and (max-width: 720px) {
.change-script-set .selection-box {
width:100%
}
}
.change-script-set select[multiple] {
width: 100%
}
.change-script-set {
display: grid;
gap: 1.25rem;
padding: 1.25rem;
background: linear-gradient(180deg, rgba(79, 70, 229, .05), rgba(255, 255, 255, .96));
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-shadow: var(--shadow-soft);
}
.change-script-set section {
margin: 0;
}
.change-script-set button {
margin-left: 0;
}
.change-script-set #script-set-scripts {
display: grid;
grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
gap: 1rem;
align-items: start;
}
.change-script-set .selection-box,
.change-script-set #script-set-scripts > .form-control:not(.selection-box) {
margin-bottom: 0;
padding: 1rem;
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7), 0 10px 24px rgba(15, 23, 42, .06);
}
.change-script-set.gf-set-editor-enhanced select[name="remove-scripts-included[]"],
.change-script-set.gf-set-editor-enhanced button[name="remove-selected-scripts"] {
display: none !important;
}
.gf-set-script-list-panel {
display: grid;
gap: .85rem;
}
.gf-set-script-list-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: .75rem;
}
.gf-set-script-list-title {
font-size: 1rem;
font-weight: 700;
color: var(--overall-text-color);
}
.gf-set-script-list-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2rem;
padding: .25rem .65rem;
border-radius: 999px;
background: rgba(79, 70, 229, .12);
color: var(--link-color);
font-size: .82rem;
font-weight: 700;
}
.gf-set-script-list {
display: grid;
gap: .6rem;
}
.gf-set-script-row {
display: flex;
align-items: center;
gap: .75rem;
padding: .8rem .9rem;
background: linear-gradient(180deg, rgba(79, 70, 229, .05), rgba(79, 70, 229, .02));
border: 1px solid rgba(79, 70, 229, .12);
border-radius: var(--border-radius-small);
transition: border-color var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}
.gf-set-script-row:hover {
border-color: rgba(79, 70, 229, .28);
box-shadow: 0 10px 20px rgba(79, 70, 229, .08);
transform: translateY(-1px);
}
.gf-set-script-name {
flex: 1;
min-width: 0;
color: var(--overall-text-color);
font-weight: 600;
overflow-wrap: anywhere;
}
.gf-set-script-remove {
display: inline-grid;
place-items: center;
width: 1.35rem;
height: 1.35rem;
min-width: 1.35rem;
min-height: 1.35rem;
margin: 0;
padding: 0;
border: 0;
border-radius: 0;
background: transparent;
color: #b91c1c !important;
box-shadow: none;
cursor: pointer;
transform: none !important;
}
.gf-set-script-remove:hover,
.gf-set-script-remove:focus-visible {
background: transparent;
color: #991b1b !important;
box-shadow: none;
transform: none !important;
}
.gf-set-script-remove svg {
width: 16px;
height: 16px;
stroke: currentColor;
stroke-width: 2.25;
fill: none;
}
.gf-set-script-empty {
padding: .95rem 1rem;
background: rgba(148, 163, 184, .08);
border: 1px dashed rgba(100, 116, 139, .28);
border-radius: var(--border-radius-small);
color: var(--texty-link-visited-color);
}
.gf-set-editor-footer {
display: flex;
justify-content: flex-end;
align-items: center;
gap: .75rem;
padding-top: .25rem;
}
.gf-set-editor-actions {
display: flex;
justify-content: flex-end;
margin-top: .85rem;
}
@media screen and (max-width: 820px) {
.change-script-set #script-set-scripts {
grid-template-columns: 1fr;
}
}
.add-script-set label {
font-weight: 700;
display: block
}
.add-automatic-script-set-4>* {
vertical-align: top
}
.history_versions {
display: table;
padding: 0
}
.history_versions>li {
display: table-row
}
.diff-controls,.version-number,.version-date,.version-changelog {
display: table-cell;
padding-bottom: .5em
}
.diff-controls,.version-number,.version-date {
white-space: nowrap;
padding-right: 1em
}
.version-changelog {
overflow-wrap: anywhere
}
.version-changelog img {
max-width: 100%
}
.version-changelog p:first-child {
margin-top: 0
}
.version-changelog p:last-child {
margin-bottom: 0
}
.remove-attachment {
margin-top: 20px
}
.remove-attachment input {
margin-left: 0
}
.sidebarred {
display: flex
}
.sidebarred-main-content {
flex: 1
}
.sidebar {
width: 200px;
padding-top: 1.75em;
padding-bottom: .75em;
margin-inline-start:1.5em;flex: none
}
@media screen and (min-width: 801px) {
.sidebar {
position: sticky;
top: var(--gfplus-sidebar-sticky-top, 1rem);
align-self: flex-start;
box-sizing: border-box;
max-height: none;
overflow: visible;
scrollbar-gutter: auto;
will-change: top;
}
}
.close-sidebar,.open-sidebar {
cursor: pointer
}
.close-sidebar {
display: none
}
.open-sidebar {
visibility: hidden;
float: right;
background-color: var(--sidebar-background);
padding: 2px 1.2vw;
margin-left: 1.2vw;
margin-right: -1.2vw;
border-radius: 6px 0 0 6px;
border-width: 1px 0 1px 1px;
border-style: solid;
border-color: gray
}
.sidebar-title {
flex: 1
}
.gf-sidebar-scroll-controls {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: .5rem;
margin-top: .9rem;
}
.sidebar button.gf-sidebar-scroll-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 2.25rem;
margin: 0;
padding: .4rem;
border: 1px solid var(--content-border-color);
border-radius: 7px;
background: var(--content-background-color);
color: var(--overall-text-color) !important;
box-shadow: none !important;
cursor: pointer;
transform: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}
.sidebar button.gf-sidebar-scroll-button:hover,
.sidebar button.gf-sidebar-scroll-button:focus-visible {
background: var(--inactive-item-background-color);
border-color: var(--link-color);
color: var(--link-color) !important;
box-shadow: none !important;
outline: none;
transform: none !important;
}
.sidebar button.gf-sidebar-scroll-button:focus {
box-shadow: none !important;
outline: none;
}
.sidebar button.gf-sidebar-scroll-button:active {
box-shadow: none !important;
transform: translateY(1px) !important;
}
.sidebar button.gf-sidebar-scroll-button svg {
width: 18px;
height: 18px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
@media screen and (max-width: 800px) {
.sidebarred {
display:block;
position: relative
}
.sidebar {
position: absolute;
right: 0;
top: 0;
z-index: 40;
background: var(--sidebar-background);
padding-top: 0;
padding-left: 1em;
padding-right: 1em;
max-height: min(calc(100vh - 1.5rem), calc(100dvh - 1.5rem));
border-width: 1px 0 1px 1px;
border-style: solid;
border-color: gray;
border-radius: 6px 0 0 6px;
overflow-y: auto;
overscroll-behavior: contain;
box-shadow: var(--shadow-soft)
}
.sidebar.collapsed {
display: none
}
.close-sidebar {
display: flex;
margin-bottom: 1.5em;
background-color: var(--close-sidebar-background);
border-bottom: 1px solid var(--close-sidebar-border-bottom);
margin-left: -16px;
margin-right: -16px;
padding: .25em 1.2vw .25em 16px
}
.open-sidebar.sidebar-collapsed {
visibility: visible;
margin-right: 0;
position: relative;
right: -0.35rem;
z-index: 39;
box-shadow: var(--shadow-soft)
}
html.gfplus-mobile-sidebar-stuck .sidebar:not(.collapsed) {
position: fixed;
top: .75rem;
right: 0;
}
html.gfplus-mobile-sidebar-stuck .open-sidebar.sidebar-collapsed {
position: fixed;
top: .75rem;
right: 0;
}
}
@media screen and (min-width: 800px) {
.sidebarred-main-content {
max-width:calc(100% - 224px)
}
}
@media screen and (max-width: 400px) {
.open-sidebar {
margin-right:0
}
.close-sidebar {
padding-right: 2.4vw;
margin-right: -1em
}
}
.tabs {
list-style: none;
padding: 0 1em;
margin: 0 -1em;
display: flex;
position: relative;
top: -3.5px;
flex-wrap: wrap
}
.tabs>* {
align-items: stretch
}
.tabs>*>* {
padding: .25em .5em .5em;
display: block
}
.tabs a {
text-decoration: none;
cursor: pointer
}
.tabs .current,.tabs>*:not(.current) a:hover,.tabs>*:not(.current) a:focus {
background: var(--tab-active-background-color);
box-shadow: inset 1px 0 var(--tab-active-box-shadow-color),inset -1px 0 var(--tab-active-box-shadow-color),inset 0 -1px var(--tab-active-box-shadow-color)
}
.tabs .current {
border-top: 7px solid var(--tab-active-top-border-color)
}
.tabs>*:not(.current) a {
margin-top: 3.5px;
padding-top: calc(.25em + 3.5px)
}
.user-content {
background: linear-gradient(to right,var(--user-content-background-color-gradient-1),var(--user-content-background-color-gradient-2) 1em);
border-left: 2px solid var(--user-content-border-left-color);
padding: .5em 1em;
overflow-x: auto
}
.user-content>p:first-child {
margin-top: 0
}
.user-content>p:last-child {
margin-bottom: 0
}
.user-content img {
max-width: 100%
}
.user-content img.gfplus-standalone-lightbox-trigger,
#script-content img.gfplus-standalone-lightbox-trigger {
cursor: zoom-in
}
.user-screenshots * {
vertical-align: middle
}
.user-screenshots a {
text-decoration: none
}
.comment-screenshot-control {
margin: 10px 0
}
.remove-images {
display: flex;
margin-top: 5px
}
.remove-image {
border: 2px solid black;
padding: 5px;
display: flex;
justify-content: space-between;
flex-direction: column
}
.remove-image:not(:first-child) {
margin-left: 5px
}
.remove-image img {
display: block
}
.remove-image-selecter,.comment .user-content .user-screenshots {
margin-top: 10px
}
#additional-info .user-screenshots {
margin-top: 1em
}
.user-content blockquote {
margin-left: 10px;
padding-left: 10px;
border-left: 2px solid #CCC
}
.user-content>ol:first-child,.user-content>ul:first-child {
margin-top: 0
}
.user-content>ol:last-child,.user-content>ul:last-child {
margin-bottom: 0
}
@keyframes lum-fade {
0% {
opacity: 0
}
to {
opacity: 1
}
}
@keyframes lum-fadeZoom {
0% {
transform: scale(.5);
opacity: 0
}
to {
transform: scale(1);
opacity: 1
}
}
@keyframes lum-loader-rotate {
0% {
transform: translate(-50%,-50%) rotate(0)
}
50% {
transform: translate(-50%,-50%) rotate(-180deg)
}
to {
transform: translate(-50%,-50%) rotate(-360deg)
}
}
@keyframes lum-loader-before {
0% {
transform: scale(1)
}
10% {
transform: scale(1.2) translate(6px)
}
25% {
transform: scale(1.3) translate(8px)
}
40% {
transform: scale(1.2) translate(6px)
}
50% {
transform: scale(1)
}
60% {
transform: scale(.8) translate(6px)
}
75% {
transform: scale(.7) translate(8px)
}
90% {
transform: scale(.8) translate(6px)
}
to {
transform: scale(1)
}
}
@keyframes lum-loader-after {
0% {
transform: scale(1)
}
10% {
transform: scale(1.2) translate(-6px)
}
25% {
transform: scale(1.3) translate(-8px)
}
40% {
transform: scale(1.2) translate(-6px)
}
50% {
transform: scale(1)
}
60% {
transform: scale(.8) translate(-6px)
}
75% {
transform: scale(.7) translate(-8px)
}
90% {
transform: scale(.8) translate(-6px)
}
to {
transform: scale(1)
}
}
.lum-lightbox {
background: #0009
}
.lum-lightbox.lum-open {
position: fixed !important;
inset: 0 !important;
z-index: 2147483000;
display: block;
overflow: hidden !important
}
html.gfplus-lightbox-open,
html.gfplus-lightbox-open body {
overflow: hidden !important;
overscroll-behavior: none;
touch-action: none
}
.lum-lightbox-inner {
position: absolute;
top: 2.5%;
right: 2.5%;
bottom: 2.5%;
left: 2.5%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden
}
.lum-lightbox-inner img {
position: relative
}
.lum-lightbox-image-wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
max-width: 100%;
height: 100%;
max-height: 100%;
overflow: hidden
}
.lum-lightbox-position-helper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 100%;
max-height: 100%;
margin: auto
}
.lum-lightbox-image-wrapper .lum-img {
width: auto;
height: auto;
max-width: 100%;
max-height: calc(100vh - 7rem);
max-height: calc(100dvh - 7rem);
object-fit: contain
}
.lum-lightbox-inner .lum-lightbox-caption {
display: block;
flex: 0 0 auto;
width: min(700px, 100%);
margin: .75rem auto 0;
color: #fff;
max-width: 700px;
text-align: center;
line-height: 1.35
}
.lum-loading .lum-lightbox-loader {
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: 66px;
height: 20px;
animation: lum-loader-rotate 1.8s infinite linear
}
.lum-lightbox-loader:before,.lum-lightbox-loader:after {
content: "";
display: block;
width: 20px;
height: 20px;
position: absolute;
top: 50%;
margin-top: -10px;
border-radius: 20px;
background: #ffffffe6
}
.lum-lightbox-loader:before {
left: 0;
animation: lum-loader-before 1.8s infinite linear
}
.lum-lightbox-loader:after {
right: 0;
animation: lum-loader-after 1.8s infinite linear;
animation-delay: -.9s
}
.lum-lightbox.lum-opening {
animation: lum-fade .18s ease-out
}
.lum-lightbox.lum-opening .lum-lightbox-inner {
animation: lum-fadeZoom .18s ease-out
}
.lum-lightbox.lum-closing {
animation: lum-fade .3s ease-in;
animation-direction: reverse
}
.lum-lightbox.lum-closing .lum-lightbox-inner {
animation: lum-fadeZoom .3s ease-in;
animation-direction: reverse
}
.lum-img {
transition: opacity .12s ease-out
}
.lum-lightbox img.gfplus-lightbox-zoomable {
cursor: zoom-in;
touch-action: none;
transform-origin: center center;
transition: opacity .12s ease-out, transform .12s ease-out;
will-change: transform
}
.lum-lightbox img.gfplus-lightbox-zoomed {
cursor: grab
}
.lum-lightbox img.gfplus-lightbox-dragging {
cursor: grabbing;
transition: opacity .12s ease-out
}
.lum-loading .lum-img {
opacity: 0
}
.lum-gallery-button {
display: inline-flex;
align-items: center;
justify-content: center;
overflow: visible;
text-indent: -9999px;
font-size: 0;
line-height: 0;
white-space: nowrap;
background: rgba(15, 23, 42, .46) !important;
color: #fff !important;
border: 1px solid rgba(255, 255, 255, .18) !important;
border-radius: 999px;
margin: 0;
padding: 0;
outline: 0;
position: absolute;
z-index: 2;
top: 50%;
transform: translateY(-50%) !important;
height: 48px;
max-height: none;
width: 48px;
cursor: pointer;
box-shadow: 0 8px 20px rgba(0, 0, 0, .22) !important;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: background-color .16s ease, border-color .16s ease, box-shadow .16s ease, transform .16s ease
}
.lum-gallery-button:hover,
.lum-gallery-button:focus-visible {
background: rgba(15, 23, 42, .66) !important;
border-color: rgba(255, 255, 255, .32) !important;
box-shadow: 0 10px 24px rgba(0, 0, 0, .28) !important;
transform: translateY(-50%) !important;
outline: none
}
.lum-gallery-button:focus {
outline: none
}
.lum-gallery-button:active {
background: rgba(15, 23, 42, .74) !important;
transform: translateY(-50%) !important
}
.lum-close-button {
position: absolute;
z-index: 3;
right: 12px;
top: 12px;
width: 40px;
height: 40px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, .2);
background: rgba(15, 23, 42, .52);
box-shadow: 0 8px 20px rgba(0, 0, 0, .22);
opacity: 1;
cursor: pointer;
transition: background-color .16s ease, border-color .16s ease, box-shadow .16s ease
}
.lum-close-button:hover {
background: rgba(15, 23, 42, .72);
border-color: rgba(255, 255, 255, .34);
box-shadow: 0 10px 24px rgba(0, 0, 0, .28)
}
.lum-close-button,
.lum-close-button:hover,
.lum-close-button:focus-visible,
.lum-close-button:active {
transform: none !important
}
.lum-close-button:before,.lum-close-button:after {
position: absolute;
left: 50%;
top: 50%;
content: " ";
height: 20px;
width: 2px;
border-radius: 999px;
background-color: rgba(255, 255, 255, .95)
}
.lum-close-button:before {
transform: translate(-50%,-50%) rotate(45deg)
}
.lum-close-button:after {
transform: translate(-50%,-50%) rotate(-45deg)
}
.lum-previous-button {
left: clamp(10px,3vw,28px)
}
.lum-next-button {
right: clamp(10px,3vw,28px)
}
.lum-gallery-button:after {
content: "";
display: block;
position: absolute;
top: 50%;
left: 50%;
width: 13px;
height: 13px;
border: 0;
border-top: 2.5px solid currentColor;
box-shadow: none
}
.lum-previous-button:after {
transform: translate(-35%,-50%) rotate(-45deg);
border-left: 2.5px solid currentColor;
border-radius: 2px 0 0
}
.lum-next-button:after {
transform: translate(-65%,-50%) rotate(45deg);
border-right: 2.5px solid currentColor;
border-radius: 0 2px 0 0
}
@media (max-width: 460px) {
.lum-lightbox,
.lum-lightbox-inner {
overflow: hidden !important
}
.lum-lightbox-inner {
top: .75rem;
right: .75rem;
bottom: .75rem;
left: .75rem
}
.lum-gallery-button {
width: 40px;
height: 40px;
top: auto;
bottom: 4.25rem;
transform: none !important;
background: rgba(15, 23, 42, .58) !important;
box-shadow: 0 8px 18px rgba(0, 0, 0, .24) !important
}
.lum-gallery-button:hover,
.lum-gallery-button:focus-visible {
transform: none !important
}
.lum-gallery-button:active {
transform: none !important
}
.lum-previous-button {
left: 12px
}
.lum-next-button {
right: 12px
}
.lum-gallery-button:after {
width: 11px;
height: 11px;
border-top-width: 2.25px
}
.lum-previous-button:after {
border-left-width: 2.25px
}
.lum-next-button:after {
border-right-width: 2.25px
}
.lum-lightbox-image-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 100% !important;
max-width: 100% !important;
height: calc(100dvh - 1.5rem) !important;
max-height: calc(100dvh - 1.5rem) !important;
overflow: hidden !important
}
.lum-lightbox-caption {
width: 100%;
position: static;
bottom: auto;
margin-top: .55rem
}
.lum-lightbox-position-helper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 100%;
max-height: 100%;
margin: auto
}
.lum-lightbox-inner img {
width: auto !important;
height: auto !important;
max-width: 100% !important;
max-height: calc(100dvh - 5.5rem) !important;
object-fit: contain
}
}
:root {
color-scheme: light;
--font-family-base: "Inter", "Open Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-family-monospace: "JetBrains Mono", "Fira Code", "Source Code Pro", monospace;
--overall-background-color: #f5f7fb;
--overall-text-color: #111827;
--overall-text-color-icon: #e5e7eb;
--link-color: #4f46e5;
--link-color-icon: #e5bcbc;
--link-visited-color: #4338ca;
--texty-link-visited-color: #4b5563;
--content-background-color: #ffffff;
--content-border-color: #e2e8f0;
--content-box-shadow-color: rgba(15, 23, 42, 0.08);
--content-separator-color: #edf1f7;
--tab-active-background-color: rgba(79, 70, 229, 0.12);
--tab-active-box-shadow-color: rgba(79, 70, 229, 0.18);
--tab-active-top-border-color: #4f46e5;
--inactive-item-background-color: #f3f4f6;
--code-background-color: #f4f2ff;
--user-content-background-color-gradient-1: #f8fafc;
--user-content-background-color-gradient-2: #ffffff;
--user-content-border-left-color: #e2e8f0;
--list-option-background-color-gradient-1: #ffffff;
--list-option-background-color-gradient-2: #f5f7fb;
--list-option-hover-background-color-gradient-1: #f4f7ff;
--list-option-hover-background-color-gradient-2: #e1e7ff;
--list-option-hover-box-shadow-top: rgba(15, 23, 42, 0.06);
--list-option-hover-box-shadow-bottom: rgba(79, 70, 229, 0.1);
--notice-background-color: #e0f2fe;
--notice-border-color: #0284c7;
--notice-text-color: #0f172a;
--alert-background-color: #fef3c7;
--alert-border-color: #f59e0b;
--alert-text-color: #78350f;
--chart-background-color: #61a5fa;
--chart-border-color: #61a5fa;
--install-stats-bar-color: #61a5fa;
--install-stats-bar-hover-color: #61a5fa;
--install-stats-grid-color: #dbe4f0;
--install-stats-text-color: #334155;
--highlight-background-color: #fef9c3;
--rating-icon-good-border-color: #16a34a;
--rating-icon-good-background-color: rgba(22, 163, 74, 0.12);
--rating-icon-good-color: #166534;
--rating-icon-ok-border-color: #ca8a04;
--rating-icon-ok-background-color: rgba(202, 138, 4, 0.14);
--rating-icon-ok-color: #92400e;
--rating-icon-bad-border-color: #dc2626;
--rating-icon-bad-background-color: rgba(220, 38, 38, 0.12);
--rating-icon-bad-color: #7f1d1d;
--expander-color: #4f46e5;
--expander-background-color: rgba(79, 70, 229, 0.08);
--pagination-background-color: rgba(79, 70, 229, 0.08);
--pagination-hover-background-color: rgba(79, 70, 229, 0.18);
--diff-del-background: #fee2e2;
--diff-del-color: #b91c1c;
--diff-ins-background: #dcfce7;
--diff-ins-color: #047857;
--diff-del-strong-background: #fecaca;
--diff-ins-strong-background: #bbf7d0;
--diff-block-info: #64748b;
--list-option-button-background-color: #ffffff;
--list-option-button-color: #0f172a;
--list-option-button-border-color: #d0d5dd;
--list-option-button-background-color-gradient-1: #ffffff;
--list-option-button-background-color-gradient-2: #f5f7fb;
--code-container-border-color: #e2e8f0;
--prettyprint-background-color: #ffffff;
--prettyprint-color: #111827;
--sidebar-background: #ffffff;
--close-sidebar-background: #f1f5f9;
--close-sidebar-border-bottom: #cbd5f5;
--border-radius-small: 6px;
--border-radius-medium: 12px;
--border-radius-large: 18px;
--shadow-soft: 0 6px 20px rgba(15, 23, 42, 0.07);
--shadow-hover: 0 8px 24px rgba(15, 23, 42, 0.1);
--focus-ring-color: rgba(79, 70, 229, 0.45);
--transition-base: 160ms ease;
}
.code-container pre.prettyprint,
.code-container pre.prettyprint .pln,
.code-container pre.prettyprint .com,
.code-container pre.prettyprint .kwd,
.code-container pre.prettyprint .str,
.code-container pre.prettyprint .typ {
font-size: 0.85rem !important;
line-height: 1.4 !important;
font-family: "Fira Code", "Consolas", "Menlo", monospace !important;
}
/* Highlight.js theme */
pre.gf-hljs {
min-width: calc(100% - 6px);
background-color: var(--hljs-bg);
color: var(--hljs-text);
border: 1px solid var(--hljs-border);
border-radius: var(--border-radius-small);
padding: 0;
overflow: auto;
display: flex;
gap: 0;
}
pre.gf-hljs .hljs-line-numbers {
flex: 0 0 auto;
padding: 0 .75em .85em;
background-color: var(--hljs-bg);
color: var(--hljs-line-number);
font-family: var(--font-family-monospace);
font-size: var(--hljs-font-size);
line-height: var(--hljs-line-height);
text-align: right;
white-space: pre;
user-select: none;
border-right: 1px solid var(--hljs-border);
background-image: linear-gradient(
to bottom,
transparent 0,
transparent var(--hljs-line-height),
var(--hljs-bg-alt) var(--hljs-line-height),
var(--hljs-bg-alt) calc(var(--hljs-line-height) * 2)
);
background-repeat: repeat-y;
background-size: 100% calc(var(--hljs-line-height) * 2);
background-attachment: local;
}
pre.gf-hljs code.hljs {
display: block;
flex: 0 0 auto;
min-width: 100%;
width: max-content;
padding: 0 1em .85em;
background: transparent;
color: inherit;
font-family: var(--font-family-monospace);
font-size: var(--hljs-font-size);
line-height: var(--hljs-line-height);
white-space: pre;
background-image: linear-gradient(
to bottom,
transparent 0,
transparent var(--hljs-line-height),
var(--hljs-bg-alt) var(--hljs-line-height),
var(--hljs-bg-alt) calc(var(--hljs-line-height) * 2)
);
background-repeat: repeat-y;
background-size: 100% calc(var(--hljs-line-height) * 2);
background-attachment: local;
}
pre.gf-hljs.wrap code.hljs {
white-space: pre-wrap;
flex: 1 1 auto;
min-width: 0;
width: 100%;
overflow-wrap: anywhere;
word-break: break-word;
line-break: anywhere;
}
.hljs-comment,.hljs-quote {
color: var(--hljs-comment);
font-style: italic;
}
.hljs-keyword,.hljs-selector-tag,.hljs-subst {
color: var(--hljs-keyword);
}
.hljs-number,.hljs-literal,.hljs-symbol,.hljs-bullet {
color: var(--hljs-number);
}
.hljs-string,.hljs-doctag,.hljs-built_in,.hljs-builtin-name {
color: var(--hljs-string);
}
.hljs-title,.hljs-section,.hljs-name {
color: var(--hljs-title);
font-weight: 600;
}
.hljs-attr,.hljs-attribute {
color: var(--hljs-attr);
}
.hljs-tag {
color: var(--hljs-tag);
}
.hljs-meta,.hljs-link {
color: var(--hljs-meta);
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: 700;
}
.hljs-addition {
background-color: var(--hljs-add-bg);
color: var(--hljs-add-text);
}
.hljs-deletion {
background-color: var(--hljs-del-bg);
color: var(--hljs-del-text);
}
:root[data-theme="light"] {
--hljs-bg: #ffffff;
--hljs-bg-alt: #f4f7fb;
--hljs-line-height: 24px;
--hljs-font-size: 14px;
--hljs-border: #e2e8f0;
--hljs-text: #0f172a;
--hljs-line-number: #94a3b8;
--hljs-comment: #64748b;
--hljs-keyword: #6d28d9;
--hljs-number: #b45309;
--hljs-string: #15803d;
--hljs-title: #1d4ed8;
--hljs-attr: #c2410c;
--hljs-tag: #0f766e;
--hljs-meta: #475569;
--hljs-add-bg: #dcfce7;
--hljs-add-text: #14532d;
--hljs-del-bg: #fee2e2;
--hljs-del-text: #7f1d1d;
}
#user-script-sets {
margin-top: 0px;
}
/* User Navigation Icons and Panels */
.gf-user-nav-icons {
display: inline-flex;
align-items: center;
gap: 0.5em;
margin-left: 0.75em;
vertical-align: middle;
}
.gf-user-icon {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: var(--border-radius-small);
cursor: pointer;
background: transparent;
border: 1px solid transparent;
transition: background-color var(--transition-base), border-color var(--transition-base);
}
.gf-user-icon:hover,
.gf-user-icon.active {
background-color: rgb(255 122 122 / 16%);
border-color: rgba(255, 122, 122, 0.2);
}
.gf-user-icon svg {
width: 18px;
height: 18px;
stroke: var(--overall-text-color-icon);
fill: none;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
transition: stroke var(--transition-base);
}
.gf-user-icon:hover svg {
stroke: var(--link-color-icon);
}
.gf-user-icon--settings:hover svg {
fill: var(--link-color-icon);
}
.gf-user-icon--settings svg {
fill: currentColor;
stroke: none;
}
/* User Panels */
.gf-user-panel {
position: absolute;
top: calc(100% + 8px);
right: 0;
min-width: 220px;
background: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-shadow: var(--shadow-soft);
padding: 0.5em 0;
z-index: 1000;
display: none;
opacity: 0;
transform: translateY(-8px);
transition: opacity var(--transition-base), transform var(--transition-base);
}
.gf-user-panel.active {
display: block;
opacity: 1;
transform: translateY(0);
}
.gf-user-panel a {
display: block;
padding: 0.75em 1.25em;
color: #111827 !important;
text-decoration: none;
font-weight: 500;
font-size: 14px;
transition: background-color var(--transition-base), color var(--transition-base);
}
.gf-user-panel a:visited {
color: var(--overall-text-color);
}
.gf-user-panel a:hover {
background: linear-gradient(135deg, rgba(79, 70, 229, 0.12), rgba(79, 70, 229, 0.06));
color: var(--link-color);
}
.gf-user-panel-separator {
height: 1px;
background-color: var(--content-separator-color);
margin: 0.5em 0;
}
`;
// ============================================================================
// Dark Theme
// ============================================================================
const DARK_CSS = `
:root {
color-scheme: dark;
scrollbar-color: #334155 #0b111a;
--font-family-base: "Inter", "Open Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-family-monospace: "JetBrains Mono", "Fira Code", "Source Code Pro", monospace;
--overall-background-color: #0d1117;
--overall-text-color: #e6edf3;
--link-color: #78a9ff;
--link-visited-color: #a8c7fa;
--texty-link-visited-color: #a7b1bd;
--content-background-color: #151b23;
--content-border-color: #27313d;
--content-box-shadow-color: rgba(0, 0, 0, 0.28);
--content-separator-color: #202934;
--tab-active-background-color: rgba(120, 169, 255, 0.12);
--tab-active-box-shadow-color: rgba(120, 169, 255, 0.18);
--tab-active-top-border-color: #78a9ff;
--inactive-item-background-color: #1a222d;
--code-background-color: #0f172a;
--user-content-background-color-gradient-1: #151b23;
--user-content-background-color-gradient-2: #131922;
--user-content-border-left-color: #27313d;
--list-option-background-color-gradient-1: #151b23;
--list-option-background-color-gradient-2: #131922;
--list-option-hover-background-color-gradient-1: #1b2633;
--list-option-hover-background-color-gradient-2: #18212c;
--list-option-hover-box-shadow-top: rgba(0, 0, 0, 0.24);
--list-option-hover-box-shadow-bottom: rgba(120, 169, 255, 0.12);
--notice-background-color: #0f1a2a;
--notice-border-color: #38bdf8;
--notice-text-color: #e5e7eb;
--alert-background-color: #2f2411;
--alert-border-color: #f59e0b;
--alert-text-color: #fde68a;
--chart-background-color: #61a5fa;
--chart-border-color: #61a5fa;
--install-stats-bar-color: #61a5fa;
--install-stats-bar-hover-color: #61a5fa;
--install-stats-grid-color: #263449;
--install-stats-text-color: #cbd5e1;
--highlight-background-color: #3a2f1a;
--rating-icon-good-border-color: #22c55e;
--rating-icon-good-background-color: rgba(34, 197, 94, 0.18);
--rating-icon-good-color: #bbf7d0;
--rating-icon-ok-border-color: #eab308;
--rating-icon-ok-background-color: rgba(234, 179, 8, 0.18);
--rating-icon-ok-color: #facc15;
--rating-icon-bad-border-color: #f87171;
--rating-icon-bad-background-color: rgba(248, 113, 113, 0.18);
--rating-icon-bad-color: #fca5a5;
--expander-color: #60a5fa;
--expander-background-color: rgba(59, 130, 246, 0.2);
--pagination-background-color: rgba(59, 130, 246, 0.18);
--pagination-hover-background-color: rgba(59, 130, 246, 0.32);
--diff-del-background: rgba(248, 113, 113, 0.18);
--diff-del-color: #fca5a5;
--diff-ins-background: rgba(34, 197, 94, 0.18);
--diff-ins-color: #86efac;
--diff-del-strong-background: rgba(248, 113, 113, 0.28);
--diff-ins-strong-background: rgba(34, 197, 94, 0.28);
--diff-block-info: #94a3b8;
--list-option-button-background-color: #151b23;
--list-option-button-color: #e6edf3;
--list-option-button-border-color: #27313d;
--list-option-button-background-color-gradient-1: #151b23;
--list-option-button-background-color-gradient-2: #131922;
--code-container-border-color: #27313d;
--prettyprint-background-color: #111820;
--prettyprint-color: #e6edf3;
--sidebar-background: #121820;
--close-sidebar-background: #19212b;
--close-sidebar-border-bottom: #27313d;
--border-radius-small: 6px;
--border-radius-medium: 12px;
--border-radius-large: 18px;
--shadow-soft: 0 8px 24px rgba(0, 0, 0, 0.28);
--shadow-hover: 0 10px 28px rgba(0, 0, 0, 0.34);
--container-glow-stroke: rgba(120, 169, 255, 0.22);
--container-glow-color: rgba(120, 169, 255, 0.08);
--hljs-bg: #0f172a;
--hljs-bg-alt: #182235;
--hljs-line-height: 24px;
--hljs-font-size: 14px;
--hljs-border: #1f2937;
--hljs-text: #e5e7eb;
--hljs-line-number: #64748b;
--hljs-comment: #94a3b8;
--hljs-keyword: #a78bfa;
--hljs-number: #f59e0b;
--hljs-string: #34d399;
--hljs-title: #60a5fa;
--hljs-attr: #f97316;
--hljs-tag: #22d3ee;
--hljs-meta: #94a3b8;
--hljs-add-bg: rgba(34, 197, 94, 0.18);
--hljs-add-text: #bbf7d0;
--hljs-del-bg: rgba(248, 113, 113, 0.2);
--hljs-del-text: #fecaca;
--focus-ring-color: rgba(59, 130, 246, 0.45);
--transition-base: 160ms ease;
}
*,*::before,*::after {
box-sizing: border-box;
}
::selection {
background-color: #355374;
}
@media (prefers-reduced-motion: reduce) {
*,*::before,*::after {
animation-duration: .01ms!important;
animation-iteration-count: 1!important;
transition-duration: .01ms!important;
scroll-behavior: auto!important;
}
}
html {
overflow-y: scroll;
scroll-behavior: smooth;
background-color: var(--overall-background-color);
}
body {
margin: 0;
min-height: 100vh;
background: var(--overall-background-color);
color: var(--overall-text-color);
line-height: 1.6;
font-size: 16px;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
transition: background-color var(--transition-base), color var(--transition-base);
}
body,select,input {
font-family: var(--font-family-base);
letter-spacing: .01em;
transition: color var(--transition-base), background-color var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base);
}
body:lang(zh-CN),select:lang(zh-CN),input:lang(zh-CN) {
font-family: "Noto Sans SC","Microsoft YaHei UI",var(--font-family-base)
}
body:lang(zh-TW),select:lang(zh-TW),input:lang(zh-TW) {
font-family: "Noto Sans TC","Microsoft JHengHei UI",var(--font-family-base)
}
pre,code {
direction: ltr!important;
font-family: var(--font-family-monospace)
}
code {
background-color: var(--code-background-color);
border-radius: var(--border-radius-small);
padding: .15em .4em
}
pre {
margin: 0;
padding: 1em;
background-color: var(--code-background-color);
border-radius: var(--border-radius-medium);
box-shadow: inset 0 0 0 1px rgba(139, 92, 246, .2);
overflow-x: auto
}
pre code {
background-color: transparent;
padding: 0
}
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=image]):not([type=file]),select,textarea {
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
padding: .6em .7em;
font: inherit;
box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
transition: border-color var(--transition-base), box-shadow var(--transition-base), background-color var(--transition-base);
}
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=image]):not([type=file]):focus,select:focus,textarea:focus {
border-color: var(--link-color);
box-shadow: 0 0 0 0 rgba(139, 92, 246, .25);
outline: none;
}
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=button]):not([type=image]):not([type=file]):focus-visible,select:focus-visible,textarea:focus-visible {
outline: none;
border-color: var(--link-visited-color);
box-shadow: 0 0 0 0 var(--focus-ring-color);
}
input[disabled],select[disabled],textarea[disabled] {
background-color: rgba(148, 163, 184, .15);
cursor: not-allowed;
opacity: .7
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button),input[type=submit]:not(.search-submit),input[type=submit].search-submit:not([value="🔎"]),input[type=button],.button {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 2.45rem;
max-width: 100%;
margin: .25rem .35rem .25rem 0;
margin-inline: 0 .35rem;
border: 1px solid rgba(96, 165, 250, .38);
border-radius: 8px;
padding: .64em 1.05em;
background: linear-gradient(180deg, #3f76c9, #315fae);
color: #ffffff;
font-weight: 700;
line-height: 1.2;
letter-spacing: .01em;
cursor: pointer;
box-shadow: none;
text-decoration: none;
white-space: normal;
transition: transform var(--transition-base), box-shadow var(--transition-base), background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):hover,input[type=submit]:not(.search-submit):hover,input[type=submit].search-submit:not([value="🔎"]):hover,input[type=button]:hover,.button:hover,button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):focus,input[type=submit]:not(.search-submit):focus,input[type=submit].search-submit:not([value="🔎"]):focus,input[type=button]:focus,.button:focus {
background: linear-gradient(180deg, #4d83d5, #3768bd);
border-color: rgba(120, 169, 255, .42);
box-shadow: none;
transform: translateY(-1px);
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):active,input[type=submit]:not(.search-submit):active,input[type=submit].search-submit:not([value="🔎"]):active,input[type=button]:active,.button:active {
transform: translateY(0);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, .28);
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):disabled,input[type=submit]:not(.search-submit):disabled,input[type=submit].search-submit:not([value="🔎"]):disabled,input[type=button]:disabled,.button:disabled {
opacity: .65;
box-shadow: none;
cursor: not-allowed;
transform: none
}
button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):focus-visible,input[type=submit]:not(.search-submit):focus-visible,input[type=submit].search-submit:not([value="🔎"]):focus-visible,input[type=button]:focus-visible,.button:focus-visible {
outline: 2px solid var(--focus-ring-color);
outline-offset: 3px
}
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button),
.form-control input[type=submit]:not(.search-submit),
.form-control input[type=button] {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 2.55rem;
width: fit-content;
max-width: 100%;
margin: .25rem 0 0;
padding: .68rem 1.05rem;
border: 1px solid rgba(96, 165, 250, .38);
border-radius: 8px;
background: linear-gradient(180deg, #3f76c9, #315fae);
color: #ffffff;
font-weight: 700;
line-height: 1.2;
letter-spacing: .01em;
box-shadow: none;
text-decoration: none;
white-space: normal
}
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):hover,
.form-control input[type=submit]:not(.search-submit):hover,
.form-control input[type=button]:hover,
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):focus,
.form-control input[type=submit]:not(.search-submit):focus,
.form-control input[type=button]:focus {
background: linear-gradient(180deg, #4d83d5, #3768bd);
border-color: rgba(120, 169, 255, .42);
box-shadow: none;
transform: translateY(-1px)
}
.form-control button:not(.external-login):not(.gf-set-script-remove):not(.gf-script-star-button):not(.gf-script-detail-button):not(.gf-list-option-toggle):not(.gf-sidebar-scroll-button):active,
.form-control input[type=submit]:not(.search-submit):active,
.form-control input[type=button]:active {
transform: translateY(0);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, .28)
}
input.search-submit[value="🔎"] {
color: transparent;
-webkit-text-fill-color: transparent;
text-shadow: none;
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e2e8f0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><line x1='21' y1='21' x2='16.65' y2='16.65'/></svg>") no-repeat center / 16px 16px !important;
cursor: pointer;
opacity: 1 !important;
}
textarea {
resize: vertical;
min-height: 6em;
background-color: var(--content-background-color)
}
a {
color: var(--link-color);
font-weight: 600;
text-decoration: none;
text-underline-offset: 4px;
text-decoration-thickness: 2px;
transition: color var(--transition-base), text-decoration-color var(--transition-base), opacity var(--transition-base);
}
a:visited {
color: var(--link-visited-color)
}
a:hover,a:focus {
color: var(--link-visited-color);
text-decoration: underline;
text-decoration-color: currentColor
}
a:focus-visible {
outline: 2px solid var(--focus-ring-color);
outline-offset: 3px;
border-radius: var(--border-radius-small)
}
input[type=checkbox],input[type=radio] {
vertical-align: middle;
accent-color: var(--link-color)
}
.form-control input[type=checkbox],
.form-control input[type=radio] {
inline-size: 1rem;
block-size: 1rem;
margin: 0 .45em 0 0;
margin-inline: 0 .45em;
vertical-align: -0.14em;
accent-color: var(--link-color)
}
.form-control input[type=checkbox] + label.radio-label,
.form-control input[type=checkbox] + label.checkbox-label,
.form-control input[type=radio] + label.radio-label,
.form-control input[type=radio] + label.checkbox-label,
.form-control input[type=radio] + label {
display: inline;
margin: 0;
line-height: 1.45;
vertical-align: baseline;
font-size: inherit;
font-weight: 400
}
.width-constraint {
margin: auto;
max-width: 1200px;
width: min(96%, 1200px);
}
@media screen and (max-width: 1228px) {
.width-constraint {
margin:auto 1.2vw;
padding-inline: clamp(.8rem, 4vw, 1.5rem)
}
}
@media screen and (max-width: 400px) {
.width-constraint {
margin:auto 0;
padding-inline: 0
}
}
.inline-list,.block-list {
padding-left: 0;
padding-right: 0;
list-style: none
}
.inline-list {
display: inline
}
.block-list {
display: block;
margin: 0
}
.inline-list li,.block-list li {
display: inline
}
.inline-list li:after,.block-list li:after {
content: ", "
}
body:lang(he) .inline-list li:after,body:lang(he) .block-list li:after,body:lang(ar) .inline-list li:after,body:lang(ar) .block-list li:after,body:lang(ug) .inline-list li:after,body:lang(ug) .block-list li:after,body:lang(ckb) .inline-list li:after,body:lang(ckb) .block-list li:after {
content: "،"
}
.inline-list li:last-child:after,.block-list li:last-child:after {
content: ""
}
dt[title]>span {
border-bottom: 1px dotted black
}
.form-section {
margin-bottom: 2em
}
.form-control {
margin-bottom: 1.4em;
flex-direction: column;
gap: .4em
}
.form-control textarea,#ace-editor {
width: 100%;
box-sizing: border-box;
margin-top: 1px;
margin-bottom: 1px
}
.form-control textarea:not([rows]),#ace-editor {
height: 20em
}
#ace-editor {
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
background-color: var(--content-background-color);
box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
resize: vertical;
transition: border-color var(--transition-base), box-shadow var(--transition-base), background-color var(--transition-base)
}
.form-control input:not([type=radio]):not([type=file]):not([type=checkbox]):not([type=search]):not([type=submit]):not([size]) {
box-sizing: border-box;
width: 100%
}
.radio-group input[type=radio] {
inline-size: 1rem;
block-size: 1rem;
margin: 0 .45em 0 1em;
margin-inline: 1em .45em;
vertical-align: -0.14em;
accent-color: var(--link-color)
}
.radio-group input[type=radio] + label {
display: inline;
line-height: 1.45;
vertical-align: baseline
}
.form-control label {
font-weight: 600;
color: var(--overall-text-color);
display: inline-block;
margin-bottom: .4em;
letter-spacing: .01em
}
.form-control label.radio-label,.form-control label.checkbox-label {
font-weight: 400
}
.form-control .enable-source-editor + label.checkbox-label {
display: inline;
margin: 0;
line-height: 1.25;
vertical-align: middle;
}
.form-control .label-note .enable-source-editor {
margin: 0 .35em 0 0;
vertical-align: middle;
}
.form-control select[name*="[additional_info]"][name$="[locale]"] {
width: auto;
max-width: min(100%, 18rem);
padding: .35em .65em;
font-size: .92rem;
}
.form-control textarea[name="script_version[code]"],
textarea[name="script_version[changelog]"],
textarea.comment-entry,
.form-control textarea[name*="[additional_info]"][name$="[attribute_value]"] {
background-color: #0b1220;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, .34), 0 0 0 1px rgba(167, 139, 250, .12);
}
.form-control textarea[name*="[additional_info]"][name$="[attribute_value]"] {
border-top-left-radius: 0;
}
textarea.comment-entry {
border-top-left-radius: 0;
}
.previewable[data-markup-option-name="script_version[changelog_markup]"] textarea,
.previewable[data-markup-option-name="script_version[changelog_markup]"] .preview-results {
border-top-left-radius: 0;
}
label.subselection-radio-title {
font-weight: 400;
font-size: small;
display: block;
margin-left: 3px
}
.field_with_errors textarea,.field_with_errors input {
background-color: rgba(220, 38, 38, .12);
border-color: var(--rating-icon-bad-border-color);
box-shadow: 0 0 0 0 rgba(220, 38, 38, .12)
}
.label-note {
font-size: smaller;
color: var(--texty-link-visited-color)
}
.label-note.markup-options > a:first-child {
margin-inline-end: .75em
}
.label-note.markup-options label.radio-label {
margin-inline-end: .65em
}
.screenshots-controls>*:not(label) {
padding-left: 1em
}
.add-screenshot-control,.screenshot-control {
clear: left
}
.screenshot-control>* {
vertical-align: middle
}
.screenshot-control a {
float: left;
min-width: 150px;
text-align: center
}
#script-info,.user-list,.text-content,.discussion-list,.notification-list {
padding: clamp(1rem, 2.4vw, 1.5rem)
}
#script-info>*:last-child,.user-list>*:last-child,.text-content>*:last-child,.discussion-list>*:last-child,.notification-list>*:last-child {
margin-bottom: 0
}
.script-list {
padding: 0;
border-radius: var(--border-radius-medium);
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
box-shadow: var(--shadow-soft);
box-sizing: border-box;
margin: 18px 0;
overflow: hidden;
transition: box-shadow var(--transition-base), border-color var(--transition-base), background-color var(--transition-base), transform var(--transition-base)
}
.user-list,.text-content,.discussion-list,.notification-list {
list-style-type: none;
box-shadow: var(--shadow-soft);
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-sizing: border-box;
margin: 18px 0;
padding: clamp(1.15rem, 2vw, 1.6rem);
display: flex;
flex-direction: column;
transition: box-shadow var(--transition-base), border-color var(--transition-base), background-color var(--transition-base), transform var(--transition-base)
}
.script-list:hover,.user-list:hover,.text-content:hover,.discussion-list:hover,.notification-list:hover {
border-color: var(--container-glow-stroke);
box-shadow: var(--shadow-hover);
transform: none
}
.text-content:last-child {
margin-bottom: 0
}
.text-content.text-content-compact {
padding: clamp(.85rem, 1.5vw, 1.2rem);
margin-top: 0px
}
html[data-gfplus-set-editor-page] .text-content > p:first-of-type {
font-size: 1.3rem;
line-height: 1.72;
margin-top: 0;
}
.user-list {
background-image: none
}
.script-link,.script-description,.user-link {
unicode-bidi: isolate
}
.gf-script-logo {
width: 26px;
height: 26px;
aspect-ratio: 1 / 1;
min-width: 26px;
min-height: 26px;
max-width: 26px;
max-height: 26px;
flex: 0 0 26px;
border-radius: 6px;
display: inline-flex;
align-items: center;
justify-content: center;
margin-right: 8px;
vertical-align: text-bottom;
border: 0;
background: transparent;
box-shadow: none;
overflow: hidden;
line-height: 0;
}
img.gf-script-logo {
width: 100%;
height: 100%;
display: block;
object-fit: contain;
object-position: center;
max-width: 100%;
max-height: 100%;
filter: none;
mix-blend-mode: normal;
image-rendering: auto;
}
.gf-script-logo--title {
width: 34px;
height: 34px;
min-width: 34px;
min-height: 34px;
max-width: 34px;
max-height: 34px;
flex-basis: 34px;
margin-right: 10px;
}
.gf-script-logo--fallback {
color: var(--link-color);
}
.gf-script-logo--fallback svg {
width: 16px;
height: 16px;
stroke: currentColor;
}
#script-info header h2,
#script-info > h2 {
display: flex;
align-items: center;
gap: 10px;
}
#script-info header h2 .gf-script-logo,
#script-info > h2 .gf-script-logo {
margin-right: 0;
}
#script-info header h2 .gf-script-logo--fallback svg,
#script-info > h2 .gf-script-logo--fallback svg {
width: 18px;
height: 18px;
}
.list-option-groups~ol {
width: calc(960px - 14em)
}
.text-content .list-option-groups~ol {
width: calc(960px - 16em)
}
@media screen and (max-width: 960px) {
#script-info,.user-list,.text-content {
padding: clamp(.9rem, 4vw, 1.2rem)
}
}
@media screen and (max-width: 400px) {
.script-list,.user-list,.text-content,.discussion-list,.notification-list {
border-left:0;
border-right: 0
}
.user-list,.text-content,.discussion-list,.notification-list,.script-list-description {
padding-left: 1rem;
padding-right: 1rem
}
.discussion-list-header,.user-list-header,.library-list-header {
padding-left: 1em;
padding-right: 1em;
margin-top: 15px;
margin-bottom: 10px
}
#script-info {
padding-left: 1em;
padding-right: 1em
}
#script-links {
margin-left: -1em;
margin-right: -1em;
padding: 0
}
#additional-info {
margin-left: -1em;
margin-right: -1em
}
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) {
border-bottom: 1px solid var(--content-separator-color);
padding: clamp(1rem, 2.5vw, 1.6rem);
display: grid;
min-width: 0;
max-width: 100%;
box-sizing: border-box;
list-style-type: none;
gap: .55rem;
background: rgba(255, 255, 255, 0.02);
transition: background-color var(--transition-base, 0.25s ease),
box-shadow var(--transition-base, 0.25s ease),
transform var(--transition-base, 0.25s ease);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):hover {
background: rgba(255, 255, 255, 0.05);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12), inset 0 0 0 1px rgba(255,255,255,0.06);
transform: translateY(-1px);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):has(.gf-script-star-button[data-active="true"]) {
background: linear-gradient(90deg, rgba(244, 180, 0, .075), rgba(244, 180, 0, .018) 44%, transparent);
box-shadow: inset 3px 0 rgba(244, 180, 0, .68);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):has(.gf-script-star-button[data-active="true"]):hover {
background: linear-gradient(90deg, rgba(244, 180, 0, .12), rgba(244, 180, 0, .03) 50%, transparent);
box-shadow: inset 3px 0 rgba(244, 180, 0, .92), inset 0 0 0 1px rgba(244, 180, 0, .1);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info):last-child {
border-bottom: none
}
.script-list .cf-wrapper {
margin: 0!important
}
@media screen and (max-width: 960px) {
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) {
padding: clamp(.9rem, 4vw, 1.3rem)
}
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 {
margin: 0;
font-size: 1.25rem;
line-height: 1.35;
letter-spacing: .01em;
color: var(--overall-text-color);
display: flex;
flex-wrap: wrap;
align-items: center;
column-gap: 8px;
row-gap: .35em;
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 .gf-script-logo {
flex: 0 0 26px;
margin-right: 0;
align-self: center;
vertical-align: middle;
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 .gf-script-title-content {
display: block;
flex: 1 1 0;
min-width: 0;
max-width: calc(100% - 34px);
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 > .script-link,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 .gf-script-title-content .script-link {
min-width: 0;
max-width: 100%;
overflow-wrap: anywhere;
word-break: normal;
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > p {
margin: 0
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > footer {
margin-top: .35em;
display: flex;
flex-wrap: wrap;
gap: .6rem;
font-size: .875rem;
color: var(--texty-link-visited-color)
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > footer a {
font-weight: 500
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article {
min-width: 0;
max-width: 100%;
}
.list-current,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 {
font-weight: 700
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article .description {
font-weight: 400;
display: block;
flex: 0 0 100%;
margin: .5em 0;
font-size: .95rem;
color: var(--texty-link-visited-color)
}
.gf-script-extra-info {
display: none;
min-width: 0;
max-width: 100%;
margin-top: .8rem;
padding-top: .8rem;
border-top: 1px solid var(--content-separator-color);
}
.gf-script-extra-info[data-open="true"] {
display: block;
}
.gf-script-extra-info .user-content ul,
.gf-script-extra-info .user-content ol {
margin-top: .35em;
margin-bottom: .45em;
padding-left: 1.45em;
}
.gf-script-extra-info .user-content li {
display: list-item;
margin: 0;
padding: 0;
border-bottom: 0;
background: transparent;
box-shadow: none;
transform: none;
transition: none;
}
.gf-script-extra-info .user-content li > ul,
.gf-script-extra-info .user-content li > ol {
margin-top: .2em;
margin-bottom: .2em;
}
.gf-script-extra-status {
display: inline-flex;
align-items: center;
gap: .6rem;
min-height: 40px;
max-width: 100%;
box-sizing: border-box;
padding: .65rem .85rem;
border: 1px solid rgba(129, 140, 248, .18);
border-radius: var(--border-radius-small);
background: linear-gradient(180deg, rgba(129, 140, 248, .12), rgba(129, 140, 248, .045));
color: var(--texty-link-visited-color);
font-size: .9rem;
font-weight: 600;
}
.gf-script-extra-status::before {
content: "";
width: 14px;
height: 14px;
flex: 0 0 14px;
border: 2px solid currentColor;
border-right-color: transparent;
border-radius: 999px;
opacity: .72;
animation: gf-script-extra-spin .8s linear infinite;
}
.gf-script-extra-info[data-gfplus-extra-info="loaded"] .gf-script-extra-status::before,
.gf-script-extra-info[data-gfplus-extra-info="error"] .gf-script-extra-status::before {
display: none;
}
@keyframes gf-script-extra-spin {
to {
transform: rotate(360deg);
}
}
.script-list .name-description-separator {
display: none
}
#script-description,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article > h2 > a,
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article .description {
word-wrap: break-word
}
@media screen and (max-width: 720px) {
.script-list,#script-content {
margin-left:unset
}
}
.pagination,.script-list+.pagination,.user-list+.pagination {
font-size: 1rem;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: .6rem;
background-color: transparent;
padding: 1.1rem 0;
margin: 0;
border-radius: var(--border-radius-small)
}
.pagination>*,.script-list+.pagination>*,.user-list+.pagination>* {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2.6rem;
background-color: var(--pagination-background-color);
padding: .55em .95em;
border-radius: var(--border-radius-small);
text-decoration: none;
border: 1px solid transparent;
color: var(--overall-text-color);
font-weight: 600;
transition: background-color var(--transition-base), color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base)
}
.pagination .disabled {
display: none
}
.pagination .current {
font-style: normal;
font-weight: 700
}
.pagination .current,.pagination .gap {
background-color: transparent;
color: var(--texty-link-visited-color)
}
.pagination .current {
border-color: var(--link-color);
color: var(--link-color);
box-shadow: inset 0 0 0 1px var(--link-color);
background-color: rgba(139, 92, 246, .16)
}
.pagination>a:hover,.pagination>a:focus {
background-color: var(--pagination-hover-background-color);
color: var(--overall-text-color);
transform: translateY(-1px);
box-shadow: 0 12px 24px rgba(139, 92, 246, .28)
}
.pagination>a:focus-visible {
outline: 2px solid var(--focus-ring-color);
outline-offset: 2px
}
@media screen and (max-width: 400px) {
.pagination,.script-list+.pagination,.user-list+.pagination {
padding-left: 1rem;
padding-right: 1rem
}
}
.good-rating-count,.ok-rating-count,.bad-rating-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2.5em;
text-align: center;
padding: .1em .5em;
border-radius: 999px;
font-weight: 600;
font-size: .85rem;
border: 1px solid transparent;
transition: transform var(--transition-base), box-shadow var(--transition-base)
}
.good-rating-count {
background-color: var(--rating-icon-good-background-color);
border-color: var(--rating-icon-good-border-color);
color: var(--rating-icon-good-color)
}
.ok-rating-count {
background-color: var(--rating-icon-ok-background-color);
border-color: var(--rating-icon-ok-border-color);
color: var(--rating-icon-ok-color)
}
.bad-rating-count {
background-color: var(--rating-icon-bad-background-color);
border-color: var(--rating-icon-bad-border-color);
color: var(--rating-icon-bad-color)
}
.select-all,.select-none {
display: none
}
#help-allowed-elements,#help-allowed-styles {
column-width: 20em
}
#help-allowed-elements li,#help-allowed-styles li {
padding-right: 1em
}
#by-site-list {
list-style-type: none;
padding: 0
}
#by-site-list li {
display: inline;
vertical-align: middle
}
#user_profile {
width: 100%;
height: 10em
}
.preview-result {
display: none;
background-color: rgba(253, 230, 138, 0.2);
padding: .5em
}
.failed-sync {
background-color: rgba(248, 113, 113, 0.22)
}
.alert {
font-style: normal;
background-color: var(--alert-background-color);
border: 1px solid rgba(245, 158, 11, .25);
border-left: 6px solid var(--alert-border-color);
padding: 1rem 1.1rem;
color: var(--alert-text-color);
border-radius: var(--border-radius-small);
box-shadow: 0 12px 20px rgba(120, 53, 15, .12)
}
.notice,.validation-errors {
background-color: var(--notice-background-color);
border: 1px solid rgba(2, 132, 199, .2);
border-left: 6px solid var(--notice-border-color);
padding: 1rem 1.1rem;
color: var(--notice-text-color);
border-radius: var(--border-radius-small);
box-shadow: 0 12px 20px rgba(15, 23, 42, .08)
}
.validation-errors {
margin: .5em 0
}
.validation-errors>p:first-child {
margin-top: 0
}
.validation-errors>p:last-child {
margin-bottom: 0
}
.alert p,.notice p,.validation-errors p {
margin: 0
}
.alert p+p,.notice p+p,.validation-errors p+p {
margin-top: .6rem
}
#install-stats-chart {
width: 100%;
height: 400px;
background: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
overflow: hidden
}
#install-stats-chart-container,
#weekly-install-stats-chart-container,
#update-check-stats-chart-container {
width: 100%;
min-height: 320px;
background: var(--content-background-color) !important;
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
overflow: hidden
}
#install-stats-chart-container canvas,
#weekly-install-stats-chart-container canvas,
#update-check-stats-chart-container canvas {
display: block;
max-width: 100%;
}
#install-stats-chart svg text {
fill: var(--install-stats-text-color) !important
}
#install-stats-chart svg line[stroke],
#install-stats-chart svg path[stroke="#cccccc"],
#install-stats-chart svg path[stroke="#e6e6e6"],
#install-stats-chart svg path[stroke="#d9d9d9"] {
stroke: var(--install-stats-grid-color) !important
}
#install-stats-chart svg rect[fill="#ffffff"],
#install-stats-chart svg rect[fill="white"] {
fill: var(--content-background-color) !important
}
.stats-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-small);
overflow: hidden;
box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .04)
}
.stats-table th,.stats-table td {
border: 1px solid var(--content-border-color);
padding: .75rem 1rem;
text-align: left
}
.stats-table th {
background: linear-gradient(180deg, rgba(139, 92, 246, .18), rgba(139, 92, 246, .06));
font-weight: 600;
color: var(--overall-text-color)
}
.stats-table thead tr:first-child th:first-child {
border-start-start-radius: 5px;
overflow: hidden
}
.stats-table thead tr:first-child th:last-child {
border-start-end-radius: 5px;
overflow: hidden
}
.stats-table tbody tr:last-child > * {
border-block-end: 1px solid var(--content-border-color) !important;
border-bottom: 1px solid var(--content-border-color) !important;
background-clip: padding-box
}
.stats-table tbody tr:last-child > *:first-child {
border-inline-start: 1px solid var(--content-border-color) !important;
border-bottom-left-radius: 5px;
border-end-start-radius: 5px;
overflow: hidden
}
.stats-table tbody tr:last-child > *:last-child {
border-inline-end: 1px solid var(--content-border-color) !important;
border-bottom-right-radius: 5px;
border-end-end-radius: 5px;
overflow: hidden
}
body:lang(ar) .stats-table tbody tr:last-child > *:first-child,
body:lang(he) .stats-table tbody tr:last-child > *:first-child,
body:lang(ug) .stats-table tbody tr:last-child > *:first-child,
body:lang(ckb) .stats-table tbody tr:last-child > *:first-child {
border-bottom-left-radius: 0;
border-bottom-right-radius: 5px
}
body:lang(ar) .stats-table tbody tr:last-child > *:last-child,
body:lang(he) .stats-table tbody tr:last-child > *:last-child,
body:lang(ug) .stats-table tbody tr:last-child > *:last-child,
body:lang(ckb) .stats-table tbody tr:last-child > *:last-child {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 0
}
.stats-table tbody tr:hover {
background-color: rgba(139, 92, 246, .14)
}
td.numeric,th.numeric {
text-align: right
}
.translation_missing {
outline: dashed red
}
#edit_user>div {
margin-bottom: .5em
}
#edit_user>div>label:first-child {
font-weight: 700
}
.inline-form {
display: inline
}
a.self-link,a.self-link:visited {
text-decoration: none;
color: var(--overall-text-color);
opacity: .35
}
.indented {
padding-left: 1em
}
.external-login {
display: inline-flex !important;
align-items: center;
justify-content: center;
min-height: 2.45rem;
max-width: 100%;
margin: .25rem .35rem .25rem 0;
padding: .64em 1.05em .64em 2.35em;
border: 1px solid rgba(96, 165, 250, .38);
border-radius: 8px;
background-color: #315fae;
background-repeat: no-repeat;
background-size: 16px 16px;
background-position: .82em center;
color: #ffffff;
font-weight: 700;
line-height: 1.2;
letter-spacing: .01em;
cursor: pointer;
box-shadow: none;
text-decoration: none;
white-space: normal;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
transform: none !important;
}
.external-login:hover,
.external-login:focus,
.external-login:active {
border-color: rgba(120, 169, 255, .42);
background-color: #3768bd;
background-repeat: no-repeat !important;
background-size: 16px 16px !important;
background-position: .82em center !important;
color: #ffffff;
transform: none !important;
}
.external-login.github-login,
.external-login.gitlab-login,
.external-login.google_oauth2-login,
.external-login.github-login:hover,
.external-login.gitlab-login:hover,
.external-login.google_oauth2-login:hover,
.external-login.github-login:focus,
.external-login.gitlab-login:focus,
.external-login.google_oauth2-login:focus,
.external-login.github-login:active,
.external-login.gitlab-login:active,
.external-login.google_oauth2-login:active {
box-shadow: none !important;
}
.external-login-container {
display: inline-block;
vertical-align: top
}
.external-login-container * {
text-align: center;
display: block
}
.external-login-container .external-login {
display: inline-flex !important
}
.external-login-container>*:not(button) {
font-size: smaller
}
.external-login-container:not(:last-child) {
margin-right: 5px
}
.external-login-container .github-login {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFNTE3OEEyQTk5QTAxMUUyOUExNUJDMTA0NkE4OTA0RCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFNTE3OEEyQjk5QTAxMUUyOUExNUJDMTA0NkE4OTA0RCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU1MTc4QTI4OTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU1MTc4QTI5OTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+m4QGuQAAAyRJREFUeNrEl21ojWEYx895TDPbMNlBK46IUiNmPvHBSUjaqc0H8pF5+aDUKPEBqU2NhRQpX5Rv5jWlDIWlMCv7MMSWsWwmb3tpXub4XXWdPHvc9/Gc41nu+nedc7/8r/99PffLdYdDPsvkwsgkTBwsA/PADJCnzX2gHTwBt8Hl7p537/3whn04XoDZDcpBlk+9P8AFcAghzRkJwPF4zGGw0Y9QS0mAM2AnQj77FqCzrtcwB1Hk81SYojHK4DyGuQ6mhIIrBWB9Xm7ug/6B/nZrBHBegrkFxoVGpnwBMSLR9EcEcC4qb8pP14BWcBcUgewMnF3T34VqhWMFkThLJAalwnENOAKiHpJq1FZgI2AT6HZtuxZwR9GidSHtI30jOrbawxlVX78/AbNfhHlomEUJJI89O2MqeE79T8/nk8nMBm/dK576hZgmA3cp/R4l9/UeSxiHLVIlNm4nFfT0bxyuIj7LHRTKai+zdJobwMKzcZSJb0ePV5PKN+BqAAKE47UlMnERELMM3EdYP/yrd+XYb2mOiYBiQ8OQnoRBlXrl9JZix7D1pHTazu4MoyBcnYamqAjIMTR8G4FT8LuhLsexXYYjICBiqhQBvYb6fLZIJCjPypVvaOoVAW2WcasCnL2Nq82xHJNSqlCeFcDshaPK0twkAhosjZL31QYw+1rlMpWGMArl23SBsZZO58F2tlJXmjOXS+s4WGvpMiBJT/I2PInZ6lIs9/hBsNS1hS6BG0DSqmYEDRlCXQrmy50P1oDRKTSegmNbUsA0zDMwRhPJXeCE3vWLPQMvan6X8AgIa1vcR4AkGZkDR4ejJ1UHpsaVI0g2LInpOsNFUud1rhxSV+fzC9Woz2EZkWQuja7/B+jUrgtIMpy9YCW4n4K41YfzRneW5E1KJTe4B2Zq1Q5EHEtj4U3AfEzR5SVY4l7QYQPJdN2as7RKBF0BPZqqH4VgMAMBL8Byxr7y8zCZiDlnOcEKIPmUpgB5Z2ww5RdOiiRiNajUmWda5IG6WbhsyY2fx6m8gLcoJDJFkH219M3We1+cnda93pfycZpIJEL/s/wSYADmOAwAQgdpBAAAAABJRU5ErkJggg==)
}
.external-login-container .gitlab-login {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAACoUlEQVRYhc3WzW+UVRQG8N/MtKKYsEFMmpo27DUEFgSiSIHSsDAxsYr6L4Cs+AMkMWiMCwgB2lQMhIWJ0Rip7owbXbhjhekGTFBQkC9rTCxBWxb3vpkzb2Y6H+00PsnN3Hve8zznzL3nfvA/xQRm8Qk2rUBnU9aYxf5OSevxF5ZyO7eCBM4Fnb/xVCekyUBawl0M9BB8EPdLWq92Qvy0RFrCvh4SmGiic7EdaZ3G6S/aVA8JzDTR+RNPLEd6JTi/h19z/zZqXQQfwB+Zex3Hg+6B5Yjng+MWnAzjl7tIYE/gncDWMP64FSkWzVVUsCsQT3WRwOnAeylr/ZzHd7Qo6v2B9GG21XAr226i2kHwKn7LnN8D56Ogv6cZcTo4bA/2qWDf2UECLwb/s8G+I9jPFMZK/q3lrJ+VCm80O8I4vs39RRxtk8CJ0B/Hd7lfxS8YlmbmuawHxjQWTcSgdBiVt1S71uwAOxW+7yqygteD05cl0iNcaPl/W+MC/i3Zvgj9g6QlqOIGhqSCGxamJqOKbXiyw+ALuNxEpyYt8ZB0tgyTCqtZ0fQLcRn2VqXLp0B5+vuBz0L/TbiWs7knFVy/UVU/4u9QP7Pn5crsM8bVl+AfeDcY/svjXu7/dhjAMY1b9Trpejxf+vA9RlYx+Ah+KMX4HBui09vSMhQO9/HaKgSfxIOgO4+3Wjlvxo+lTKeld2K3WK/xflnK2pvbEQelB8RiIF7B810EfwE/Bf5i1uxql+1Vv1aLij2kfoE1QwWHpZOw4N3MWj3hGXytcRq/wsYmvhtxqeQ7mzVWhAqO4GEQvoHdwWcs24rvC3jH8rPVNbZgTuO6vo8PNNbLXPbtC56WHpWt3gAz2afveEN64xeBH2h8U6wJRvFNbqNrHXzV8BjO7vx8x02KpQAAAABJRU5ErkJggg==)
}
.external-login-container .google_oauth2-login {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAnFJREFUOI2FU11Ik1EYfs75zvZ9c35buAKpaWaSSVZoiheBKVmYdWF1ERi7kMhFUeqNFxLURRAhFKvhTcHMioQiCBG8iOgH8QfFKZj4M81ES0fONfe5tW87XcQncw17rs7znud5f87LIUgCn8u1jQaWL2MtWMTBGZGkKUgpLvPVxolELYkn3if3ZP38ytvQ8EAZCa6RzUoK4WDBrJiXey61rtH9T4LVx86cWF/PsPp1OjVZVxpo+q6wpfSUTOz2CAAwAIg5HOJqf89QvFnI3KNQa6ab6vTB2Ir3QGRsdCeMqVw8WmbTzBsJFPNSmzo7bfpbgkI6UeWSm25dIgDXhAHn/YtgRJWvNLza1BLnIOHPWZFwVyVfrizhvjvNXVuNkAimTjVV0PADBnEBpuYiVRnfXRMvaOkMOaOcpyUz7zDgJiPRtRKtTyrBn2a3++NFg7NqnTcAXbIE1UWsjwJkY07ON6/1v4hBYlxn6tP4SHS7yTH5zFS/z/ZLix3OEDrDUVg0PjSjlioRQgBA1GGSsb1334cXsyMd5Liudd7HKuB9CeC0Zmg+azivnR92h6qVCDkGAAYd53pB7KaEgLeJ1147F1YQ4xzv5nurbvc/eoqEcZwfh0r7PWqHxvOtwlhtOQkRAHBMOsQBz9zShH/OrAky5PT1LKN1lDG6/nPdnzPu81gPyeWYGbkAA2P8zBF9YV256N6o0jr6IvvT4qB7evWbvNW75Znzo8VCU8ONk0YnkPCZWtztRp+y/Kb3x0hF4LdC4+8oIci37P9eYMmtuV5g+6DFk66txd1uRFStDarBYnAuiYLkSREMz+sLbV8StX8AjxDtgxiuzNwAAAAASUVORK5CYII=)
}
.centered-sections h2,.centered-sections h3 {
text-align: center
}
form.external-login-form {
position: relative;
display: table;
margin: 0 auto;
padding: 1em;
background-color: var(--content-background-color);
border: 1px solid #414954;
border-radius: 5px;
text-align: center
}
form.external-login-form .remember-me {
margin-top: 12px
}
form.new_user {
position: relative;
width: 340px;
margin: 0 auto;
padding: 1em;
background-color: var(--content-background-color);
border: 0;
border-radius: 5px;
text-align: start
}
@media screen and (max-width: 440px) {
form.new_user {
width:unset
}
}
form.new_user label,form.new_user em {
display: block;
font-size: small
}
form.new_user br {
display: none
}
form.new_user input[type=text],form.new_user input[type=email],form.new_user input[type=password] {
display: block;
width: 100%;
min-height: 34px;
box-sizing: border-box;
margin-top: .2em;
margin-bottom: .5em;
padding: 6px 8px;
font-size: 14px;
line-height: 20px;
vertical-align: middle;
border: 1px solid rgba(196, 181, 253, .32);
border-radius: 3px;
outline: none;
box-shadow: inset 0 1px 2px #0000001a
}
form.new_user #user_email,
form.new_user #user_password {
border: 1px solid #414954;
}
form input[type=checkbox],input[type=checkbox]+label,form input[type=radio],input[type=radio]+label {
display: inline-block;
font-size: small
}
.radio-note {
font-size: small;
margin-top: 5px
}
@media screen and (max-width: 440px) {
form input[type=checkbox]+label {
display:unset;
word-wrap: break-word
}
}
form.new_user input[type=submit] {
display: block;
width: 100%;
min-height: 34px;
box-sizing: border-box;
margin: .5em 0 0;
padding: 6px 8px;
font-size: 14px;
font-weight: 700;
line-height: 20px;
text-align: center;
vertical-align: middle;
color: #f8fafc;
background-color: #3b1e8a;
background-image: linear-gradient(#2f2675,#4c1d95);
border: 0px solid transparent;
box-shadow: none;
border-radius: 3px;
white-space: normal
}
form.new_user~br {
display: none
}
form.new_user~a {
width: 340px;
display: block;
margin: 0 auto 2em;
font-size: small
}
form.new_user+a {
width: 340px;
display: block;
margin: 0 auto
}
.qr-code {
max-width: 400px;
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
box-shadow: var(--shadow-soft);
border-radius: var(--border-radius-small)
}
.sidebar-search,.home-search,
#library-search,#user-search,#code-search {
position: relative;
vertical-align: middle
}
.sidebar-search input[type=search],.home-search input[type=search],
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
padding: .6em 78px .6em .8em;
}
.sidebar-search input[type=search]::-webkit-search-cancel-button,
.home-search input[type=search]::-webkit-search-cancel-button,
#library-search input[type=search]::-webkit-search-cancel-button,
#user-search input[type=search]::-webkit-search-cancel-button,
#code-search input[type=search]::-webkit-search-cancel-button {
margin-right: 38px;
}
.sidebar-search input[type=search],
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
width: 100%;
margin: 0 0 16px;
}
.sidebar-search input.search-submit[value="🔎"],.home-search input.search-submit[value="🔎"],
#library-search input.search-submit[value="🔎"],
#user-search input.search-submit[value="🔎"],
#code-search input.search-submit[value="🔎"] {
position: absolute;
-moz-appearance: none;
-webkit-appearance: none;
inset-inline-end: 1px;
top: 1px;
bottom: 1px;
width: 38px;
border: 0;
border-inline-start: 1px solid var(--content-border-color);
border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;
padding: 0;
margin-left: 0;
margin-right: 0;
background-color: var(--content-background-color) !important;
box-shadow: none;
opacity: 1;
transform: none
}
.sidebar-search input.search-submit[value="🔎"] {
bottom: 17px;
}
.sidebar-search input.search-submit[value="🔎"]:hover,.sidebar-search input.search-submit[value="🔎"]:focus,.sidebar-search input.search-submit[value="🔎"]:active,
.home-search input.search-submit[value="🔎"]:hover,.home-search input.search-submit[value="🔎"]:focus,.home-search input.search-submit[value="🔎"]:active,
#library-search input.search-submit[value="🔎"]:hover,#library-search input.search-submit[value="🔎"]:focus,#library-search input.search-submit[value="🔎"]:active,
#user-search input.search-submit[value="🔎"]:hover,#user-search input.search-submit[value="🔎"]:focus,#user-search input.search-submit[value="🔎"]:active,
#code-search input.search-submit[value="🔎"]:hover,#code-search input.search-submit[value="🔎"]:focus,#code-search input.search-submit[value="🔎"]:active {
background-color: var(--content-background-color) !important;
box-shadow: none;
transform: none
}
#library-search,
#user-search,
#code-search {
display: grid;
grid-template-columns: minmax(0, 1fr) 38px;
align-items: stretch
}
#library-search > h3,
#library-search > p,
#user-search > h3,
#user-search > p,
#code-search > h3,
#code-search > p {
grid-column: 1 / -1
}
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
grid-column: 1;
margin: 0 0 16px;
padding: .6em 34px .6em .8em;
border-start-end-radius: 0;
border-end-end-radius: 0
}
#library-search input[type=search]::-webkit-search-cancel-button,
#user-search input[type=search]::-webkit-search-cancel-button,
#code-search input[type=search]::-webkit-search-cancel-button {
margin-right: 8px
}
#library-search input.search-submit[value="🔎"],
#user-search input.search-submit[value="🔎"],
#code-search input.search-submit[value="🔎"] {
position: static;
grid-column: 2;
align-self: stretch;
width: 38px;
min-height: auto;
margin: 0 0 16px;
border: 1px solid var(--content-border-color);
border-inline-start: 0;
border-start-start-radius: 0;
border-end-start-radius: 0;
border-start-end-radius: var(--border-radius-small);
border-end-end-radius: var(--border-radius-small);
background-color: var(--content-background-color) !important
}
@media screen and (max-width: 680px) {
.sidebar-search input[type=search],.home-search input[type=search],
#library-search input[type=search],
#user-search input[type=search],
#code-search input[type=search] {
font-size:unset
}
}
figure {
padding: 5px;
box-shadow: 0 4px 8px #00000026,0 6px 10px #00000026;
border-radius: 5px
}
figcaption {
font-size: smaller;
text-align: center
}
.multiform-page:not(:first-child) {
margin-top: 30px
}
.multiform-page:not(:last-child) {
padding-bottom: 30px;
border-bottom: 1px solid lightgray
}
summary {
cursor: pointer
}
@media screen and (max-width: 400px) {
.user-list {
padding-top:1em;
padding-bottom: 1em
}
}
.blocked-script-codes {
font-size: smaller;
border-collapse: collapse;
width: 100%;
text-align: left
}
.blocked-script-codes .pattern-row code {
font-size: medium
}
.blocked-script-codes .pattern-row {
border-top: 1px solid gray
}
.blocked-script-codes .info-row td:first-child {
width: 2em
}
.ad {
margin-top: 1em;
margin-bottom: 1em
}
.script-list-cd-entry {
border-bottom: 1px solid var(--content-border-color)
}
#script-list-cd,#discussion-show-cd {
width: 300px;
margin-left: auto;
margin-right: auto
}
#script-list-cd {
padding: 1em
}
.ethical-ads-text .ea-placement {
position: relative
}
.ethical-ads-text .ea-callout {
position: absolute;
bottom: 0;
right: 0
}
.ethical-ads-text:empty {
min-height: 46px
}
.ethical-ads.text-content-top-ad {
margin: 0 calc(-1em - 1px);
border-radius: 5px 5px 0 0
}
@media screen and (max-width: 960px) {
.ethical-ads.text-content-top-ad {
margin:0 calc(-1.2vw - 1px)
}
}
@media screen and (max-width: 400px) {
.ethical-ads.text-content-top-ad {
margin:0 calc(-1em - 1px);
border-radius: 5px 5px 0 0
}
}
@media screen and (max-width: 400px) {
.script-list li.ad-entry {
padding:0
}
}
#script-info .ethical-ads-text {
margin: 0 calc(-1em - 1px)
}
#script-info .ethical-ads-text .ea-content {
border-radius: 0!important
}
@media screen and (max-width: 960px) {
#script-info .ethical-ads-text {
margin:0 calc(-1.2vw - 1px)
}
}
.after-radio-chosen {
display: none;
margin-left: 29px
}
input[type=radio]:checked~.after-radio-chosen {
display: block
}
.announcement {
margin: 14px 0;
text-align: center;
font-size: smaller
}
.announcement form {
display: inline
}
.announcement input {
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
border: 0;
background: none;
margin: 0 0 0 4px;
padding: 0;
cursor: pointer
}
.announcement,.announcement input {
font-size: 12px
}
.badge {
margin-left: 1ex;
border-radius: 10%/25%;
font-size: 70%;
padding: 0 .5ex;
text-transform: uppercase;
position: relative;
top: -.2ex
}
.badge-banned,.badge-deleted {
background-color: rgba(248, 113, 113, .85);
color: #fef2f2
}
.badge-deleted {
margin-left: 0;
border-color: rgba(248, 113, 113, .85)
}
.badge-moderator {
background-color: rgba(99, 102, 241, .85);
color: #eef2ff
}
.badge-author {
background-color: rgba(34, 197, 94, .82);
color: #ecfdf5
}
.badge-js {
background-color: #facc15;
color: #0f172a
}
.badge-css {
background-color: #61a5fa;
color: #e0f2fe
}
.badge-js,.badge-css {
display: none
}
.showing-all-languages .badge-js,.showing-all-languages .badge-css {
display: inline
}
code {
background-color: var(--code-background-color)
}
pre code {
background: none;
border: 0
}
pre,code {
border-radius: 2px
}
pre {
padding: 1em
}
.prettyprint {
min-width: calc(100% - 6px);
background-color: var(--prettyprint-background-color);
color: var(--prettyprint-color)
}
.prettyprint.wrap {
white-space: pre-wrap;
line-break: anywhere
}
.prettyprint:not(.wrap) {
width: max-content
}
.code-container {
max-height: calc(100vh - 54px);
overflow-x: auto;
border-radius: 2px;
border: 1px solid var(--code-container-border-color)
}
.code-container pre {
border: 0;
margin: 0
}
li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9 {
list-style-type: decimal!important
}
@media screen and (max-width: 440px) {
#code-container {
font-size:small
}
}
.diff_options input[type=number] {
width: 10ch
}
.diff {
overflow: auto
}
.diff ul {
background: var(--content-background-color);
overflow: auto;
font-size: 13px;
list-style: none;
margin: 0;
padding: 0;
display: table;
width: 100%
}
.diff del,.diff ins {
display: block;
text-decoration: none
}
.diff li {
padding: 0;
display: table-row;
margin: 0;
height: 1em
}
.diff li.ins {
background: var(--diff-ins-background);
color: var(--diff-ins-color)
}
.diff li.del {
background: var(--diff-del-background);
color: var(--diff-del-color)
}
.diff li:hover {
background: rgba(253, 230, 138, 0.14)
}
.diff del,.diff ins,.diff span {
white-space: pre;
font-family: courier
}
.diff del strong {
font-weight: 400;
background: var(--diff-del-strong-background)
}
.diff ins strong {
font-weight: 400;
background: var(--diff-ins-strong-background)
}
.diff li.diff-comment {
display: none
}
.diff li.diff-block-info {
background: none repeat scroll 0 0 var(--diff-block-info)
}
.diff del,.diff ins,.diff span {
font-family: monospace
}
.diff {
max-height: calc(100vh - 54px);
overflow-y: auto
}
.report-diff .diff {
max-height: 75vh
}
.report-diff form {
display: inline
}
.diff ul {
background-color: var(--content-background-color);
color: var(--overall-text-color)
}
.diff {
border: 2px solid var(--content-border-color)
}
.diff li:hover {
background: var(--highlight-background-color)
}
#ace-editor.ace-tm {
background-color:#181a1b;
color: #e8e6e3;
border-color: #43494c
}
#ace-editor.ace-tm .ace_indent-guide {
opacity: .1
}
#ace-editor.ace-tm .ace_scroller {
background-color: #181a1b
}
#ace-editor.ace-tm .ace_gutter {
background: #202325;
color: #c8c3bc
}
#ace-editor.ace-tm .ace_print-margin {
display: none!important;
visibility: hidden!important
}
#ace-editor.ace-tm .ace_fold {
background-color: #161d84
}
#ace-editor.ace-tm .ace_cursor {
color: #e8e6e3
}
#ace-editor.ace-tm .ace_invisible {
color: #c0bab2
}
#ace-editor.ace-tm .ace_storage,#ace-editor.ace-tm .ace_keyword {
color: #337dff
}
#ace-editor.ace-tm .ace_constant {
color: #f94448
}
#ace-editor.ace-tm .ace_constant.ace_buildin {
color: #5e4ef6
}
#ace-editor.ace-tm .ace_constant.ace_language {
color: #5a94f6
}
#ace-editor.ace-tm .ace_constant.ace_library {
color: #65f96d
}
#ace-editor.ace-tm .ace_invalid {
background-color: #cc00001a;
color: #ff1a1a
}
#ace-editor.ace-tm .ace_support.ace_function {
color: #99b0c9
}
#ace-editor.ace-tm .ace_support.ace_constant {
color: #65f96d
}
#ace-editor.ace-tm .ace_support.ace_type,#ace-editor.ace-tm .ace_support.ace_class {
color: #6f9cde
}
#ace-editor.ace-tm .ace_keyword.ace_operator {
color: #9d9487
}
#ace-editor.ace-tm .ace_string {
color: #83fb88
}
#ace-editor.ace-tm .ace_comment {
color: #7fb89c
}
#ace-editor.ace-tm .ace_comment.ace_doc {
color: #339cff
}
#ace-editor.ace-tm .ace_comment.ace_doc.ace_tag {
color: #84a6c1
}
#ace-editor.ace-tm .ace_constant.ace_numeric {
color: #5190ff
}
#ace-editor.ace-tm .ace_variable {
color: #70c0d0
}
#ace-editor.ace-tm .ace_xml-pe {
color: #aaa398
}
#ace-editor.ace-tm .ace_entity.ace_name.ace_function {
color: #6ba1ff
}
#ace-editor.ace-tm .ace_heading {
color: #1e6fff
}
#ace-editor.ace-tm .ace_list {
color: #f94cd2
}
#ace-editor.ace-tm .ace_meta.ace_tag {
color: #77b0ff
}
#ace-editor.ace-tm .ace_string.ace_regex {
color: #ff1a1a
}
#ace-editor.ace-tm .ace_marker-layer .ace_selection {
background: #2d3133
}
#ace-editor.ace-tm.ace_multiselect .ace_selection.ace_start {
box-shadow: 0 0 3px #181a1b
}
#ace-editor.ace-tm .ace_marker-layer .ace_step {
background: #989900
}
#ace-editor.ace-tm .ace_marker-layer .ace_stack {
background: #5d8817
}
#ace-editor.ace-tm .ace_marker-layer .ace_bracket {
margin: -1px 0 0 -1px;
border: 1px solid #42474a
}
#ace-editor.ace-tm .ace_marker-layer .ace_active-line {
background: #00000012
}
#ace-editor.ace-tm .ace_gutter-active-line {
background-color: #2c2f31
}
#ace-editor.ace-tm .ace_marker-layer .ace_selected-word {
background: #191c1d;
border: 1px solid #0a0a6e
}
.code-container pre.prettyprint {
border:1px solid #52585c
}
.prettyprint li.L1,.prettyprint li.L3,.prettyprint li.L5,.prettyprint li.L7,.prettyprint li.L9 {
background: #222426
}
.prettyprint .pln {
color: #e8e6e3
}
.prettyprint .str {
color: #6dff6d
}
.prettyprint .kwd {
color: #7aabff
}
.prettyprint .com {
color: #ff6d6d
}
.prettyprint .typ {
color: #ff85ff
}
.prettyprint .lit {
color: #85ffff
}
.prettyprint .clo,.prettyprint .opn,.prettyprint .pun {
color: #ffff85
}
.prettyprint .tag {
color: #7aabff
}
.prettyprint .atn {
color: #ff85ff
}
.prettyprint .atv {
color: #6dff6d
}
.prettyprint .var,.prettyprint .dec {
color: #ff85ff
}
.prettyprint .fun {
color: red
}
.ea-content,.ea-callout {
margin: 0!important
}
#about-user .ethical-ads {
margin: 0 calc(-1em - 5px)
}
@media screen and (max-width: 960px) {
#about-user .ethical-ads {
margin:0 -1.2vw
}
}
@media screen and (max-width: 400px) {
#about-user .ethical-ads {
margin:0 -1em
}
}
#user-show-ea+.report-link {
top: 65px
}
.expander {
cursor: pointer;
display: block;
color: var(--expander-color);
border-radius: 3px;
background-color: var(--expander-background-color);
position: absolute;
width: 20px;
height: 20px;
text-align: center;
inset-inline-end: -22px;
bottom: 0
}
.expanded {
overflow: auto
}
.collapsed {
overflow: hidden
}
.comment {
margin-bottom: 20px
}
.comment-entry {
width: 100%;
height: 10em
}
.discussion-meta,.comment-meta,.notification-meta {
display: flex;
align-items: flex-end
}
.discussion-meta,.notification-meta {
font-size: 11px
}
.comment-meta {
font-size: smaller;
margin-bottom: 2px
}
.comment-meta-item-main {
font-size: medium;
font-weight: 700
}
.comment-meta-item+.comment-meta-item {
margin-left: 15px
}
.discussion-meta-item,.notification-meta-item {
flex: 1;
text-align: left
}
.discussion-meta-item:not(:first-child) {
margin-left: 8px
}
.discussion-meta-item:not(:last-child) {
margin-right: 8px
}
.discussion-meta-item:last-child {
text-align: right
}
.comment-meta-spacer {
flex: 1
}
.post-reply {
margin-top: 20px
}
.post-reply h3,.edit-comment-form h3 {
margin-bottom: 0
}
.post-reply input[type=submit],.edit-comment-form input[type=submit] {
margin-top: 5px
}
.discussion-up-level {
font-size: smaller;
margin-top: 0
}
.edit-comment-form {
display: none
}
.edit-comment-mode .edit-comment-form {
display: block
}
.edit-comment-mode .user-content,.edit-comment-mode .comment-meta {
display: none
}
.discussion-rating {
margin-top: 10px
}
.discussion-list,.notification-list {
padding-bottom: 0
}
.discussion-list-item,.notification-list-item {
padding-top: 10px;
border-top: 1px solid var(--content-separator-color)
}
.discussion-list-container:first-child .discussion-list-item {
border-top: 0
}
.discussion-list-logged-in .discussion-read,.notification-read {
background-color: var(--inactive-item-background-color);
margin-left: -16px;
margin-right: -16px;
padding-left: 16px;
padding-right: 16px
}
.script-discussion-list .discussion-list-item:last-child {
border-bottom: 1px solid var(--content-separator-color)
}
a.discussion-title,.notification-list-item a {
display: block;
text-decoration: none;
color: var(--overall-text-color);
padding: 4px 0 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis
}
.discussion-title,.notification-list-item a {
vertical-align: middle
}
.discussion-title:hover,.notification-list-item a {
color: var(--texty-link-visited-color)
}
.rating-icon,.badge-deleted {
border: 2px solid black;
border-radius: 5px;
font-size: 12px;
text-transform: uppercase;
font-weight: 800;
padding: 2px 5px;
margin-right: 5px;
display: inline-block;
text-align: center;
min-width: 45px;
position: relative;
top: -1px
}
.rating-icon-good {
border-color: var(--rating-icon-good-border-color);
background-color: var(--rating-icon-good-background-color);
color: var(--rating-icon-good-color)
}
.rating-icon-ok {
border-color: var(--rating-icon-ok-border-color);
background-color: var(--rating-icon-ok-background-color);
color: var(--rating-icon-ok-color)
}
.rating-icon-bad {
border-color: var(--rating-icon-bad-border-color);
background-color: var(--rating-icon-bad-background-color);
color: var(--rating-icon-bad-color)
}
.discussion-meta-item-script-name {
overflow: hidden
}
.discussion-meta-item-script-name a {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: block
}
.comment .user-content>*:first-child {
margin-top: 0
}
.comment-screenshot-control {
font-size: smaller;
padding: .5em 0
}
.discussion-header,.discussion-list-header,.notification-list-header {
display: flex;
margin-top: 30px;
margin-bottom: 20px
}
@media screen and (max-width: 400px) {
.discussion-header,.discussion-list-header,.notification-list-header,.user-list-header {
margin-top:15px;
margin-bottom: 10px
}
}
.discussion-header-no-script {
margin-top: 16px
}
.discussion-header>*:first-child,.discussion-list-header h2,.notification-list-header>*:first-child {
flex: 1;
margin: 0!important
}
.discussion-header h2,.discussion-header .discussion-up-level,.notification-list-header h2 {
margin: 0
}
.discussion-header .badge {
vertical-align: middle
}
.discussion-actions,.notification-actions {
font-size: smaller
}
.discussion-subscribed .discussion-subscribe,.discussion-not-subscribed .discussion-unsubscribe {
display: none
}
.post-discussion label:not(.radio-label),.post-reply label:not(.radio-label),.post-discussion .form-note,.post-reply .form-note {
font-size: smaller
}
#main-header {
background-color: #2d2260;
background-image: linear-gradient(180deg, #2d2260, #21194a);
box-shadow: 0 0 16px 1px rgba(0, 0, 0, 0.6);
padding: .25em 0;
}
#main-header .width-constraint {
padding: 0 0 .25em;
position: relative
}
#site-name img {
vertical-align: bottom
}
#site-name-text {
display: inline-block;
vertical-align: top
}
#site-name-text h1 {
line-height: 1.1em
}
#main-header,#main-header a,#main-header a:visited,#main-header a:active {
color: #ede9fe
}
#main-header h1 {
font-size: 72px;
margin: 0;
letter-spacing: -2px
}
#main-header h1 a {
text-decoration: none
}
#main-header .subtitle {
margin: -8px 0 0 10px;
font-size: .7em;
text-shadow: -1px -1px 0px #301c7a,1px -1px 0px #301c7a,-1px 1px 0px #301c7a,1px 1px 0px #301c7a
}
#site-nav>nav,#nav-user-info {
text-align: end;
position: absolute;
right: 0
}
#site-nav>nav {
bottom: 0
}
#nav-user-info {
top: 0
}
#site-nav>nav a:hover {
color: #ede9fe
}
#site-nav>nav {
padding: 0
}
#site-nav>nav>li {
list-style-type: none;
display: inline-block
}
#site-nav>nav>li+li {
margin-left: .5em
}
#script-search,.language-selector {
display: inline
}
#nav-user-info {
font-size: small
}
#nav-user-info select,#nav-user-info input {
font-size: 11px
}
nav nav {
position: absolute;
right: 0;
background-color: #20194a;
min-width: 100%;
display: none;
padding: 5px 0;
z-index: 10
}
nav nav li {
white-space: nowrap;
margin: 0
}
nav nav li a {
display: block;
padding: 5px 15px
}
nav a:hover+nav,nav nav:hover,nav a:focus+nav {
display: block
}
.with-submenu {
position: relative;
padding-right: 15px
}
nav .with-submenu>a:after {
content: " ▾"
}
@media screen and (max-width: 920px) {
#site-name img {
max-width:96px;
max-height: 96px;
width: 12%;
height: 12%
}
#site-name-text {
margin-top: 1.15vw;
margin-bottom: 1.15vw
}
#main-header h1 {
font-size: 8.3vw
}
#main-header .subtitle {
margin: -.8em 0 0 10px;
font-size: 2vw
}
#site-nav {
margin-top: -1vw
}
#site-nav>nav,#nav-user-info {
display: block;
position: unset;
right: unset;
padding-top: .3em
}
#site-nav>nav {
bottom: unset
}
#nav-user-info {
top: unset;
font-size: unset;
width: 100%
}
#nav-user-info .sign-in-link {
padding-right: .7em
}
#script-search,.language-selector {
display: unset
}
}
#mobile-nav {
display: none
}
.mobile-nav-opener {
cursor: pointer;
position: absolute;
right: 0;
top: 0;
font-size: 8.3vw;
padding: 0 2vw
}
#mobile-nav .collapsed {
display: none
}
#mobile-nav nav {
text-align: end;
position: absolute;
top: calc(100% + 4px);
right: calc((100vw - 100%) / -2);
width: min(22rem, calc(100vw - 0.8rem));
max-width: calc(100vw - 0.8rem);
max-height: calc(100vh - 0.75rem);
box-sizing: border-box;
overflow-x: hidden;
overflow-y: auto;
background-color: #22194a;
background-image: linear-gradient(180deg, #22194a, #21194a);
z-index: 1000;
border-radius: 0 0 0 5px;
font-size: 24px
}
#mobile-nav nav li {
list-style-type: none
}
#mobile-nav nav li>a {
display: block;
padding: 10px 15px
}
#mobile-nav nav select {
margin: 10px 15px;
width: calc(100% - 30px);
max-width: calc(100% - 30px);
font: -webkit-small-control;
box-sizing: border-box
}
#mobile-nav nav select.language-selector-locale {
font-size: .92rem;
min-height: 2rem;
padding: .15rem .35rem;
}
#mobile-nav nav li.multi-link-nav {
padding: 10px 15px
}
#mobile-nav nav li.multi-link-nav > a {
display: inline;
padding: 0
}
.gf-mobile-sign-out-icon {
display: inline-flex !important;
margin-top: 0;
padding: 0 !important;
}
.gf-user-icon.gf-mobile-sign-out-icon svg {
stroke-width: 3;
}
#mobile-nav .gf-user-icon.gf-mobile-edit-icon svg {
stroke-width: 3;
}
#gf-mobile-primary-nav {
display: flex;
align-items: center;
gap: 0.9rem;
padding: 0.7rem 0.85rem 0.55rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.16);
}
#gf-mobile-primary-nav > a {
display: inline-flex !important;
align-items: center;
justify-content: flex-start;
flex: 0 1 auto;
min-width: 0;
padding: 0 !important;
color: inherit;
text-decoration: none;
font-size: 1.16rem;
font-weight: 700;
line-height: 1.2;
min-height: 50px;
}
#gf-mobile-primary-nav-toggle {
all: unset;
display: inline-flex;
align-items: center;
justify-content: center;
width: auto;
height: auto;
color: inherit;
font-size: 1.32rem;
font-weight: 700;
cursor: pointer;
flex: none;
margin-left: auto;
}
#gf-mobile-secondary-nav {
padding: 0 0.85rem 0.45rem;
}
#gf-mobile-secondary-nav.collapsed {
display: none;
}
.gf-mobile-secondary-divider {
display: none;
}
#gf-mobile-secondary-nav > li > a {
display: block !important;
font-size: 1.04rem;
line-height: 1.2;
}
#gf-mobile-user-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.2rem 0 0;
}
#gf-mobile-user-row .user-profile-link a {
display: inline-block;
padding: 0;
font-weight: 700;
}
#gf-mobile-user-meta {
display: inline-flex;
align-items: center;
gap: 0.45rem;
min-width: 0;
}
#gf-mobile-user-actions {
display: inline-flex;
align-items: center;
gap: 0.45rem;
flex: none;
}
#gf-mobile-user-actions .gf-user-icon {
width: 30px;
height: 30px;
}
#gf-mobile-user-actions .gf-user-icon[data-panel] {
cursor: pointer;
}
.gf-mobile-user-panel {
position: static;
display: none;
opacity: 1;
transform: none;
min-width: 0;
margin-top: 0.7rem;
}
.gf-mobile-user-panel.active {
display: block !important;
position: relative;
z-index: 1;
}
.gf-mobile-user-panel a {
display: block !important;
padding: 0.75em 1.25em !important;
}
@media screen and (max-width: 920px) {
#site-nav {
display:none
}
#main-header,
#main-header .width-constraint,
#mobile-nav {
overflow: visible;
}
#mobile-nav {
display: block
}
.width-constraint {
margin-inline: auto;
padding-inline: 0;
width: calc(100% - 0.7rem);
}
#main-header .width-constraint {
width: calc(100% - 0.8rem);
padding-inline: 0.4rem;
}
}
@media screen and (max-width: 400px) {
#site-name {
margin-left:1em
}
}
#test-require-result-ok,#test-require-result-not-ok {
display: none;
font-weight: 700
}
#test-require-result-ok {
color: green
}
#test-require-result-not-ok {
color: red
}
#home-script-nav {
max-width: 700px;
margin: 0 auto 15px;
padding-bottom: 20px;
border-bottom: 1px solid var(--content-border-color)
}
.home-search input {
font-size: large
}
.home-search input[type=search] {
width: 100%
}
#home-top-sites {
overflow: hidden;
margin-top: 5px
}
#home-top-sites a {
margin: 0 5px
}
#home-step-1,#home-step-2,#home-step-3 {
overflow: auto
}
#home-step-1 figure {
float: right;
max-width: 50%;
margin-inline-end:10px;margin-top: 0
}
#home-step-2 figure {
float: left;
max-width: 50%;
margin-inline-start:7px;margin-top: 0
}
#home-step-2 li {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis
}
@media screen and (max-width: 680px) {
#home-step-1 figure,#home-step-2 figure,#home-step-3 figure {
float:unset;
max-width: unset;
width: fit-content;
margin: 0 auto
}
[id^=home-step-] figure img {
width: 100%;
height: auto
}
}
.super-title {
text-align: center
}
.browser-list {
display: none
}
#desktop-browser-list {
display: block
}
.browser-list-selector:not(.browser-list-selector-active) {
text-decoration: underline;
cursor: pointer
}
.browser-list-selector-active {
font-weight: 700
}
.browser-list-selector:not(:last-child) {
margin-right: 1em
}
.highlight {
background-color: rgba(253, 224, 71, 0.28)
}
#install-area {
margin-bottom: 1em;
display: flex;
align-items: center;
flex-wrap: wrap
}
#install-area .install-link:hover,#install-area .install-link:focus,#install-area .install-help-link:hover,#install-area .install-help-link:focus {
transition: box-shadow .2s;
box-shadow: 0 8px 16px #0003,0 6px 20px #00000030
}
.install-link,.install-link:visited,.install-link:active,.install-link:hover,.install-help-link {
transition: box-shadow .2s;
display: inline-block;
background-color: #166534;
padding: .5em 1em;
color: #ecfdf5;
text-decoration: none;
border-radius: .25rem 0 0 .25rem
}
.install-help-link,.install-help-link:visited,.install-help-link:active,.install-help-link:hover {
background-color: #22c55e;
color: #f0fdf4;
border-radius: 0 .25rem .25rem 0;
text-decoration: none;
}
.installation-instructions-modal-content-firefox,.installation-instructions-modal-content-chrome,.installation-instructions-modal-content-opera,.installation-instructions-modal-content-safari,.installation-instructions-modal-content-edge,.installation-instructions-modal-content-other {
display: none
}
.installation-instructions-modal-firefox .installation-instructions-modal-content-firefox,.installation-instructions-modal-chrome .installation-instructions-modal-content-chrome,.installation-instructions-modal-opera .installation-instructions-modal-content-opera,.installation-instructions-modal-safari .installation-instructions-modal-content-safari,.installation-instructions-modal-edge .installation-instructions-modal-content-edge,.installation-instructions-modal-other .installation-instructions-modal-content-other {
display: block
}
.installation-instructions-modal-content-bypass,.list-option-groups {
font-size: smaller
}
.list-option-group {
margin-bottom: 1em
}
.list-option-group ul {
margin: .5em 0 0;
list-style-type: none;
padding: 1em 0;
box-shadow: 0 0 5px var(--content-box-shadow-color);
border: 1px solid var(--content-border-color);
border-radius: 5px;
background-color: var(--content-background-color)
}
.list-option-group[data-gfplus-collapsed="true"] > ul > :not(.list-current) {
display: none;
}
.list-option-group .gf-list-option-toggle-row {
display: flex;
justify-content: center;
position: relative;
z-index: 2;
height: 14px;
margin-top: -14px;
margin-bottom: .55rem;
}
.sidebar button.gf-list-option-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
min-width: 28px;
height: 28px;
min-height: 28px;
margin: 0;
padding: 0;
border: 1px solid var(--content-border-color);
border-radius: 50%;
background: var(--content-background-color);
color: var(--overall-text-color) !important;
box-shadow: none !important;
cursor: pointer;
transform: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base), transform var(--transition-base);
}
.sidebar button.gf-list-option-toggle:hover,
.sidebar button.gf-list-option-toggle:focus-visible {
background: var(--inactive-item-background-color);
border-color: var(--link-color);
color: var(--link-color) !important;
box-shadow: none !important;
outline: none;
transform: scale(1.06) !important;
}
.sidebar button.gf-list-option-toggle:focus {
box-shadow: none !important;
outline: none;
}
.sidebar button.gf-list-option-toggle svg {
width: 15px;
height: 15px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.list-option-group a {
padding: .35em 1em;
display: block
}
.list-option-group a:hover,.list-option-group a:focus {
background: linear-gradient(var(--list-option-hover-background-color-gradient-1),var(--list-option-hover-background-color-gradient-2));
text-decoration: none;
box-shadow: inset 0 -1px var(--list-option-hover-box-shadow-top),inset 0 1px var(--list-option-hover-box-shadow-bottom)
}
.list-option-group .list-current {
border-left: 7px solid var(--link-color);
color: #f1f5f9;
font-weight: 600;
box-shadow: inset 0 1px rgba(120, 169, 255, .12), inset 0 -1px rgba(0, 0, 0, .24);
margin: 0 0 0 -4px;
padding: .4em 1em .4em calc(1em - 3px);
background: linear-gradient(90deg, rgba(120, 169, 255, .14), rgba(120, 169, 255, .04))
}
@media screen and (min-width: 440px) and (max-width: 960px) {
.list-option-group a,.list-option-group .list-current {
padding-left:1.2vw;
padding-right: 1.2vw
}
}
.list-option-button {
display: block;
background-color: var(--list-option-button-background-color);
text-align: center;
text-decoration: none;
color: var(--list-option-button-color)!important;
border: 1px solid var(--list-option-button-border-color);
padding: .5em;
font-weight: 700
}
.list-option-button:hover,.list-option-button:focus {
background: linear-gradient(var(--list-option-button-background-color-gradient-1),var(--list-option-button-background-color-gradient-2));
text-decoration: none
}
.list-option:not(.list-current) select {
width: calc(100% - 1.4em + 3px);
margin: .4em 1em .4em calc(1em - 3px)
}
.list-option.list-current select,.log-table {
width: 100%
}
.log-table th {
text-align: left
}
.log-table td,.log-table th {
padding: 0 5px
}
.log-table td .possibly-long-text {
max-width: 500px;
overflow-wrap: break-word
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content {
display: table;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content thead {
display: table-header-group;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content tbody {
display: table-row-group;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content tr {
display: table-row;
}
html[data-gfplus-moderator-actions-page] table.log-table.text-content th,
html[data-gfplus-moderator-actions-page] table.log-table.text-content td {
display: table-cell;
vertical-align: top;
}
@media screen and (max-width: 820px) {
html[data-gfplus-moderator-actions-page] .width-constraint {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
padding-bottom: .25rem;
}
html[data-gfplus-moderator-actions-page] .width-constraint > .log-table {
min-width: 48rem;
}
}
.modal__overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #0009;
display: flex;
justify-content: center;
align-items: center;
z-index: 100
}
.modal__container {
background-color: var(--content-background-color);
padding: 30px;
max-width: 500px;
max-height: 100vh;
border-radius: var(--border-radius-small);
overflow-y: auto;
box-sizing: border-box;
border: 1px solid var(--content-border-color);
box-shadow: var(--shadow-soft)
}
.modal__header {
display: flex;
justify-content: space-between;
align-items: center
}
.modal__title {
margin-top: 0!important;
margin-bottom: 0;
font-weight: 600;
font-size: 1rem;
line-height: 1.25;
box-sizing: border-box
}
.modal__close {
background: transparent;
border: 0
}
.modal__header .modal__close:before {
content: "✕"
}
.modal__content {
margin-bottom: 2rem
}
.modal__content q {
font-style: italic
}
.modal__btn {
font-size: .875rem;
padding: .5rem 1rem;
background-color: rgba(148, 163, 184, .16);
color: var(--overall-text-color);
border-radius: .25rem;
border-style: none;
border-width: 0;
cursor: pointer;
-webkit-appearance: button;
text-transform: none;
overflow: visible;
line-height: 1.15;
margin: 0 0 0 .5rem;
will-change: transform;
-moz-osx-font-smoothing: grayscale;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transform: translateZ(0);
transform: translateZ(0);
transition: -webkit-transform .25s ease-out;
transition: transform .25s ease-out;
transition: transform .25s ease-out,-webkit-transform .25s ease-out
}
.modal__btn:focus,.modal__btn:hover {
-webkit-transform: scale(1.05);
transform: scale(1.05)
}
.modal__btn-primary {
background-color: #22c55e;
color: #052e16
}
.modal__footer {
text-align: right
}
@keyframes mmfadeIn {
0% {
opacity: 0
}
to {
opacity: 1
}
}
@keyframes mmfadeOut {
0% {
opacity: 1
}
to {
opacity: 0
}
}
@keyframes mmslideIn {
0% {
transform: translateY(15%)
}
to {
transform: translateY(0)
}
}
@keyframes mmslideOut {
0% {
transform: translateY(0)
}
to {
transform: translateY(-10%)
}
}
.micromodal-slide {
display: none
}
.micromodal-slide.is-open {
display: block
}
.micromodal-slide[aria-hidden=false] .modal__overlay {
animation: mmfadeIn .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide[aria-hidden=false] .modal__container {
animation: mmslideIn .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide[aria-hidden=true] .modal__overlay {
animation: mmfadeOut .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide[aria-hidden=true] .modal__container {
animation: mmslideOut .3s cubic-bezier(0,0,.2,1)
}
.micromodal-slide .modal__container,.micromodal-slide .modal__overlay {
will-change: transform
}
.notification-widget {
display: inline-block;
width: 1em;
height: 1em;
text-align: center;
line-height: 1em;
padding: 2px;
background-color: #0ea5e9;
border-radius: 50%;
color: #0f172a;
text-decoration: none
}
.notification-type-consecutive_bad_ratings a {
white-space: normal
}
.post-install {
margin: 1em 0;
border-radius: 2px;
padding: 5px;
max-width: 600px;
display: none;
align-items: center;
background-color: rgba(14, 165, 233, 0.18);
border: 1px solid rgba(14, 165, 233, 0.35);
position: relative
}
.post-install-label {
font-size: xx-small;
position: absolute;
top: -2px;
left: 2px;
opacity: .5
}
.post-install-text {
text-align: center;
align-items: center;
flex: 1
}
.post-install-text p {
margin: 0;
padding: 0
}
.post-install-button {
text-align: center;
margin-left: 10px;
white-space: nowrap
}
.preview-results {
border: 1px solid var(--content-border-color);
border-left: 1px solid var(--content-border-color) !important;
border-radius: 0 0 var(--border-radius-small) var(--border-radius-small);
background: var(--content-background-color);
overflow: auto;
box-sizing: border-box;
margin: 0;
padding: 16px
}
.previewable .preview-results.user-content {
border-left: 1px solid var(--content-border-color) !important;
border-radius: 0 0 var(--border-radius-small) var(--border-radius-small);
background: var(--content-background-color);
}
.preview-results>p:first-child {
margin-top: 0
}
.preview-results>p:last-child {
margin-bottom: 0
}
.previewable textarea {
margin: 0
}
.previewable .tabs {
margin-top: 10px;
margin-bottom: -4px
}
.gf-editor-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: .3rem;
padding: .42rem;
margin: 0;
background: color-mix(in srgb, var(--content-background-color) 84%, #78a9ff 16%);
border: 1px solid var(--content-border-color);
border-bottom: 0;
border-radius: 0 10px 0 0;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06), 0 10px 22px rgba(0, 0, 0, .14)
}
.gf-editor-toolbar + textarea,
.gf-editor-toolbar + .field_with_errors textarea,
.gf-editor-toolbar ~ .preview-results {
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button {
all: unset;
box-sizing: border-box !important;
inline-size: 34px !important;
block-size: 34px !important;
min-inline-size: 34px !important;
min-block-size: 34px !important;
position: relative !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0 !important;
margin: 0 !important;
border: 1px solid rgba(120, 169, 255, .2) !important;
border-radius: 9px !important;
background: rgba(11, 18, 32, .72) !important;
color: var(--overall-text-color) !important;
cursor: pointer !important;
line-height: 1 !important;
box-shadow: none !important;
transform: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base) !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button:hover,
.gf-editor-toolbar button.gf-editor-toolbar-button:focus-visible {
background: rgba(120, 169, 255, .16) !important;
border-color: rgba(120, 169, 255, .44) !important;
color: var(--link-color) !important;
transform: none !important;
box-shadow: 0 7px 16px rgba(0, 0, 0, .2) !important;
outline: none !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button:active {
transform: none !important;
box-shadow: none !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-button svg {
inline-size: 17px;
block-size: 17px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round
}
.gf-editor-toolbar button.gf-editor-toolbar-button--text {
font-size: .8rem !important;
font-weight: 800;
font-family: var(--font-family-base);
}
.gf-editor-toolbar-color-tool {
display: inline-flex;
align-items: center;
position: relative;
margin: 0;
}
.gf-editor-toolbar-heading-tool {
display: inline-flex;
align-items: center;
margin: 0;
}
.gf-editor-toolbar-heading-tool button.gf-editor-toolbar-button {
inline-size: 31px !important;
min-inline-size: 31px !important;
border-start-end-radius: 0 !important;
border-end-end-radius: 0 !important;
border-inline-end: 0 !important;
}
.gf-editor-toolbar select.gf-editor-toolbar-heading-select {
appearance: none !important;
-webkit-appearance: none !important;
box-sizing: border-box !important;
inline-size: 42px !important;
block-size: 34px !important;
min-inline-size: 42px !important;
min-block-size: 34px !important;
padding: 0 16px 0 8px !important;
margin: 0 !important;
border: 1px solid rgba(120, 169, 255, .2) !important;
border-start-start-radius: 0 !important;
border-end-start-radius: 0 !important;
border-start-end-radius: 9px !important;
border-end-end-radius: 9px !important;
background: rgba(11, 18, 32, .58) !important;
color: var(--overall-text-color) !important;
font: 800 .75rem/1 var(--font-family-base) !important;
cursor: pointer !important;
box-shadow: none !important;
background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%) !important;
background-position: calc(100% - 10px) 14px, calc(100% - 6px) 14px !important;
background-size: 4px 4px, 4px 4px !important;
background-repeat: no-repeat !important;
}
.gf-editor-toolbar select.gf-editor-toolbar-heading-select:hover,
.gf-editor-toolbar select.gf-editor-toolbar-heading-select:focus-visible {
background-color: rgba(120, 169, 255, .14) !important;
border-color: rgba(120, 169, 255, .44) !important;
color: var(--link-color) !important;
outline: none !important;
}
.gf-editor-toolbar-color-tool button.gf-editor-toolbar-button {
inline-size: 31px !important;
min-inline-size: 31px !important;
border-start-end-radius: 0 !important;
border-end-end-radius: 0 !important;
border-inline-end: 0 !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-color-swatch-button {
all: unset;
box-sizing: border-box !important;
inline-size: 20px !important;
block-size: 34px !important;
min-inline-size: 20px !important;
min-block-size: 34px !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
padding: 0 !important;
margin: 0 !important;
border: 1px solid rgba(120, 169, 255, .2) !important;
border-start-start-radius: 0 !important;
border-end-start-radius: 0 !important;
border-start-end-radius: 9px !important;
border-end-end-radius: 9px !important;
background: rgba(11, 18, 32, .58) !important;
cursor: pointer !important;
box-shadow: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base) !important;
}
.gf-editor-toolbar button.gf-editor-toolbar-color-swatch-button:hover,
.gf-editor-toolbar button.gf-editor-toolbar-color-swatch-button:focus-visible,
.gf-editor-toolbar-color-tool:hover button.gf-editor-toolbar-color-swatch-button,
.gf-editor-toolbar-color-tool:focus-within button.gf-editor-toolbar-color-swatch-button {
background: rgba(120, 169, 255, .14) !important;
border-color: rgba(120, 169, 255, .44) !important;
transform: none !important;
outline: none !important;
box-shadow: 0 7px 16px rgba(0, 0, 0, .16) !important;
}
.gf-editor-toolbar-color-input {
position: absolute !important;
inset-block-start: 0 !important;
inset-inline-end: 0 !important;
inline-size: 20px !important;
block-size: 34px !important;
opacity: 0 !important;
cursor: pointer !important;
pointer-events: auto !important;
z-index: 2 !important;
padding: 0 !important;
margin: 0 !important;
border: 0 !important;
}
.gf-editor-toolbar-color-swatch {
inline-size: 12px;
block-size: 22px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, .24);
box-shadow: 0 0 0 1px rgba(0, 0, 0, .35);
}
#report_explanation {
width: 100%;
height: 10em
}
.reportable {
position: relative
}
.report-link-abs {
position: absolute;
top: 0;
right: 0;
font-size: smaller;
margin-right: 16px;
margin-top: 8px
}
.report-list-item:not(:last-child) {
padding-bottom: 20px;
border-bottom: 1px solid gray;
margin-bottom: 20px
}
.report-list-item .inline-form {
margin-right: 5px
}
.report-resolution-options {
display: inline-block;
vertical-align: top;
min-width: 30%
}
.report-resolution-options+.report-resolution-options {
margin-left: 1em
}
.report-resolution-options input[type=submit] {
margin-top: .5em
}
.report-resolution-options textarea {
width: 100%
}
.report-screenshot-control {
font-size: smaller;
padding: .5em 0
}
.unauthorized-code-comparison th {
text-align: left
}
.unauthorized-code-comparison th,.unauthorized-code-comparison td {
padding-right: 1em
}
body:lang(he),body:lang(ar),body:lang(ug),body:lang(ckb) {
direction: rtl
}
:not(:lang(he)):not(:lang(ar)):not(:lang(ug)):not(:lang(ckb)) {
direction: ltr
}
body:lang(he) #main-header,body:lang(ar) #main-header,body:lang(ug) #main-header,body:lang(ckb) #main-header {
direction: ltr
}
:lang(ar) #home-step-1 figure,:lang(he) #home-step-1 figure,:lang(ug) #home-step-1 figure,:lang(ckb) #home-step-1 figure {
float: left
}
:lang(ar) #home-step-2 figure,:lang(he) #home-step-2 figure,:lang(ug) #home-step-2 figure,:lang(ckb) #home-step-2 figure {
float: right
}
#script-info {
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
clear: left;
background-color: var(--content-background-color);
margin: 1.5em 0 0;
box-shadow: var(--shadow-soft);
display: grid;
gap: 1.1rem;
overflow-x: hidden;
overflow-wrap: anywhere;
word-break: break-word;
transition: box-shadow var(--transition-base), border-color var(--transition-base), background-color var(--transition-base)
}
#script-info>* {
min-width: 0
}
#script-info:hover {
border-color: var(--container-glow-stroke);
box-shadow: var(--shadow-hover)
}
#script-content {
margin-top: 1.5em
}
#script-content>*:first-child {
margin-top: 0
}
#script-info header h2 {
margin: .2em 0 0;
font-size: clamp(1.75rem, 2.8vw, 2.4rem);
line-height: 1.15;
font-weight: 700;
letter-spacing: .01em;
overflow-wrap: anywhere
}
#script-description {
margin: 0
}
#version-note,#reported-note,#deleted-note {
font-style: italic;
background-color: var(--alert-background-color);
border: 2px dotted var(--alert-border-color);
color: var(--alert-text-color);
padding: .5em
}
#script-feedback-suggestion {
margin: .75em 0
}
#script-content h3 {
margin-top: 30px
}
.checkup-list {
padding-inline-start:1em}
.checkup-list li {
list-style-type: "✗";
padding-inline-start:.5em}
.checkup-list li::marker {
color: red
}
.checkup-list li.good-check {
list-style-type: "✓"
}
.checkup-list li.good-check::marker {
color: green
}
.script-meta-block {
max-width: 600px;
column-count: 2
}
.script-meta-block>*:last-child {
margin-bottom: 1em
}
.gf-script-card-actions {
display: flex;
justify-content: flex-end;
align-items: center;
flex-wrap: wrap;
gap: 0.55rem;
margin-top: 0.9rem;
}
#install-area .gf-script-card-actions,
#script-links .gf-script-card-actions {
justify-content: flex-start;
margin-top: 0.75rem;
}
#install-area > .gf-script-star-button {
margin-left: .45rem;
min-width: 2.4rem;
min-height: 2.4rem;
}
#install-area > .gf-script-star-button svg {
width: 24px;
height: 24px;
}
.gf-script-install-button,
.gf-script-detail-button,
.gf-script-star-button {
display: inline-flex;
align-items: center;
justify-content: center;
height: 2.2rem;
border-radius: 999px;
border: 1px solid var(--content-border-color);
background: linear-gradient(180deg, rgba(139, 92, 246, 0.22), rgba(139, 92, 246, 0.1));
color: var(--overall-text-color) !important;
text-decoration: none;
box-sizing: border-box;
transition: transform var(--transition-base), background-color var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base), color var(--transition-base);
}
.gf-script-install-button,
.gf-script-install-button:visited,
.gf-script-install-button:hover,
.gf-script-install-button:focus-visible,
.gf-script-detail-button,
.gf-script-detail-button:visited,
.gf-script-detail-button:hover,
.gf-script-detail-button:focus-visible {
text-decoration: none !important;
}
.gf-script-install-button {
gap: 0.45rem;
padding: 0 0.95rem;
font-size: 0.92rem;
font-weight: 700;
letter-spacing: 0.01em;
}
.gf-script-detail-button {
width: 2.2rem;
min-width: 2.2rem;
padding: 0;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
}
.gf-script-star-button {
width: auto;
height: auto;
padding: 0;
margin-left: 0;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
border: none;
background: transparent;
color: var(--overall-text-color) !important;
box-shadow: none;
line-height: 0;
transform: none;
transition: color var(--transition-base);
}
.gf-script-install-button svg,
.gf-script-detail-button svg,
.gf-script-star-button svg {
width: 19px;
height: 19px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
flex: none;
transition: fill var(--transition-base), stroke var(--transition-base), stroke-width var(--transition-base), transform var(--transition-base);
}
.gf-script-install-button:hover,
.gf-script-install-button:focus-visible,
.gf-script-detail-button:hover,
.gf-script-detail-button:focus-visible,
.gf-script-detail-button[data-expanded="true"] {
border-color: var(--link-color);
color: var(--link-color) !important;
box-shadow: none;
outline: none;
}
.gf-script-detail-button[data-expanded="true"] svg {
transform: rotate(45deg);
}
.gf-script-star-button:hover,
.gf-script-star-button:focus,
.gf-script-star-button:focus-visible,
.gf-script-star-button[data-active="true"],
.gf-script-star-button[data-active="true"]:hover,
.gf-script-star-button[data-active="true"]:focus,
.gf-script-star-button[data-active="true"]:focus-visible {
background: transparent !important;
border-color: transparent !important;
box-shadow: none !important;
outline: none !important;
transform: none !important;
}
.gf-script-star-button:hover,
.gf-script-star-button:focus,
.gf-script-star-button:focus-visible {
color: var(--overall-text-color) !important;
}
.gf-script-star-button:hover svg,
.gf-script-star-button:focus-visible svg {
fill: none;
stroke: currentColor;
stroke-width: 2.55;
transform: scale(1.06);
}
.gf-script-star-button[data-active="true"] {
color: #f4b400 !important;
}
.gf-script-star-button[data-active="true"] svg {
stroke: #f4b400;
fill: rgba(244, 180, 0, 0.18);
stroke-width: 2.1;
width: 21px;
height: 21px;
}
.gf-script-star-button[data-active="true"]:hover svg,
.gf-script-star-button[data-active="true"]:focus-visible svg {
stroke-width: 2.65;
transform: scale(1.06);
}
.gf-script-star-button[data-active="true"]:hover,
.gf-script-star-button[data-active="true"]:focus,
.gf-script-star-button[data-active="true"]:focus-visible {
color: #f4b400 !important;
}
.inline-script-stats {
align-items: center;
}
.inline-script-stats dd span relative-time {
white-space: nowrap !important;
display: inline-block !important;
line-height: 1.3;
vertical-align: middle;
}
.inline-script-stats,.inline-script-stats dt,.inline-script-stats dd {
vertical-align: top;
padding: 0;
font-size: small;
}
.inline-script-stats dt,.inline-script-stats dd {
box-sizing: border-box;
overflow-wrap: break-word;
margin: 1px 0
}
.inline-script-stats dt {
font-weight: 700;
text-align: end;
padding-inline-end:1em}
html[data-gfplus-safari] .script-meta-block {
column-count: initial;
}
html[data-gfplus-safari] .inline-script-stats {
display: grid;
grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr);
column-gap: 1.4rem;
row-gap: .32rem;
margin: 0;
}
html[data-gfplus-safari] .inline-script-stats dt,
html[data-gfplus-safari] .inline-script-stats dd {
margin: 0;
break-inside: avoid;
-webkit-column-break-inside: avoid;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(-n+3) {
grid-column: 1;
}
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(-n+3) {
grid-column: 2;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(n+4) {
grid-column: 3;
}
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(n+4) {
grid-column: 4;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(1),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(1),
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(4),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(4) {
grid-row: 1;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(2),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(2),
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(5),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(5) {
grid-row: 2;
}
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(3),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(3),
html[data-gfplus-safari] .inline-script-stats dt:nth-of-type(6),
html[data-gfplus-safari] .inline-script-stats dd:nth-of-type(6) {
grid-row: 3;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(-n+5) {
grid-column: 1;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(-n+5) {
grid-column: 2;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(n+6) {
grid-column: 3;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(n+6) {
grid-column: 4;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(1),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(1),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(6),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(6) {
grid-row: 1;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(2),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(2),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(7),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(7) {
grid-row: 2;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(3),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(3),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(8),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(8) {
grid-row: 3;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(4),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(4),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(9),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(9) {
grid-row: 4;
}
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(5),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(5),
html[data-gfplus-safari] #script-stats.inline-script-stats dt:nth-of-type(10),
html[data-gfplus-safari] #script-stats.inline-script-stats dd:nth-of-type(10) {
grid-row: 5;
}
dd.script-list-ratings {
margin-top: 0;
margin-bottom: 0;
display: flex !important;
align-items: center !important;
gap: 6px !important;
overflow: visible;
overflow-wrap: normal;
word-break: normal;
white-space: nowrap;
}
dd.script-list-ratings > span {
display: inline-flex !important;
align-items: center !important;
gap: 4px !important;
overflow: visible;
flex-wrap: nowrap !important;
overflow-wrap: normal;
word-break: normal;
white-space: nowrap;
}
dd.script-list-ratings span.good-rating-count,
dd.script-list-ratings span.ok-rating-count,
dd.script-list-ratings span.bad-rating-count {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
flex: 0 0 auto !important;
min-width: 2.8em !important;
box-sizing: border-box !important;
margin: 0 !important;
padding: .1em .5em !important;
line-height: 1.1 !important;
overflow-wrap: normal !important;
word-break: normal !important;
white-space: nowrap !important;
}
dd.script-list-ratings span.good-rating-count { color: #4CAF50 !important; }
dd.script-list-ratings span.ok-rating-count { color: #FFC107 !important; }
dd.script-list-ratings span.bad-rating-count { color: #F44336 !important; }
@media screen and (max-width: 600px) {
.script-meta-block {
max-width: 100%;
column-count: initial;
}
.inline-script-stats,
html[data-gfplus-safari] .inline-script-stats,
html[data-gfplus-safari] #script-stats.inline-script-stats {
display: grid;
grid-template-columns: minmax(6.8rem, 42%) minmax(0, 1fr);
column-gap: .75rem;
row-gap: .34rem;
align-items: start;
margin: 0;
}
.inline-script-stats dt,
.inline-script-stats dd,
html[data-gfplus-safari] .inline-script-stats dt,
html[data-gfplus-safari] .inline-script-stats dd,
html[data-gfplus-safari] #script-stats.inline-script-stats dt,
html[data-gfplus-safari] #script-stats.inline-script-stats dd {
grid-column: auto !important;
grid-row: auto !important;
min-width: 0;
margin: 0;
break-inside: auto;
-webkit-column-break-inside: auto;
}
.inline-script-stats dt {
grid-column: 1 !important;
text-align: start;
padding-inline-end: .35rem;
}
.inline-script-stats dd {
grid-column: 2 !important;
overflow-wrap: anywhere;
}
dd.script-list-ratings {
justify-content: flex-start !important;
white-space: normal !important;
}
dd.script-list-ratings > span {
flex-wrap: wrap !important;
gap: 3px !important;
white-space: normal !important;
}
dd.script-list-ratings span.good-rating-count,
dd.script-list-ratings span.ok-rating-count,
dd.script-list-ratings span.bad-rating-count {
min-width: 2.65em !important;
padding: .08em .38em !important;
}
}
.script-antifeatures span[title] {
text-decoration: underline;
text-decoration-style: dotted
}
.script-show-compatibility {
vertical-align: bottom
}
.browser-compatible,.browser-incompatible,.browser-incompatible-marker {
width: 16px;
height: 16px
}
.browser-incompatible {
opacity: .5
}
.browser-incompatible-marker {
position: absolute
}
.script-lock-appeal-actions form {
display: inline-block;
margin-top: 1em
}
.change-script-set section {
border-bottom: 1px solid var(--content-border-color);
padding-bottom: 1em
}
.change-script-set textarea {
height: 5em
}
.change-script-set .selection-box {
width: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: 1em
}
@media screen and (max-width: 720px) {
.change-script-set .selection-box {
width:100%
}
}
.change-script-set select[multiple] {
width: 100%
}
.change-script-set {
display: grid;
gap: 1.25rem;
padding: 1.25rem;
background: linear-gradient(180deg, rgba(139, 92, 246, .08), rgba(17, 24, 39, .55));
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-shadow: var(--shadow-soft);
}
.change-script-set section {
margin: 0;
}
.change-script-set button {
margin-left: 0;
}
.change-script-set #script-set-scripts {
display: grid;
grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
gap: 1rem;
align-items: start;
}
.change-script-set .selection-box,
.change-script-set #script-set-scripts > .form-control:not(.selection-box) {
margin-bottom: 0;
padding: 1rem;
background-color: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04), 0 10px 24px rgba(15, 23, 42, .18);
}
.change-script-set.gf-set-editor-enhanced select[name="remove-scripts-included[]"],
.change-script-set.gf-set-editor-enhanced button[name="remove-selected-scripts"] {
display: none !important;
}
.gf-set-script-list-panel {
display: grid;
gap: .85rem;
}
.gf-set-script-list-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: .75rem;
}
.gf-set-script-list-title {
font-size: 1rem;
font-weight: 700;
color: var(--overall-text-color);
}
.gf-set-script-list-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2rem;
padding: .25rem .65rem;
border-radius: 999px;
background: rgba(139, 92, 246, .18);
color: #ddd6fe;
font-size: .82rem;
font-weight: 700;
}
.gf-set-script-list {
display: grid;
gap: .6rem;
}
.gf-set-script-row {
display: flex;
align-items: center;
gap: .75rem;
padding: .8rem .9rem;
background: linear-gradient(180deg, rgba(139, 92, 246, .12), rgba(139, 92, 246, .06));
border: 1px solid rgba(167, 139, 250, .22);
border-radius: var(--border-radius-small);
transition: border-color var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base);
}
.gf-set-script-row:hover {
border-color: rgba(196, 181, 253, .34);
box-shadow: 0 12px 22px rgba(15, 23, 42, .2);
transform: translateY(-1px);
}
.gf-set-script-name {
flex: 1;
min-width: 0;
color: var(--overall-text-color);
font-weight: 600;
overflow-wrap: anywhere;
}
.gf-set-script-remove {
display: inline-grid;
place-items: center;
width: 1.35rem;
height: 1.35rem;
min-width: 1.35rem;
min-height: 1.35rem;
margin: 0;
padding: 0;
border: 0;
border-radius: 0;
background: transparent;
color: #fecaca !important;
box-shadow: none;
cursor: pointer;
transform: none !important;
}
.gf-set-script-remove:hover,
.gf-set-script-remove:focus-visible {
background: transparent;
color: #fee2e2 !important;
box-shadow: none;
transform: none !important;
}
.gf-set-script-remove svg {
width: 16px;
height: 16px;
stroke: currentColor;
stroke-width: 2.25;
fill: none;
}
.gf-set-script-empty {
padding: .95rem 1rem;
background: rgba(148, 163, 184, .08);
border: 1px dashed rgba(148, 163, 184, .25);
border-radius: var(--border-radius-small);
color: var(--texty-link-visited-color);
}
.gf-set-editor-footer {
display: flex;
justify-content: flex-end;
align-items: center;
gap: .75rem;
padding-top: .25rem;
}
.gf-set-editor-actions {
display: flex;
justify-content: flex-end;
margin-top: .85rem;
}
@media screen and (max-width: 820px) {
.change-script-set #script-set-scripts {
grid-template-columns: 1fr;
}
}
.add-script-set label {
font-weight: 700;
display: block
}
.add-automatic-script-set-4>* {
vertical-align: top
}
.history_versions {
display: table;
padding: 0
}
.history_versions>li {
display: table-row
}
.diff-controls,.version-number,.version-date,.version-changelog {
display: table-cell;
padding-bottom: .5em
}
.diff-controls,.version-number,.version-date {
white-space: nowrap;
padding-right: 1em
}
.version-changelog {
overflow-wrap: anywhere
}
.version-changelog img {
max-width: 100%
}
.version-changelog p:first-child {
margin-top: 0
}
.version-changelog p:last-child {
margin-bottom: 0
}
.remove-attachment {
margin-top: 20px
}
.remove-attachment input {
margin-left: 0
}
.sidebarred {
display: flex
}
.sidebarred-main-content {
flex: 1
}
.sidebar {
width: 200px;
padding-top: 1.75em;
padding-bottom: .75em;
margin-inline-start:1.5em;flex: none
}
@media screen and (min-width: 801px) {
.sidebar {
position: sticky;
top: var(--gfplus-sidebar-sticky-top, 1rem);
align-self: flex-start;
box-sizing: border-box;
max-height: none;
overflow: visible;
scrollbar-gutter: auto;
will-change: top;
}
}
.close-sidebar,.open-sidebar {
cursor: pointer
}
.close-sidebar {
display: none
}
.open-sidebar {
visibility: hidden;
float: right;
background-color: var(--sidebar-background);
padding: 2px 1.2vw;
margin-left: 1.2vw;
margin-right: -1.2vw;
border-radius: 6px 0 0 6px;
border-width: 1px 0 1px 1px;
border-style: solid;
border-color: gray
}
.sidebar-title {
flex: 1
}
.gf-sidebar-scroll-controls {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: .5rem;
margin-top: .9rem;
}
.sidebar button.gf-sidebar-scroll-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 2.25rem;
margin: 0;
padding: .4rem;
border: 1px solid var(--content-border-color);
border-radius: 7px;
background: var(--content-background-color);
color: var(--overall-text-color) !important;
box-shadow: none !important;
cursor: pointer;
transform: none !important;
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}
.sidebar button.gf-sidebar-scroll-button:hover,
.sidebar button.gf-sidebar-scroll-button:focus-visible {
background: var(--inactive-item-background-color);
border-color: var(--link-color);
color: var(--link-color) !important;
box-shadow: none !important;
outline: none;
transform: none !important;
}
.sidebar button.gf-sidebar-scroll-button:focus {
box-shadow: none !important;
outline: none;
}
.sidebar button.gf-sidebar-scroll-button:active {
box-shadow: none !important;
transform: translateY(1px) !important;
}
.sidebar button.gf-sidebar-scroll-button svg {
width: 18px;
height: 18px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
@media screen and (max-width: 800px) {
.sidebarred {
display:block;
position: relative
}
.sidebar {
position: absolute;
right: 0;
top: 0;
z-index: 40;
background: var(--sidebar-background);
padding-top: 0;
padding-left: 1em;
padding-right: 1em;
max-height: min(calc(100vh - 1.5rem), calc(100dvh - 1.5rem));
border-width: 1px 0 1px 1px;
border-style: solid;
border-color: gray;
border-radius: 6px 0 0 6px;
overflow-y: auto;
overscroll-behavior: contain;
box-shadow: var(--shadow-soft)
}
.sidebar.collapsed {
display: none
}
.close-sidebar {
display: flex;
margin-bottom: 1.5em;
background-color: var(--close-sidebar-background);
border-bottom: 1px solid var(--close-sidebar-border-bottom);
margin-left: -16px;
margin-right: -16px;
padding: .25em 1.2vw .25em 16px
}
.open-sidebar.sidebar-collapsed {
visibility: visible;
margin-right: 0;
position: relative;
right: -0.35rem;
z-index: 39;
box-shadow: var(--shadow-soft)
}
html.gfplus-mobile-sidebar-stuck .sidebar:not(.collapsed) {
position: fixed;
top: .75rem;
right: 0;
}
html.gfplus-mobile-sidebar-stuck .open-sidebar.sidebar-collapsed {
position: fixed;
top: .75rem;
right: 0;
}
}
@media screen and (min-width: 800px) {
.sidebarred-main-content {
max-width:calc(100% - 224px)
}
}
@media screen and (max-width: 400px) {
.open-sidebar {
margin-right:0
}
.close-sidebar {
padding-right: 2.4vw;
margin-right: -1em
}
}
.tabs {
list-style: none;
padding: 0 1em;
margin: 0 -1em;
display: flex;
position: relative;
top: -3.5px;
flex-wrap: wrap
}
.tabs>* {
align-items: stretch
}
.tabs>*>* {
padding: .25em .5em .5em;
display: block
}
.tabs a {
text-decoration: none;
cursor: pointer
}
.tabs .current,.tabs>*:not(.current) a:hover,.tabs>*:not(.current) a:focus {
background: var(--tab-active-background-color);
box-shadow: inset 1px 0 var(--tab-active-box-shadow-color),inset -1px 0 var(--tab-active-box-shadow-color),inset 0 -1px var(--tab-active-box-shadow-color)
}
.tabs .current {
border-top: 7px solid var(--tab-active-top-border-color)
}
.tabs>*:not(.current) a {
margin-top: 3.5px;
padding-top: calc(.25em + 3.5px)
}
.user-content {
background: linear-gradient(to right,var(--user-content-background-color-gradient-1),var(--user-content-background-color-gradient-2) 1em);
border-left: 2px solid var(--user-content-border-left-color);
padding: .5em 1em;
overflow-x: auto
}
.user-content>p:first-child {
margin-top: 0
}
.user-content>p:last-child {
margin-bottom: 0
}
.user-content img {
max-width: 100%
}
.user-content img.gfplus-standalone-lightbox-trigger,
#script-content img.gfplus-standalone-lightbox-trigger {
cursor: zoom-in
}
.user-screenshots * {
vertical-align: middle
}
.user-screenshots a {
text-decoration: none
}
.comment-screenshot-control {
margin: 10px 0
}
.remove-images {
display: flex;
margin-top: 5px
}
.remove-image {
border: 2px solid black;
padding: 5px;
display: flex;
justify-content: space-between;
flex-direction: column
}
.remove-image:not(:first-child) {
margin-left: 5px
}
.remove-image img {
display: block
}
.remove-image-selecter,.comment .user-content .user-screenshots {
margin-top: 10px
}
#additional-info .user-screenshots {
margin-top: 1em
}
.user-content blockquote {
margin-left: 10px;
padding-left: 10px;
border-left: 2px solid var(--content-border-color)
}
.user-content>ol:first-child,.user-content>ul:first-child {
margin-top: 0
}
.user-content>ol:last-child,.user-content>ul:last-child {
margin-bottom: 0
}
@keyframes lum-fade {
0% {
opacity: 0
}
to {
opacity: 1
}
}
@keyframes lum-fadeZoom {
0% {
transform: scale(.5);
opacity: 0
}
to {
transform: scale(1);
opacity: 1
}
}
@keyframes lum-loader-rotate {
0% {
transform: translate(-50%,-50%) rotate(0)
}
50% {
transform: translate(-50%,-50%) rotate(-180deg)
}
to {
transform: translate(-50%,-50%) rotate(-360deg)
}
}
@keyframes lum-loader-before {
0% {
transform: scale(1)
}
10% {
transform: scale(1.2) translate(6px)
}
25% {
transform: scale(1.3) translate(8px)
}
40% {
transform: scale(1.2) translate(6px)
}
50% {
transform: scale(1)
}
60% {
transform: scale(.8) translate(6px)
}
75% {
transform: scale(.7) translate(8px)
}
90% {
transform: scale(.8) translate(6px)
}
to {
transform: scale(1)
}
}
@keyframes lum-loader-after {
0% {
transform: scale(1)
}
10% {
transform: scale(1.2) translate(-6px)
}
25% {
transform: scale(1.3) translate(-8px)
}
40% {
transform: scale(1.2) translate(-6px)
}
50% {
transform: scale(1)
}
60% {
transform: scale(.8) translate(-6px)
}
75% {
transform: scale(.7) translate(-8px)
}
90% {
transform: scale(.8) translate(-6px)
}
to {
transform: scale(1)
}
}
.lum-lightbox {
background: #0009
}
.lum-lightbox.lum-open {
position: fixed !important;
inset: 0 !important;
z-index: 2147483000;
display: block;
overflow: hidden !important
}
html.gfplus-lightbox-open,
html.gfplus-lightbox-open body {
overflow: hidden !important;
overscroll-behavior: none;
touch-action: none
}
.lum-lightbox-inner {
position: absolute;
top: 2.5%;
right: 2.5%;
bottom: 2.5%;
left: 2.5%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden
}
.lum-lightbox-inner img {
position: relative
}
.lum-lightbox-image-wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
max-width: 100%;
height: 100%;
max-height: 100%;
overflow: hidden
}
.lum-lightbox-position-helper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 100%;
max-height: 100%;
margin: auto
}
.lum-lightbox-image-wrapper .lum-img {
width: auto;
height: auto;
max-width: 100%;
max-height: calc(100vh - 7rem);
max-height: calc(100dvh - 7rem);
object-fit: contain
}
.lum-lightbox-inner .lum-lightbox-caption {
display: block;
flex: 0 0 auto;
width: min(700px, 100%);
margin: .75rem auto 0;
color: #fff;
max-width: 700px;
text-align: center;
line-height: 1.35
}
.lum-loading .lum-lightbox-loader {
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: 66px;
height: 20px;
animation: lum-loader-rotate 1.8s infinite linear
}
.lum-lightbox-loader:before,.lum-lightbox-loader:after {
content: "";
display: block;
width: 20px;
height: 20px;
position: absolute;
top: 50%;
margin-top: -10px;
border-radius: 20px;
background: rgba(148, 163, 184, .9)
}
.lum-lightbox-loader:before {
left: 0;
animation: lum-loader-before 1.8s infinite linear
}
.lum-lightbox-loader:after {
right: 0;
animation: lum-loader-after 1.8s infinite linear;
animation-delay: -.9s
}
.lum-lightbox.lum-opening {
animation: lum-fade .18s ease-out
}
.lum-lightbox.lum-opening .lum-lightbox-inner {
animation: lum-fadeZoom .18s ease-out
}
.lum-lightbox.lum-closing {
animation: lum-fade .3s ease-in;
animation-direction: reverse
}
.lum-lightbox.lum-closing .lum-lightbox-inner {
animation: lum-fadeZoom .3s ease-in;
animation-direction: reverse
}
.lum-img {
transition: opacity .12s ease-out
}
.lum-lightbox img.gfplus-lightbox-zoomable {
cursor: zoom-in;
touch-action: none;
transform-origin: center center;
transition: opacity .12s ease-out, transform .12s ease-out;
will-change: transform
}
.lum-lightbox img.gfplus-lightbox-zoomed {
cursor: grab
}
.lum-lightbox img.gfplus-lightbox-dragging {
cursor: grabbing;
transition: opacity .12s ease-out
}
.lum-loading .lum-img {
opacity: 0
}
.lum-gallery-button {
display: inline-flex;
align-items: center;
justify-content: center;
overflow: visible;
text-indent: -9999px;
font-size: 0;
line-height: 0;
white-space: nowrap;
background: rgba(15, 23, 42, .46) !important;
color: #fff !important;
border: 1px solid rgba(255, 255, 255, .18) !important;
border-radius: 999px;
margin: 0;
padding: 0;
outline: 0;
position: absolute;
z-index: 2;
top: 50%;
transform: translateY(-50%) !important;
height: 48px;
max-height: none;
width: 48px;
cursor: pointer;
box-shadow: 0 8px 20px rgba(0, 0, 0, .22) !important;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: background-color .16s ease, border-color .16s ease, box-shadow .16s ease, transform .16s ease
}
.lum-gallery-button:hover,
.lum-gallery-button:focus-visible {
background: rgba(15, 23, 42, .66) !important;
border-color: rgba(255, 255, 255, .32) !important;
box-shadow: 0 10px 24px rgba(0, 0, 0, .28) !important;
transform: translateY(-50%) !important;
outline: none
}
.lum-gallery-button:focus {
outline: none
}
.lum-gallery-button:active {
background: rgba(15, 23, 42, .74) !important;
transform: translateY(-50%) !important
}
.lum-close-button {
position: absolute;
z-index: 3;
right: 12px;
top: 12px;
width: 40px;
height: 40px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, .2);
background: rgba(15, 23, 42, .52);
box-shadow: 0 8px 20px rgba(0, 0, 0, .22);
opacity: 1;
cursor: pointer;
transition: background-color .16s ease, border-color .16s ease, box-shadow .16s ease
}
.lum-close-button:hover {
background: rgba(15, 23, 42, .72);
border-color: rgba(255, 255, 255, .34);
box-shadow: 0 10px 24px rgba(0, 0, 0, .28)
}
.lum-close-button,
.lum-close-button:hover,
.lum-close-button:focus-visible,
.lum-close-button:active {
transform: none !important
}
.lum-close-button:before,.lum-close-button:after {
position: absolute;
left: 50%;
top: 50%;
content: " ";
height: 20px;
width: 2px;
border-radius: 999px;
background-color: rgba(255, 255, 255, .95)
}
.lum-close-button:before {
transform: translate(-50%,-50%) rotate(45deg)
}
.lum-close-button:after {
transform: translate(-50%,-50%) rotate(-45deg)
}
.lum-previous-button {
left: clamp(10px,3vw,28px)
}
.lum-next-button {
right: clamp(10px,3vw,28px)
}
.lum-gallery-button:after {
content: "";
display: block;
position: absolute;
top: 50%;
left: 50%;
width: 13px;
height: 13px;
border: 0;
border-top: 2.5px solid currentColor;
box-shadow: none
}
.lum-previous-button:after {
transform: translate(-35%,-50%) rotate(-45deg);
border-left: 2.5px solid currentColor;
border-radius: 2px 0 0
}
.lum-next-button:after {
transform: translate(-65%,-50%) rotate(45deg);
border-right: 2.5px solid currentColor;
border-radius: 0 2px 0 0
}
@media (max-width: 460px) {
.lum-lightbox,
.lum-lightbox-inner {
overflow: hidden !important
}
.lum-lightbox-inner {
top: .75rem;
right: .75rem;
bottom: .75rem;
left: .75rem
}
.lum-gallery-button {
width: 40px;
height: 40px;
top: auto;
bottom: 4.25rem;
transform: none !important;
background: rgba(15, 23, 42, .58) !important;
box-shadow: 0 8px 18px rgba(0, 0, 0, .24) !important
}
.lum-gallery-button:hover,
.lum-gallery-button:focus-visible {
transform: none !important
}
.lum-gallery-button:active {
transform: none !important
}
.lum-previous-button {
left: 12px
}
.lum-next-button {
right: 12px
}
.lum-gallery-button:after {
width: 11px;
height: 11px;
border-top-width: 2.25px
}
.lum-previous-button:after {
border-left-width: 2.25px
}
.lum-next-button:after {
border-right-width: 2.25px
}
.lum-lightbox-image-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 100% !important;
max-width: 100% !important;
height: calc(100dvh - 1.5rem) !important;
max-height: calc(100dvh - 1.5rem) !important;
overflow: hidden !important
}
.lum-lightbox-caption {
width: 100%;
position: static;
bottom: auto;
margin-top: .55rem
}
.lum-lightbox-position-helper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-width: 100%;
max-height: 100%;
margin: auto
}
.lum-lightbox-inner img {
width: auto !important;
height: auto !important;
max-width: 100% !important;
max-height: calc(100dvh - 5.5rem) !important;
object-fit: contain
}
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article dd span relative-time {
display: inline-block;
line-height: 1.2;
vertical-align: middle;
position: relative;
top: 0.5px;
}
.script-list > li:not(.ad-entry):not(.gf-script-extra-info) > article dd {
align-items: center;
}
.code-container pre.prettyprint,
.code-container pre.prettyprint .pln,
.code-container pre.prettyprint .com,
.code-container pre.prettyprint .kwd,
.code-container pre.prettyprint .str,
.code-container pre.prettyprint .typ {
font-size: 0.85rem !important;
line-height: 1.4 !important;
font-family: "Fira Code", "Consolas", "Menlo", monospace !important;
}
/* Highlight.js theme */
pre.gf-hljs {
min-width: calc(100% - 6px);
background-color: var(--hljs-bg);
color: var(--hljs-text);
border: 1px solid var(--hljs-border);
border-radius: var(--border-radius-small);
padding: 0;
overflow: auto;
display: flex;
gap: 0;
}
pre.gf-hljs .hljs-line-numbers {
flex: 0 0 auto;
padding: 0 .75em .85em;
background-color: var(--hljs-bg);
color: var(--hljs-line-number);
font-family: var(--font-family-monospace);
font-size: var(--hljs-font-size);
line-height: var(--hljs-line-height);
text-align: right;
white-space: pre;
user-select: none;
border-right: 1px solid var(--hljs-border);
background-image: linear-gradient(
to bottom,
transparent 0,
transparent var(--hljs-line-height),
var(--hljs-bg-alt) var(--hljs-line-height),
var(--hljs-bg-alt) calc(var(--hljs-line-height) * 2)
);
background-repeat: repeat-y;
background-size: 100% calc(var(--hljs-line-height) * 2);
background-attachment: local;
}
pre.gf-hljs code.hljs {
display: block;
flex: 0 0 auto;
min-width: 100%;
width: max-content;
padding: 0 1em .85em;
background: transparent;
color: inherit;
font-family: var(--font-family-monospace);
font-size: var(--hljs-font-size);
line-height: var(--hljs-line-height);
white-space: pre;
background-image: linear-gradient(
to bottom,
transparent 0,
transparent var(--hljs-line-height),
var(--hljs-bg-alt) var(--hljs-line-height),
var(--hljs-bg-alt) calc(var(--hljs-line-height) * 2)
);
background-repeat: repeat-y;
background-size: 100% calc(var(--hljs-line-height) * 2);
background-attachment: local;
}
pre.gf-hljs.wrap code.hljs {
white-space: pre-wrap;
flex: 1 1 auto;
min-width: 0;
width: 100%;
overflow-wrap: anywhere;
word-break: break-word;
line-break: anywhere;
}
.hljs-comment,.hljs-quote {
color: var(--hljs-comment);
font-style: italic;
}
.hljs-keyword,.hljs-selector-tag,.hljs-subst {
color: var(--hljs-keyword);
}
.hljs-number,.hljs-literal,.hljs-symbol,.hljs-bullet {
color: var(--hljs-number);
}
.hljs-string,.hljs-doctag,.hljs-built_in,.hljs-builtin-name {
color: var(--hljs-string);
}
.hljs-title,.hljs-section,.hljs-name {
color: var(--hljs-title);
font-weight: 600;
}
.hljs-attr,.hljs-attribute {
color: var(--hljs-attr);
}
.hljs-tag {
color: var(--hljs-tag);
}
.hljs-meta,.hljs-link {
color: var(--hljs-meta);
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: 700;
}
.hljs-addition {
background-color: var(--hljs-add-bg);
color: var(--hljs-add-text);
}
.hljs-deletion {
background-color: var(--hljs-del-bg);
color: var(--hljs-del-text);
}
.gf-script-logo--fallback {
color: #4f46e5;
}
#user-script-sets {
margin-top: 0px;
}
/* User Navigation Icons and Panels */
.gf-user-nav-icons {
display: inline-flex;
align-items: center;
gap: 0.5em;
margin-left: 0.75em;
vertical-align: middle;
}
.gf-user-icon {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: var(--border-radius-small);
cursor: pointer;
background: transparent;
border: 1px solid transparent;
transition: background-color var(--transition-base), border-color var(--transition-base);
}
.gf-user-icon:hover,
.gf-user-icon.active {
background-color: rgba(59, 130, 246, 0.18);
border-color: rgba(59, 130, 246, 0.3);
}
.gf-user-icon svg {
width: 18px;
height: 18px;
stroke: var(--overall-text-color);
fill: none;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
transition: stroke var(--transition-base);
}
.gf-user-icon:hover svg {
stroke: var(--link-color);
}
.gf-user-icon--settings:hover svg {
fill: var(--link-color);
}
.gf-user-icon--settings svg {
fill: currentColor;
stroke: none;
}
/* User Panels */
.gf-user-panel {
position: absolute;
top: calc(100% + 8px);
right: 0;
min-width: 220px;
background: var(--content-background-color);
border: 1px solid var(--content-border-color);
border-radius: var(--border-radius-medium);
box-shadow: var(--shadow-soft);
padding: 0.5em 0;
z-index: 1000;
display: none;
opacity: 0;
transform: translateY(-8px);
transition: opacity var(--transition-base), transform var(--transition-base);
}
.gf-user-panel.active {
display: block;
opacity: 1;
transform: translateY(0);
}
.gf-user-panel a {
display: block;
padding: 0.75em 1.25em;
color: var(--overall-text-color);
text-decoration: none;
font-weight: 500;
font-size: 14px;
transition: background-color var(--transition-base), color var(--transition-base);
}
.gf-user-panel a:visited {
color: var(--overall-text-color);
}
.gf-user-panel a:hover {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.22), rgba(59, 130, 246, 0.1));
color: var(--link-color);
}
.gf-user-panel-separator {
height: 1px;
background-color: var(--content-separator-color);
margin: 0.5em 0;
}
`;
let loadingCleared = false;
let phoneLoadClearScheduled = false;
const clearNoTransition = () => {
if (loadingCleared) {
return;
}
loadingCleared = true;
root.removeAttribute(LOADING_ATTR);
root.removeAttribute(INTERNAL_LOADING_ATTR);
if (noTransitionStyle.parentNode) {
noTransitionStyle.parentNode.removeChild(noTransitionStyle);
}
};
const scheduleNoTransitionClear = (frames = 2) => {
if (loadingCleared) {
return;
}
let remainingFrames = Math.max(0, frames);
const step = () => {
if (loadingCleared) {
return;
}
if (remainingFrames === 0) {
clearNoTransition();
return;
}
remainingFrames -= 1;
requestAnimationFrame(step);
};
requestAnimationFrame(step);
};
const schedulePhoneLoadClear = () => {
if (phoneLoadClearScheduled || !root.hasAttribute(HANDHELD_ATTR)) {
return;
}
phoneLoadClearScheduled = true;
const unlock = () => {
scheduleNoTransitionClear(root.hasAttribute(INTERNAL_LOADING_ATTR) ? 3 : 1);
};
if (document.readyState === 'complete') {
unlock();
return;
}
window.addEventListener('load', unlock, { once: true });
};
const lightThemeStyle = document.createElement('style');
lightThemeStyle.id = THEME_STYLE_ID;
lightThemeStyle.textContent = LIGHT_CSS;
appendStyle(lightThemeStyle);
const darkThemeStyle = document.createElement('style');
darkThemeStyle.id = DARK_THEME_STYLE_ID;
darkThemeStyle.textContent = DARK_CSS;
appendStyle(darkThemeStyle);
const syncThemeStyles = (theme) => {
lightThemeStyle.media = theme === 'dark' ? 'not all' : 'all';
darkThemeStyle.media = theme === 'dark' ? 'all' : 'not all';
};
syncThemeStyles(currentTheme);
if (root.hasAttribute(HANDHELD_ATTR)) {
schedulePhoneLoadClear();
}
const themeSwitchHosts = [];
const syncThemeSwitchHosts = (theme) => {
themeSwitchHosts.forEach((host) => {
host.setAttribute('theme', theme);
});
};
const getThemeColor = (name) => {
const value = getComputedStyle(root).getPropertyValue(name).trim();
return value || '';
};
const INSTALL_STATS_CHART_CONTAINER_IDS = [
'install-stats-chart-container',
'weekly-install-stats-chart-container',
'update-check-stats-chart-container'
];
const applyInstallStatsChartTheme = () => {
const backgroundColor = getThemeColor('--content-background-color');
const borderColor = getThemeColor('--content-border-color');
const barColor = getThemeColor('--install-stats-bar-color') || getThemeColor('--chart-background-color');
const barHoverColor = getThemeColor('--install-stats-bar-hover-color') || getThemeColor('--chart-border-color');
const textColor = getThemeColor('--install-stats-text-color') || getThemeColor('--overall-text-color');
const gridColor = getThemeColor('--install-stats-grid-color') || getThemeColor('--content-border-color');
root.style.setProperty('--chart-background-color', barColor);
root.style.setProperty('--chart-border-color', barHoverColor);
root.style.setProperty('--install-stats-bar-color', barColor);
root.style.setProperty('--install-stats-bar-hover-color', barHoverColor);
root.style.setProperty('--install-stats-grid-color', gridColor);
root.style.setProperty('--install-stats-text-color', textColor);
INSTALL_STATS_CHART_CONTAINER_IDS.forEach((containerId) => {
const container = document.getElementById(containerId);
if (!container) {
return;
}
if (backgroundColor) {
container.style.backgroundColor = backgroundColor;
}
if (borderColor) {
container.style.border = `1px solid ${borderColor}`;
}
});
const ChartCtor = window.Chart;
if (ChartCtor?.defaults) {
ChartCtor.defaults.color = textColor;
ChartCtor.defaults.defaultFontColor = textColor;
ChartCtor.defaults.backgroundColor = barColor;
ChartCtor.defaults.borderColor = gridColor;
}
};
const extractInstallStatsChartInitializers = () => Array.from(document.querySelectorAll('#script-content script'))
.flatMap((script) => Array.from(String(script.textContent || '').matchAll(/initializeChart\(([\s\S]*?),\s*['"]([^'"]+)['"]\)/g)))
.map((match) => ({
dataSource: match[1],
containerId: match[2]
}))
.filter(({ containerId }) => INSTALL_STATS_CHART_CONTAINER_IDS.includes(containerId));
const destroyInstallStatsCanvasChart = (canvas) => {
const ChartCtor = window.Chart;
if (!ChartCtor || !canvas) {
return;
}
const chart = typeof ChartCtor.getChart === 'function'
? (ChartCtor.getChart(canvas) || ChartCtor.getChart(canvas.id))
: Object.values(ChartCtor.instances || {}).find((instance) => {
const instanceCanvas = instance?.canvas || instance?.chart?.canvas || instance?.ctx?.canvas;
return instanceCanvas === canvas;
});
if (chart && typeof chart.destroy === 'function') {
chart.destroy();
}
};
const rebuildInstallStatsCharts = () => {
if (typeof window.initializeChart !== 'function') {
return false;
}
const initializers = extractInstallStatsChartInitializers();
if (!initializers.length) {
applyInstallStatsChartTheme();
return false;
}
applyInstallStatsChartTheme();
INSTALL_STATS_CHART_CONTAINER_IDS.forEach((containerId) => {
const container = document.getElementById(containerId);
if (!container) {
return;
}
container.querySelectorAll('canvas').forEach((canvas) => {
destroyInstallStatsCanvasChart(canvas);
canvas.remove();
});
});
initializers.forEach(({ dataSource, containerId }) => {
try {
const data = Function(`return ${dataSource}`)();
window.initializeChart(data, containerId);
} catch (error) {
console.warn('GreasyFork Premium: stats chart rebuild failed.', error);
}
});
applyInstallStatsChartTheme();
return true;
};
let installStatsChartRebuildFrame = 0;
const initInstallStatsChartTheme = () => {
if (installStatsChartRebuildFrame) {
return;
}
installStatsChartRebuildFrame = requestAnimationFrame(() => {
installStatsChartRebuildFrame = 0;
window.setTimeout(rebuildInstallStatsCharts, 0);
});
};
const clearThemeMotion = () => {
if (themeMotionTimer) {
window.clearTimeout(themeMotionTimer);
themeMotionTimer = 0;
}
if (root) {
root.removeAttribute(THEME_MOTION_ATTR);
root.removeAttribute(THEME_FALLBACK_MOTION_ATTR);
}
};
const commitTheme = (theme) => {
currentTheme = theme;
applyRootTheme(theme);
localStorage.setItem(STORAGE_KEY, theme);
syncThemeStyles(theme);
syncThemeSwitchHosts(theme);
rebuildInstallStatsCharts();
};
const switchTheme = (theme) => {
if (!root || theme === currentTheme) {
return;
}
clearThemeMotion();
const finish = () => {
themeMotionTimer = window.setTimeout(clearThemeMotion, THEME_MOTION_DURATION);
};
if (typeof document.startViewTransition === 'function' && !root.hasAttribute(LOADING_ATTR)) {
root.setAttribute(THEME_MOTION_ATTR, 'true');
const transition = document.startViewTransition(() => {
commitTheme(theme);
});
Promise.resolve(transition.finished || transition.ready).finally(finish);
return;
}
root.setAttribute(THEME_FALLBACK_MOTION_ATTR, 'true');
requestAnimationFrame(() => {
commitTheme(theme);
finish();
});
};
const createThemeSwitchHost = (hostId, options = {}) => {
if (document.getElementById(hostId)) {
return null;
}
const host = document.createElement('div');
host.id = hostId;
host.style.display = 'inline-flex';
host.style.alignItems = 'center';
host.style.verticalAlign = 'middle';
host.style.marginLeft = options.marginLeft || '0';
host.style.marginRight = options.marginRight || '0';
host.style.marginTop = options.marginTop || '0';
host.style.justifyContent = options.justifyContent || 'flex-start';
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
:host {
all: initial;
display: inline-flex;
align-items: center;
vertical-align: middle;
}
button {
all: unset;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: flex-start;
width: 52px;
height: 26px;
border-radius: 20px;
background: #ccc;
position: relative;
transition: background 0.3s ease;
box-sizing: border-box;
}
.thumb {
position: absolute;
top: 2px;
left: 2px;
width: 22px;
height: 22px;
border-radius: 50%;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.3s ease, background 0.3s ease;
box-sizing: border-box;
}
svg {
width: 14px;
height: 14px;
stroke-width: 2;
fill: none;
}
.sun { stroke: #f9b208; }
.moon { stroke: #58a6ff; display: none; }
:host([theme="dark"]) button { background: #444; }
:host([theme="dark"]) .thumb { transform: translateX(24px); background: #111; }
:host([theme="dark"]) .sun { display: none; }
:host([theme="dark"]) .moon { display: block; }
</style>
<button type="button">
<div class="thumb">
<svg class="sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="5"/>
<line x1="12" y1="1" x2="12" y2="3"/>
<line x1="12" y1="21" x2="12" y2="23"/>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
<line x1="1" y1="12" x2="3" y2="12"/>
<line x1="21" y1="12" x2="23" y2="12"/>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
</svg>
<svg class="moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
</div>
</button>
`;
const button = shadow.querySelector('button');
const themeLabel = getUserNavI18n(getCurrentLocale()).themeToggle || 'Toggle theme';
button.setAttribute('title', themeLabel);
button.setAttribute('aria-label', themeLabel);
button.addEventListener('click', () => {
const newTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
switchTheme(newTheme);
});
themeSwitchHosts.push(host);
host.setAttribute('theme', currentTheme);
return host;
};
const initThemeSwitch = () => {
if (document.getElementById('gf-theme-switch')) {
return true;
}
const langForm = document.querySelector('form.language-selector');
if (!langForm || !langForm.parentNode) {
return false;
}
const host = createThemeSwitchHost('gf-theme-switch', {
marginLeft: '8px'
});
if (!host) {
return Boolean(document.getElementById('gf-theme-switch'));
}
langForm.parentNode.insertBefore(host, langForm.nextSibling);
return true;
};
const initMobileThemeSwitch = () => {
if (document.getElementById('gf-mobile-theme-switch')) {
return true;
}
const mobileNav = document.querySelector('#mobile-nav nav');
const languageItem = document.querySelector('#mobile-nav form.language-selector')?.closest('li');
if (!mobileNav || !languageItem) {
return false;
}
const host = createThemeSwitchHost('gf-mobile-theme-switch', {
marginTop: '0.85rem',
marginRight: '1.2rem'
});
if (!host) {
return Boolean(document.getElementById('gf-mobile-theme-switch'));
}
const switchItem = document.createElement('li');
switchItem.id = 'gf-mobile-theme-switch-item';
switchItem.appendChild(host);
mobileNav.insertBefore(switchItem, languageItem);
return true;
};
const initMobileNavLayout = () => {
const mobileNav = document.querySelector('#mobile-nav nav');
if (!mobileNav) {
return false;
}
if (document.getElementById('gf-mobile-primary-nav-item')) {
return true;
}
const scriptsItem = mobileNav.querySelector('li.scripts-index-link');
const forumItem = mobileNav.querySelector('li.forum-link');
const helpItem = mobileNav.querySelector('li.help-link');
if (!scriptsItem || !forumItem || !helpItem) {
return false;
}
const primaryItem = document.createElement('li');
primaryItem.id = 'gf-mobile-primary-nav-item';
const primaryNav = document.createElement('div');
primaryNav.id = 'gf-mobile-primary-nav';
[scriptsItem, forumItem, helpItem].forEach((item) => {
const link = item.querySelector('a');
if (link) {
primaryNav.appendChild(link);
}
item.remove();
});
const toggleButton = document.createElement('button');
toggleButton.id = 'gf-mobile-primary-nav-toggle';
toggleButton.type = 'button';
toggleButton.textContent = '+';
toggleButton.setAttribute('aria-expanded', 'false');
primaryNav.appendChild(toggleButton);
primaryItem.appendChild(primaryNav);
const secondaryItem = document.createElement('li');
secondaryItem.id = 'gf-mobile-secondary-nav-item';
const secondaryNav = document.createElement('div');
secondaryNav.id = 'gf-mobile-secondary-nav';
secondaryNav.className = 'collapsed';
const divider = document.createElement('div');
divider.className = 'gf-mobile-secondary-divider';
secondaryNav.appendChild(divider);
[
...mobileNav.querySelectorAll(':scope > li')
].filter((item) => {
if (item.id === 'gf-mobile-theme-switch-item') {
return false;
}
if (item.classList.contains('multi-link-nav')) {
return false;
}
return !item.querySelector('form.language-selector');
}).forEach((item) => {
secondaryNav.appendChild(item);
});
toggleButton.addEventListener('click', () => {
const willExpand = secondaryNav.classList.contains('collapsed');
secondaryNav.classList.toggle('collapsed', !willExpand);
toggleButton.textContent = willExpand ? '-' : '+';
toggleButton.setAttribute('aria-expanded', willExpand ? 'true' : 'false');
});
secondaryItem.appendChild(secondaryNav);
mobileNav.prepend(secondaryItem);
mobileNav.prepend(primaryItem);
return true;
};
const createSidebarScrollButton = (direction) => {
const isTop = direction === 'top';
const label = isTop ? 'Aller en haut de la page' : 'Aller en bas de la page';
const button = document.createElement('button');
button.className = 'gf-sidebar-scroll-button';
button.type = 'button';
button.title = label;
button.setAttribute('aria-label', label);
button.innerHTML = isTop
? '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m18 15-6-6-6 6"></path></svg>'
: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg>';
button.addEventListener('click', () => {
const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
const scrollingElement = document.scrollingElement || document.documentElement;
window.scrollTo({
top: isTop ? 0 : scrollingElement.scrollHeight,
behavior: reduceMotion ? 'auto' : 'smooth'
});
button.blur();
});
return button;
};
const initSidebarScrollControls = () => {
document.querySelectorAll('.sidebar').forEach((sidebar) => {
if (sidebar.querySelector(':scope > .gf-sidebar-scroll-controls')) {
return;
}
const controls = document.createElement('div');
controls.className = 'gf-sidebar-scroll-controls';
controls.appendChild(createSidebarScrollButton('top'));
controls.appendChild(createSidebarScrollButton('bottom'));
sidebar.appendChild(controls);
});
};
const syncActiveScriptSetFilter = () => {
const setGroup = document.getElementById('script-list-set');
const activeSetId = new URL(window.location.href).searchParams.get('set');
if (!setGroup || !activeSetId) {
return false;
}
const activeLink = Array.from(setGroup.querySelectorAll('a[href]')).find((link) => {
try {
return new URL(link.href, window.location.href).searchParams.get('set') === activeSetId;
} catch (error) {
return false;
}
});
const activeOption = activeLink?.closest('.list-option, li');
if (!activeOption) {
return false;
}
setGroup.querySelectorAll('.list-current').forEach((option) => {
if (option !== activeOption) {
option.classList.remove('list-current');
option.removeAttribute('aria-current');
option.querySelector('[aria-current]')?.removeAttribute('aria-current');
}
});
activeOption.classList.add('list-current');
activeOption.setAttribute('aria-current', 'page');
activeLink.setAttribute('aria-current', 'page');
return true;
};
const SIDEBAR_STICKY_GAP = 16;
const MOBILE_SIDEBAR_STUCK_CLASS = 'gfplus-mobile-sidebar-stuck';
let smartSidebarItems = [];
let smartSidebarFrame = 0;
let smartSidebarLastScrollY = window.scrollY;
let smartSidebarResizeObserver = null;
let smartSidebarInitialized = false;
let mobileSidebarFrame = 0;
let mobileSidebarInitialized = false;
let mobileSidebarResizeObserver = null;
const clampSidebarTop = (value, min, max) => Math.max(min, Math.min(max, value));
const updateSmartSidebarPositions = () => {
smartSidebarFrame = 0;
const scrollY = window.scrollY;
const scrollDelta = scrollY - smartSidebarLastScrollY;
const desktop = window.matchMedia('(min-width: 801px)').matches;
smartSidebarItems.forEach((item) => {
const { sidebar } = item;
if (!desktop) {
sidebar.style.removeProperty('--gfplus-sidebar-sticky-top');
item.top = SIDEBAR_STICKY_GAP;
return;
}
const sidebarHeight = sidebar.offsetHeight;
const maxTop = SIDEBAR_STICKY_GAP;
const minTop = Math.min(maxTop, window.innerHeight - sidebarHeight - SIDEBAR_STICKY_GAP);
if (sidebarHeight <= window.innerHeight - (SIDEBAR_STICKY_GAP * 2)) {
item.top = maxTop;
} else if (!Number.isFinite(item.top)) {
item.top = clampSidebarTop(sidebar.getBoundingClientRect().top, minTop, maxTop);
} else {
item.top = clampSidebarTop(item.top - scrollDelta, minTop, maxTop);
}
sidebar.style.setProperty('--gfplus-sidebar-sticky-top', `${item.top}px`);
});
smartSidebarLastScrollY = scrollY;
};
const scheduleSmartSidebarUpdate = () => {
if (smartSidebarFrame) {
return;
}
smartSidebarFrame = requestAnimationFrame(updateSmartSidebarPositions);
};
const initSmartSidebar = () => {
const sidebars = Array.from(document.querySelectorAll('.sidebar'));
if (!sidebars.length) {
return;
}
smartSidebarItems = sidebars.map((sidebar) => ({
sidebar,
top: Number.NaN
}));
smartSidebarLastScrollY = window.scrollY;
if (!smartSidebarInitialized) {
window.addEventListener('scroll', scheduleSmartSidebarUpdate, { passive: true });
window.addEventListener('resize', scheduleSmartSidebarUpdate, { passive: true });
smartSidebarInitialized = true;
}
if (typeof ResizeObserver === 'function') {
if (smartSidebarResizeObserver) {
smartSidebarResizeObserver.disconnect();
}
smartSidebarResizeObserver = new ResizeObserver(scheduleSmartSidebarUpdate);
sidebars.forEach((sidebar) => smartSidebarResizeObserver.observe(sidebar));
}
scheduleSmartSidebarUpdate();
};
const updateMobileSidebarStickiness = () => {
mobileSidebarFrame = 0;
const mobile = window.matchMedia('(max-width: 800px)').matches;
const anchor = document.querySelector('.sidebarred');
if (!mobile || !anchor) {
root.classList.remove(MOBILE_SIDEBAR_STUCK_CLASS);
return;
}
const anchorTop = anchor.getBoundingClientRect().top + window.scrollY;
root.classList.toggle(MOBILE_SIDEBAR_STUCK_CLASS, window.scrollY > 12 && window.scrollY + 12 >= anchorTop);
};
const scheduleMobileSidebarStickiness = () => {
if (mobileSidebarFrame) {
return;
}
mobileSidebarFrame = requestAnimationFrame(updateMobileSidebarStickiness);
};
const initMobileSidebarStickiness = () => {
if (!document.querySelector('.sidebarred .sidebar, .sidebarred .open-sidebar')) {
return;
}
if (!mobileSidebarInitialized) {
window.addEventListener('scroll', scheduleMobileSidebarStickiness, { passive: true });
window.addEventListener('resize', scheduleMobileSidebarStickiness, { passive: true });
mobileSidebarInitialized = true;
}
if (typeof ResizeObserver === 'function') {
if (mobileSidebarResizeObserver) {
mobileSidebarResizeObserver.disconnect();
}
mobileSidebarResizeObserver = new ResizeObserver(scheduleMobileSidebarStickiness);
document.querySelectorAll('.sidebarred, .sidebarred .sidebar').forEach((element) => {
mobileSidebarResizeObserver.observe(element);
});
}
scheduleMobileSidebarStickiness();
};
const readSidebarGroupStates = () => {
try {
const storedStates = JSON.parse(localStorage.getItem(SIDEBAR_GROUP_STATE_KEY) || '{}');
return storedStates && typeof storedStates === 'object' ? storedStates : {};
} catch (error) {
return {};
}
};
const saveSidebarGroupState = (groupKey, collapsed) => {
try {
const states = readSidebarGroupStates();
states[groupKey] = collapsed;
localStorage.setItem(SIDEBAR_GROUP_STATE_KEY, JSON.stringify(states));
} catch (error) {
// The controls still work when storage is unavailable.
}
};
const getSidebarGroupLabel = (group) => {
const textNode = Array.from(group.childNodes).find((node) => {
return node.nodeType === Node.TEXT_NODE && node.textContent.trim();
});
return textNode?.textContent.trim().replace(/\s*:\s*$/, '') || group.id || 'ce groupe';
};
const updateSidebarGroupToggle = (group, button, collapsed) => {
const label = getSidebarGroupLabel(group);
group.setAttribute('data-gfplus-collapsed', String(collapsed));
button.setAttribute('aria-expanded', String(!collapsed));
button.setAttribute('aria-label', collapsed ? `Déplier ${label}` : `Replier ${label}`);
button.title = collapsed ? `Déplier ${label}` : `Replier ${label}`;
button.innerHTML = collapsed
? '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg>'
: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m18 15-6-6-6 6"></path></svg>';
};
const initSidebarGroupToggles = () => {
const savedStates = readSidebarGroupStates();
document.querySelectorAll('.sidebar .list-option-group').forEach((group, index) => {
const list = group.querySelector(':scope > ul');
if (!list || group.querySelector(':scope > .gf-list-option-toggle-row')) {
return;
}
const groupKey = group.id || `sidebar-group-${index}`;
const row = document.createElement('div');
row.className = 'gf-list-option-toggle-row';
const button = document.createElement('button');
button.className = 'gf-list-option-toggle';
button.type = 'button';
if (!list.id) {
list.id = `${groupKey}-options`;
}
button.setAttribute('aria-controls', list.id);
const collapsed = savedStates[groupKey] === true;
updateSidebarGroupToggle(group, button, collapsed);
button.addEventListener('click', () => {
const willCollapse = group.getAttribute('data-gfplus-collapsed') !== 'true';
updateSidebarGroupToggle(group, button, willCollapse);
saveSidebarGroupState(groupKey, willCollapse);
button.blur();
scheduleSmartSidebarUpdate();
});
row.appendChild(button);
list.insertAdjacentElement('afterend', row);
});
};
const initCompactUserScriptSets = () => {
const scriptSets = document.querySelector('#user-script-sets');
if (!scriptSets) {
return;
}
const container = scriptSets.closest('.text-content');
if (container) {
container.classList.add('text-content-compact');
}
};
const MODERATOR_ACTIONS_PAGE_ATTR = 'data-gfplus-moderator-actions-page';
const initModeratorActionsLayout = () => {
if (window.location.pathname.includes('/moderator_actions')) {
root.setAttribute(MODERATOR_ACTIONS_PAGE_ATTR, 'true');
} else {
root.removeAttribute(MODERATOR_ACTIONS_PAGE_ATTR);
}
};
const SCRIPT_SET_EDITOR_ATTR = 'data-gfplus-set-editor';
const SCRIPT_SET_EDITOR_PAGE_ATTR = 'data-gfplus-set-editor-page';
const getScriptSetEditorI18n = (locale) => getUserNavI18n(locale);
const collectScriptSetEntries = (form, select) => {
const entries = new Map();
Array.from(select?.options || []).forEach((option) => {
const id = String(option.value || '').trim();
if (!id) {
return;
}
entries.set(id, {
id,
title: (option.textContent || '').trim() || `#${id}`
});
});
form.querySelectorAll('input[name="scripts-included[]"]').forEach((input) => {
const id = String(input.value || '').trim();
if (!id || entries.has(id)) {
return;
}
entries.set(id, {
id,
title: input.getAttribute('data-script-title') || `#${id}`
});
});
return Array.from(entries.values());
};
const syncScriptSetHiddenInputs = (form, entries, anchor) => {
form.querySelectorAll('input[name="scripts-included[]"]').forEach((input) => input.remove());
entries.forEach(({ id, title }) => {
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'scripts-included[]';
hiddenInput.value = id;
hiddenInput.setAttribute('data-script-title', title);
anchor.appendChild(hiddenInput);
});
};
const enhanceScriptSetEditor = (form) => {
if (!form || form.getAttribute(SCRIPT_SET_EDITOR_ATTR) === 'done') {
return;
}
const locale = getCurrentLocale();
const i18n = getScriptSetEditorI18n(locale);
const scriptsSection = form.querySelector('#script-set-scripts');
const selectionBox = scriptsSection?.querySelector('.selection-box');
const select = selectionBox?.querySelector('select[name="remove-scripts-included[]"], select[name*="remove-scripts-included"]');
const removeSelectedButton = selectionBox?.querySelector('button[name="remove-selected-scripts"]');
const addControl = scriptsSection?.querySelector('.form-control:not(.selection-box)');
const includeButton = scriptsSection?.querySelector('button[name="script-action"]');
const saveButton = form.querySelector('button[name="save"]');
if (!scriptsSection || !selectionBox || !select) {
return;
}
form.setAttribute(SCRIPT_SET_EDITOR_ATTR, 'done');
form.classList.add('gf-set-editor-enhanced');
root.setAttribute(SCRIPT_SET_EDITOR_PAGE_ATTR, 'true');
const listPanel = document.createElement('div');
listPanel.className = 'gf-set-script-list-panel';
const listHeader = document.createElement('div');
listHeader.className = 'gf-set-script-list-header';
const listTitle = document.createElement('div');
listTitle.className = 'gf-set-script-list-title';
listTitle.textContent = i18n.currentScripts;
const listCount = document.createElement('span');
listCount.className = 'gf-set-script-list-count';
const listBody = document.createElement('div');
listBody.className = 'gf-set-script-list';
const emptyState = document.createElement('div');
emptyState.className = 'gf-set-script-empty';
emptyState.textContent = i18n.emptyScripts;
listHeader.appendChild(listTitle);
listHeader.appendChild(listCount);
listPanel.appendChild(listHeader);
listPanel.appendChild(listBody);
listPanel.appendChild(emptyState);
selectionBox.prepend(listPanel);
if (removeSelectedButton) {
removeSelectedButton.hidden = true;
removeSelectedButton.disabled = true;
}
if (addControl && includeButton) {
const actions = document.createElement('div');
actions.className = 'gf-set-editor-actions';
includeButton.parentNode?.insertBefore(actions, includeButton);
actions.appendChild(includeButton);
}
if (saveButton && !saveButton.closest('.gf-set-editor-footer')) {
const footer = document.createElement('div');
footer.className = 'gf-set-editor-footer';
saveButton.textContent = i18n.save;
saveButton.parentNode?.insertBefore(footer, saveButton);
footer.appendChild(saveButton);
}
const renderEntries = () => {
const entries = collectScriptSetEntries(form, select);
listBody.innerHTML = '';
listCount.textContent = String(entries.length);
emptyState.hidden = entries.length > 0;
entries.forEach(({ id, title }) => {
const row = document.createElement('div');
row.className = 'gf-set-script-row';
row.setAttribute('data-script-id', id);
const name = document.createElement('div');
name.className = 'gf-set-script-name';
name.textContent = title;
const removeButton = document.createElement('button');
removeButton.type = 'button';
removeButton.className = 'gf-set-script-remove';
removeButton.setAttribute('aria-label', `${i18n.removeScript}: ${title}`);
removeButton.innerHTML = `
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M18 6 6 18"></path>
<path d="m6 6 12 12"></path>
</svg>
`;
removeButton.addEventListener('click', () => {
Array.from(select.options)
.filter((option) => String(option.value || '').trim() === id)
.forEach((option) => option.remove());
form.querySelectorAll('input[name="scripts-included[]"]').forEach((input) => {
if (String(input.value || '').trim() === id) {
input.remove();
}
});
syncScriptSetHiddenInputs(form, collectScriptSetEntries(form, select), scriptsSection);
renderEntries();
});
row.appendChild(name);
row.appendChild(removeButton);
listBody.appendChild(row);
});
syncScriptSetHiddenInputs(form, entries, scriptsSection);
};
renderEntries();
};
const initScriptSetEditor = () => {
document.querySelectorAll(FAVORITE_FORM_SELECTOR).forEach(enhanceScriptSetEditor);
};
const HIGHLIGHT_ATTR = 'data-gfplus-hljs';
const HLJS_SRC = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js';
const HLJS_SCRIPT_ATTR = 'data-gfplus-hljs-script';
let wrapLinesBound = false;
const getWrapLinesToggle = () => document.querySelector('#wrap-lines');
const syncWrapLines = () => {
const toggle = getWrapLinesToggle();
if (!toggle) {
return;
}
const shouldWrap = toggle.checked;
document.querySelectorAll('pre.gf-hljs').forEach((pre) => {
pre.classList.toggle('wrap', shouldWrap);
});
scheduleLineNumberSync();
};
const maybeInitWrapLinesToggle = () => {
if (wrapLinesBound) {
return;
}
const toggle = getWrapLinesToggle();
if (!toggle) {
return;
}
wrapLinesBound = true;
toggle.addEventListener('change', syncWrapLines);
};
const loadHighlightJs = () => {
if (window.hljs && typeof window.hljs.highlightElement === 'function') {
return Promise.resolve(true);
}
return new Promise((resolve) => {
const existing = document.querySelector(`script[${HLJS_SCRIPT_ATTR}]`);
if (existing) {
existing.addEventListener('load', () => resolve(true), { once: true });
existing.addEventListener('error', () => resolve(false), { once: true });
return;
}
const script = document.createElement('script');
script.src = HLJS_SRC;
script.async = true;
script.setAttribute(HLJS_SCRIPT_ATTR, 'true');
script.onload = () => resolve(true);
script.onerror = () => resolve(false);
(document.head || document.documentElement).appendChild(script);
});
};
const getHighlightLanguage = (element) => {
if (!element || !element.className) {
return null;
}
const classes = element.className.split(/\s+/);
const langClass = classes.find((cls) => cls.startsWith('language-') || cls.startsWith('lang-'));
if (!langClass) {
return null;
}
return langClass.replace(/^language-/, '').replace(/^lang-/, '');
};
const countCodeLines = (codeText) => {
const normalized = String(codeText || '').replace(/\r\n?/g, '\n');
if (!normalized) {
return 0;
}
return normalized.split('\n').length;
};
const getCodeTextFromPre = (pre) => {
const codeEl = pre.querySelector('code.hljs');
if (codeEl) {
return codeEl.textContent || '';
}
const sourceLines = pre.querySelectorAll('ol.linenums > li, li.L0, li.L1, li.L2, li.L3, li.L4, li.L5, li.L6, li.L7, li.L8, li.L9');
if (sourceLines.length) {
return Array.from(sourceLines, (line) => line.textContent || '').join('\n');
}
return pre.textContent || '';
};
const getRenderedCodeLineCount = (pre, fallbackCount) => {
const codeEl = pre.querySelector('code.hljs');
if (!codeEl || !pre.classList.contains('wrap')) {
return fallbackCount;
}
const style = window.getComputedStyle(codeEl);
const lineHeight = parseFloat(style.lineHeight);
if (!Number.isFinite(lineHeight) || lineHeight <= 0) {
return fallbackCount;
}
const paddingTop = parseFloat(style.paddingTop) || 0;
const paddingBottom = parseFloat(style.paddingBottom) || 0;
const renderedHeight = codeEl.scrollHeight - paddingTop - paddingBottom;
const renderedLineCount = Math.round(renderedHeight / lineHeight);
if (!Number.isFinite(renderedLineCount) || renderedLineCount <= 0) {
return fallbackCount;
}
return Math.max(fallbackCount, renderedLineCount);
};
const ensureLineNumbers = (pre, codeText) => {
const lineCount = getRenderedCodeLineCount(pre, countCodeLines(codeText));
if (!lineCount) {
return;
}
let numbersEl = Array.from(pre.children).find((child) => child.classList?.contains('hljs-line-numbers'));
if (!numbersEl) {
numbersEl = document.createElement('span');
numbersEl.className = 'hljs-line-numbers';
pre.insertBefore(numbersEl, pre.firstChild);
}
const nextLineCount = String(lineCount);
if (numbersEl.getAttribute('data-gfplus-line-count') === nextLineCount) {
return;
}
numbersEl.textContent = Array.from({ length: lineCount }, (_, index) => index + 1).join('\n');
numbersEl.setAttribute('data-gfplus-line-count', nextLineCount);
};
const syncLineNumbers = () => {
document.querySelectorAll('pre.gf-hljs').forEach((pre) => {
ensureLineNumbers(pre, getCodeTextFromPre(pre));
});
};
const scheduleLineNumberSync = () => {
requestAnimationFrame(() => {
syncLineNumbers();
requestAnimationFrame(syncLineNumbers);
});
};
window.addEventListener('resize', scheduleLineNumberSync, { passive: true });
const highlightCodeBlock = (pre) => {
const state = pre.getAttribute(HIGHLIGHT_ATTR);
const hasHljs = window.hljs && typeof window.hljs.highlightElement === 'function';
if (state === 'done') {
const codeEl = pre.querySelector('code.hljs');
if (codeEl) {
ensureLineNumbers(pre, getCodeTextFromPre(pre));
pre.classList.add('gf-hljs');
}
return;
}
let codeEl = pre.querySelector('code.hljs');
if (!codeEl) {
const codeText = getCodeTextFromPre(pre);
if (!codeText || !codeText.trim()) {
return;
}
codeEl = document.createElement('code');
const lang = getHighlightLanguage(pre) || getHighlightLanguage(pre.querySelector('code'));
codeEl.classList.add('hljs');
if (lang) {
codeEl.classList.add(`language-${lang}`);
}
codeEl.textContent = codeText;
pre.innerHTML = '';
pre.appendChild(codeEl);
pre.classList.add('gf-hljs');
pre.classList.remove('prettyprint', 'linenums');
ensureLineNumbers(pre, codeText);
} else {
const codeText = codeEl.textContent || '';
if (codeText) {
ensureLineNumbers(pre, codeText);
}
pre.classList.add('gf-hljs');
}
if (hasHljs) {
window.hljs.highlightElement(codeEl);
pre.setAttribute(HIGHLIGHT_ATTR, 'done');
} else {
pre.setAttribute(HIGHLIGHT_ATTR, 'pending');
}
};
const applyHighlightJs = () => {
document
.querySelectorAll('.code-container pre, #code-container pre, pre.prettyprint, pre.gf-hljs')
.forEach(highlightCodeBlock);
maybeInitWrapLinesToggle();
syncWrapLines();
};
const initHighlightJs = () => {
applyHighlightJs();
const root = document.querySelector('#script-content') || document.body;
const observer = new MutationObserver(applyHighlightJs);
observer.observe(root, { childList: true, subtree: true });
loadHighlightJs().then((loaded) => {
if (!loaded || !window.hljs || typeof window.hljs.highlightElement !== 'function') {
return;
}
applyHighlightJs();
});
};
// ============================================================================
// Script Logos
// ============================================================================
const SCRIPT_LOGO_ATTR = 'data-gfplus-logo';
const SCRIPT_TITLE_CONTENT_CLASS = 'gf-script-title-content';
const scriptIconCache = new Map();
let scriptLogoObserver = null;
const LOGO_SIZE_LIST = 26;
const LOGO_SIZE_TITLE = 34;
const normalizeIconUrl = (iconUrl, baseUrl) => {
if (!iconUrl) {
return null;
}
if (iconUrl.startsWith('data:')) {
return iconUrl;
}
if (iconUrl.startsWith('//')) {
return `https:${iconUrl}`;
}
try {
return new URL(iconUrl, baseUrl).href;
} catch (error) {
return iconUrl;
}
};
const extractMetaIcon = (scriptText, baseUrl) => {
const metaMatch = scriptText.match(/\/\/\s*==UserScript==[\s\S]*?\/\/\s*==\/UserScript==/);
if (!metaMatch) {
return null;
}
const lines = metaMatch[0].split(/\r?\n/);
let iconValue = null;
let icon64Value = null;
lines.forEach((line) => {
const cleaned = line.replace(/^\s*\/\/\s*/, '').trim();
if (!cleaned.startsWith('@')) {
return;
}
const [rawTag, ...rest] = cleaned.split(/\s+/);
const tag = rawTag.toLowerCase();
const value = rest.join(' ').trim();
if (!value) {
return;
}
if (tag === '@icon64' || tag === '@icon64url') {
icon64Value = value;
} else if (tag === '@icon' || tag === '@iconurl') {
if (!iconValue) {
iconValue = value;
}
}
});
return normalizeIconUrl(icon64Value || iconValue, baseUrl);
};
const fetchScriptIcon = (codeUrl) => {
if (!codeUrl) {
return Promise.resolve(null);
}
if (scriptIconCache.has(codeUrl)) {
return scriptIconCache.get(codeUrl);
}
const fetchPromise = (async () => {
let scriptText = '';
let iconUrl = null;
try {
const ranged = await fetch(codeUrl, { headers: { Range: 'bytes=0-8191' } });
if (ranged.ok) {
scriptText = await ranged.text();
iconUrl = extractMetaIcon(scriptText, codeUrl);
}
} catch (error) {
scriptText = '';
}
if (!iconUrl) {
try {
const response = await fetch(codeUrl);
if (response.ok) {
scriptText = await response.text();
iconUrl = extractMetaIcon(scriptText, codeUrl);
}
} catch (error) {
iconUrl = null;
}
}
return iconUrl;
})();
scriptIconCache.set(codeUrl, fetchPromise);
return fetchPromise;
};
const createScriptLogoElement = (iconUrl) => {
if (iconUrl) {
const img = document.createElement('img');
img.className = 'gf-script-logo';
img.alt = '';
img.loading = 'lazy';
img.decoding = 'async';
img.referrerPolicy = 'no-referrer';
img.width = LOGO_SIZE_LIST;
img.height = LOGO_SIZE_LIST;
img.src = iconUrl;
return img;
}
const fallback = document.createElement('span');
fallback.className = 'gf-script-logo gf-script-logo--fallback';
fallback.setAttribute('aria-hidden', 'true');
fallback.innerHTML = `
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M7 8L3 12L7 16"></path>
<path d="M17 8L21 12L17 16"></path>
<path d="M10 19L14 5"></path>
</svg>
`;
return fallback;
};
const ensureScriptListTitleContentLayout = (link, logoEl) => {
const title = link ? link.closest('.script-list h2') : null;
if (!title || !logoEl || logoEl.parentNode !== title) {
return;
}
let content = title.querySelector(`:scope > .${SCRIPT_TITLE_CONTENT_CLASS}`);
if (!content) {
content = document.createElement('span');
content.className = SCRIPT_TITLE_CONTENT_CLASS;
title.insertBefore(content, logoEl.nextSibling);
}
let insertAfterContent = content;
Array.from(content.childNodes).forEach((child) => {
if (
child.nodeType === Node.ELEMENT_NODE &&
child.matches('.name-description-separator, .script-description, .description')
) {
title.insertBefore(child, insertAfterContent.nextSibling);
insertAfterContent = child;
}
});
let shouldMoveTitleNodes = true;
Array.from(title.childNodes).forEach((child) => {
if (child === logoEl || child === content) {
return;
}
if (
child.nodeType === Node.ELEMENT_NODE &&
child.matches('.name-description-separator, .script-description, .description')
) {
shouldMoveTitleNodes = false;
return;
}
if (!shouldMoveTitleNodes) {
return;
}
content.appendChild(child);
});
if (content.previousSibling !== logoEl) {
title.insertBefore(content, logoEl.nextSibling);
}
};
const ensureLogoForLink = (link) => {
if (!link || link.getAttribute(SCRIPT_LOGO_ATTR)) {
return;
}
const listItem = link.closest('li[data-code-url]');
const codeUrl = listItem ? listItem.getAttribute('data-code-url') : null;
if (!codeUrl) {
return;
}
link.setAttribute(SCRIPT_LOGO_ATTR, 'pending');
fetchScriptIcon(codeUrl)
.then((iconUrl) => {
const parent = link.parentNode;
if (!parent) {
link.removeAttribute(SCRIPT_LOGO_ATTR);
return;
}
const existingLogo = parent.querySelector(':scope > .gf-script-logo');
if (existingLogo) {
ensureScriptListTitleContentLayout(link, existingLogo);
link.setAttribute(SCRIPT_LOGO_ATTR, 'done');
return;
}
const logoEl = createScriptLogoElement(iconUrl);
if (!logoEl) {
link.removeAttribute(SCRIPT_LOGO_ATTR);
return;
}
parent.insertBefore(logoEl, link);
ensureScriptListTitleContentLayout(link, logoEl);
link.setAttribute(SCRIPT_LOGO_ATTR, 'done');
})
.catch(() => {
link.removeAttribute(SCRIPT_LOGO_ATTR);
});
};
const ensureLogoForHeaderTitle = () => {
const headerTitle = document.querySelector('#script-info header h2, #script-info h2');
if (!headerTitle || headerTitle.getAttribute(SCRIPT_LOGO_ATTR)) {
return;
}
const installLink = document.querySelector('a.install-link[data-install-format="js"]');
const codeUrl = installLink ? installLink.href : null;
if (!codeUrl) {
return;
}
headerTitle.setAttribute(SCRIPT_LOGO_ATTR, 'pending');
fetchScriptIcon(codeUrl)
.then((iconUrl) => {
if (headerTitle.querySelector('.gf-script-logo')) {
headerTitle.setAttribute(SCRIPT_LOGO_ATTR, 'done');
return;
}
const logoEl = createScriptLogoElement(iconUrl);
if (!logoEl) {
headerTitle.removeAttribute(SCRIPT_LOGO_ATTR);
return;
}
logoEl.classList.add('gf-script-logo--title');
if (logoEl.tagName === 'IMG') {
logoEl.width = LOGO_SIZE_TITLE;
logoEl.height = LOGO_SIZE_TITLE;
}
headerTitle.insertBefore(logoEl, headerTitle.firstChild);
headerTitle.setAttribute(SCRIPT_LOGO_ATTR, 'done');
})
.catch(() => {
headerTitle.removeAttribute(SCRIPT_LOGO_ATTR);
});
};
const applyScriptLogos = () => {
document.querySelectorAll('a.script-link').forEach(ensureLogoForLink);
ensureLogoForHeaderTitle();
};
const initScriptLogos = () => {
applyScriptLogos();
if (scriptLogoObserver) {
return;
}
scriptLogoObserver = new MutationObserver(applyScriptLogos);
scriptLogoObserver.observe(document.body, { childList: true, subtree: true });
};
// ============================================================================
// Script Cards And Detail Actions
// ============================================================================
const SCRIPT_CARD_ACTIONS_ATTR = 'data-gfplus-actions';
const SCRIPT_DETAIL_ACTIONS_ATTR = 'data-gfplus-detail-actions';
const SCRIPT_DETAIL_ACTIONS_CONTAINER_ID = 'gfplus-script-detail-actions';
const SCRIPT_EXTRA_INFO_ATTR = 'data-gfplus-extra-info';
const SCRIPT_EXTRA_INFO_CACHE = new Map();
const SCRIPT_LIBRARY_NAME_PATTERN = /\b(?:library|librairie|biblioth[eè]que)\b/i;
const SCRIPT_LIBRARY_INFO_PATTERN = /(?:ne doit pas être installé directement|should not be installed directly|not intended to be installed directly|librairie destinée à être incluse|library intended to be included)/i;
// ============================================================================
// Favorites
// ============================================================================
const FAVORITES_IDS_STORAGE_KEY = 'gfplus-favorites-ids-v1';
const FAVORITE_SET_NAME_PATTERN = /\bfavor(?:it(?:e|es|o|os|a|as)?|is?)\b/i;
const FAVORITE_FORM_SELECTOR = 'form.change-script-set, form[id^="edit_script_set"], form[id^="new_script_set"]';
let scriptCardActionsObserver = null;
let currentPageLibraryDetailPromise = null;
let favoriteIdsCache = null;
let favoriteIdsPromise = null;
let favoriteSetMetaCache = null;
let favoriteSetMissingConfirmed = false;
let favoriteMutationQueue = Promise.resolve();
let favoriteSyncToken = 0;
const pendingFavoriteOverrides = new Map();
const favoriteBusyScriptIds = new Set();
const getCurrentLocale = () => (window.location.pathname.match(/^\/([a-z]{2}(?:-[A-Z]{2})?)(?:\/|$)/) || [null, 'en'])[1];
const buildFavoriteHtmlHeaders = () => ({
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
});
const extractUserProfilePathFromValue = (value) => {
const match = String(value || '').match(/\/[a-z]{2}(?:-[A-Z]{2})?\/users\/\d+(?:-[^/?#]+)?/);
return match ? match[0] : null;
};
const extractUserIdFromProfilePath = (profilePath) => String(profilePath || '').match(/\/users\/(\d+)/)?.[1] || '';
const isSameUserProfilePath = (leftProfilePath, rightProfilePath) => {
const leftId = extractUserIdFromProfilePath(leftProfilePath);
const rightId = extractUserIdFromProfilePath(rightProfilePath);
return Boolean(leftId && rightId && leftId === rightId);
};
const extractCurrentUserProfilePath = () => {
const selectors = [
'#nav-user-info .user-profile-link a[href*="/users/"]',
'#nav-user-info a[href*="/users/"][href*="/notification_settings"]',
'#nav-user-info a[href*="/users/"][href*="/notifications"]',
'#nav-user-info a[href*="/users/"][href*="/sets/"][href*="/edit"]',
'#nav-user-info a[href*="/users/"]:not([href*="/sign_in"]):not([href*="/sign_out"])',
'#mobile-nav .user-profile-link a[href*="/users/"]',
'#mobile-nav a[href*="/users/"][href*="/notification_settings"]',
'#mobile-nav a[href*="/users/"][href*="/notifications"]',
'#mobile-nav a[href*="/users/"][href*="/sets/"][href*="/edit"]',
'#mobile-nav a[href*="/users/"]:not([href*="/sign_in"]):not([href*="/sign_out"])',
'.gf-user-panel a[href*="/users/"][href*="/notification_settings"]',
'.gf-user-panel a[href*="/users/"][href*="/notifications"]'
];
for (const selector of selectors) {
const href = document.querySelector(selector)?.getAttribute('href') || '';
const profilePath = extractUserProfilePathFromValue(href);
if (profilePath) {
return profilePath;
}
}
return null;
};
const readStoredFavoriteIds = () => {
try {
const currentUserId = extractUserIdFromProfilePath(extractCurrentUserProfilePath());
if (!currentUserId) {
return new Set();
}
const parsed = JSON.parse(localStorage.getItem(`${FAVORITES_IDS_STORAGE_KEY}:${currentUserId}`) || '[]');
return new Set(Array.isArray(parsed) ? parsed.map((id) => String(id).trim()).filter(Boolean) : []);
} catch {
return new Set();
}
};
const writeStoredFavoriteIds = (favoriteIds) => {
try {
const currentUserId = extractUserIdFromProfilePath(extractCurrentUserProfilePath());
if (!currentUserId) {
return;
}
localStorage.setItem(`${FAVORITES_IDS_STORAGE_KEY}:${currentUserId}`, JSON.stringify(Array.from(favoriteIds instanceof Set ? favoriteIds : new Set())));
localStorage.removeItem(FAVORITES_IDS_STORAGE_KEY);
} catch {
}
};
const clearStoredFavoriteIds = () => {
favoriteIdsCache = new Set();
favoriteSetMetaCache = null;
try {
const currentUserId = extractUserIdFromProfilePath(extractCurrentUserProfilePath());
if (currentUserId) {
localStorage.removeItem(`${FAVORITES_IDS_STORAGE_KEY}:${currentUserId}`);
}
localStorage.removeItem(FAVORITES_IDS_STORAGE_KEY);
} catch {
}
};
const findFavoriteSetLinkInDocument = (doc, baseUrl = window.location.href) => {
const currentUserProfilePath = extractCurrentUserProfilePath();
if (!currentUserProfilePath) {
return null;
}
const sourceUrl = new URL(baseUrl, window.location.origin);
const sourceProfilePath = extractUserProfilePathFromValue(sourceUrl.pathname);
const isOwnProfileDocument = isSameUserProfilePath(sourceProfilePath, currentUserProfilePath);
const currentSetId = sourceUrl.searchParams.get('set');
const currentHeading = doc.querySelector('.sidebarred-main-content h1, .sidebarred-main-content h2, .sidebarred-main-content h3, .text-content h1, .text-content h2, .text-content h3')?.textContent || '';
if (currentSetId && isFavoriteSetName(currentHeading)) {
const ownEditLink = doc.querySelector(`a[href*="/sets/${currentSetId}/edit"]`)?.getAttribute('href') || '';
const editProfilePath = extractUserProfilePathFromValue(ownEditLink);
if (
favoriteSetMetaCache?.setId === currentSetId
|| isSameUserProfilePath(editProfilePath, currentUserProfilePath)
) {
return sourceUrl.toString();
}
}
const links = Array.from(doc.querySelectorAll([
'#script-list-set a[href*="set="]',
'#user-script-sets a[href*="set="]',
'.sidebarred-main-content a[href*="set="]',
'.text-content a[href*="set="]'
].join(', ')));
const favoriteLink = links.find((link) => {
if (!isFavoriteSetName(link.textContent || '')) {
return false;
}
const href = link.getAttribute('href') || '';
const linkUrl = new URL(href, sourceUrl);
const linkProfilePath = extractUserProfilePathFromValue(linkUrl.pathname);
return linkProfilePath
? isSameUserProfilePath(linkProfilePath, currentUserProfilePath)
: isOwnProfileDocument;
});
return favoriteLink?.href ? new URL(favoriteLink.href, baseUrl).toString() : null;
};
const resolveFavoriteSetUrl = async () => {
if (favoriteSetMetaCache?.viewUrl) {
favoriteSetMissingConfirmed = false;
return favoriteSetMetaCache.viewUrl;
}
const currentSetUrl = findFavoriteSetLinkInDocument(document);
if (currentSetUrl) {
favoriteSetMissingConfirmed = false;
return currentSetUrl;
}
const profilePath = extractCurrentUserProfilePath();
if (!profilePath) {
return null;
}
const response = await fetch(new URL(profilePath, window.location.origin).toString(), {
credentials: 'include',
cache: 'no-store'
});
if (!response.ok) {
return null;
}
const doc = new DOMParser().parseFromString(await response.text(), 'text/html');
const favoriteSetUrl = findFavoriteSetLinkInDocument(doc, response.url);
if (favoriteSetUrl) {
favoriteSetMissingConfirmed = false;
return favoriteSetUrl;
}
favoriteSetMissingConfirmed = true;
clearStoredFavoriteIds();
return null;
};
const getAllFavoritesIds = async ({ force = false } = {}) => {
if (!force && favoriteIdsCache instanceof Set) {
return new Set(favoriteIdsCache);
}
if (!force && favoriteIdsPromise) {
return favoriteIdsPromise.then((favoriteIds) => new Set(favoriteIds));
}
const storedFavoriteIds = readStoredFavoriteIds();
if (!force && storedFavoriteIds.size) {
favoriteIdsCache = new Set(storedFavoriteIds);
}
const loadPromise = (async () => {
const setUrl = await resolveFavoriteSetUrl();
if (!setUrl) {
if (favoriteSetMissingConfirmed) {
return new Set();
}
favoriteIdsCache = new Set(storedFavoriteIds);
return new Set(storedFavoriteIds);
}
const baseUrl = new URL(setUrl, window.location.origin);
baseUrl.searchParams.set('filter_locale', '0');
const allIds = new Set();
let page = 1;
let fetchedExistingSet = false;
while (true) {
baseUrl.searchParams.set('page', String(page));
const response = await fetch(baseUrl.href, {
credentials: 'include',
cache: 'no-store'
});
if (!response.ok) {
break;
}
if (response.url.includes('/users/sign_in')) {
throw new Error('Authentication required.');
}
fetchedExistingSet = true;
const html = await response.text();
const doc = new DOMParser().parseFromString(html, 'text/html');
const ids = Array.from(doc.querySelectorAll('li[data-script-id]'))
.map((element) => String(element.getAttribute('data-script-id') || '').trim())
.filter(Boolean);
if (!ids.length) {
break;
}
ids.forEach((id) => allIds.add(id));
page += 1;
}
if (allIds.size) {
favoriteSetMissingConfirmed = false;
favoriteIdsCache = new Set(allIds);
writeStoredFavoriteIds(allIds);
return allIds;
}
if (fetchedExistingSet) {
favoriteSetMissingConfirmed = false;
favoriteIdsCache = new Set();
writeStoredFavoriteIds([]);
return new Set();
}
if (force) {
throw new Error('Favorite set could not be loaded.');
}
if (favoriteSetMissingConfirmed) {
return new Set();
}
favoriteIdsCache = new Set(storedFavoriteIds);
return new Set(storedFavoriteIds);
})().finally(() => {
if (favoriteIdsPromise === loadPromise) {
favoriteIdsPromise = null;
}
});
favoriteIdsPromise = loadPromise;
return loadPromise.then((favoriteIds) => new Set(favoriteIds));
};
const getFavoriteSetMeta = async () => {
if (favoriteSetMetaCache?.editUrl) {
return favoriteSetMetaCache;
}
const viewUrl = await resolveFavoriteSetUrl();
if (!viewUrl) {
return null;
}
const view = new URL(viewUrl, window.location.origin);
const setId = view.searchParams.get('set');
if (!setId) {
return null;
}
const directEditLink = document.querySelector(`a[href*="/sets/${setId}/edit"]`)?.getAttribute('href') || '';
const profilePath = extractCurrentUserProfilePath();
const editUrl = directEditLink
? new URL(directEditLink, window.location.origin).toString()
: (profilePath ? new URL(`${profilePath}/sets/${setId}/edit`, window.location.origin).toString() : null);
if (!editUrl) {
return null;
}
favoriteSetMetaCache = {
setId: String(setId),
viewUrl: view.toString(),
editUrl
};
return favoriteSetMetaCache;
};
const fetchFavoriteDocument = async (url, options = {}) => {
const response = await fetch(url, {
credentials: 'include',
cache: 'no-store',
headers: {
...buildFavoriteHtmlHeaders(),
...(options.headers || {})
},
...options
});
if (!response.ok) {
throw new Error(`Favorite request failed (${response.status})`);
}
const html = await response.text();
return {
response,
doc: new DOMParser().parseFromString(html, 'text/html')
};
};
const formDataToUrlEncodedBody = (formData) => {
const params = new URLSearchParams();
for (const [key, value] of formData.entries()) {
params.append(key, typeof value === 'string' ? value : String(value));
}
return params.toString();
};
const setFirstMatchingFormValue = (formData, candidateNames, value) => {
const fieldName = candidateNames.find((name) => formData.has(name)) || candidateNames[0];
formData.set(fieldName, value);
return fieldName;
};
const extractFavoriteSetMetaFromDocument = (doc, fallbackUrl = '') => {
const form = doc.querySelector(FAVORITE_FORM_SELECTOR);
const actionUrl = form?.getAttribute('action')
? new URL(form.getAttribute('action'), fallbackUrl || window.location.href).toString()
: String(fallbackUrl || '');
const editLink = doc.querySelector('a[href*="/sets/"][href*="/edit"]')?.getAttribute('href') || '';
const candidateUrl = actionUrl || (editLink ? new URL(editLink, fallbackUrl || window.location.href).toString() : '');
const setId = candidateUrl.match(/\/sets\/(\d+)/)?.[1]
|| editLink.match(/\/sets\/(\d+)/)?.[1]
|| '';
if (!setId) {
return null;
}
const locale = getCurrentLocale();
const viewUrl = new URL(`/${locale}/scripts?set=${setId}`, window.location.origin).toString();
const editUrl = candidateUrl.includes('/edit')
? candidateUrl
: new URL(`${extractCurrentUserProfilePath() || `/${locale}/users`}/sets/${setId}/edit`, window.location.origin).toString();
return {
setId: String(setId),
viewUrl,
editUrl
};
};
const extractFavoriteIdsFromForm = (form) => {
const ids = new Set();
if (!form) {
return ids;
}
form.querySelectorAll([
'input[name="scripts-included[]"]',
'input[name*="scripts-included"]',
'input[name="remove-scripts-included[]"]',
'input[name*="remove-scripts-included"]',
'select[name="scripts-included[]"] option',
'select[name*="scripts-included"] option',
'select[name="remove-scripts-included[]"] option',
'select[name*="remove-scripts-included"] option'
].join(', ')).forEach((element) => {
const rawValue = ('value' in element ? element.value : element.getAttribute('value')) || '';
const id = String(rawValue).trim().match(/^(\d+)$/)?.[1] || '';
if (id) {
ids.add(id);
}
});
return ids;
};
const createFavoriteSaveFormData = (doc, form, favoriteIds) => {
const formData = new FormData(form);
const csrfToken = doc.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (csrfToken) {
formData.set('authenticity_token', csrfToken);
}
Array.from(formData.keys()).forEach((key) => {
if (
key === 'save'
|| key === 'add-script'
|| key === 'script-action'
|| key === 'remove-selected-scripts'
|| key.includes('scripts-included')
|| key.includes('remove-scripts-included')
) {
formData.delete(key);
}
});
Array.from(favoriteIds)
.map((id) => String(id).trim())
.filter(Boolean)
.sort((left, right) => Number(left) - Number(right))
.forEach((id) => {
formData.append('scripts-included[]', id);
});
if (formData.has('script_set[favorite]')) {
formData.set('script_set[favorite]', '1');
}
if (formData.has('favorite')) {
formData.set('favorite', '1');
}
formData.set('save', '1');
return formData;
};
const createFavoriteSet = async () => {
const profilePath = extractCurrentUserProfilePath();
if (!profilePath) {
throw new Error('Authentication required.');
}
const locale = getCurrentLocale();
const newSetUrl = new URL(`${profilePath}/sets/new?fav=1`, window.location.origin).toString();
const { response: newSetResponse, doc: newSetDoc } = await fetchFavoriteDocument(newSetUrl);
if (newSetResponse.url.includes('/users/sign_in')) {
throw new Error('Authentication required.');
}
const form = newSetDoc.querySelector(FAVORITE_FORM_SELECTOR);
if (!form) {
throw new Error('Favorite creation form not found.');
}
const formData = new FormData(form);
const csrfToken = newSetDoc.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (csrfToken) {
formData.set('authenticity_token', csrfToken);
}
setFirstMatchingFormValue(formData, ['script_set[name]', 'name'], getUserNavI18n(locale).favoriteSetName || 'Favorites');
setFirstMatchingFormValue(formData, ['script_set[favorite]', 'favorite'], '1');
formData.set('save', '1');
const actionUrl = form.getAttribute('action')
? new URL(form.getAttribute('action'), newSetResponse.url).toString()
: newSetResponse.url;
const { response: createResponse, doc: createDoc } = await fetchFavoriteDocument(actionUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: formDataToUrlEncodedBody(formData)
});
if (createResponse.url.includes('/users/sign_in')) {
throw new Error('Authentication required.');
}
const favoriteSetMeta = extractFavoriteSetMetaFromDocument(createDoc, createResponse.url);
if (!favoriteSetMeta?.editUrl) {
throw new Error('Favorite set creation failed.');
}
favoriteSetMissingConfirmed = false;
favoriteSetMetaCache = favoriteSetMeta;
return favoriteSetMeta;
};
const saveFavoritesToRemote = async (favoriteIds) => {
let favoriteSetMeta = await getFavoriteSetMeta();
if (!favoriteSetMeta?.editUrl) {
favoriteSetMeta = await createFavoriteSet();
}
const { response: editResponse, doc: editDoc } = await fetchFavoriteDocument(favoriteSetMeta.editUrl);
if (editResponse.url.includes('/users/sign_in')) {
throw new Error('Authentication required.');
}
const form = editDoc.querySelector(FAVORITE_FORM_SELECTOR);
if (!form) {
throw new Error('Favorite edit form not found.');
}
const actionUrl = form.getAttribute('action')
? new URL(form.getAttribute('action'), editResponse.url).toString()
: editResponse.url;
const formData = createFavoriteSaveFormData(editDoc, form, favoriteIds);
const { response: saveResponse, doc: saveDoc } = await fetchFavoriteDocument(actionUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: formDataToUrlEncodedBody(formData)
});
if (saveResponse.url.includes('/users/sign_in')) {
throw new Error('Authentication required.');
}
const savedMeta = extractFavoriteSetMetaFromDocument(saveDoc, saveResponse.url);
if (savedMeta?.editUrl) {
favoriteSetMissingConfirmed = false;
favoriteSetMetaCache = savedMeta;
}
const verificationUrl = favoriteSetMetaCache?.editUrl || favoriteSetMeta.editUrl;
const verification = await fetchFavoriteDocument(verificationUrl);
if (verification.response.url.includes('/users/sign_in')) {
throw new Error('Authentication required.');
}
const verifiedForm = verification.doc.querySelector(FAVORITE_FORM_SELECTOR);
if (!verifiedForm) {
throw new Error('Favorite save could not be verified.');
}
const verifiedMeta = extractFavoriteSetMetaFromDocument(verification.doc, verification.response.url);
if (verifiedMeta?.editUrl) {
favoriteSetMissingConfirmed = false;
favoriteSetMetaCache = verifiedMeta;
}
return extractFavoriteIdsFromForm(verifiedForm);
};
const enqueueFavoriteMutation = (task) => {
const queuedTask = favoriteMutationQueue.catch(() => undefined).then(task);
favoriteMutationQueue = queuedTask.catch(() => undefined);
return queuedTask;
};
const setFavoriteButtonsBusy = (scriptId, isBusy) => {
document.querySelectorAll(`.gf-script-star-button[data-script-id="${scriptId}"]`).forEach((starButton) => {
starButton.disabled = isBusy;
starButton.setAttribute('aria-busy', String(isBusy));
});
};
const setStarButtonState = (starButton, isActive, locale) => {
starButton.setAttribute('data-active', String(isActive));
starButton.setAttribute('aria-pressed', String(isActive));
starButton.classList.toggle('active', isActive);
const i18n = getUserNavI18n(locale);
starButton.setAttribute('aria-label', isActive ? i18n.removeFromFavorites : i18n.addToFavorites);
};
const setFavoriteStateForScript = (scriptId, isActive, locale) => {
document.querySelectorAll(`.gf-script-star-button[data-script-id="${scriptId}"]`).forEach((starButton) => {
setStarButtonState(starButton, isActive, locale);
});
};
const syncFavoriteStarsWithSet = async ({ force = false } = {}) => {
const syncToken = ++favoriteSyncToken;
const locale = getCurrentLocale();
const applyFavoriteIds = (favoriteIds) => {
const visibleScriptIds = new Set();
document.querySelectorAll('li[data-script-id]').forEach((scriptElement) => {
const scriptId = String(scriptElement.getAttribute('data-script-id') || '').trim();
if (scriptId) {
visibleScriptIds.add(scriptId);
}
});
document.querySelectorAll('.gf-script-star-button[data-script-id]').forEach((starButton) => {
const scriptId = String(starButton.getAttribute('data-script-id') || '').trim();
if (scriptId) {
visibleScriptIds.add(scriptId);
}
});
const currentPageScriptId = getCurrentPageScriptId();
if (Number.isFinite(currentPageScriptId)) {
visibleScriptIds.add(String(currentPageScriptId));
}
visibleScriptIds.forEach((scriptId) => {
setFavoriteStateForScript(scriptId, favoriteIds.has(scriptId), locale);
});
};
const storedFavoriteIds = readStoredFavoriteIds();
if (storedFavoriteIds.size) {
if (syncToken !== favoriteSyncToken) {
return;
}
applyFavoriteIds(storedFavoriteIds);
}
const favoriteIds = await getAllFavoritesIds({ force });
if (syncToken !== favoriteSyncToken) {
return;
}
pendingFavoriteOverrides.forEach((isActive, scriptId) => {
if (isActive) {
favoriteIds.add(scriptId);
} else {
favoriteIds.delete(scriptId);
}
});
applyFavoriteIds(favoriteIds);
};
const createScriptInstallButton = (codeUrl, locale) => {
const installLabel = getUserNavI18n(locale).install || 'Install';
const installButton = document.createElement('a');
installButton.className = 'gf-script-install-button';
installButton.href = codeUrl;
installButton.textContent = installLabel;
installButton.setAttribute('aria-label', installLabel);
const icon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
icon.setAttribute('viewBox', '0 0 24 24');
icon.setAttribute('aria-hidden', 'true');
icon.innerHTML = `
<path d="M12 3v11"></path>
<path d="m7 11 5 5 5-5"></path>
<path d="M5 20h14"></path>
`;
installButton.prepend(icon);
return installButton;
};
const isSafeScriptExtraUrl = (value, baseUrl, attrName) => {
const rawValue = String(value || '').trim();
if (!rawValue || rawValue.startsWith('#') || rawValue.startsWith('data:')) {
return attrName !== 'href' || !rawValue.startsWith('data:');
}
try {
const url = new URL(rawValue, baseUrl);
return /^(https?:|mailto:)$/.test(url.protocol);
} catch {
return false;
}
};
const sanitizeScriptExtraElement = (sourceElement, baseUrl) => {
if (!sourceElement) {
return '';
}
const clone = sourceElement.cloneNode(true);
clone.querySelectorAll('script,style,iframe,object,embed,form,input,button,textarea,select,link,meta').forEach((element) => {
element.remove();
});
clone.querySelectorAll('*').forEach((element) => {
Array.from(element.attributes).forEach((attribute) => {
const attrName = attribute.name.toLowerCase();
const attrValue = attribute.value || '';
if (attrName.startsWith('on') || attrName === 'id') {
element.removeAttribute(attribute.name);
return;
}
if (['href', 'src', 'poster'].includes(attrName)) {
if (!isSafeScriptExtraUrl(attrValue, baseUrl, attrName)) {
element.removeAttribute(attribute.name);
}
}
});
});
return clone.innerHTML.trim();
};
const fetchScriptExtraInfo = (scriptUrl) => {
if (SCRIPT_EXTRA_INFO_CACHE.has(scriptUrl)) {
return SCRIPT_EXTRA_INFO_CACHE.get(scriptUrl);
}
const extraInfoPromise = (async () => {
const response = await fetch(scriptUrl, {
credentials: 'include',
cache: 'force-cache',
headers: buildFavoriteHtmlHeaders()
});
if (!response.ok) {
throw new Error(`Script details request failed (${response.status})`);
}
const doc = new DOMParser().parseFromString(await response.text(), 'text/html');
const additionalInfo = doc.querySelector('#additional-info');
return {
className: additionalInfo?.className || 'user-content',
lang: additionalInfo?.getAttribute('lang') || '',
html: sanitizeScriptExtraElement(additionalInfo, response.url)
};
})().catch((error) => {
SCRIPT_EXTRA_INFO_CACHE.delete(scriptUrl);
throw error;
});
SCRIPT_EXTRA_INFO_CACHE.set(scriptUrl, extraInfoPromise);
return extraInfoPromise;
};
const renderScriptExtraInfoPanel = (panel, extraInfo, locale) => {
const i18n = getUserNavI18n(locale);
panel.textContent = '';
if (extraInfo.html) {
const content = document.createElement('div');
content.className = extraInfo.className || 'user-content';
if (extraInfo.lang) {
content.setAttribute('lang', extraInfo.lang);
}
content.innerHTML = extraInfo.html;
panel.appendChild(content);
} else {
const empty = document.createElement('div');
empty.className = 'gf-script-extra-status';
empty.textContent = i18n.noDetailedInfo;
panel.appendChild(empty);
}
};
const loadScriptExtraInfoPanel = async (panel) => {
const scriptUrl = panel.getAttribute('data-script-url') || '';
if (!scriptUrl || panel.getAttribute(SCRIPT_EXTRA_INFO_ATTR) === 'loaded' || panel.getAttribute(SCRIPT_EXTRA_INFO_ATTR) === 'loading') {
return;
}
const locale = getCurrentLocale();
const i18n = getUserNavI18n(locale);
panel.setAttribute(SCRIPT_EXTRA_INFO_ATTR, 'loading');
panel.textContent = '';
const status = document.createElement('div');
status.className = 'gf-script-extra-status';
status.textContent = i18n.loadingDetails;
panel.appendChild(status);
try {
const extraInfo = await fetchScriptExtraInfo(scriptUrl);
renderScriptExtraInfoPanel(panel, extraInfo, locale);
panel.setAttribute(SCRIPT_EXTRA_INFO_ATTR, 'loaded');
} catch (error) {
console.warn('GreasyFork Premium: script details failed.', error);
panel.setAttribute(SCRIPT_EXTRA_INFO_ATTR, 'error');
status.textContent = i18n.detailsLoadFailed;
}
};
const extractGreasyForkCodeUrl = (value) => {
const match = String(value || '').match(/https:\/\/update\.greasyfork\.org\/scripts\/\d+\/[^\s"'<>]+/);
return match ? match[0] : null;
};
const getCurrentPageScriptId = () => {
const pathnameMatch = window.location.pathname.match(/\/scripts\/(\d+)(?:-|$)/);
const pathnameScriptId = Number.parseInt(pathnameMatch?.[1] || '', 10);
if (Number.isFinite(pathnameScriptId)) {
return pathnameScriptId;
}
const installLink = document.querySelector('a.install-link[href*="/scripts/"], a[href*="/scripts/"][data-install-format]');
const linkMatch = installLink?.href.match(/\/scripts\/(\d+)(?:-|$)/);
const linkScriptId = Number.parseInt(linkMatch?.[1] || '', 10);
return Number.isFinite(linkScriptId) ? linkScriptId : null;
};
const getCurrentPageCodeUrl = () => {
const installLink = document.querySelector('a.install-link[href], a[href][data-install-format]');
if (installLink?.href) {
return installLink.href;
}
const currentPageScriptId = getCurrentPageScriptId();
const currentListItemCodeUrl = currentPageScriptId
? document.querySelector(`li[data-script-id="${currentPageScriptId}"][data-code-url]`)?.getAttribute('data-code-url')
: '';
if (currentListItemCodeUrl) {
return currentListItemCodeUrl;
}
const candidateValues = Array.from(document.querySelectorAll('#script-content code, #script-info code, #script-content a[href], #script-info a[href]'))
.flatMap((node) => [node.textContent || '', node.getAttribute?.('href') || '']);
for (const candidateValue of candidateValues) {
const codeUrl = extractGreasyForkCodeUrl(candidateValue);
if (codeUrl) {
return codeUrl;
}
}
return extractGreasyForkCodeUrl(document.querySelector('#script-content')?.textContent || '');
};
const isInstallableScriptCodeUrl = (codeUrl) => /\.user\.(?:js|css)(?:[?#]|$)/i.test(String(codeUrl || ''));
const isScriptLibraryListItem = (listItem) => {
const codeUrl = listItem?.getAttribute('data-code-url') || '';
const scriptType = String(listItem?.getAttribute('data-script-type') || '').trim().toLowerCase();
return scriptType === 'library' || (Boolean(codeUrl) && !isInstallableScriptCodeUrl(codeUrl));
};
const getCurrentPageScriptInfoUrl = () => {
const pathnameMatch = window.location.pathname.match(/^(\/[a-z]{2}(?:-[A-Z]{2})?\/scripts\/\d+(?:-[^/?#]+)?)/);
if (!pathnameMatch) {
return '';
}
return new URL(pathnameMatch[1], window.location.origin).toString();
};
const isCurrentScriptInfoOrCodePage = () => /^\/[a-z]{2}(?:-[A-Z]{2})?\/scripts\/\d+(?:-[^/?#\/]+)?(?:\/code)?\/?$/.test(window.location.pathname);
const isLibraryInfoDocument = (doc) => {
const nativeInstallLink = doc.querySelector('a.install-link[href][data-install-format]');
if (nativeInstallLink) {
return !isInstallableScriptCodeUrl(nativeInstallLink.href);
}
const scriptContentText = doc.querySelector('#script-content')?.textContent || '';
if (SCRIPT_LIBRARY_INFO_PATTERN.test(scriptContentText)) {
return true;
}
const codeUrl = extractGreasyForkCodeUrl(scriptContentText);
return Boolean(codeUrl) && !isInstallableScriptCodeUrl(codeUrl);
};
const getCurrentPageScriptTitleText = () => [
document.querySelector('meta[property="og:title"]')?.getAttribute('content') || '',
document.querySelector('#script-info header h2, #script-info > h2')?.textContent || '',
document.title || '',
decodeURIComponent(window.location.pathname)
].join(' ');
const isCurrentPageLibraryDetail = () => {
if (!window.location.pathname.includes('/scripts/')) {
return false;
}
if (document.documentElement.getAttribute('data-gfplus-library-detail') === 'true') {
return true;
}
if (isLibraryInfoDocument(document)) {
return true;
}
const nativeInstallLink = document.querySelector('a.install-link[href][data-install-format]');
if (nativeInstallLink) {
return !isInstallableScriptCodeUrl(nativeInstallLink.href);
}
const codeUrl = getCurrentPageCodeUrl();
if (codeUrl) {
return !isInstallableScriptCodeUrl(codeUrl);
}
return SCRIPT_LIBRARY_NAME_PATTERN.test(getCurrentPageScriptTitleText());
};
const removeDetailActionsIfConfirmedLibrary = async () => {
if (!window.location.pathname.includes('/scripts/')) {
return;
}
if (!currentPageLibraryDetailPromise) {
currentPageLibraryDetailPromise = (async () => {
const infoUrl = getCurrentPageScriptInfoUrl();
if (!infoUrl) {
return false;
}
const response = await fetch(infoUrl, {
credentials: 'include',
cache: 'force-cache',
headers: buildFavoriteHtmlHeaders()
});
if (!response.ok) {
return false;
}
const doc = new DOMParser().parseFromString(await response.text(), 'text/html');
return isLibraryInfoDocument(doc);
})().catch(() => false);
}
if (await currentPageLibraryDetailPromise) {
document.documentElement.setAttribute('data-gfplus-library-detail', 'true');
document.getElementById(SCRIPT_DETAIL_ACTIONS_CONTAINER_ID)?.remove();
}
};
const getScriptDetailActionsContainer = () => {
const installArea = document.getElementById('install-area');
if (installArea) {
return installArea;
}
const existingContainer = document.getElementById(SCRIPT_DETAIL_ACTIONS_CONTAINER_ID);
if (existingContainer) {
return existingContainer;
}
const container = document.createElement('div');
container.id = SCRIPT_DETAIL_ACTIONS_CONTAINER_ID;
container.className = 'gf-script-card-actions gf-script-detail-actions';
const tabs = document.getElementById('script-links');
if (tabs) {
tabs.insertAdjacentElement('afterend', container);
return container;
}
const header = document.querySelector('#script-info header');
if (header) {
header.insertAdjacentElement('afterend', container);
return container;
}
const content = document.getElementById('script-content');
if (content) {
content.insertAdjacentElement('afterbegin', container);
return container;
}
return null;
};
const createScriptStarButton = (locale, scriptId) => {
const starButton = document.createElement('button');
starButton.className = 'gf-script-star-button';
starButton.type = 'button';
starButton.setAttribute('data-script-id', String(scriptId));
setStarButtonState(starButton, false, locale);
starButton.innerHTML = `
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="m12 3.6 2.55 5.17 5.7.83-4.12 4.01.97 5.67L12 16.6l-5.1 2.68.97-5.67L3.75 9.6l5.7-.83L12 3.6Z"></path>
</svg>
`;
starButton.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
const currentProfilePath = extractCurrentUserProfilePath();
if (!currentProfilePath) {
const signInUrl = new URL(`/${locale}/users/sign_in`, window.location.origin);
signInUrl.searchParams.set('return_to', window.location.href);
window.location.assign(signInUrl.toString());
return;
}
const scriptIdString = String(scriptId);
if (favoriteBusyScriptIds.has(scriptIdString)) {
return;
}
favoriteBusyScriptIds.add(scriptIdString);
setFavoriteButtonsBusy(scriptIdString, true);
let previousFavoriteIds = null;
let desiredFavoriteState = null;
enqueueFavoriteMutation(async () => {
previousFavoriteIds = await getAllFavoritesIds({ force: true });
const isActive = previousFavoriteIds.has(scriptIdString);
desiredFavoriteState = !isActive;
const nextFavoriteIds = new Set(previousFavoriteIds);
if (isActive) {
nextFavoriteIds.delete(scriptIdString);
} else {
nextFavoriteIds.add(scriptIdString);
}
favoriteSyncToken += 1;
pendingFavoriteOverrides.set(scriptIdString, desiredFavoriteState);
setFavoriteStateForScript(scriptIdString, desiredFavoriteState, locale);
const savedFavoriteIds = await saveFavoritesToRemote(nextFavoriteIds);
if (savedFavoriteIds.has(scriptIdString) !== desiredFavoriteState) {
throw new Error('Favorite save verification mismatch.');
}
favoriteIdsCache = new Set(savedFavoriteIds);
writeStoredFavoriteIds(savedFavoriteIds);
pendingFavoriteOverrides.delete(scriptIdString);
void syncFavoriteStarsWithSet({ force: true }).catch((syncError) => {
console.warn('GreasyFork Premium: favorite sync after save failed.', syncError);
});
}).catch((error) => {
console.warn('GreasyFork Premium: favorite update failed; reverted local state.', error);
favoriteSyncToken += 1;
const restoredFavoriteIds = previousFavoriteIds instanceof Set
? new Set(previousFavoriteIds)
: (favoriteIdsCache instanceof Set ? new Set(favoriteIdsCache) : readStoredFavoriteIds());
favoriteIdsCache = new Set(restoredFavoriteIds);
writeStoredFavoriteIds(restoredFavoriteIds);
setFavoriteStateForScript(scriptIdString, restoredFavoriteIds.has(scriptIdString), locale);
}).finally(() => {
pendingFavoriteOverrides.delete(scriptIdString);
favoriteBusyScriptIds.delete(scriptIdString);
setFavoriteButtonsBusy(scriptIdString, false);
starButton.blur();
});
});
return starButton;
};
const createScriptExtraInfoPanel = (scriptUrl) => {
const panel = document.createElement('div');
panel.className = 'gf-script-extra-info';
panel.setAttribute(SCRIPT_EXTRA_INFO_ATTR, 'pending');
panel.setAttribute('data-script-url', scriptUrl);
panel.setAttribute('data-open', 'false');
return panel;
};
const createScriptDetailButton = (locale, panel) => {
const i18n = getUserNavI18n(locale);
const detailButton = document.createElement('button');
detailButton.className = 'gf-script-detail-button';
detailButton.type = 'button';
detailButton.setAttribute('aria-label', i18n.showDetails);
detailButton.setAttribute('aria-expanded', 'false');
detailButton.setAttribute('data-expanded', 'false');
detailButton.innerHTML = `
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 5v14"></path>
<path d="M5 12h14"></path>
</svg>
`;
detailButton.addEventListener('click', async (event) => {
event.preventDefault();
event.stopPropagation();
const shouldOpen = panel.getAttribute('data-open') !== 'true';
panel.setAttribute('data-open', String(shouldOpen));
detailButton.setAttribute('aria-expanded', String(shouldOpen));
detailButton.setAttribute('data-expanded', String(shouldOpen));
detailButton.setAttribute('aria-label', shouldOpen ? i18n.hideDetails : i18n.showDetails);
if (shouldOpen) {
await loadScriptExtraInfoPanel(panel);
}
detailButton.blur();
});
return detailButton;
};
const applyScriptCardActions = () => {
const locale = getCurrentLocale();
document.querySelectorAll('li[data-script-id]:not(.ad-entry)').forEach((listItem) => {
const isLibraryListItem = isScriptLibraryListItem(listItem);
if (listItem.getAttribute(SCRIPT_CARD_ACTIONS_ATTR) === 'done') {
if (isLibraryListItem) {
listItem.querySelectorAll('.gf-script-star-button').forEach((starButton) => {
starButton.remove();
});
}
return;
}
const article = listItem.querySelector('article');
const codeUrl = listItem.getAttribute('data-code-url');
const scriptLink = listItem.querySelector('a.script-link[href*="/scripts/"]');
const scriptUrl = scriptLink?.href ? new URL(scriptLink.href, window.location.href).toString() : '';
const scriptId = Number.parseInt(listItem.getAttribute('data-script-id') || '', 10);
if (!article || !Number.isFinite(scriptId)) {
return;
}
const actions = document.createElement('div');
actions.className = 'gf-script-card-actions';
let extraInfoPanel = null;
if (codeUrl) {
actions.appendChild(createScriptInstallButton(codeUrl, locale));
}
if (scriptUrl) {
extraInfoPanel = createScriptExtraInfoPanel(scriptUrl);
actions.appendChild(createScriptDetailButton(locale, extraInfoPanel));
}
if (!isLibraryListItem) {
actions.appendChild(createScriptStarButton(locale, scriptId));
}
article.appendChild(actions);
if (extraInfoPanel) {
article.appendChild(extraInfoPanel);
}
listItem.setAttribute(SCRIPT_CARD_ACTIONS_ATTR, 'done');
});
if (!isCurrentScriptInfoOrCodePage()) {
document.getElementById(SCRIPT_DETAIL_ACTIONS_CONTAINER_ID)?.remove();
void syncFavoriteStarsWithSet();
return;
}
if (isCurrentPageLibraryDetail()) {
document.getElementById(SCRIPT_DETAIL_ACTIONS_CONTAINER_ID)?.remove();
void syncFavoriteStarsWithSet();
return;
}
void removeDetailActionsIfConfirmedLibrary();
const detailActionsTarget = getScriptDetailActionsContainer();
if (detailActionsTarget && detailActionsTarget.getAttribute(SCRIPT_DETAIL_ACTIONS_ATTR) !== 'done') {
const scriptId = getCurrentPageScriptId();
const codeUrl = getCurrentPageCodeUrl();
const hasNativeInstallArea = Boolean(document.getElementById('install-area'));
if (Number.isFinite(scriptId) && !detailActionsTarget.querySelector(`.gf-script-star-button[data-script-id="${scriptId}"]`)) {
if (!hasNativeInstallArea && codeUrl) {
detailActionsTarget.appendChild(createScriptInstallButton(codeUrl, locale));
}
detailActionsTarget.appendChild(createScriptStarButton(locale, scriptId));
}
detailActionsTarget.setAttribute(SCRIPT_DETAIL_ACTIONS_ATTR, 'done');
}
void syncFavoriteStarsWithSet();
};
const initScriptCardActions = () => {
applyScriptCardActions();
void syncFavoriteStarsWithSet();
if (scriptCardActionsObserver) {
return;
}
scriptCardActionsObserver = new MutationObserver(applyScriptCardActions);
scriptCardActionsObserver.observe(document.body, { childList: true, subtree: true });
};
// i18n dictionary for user navigation
// ============================================================================
// User Navigation And Translations
// ============================================================================
const USER_NAV_I18N = {
'en': {
install: 'Install',
themeToggle: 'Toggle theme',
currentScripts: 'Included scripts',
emptyScripts: 'No scripts in this list yet.',
removeScript: 'Remove this script',
save: 'Save',
favoriteSetName: 'Favorites',
addToFavorites: 'Add to favorites',
removeFromFavorites: 'Remove from favorites',
showDetails: 'Show more',
hideDetails: 'Hide details',
loadingDetails: 'Loading detailed info...',
detailsLoadFailed: 'Unable to load detailed info.',
noDetailedInfo: 'No additional details available.',
submitScript: 'Post a script',
submitStyle: 'Post a style',
submitSet: 'New script set',
webhookInfo: 'Set up a webhook',
importScripts: 'Import scripts',
editProfile: 'Edit profile',
editSignIn: 'Edit sign-in methods',
viewNotifications: 'View notifications',
notificationSettings: 'Edit notification settings',
deleteAccount: 'Delete account'
},
'fr': {
install: 'Installer',
themeToggle: 'Changer de thème',
currentScripts: 'Scripts inclus',
emptyScripts: 'Aucun script dans cette liste pour le moment.',
removeScript: 'Retirer ce script',
save: 'Enregistrer',
favoriteSetName: 'Favoris',
addToFavorites: 'Ajouter aux favoris',
removeFromFavorites: 'Retirer des favoris',
showDetails: 'Voir plus',
hideDetails: 'Réduire',
loadingDetails: 'Chargement des détails...',
detailsLoadFailed: 'Impossible de charger les détails.',
noDetailedInfo: 'Aucun détail supplémentaire disponible.',
submitScript: 'Publier un script',
submitStyle: 'Publier un style',
submitSet: 'Nouveau jeu de scripts',
webhookInfo: 'Mettre en place un Webhook',
importScripts: 'Importer des scripts',
editProfile: 'Modifier le profil',
editSignIn: 'Modifier mes méthodes d\'identification',
viewNotifications: 'Afficher les notifications',
notificationSettings: 'Modifier les paramètres de notification',
deleteAccount: 'Supprimer mon compte'
},
'es': {
install: 'Instalar',
themeToggle: 'Cambiar tema',
currentScripts: 'Scripts incluidos',
emptyScripts: 'No hay scripts en esta lista todavía.',
removeScript: 'Quitar este script',
save: 'Guardar',
favoriteSetName: 'Favoritos',
addToFavorites: 'Añadir a favoritos',
removeFromFavorites: 'Quitar de favoritos',
showDetails: 'Ver más',
hideDetails: 'Reducir',
loadingDetails: 'Cargando detalles...',
detailsLoadFailed: 'No se pudieron cargar los detalles.',
noDetailedInfo: 'No hay detalles adicionales disponibles.',
submitScript: 'Publicar un script',
submitStyle: 'Publicar un estilo',
submitSet: 'Nuevo conjunto de scripts',
webhookInfo: 'Configurar un webhook',
importScripts: 'Importar scripts',
editProfile: 'Editar perfil',
editSignIn: 'Editar métodos de inicio de sesión',
viewNotifications: 'Ver notificaciones',
notificationSettings: 'Editar configuración de notificaciones',
deleteAccount: 'Eliminar cuenta'
},
'de': {
install: 'Installieren',
themeToggle: 'Design wechseln',
currentScripts: 'Enthaltene Skripte',
emptyScripts: 'Noch keine Skripte in dieser Liste.',
removeScript: 'Dieses Skript entfernen',
save: 'Speichern',
favoriteSetName: 'Favoriten',
addToFavorites: 'Zu Favoriten hinzufügen',
removeFromFavorites: 'Aus Favoriten entfernen',
showDetails: 'Mehr anzeigen',
hideDetails: 'Details ausblenden',
loadingDetails: 'Details werden geladen...',
detailsLoadFailed: 'Details konnten nicht geladen werden.',
noDetailedInfo: 'Keine zusätzlichen Details verfügbar.',
submitScript: 'Skript veröffentlichen',
submitStyle: 'Style veröffentlichen',
submitSet: 'Neues Skript-Set',
webhookInfo: 'Webhook einrichten',
importScripts: 'Skripte importieren',
editProfile: 'Profil bearbeiten',
editSignIn: 'Anmeldemethoden bearbeiten',
viewNotifications: 'Benachrichtigungen anzeigen',
notificationSettings: 'Benachrichtigungseinstellungen bearbeiten',
deleteAccount: 'Konto löschen'
},
'it': {
install: 'Installare',
themeToggle: 'Cambia tema',
currentScripts: 'Script inclusi',
emptyScripts: 'Nessuno script in questa lista per ora.',
removeScript: 'Rimuovi questo script',
save: 'Salva',
favoriteSetName: 'Preferiti',
addToFavorites: 'Aggiungi ai preferiti',
removeFromFavorites: 'Rimuovi dai preferiti',
showDetails: 'Mostra di più',
hideDetails: 'Riduci',
loadingDetails: 'Caricamento dettagli...',
detailsLoadFailed: 'Impossibile caricare i dettagli.',
noDetailedInfo: 'Nessun dettaglio aggiuntivo disponibile.',
submitScript: 'Pubblica uno script',
submitStyle: 'Pubblica uno stile',
submitSet: 'Nuovo set di script',
webhookInfo: 'Configurare un webhook',
importScripts: 'Importa script',
editProfile: 'Modifica profilo',
editSignIn: 'Modifica metodi di accesso',
viewNotifications: 'Visualizza notifiche',
notificationSettings: 'Modifica impostazioni notifiche',
deleteAccount: 'Elimina account'
},
'pt': {
install: 'Instalar',
themeToggle: 'Mudar tema',
currentScripts: 'Scripts incluídos',
emptyScripts: 'Ainda não há scripts nesta lista.',
removeScript: 'Remover este script',
save: 'Salvar',
favoriteSetName: 'Favoritos',
addToFavorites: 'Adicionar aos favoritos',
removeFromFavorites: 'Remover dos favoritos',
showDetails: 'Ver mais',
hideDetails: 'Reduzir',
loadingDetails: 'Carregando detalhes...',
detailsLoadFailed: 'Não foi possível carregar os detalhes.',
noDetailedInfo: 'Nenhum detalhe adicional disponível.',
submitScript: 'Publicar script',
submitStyle: 'Publicar estilo',
submitSet: 'Novo conjunto de scripts',
webhookInfo: 'Configurar webhook',
importScripts: 'Importar scripts',
editProfile: 'Editar perfil',
editSignIn: 'Editar métodos de login',
viewNotifications: 'Ver notificações',
notificationSettings: 'Editar configurações de notificação',
deleteAccount: 'Excluir conta'
},
'ru': {
install: 'Установить',
themeToggle: 'Переключить тему',
currentScripts: 'Включённые скрипты',
emptyScripts: 'В этом списке пока нет скриптов.',
removeScript: 'Удалить этот скрипт',
save: 'Сохранить',
favoriteSetName: 'Избранное',
addToFavorites: 'Добавить в избранное',
removeFromFavorites: 'Удалить из избранного',
showDetails: 'Показать больше',
hideDetails: 'Свернуть',
loadingDetails: 'Загрузка подробностей...',
detailsLoadFailed: 'Не удалось загрузить подробности.',
noDetailedInfo: 'Дополнительные сведения недоступны.',
submitScript: 'Опубликовать скрипт',
submitStyle: 'Опубликовать стиль',
submitSet: 'Набор скриптов',
webhookInfo: 'Настроить вебхук',
importScripts: 'Импортировать скрипты',
editProfile: 'Редактировать профиль',
editSignIn: 'Редактировать способы входа',
viewNotifications: 'Просмотр уведомлений',
notificationSettings: 'Настройки уведомлений',
deleteAccount: 'Удалить аккаунт'
},
'ja': {
install: 'インストール',
themeToggle: 'テーマを切り替え',
currentScripts: '含まれるスクリプト',
emptyScripts: 'このリストにはまだスクリプトがありません。',
removeScript: 'このスクリプトを削除',
save: '保存',
favoriteSetName: 'お気に入り',
addToFavorites: 'お気に入りに追加',
removeFromFavorites: 'お気に入りから削除',
showDetails: 'もっと見る',
hideDetails: '詳細を閉じる',
loadingDetails: '詳細を読み込み中...',
detailsLoadFailed: '詳細を読み込めませんでした。',
noDetailedInfo: '追加の詳細はありません。',
submitScript: 'スクリプトを投稿',
submitStyle: 'スタイルを投稿',
submitSet: '新しいスクリプトセット',
webhookInfo: 'Webhookを設定',
importScripts: 'スクリプトをインポート',
editProfile: 'プロフィールを編集',
editSignIn: 'ログイン方法を編集',
viewNotifications: '通知を表示',
notificationSettings: '通知設定を編集',
deleteAccount: 'アカウントを削除'
},
'zh-CN': {
install: '安装',
themeToggle: '切换主题',
currentScripts: '已包含的脚本',
emptyScripts: '此列表中还没有脚本。',
removeScript: '移除此脚本',
save: '保存',
favoriteSetName: '收藏',
addToFavorites: '添加到收藏',
removeFromFavorites: '从收藏中移除',
showDetails: '查看更多',
hideDetails: '收起详情',
loadingDetails: '正在加载详细信息...',
detailsLoadFailed: '无法加载详细信息。',
noDetailedInfo: '没有可用的附加详细信息。',
submitScript: '发布脚本',
submitStyle: '发布样式',
submitSet: '新的脚本集',
webhookInfo: '设置 Webhook',
importScripts: '导入脚本',
editProfile: '编辑个人资料',
editSignIn: '编辑登录方式',
viewNotifications: '查看通知',
notificationSettings: '编辑通知设置',
deleteAccount: '删除账户'
},
'zh-TW': {
install: '安裝',
themeToggle: '切換主題',
currentScripts: '已包含的腳本',
emptyScripts: '此清單中還沒有腳本。',
removeScript: '移除此腳本',
save: '儲存',
favoriteSetName: '收藏',
addToFavorites: '加入收藏',
removeFromFavorites: '從收藏移除',
showDetails: '查看更多',
hideDetails: '收合詳情',
loadingDetails: '正在載入詳細資訊...',
detailsLoadFailed: '無法載入詳細資訊。',
noDetailedInfo: '沒有可用的附加詳細資訊。',
submitScript: '發佈腳本',
submitStyle: '發佈樣式',
submitSet: '新的腳本集',
webhookInfo: '設定 Webhook',
importScripts: '匯入腳本',
editProfile: '編輯個人資料',
editSignIn: '編輯登入方式',
viewNotifications: '查看通知',
notificationSettings: '編輯通知設定',
deleteAccount: '刪除帳戶'
},
'ar': {
install: 'تثبيت',
themeToggle: 'تبديل المظهر',
currentScripts: 'السكربتات المضمنة',
emptyScripts: 'لا توجد سكربتات في هذه القائمة بعد.',
removeScript: 'إزالة هذا السكربت',
save: 'حفظ',
favoriteSetName: 'المفضلة',
addToFavorites: 'إضافة إلى المفضلة',
removeFromFavorites: 'إزالة من المفضلة',
showDetails: 'عرض المزيد',
hideDetails: 'طي التفاصيل',
loadingDetails: 'جارٍ تحميل التفاصيل...',
detailsLoadFailed: 'تعذر تحميل التفاصيل.',
noDetailedInfo: 'لا توجد تفاصيل إضافية متاحة.',
submitScript: 'نشر سكربت',
submitStyle: 'نشر نمط',
submitSet: 'مجموعة سكربتات جديدة',
webhookInfo: 'إعداد Webhook',
importScripts: 'استيراد سكربتات',
editProfile: 'تعديل الحساب',
editSignIn: 'تعديل طرق تسجيل الدخول',
viewNotifications: 'عرض الإشعارات',
notificationSettings: 'تعديل إعدادات الإشعارات',
deleteAccount: 'حذف الحساب'
},
'hi': {
install: 'इंस्टॉल करें',
themeToggle: 'थीम बदलें',
currentScripts: 'शामिल स्क्रिप्ट',
emptyScripts: 'इस सूची में अभी कोई स्क्रिप्ट नहीं है.',
removeScript: 'इस स्क्रिप्ट को हटाएँ',
save: 'सहेजें',
favoriteSetName: 'पसंदीदा',
addToFavorites: 'पसंदीदा में जोड़ें',
removeFromFavorites: 'पसंदीदा से हटाएँ',
showDetails: 'और देखें',
hideDetails: 'विवरण समेटें',
loadingDetails: 'विवरण लोड हो रहे हैं...',
detailsLoadFailed: 'विवरण लोड नहीं हो सके.',
noDetailedInfo: 'कोई अतिरिक्त विवरण उपलब्ध नहीं है.',
submitScript: 'स्क्रिप्ट प्रकाशित करें',
submitStyle: 'स्टाइल प्रकाशित करें',
submitSet: 'नया स्क्रिप्ट सेट',
webhookInfo: 'Webhook सेट करें',
importScripts: 'स्क्रिप्ट आयात करें',
editProfile: 'प्रोफ़ाइल संपादित करें',
editSignIn: 'लॉगिन विधियाँ संपादित करें',
viewNotifications: 'सूचनाएँ देखें',
notificationSettings: 'सूचना सेटिंग संपादित करें',
deleteAccount: 'खाता हटाएँ'
},
'bn': {
install: 'ইনস্টল করুন',
themeToggle: 'থিম বদলান',
currentScripts: 'অন্তর্ভুক্ত স্ক্রিপ্ট',
emptyScripts: 'এই তালিকায় এখনও কোনো স্ক্রিপ্ট নেই।',
removeScript: 'এই স্ক্রিপ্ট সরান',
save: 'সংরক্ষণ করুন',
favoriteSetName: 'প্রিয়',
addToFavorites: 'প্রিয়তে যোগ করুন',
removeFromFavorites: 'প্রিয় থেকে সরান',
showDetails: 'আরও দেখুন',
hideDetails: 'বিস্তারিত সংকুচিত করুন',
loadingDetails: 'বিস্তারিত লোড হচ্ছে...',
detailsLoadFailed: 'বিস্তারিত লোড করা যায়নি।',
noDetailedInfo: 'অতিরিক্ত কোনো বিস্তারিত নেই।',
submitScript: 'স্ক্রিপ্ট প্রকাশ করুন',
submitStyle: 'স্টাইল প্রকাশ করুন',
submitSet: 'নতুন স্ক্রিপ্ট সেট',
webhookInfo: 'Webhook সেট আপ করুন',
importScripts: 'স্ক্রিপ্ট আমদানি করুন',
editProfile: 'প্রোফাইল সম্পাদনা করুন',
editSignIn: 'সাইন-ইন পদ্ধতি সম্পাদনা করুন',
viewNotifications: 'বিজ্ঞপ্তি দেখুন',
notificationSettings: 'বিজ্ঞপ্তি সেটিংস সম্পাদনা করুন',
deleteAccount: 'অ্যাকাউন্ট মুছুন'
},
'ur': {
install: 'انسٹال کریں',
themeToggle: 'تھیم تبدیل کریں',
currentScripts: 'شامل اسکرپٹس',
emptyScripts: 'اس فہرست میں ابھی کوئی اسکرپٹ نہیں ہے۔',
removeScript: 'یہ اسکرپٹ ہٹائیں',
save: 'محفوظ کریں',
favoriteSetName: 'پسندیدہ',
addToFavorites: 'پسندیدہ میں شامل کریں',
removeFromFavorites: 'پسندیدہ سے ہٹائیں',
showDetails: 'مزید دیکھیں',
hideDetails: 'تفصیلات سمیٹیں',
loadingDetails: 'تفصیلات لوڈ ہو رہی ہیں...',
detailsLoadFailed: 'تفصیلات لوڈ نہیں ہو سکیں۔',
noDetailedInfo: 'اضافی تفصیلات دستیاب نہیں ہیں۔',
submitScript: 'اسکرپٹ شائع کریں',
submitStyle: 'اسٹائل شائع کریں',
submitSet: 'نیا اسکرپٹ سیٹ',
webhookInfo: 'Webhook سیٹ اپ کریں',
importScripts: 'اسکرپٹس درآمد کریں',
editProfile: 'پروفائل میں ترمیم کریں',
editSignIn: 'سائن اِن طریقے میں ترمیم کریں',
viewNotifications: 'اطلاعات دیکھیں',
notificationSettings: 'اطلاع کی ترتیبات میں ترمیم کریں',
deleteAccount: 'اکاؤنٹ حذف کریں'
},
'ml': {
install: 'ഇൻസ്റ്റാൾ ചെയ്യുക',
themeToggle: 'തീം മാറ്റുക',
currentScripts: 'ഉൾപ്പെടുത്തിയ സ്ക്രിപ്റ്റുകൾ',
emptyScripts: 'ഈ പട്ടികയിൽ ഇതുവരെ സ്ക്രിപ്റ്റുകളൊന്നുമില്ല.',
removeScript: 'ഈ സ്ക്രിപ്റ്റ് നീക്കം ചെയ്യുക',
save: 'സംരക്ഷിക്കുക',
favoriteSetName: 'പ്രിയപ്പെട്ടവ',
addToFavorites: 'പ്രിയപ്പെട്ടവയിൽ ചേർക്കുക',
removeFromFavorites: 'പ്രിയപ്പെട്ടവയിൽ നിന്ന് നീക്കം ചെയ്യുക',
showDetails: 'കൂടുതൽ കാണിക്കുക',
hideDetails: 'വിശദാംശങ്ങൾ ചുരുക്കുക',
loadingDetails: 'വിശദാംശങ്ങൾ ലോഡ് ചെയ്യുന്നു...',
detailsLoadFailed: 'വിശദാംശങ്ങൾ ലോഡ് ചെയ്യാനായില്ല.',
noDetailedInfo: 'കൂടുതൽ വിശദാംശങ്ങൾ ലഭ്യമല്ല.',
submitScript: 'സ്ക്രിപ്റ്റ് പ്രസിദ്ധീകരിക്കുക',
submitStyle: 'സ്റ്റൈൽ പ്രസിദ്ധീകരിക്കുക',
submitSet: 'പുതിയ സ്ക്രിപ്റ്റ് സെറ്റ്',
webhookInfo: 'Webhook സജ്ജമാക്കുക',
importScripts: 'സ്ക്രിപ്റ്റുകൾ ഇറക്കുമതി ചെയ്യുക',
editProfile: 'പ്രൊഫൈൽ തിരുത്തുക',
editSignIn: 'സൈൻ-ഇൻ രീതികൾ തിരുത്തുക',
viewNotifications: 'അറിയിപ്പുകൾ കാണുക',
notificationSettings: 'അറിയിപ്പ് ക്രമീകരണങ്ങൾ തിരുത്തുക',
deleteAccount: 'അക്കൗണ്ട് ഇല്ലാതാക്കുക'
},
'ko': {
install: '설치',
themeToggle: '테마 전환',
currentScripts: '포함된 스크립트',
emptyScripts: '이 목록에는 아직 스크립트가 없습니다.',
removeScript: '이 스크립트 제거',
save: '저장',
favoriteSetName: '즐겨찾기',
addToFavorites: '즐겨찾기에 추가',
removeFromFavorites: '즐겨찾기에서 제거',
showDetails: '더 보기',
hideDetails: '상세 정보 접기',
loadingDetails: '상세 정보를 불러오는 중...',
detailsLoadFailed: '상세 정보를 불러올 수 없습니다.',
noDetailedInfo: '추가 상세 정보가 없습니다.',
submitScript: '스크립트 게시',
submitStyle: '스타일 게시',
submitSet: '새 스크립트 세트',
webhookInfo: 'Webhook 설정',
importScripts: '스크립트 가져오기',
editProfile: '프로필 수정',
editSignIn: '로그인 방법 수정',
viewNotifications: '알림 보기',
notificationSettings: '알림 설정 수정',
deleteAccount: '계정 삭제'
},
'tr': {
install: 'Yükle',
themeToggle: 'Tema değiştir',
currentScripts: 'Dahil edilen scriptler',
emptyScripts: 'Bu listede henüz script yok.',
removeScript: 'Bu scripti kaldır',
save: 'Kaydet',
favoriteSetName: 'Favoriler',
addToFavorites: 'Favorilere ekle',
removeFromFavorites: 'Favorilerden kaldır',
showDetails: 'Daha fazla göster',
hideDetails: 'Ayrıntıları daralt',
loadingDetails: 'Ayrıntılar yükleniyor...',
detailsLoadFailed: 'Ayrıntılar yüklenemedi.',
noDetailedInfo: 'Ek ayrıntı yok.',
submitScript: 'Script yayınla',
submitStyle: 'Stil yayınla',
submitSet: 'Yeni script seti',
webhookInfo: 'Webhook ayarla',
importScripts: 'Script içe aktar',
editProfile: 'Profili düzenle',
editSignIn: 'Giriş yöntemlerini düzenle',
viewNotifications: 'Bildirimleri görüntüle',
notificationSettings: 'Bildirim ayarlarını düzenle',
deleteAccount: 'Hesabı sil'
},
'pl': {
install: 'Zainstaluj',
themeToggle: 'Przełącz motyw',
currentScripts: 'Dołączone skrypty',
emptyScripts: 'Na tej liście nie ma jeszcze skryptów.',
removeScript: 'Usuń ten skrypt',
save: 'Zapisz',
favoriteSetName: 'Ulubione',
addToFavorites: 'Dodaj do ulubionych',
removeFromFavorites: 'Usuń z ulubionych',
showDetails: 'Pokaż więcej',
hideDetails: 'Zwiń szczegóły',
loadingDetails: 'Ładowanie szczegółów...',
detailsLoadFailed: 'Nie udało się załadować szczegółów.',
noDetailedInfo: 'Brak dodatkowych szczegółów.',
submitScript: 'Opublikuj skrypt',
submitStyle: 'Opublikuj styl',
submitSet: 'Nowy zestaw skryptów',
webhookInfo: 'Skonfiguruj webhook',
importScripts: 'Importuj skrypty',
editProfile: 'Edytuj profil',
editSignIn: 'Edytuj metody logowania',
viewNotifications: 'Zobacz powiadomienia',
notificationSettings: 'Edytuj ustawienia powiadomień',
deleteAccount: 'Usuń konto'
},
'nl': {
install: 'Installeren',
themeToggle: 'Thema wisselen',
currentScripts: 'Opgenomen scripts',
emptyScripts: 'Er staan nog geen scripts in deze lijst.',
removeScript: 'Dit script verwijderen',
save: 'Opslaan',
favoriteSetName: 'Favorieten',
addToFavorites: 'Aan favorieten toevoegen',
removeFromFavorites: 'Uit favorieten verwijderen',
showDetails: 'Meer weergeven',
hideDetails: 'Details inklappen',
loadingDetails: 'Details laden...',
detailsLoadFailed: 'Details konden niet worden geladen.',
noDetailedInfo: 'Geen extra details beschikbaar.',
submitScript: 'Script publiceren',
submitStyle: 'Stijl publiceren',
submitSet: 'Nieuwe scriptset',
webhookInfo: 'Webhook instellen',
importScripts: 'Scripts importeren',
editProfile: 'Profiel bewerken',
editSignIn: 'Aanmeldmethoden bewerken',
viewNotifications: 'Meldingen bekijken',
notificationSettings: 'Meldingsinstellingen bewerken',
deleteAccount: 'Account verwijderen'
},
'sv': {
install: 'Installera',
themeToggle: 'Växla tema',
currentScripts: 'Inkluderade skript',
emptyScripts: 'Det finns inga skript i den här listan ännu.',
removeScript: 'Ta bort det här skriptet',
save: 'Spara',
favoriteSetName: 'Favoriter',
addToFavorites: 'Lägg till i favoriter',
removeFromFavorites: 'Ta bort från favoriter',
showDetails: 'Visa mer',
hideDetails: 'Dölj detaljer',
loadingDetails: 'Läser in detaljer...',
detailsLoadFailed: 'Det gick inte att läsa in detaljer.',
noDetailedInfo: 'Inga ytterligare detaljer tillgängliga.',
submitScript: 'Publicera skript',
submitStyle: 'Publicera stil',
submitSet: 'Ny skriptsamling',
webhookInfo: 'Konfigurera webhook',
importScripts: 'Importera skript',
editProfile: 'Redigera profil',
editSignIn: 'Redigera inloggningsmetoder',
viewNotifications: 'Visa notiser',
notificationSettings: 'Redigera notisinställningar',
deleteAccount: 'Ta bort konto'
},
'ro': {
install: 'Instalează',
themeToggle: 'Comută tema',
currentScripts: 'Scripturi incluse',
emptyScripts: 'Nu există încă scripturi în această listă.',
removeScript: 'Elimină acest script',
save: 'Salvează',
favoriteSetName: 'Favorite',
addToFavorites: 'Adaugă la favorite',
removeFromFavorites: 'Elimină din favorite',
showDetails: 'Vezi mai mult',
hideDetails: 'Restrânge detaliile',
loadingDetails: 'Se încarcă detaliile...',
detailsLoadFailed: 'Detaliile nu au putut fi încărcate.',
noDetailedInfo: 'Nu există detalii suplimentare disponibile.',
submitScript: 'Publică script',
submitStyle: 'Publică stil',
submitSet: 'Set nou de scripturi',
webhookInfo: 'Configurează webhook',
importScripts: 'Importă scripturi',
editProfile: 'Editează profil',
editSignIn: 'Editează metodele de autentificare',
viewNotifications: 'Vezi notificări',
notificationSettings: 'Editează setările notificărilor',
deleteAccount: 'Șterge contul'
},
'vi': {
install: 'Cài đặt',
themeToggle: 'Chuyển giao diện',
currentScripts: 'Script đã thêm',
emptyScripts: 'Chưa có script nào trong danh sách này.',
removeScript: 'Xóa script này',
save: 'Lưu',
favoriteSetName: 'Yêu thích',
addToFavorites: 'Thêm vào yêu thích',
removeFromFavorites: 'Xóa khỏi yêu thích',
showDetails: 'Xem thêm',
hideDetails: 'Thu gọn chi tiết',
loadingDetails: 'Đang tải chi tiết...',
detailsLoadFailed: 'Không thể tải chi tiết.',
noDetailedInfo: 'Không có chi tiết bổ sung.',
submitScript: 'Đăng script',
submitStyle: 'Đăng kiểu',
submitSet: 'Bộ script mới',
webhookInfo: 'Thiết lập webhook',
importScripts: 'Nhập script',
editProfile: 'Chỉnh sửa hồ sơ',
editSignIn: 'Chỉnh sửa phương thức đăng nhập',
viewNotifications: 'Xem thông báo',
notificationSettings: 'Chỉnh sửa cài đặt thông báo',
deleteAccount: 'Xóa tài khoản'
},
'id': {
install: 'Pasang',
themeToggle: 'Ganti tema',
currentScripts: 'Skrip yang disertakan',
emptyScripts: 'Belum ada skrip dalam daftar ini.',
removeScript: 'Hapus skrip ini',
save: 'Simpan',
favoriteSetName: 'Favorit',
addToFavorites: 'Tambahkan ke favorit',
removeFromFavorites: 'Hapus dari favorit',
showDetails: 'Lihat selengkapnya',
hideDetails: 'Sembunyikan detail',
loadingDetails: 'Memuat detail...',
detailsLoadFailed: 'Tidak dapat memuat detail.',
noDetailedInfo: 'Tidak ada detail tambahan.',
submitScript: 'Publikasikan skrip',
submitStyle: 'Publikasikan gaya',
submitSet: 'Set skrip baru',
webhookInfo: 'Atur webhook',
importScripts: 'Impor skrip',
editProfile: 'Edit profil',
editSignIn: 'Edit metode masuk',
viewNotifications: 'Lihat notifikasi',
notificationSettings: 'Edit pengaturan notifikasi',
deleteAccount: 'Hapus akun'
},
'ms': {
install: 'Pasang',
themeToggle: 'Tukar tema',
currentScripts: 'Skrip disertakan',
emptyScripts: 'Tiada skrip dalam senarai ini lagi.',
removeScript: 'Alih keluar skrip ini',
save: 'Simpan',
favoriteSetName: 'Kegemaran',
addToFavorites: 'Tambah ke kegemaran',
removeFromFavorites: 'Alih keluar daripada kegemaran',
showDetails: 'Lihat lagi',
hideDetails: 'Sembunyikan butiran',
loadingDetails: 'Memuatkan butiran...',
detailsLoadFailed: 'Tidak dapat memuatkan butiran.',
noDetailedInfo: 'Tiada butiran tambahan tersedia.',
submitScript: 'Terbitkan skrip',
submitStyle: 'Terbitkan gaya',
submitSet: 'Set skrip baharu',
webhookInfo: 'Sediakan webhook',
importScripts: 'Import skrip',
editProfile: 'Edit profil',
editSignIn: 'Edit kaedah log masuk',
viewNotifications: 'Lihat notifikasi',
notificationSettings: 'Edit tetapan notifikasi',
deleteAccount: 'Padam akaun'
},
'th': {
install: 'ติดตั้ง',
themeToggle: 'สลับธีม',
currentScripts: 'สคริปต์ที่รวมอยู่',
emptyScripts: 'ยังไม่มีสคริปต์ในรายการนี้',
removeScript: 'ลบสคริปต์นี้',
save: 'บันทึก',
favoriteSetName: 'รายการโปรด',
addToFavorites: 'เพิ่มในรายการโปรด',
removeFromFavorites: 'ลบออกจากรายการโปรด',
showDetails: 'ดูเพิ่มเติม',
hideDetails: 'ย่อรายละเอียด',
loadingDetails: 'กำลังโหลดรายละเอียด...',
detailsLoadFailed: 'ไม่สามารถโหลดรายละเอียดได้',
noDetailedInfo: 'ไม่มีรายละเอียดเพิ่มเติม',
submitScript: 'เผยแพร่สคริปต์',
submitStyle: 'เผยแพร่สไตล์',
submitSet: 'ชุดสคริปต์ใหม่',
webhookInfo: 'ตั้งค่า Webhook',
importScripts: 'นำเข้าสคริปต์',
editProfile: 'แก้ไขโปรไฟล์',
editSignIn: 'แก้ไขวิธีเข้าสู่ระบบ',
viewNotifications: 'ดูการแจ้งเตือน',
notificationSettings: 'แก้ไขการตั้งค่าการแจ้งเตือน',
deleteAccount: 'ลบบัญชี'
}
};
const getUserNavI18n = (locale) => {
const exactLocale = USER_NAV_I18N[locale] || {};
const primaryLocale = USER_NAV_I18N[String(locale || '').split('-')[0]] || {};
return {
...USER_NAV_I18N.en,
...primaryLocale,
...exactLocale
};
};
const normalizeFavoriteSetName = (value) => String(value || '').trim().toLocaleLowerCase();
const isFavoriteSetName = (value) => {
const normalizedValue = normalizeFavoriteSetName(value);
if (!normalizedValue) {
return false;
}
return FAVORITE_SET_NAME_PATTERN.test(normalizedValue)
|| Object.values(USER_NAV_I18N).some((i18n) => {
const favoriteSetName = normalizeFavoriteSetName(i18n.favoriteSetName);
return favoriteSetName && (normalizedValue === favoriteSetName || normalizedValue.includes(favoriteSetName));
});
};
const initUserNavigation = () => {
const navUserInfo = document.getElementById('nav-user-info');
if (!navUserInfo) {
return false;
}
if (navUserInfo.querySelector('.gf-user-nav-icons')) {
return true;
}
// Extract user ID and locale from the profile link
const profileLink = navUserInfo.querySelector('.user-profile-link a');
if (!profileLink) {
return false;
}
const profileHref = profileLink.getAttribute('href');
const match = profileHref.match(/\/([a-z]{2}(?:-[A-Z]{2})?)\/users\/(\d+)-/);
if (!match) {
return false;
}
const locale = match[1];
const userId = match[2];
// Get i18n strings for current locale (fallback to English)
const i18n = getUserNavI18n(locale);
// Remove old sign-out link
const signOutLink = navUserInfo.querySelector('.sign-out-link');
if (signOutLink) {
signOutLink.remove();
}
// Create icons container
const iconsContainer = document.createElement('span');
iconsContainer.className = 'gf-user-nav-icons';
// Create Edit Icon and Panel
const editIconContainer = document.createElement('span');
editIconContainer.className = 'gf-user-icon';
editIconContainer.setAttribute('data-panel', 'edit');
editIconContainer.innerHTML = `
<svg viewBox="0 0 24 24">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
`;
const editPanel = document.createElement('div');
editPanel.className = 'gf-user-panel';
editPanel.setAttribute('data-panel-type', 'edit');
editPanel.innerHTML = `
<a href="/${locale}/script_versions/new">${i18n.submitScript}</a>
<a href="/${locale}/script_versions/new?language=css">${i18n.submitStyle}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/users/${userId}/sets/new">${i18n.submitSet}</a>
<a href="/${locale}/users/webhook-info">${i18n.webhookInfo}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/import">${i18n.importScripts}</a>
`;
editIconContainer.appendChild(editPanel);
// Create Settings Icon and Panel
const settingsIconContainer = document.createElement('span');
settingsIconContainer.className = 'gf-user-icon gf-user-icon--settings gf-user-icon--settings--hover';
settingsIconContainer.setAttribute('data-panel', 'settings');
settingsIconContainer.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor">
<path d="M217.6,499.2v-55.279c-23.97-4.89-46.908-14.387-67.328-27.887l-39.091,39.083l-54.298-54.298
l39.083-39.091c-13.5-20.429-22.997-43.366-27.887-67.328H12.8v-76.8h55.279
c4.89-23.97,14.387-46.908,27.887-67.328l-39.083-39.091l54.298-54.306
l39.091,39.091c20.42-13.5,43.358-22.997,67.328-27.887V12.8h76.8v55.279
c23.97,4.89,46.908,14.387,67.328,27.887l39.091-39.091l54.298,54.306
l-39.083,39.091c13.5,20.429,22.997,43.366,27.887,67.328H499.2v76.8h-55.279
c-4.89,23.97-14.387,46.908-27.887,67.328l39.083,39.091l-54.298,54.298
l-39.091-39.083c-20.429,13.5-43.366,22.997-67.328,27.887V499.2H217.6z
M256,140.8c-63.522,0-115.2,51.678-115.2,115.2S192.478,371.2,256,371.2
S371.2,319.522,371.2,256S319.522,140.8,256,140.8z"/>
</svg>
`;
const settingsPanel = document.createElement('div');
settingsPanel.className = 'gf-user-panel';
settingsPanel.setAttribute('data-panel-type', 'settings');
settingsPanel.innerHTML = `
<a href="/${locale}/users/edit">${i18n.editProfile}</a>
<a href="/${locale}/users/edit_sign_in">${i18n.editSignIn}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/users/${userId}/notifications">${i18n.viewNotifications}</a>
<a href="/${locale}/users/${userId}/notification_settings">${i18n.notificationSettings}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/users/edit_account_deletion">${i18n.deleteAccount}</a>
`;
settingsIconContainer.appendChild(settingsPanel);
// Create Sign-out Icon
const signOutIconContainer = document.createElement('a');
signOutIconContainer.className = 'gf-user-icon';
signOutIconContainer.setAttribute('href', `/${locale}/users/sign_out`);
signOutIconContainer.setAttribute('rel', 'nofollow');
signOutIconContainer.setAttribute('data-method', 'delete');
signOutIconContainer.innerHTML = `
<svg viewBox="0 0 24 24">
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
<polyline points="16 17 21 12 16 7"></polyline>
<line x1="21" y1="12" x2="9" y2="12"></line>
</svg>
`;
// Append icons to container
iconsContainer.appendChild(editIconContainer);
iconsContainer.appendChild(settingsIconContainer);
iconsContainer.appendChild(signOutIconContainer);
// Insert icons container after the profile link
const profileLinkSpan = navUserInfo.querySelector('.user-profile-link');
if (profileLinkSpan.nextSibling) {
navUserInfo.insertBefore(iconsContainer, profileLinkSpan.nextSibling);
} else {
navUserInfo.appendChild(iconsContainer);
}
// Panel toggle logic
let activePanel = null;
const closeAllPanels = () => {
document.querySelectorAll('.gf-user-panel').forEach(panel => {
panel.classList.remove('active');
});
document.querySelectorAll('.gf-user-icon[data-panel]').forEach(icon => {
icon.classList.remove('active');
});
activePanel = null;
};
const togglePanel = (icon, panel) => {
const isActive = panel.classList.contains('active');
closeAllPanels();
if (!isActive) {
panel.classList.add('active');
icon.classList.add('active');
activePanel = panel;
}
};
// Add click handlers for edit and settings icons
editIconContainer.addEventListener('click', (e) => {
e.stopPropagation();
togglePanel(editIconContainer, editPanel);
});
settingsIconContainer.addEventListener('click', (e) => {
e.stopPropagation();
togglePanel(settingsIconContainer, settingsPanel);
});
// Close panels when clicking outside
document.addEventListener('click', (e) => {
if (activePanel && !e.target.closest('.gf-user-icon')) {
closeAllPanels();
}
});
// Close panels on ESC key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && activePanel) {
closeAllPanels();
}
});
return true;
};
const initMobileUserNavigation = () => {
const mobileUserItem = document.querySelector('#mobile-nav li.multi-link-nav');
if (!mobileUserItem) {
return false;
}
if (mobileUserItem.querySelector('#gf-mobile-user-actions')) {
return true;
}
const profileLinkSpan = mobileUserItem.querySelector('.user-profile-link');
const profileLink = profileLinkSpan?.querySelector('a');
const signOutContainer = mobileUserItem.querySelector('.sign-out-link');
if (!profileLink || !signOutContainer) {
return false;
}
const profileHref = profileLink.getAttribute('href') || '';
const match = profileHref.match(/\/([a-z]{2}(?:-[A-Z]{2})?)\/users\/(\d+)-/);
if (!match) {
return false;
}
const locale = match[1];
const userId = match[2];
const i18n = getUserNavI18n(locale);
const signOutAnchor = signOutContainer.querySelector('a');
if (!signOutAnchor) {
return false;
}
const userRow = document.createElement('div');
userRow.id = 'gf-mobile-user-row';
const actions = document.createElement('span');
actions.id = 'gf-mobile-user-actions';
const editIconContainer = document.createElement('span');
editIconContainer.className = 'gf-user-icon gf-mobile-edit-icon';
editIconContainer.setAttribute('data-panel', 'edit');
editIconContainer.innerHTML = `
<svg viewBox="0 0 24 24">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
`;
const editPanel = document.createElement('div');
editPanel.className = 'gf-user-panel gf-mobile-user-panel';
editPanel.setAttribute('data-panel-type', 'edit');
editPanel.innerHTML = `
<a href="/${locale}/script_versions/new">${i18n.submitScript}</a>
<a href="/${locale}/script_versions/new?language=css">${i18n.submitStyle}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/users/${userId}/sets/new">${i18n.submitSet}</a>
<a href="/${locale}/users/webhook-info">${i18n.webhookInfo}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/import">${i18n.importScripts}</a>
`;
const settingsIconContainer = document.createElement('span');
settingsIconContainer.className = 'gf-user-icon gf-user-icon--settings gf-user-icon--settings--hover';
settingsIconContainer.setAttribute('data-panel', 'settings');
settingsIconContainer.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M217.6,499.2v-55.279c-23.97-4.89-46.908-14.387-67.328-27.887l-39.091,39.083l-54.298-54.298
l39.083-39.091c-13.5-20.429-22.997-43.366-27.887-67.328H12.8v-76.8h55.279
c4.89-23.97,14.387-46.908,27.887-67.328l-39.083-39.091l54.298-54.306
l39.091,39.091c20.42-13.5,43.358-22.997,67.328-27.887V12.8h76.8v55.279
c23.97,4.89,46.908,14.387,67.328,27.887l39.091-39.091l54.298,54.306
l-39.083,39.091c13.5,20.429,22.997,43.366,27.887,67.328H499.2v76.8h-55.279
c-4.89,23.97-14.387,46.908-27.887,67.328l39.083,39.091l-54.298,54.298
l-39.091-39.083c-20.429,13.5-43.366,22.997-67.328,27.887V499.2H217.6z
M256,140.8c-63.522,0-115.2,51.678-115.2,115.2S192.478,371.2,256,371.2
S371.2,319.522,371.2,256S319.522,140.8,256,140.8z"/>
</svg>
`;
const settingsPanel = document.createElement('div');
settingsPanel.className = 'gf-user-panel gf-mobile-user-panel';
settingsPanel.setAttribute('data-panel-type', 'settings');
settingsPanel.innerHTML = `
<a href="/${locale}/users/edit">${i18n.editProfile}</a>
<a href="/${locale}/users/edit_sign_in">${i18n.editSignIn}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/users/${userId}/notifications">${i18n.viewNotifications}</a>
<a href="/${locale}/users/${userId}/notification_settings">${i18n.notificationSettings}</a>
<div class="gf-user-panel-separator"></div>
<a href="/${locale}/users/edit_account_deletion">${i18n.deleteAccount}</a>
`;
const mobileSignOutLink = document.createElement('a');
mobileSignOutLink.className = 'gf-user-icon gf-mobile-sign-out-icon';
mobileSignOutLink.href = signOutAnchor.href;
mobileSignOutLink.setAttribute('rel', signOutAnchor.getAttribute('rel') || 'nofollow');
const method = signOutAnchor.getAttribute('data-method');
if (method) {
mobileSignOutLink.setAttribute('data-method', method);
}
mobileSignOutLink.innerHTML = `
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
<polyline points="16 17 21 12 16 7"></polyline>
<line x1="21" y1="12" x2="9" y2="12"></line>
</svg>
`;
actions.appendChild(editIconContainer);
actions.appendChild(settingsIconContainer);
actions.appendChild(mobileSignOutLink);
const userMeta = document.createElement('div');
userMeta.id = 'gf-mobile-user-meta';
userMeta.appendChild(profileLinkSpan);
const mobileThemeSwitch = document.getElementById('gf-mobile-theme-switch');
const mobileThemeSwitchItem = document.getElementById('gf-mobile-theme-switch-item');
if (mobileThemeSwitch) {
mobileThemeSwitch.style.marginTop = '0';
mobileThemeSwitch.style.marginRight = '0';
mobileThemeSwitch.style.marginLeft = '0';
userMeta.appendChild(mobileThemeSwitch);
}
if (mobileThemeSwitchItem) {
mobileThemeSwitchItem.remove();
}
userRow.appendChild(userMeta);
userRow.appendChild(actions);
signOutContainer.remove();
mobileUserItem.prepend(userRow);
mobileUserItem.appendChild(editPanel);
mobileUserItem.appendChild(settingsPanel);
let activePanel = null;
const closeMobilePanels = () => {
[editPanel, settingsPanel].forEach((panel) => panel.classList.remove('active'));
[editIconContainer, settingsIconContainer].forEach((icon) => icon.classList.remove('active'));
activePanel = null;
};
const toggleMobilePanel = (icon, panel) => {
const isActive = panel.classList.contains('active');
closeMobilePanels();
if (!isActive) {
panel.classList.add('active');
icon.classList.add('active');
activePanel = panel;
}
};
editIconContainer.addEventListener('click', (event) => {
event.stopPropagation();
toggleMobilePanel(editIconContainer, editPanel);
});
settingsIconContainer.addEventListener('click', (event) => {
event.stopPropagation();
toggleMobilePanel(settingsIconContainer, settingsPanel);
});
document.addEventListener('click', (event) => {
if (activePanel && !event.target.closest('#gf-mobile-user-actions')) {
closeMobilePanels();
}
});
return true;
};
// ============================================================================
// Lightbox And Image Zoom
// ============================================================================
const STANDALONE_LIGHTBOX_IMAGE_ATTR = 'data-gfplus-standalone-lightbox';
let lightboxScrollLockObserver = null;
let lightboxScrollPreventInitialized = false;
let standaloneLightboxObserver = null;
let lightboxZoomImage = null;
let lightboxZoomImageSource = '';
let lightboxZoomState = {
scale: 1,
x: 0,
y: 0
};
let lightboxDragState = null;
let lightboxPinchState = null;
const clampLightboxZoomValue = (value, min, max) => Math.max(min, Math.min(max, value));
const constrainLightboxPan = () => {
if (!lightboxZoomImage || lightboxZoomState.scale <= 1) {
lightboxZoomState.x = 0;
lightboxZoomState.y = 0;
return;
}
const maxX = (lightboxZoomImage.clientWidth * (lightboxZoomState.scale - 1)) / 2;
const maxY = (lightboxZoomImage.clientHeight * (lightboxZoomState.scale - 1)) / 2;
lightboxZoomState.x = clampLightboxZoomValue(lightboxZoomState.x, -maxX, maxX);
lightboxZoomState.y = clampLightboxZoomValue(lightboxZoomState.y, -maxY, maxY);
};
const applyLightboxImageZoom = () => {
if (!lightboxZoomImage) {
return;
}
constrainLightboxPan();
const zoomed = lightboxZoomState.scale > 1.01;
lightboxZoomImage.classList.toggle('gfplus-lightbox-zoomed', zoomed);
lightboxZoomImage.style.transform = zoomed
? `translate3d(${lightboxZoomState.x}px, ${lightboxZoomState.y}px, 0) scale(${lightboxZoomState.scale})`
: '';
};
const resetLightboxImageZoom = () => {
if (!lightboxZoomImage) {
return;
}
lightboxZoomState = { scale: 1, x: 0, y: 0 };
lightboxDragState = null;
lightboxPinchState = null;
lightboxZoomImage.classList.remove('gfplus-lightbox-zoomed', 'gfplus-lightbox-dragging');
lightboxZoomImage.style.transform = '';
};
const setLightboxImageZoom = (scale, focalPoint = null) => {
const previousScale = lightboxZoomState.scale;
const nextScale = clampLightboxZoomValue(scale, 1, 4);
if (lightboxZoomImage && focalPoint && previousScale > 0) {
const rect = lightboxZoomImage.getBoundingClientRect();
const imageCenterX = rect.left + rect.width / 2;
const imageCenterY = rect.top + rect.height / 2;
const scaleRatio = nextScale / previousScale;
lightboxZoomState.x += (focalPoint.x - imageCenterX) * (1 - scaleRatio);
lightboxZoomState.y += (focalPoint.y - imageCenterY) * (1 - scaleRatio);
}
lightboxZoomState.scale = nextScale;
if (lightboxZoomState.scale <= 1.01) {
lightboxZoomState = { scale: 1, x: 0, y: 0 };
}
applyLightboxImageZoom();
};
const getTouchDistance = (touches) => {
const dx = touches[0].clientX - touches[1].clientX;
const dy = touches[0].clientY - touches[1].clientY;
return Math.hypot(dx, dy);
};
const getTouchCenter = (touches) => ({
x: (touches[0].clientX + touches[1].clientX) / 2,
y: (touches[0].clientY + touches[1].clientY) / 2
});
const handleLightboxImageWheel = (event) => {
if (!root.classList.contains(LIGHTBOX_SCROLL_LOCK_CLASS)) {
return;
}
event.preventDefault();
event.stopPropagation();
const factor = event.deltaY < 0 ? 1.14 : 0.88;
setLightboxImageZoom(lightboxZoomState.scale * factor, {
x: event.clientX,
y: event.clientY
});
};
const handleLightboxImageDoubleClick = (event) => {
event.preventDefault();
event.stopPropagation();
setLightboxImageZoom(lightboxZoomState.scale > 1.01 ? 1 : 2.4, {
x: event.clientX,
y: event.clientY
});
};
const stopLightboxImageClickClose = (event) => {
event.stopPropagation();
};
const handleLightboxImagePointerDown = (event) => {
if (event.pointerType === 'touch' || lightboxZoomState.scale <= 1.01) {
return;
}
event.preventDefault();
lightboxDragState = {
pointerId: event.pointerId,
startX: event.clientX,
startY: event.clientY,
x: lightboxZoomState.x,
y: lightboxZoomState.y
};
lightboxZoomImage?.classList.add('gfplus-lightbox-dragging');
lightboxZoomImage?.setPointerCapture?.(event.pointerId);
};
const handleLightboxImagePointerMove = (event) => {
if (!lightboxDragState || lightboxDragState.pointerId !== event.pointerId) {
return;
}
event.preventDefault();
lightboxZoomState.x = lightboxDragState.x + event.clientX - lightboxDragState.startX;
lightboxZoomState.y = lightboxDragState.y + event.clientY - lightboxDragState.startY;
applyLightboxImageZoom();
};
const endLightboxImagePointerDrag = (event) => {
if (!lightboxDragState || lightboxDragState.pointerId !== event.pointerId) {
return;
}
lightboxZoomImage?.releasePointerCapture?.(event.pointerId);
lightboxZoomImage?.classList.remove('gfplus-lightbox-dragging');
lightboxDragState = null;
};
const handleLightboxImageTouchStart = (event) => {
if (event.touches.length === 2) {
lightboxPinchState = {
distance: getTouchDistance(event.touches),
scale: lightboxZoomState.scale
};
return;
}
if (event.touches.length === 1 && lightboxZoomState.scale > 1.01) {
lightboxDragState = {
startX: event.touches[0].clientX,
startY: event.touches[0].clientY,
x: lightboxZoomState.x,
y: lightboxZoomState.y
};
}
};
const handleLightboxImageTouchMove = (event) => {
if (event.touches.length === 2 && lightboxPinchState) {
event.preventDefault();
event.stopPropagation();
const nextScale = lightboxPinchState.scale * (getTouchDistance(event.touches) / lightboxPinchState.distance);
setLightboxImageZoom(nextScale, getTouchCenter(event.touches));
return;
}
if (event.touches.length === 1 && lightboxDragState && lightboxZoomState.scale > 1.01) {
event.preventDefault();
event.stopPropagation();
lightboxZoomState.x = lightboxDragState.x + event.touches[0].clientX - lightboxDragState.startX;
lightboxZoomState.y = lightboxDragState.y + event.touches[0].clientY - lightboxDragState.startY;
applyLightboxImageZoom();
}
};
const handleLightboxImageTouchEnd = () => {
lightboxDragState = null;
lightboxPinchState = null;
lightboxZoomImage?.classList.remove('gfplus-lightbox-dragging');
};
const bindLightboxImageZoom = () => {
const openLightbox = document.querySelector('.lum-lightbox.lum-open');
const image = openLightbox?.querySelector('.lum-img, .lum-lightbox-inner img, img');
const imageSource = image?.currentSrc || image?.src || '';
if (!image) {
return;
}
if (image === lightboxZoomImage && imageSource === lightboxZoomImageSource) {
return;
}
resetLightboxImageZoom();
lightboxZoomImage = image;
lightboxZoomImageSource = imageSource;
lightboxZoomImage.classList.add('gfplus-lightbox-zoomable');
if (lightboxZoomImage.dataset.gfplusZoomBound !== 'true') {
lightboxZoomImage.dataset.gfplusZoomBound = 'true';
lightboxZoomImage.addEventListener('click', stopLightboxImageClickClose);
lightboxZoomImage.addEventListener('wheel', handleLightboxImageWheel, { passive: false });
lightboxZoomImage.addEventListener('dblclick', handleLightboxImageDoubleClick);
lightboxZoomImage.addEventListener('pointerdown', handleLightboxImagePointerDown);
lightboxZoomImage.addEventListener('pointermove', handleLightboxImagePointerMove);
lightboxZoomImage.addEventListener('pointerup', endLightboxImagePointerDrag);
lightboxZoomImage.addEventListener('pointercancel', endLightboxImagePointerDrag);
lightboxZoomImage.addEventListener('touchstart', handleLightboxImageTouchStart, { passive: false });
lightboxZoomImage.addEventListener('touchmove', handleLightboxImageTouchMove, { passive: false });
lightboxZoomImage.addEventListener('touchend', handleLightboxImageTouchEnd);
lightboxZoomImage.addEventListener('touchcancel', handleLightboxImageTouchEnd);
}
};
const updateLightboxScrollLock = () => {
const lightboxOpen = Boolean(document.querySelector('.lum-lightbox.lum-open'));
root.classList.toggle(LIGHTBOX_SCROLL_LOCK_CLASS, lightboxOpen);
if (lightboxOpen) {
bindLightboxImageZoom();
} else {
resetLightboxImageZoom();
lightboxZoomImage = null;
lightboxZoomImageSource = '';
}
};
const preventLightboxBackgroundScroll = (event) => {
if (root.classList.contains(LIGHTBOX_SCROLL_LOCK_CLASS)) {
event.preventDefault();
}
};
const initLightboxScrollLock = () => {
updateLightboxScrollLock();
if (!lightboxScrollPreventInitialized) {
document.addEventListener('wheel', preventLightboxBackgroundScroll, { passive: false, capture: true });
document.addEventListener('touchmove', preventLightboxBackgroundScroll, { passive: false, capture: true });
lightboxScrollPreventInitialized = true;
}
if (lightboxScrollLockObserver || !document.body) {
return;
}
lightboxScrollLockObserver = new MutationObserver(updateLightboxScrollLock);
lightboxScrollLockObserver.observe(document.body, {
attributes: true,
attributeFilter: ['class'],
childList: true,
subtree: true
});
};
const closeStandaloneImageLightbox = (lightbox) => {
resetLightboxImageZoom();
lightbox?.__gfplusEscapeHandler && document.removeEventListener('keydown', lightbox.__gfplusEscapeHandler);
lightbox?.remove();
updateLightboxScrollLock();
};
const openStandaloneImageLightbox = (sourceImage) => {
const source = sourceImage.currentSrc || sourceImage.src;
if (!source) {
return;
}
const lightbox = document.createElement('div');
lightbox.className = 'lum-lightbox lum-open gfplus-standalone-lightbox';
lightbox.innerHTML = `
<div class="lum-lightbox-inner">
<div class="lum-lightbox-image-wrapper">
<span class="lum-lightbox-position-helper">
<img class="lum-img" alt="">
<p class="lum-lightbox-caption"></p>
</span>
</div>
<div class="lum-close-button"></div>
</div>
`;
const image = lightbox.querySelector('.lum-img');
const caption = lightbox.querySelector('.lum-lightbox-caption');
image.src = source;
image.alt = sourceImage.alt || '';
const captionText = sourceImage.alt || sourceImage.title || '';
if (captionText) {
caption.textContent = captionText;
} else {
caption.remove();
}
lightbox.addEventListener('click', (event) => {
if (!event.target.closest('.lum-img, .lum-close-button')) {
closeStandaloneImageLightbox(lightbox);
}
});
lightbox.querySelector('.lum-close-button')?.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
closeStandaloneImageLightbox(lightbox);
});
const handleEscape = (event) => {
if (event.key === 'Escape' && lightbox.isConnected) {
closeStandaloneImageLightbox(lightbox);
}
};
lightbox.__gfplusEscapeHandler = handleEscape;
document.addEventListener('keydown', handleEscape);
document.body.appendChild(lightbox);
updateLightboxScrollLock();
};
const shouldBindStandaloneImageLightbox = (image) => {
if (!image?.src || image.closest('.lum-lightbox')) {
return false;
}
if (!image.closest('.user-content, #additional-info, #script-content, .gf-script-extra-info')) {
return false;
}
if (image.closest('a[href]') || image.classList.contains('gf-script-logo')) {
return false;
}
return true;
};
const bindStandaloneImageLightboxes = () => {
document.querySelectorAll('img[src]').forEach((image) => {
if (image.getAttribute(STANDALONE_LIGHTBOX_IMAGE_ATTR) === 'done' || !shouldBindStandaloneImageLightbox(image)) {
return;
}
image.setAttribute(STANDALONE_LIGHTBOX_IMAGE_ATTR, 'done');
image.classList.add('gfplus-standalone-lightbox-trigger');
image.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
openStandaloneImageLightbox(image);
});
});
};
const initStandaloneImageLightboxes = () => {
bindStandaloneImageLightboxes();
if (standaloneLightboxObserver || !document.body) {
return;
}
standaloneLightboxObserver = new MutationObserver(bindStandaloneImageLightboxes);
standaloneLightboxObserver.observe(document.body, {
childList: true,
subtree: true
});
};
// ============================================================================
// Editor Toolbar
// ============================================================================
const EDITOR_TOOLBAR_ATTR = 'data-gfplus-editor-toolbar';
const EDITOR_TOOLBAR_BUTTONS = [
{
id: 'heading',
label: 'Heading',
icon: 'H',
headingLevel: 2
},
{
id: 'bold',
label: 'Bold',
icon: '<path d="M7 5h6a3 3 0 0 1 0 6H7z"></path><path d="M7 11h7a3 3 0 0 1 0 6H7z"></path>',
markdown: (text) => `**${text || 'texte'}**`,
html: (text) => `<strong>${text || 'texte'}</strong>`
},
{
id: 'italic',
label: 'Italic',
icon: '<path d="M10 5h8"></path><path d="M6 19h8"></path><path d="M14 5 10 19"></path>',
markdown: (text) => `*${text || 'texte'}*`,
html: (text) => `<em>${text || 'texte'}</em>`
},
{
id: 'link',
label: 'Link',
icon: '<path d="M10 13a5 5 0 0 0 7.07 0l2-2a5 5 0 0 0-7.07-7.07l-1.15 1.15"></path><path d="M14 11a5 5 0 0 0-7.07 0l-2 2A5 5 0 0 0 12 20.07l1.15-1.15"></path>',
markdown: (text) => `[${text || 'texte'}](https://example.com)`,
html: (text) => `<a href="https://example.com">${text || 'texte'}</a>`
},
{
id: 'image',
label: 'Image',
icon: '<rect x="4" y="5" width="16" height="14" rx="2"></rect><circle cx="9" cy="10" r="1.5"></circle><path d="m4 16 4-4 3 3 2-2 7 6"></path>',
markdown: (text) => ``,
html: (text) => `<img src="https://example.com/image.png" alt="${text || 'description'}">`
},
{
id: 'code',
label: 'Code',
icon: '<path d="m9 18 6-12"></path><path d="m7 8-4 4 4 4"></path><path d="m17 8 4 4-4 4"></path>',
markdown: (text) => text.includes('\n') ? `\`\`\`\n${text || 'code'}\n\`\`\`` : `\`${text || 'code'}\``,
html: (text) => text.includes('\n') ? `<pre><code>${text || 'code'}</code></pre>` : `<code>${text || 'code'}</code>`
},
{
id: 'quote',
label: 'Blockquote',
icon: '<path d="M8 8H5a4 4 0 0 0-4 4v5h7v-7H4"></path><path d="M20 8h-3a4 4 0 0 0-4 4v5h7v-7h-4"></path>',
markdown: (text) => `> ${text || 'citation'}`,
html: (text) => `<blockquote>${text || 'citation'}</blockquote>`
},
{
id: 'list',
label: 'List',
icon: '<path d="M8 6h13"></path><path d="M8 12h13"></path><path d="M8 18h13"></path><path d="M3 6h.01"></path><path d="M3 12h.01"></path><path d="M3 18h.01"></path>',
markdown: (text) => (text || 'élément').split('\n').map((line) => `- ${line || 'élément'}`).join('\n'),
html: (text) => `<ul>\n${(text || 'élément').split('\n').map((line) => ` <li>${line || 'élément'}</li>`).join('\n')}\n</ul>`
},
{
id: 'details',
label: 'Details',
icon: '<path d="m9 18 6-6-6-6"></path><path d="M4 5h16"></path><path d="M4 19h16"></path>',
markdown: (text) => `<details open>\n<summary>Titre</summary>\n\n${text || 'Contenu'}\n</details>`,
html: (text) => `<details open>\n<summary>Titre</summary>\n<p>${text || 'Contenu'}</p>\n</details>`
},
{
id: 'mark',
label: 'Highlight',
icon: '<path d="m4 20 4-1 10-10a2.8 2.8 0 0 0-4-4L4 15l-1 4z"></path><path d="M13 6l5 5"></path>',
markdown: (text) => `<mark>${text || 'texte'}</mark>`,
html: (text) => `<mark>${text || 'texte'}</mark>`
},
{
id: 'textColor',
label: 'Text Color',
icon: '<path d="M4 19h16"></path><path d="M8 15 12 5l4 10"></path><path d="M9.5 11h5"></path>',
colorProperty: 'color',
defaultColor: '#4f46e5'
},
{
id: 'backgroundColor',
label: 'Background Color',
icon: '<path d="m4 14 7-7 6 6-7 7z"></path><path d="M14 4 20 10"></path><path d="M4 20h16"></path>',
colorProperty: 'background-color',
defaultColor: '#fef3c7'
}
];
const getPreviewableMarkupMode = (previewable) => {
const markupName = previewable.getAttribute('data-markup-option-name') || '';
const escapedMarkupName = window.CSS?.escape ? window.CSS.escape(markupName) : markupName.replace(/"/g, '\\"');
const checkedControl = markupName
? document.querySelector(`input[name="${escapedMarkupName}"]:checked, select[name="${escapedMarkupName}"]`)
: null;
const mode = String(checkedControl?.value || '').toLowerCase();
return mode.includes('html') ? 'html' : 'markdown';
};
const insertEditorSnippet = (textarea, snippetFactory) => {
const start = textarea.selectionStart ?? textarea.value.length;
const end = textarea.selectionEnd ?? start;
const selectedText = textarea.value.slice(start, end);
const snippet = snippetFactory(selectedText);
textarea.setRangeText(snippet, start, end, 'end');
textarea.dispatchEvent(new Event('input', { bubbles: true }));
textarea.dispatchEvent(new Event('change', { bubbles: true }));
textarea.focus();
};
const createEditorToolbarButton = (buttonConfig, previewable, textarea) => {
const fragment = document.createDocumentFragment();
const button = document.createElement('button');
button.className = `gf-editor-toolbar-button${buttonConfig.icon.startsWith('<') ? '' : ' gf-editor-toolbar-button--text'}`;
button.type = 'button';
button.title = buttonConfig.label;
button.setAttribute('aria-label', buttonConfig.label);
button.innerHTML = buttonConfig.icon.startsWith('<')
? `<svg viewBox="0 0 24 24" aria-hidden="true">${buttonConfig.icon}</svg>`
: buttonConfig.icon;
if (buttonConfig.headingLevel) {
const tool = document.createElement('span');
tool.className = 'gf-editor-toolbar-heading-tool';
const headingSelect = document.createElement('select');
headingSelect.className = 'gf-editor-toolbar-heading-select';
headingSelect.title = 'Heading Level';
headingSelect.setAttribute('aria-label', 'Heading Level');
[1, 2, 3, 4, 5, 6].forEach((level) => {
const option = document.createElement('option');
option.value = String(level);
option.textContent = `H${level}`;
headingSelect.appendChild(option);
});
headingSelect.value = String(buttonConfig.headingLevel);
button.addEventListener('click', (event) => {
event.preventDefault();
const level = Number.parseInt(headingSelect.value || String(buttonConfig.headingLevel), 10);
const safeLevel = Math.min(6, Math.max(1, Number.isFinite(level) ? level : 2));
const mode = getPreviewableMarkupMode(previewable);
insertEditorSnippet(textarea, (text) => (
mode === 'html'
? `<h${safeLevel}>${text || 'Titre'}</h${safeLevel}>`
: `${'#'.repeat(safeLevel)} ${text || 'Titre'}`
));
button.blur();
});
tool.appendChild(button);
tool.appendChild(headingSelect);
fragment.appendChild(tool);
return fragment;
}
if (buttonConfig.colorProperty) {
const tool = document.createElement('span');
tool.className = 'gf-editor-toolbar-color-tool';
const colorInput = document.createElement('input');
colorInput.className = 'gf-editor-toolbar-color-input';
colorInput.type = 'color';
colorInput.value = buttonConfig.defaultColor;
colorInput.setAttribute('aria-label', buttonConfig.label);
const swatchButton = document.createElement('button');
swatchButton.className = 'gf-editor-toolbar-color-swatch-button';
swatchButton.type = 'button';
swatchButton.title = `Change ${buttonConfig.label.toLowerCase()}`;
swatchButton.setAttribute('aria-label', `Change ${buttonConfig.label.toLowerCase()}`);
const colorSwatch = document.createElement('span');
colorSwatch.className = 'gf-editor-toolbar-color-swatch';
colorSwatch.style.backgroundColor = colorInput.value;
swatchButton.appendChild(colorSwatch);
button.addEventListener('click', (event) => {
event.preventDefault();
insertEditorSnippet(textarea, (text) => `<span style="${buttonConfig.colorProperty}:${colorInput.value}">${text || 'texte'}</span>`);
button.blur();
});
swatchButton.addEventListener('click', (event) => {
event.preventDefault();
colorInput.focus({ preventScroll: true });
if (typeof colorInput.showPicker === 'function') {
colorInput.showPicker();
} else {
colorInput.click();
}
});
colorInput.addEventListener('input', () => {
colorSwatch.style.backgroundColor = colorInput.value;
});
colorInput.addEventListener('change', () => {
colorSwatch.style.backgroundColor = colorInput.value;
});
tool.appendChild(button);
tool.appendChild(swatchButton);
tool.appendChild(colorInput);
fragment.appendChild(tool);
return fragment;
}
button.addEventListener('click', (event) => {
event.preventDefault();
const mode = getPreviewableMarkupMode(previewable);
insertEditorSnippet(textarea, buttonConfig[mode] || buttonConfig.markdown);
button.blur();
});
fragment.appendChild(button);
return fragment;
};
const enhancePreviewableEditor = (previewable) => {
if (previewable.getAttribute(EDITOR_TOOLBAR_ATTR) === 'done') {
return;
}
const textarea = previewable.querySelector('textarea.comment-entry, textarea');
if (!textarea) {
return;
}
const toolbar = document.createElement('div');
toolbar.className = 'gf-editor-toolbar';
toolbar.setAttribute('role', 'toolbar');
toolbar.setAttribute('aria-label', 'Outils de mise en forme');
EDITOR_TOOLBAR_BUTTONS.forEach((buttonConfig) => {
toolbar.appendChild(createEditorToolbarButton(buttonConfig, previewable, textarea));
});
const tabs = previewable.querySelector(':scope > .tabs');
if (tabs) {
tabs.insertAdjacentElement('afterend', toolbar);
} else {
textarea.insertAdjacentElement('beforebegin', toolbar);
}
previewable.setAttribute(EDITOR_TOOLBAR_ATTR, 'done');
};
let editorToolbarObserver = null;
const initPreviewableEditorToolbars = () => {
document.querySelectorAll('.previewable').forEach(enhancePreviewableEditor);
if (editorToolbarObserver || !document.body) {
return;
}
editorToolbarObserver = new MutationObserver(() => {
document.querySelectorAll('.previewable:not([data-gfplus-editor-toolbar="done"])').forEach(enhancePreviewableEditor);
});
editorToolbarObserver.observe(document.body, { childList: true, subtree: true });
};
let fastMenuObserver = null;
let fastMenuFrame = 0;
const applyFastMenuEnhancements = () => {
initThemeSwitch();
initMobileNavLayout();
initMobileThemeSwitch();
syncActiveScriptSetFilter();
initUserNavigation();
initMobileUserNavigation();
};
const scheduleFastMenuEnhancements = () => {
if (fastMenuFrame) {
return;
}
fastMenuFrame = requestAnimationFrame(() => {
fastMenuFrame = 0;
applyFastMenuEnhancements();
});
};
const initFastMenuEnhancements = () => {
applyFastMenuEnhancements();
if (document.readyState !== 'loading' || fastMenuObserver) {
return;
}
fastMenuObserver = new MutationObserver(scheduleFastMenuEnhancements);
fastMenuObserver.observe(root, {
childList: true,
subtree: true
});
document.addEventListener('DOMContentLoaded', () => {
scheduleFastMenuEnhancements();
if (fastMenuObserver) {
fastMenuObserver.disconnect();
fastMenuObserver = null;
}
}, { once: true });
};
let uiInitialized = false;
const initUi = () => {
if (uiInitialized) {
return;
}
uiInitialized = true;
initThemeSwitch();
initMobileNavLayout();
initMobileThemeSwitch();
initSidebarScrollControls();
syncActiveScriptSetFilter();
initSidebarGroupToggles();
initSmartSidebar();
initMobileSidebarStickiness();
initModeratorActionsLayout();
initCompactUserScriptSets();
initScriptSetEditor();
initHighlightJs();
initInstallStatsChartTheme();
initLightboxScrollLock();
initStandaloneImageLightboxes();
initPreviewableEditorToolbars();
initScriptLogos();
initScriptCardActions();
initUserNavigation();
initMobileUserNavigation();
if (root.hasAttribute(HANDHELD_ATTR)) {
schedulePhoneLoadClear();
return;
}
scheduleNoTransitionClear();
};
initFastMenuEnhancements();
if (document.readyState === 'loading') {
window.addEventListener('DOMContentLoaded', initUi, { once: true });
} else {
initUi();
}
})();