WTR-Lab Reader & UI Enhancer

Adds a responsive configuration panel to adjust reader width, navigation width, and optionally override font style on wtr-lab.com.

// ==UserScript==
// @name         WTR-Lab Reader & UI Enhancer
// @namespace    http://tampermonkey.net/
// @version      3.5
// @description  Adds a responsive configuration panel to adjust reader width, navigation width, and optionally override font style on wtr-lab.com.
// @author       MasuRii
// @license      MIT
// @match        https://wtr-lab.com/en/novel/*/*/chapter-*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM_xmlhttpRequest
// @connect      gwfh.mranftl.com
// @connect      fonts.googleapis.com
// @icon         https://www.google.com/s2/favicons?sz=64&domain=wtr-lab.com
// ==/UserScript==

;(function () {
	'use strict'

	// --- CONFIGURATION ---
	const DEBUG_KEY = 'wtr_lab_enhancer_debug'
	const STEP_WIDTH = 50
	const MIN_WIDTH = 300
	const FONTS_API_URL = 'https://gwfh.mranftl.com/api/fonts'

	const RECOMMENDED_FONTS = {
		serif: ['Merriweather', 'Lora', 'Crimson Text', 'Libre Baskerville', 'Spectral', 'EB Garamond', 'Noto Serif'],
		sansSerif: ['Roboto', 'Open Sans', 'Source Sans Pro']
	}

	const configs = {
		reader: {key: 'wtr_lab_reader_width', selector: '.fix-size.card', defaultWidth: 760, label: 'Reader Content Width'},
		nav: {
			key: 'wtr_lab_nav_width',
			selector: 'nav.bottom-reader-nav .fix-size',
			defaultWidth: 760,
			label: 'Bottom Navigator Width'
		},
		navConstraint: {
			key: 'wtr_lab_nav_constraint',
			selector: 'nav.bottom-reader-nav',
			defaultState: false,
			label: 'Constrain Navigator Background'
		},
		fontToggle: {key: 'wtr_lab_font_style_enabled', defaultState: false, label: 'Enable Custom Font Style'},
		font: {key: 'wtr_lab_font_family', selector: '.chapter-body', defaultFont: 'Merriweather', label: 'Font Style'},
		blockAddTerm: {
			key: 'wtr_lab_block_add_term',
			selector: '.floating-add-term-btn',
			defaultState: false,
			label: 'Block "Add Term" Button'
		},
		hideBookBtn: {
			key: 'wtr_lab_hide_book_btn',
			selector: 'div.btn-group button:has(svg use[href="/icons/sprite.svg#book"])',
			defaultState: false,
			label: 'Book',
			iconHTML: '<svg><use href="/icons/sprite.svg#book"></use></svg>'
		},
		hideTextFieldsBtn: {
			key: 'wtr_lab_hide_text_fields_btn',
			selector: 'div.btn-group button:has(svg use[href="/icons/sprite.svg#text_fields"])',
			defaultState: false,
			label: 'Text',
			iconHTML: '<svg><use href="/icons/sprite.svg#text_fields"></use></svg>'
		},
		hideTtsBtn: {
			key: 'wtr_lab_hide_tts_btn',
			selector: 'div.btn-group button:has(svg use[href="/icons/sprite.svg#tts"])',
			defaultState: false,
			label: 'TTS',
			iconHTML: '<svg><use href="/icons/sprite.svg#tts"></use></svg>'
		},
		hideCogBtn: {
			key: 'wtr_lab_hide_cog_btn',
			selector: 'div.btn-group button:has(svg use[href="/icons/sprite.svg#cog-outline"])',
			defaultState: false,
			label: 'Settings',
			iconHTML: '<svg><use href="/icons/sprite.svg#cog-outline"></use></svg>'
		},
		hideListBtn: {
			key: 'wtr_lab_hide_list_btn',
			selector: 'div.btn-group button:has(svg use[href="/icons/sprite.svg#list"])',
			defaultState: false,
			label: 'List',
			iconHTML: '<svg><use href="/icons/sprite.svg#list"></use></svg>'
		},
		debug: {
			key: DEBUG_KEY,
			defaultState: false,
			label: 'Enable Debug Logging'
		}
	}

	// --- DEBUG LOGGER ---
	let isDebugEnabled = GM_getValue(DEBUG_KEY, false)
	const syncDebugState = () => {
		isDebugEnabled = GM_getValue(DEBUG_KEY, false)
	}
	const log = (...args) => {
		if (isDebugEnabled) console.log('[WTR-Lab Enhancer]', ...args)
	}
	const toggleDebugLogging = () => {
		isDebugEnabled = !isDebugEnabled
		GM_setValue(DEBUG_KEY, isDebugEnabled)
		alert(`Debug logging is now ${isDebugEnabled ? 'ENABLED' : 'DISABLED'}.`)
	}

	// --- CORE LOGIC ---
	const saveValue = (key, value) => GM_setValue(key, value)
	const loadValue = (key, defaultValue) => GM_getValue(key, defaultValue)

	const applyWidthStyle = (configName, width) => {
		const styleId = `custom-width-styler-${configName}`
		let styleElement = document.getElementById(styleId)
		if (!styleElement) {
			styleElement = document.createElement('style')
			styleElement.id = styleId
			document.head.appendChild(styleElement)
		}
		styleElement.textContent = `${configs[configName].selector} { max-width: ${width}px !important; }`
	}

	const updateNavConstraint = () => {
		const isConstrained = loadValue(configs.navConstraint.key, configs.navConstraint.defaultState)
		const styleId = 'custom-nav-constraint-styler'
		let styleElement = document.getElementById(styleId)
		if (isConstrained) {
			if (!styleElement) {
				styleElement = document.createElement('style')
				styleElement.id = styleId
				document.head.appendChild(styleElement)
			}
			const navContentWidth = loadValue(configs.nav.key, configs.nav.defaultWidth)
			const marginValue = Math.max(0, (window.innerWidth - navContentWidth) / 2)
			styleElement.textContent = `${configs.navConstraint.selector} { margin-left: ${marginValue}px !important; margin-right: ${marginValue}px !important; }`
		} else if (styleElement) {
			styleElement.remove()
		}
	}

	const updateBlockAddTerm = () => {
		const isBlocked = loadValue(configs.blockAddTerm.key, configs.blockAddTerm.defaultState)
		const styleId = 'custom-block-add-term-styler'
		let styleElement = document.getElementById(styleId)
		if (isBlocked) {
			if (!styleElement) {
				styleElement = document.createElement('style')
				styleElement.id = styleId
				document.head.appendChild(styleElement)
			}
			styleElement.textContent = `${configs.blockAddTerm.selector} { display: none !important; }`
		} else if (styleElement) {
			styleElement.remove()
		}
	}

	const updateButtonVisibilityStyles = () => {
		const styleId = 'custom-button-visibility-styler'
		let styleElement = document.getElementById(styleId)
		const buttonConfigs = [
			configs.hideBookBtn,
			configs.hideTextFieldsBtn,
			configs.hideTtsBtn,
			configs.hideCogBtn,
			configs.hideListBtn
		]
		const selectorsToHide = buttonConfigs
			.filter(config => loadValue(config.key, config.defaultState))
			.map(config => config.selector)
		if (!styleElement && selectorsToHide.length > 0) {
			styleElement = document.createElement('style')
			styleElement.id = styleId
			document.head.appendChild(styleElement)
		}
		if (styleElement) {
			styleElement.textContent =
				selectorsToHide.length > 0 ? `${selectorsToHide.join(', ')} { display: none !important; }` : ''
		}
	}

	const fetchFonts = () =>
		new Promise(resolve =>
			GM_xmlhttpRequest({
				method: 'GET',
				url: FONTS_API_URL,
				onload: r => {
					try {
						const d = JSON.parse(r.responseText)
						const rec = [...RECOMMENDED_FONTS.serif, ...RECOMMENDED_FONTS.sansSerif]
						resolve({
							recommendedSerif: RECOMMENDED_FONTS.serif,
							recommendedSansSerif: RECOMMENDED_FONTS.sansSerif,
							other: d
								.map(f => f.family)
								.filter(f => !rec.includes(f))
								.sort()
						})
					} catch (e) {
						resolve(getFallbackFonts())
					}
				},
				onerror: () => resolve(getFallbackFonts())
			})
		)
	const getFallbackFonts = () => ({
		recommendedSerif: RECOMMENDED_FONTS.serif,
		recommendedSansSerif: RECOMMENDED_FONTS.sansSerif,
		other: ['Georgia', 'Times New Roman', 'Arial', 'Verdana']
	})

	const removeFontStyle = () => {
		log('Removing custom font style elements.')
		const styleElement = document.getElementById('custom-font-styler')
		if (styleElement) styleElement.remove()
		const linkElement = document.getElementById('userscript-font-link')
		if (linkElement) linkElement.remove()
	}

	const applyFontStyle = fontFamily => {
		const isEnabled = loadValue(configs.fontToggle.key, configs.fontToggle.defaultState)
		if (!isEnabled) {
			removeFontStyle()
			return
		}

		log(`Applying font: ${fontFamily}`)
		const primaryFont = fontFamily.split(',')[0].trim()
		const styleId = 'custom-font-styler'
		let styleElement = document.getElementById(styleId)
		if (!styleElement) {
			styleElement = document.createElement('style')
			styleElement.id = styleId
			document.head.appendChild(styleElement)
		}

		const fontUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(primaryFont)}&display=swap`
		let linkElement = document.getElementById('userscript-font-link')
		if (!linkElement) {
			linkElement = document.createElement('link')
			linkElement.id = 'userscript-font-link'
			linkElement.rel = 'stylesheet'
			document.head.appendChild(linkElement)
		}
		linkElement.href = fontUrl

		styleElement.textContent = `${configs.font.selector} { font-family: "${primaryFont}", serif, sans-serif !important; }`
	}

	// --- UI CONFIGURATION PANEL ---
	const createConfigPanel = () => {
		const panelHTML = `<div id="wtr-config-container" class="wtr-panel-container"><div id="wtr-config-overlay" style="display: none;"><div id="wtr-config-panel"><h2>WTR-Lab Enhancer Settings</h2><div id="wtr-config-sections"></div><button id="wtr-config-close-btn" class="wtr-config-button">Close</button></div></div></div>`
		document.body.insertAdjacentHTML('beforeend', panelHTML)
		GM_addStyle(getPanelCSS())

		const sectionsContainer = document.getElementById('wtr-config-sections')

		// Section 1: Layout & Sizing
		const layoutSection = document.createElement('div')
		layoutSection.className = 'wtr-config-section'
		layoutSection.innerHTML = `<label class="wtr-section-title">Layout & Sizing</label>
            <div class="wtr-control-group">
                <label for="wtr-reader-width-input">${configs.reader.label} (px)</label>
                <div class="wtr-config-controls"><button id="wtr-reader-decrease-btn" class="wtr-config-button control">-</button><input type="number" id="wtr-reader-width-input" min="${MIN_WIDTH}" step="10"><button id="wtr-reader-increase-btn" class="wtr-config-button control">+</button><button id="wtr-reader-reset-btn" class="wtr-config-button reset">Reset</button></div>
            </div>
            <div class="wtr-control-group">
                <label for="wtr-nav-width-input">${configs.nav.label} (px)</label>
                <div class="wtr-config-controls"><button id="wtr-nav-decrease-btn" class="wtr-config-button control">-</button><input type="number" id="wtr-nav-width-input" min="${MIN_WIDTH}" step="10"><button id="wtr-nav-increase-btn" class="wtr-config-button control">+</button><button id="wtr-nav-reset-btn" class="wtr-config-button reset">Reset</button></div>
            </div>`
		sectionsContainer.appendChild(layoutSection)

		// Section 2: Font Customization
		const fontSection = document.createElement('div')
		fontSection.className = 'wtr-config-section'
		fontSection.innerHTML = `<label class="wtr-section-title">Font Customization</label>
            <div class="wtr-config-controls checkbox-control"><input type="checkbox" id="wtr-fontToggle-toggle"><label for="wtr-fontToggle-toggle">${configs.fontToggle.label}</label></div>
            <div class="wtr-control-group">
                <label for="wtr-font-select">${configs.font.label}</label>
                <div class="wtr-config-controls font-controls"><select id="wtr-font-select"></select></div>
                <div class="wtr-config-controls font-controls"><div class="wtr-button-group"><button id="wtr-font-refresh-btn" class="wtr-config-button">Refresh</button><button id="wtr-font-reset-btn" class="wtr-config-button reset">Reset</button></div></div>
            </div>`
		sectionsContainer.appendChild(fontSection)

		// Section 3: Element Visibility
		const visibilitySection = document.createElement('div')
		visibilitySection.className = 'wtr-config-section'
		visibilitySection.innerHTML = `<label class="wtr-section-title">Element Visibility</label>
            <div class="wtr-config-controls checkbox-control"><input type="checkbox" id="wtr-navConstraint-toggle"><label for="wtr-navConstraint-toggle">${configs.navConstraint.label}</label></div>
            <div class="wtr-config-controls checkbox-control"><input type="checkbox" id="wtr-blockAddTerm-toggle"><label for="wtr-blockAddTerm-toggle">${configs.blockAddTerm.label}</label></div>
            <div class="wtr-control-group"><label class="wtr-subsection-title">Hide Toolbar Buttons</label><div class="wtr-button-hide-controls"></div></div>`
		const buttonControlsContainer = visibilitySection.querySelector('.wtr-button-hide-controls')
		Object.entries(configs)
			.filter(([n]) => n.startsWith('hide'))
			.forEach(([name, config]) => {
				buttonControlsContainer.insertAdjacentHTML(
					'beforeend',
					`<div class="wtr-config-controls checkbox-control icon-checkbox"><input type="checkbox" id="wtr-${name}-toggle"><label for="wtr-${name}-toggle">${config.iconHTML}<span>${config.label}</span></label></div>`
				)
			})
		sectionsContainer.appendChild(visibilitySection)

		// Section 4: Debug & Advanced
		const debugSection = document.createElement('div')
		debugSection.className = 'wtr-config-section'
		debugSection.innerHTML = `<label class="wtr-section-title">Debug & Advanced</label>
			         <div class="wtr-config-controls checkbox-control"><input type="checkbox" id="wtr-debug-toggle"><label for="wtr-debug-toggle">Enable Debug Logging</label></div>`
		sectionsContainer.appendChild(debugSection)

		populateFontDropdown(getFallbackFonts())
		attachPanelEventListeners()
	}

	const populateFontDropdown = async (initialFontGroups = null) => {
		const fontSelect = document.getElementById('wtr-font-select')
		if (!fontSelect) return
		const currentFont = loadValue(configs.font.key, configs.font.defaultFont)
		fontSelect.innerHTML = ''
		const fontGroups = initialFontGroups || (await fetchFonts())
		const groupLabels = {
			recommendedSerif: 'Recommended (Serif)',
			recommendedSansSerif: 'Recommended (Sans-serif)',
			other: 'All Other Fonts'
		}
		for (const groupKey in fontGroups) {
			if (fontGroups[groupKey].length === 0) continue
			const optgroup = document.createElement('optgroup')
			optgroup.label = groupLabels[groupKey] || 'Fonts'
			fontGroups[groupKey].forEach(font => {
				const option = document.createElement('option')
				option.value = font
				option.textContent = font
				optgroup.appendChild(option)
			})
			fontSelect.appendChild(optgroup)
		}
		fontSelect.value = Object.values(fontGroups).flat().includes(currentFont) ? currentFont : configs.font.defaultFont
	}

	const attachPanelEventListeners = () => {
		document.getElementById('wtr-config-overlay').addEventListener('click', e => {
			if (e.target.id === 'wtr-config-overlay') hideConfigPanel()
		})
		document.getElementById('wtr-config-close-btn').addEventListener('click', hideConfigPanel)

		const updateSetting = (configName, value) => {
			const config = configs[configName]
			saveValue(config.key, value)
			if (configName === 'font') {
				applyFontStyle(value)
				document.getElementById('wtr-font-select').value = value
			} else if (configName === 'fontToggle') {
				updateFontControlsState(value)
				applyFontStyle(loadValue(configs.font.key, configs.font.defaultFont))
			} else if (configName === 'debug') {
				isDebugEnabled = value
				GM_setValue(DEBUG_KEY, isDebugEnabled)
				log(`Debug logging ${isDebugEnabled ? 'ENABLED' : 'DISABLED'}`)
			} else if (configName === 'navConstraint') {
				updateNavConstraint()
			} else if (configName === 'blockAddTerm') {
				updateBlockAddTerm()
			} else if (configName.startsWith('hide')) {
				updateButtonVisibilityStyles()
			} else {
				const validatedWidth = Math.max(MIN_WIDTH, parseInt(value, 10))
				if (isNaN(validatedWidth)) return
				applyWidthStyle(configName, validatedWidth)
				document.getElementById(`wtr-${configName}-width-input`).value = validatedWidth
				saveValue(config.key, validatedWidth)
				if (configName === 'nav') updateNavConstraint()
			}
		}

		for (const [name, config] of Object.entries(configs)) {
			if (name === 'font') {
				const select = document.getElementById('wtr-font-select')
				select.addEventListener('change', () => updateSetting(name, select.value))
				document
					.getElementById('wtr-font-reset-btn')
					.addEventListener('click', () => updateSetting(name, config.defaultFont))
				const refreshBtn = document.getElementById('wtr-font-refresh-btn')
				refreshBtn.addEventListener('click', async () => {
					refreshBtn.textContent = 'Fetching...'
					refreshBtn.disabled = true
					await populateFontDropdown()
					refreshBtn.textContent = 'Refresh'
					refreshBtn.disabled = false
				})
			} else if (['fontToggle', 'navConstraint', 'blockAddTerm', 'debug'].includes(name) || name.startsWith('hide')) {
				const toggle = document.getElementById(`wtr-${name}-toggle`)
				if (toggle) toggle.addEventListener('change', () => updateSetting(name, toggle.checked))
			} else if (['reader', 'nav'].includes(name)) {
				const input = document.getElementById(`wtr-${name}-width-input`)
				document
					.getElementById(`wtr-${name}-increase-btn`)
					.addEventListener('click', () => updateSetting(name, parseInt(input.value, 10) + STEP_WIDTH))
				document
					.getElementById(`wtr-${name}-decrease-btn`)
					.addEventListener('click', () => updateSetting(name, parseInt(input.value, 10) - STEP_WIDTH))
				document
					.getElementById(`wtr-${name}-reset-btn`)
					.addEventListener('click', () => updateSetting(name, config.defaultWidth))
				input.addEventListener('change', () => updateSetting(name, input.value))
			}
		}
	}

	const updateFontControlsState = isEnabled => {
		;['wtr-font-select', 'wtr-font-refresh-btn', 'wtr-font-reset-btn'].forEach(id => {
			document.getElementById(id).disabled = !isEnabled
		})
	}

	const showConfigPanel = () => {
		for (const [name, config] of Object.entries(configs)) {
			if (name === 'font') {
				document.getElementById('wtr-font-select').value = loadValue(config.key, config.defaultFont)
			} else if (name === 'fontToggle') {
				const isEnabled = loadValue(config.key, config.defaultState)
				document.getElementById('wtr-fontToggle-toggle').checked = isEnabled
				updateFontControlsState(isEnabled)
			} else if (['navConstraint', 'blockAddTerm', 'debug'].includes(name) || name.startsWith('hide')) {
				const toggle = document.getElementById(`wtr-${name}-toggle`)
				if (toggle) toggle.checked = loadValue(config.key, config.defaultState)
			} else if (['reader', 'nav'].includes(name)) {
				document.getElementById(`wtr-${name}-width-input`).value = loadValue(config.key, config.defaultWidth)
			}
		}

		document.getElementById('wtr-config-overlay').style.display = 'flex'
	}

	const hideConfigPanel = () => (document.getElementById('wtr-config-overlay').style.display = 'none')

	// --- MODERN CSS FEATURE DETECTION & PROGRESSIVE ENHANCEMENT ---
	const detectCSSFeatures = () => {
		const features = {
			containerQueries: CSS.supports('container-type: inline-size'),
			grid: CSS.supports('display: grid'),
			backdropFilter: CSS.supports('backdrop-filter: blur(1px)'),
			customProperties: CSS.supports('--custom: 0'),
			motionPreferences: window.matchMedia('(prefers-reduced-motion: reduce)'),
			touchDevice: 'ontouchstart' in window || navigator.maxTouchPoints > 0,
			reducedMotion: window.matchMedia('(prefers-reduced-motion: reduce)').matches
		}

		if (isDebugEnabled) {
			console.log('[WTR-Lab Enhancer] CSS Feature Detection:', features)
		}

		return features
	}

	const initializeModernFeatures = () => {
		const features = detectCSSFeatures()

		// Add feature flags to the document for CSS fallbacks
		document.documentElement.setAttribute('data-container-queries', features.containerQueries)
		document.documentElement.setAttribute('data-grid', features.grid)
		document.documentElement.setAttribute('data-backdrop-filter', features.backdropFilter)
		document.documentElement.setAttribute('data-touch-device', features.touchDevice)

		// Initialize modern features if supported
		if (features.containerQueries) {
			log('Container queries supported - enabling responsive container design')
			initializeContainerQueryResponsive()
		}

		if (features.grid) {
			log('CSS Grid supported - enabling modern grid layouts')
			initializeGridLayouts()
		}

		if (features.backdropFilter) {
			log('Backdrop filter supported - enabling blur effects')
			initializeBackdropEffects()
		}

		if (features.touchDevice) {
			log('Touch device detected - optimizing for touch interactions')
			initializeTouchOptimizations()
		}

		// Set up motion preference listeners
		features.motionPreferences.addEventListener('change', e => {
			const isReducedMotion = e.matches
			document.documentElement.setAttribute('data-reduced-motion', isReducedMotion)
			if (isDebugEnabled) {
				console.log('[WTR-Lab Enhancer] Motion preference changed:', isReducedMotion ? 'Reduce motion' : 'Allow motion')
			}
		})

		// Set initial motion preference
		document.documentElement.setAttribute('data-reduced-motion', features.reducedMotion)
	}

	const initializeContainerQueryResponsive = () => {
		const container = document.getElementById('wtr-config-container')
		if (container) {
			container.classList.add('wtr-container-responsive')
		}
	}

	const initializeGridLayouts = () => {
		const controls = document.querySelectorAll('.wtr-config-controls')
		controls.forEach(control => {
			control.classList.add('wtr-grid-enabled')
		})
	}

	const initializeBackdropEffects = () => {
		const overlay = document.getElementById('wtr-config-overlay')
		if (overlay) {
			overlay.classList.add('wtr-backdrop-filter')
		}
	}

	const initializeTouchOptimizations = () => {
		const buttons = document.querySelectorAll('.wtr-config-button')
		buttons.forEach(button => {
			button.classList.add('wtr-touch-optimized')
		})

		const inputs = document.querySelectorAll('input[type="number"], select')
		inputs.forEach(input => {
			input.classList.add('wtr-touch-optimized')
		})
	}

	const getPanelCSS = () => `
	       /* Modern CSS Design System with Fallbacks */
	       :root {
	           /* Container Queries Support Detection */
	           --supports-container-queries: false;
	           
	           /* Design Tokens - Colors */
	           --panel-bg-primary: var(--bs-component-bg, #ffffff);
	           --panel-bg-secondary: var(--bs-tertiary-bg, #f8f9fa);
	           --panel-bg-elevated: var(--bs-body-bg, #ffffff);
	           --panel-text-primary: var(--bs-body-color, #212529);
	           --panel-text-secondary: var(--bs-secondary-color, #6c757d);
	           --panel-border: var(--bs-border-color, #dee2e6);
	           --panel-accent: var(--bs-primary, #0d6efd);
	           --panel-accent-hover: #0b5ed7;
	           --panel-success: #198754;
	           --panel-danger: #dc3545;
	           --panel-warning: #fd7e14;
	           
	           /* Design Tokens - Spacing */
	           --panel-spacing-xs: 0.25rem;
	           --panel-spacing-sm: 0.5rem;
	           --panel-spacing-md: 1rem;
	           --panel-spacing-lg: 1.5rem;
	           --panel-spacing-xl: 2rem;
	           
	           /* Design Tokens - Typography */
	           --panel-font-family: var(--bs-font-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
	           --panel-font-size-xs: 0.75rem;
	           --panel-font-size-sm: 0.875rem;
	           --panel-font-size-md: 1rem;
	           --panel-font-size-lg: 1.125rem;
	           --panel-font-size-xl: 1.25rem;
	           --panel-font-weight-normal: 400;
	           --panel-font-weight-medium: 500;
	           --panel-font-weight-bold: 600;
	           --panel-line-height-tight: 1.2;
	           --panel-line-height-normal: 1.5;
	           --panel-line-height-relaxed: 1.75;
	           
	           /* Design Tokens - Border Radius */
	           --panel-radius-sm: var(--bs-border-radius-sm, 0.25rem);
	           --panel-radius-md: var(--bs-border-radius, 0.375rem);
	           --panel-radius-lg: var(--bs-border-radius-lg, 0.5rem);
	           --panel-radius-xl: 0.75rem;
	           --panel-radius-full: 9999px;
	           
	           /* Design Tokens - Shadows */
	           --panel-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
	           --panel-shadow-md: 0 2px 4px rgba(0, 0, 0, 0.1);
	           --panel-shadow-lg: var(--bs-box-shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1));
	           --panel-shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
	           
	           /* Design Tokens - Transitions */
	           --panel-transition-fast: 0.15s ease;
	           --panel-transition-normal: 0.3s ease;
	           --panel-transition-slow: 0.5s ease;
	           --panel-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	           
	           /* Design Tokens - Z-Index */
	           --panel-z-overlay: 9999;
	           --panel-z-panel: 10000;
	           --panel-z-tooltip: 10001;
	       }

	       /* Container Queries Support Detection */
	       @supports (container-type: inline-size) {
	           :root {
	               --supports-container-queries: true;
	           }
	       }
	       
	       /* Panel Container for Container Queries */
	       #wtr-config-container {
	           container-name: wtr-panel;
	           container-type: inline-size;
	           container-index: 0;
	       }
	       
	       /* Enhanced panel styling with design tokens */
	       #wtr-config-overlay {
	           position: fixed;
	           top: 0;
	           left: 0;
	           width: 100%;
	           height: 100%;
	           background-color: rgba(0, 0, 0, 0.7);
	           z-index: var(--panel-z-overlay);
	           display: flex;
	           justify-content: center;
	           align-items: center;
	           backdrop-filter: blur(4px);
	           contain: layout style paint;
	       }
	       
	       #wtr-config-panel {
	           background: var(--panel-bg-primary);
	           color: var(--panel-text-primary);
	           padding: var(--panel-spacing-xl);
	           border-radius: var(--panel-radius-lg);
	           width: 90%;
	           max-width: 550px;
	           box-shadow: var(--panel-shadow-xl);
	           font-family: var(--panel-font-family);
	           display: flex;
	           flex-direction: column;
	           gap: var(--panel-spacing-lg);
	           max-height: 90vh;
	           border: 1px solid var(--panel-border);
	           
	           /* Performance optimizations */
	           contain: layout style paint;
	           will-change: transform, opacity;
	           transform: translateZ(0);
	       }
        /* Enhanced Typography with Design Tokens */
        #wtr-config-panel h2 {
            margin: 0;
            text-align: center;
            font-weight: var(--panel-font-weight-medium);
            font-size: var(--panel-font-size-xl);
            line-height: var(--panel-line-height-tight);
            color: var(--panel-text-primary);
            flex-shrink: 0;
        }
        
        /* Enhanced Sections with Containment */
        #wtr-config-panel #wtr-config-sections {
            overflow-y: auto;
            flex-grow: 1;
            display: flex;
            flex-direction: column;
            gap: var(--panel-spacing-lg);
            padding-right: var(--panel-spacing-md);
            margin-right: calc(-1 * var(--panel-spacing-md));
            
            /* Performance optimization */
            contain: layout style;
        }
        
        #wtr-config-panel .wtr-config-section {
            display: flex;
            flex-direction: column;
            gap: var(--panel-spacing-lg);
            padding: var(--panel-spacing-lg);
            border: 1px solid var(--panel-border);
            border-radius: var(--panel-radius-lg);
            background: var(--panel-bg-secondary);
            
            /* Performance optimization */
            contain: layout style paint;
        }
        
        #wtr-config-panel .wtr-control-group {
            display: flex;
            flex-direction: column;
            gap: var(--panel-spacing-sm);
        }
        
        /* Modern Control Layout with Grid Fallback */
        #wtr-config-panel .wtr-config-controls {
            display: flex;
            gap: var(--panel-spacing-sm);
            align-items: center;
            flex-wrap: wrap;
        }
        
        #wtr-config-panel .wtr-config-controls.font-controls {
            flex-wrap: nowrap;
            display: grid;
            grid-template-columns: 1fr;
            gap: var(--panel-spacing-sm);
        }
        
        #wtr-config-panel .wtr-config-controls.checkbox-control {
            justify-content: flex-start;
            cursor: pointer;
            padding: var(--panel-spacing-sm) 0;
            display: grid;
            grid-template-columns: auto 1fr;
            gap: var(--panel-spacing-sm);
            cursor: pointer;
        }
        
        #wtr-config-panel .wtr-config-controls.checkbox-control label {
            user-select: none;
        }
        
        #wtr-config-panel .wtr-config-controls.checkbox-control input {
            margin-right: var(--panel-spacing-sm);
        }
        
        /* Enhanced Form Controls with Touch Optimization */
        #wtr-config-panel input[type="number"],
        #wtr-config-panel select {
            flex-grow: 1;
            min-width: 100px;
            min-height: 44px; /* Touch target size */
            text-align: center;
            background: var(--panel-bg-secondary);
            color: var(--panel-text-primary);
            border: 1px solid var(--panel-border);
            border-radius: var(--panel-radius-md);
            padding: var(--panel-spacing-sm) var(--panel-spacing-md);
            font-family: var(--panel-font-family);
            font-size: var(--panel-font-size-sm);
            
            /* Performance */
            contain: layout style;
        }
        
        #wtr-config-panel select:disabled {
            background: var(--panel-bg-secondary);
            color: var(--panel-text-secondary);
            cursor: not-allowed;
        }
        
        /* Modern Button Layout */
        #wtr-config-panel .wtr-button-group {
            display: grid;
            grid-auto-flow: column;
            gap: var(--panel-spacing-sm);
            justify-content: end;
            flex-shrink: 0;
        }
        
        /* Enhanced Button Styling with Motion Controls */
        #wtr-config-panel .wtr-config-button {
            min-height: 44px; /* iOS guideline */
            min-width: 44px;
            padding: var(--panel-spacing-sm) var(--panel-spacing-md);
            border: none;
            border-radius: var(--panel-radius-md);
            cursor: pointer;
            background-color: var(--panel-accent);
            color: white;
            font-weight: var(--panel-font-weight-bold);
            font-size: var(--panel-font-size-sm);
            flex-shrink: 0;
            transition: background-color var(--panel-transition-fast),
                        transform var(--panel-transition-fast);
            
            /* Touch optimization */
            touch-action: manipulation;
            -webkit-tap-highlight-color: transparent;
            
            /* Performance */
            contain: layout style paint;
            will-change: transform;
            transform: translateZ(0);
        }
        
        #wtr-config-panel .wtr-config-button:hover,
        #wtr-config-panel .wtr-config-button:focus-visible {
            background-color: var(--panel-accent-hover);
            transform: translateY(-1px);
        }
        
        #wtr-config-panel .wtr-config-button:active {
            transform: translateY(0);
        }
        
        #wtr-config-panel .wtr-config-button:disabled {
            background-color: var(--panel-text-secondary);
            cursor: not-allowed;
            transform: none;
        }
        
        #wtr-config-panel .wtr-config-button.control {
            width: 44px;
            aspect-ratio: 1;
        }
        
        #wtr-config-panel .wtr-config-button.reset {
            background-color: var(--panel-danger);
        }
        
        #wtr-config-panel #wtr-config-close-btn {
            background-color: var(--panel-text-secondary);
            align-self: center;
            width: 100px;
            flex-shrink: 0;
        }
        
        /* Enhanced Typography */
        #wtr-config-panel .wtr-section-title {
            font-weight: var(--panel-font-weight-medium);
            text-align: center;
            margin-bottom: var(--panel-spacing-sm);
            display: block;
            font-size: var(--panel-font-size-lg);
            color: var(--panel-text-primary);
        }
        
        #wtr-config-panel .wtr-subsection-title {
            font-weight: var(--panel-font-weight-medium);
            text-align: left;
            margin-top: var(--panel-spacing-lg);
            display: block;
            border-top: 1px solid var(--panel-border);
            padding-top: var(--panel-spacing-lg);
            color: var(--panel-text-primary);
        }
        
        /* Enhanced Button Hide Controls Layout */
        #wtr-config-panel .wtr-button-hide-controls {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: var(--panel-spacing-md);
            justify-content: flex-start;
        }
        
        #wtr-config-panel .icon-checkbox label {
            display: flex;
            align-items: center;
            gap: var(--panel-spacing-sm);
        }
        
        #wtr-config-panel .icon-checkbox svg {
            width: 20px;
            height: 20px;
            stroke: currentColor;
            fill: none;
        }
        
        #wtr-config-panel .icon-checkbox svg:has(use[href*="text_fields"], use[href*="tts"], use[href*="list"]) {
            fill: currentColor;
            stroke: none;
        }
        
        /* Motion Preference Handling - WCAG 2.2/2.3 Compliance */
        @media (prefers-reduced-motion: reduce) {
            #wtr-config-overlay,
            #wtr-config-panel,
            .wtr-config-button {
                transition: none !important;
                animation: none !important;
                transform: none !important;
            }
        }
        
        /* Enable motion for users who haven't disabled it */
        @supports not (prefers-reduced-motion: reduce) {
            #wtr-config-panel {
                transition: transform var(--panel-transition-normal) var(--panel-timing-function),
                           opacity var(--panel-transition-normal) ease;
                transform: scale(0.95);
            }
            
            #wtr-config-panel.visible {
                transform: scale(1);
            }
        }
        
        /* Container Query Responsive Design */
        @container wtr-panel (max-width: 480px) {
            #wtr-config-panel {
                width: 95%;
                padding: var(--panel-spacing-lg);
            }
            
            .wtr-config-controls {
                flex-direction: column;
                gap: var(--panel-spacing-xs);
            }
            
            .wtr-config-controls.font-controls {
                flex-direction: column;
                align-items: stretch;
            }
            
            .wtr-button-group {
                margin-left: 0;
                justify-content: center;
                grid-auto-flow: row;
            }
            
            .wtr-button-hide-controls {
                grid-template-columns: 1fr;
                gap: var(--panel-spacing-sm);
            }
        }
        
        @container wtr-panel (max-width: 360px) {
            #wtr-config-panel {
                width: 98%;
                margin: var(--panel-spacing-md);
                padding: var(--panel-spacing-md);
            }
            
            .wtr-config-section {
                padding: var(--panel-spacing-md);
            }
            
            .wtr-config-button {
                min-width: 40px;
            }
        }
        
        /* Grid Layout Fallbacks */
        @supports not (display: grid) {
            .wtr-config-controls {
                display: flex;
                flex-wrap: wrap;
            }
            
            .wtr-button-group {
                display: flex;
                flex-wrap: wrap;
            }
            
            .wtr-button-hide-controls {
                display: flex;
                flex-wrap: wrap;
            }
        }
        
        /* Container Queries Fallback */
        @supports not (container-type: inline-size) {
            #wtr-config-container {
                /* Fallback - styles remain as above for viewport-based responsiveness */
            }
            
            /* Legacy media queries as fallback */
            @media (max-width: 480px) {
                #wtr-config-panel {
                    width: 95%;
                    padding: var(--panel-spacing-lg);
                }
                
                .wtr-config-controls {
                    flex-direction: column;
                    gap: var(--panel-spacing-xs);
                }
            }
        }
        
        /* Backdrop Filter Fallback */
        @supports not (backdrop-filter: blur(1px)) {
            #wtr-config-overlay {
                background-color: rgba(0, 0, 0, 0.8);
            }
        }
        
        /* Touch-specific enhancements */
        @media (hover: none) and (pointer: coarse) {
            .wtr-config-button {
                min-height: 48px;
                padding: var(--panel-spacing-md) var(--panel-spacing-lg);
                font-size: var(--panel-font-size-md);
            }
            
            .wtr-config-controls input[type="number"],
            .wtr-config-controls select {
                min-height: 48px;
                font-size: var(--panel-font-size-md);
            }
        }
    `

	// --- INITIALIZATION ---
	const init = async () => {
		log('Initializing script...')
		syncDebugState() // Sync debug state from stored values
		createConfigPanel()
		applyWidthStyle('reader', loadValue(configs.reader.key, configs.reader.defaultWidth))
		applyWidthStyle('nav', loadValue(configs.nav.key, configs.nav.defaultWidth))
		updateNavConstraint()
		updateBlockAddTerm()
		updateButtonVisibilityStyles()
		window.addEventListener('resize', updateNavConstraint)
		const fontGroups = await fetchFonts()
		const allAvailableFonts = Object.values(fontGroups).flat()
		let initialFont = loadValue(configs.font.key, configs.font.defaultFont)
		if (!allAvailableFonts.includes(initialFont)) {
			initialFont = configs.font.defaultFont
			saveValue(configs.font.key, initialFont)
		}
		applyFontStyle(initialFont)
		populateFontDropdown(fontGroups)
		GM_registerMenuCommand('Configure Settings', showConfigPanel)

		// Initialize modern CSS features with progressive enhancement
		initializeModernFeatures()

		log('Initialization complete.')
	}

	init()
})()