├── .gitignore ├── assets ├── banner.png ├── screenshot-home.png ├── modrn-glass-preview.png └── screenshot-player.png ├── plugins ├── horizontal-navigation.plugin.js ├── enhanced-player.plugin.js ├── enhanced-titlebar.plugin.js └── hero-div.plugin.js ├── README.md └── themes └── liquid-glass.theme.css /.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fxy6969/Stremio-Glass-Theme/HEAD/assets/banner.png -------------------------------------------------------------------------------- /assets/screenshot-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fxy6969/Stremio-Glass-Theme/HEAD/assets/screenshot-home.png -------------------------------------------------------------------------------- /assets/modrn-glass-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fxy6969/Stremio-Glass-Theme/HEAD/assets/modrn-glass-preview.png -------------------------------------------------------------------------------- /assets/screenshot-player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fxy6969/Stremio-Glass-Theme/HEAD/assets/screenshot-player.png -------------------------------------------------------------------------------- /plugins/horizontal-navigation.plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name Horizontal Navigation 3 | * @description Moves your vertical navigation bar to a horizontal position. 4 | * @version 1.0.0 5 | * @author Fxy 6 | */ 7 | 8 | let cachedNavbars = new Map(); 9 | 10 | function moveNavbar(verticalNavbar, targetParent) { 11 | if (!verticalNavbar || !targetParent) return; 12 | if (verticalNavbar.parentElement !== targetParent) { 13 | verticalNavbar.style.visibility = "hidden"; 14 | targetParent.appendChild(verticalNavbar); 15 | verticalNavbar.style.visibility = "visible"; 16 | } 17 | } 18 | 19 | function fixAllNavbars() { 20 | const verticalNavbars = Array.from(document.querySelectorAll('[class*="vertical-nav-bar"]')); 21 | 22 | verticalNavbars.forEach(vNav => { 23 | if (!cachedNavbars.has(vNav) || !document.body.contains(cachedNavbars.get(vNav))) { 24 | cachedNavbars.set(vNav, vNav.parentElement); 25 | } 26 | const originalParent = cachedNavbars.get(vNav); 27 | 28 | const hNav = vNav.closest('div')?.querySelector('[class*="horizontal-nav-bar"]'); 29 | const horizontalVisible = hNav?.offsetParent !== null; 30 | const originalVisible = originalParent?.offsetParent !== null; 31 | 32 | if (horizontalVisible) { 33 | moveNavbar(vNav, hNav); 34 | hNav.querySelectorAll("a").forEach(link => { 35 | link.querySelector("svg")?.remove(); 36 | const label = link.querySelector("div"); 37 | if (label) label.className = "nav-label"; 38 | }); 39 | } else if (!horizontalVisible && originalVisible) { 40 | moveNavbar(vNav, originalParent); 41 | } 42 | }); 43 | } 44 | 45 | // fallback 46 | let timeoutId; 47 | const observer = new MutationObserver(() => { 48 | clearTimeout(timeoutId); 49 | timeoutId = setTimeout(fixAllNavbars, 50); 50 | }); 51 | observer.observe(document.body, { childList: true, subtree: true, attributes: true }); 52 | setInterval(fixAllNavbars, 20); 53 | 54 | // Initial call 55 | fixAllNavbars(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Modern Glass – Stremio Theme + QoL Enhancements 2 | 3 | ![Modern Glass Banner](https://github.com/user-attachments/assets/fd9d1d76-6c59-47fb-acfb-75433ba382bc) 4 | 5 | [![Reddit Community](https://img.shields.io/reddit/subreddit-subscribers/StremioMods?style=social&logo=reddit)](https://www.reddit.com/r/StremioMods/) 6 | [![Join Discord](https://img.shields.io/badge/Discord-Join%20Us-5865F2?style=flat&logo=discord&logoColor=white)](#) *(Coming soon)* 7 | 8 | **Modern Glass** is a complete visual overhaul for Stremio Enhanced. 9 | It brings a sleek, glass-like aesthetic combined with powerful quality-of-life improvements for a truly modern streaming experience. 10 | 11 | --- 12 | 13 | ## ✨ Features 14 | 15 | ### 🎨 Theme Highlights 16 | - 🌟 **Glass-like transparent interface** for a clean, modern look 17 | - 🖼️ **High-quality, wide cover art** for movies & series 18 | - 🧩 **Refined UI layout** – better spacing, typography, and animations 19 | 20 | --- 21 | 22 | ### 🔧 Quality of Life Plugins 23 | 24 | | Plugin | Description | 25 | |-------|-------------| 26 | | **horizontal-navigation.plugin.js** | Moves the vertical navigation bar to a **horizontal** position | 27 | | **enhancedcovers.plugin.js** | Widens and improves cover images in the library | 28 | | **enhancedvideoplayer.plugin.js** | Adds extra features & a redesigned look to the video player | 29 | | **enhancedtitlebar.plugin.js** | Displays additional information in the title bar | 30 | | **dynamichero.plugin.js** | Netflix-style **rotating hero banner** on the homepage | 31 | | **moveprogressbar.plugin.js** | Moves the watch progress bar inside the title container | 32 | | **Picture In Picture** | Updated and brought back the Picture In Picture feature | 33 | 34 | --- 35 | 36 | ## 📷 Screenshots 37 | 38 | | Home Page | Titles | Video Player | 39 | |----------|-------------|-------------| 40 | | ![Home Page](https://github.com/user-attachments/assets/fd9d1d76-6c59-47fb-acfb-75433ba382bc) | ![Titles](https://github.com/user-attachments/assets/fbc8a242-f89a-4fe7-a074-c9f15b517873) | ![Video Player](https://github.com/user-attachments/assets/eab96818-e4cf-488f-b9f9-bc16dfbdd7e2) | 41 | 42 | --- 43 | 44 | ## 📥 Installation 45 | 46 | You have **two ways** to install Modern Glass: 47 | 48 | 1. **Via Stremio Enhanced Marketplace (Recommended):** 49 | - Open the **Stremio Enhanced Marketplace** inside Stremio -> Settings -> Scroll all the way down 50 | - Search for **Modern Glass** and its Plugins Tagged with **Modern Glass** 51 | - Install it 52 | 53 | 2. **Direct Download / Manual Installation:** 54 | - Download the latest release from the [Releases Page](#) 55 | - Install Stremio Enhanced (required) 56 | - Drag and drop the downloaded files into your Stremio plugin/theme folder 57 | - Restart Stremio to apply changes 58 | 59 | --- 60 | 61 | ## 🖥️ Requirements 62 | 63 | - Stremio Enhanced installation 64 | - All included plugins (bundled in the release package) 65 | 66 | --- 67 | 68 | ## 🧪 Known Issues 69 | 70 | Modern Glass is actively maintained and evolving. 71 | You may encounter occasional bugs or unexpected behavior — please report them via the **Issues tab**. 72 | 73 | --- 74 | 75 | ## 🌐 Join the Community 76 | 77 | Want to discuss Stremio mods, share your own plugins, get coding help, or just hang out with other creators? 78 | Join our growing community: 79 | 80 | - **Reddit:** [r/StremioMods](https://www.reddit.com/r/StremioMods/) 81 | - **Discord:** *(Coming soon – we’ll add the invite link here!)* 82 | 83 | This community is open to **everyone** — plugin creators, theme designers, and users who want to learn, share, and improve the Stremio experience together. 84 | 85 | --- 86 | 87 | ## 🤝 Contributing 88 | 89 | We welcome community contributions! 90 | 91 | 1. Fork the repo 92 | 2. Create a feature branch 93 | 3. Commit your changes 94 | 4. Push and submit a PR 95 | 96 | --- 97 | 98 | ## ⚠️ Disclaimer 99 | 100 | - Not officially affiliated with Stremio 101 | - This is an ongoing project – code quality and structure will improve over time 102 | - Feedback and suggestions are highly appreciated ❤️ 103 | -------------------------------------------------------------------------------- /plugins/enhanced-player.plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name Enhanced Video Player 3 | * @description Enhances the video player with additional features and designs. 4 | * @version 1.0.0 5 | * @author Fxy 6 | */ 7 | class EnhancedPlayer { 8 | constructor() { 9 | this.init(); 10 | } 11 | 12 | init() { 13 | this.splitAndMoveTitles(); 14 | this.addCustomButton(); 15 | setTimeout(() => { 16 | this.splitAndMoveTitles(); 17 | this.addCustomButton(); 18 | }, 500); 19 | const observer = new MutationObserver(() => { 20 | this.splitAndMoveTitles(); 21 | this.addCustomButton(); 22 | }); 23 | observer.observe(document.body, { childList: true, subtree: true }); 24 | } 25 | 26 | addCustomButton() { 27 | const controlBarSelectors = [ 28 | '.control-bar-buttons-menu-container-M6L0_', 29 | "[class*='control-bar-buttons']", 30 | "[class*='control-bar'] [class*='buttons']", 31 | ".control-bar-container-xsWA7 [class*='buttons']" 32 | ]; 33 | 34 | let controlBarContainer = null; 35 | for (const selector of controlBarSelectors) { 36 | controlBarContainer = document.querySelector(selector); 37 | if (controlBarContainer) break; 38 | } 39 | 40 | if (!controlBarContainer) { 41 | return; 42 | } 43 | 44 | if (controlBarContainer.querySelector('.custom-enhanced-button')) { 45 | return; 46 | } 47 | 48 | const customButton = document.createElement('div'); 49 | customButton.tabIndex = -1; 50 | customButton.className = 'control-bar-button-FQUsj button-container-zVLH6 custom-enhanced-button'; 51 | 52 | customButton.innerHTML = ` 53 | 54 | `; 55 | 56 | customButton.addEventListener('click', (e) => { 57 | e.stopPropagation(); 58 | this.handleCustomButtonClick(); 59 | }); 60 | 61 | customButton.addEventListener('mouseenter', () => { 62 | customButton.style.opacity = '0.8'; 63 | }); 64 | 65 | customButton.addEventListener('mouseleave', () => { 66 | customButton.style.opacity = '1'; 67 | }); 68 | 69 | controlBarContainer.insertAdjacentElement("afterbegin", customButton); 70 | } 71 | 72 | handleCustomButtonClick() { 73 | if (document.pictureInPictureElement) { 74 | document.exitPictureInPicture().catch(err => { 75 | console.error('Failed to exit Picture-in-Picture:', err); 76 | }); 77 | } else { 78 | const videoElement = document.querySelector('video'); 79 | if (videoElement) { 80 | videoElement.requestPictureInPicture().catch(err => { 81 | console.error('Failed to enter Picture-in-Picture:', err); 82 | }); 83 | } 84 | } 85 | } 86 | 87 | splitAndMoveTitles() { 88 | const titleSelectors = [ 89 | "h2.title-DGh6h", 90 | "#app > div.router-_65XU.routes-container > div:nth-child(3) > div.route-content > div > nav > h2", // Original selector 91 | ]; 92 | 93 | let titleElement = null; 94 | for (const selector of titleSelectors) { 95 | titleElement = document.querySelector(selector); 96 | if (titleElement && this.isValidTitle(titleElement.textContent)) { 97 | break; 98 | } 99 | } 100 | 101 | const containerSelectors = [ 102 | "#app > div.router-_65XU.routes-container > div:nth-child(2) > div.route-content > div > div.layer-qalDW.control-bar-layer-m2jto.control-bar-container-xsWA7", // Original 103 | "div[class*='control-bar-container']", 104 | "div[class*='control-bar-layer']", 105 | ".video-player-controls", 106 | ]; 107 | 108 | let targetContainer = null; 109 | for (const selector of containerSelectors) { 110 | targetContainer = document.querySelector(selector); 111 | if (targetContainer) break; 112 | } 113 | 114 | if (!titleElement || !targetContainer) { 115 | return; 116 | } 117 | 118 | if (targetContainer.querySelector('.custom-series-name') || targetContainer.querySelector('.custom-movie-title')) { 119 | return; 120 | } 121 | 122 | const titleText = titleElement.textContent.trim(); 123 | const match = titleText.match(/^(.+?): (.+?) - (.+?) \((\d+x\d+)\)$/); 124 | 125 | if (!match) { 126 | const movieDiv = document.createElement('div'); 127 | movieDiv.className = 'custom-series-name'; 128 | movieDiv.textContent = titleText; 129 | 130 | targetContainer.insertBefore(movieDiv, targetContainer.firstChild); 131 | titleElement.style.display = 'none'; 132 | return; 133 | } 134 | 135 | // Handle series title 136 | const [, seriesName, episodeTitle, description, seasonEpisode] = match; 137 | 138 | const seriesDiv = document.createElement('div'); 139 | seriesDiv.className = 'custom-series-name'; 140 | seriesDiv.textContent = `${description} (${seasonEpisode})`; 141 | 142 | const episodeDiv = document.createElement('div'); 143 | episodeDiv.className = 'custom-episode-title'; 144 | episodeDiv.textContent = `${seriesName}: ${episodeTitle}`; 145 | 146 | targetContainer.insertBefore(seriesDiv, targetContainer.firstChild); 147 | targetContainer.insertBefore(episodeDiv, seriesDiv.nextSibling); 148 | 149 | titleElement.style.display = 'none'; 150 | } 151 | 152 | isValidTitle(text) { 153 | if (text && text.includes(':') && text.includes('(') && text.includes('x')) { 154 | return true; 155 | } 156 | if (text && text.trim().length > 0 && !text.includes('x')) { 157 | return true; 158 | } 159 | return false; 160 | } 161 | } 162 | 163 | new EnhancedPlayer(); -------------------------------------------------------------------------------- /plugins/enhanced-titlebar.plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name Enhanced Title Bar 3 | * @description Enhances the title bar with additional information. 4 | * @version 1.0.0 5 | * @author Fxy 6 | */ 7 | 8 | const CONFIG = { 9 | apiBase: 'https://v3-cinemeta.strem.io/meta', 10 | timeout: 5000, 11 | updateInterval: 2000 12 | }; 13 | 14 | const metadataCache = new Map(); 15 | 16 | function injectStyles() { 17 | if (document.getElementById('enhanced-title-bar-styles')) return; 18 | 19 | const style = document.createElement('style'); 20 | style.id = 'enhanced-title-bar-styles'; 21 | style.textContent = ` 22 | .enhanced-title-bar { 23 | position: relative !important; 24 | padding: 5px 4px !important; 25 | padding-right: 10px !important; 26 | overflow: hidden !important; 27 | max-width: 400px !important; 28 | transform: translateZ(0) !important; 29 | } 30 | 31 | .enhanced-title { 32 | font-size: 16px !important; 33 | font-weight: 600 !important; 34 | color: #ffffff !important; 35 | margin-bottom: 8px !important; 36 | line-height: 1.3 !important; 37 | } 38 | 39 | .enhanced-metadata { 40 | display: flex !important; 41 | align-items: center !important; 42 | gap: 8px !important; 43 | flex-wrap: wrap !important; 44 | font-size: 12px !important; 45 | color: #999 !important; 46 | } 47 | 48 | .enhanced-metadata-item { 49 | display: inline-flex !important; 50 | align-items: center !important; 51 | gap: 4px !important; 52 | } 53 | 54 | .enhanced-separator { 55 | color: #666 !important; 56 | margin: 0 4px !important; 57 | } 58 | 59 | .enhanced-loading { 60 | background: linear-gradient(90deg, #333 25%, #444 50%, #333 75%) !important; 61 | background-size: 200% 100% !important; 62 | animation: enhanced-loading 1.5s infinite !important; 63 | border-radius: 3px !important; 64 | height: 12px !important; 65 | width: 60px !important; 66 | display: inline-block !important; 67 | } 68 | 69 | @keyframes enhanced-loading { 70 | 0% { background-position: 200% 0; } 71 | 100% { background-position: -200% 0; } 72 | } 73 | `; 74 | document.head.appendChild(style); 75 | } 76 | 77 | async function getMetadata(id, type) { 78 | const cacheKey = `${type}-${id}`; 79 | 80 | if (metadataCache.has(cacheKey)) { 81 | return metadataCache.get(cacheKey); 82 | } 83 | 84 | try { 85 | const controller = new AbortController(); 86 | const timeoutId = setTimeout(() => controller.abort(), CONFIG.timeout); 87 | 88 | const response = await fetch( 89 | `${CONFIG.apiBase}/${type}/${id}.json`, 90 | { signal: controller.signal } 91 | ); 92 | 93 | clearTimeout(timeoutId); 94 | 95 | if (!response.ok) { 96 | throw new Error(`HTTP error! status: ${response.status}`); 97 | } 98 | 99 | const data = await response.json(); 100 | const meta = data.meta; 101 | 102 | if (!meta) return null; 103 | 104 | const metadata = { 105 | title: meta.name || meta.title, 106 | year: meta.year ? meta.year.toString() : null, 107 | rating: meta.imdbRating ? meta.imdbRating.toString() : null, 108 | genres: Array.isArray(meta.genre) ? meta.genre : (Array.isArray(meta.genres) ? meta.genres : []), 109 | runtime: meta.runtime || null, 110 | type: meta.type || type, 111 | poster: meta.poster, 112 | background: meta.background 113 | }; 114 | 115 | console.log(`Fetched metadata for ${id}:`, metadata); 116 | metadataCache.set(cacheKey, metadata); 117 | return metadata; 118 | 119 | } catch (error) { 120 | console.log(`Failed to fetch ${id}:`, error); 121 | return null; 122 | } 123 | } 124 | 125 | function extractMediaInfo(titleText, element) { 126 | console.log('Extracting from element:', element); 127 | 128 | const allImages = element.querySelectorAll('img'); 129 | console.log('Found images:', allImages.length); 130 | 131 | for (let img of allImages) { 132 | console.log('Checking image src:', img.src); 133 | if (img.src && img.src.includes('tt')) { 134 | const imdbMatch = img.src.match(/tt\d{7,}/); 135 | if (imdbMatch) { 136 | console.log('Found IMDb ID:', imdbMatch[0]); 137 | return { id: imdbMatch[0], type: 'series' }; 138 | } 139 | } 140 | } 141 | 142 | const parent = element.parentElement; 143 | if (parent) { 144 | const parentImages = parent.querySelectorAll('img'); 145 | for (let img of parentImages) { 146 | console.log('Checking parent image src:', img.src); 147 | if (img.src && img.src.includes('tt')) { 148 | const imdbMatch = img.src.match(/tt\d{7,}/); 149 | if (imdbMatch) { 150 | console.log('Found IMDb ID in parent:', imdbMatch[0]); 151 | return { id: imdbMatch[0], type: 'series' }; 152 | } 153 | } 154 | } 155 | } 156 | 157 | console.log('No IMDb ID found, using fallback'); 158 | return { id: 'tt0000000', type: 'movie' }; 159 | } 160 | 161 | function createMetadataElements(metadata) { 162 | const elements = []; 163 | 164 | if (metadata.rating) { 165 | const rating = document.createElement('span'); 166 | rating.className = 'enhanced-metadata-item enhanced-rating'; 167 | rating.textContent = `★ ${metadata.rating}`; 168 | elements.push(rating); 169 | } 170 | 171 | if (metadata.year) { 172 | const year = document.createElement('span'); 173 | year.className = 'enhanced-metadata-item'; 174 | year.textContent = metadata.year; 175 | elements.push(year); 176 | } 177 | 178 | if (metadata.genres && metadata.genres.length > 0) { 179 | const genres = document.createElement('span'); 180 | genres.className = 'enhanced-metadata-item'; 181 | genres.textContent = metadata.genres.slice(0, 3).join(', '); 182 | elements.push(genres); 183 | } 184 | 185 | return elements; 186 | } 187 | 188 | async function enhanceTitleBar(titleBarElement) { 189 | if (titleBarElement.classList.contains('enhanced-title-bar')) { 190 | return; 191 | } 192 | 193 | const titleElement = titleBarElement.querySelector('.title-label-VnEAc') || 194 | titleBarElement.querySelector('[class*="title-label"]') || 195 | titleBarElement.querySelector('[class*="title"]'); 196 | 197 | if (!titleElement) { 198 | return; 199 | } 200 | 201 | const originalTitle = titleElement.textContent.trim(); 202 | 203 | if (!originalTitle || originalTitle.length < 1) { 204 | return; 205 | } 206 | 207 | titleBarElement.classList.add('enhanced-title-bar'); 208 | 209 | const originalHTML = titleBarElement.innerHTML; 210 | titleBarElement.dataset.originalHtml = originalHTML; 211 | 212 | const mediaInfo = extractMediaInfo(originalTitle, titleBarElement); 213 | 214 | titleBarElement.innerHTML = ''; 215 | 216 | const title = document.createElement('div'); 217 | title.className = 'enhanced-title'; 218 | title.textContent = originalTitle; 219 | titleBarElement.appendChild(title); 220 | 221 | const metadataContainer = document.createElement('div'); 222 | metadataContainer.className = 'enhanced-metadata'; 223 | 224 | const loading = document.createElement('div'); 225 | loading.className = 'enhanced-loading'; 226 | metadataContainer.appendChild(loading); 227 | 228 | titleBarElement.appendChild(metadataContainer); 229 | 230 | try { 231 | const metadata = await getMetadata(mediaInfo.id, mediaInfo.type); 232 | 233 | if (metadata) { 234 | if (metadata.title && metadata.title !== originalTitle) { 235 | title.textContent = metadata.title; 236 | } 237 | 238 | metadataContainer.innerHTML = ''; 239 | 240 | const elements = createMetadataElements(metadata); 241 | elements.forEach((element, index) => { 242 | metadataContainer.appendChild(element); 243 | if (index < elements.length - 2) { 244 | const separator = document.createElement('span'); 245 | separator.className = 'enhanced-separator'; 246 | separator.textContent = '•'; 247 | metadataContainer.appendChild(separator); 248 | } 249 | }); 250 | } else { 251 | metadataContainer.innerHTML = ''; 252 | 253 | const fallback = document.createElement('span'); 254 | fallback.className = 'enhanced-metadata-item'; 255 | fallback.textContent = ''; 256 | fallback.style.color = '#999'; 257 | metadataContainer.appendChild(fallback); 258 | } 259 | } catch (error) { 260 | metadataContainer.innerHTML = ''; 261 | 262 | const errorText = document.createElement('span'); 263 | errorText.className = 'enhanced-metadata-item'; 264 | errorText.textContent = 'Loading failed'; 265 | errorText.style.color = '#666'; 266 | metadataContainer.appendChild(errorText); 267 | } 268 | } 269 | 270 | function enhanceAllTitleBars() { 271 | const selectors = [ 272 | '.title-bar-container-1Ba0x', 273 | '[class*="title-bar-container"]', 274 | '[class*="titleBarContainer"]', 275 | '[class*="title-container"]', 276 | '[class*="media-title"]' 277 | ]; 278 | 279 | selectors.forEach(selector => { 280 | const elements = document.querySelectorAll(selector); 281 | elements.forEach(element => { 282 | enhanceTitleBar(element).catch(() => {}); 283 | }); 284 | }); 285 | } 286 | 287 | function init() { 288 | injectStyles(); 289 | enhanceAllTitleBars(); 290 | 291 | setInterval(() => { 292 | enhanceAllTitleBars(); 293 | }, CONFIG.updateInterval); 294 | 295 | if (typeof MutationObserver !== 'undefined') { 296 | const observer = new MutationObserver((mutations) => { 297 | let shouldCheck = false; 298 | mutations.forEach(mutation => { 299 | if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { 300 | shouldCheck = true; 301 | } 302 | }); 303 | 304 | if (shouldCheck) { 305 | setTimeout(enhanceAllTitleBars, 100); 306 | } 307 | }); 308 | 309 | observer.observe(document.body, { 310 | childList: true, 311 | subtree: true 312 | }); 313 | } 314 | } 315 | 316 | if (document.readyState === 'loading') { 317 | document.addEventListener('DOMContentLoaded', init); 318 | } else { 319 | init(); 320 | } 321 | 322 | setTimeout(init, 100); -------------------------------------------------------------------------------- /plugins/hero-div.plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name Dynamic Hero 3 | * @description Netflix-style rotating hero banner. 4 | * @version 1.0.1 5 | * @author Fxy 6 | */ 7 | 8 | (function() { 9 | if (window.heroObserver) { 10 | window.heroObserver.disconnect(); 11 | delete window.heroObserver; 12 | } 13 | 14 | let heroTitles = []; 15 | let currentIndex = 0; 16 | let autoRotateInterval; 17 | let isAutoRotating = true; 18 | 19 | const MAX_RETRIES = 2; 20 | const ROTATION_INTERVAL = 8000; 21 | 22 | let heroState = { 23 | isInitializing: false, 24 | initializationComplete: false, 25 | retryCount: 0, 26 | titlesReady: false, 27 | lastKnownHash: window.location.hash 28 | }; 29 | 30 | const fallbackTitles = [ 31 | { 32 | id: "tt0903747", 33 | title: "Breaking Bad", 34 | background: "https://images.metahub.space/background/large/tt0903747/img", 35 | logo: "https://images.metahub.space/logo/medium/tt0903747/img", 36 | description: "A chemistry teacher diagnosed with inoperable lung cancer turns to manufacturing and selling methamphetamine with a former student to secure his family's future.", 37 | year: "2008", 38 | duration: "45 min", 39 | seasons: "5 seasons", 40 | rating: "9.5", 41 | numericRating: 9.5, 42 | href: null, 43 | type: "series" 44 | }, 45 | { 46 | id: "tt1375666", 47 | title: "Inception", 48 | background: "https://images.metahub.space/background/large/tt1375666/img", 49 | logo: "https://images.metahub.space/logo/medium/tt1375666/img", 50 | description: "A thief who steals corporate secrets through the use of dream-sharing technology is given the inverse task of planting an idea into a CEO's mind.", 51 | year: "2010", 52 | duration: "148 min", 53 | seasons: "Movie", 54 | rating: "8.8", 55 | numericRating: 8.8, 56 | href: null, 57 | type: "movie" 58 | }, 59 | { 60 | id: "tt0468569", 61 | title: "The Dark Knight", 62 | background: "https://images.metahub.space/background/large/tt0468569/img", 63 | logo: "https://images.metahub.space/logo/medium/tt0468569/img", 64 | description: "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, Batman must accept one of the greatest psychological and physical tests.", 65 | year: "2008", 66 | duration: "152 min", 67 | seasons: "Movie", 68 | rating: "9.0", 69 | numericRating: 9.0, 70 | href: null, 71 | type: "movie" 72 | } 73 | ]; 74 | 75 | async function fetchCatalogTitles(type, limit = 10) { 76 | const url = `https://cinemeta-catalogs.strem.io/top/catalog/${type}/top.json`; 77 | 78 | try { 79 | const controller = new AbortController(); 80 | const timeoutId = setTimeout(() => controller.abort(), 10000); 81 | 82 | const response = await fetch(url, { signal: controller.signal }); 83 | clearTimeout(timeoutId); 84 | 85 | if (!response.ok) { 86 | throw new Error(`HTTP error! status: ${response.status}`); 87 | } 88 | 89 | const data = await response.json(); 90 | const metas = data.metas || []; 91 | 92 | return metas.slice(0, limit).map(meta => ({ 93 | id: meta.id, 94 | title: meta.name, 95 | background: `https://images.metahub.space/background/large/${meta.id}/img`, 96 | logo: `https://images.metahub.space/logo/medium/${meta.id}/img`, 97 | description: meta.description || `Discover ${meta.name} and dive into an incredible viewing experience.`, 98 | year: meta.year ? meta.year.toString() : "2024", 99 | duration: meta.runtime ? `${meta.runtime}` : "Unknown", 100 | seasons: type === 'movie' ? 'Movie' : 'Series', 101 | rating: meta.imdbRating || "na", 102 | numericRating: parseFloat(meta.imdbRating) || 0, 103 | type: type, 104 | href: null, 105 | originalElement: null 106 | })); 107 | 108 | } catch (error) { 109 | console.error(`Failed to fetch ${type} catalog:`, error); 110 | return []; 111 | } 112 | } 113 | 114 | function formatDuration(runtime, type) { 115 | if (!runtime) return "Unknown"; 116 | 117 | // Clean up the runtime string - remove extra text like "min min", "/10", etc. 118 | let cleanRuntime = runtime.toString().trim(); 119 | 120 | // Remove common suffixes that cause duplication 121 | cleanRuntime = cleanRuntime.replace(/\s*min\s*min/gi, ' min'); 122 | cleanRuntime = cleanRuntime.replace(/\s*\/\d+/g, ''); // Remove "/10" or similar 123 | cleanRuntime = cleanRuntime.replace(/\s*min\s*\/\d+/gi, ' min'); // Remove "min/10" patterns 124 | 125 | // Extract just the number if it's a pure number 126 | const numMatch = cleanRuntime.match(/^(\d+)/); 127 | if (numMatch) { 128 | const minutes = parseInt(numMatch[1]); 129 | if (type === 'movie' && minutes > 0) { 130 | return `${minutes} min`; 131 | } else if (type === 'series') { 132 | // For series, assume it's episode length 133 | return `${minutes} min per episode`; 134 | } 135 | } 136 | 137 | // If it already has "min" and looks correct, return as is 138 | if (cleanRuntime.match(/^\d+\s*min$/i)) { 139 | return cleanRuntime; 140 | } 141 | 142 | return cleanRuntime || "Unknown"; 143 | } 144 | 145 | function formatSeasons(meta, type) { 146 | if (type === 'movie') { 147 | return 'Movie'; 148 | } 149 | 150 | // For series, try to get season information 151 | if (meta.videos && Array.isArray(meta.videos) && meta.videos.length > 0) { 152 | const seasonSet = new Set(); 153 | meta.videos.forEach(video => { 154 | if (video.season) seasonSet.add(video.season); 155 | }); 156 | 157 | if (seasonSet.size > 1) { 158 | return `${seasonSet.size} seasons`; 159 | } else if (seasonSet.size === 1) { 160 | const episodeCount = meta.videos.length; 161 | return episodeCount > 1 ? `${episodeCount} episodes` : '1 episode'; 162 | } 163 | } 164 | 165 | // Fallback for series 166 | return 'Series'; 167 | } 168 | 169 | async function getDetailedMetaData(id, type) { 170 | try { 171 | const controller = new AbortController(); 172 | const timeoutId = setTimeout(() => controller.abort(), 5000); 173 | 174 | const response = await fetch( 175 | `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, 176 | { signal: controller.signal } 177 | ); 178 | 179 | clearTimeout(timeoutId); 180 | 181 | if (!response.ok) { 182 | throw new Error(`HTTP error! status: ${response.status}`); 183 | } 184 | 185 | const data = await response.json(); 186 | const meta = data.meta; 187 | 188 | if (!meta) return null; 189 | 190 | // Determine actual type from the metadata 191 | let actualType = type; 192 | if (meta.type) { 193 | actualType = meta.type; 194 | } else if (meta.videos && meta.videos.length > 0) { 195 | // If it has episodes/videos, it's likely a series 196 | actualType = 'series'; 197 | } 198 | 199 | // Format duration properly 200 | let duration = "Unknown"; 201 | if (meta.runtime) { 202 | duration = formatDuration(meta.runtime, actualType); 203 | } else if (actualType === 'series') { 204 | duration = "45 min per episode"; // Default for series 205 | } 206 | 207 | // Format seasons/type info 208 | let seasons = formatSeasons(meta, actualType); 209 | 210 | return { 211 | year: meta.year ? meta.year.toString() : "2024", 212 | duration: duration, 213 | rating: meta.imdbRating || "na", 214 | numericRating: parseFloat(meta.imdbRating) || 0, 215 | seasons: seasons, 216 | description: meta.description || `Discover ${meta.name} and dive into an incredible viewing experience.`, 217 | type: actualType, // Return the corrected type 218 | genres: meta.genre || meta.genres || [], 219 | cast: meta.cast || [], 220 | director: Array.isArray(meta.director) ? meta.director.join(', ') : meta.director || '', 221 | awards: meta.awards || '' 222 | }; 223 | 224 | } catch (error) { 225 | console.error(`Failed to fetch detailed metadata for ${id}:`, error); 226 | return null; 227 | } 228 | } 229 | 230 | function resetHeroState() { 231 | heroState.isInitializing = false; 232 | heroState.retryCount = 0; 233 | stopAutoRotate(); 234 | } 235 | 236 | function isBoardTabSelected() { 237 | const boardTab = document.querySelector( 238 | 'a[title="Board"].selected, a[href="#/"].selected, .nav-tab-button-container-dYhs0.selected[href="#/"]' 239 | ); 240 | return boardTab !== null; 241 | } 242 | 243 | function isBoardPage() { 244 | const currentHash = window.location.hash; 245 | return currentHash === '#/' || currentHash === '' || currentHash === '#'; 246 | } 247 | 248 | function shouldShowHero() { 249 | return isBoardTabSelected() && isBoardPage(); 250 | } 251 | 252 | function findParentElement() { 253 | const parentSelectors = [ 254 | "#app > div.router-_65XU.routes-container > div > div.route-content > div.board-container-DTN_b > div > div > div", 255 | ".board-container-DTN_b > div > div > div", 256 | ".board-container-DTN_b > div > div", 257 | ".board-container-DTN_b > div", 258 | ".route-content > div", 259 | ".board-container-DTN_b", 260 | "[class*='board-container'] > div", 261 | "[class*='board-container']" 262 | ]; 263 | 264 | for (const selector of parentSelectors) { 265 | const element = document.querySelector(selector); 266 | if (element) return element; 267 | } 268 | 269 | const boardRows = document.querySelectorAll('.board-row-CoJrZ'); 270 | if (boardRows.length > 0) { 271 | const parent = boardRows[0].parentElement; 272 | if (parent) return parent; 273 | } 274 | 275 | const allContainers = document.querySelectorAll('div[class*="container"], div[class*="board"]'); 276 | for (let container of allContainers) { 277 | if (container.querySelector('.board-row-CoJrZ')) { 278 | return container; 279 | } 280 | } 281 | 282 | return null; 283 | } 284 | 285 | async function waitForBoardElements(timeout = 5000) { 286 | return new Promise((resolve) => { 287 | const startTime = Date.now(); 288 | 289 | function checkForElements() { 290 | if (!shouldShowHero()) { 291 | resolve(false); 292 | return; 293 | } 294 | 295 | const parent = findParentElement(); 296 | const boardRows = document.querySelectorAll('.board-row-CoJrZ'); 297 | 298 | if ((parent && boardRows.length > 0) || Date.now() - startTime > timeout) { 299 | resolve(parent && boardRows.length > 0); 300 | } else { 301 | setTimeout(checkForElements, 100); 302 | } 303 | } 304 | 305 | checkForElements(); 306 | }); 307 | } 308 | 309 | function showLoadingScreen() { 310 | let loadingScreen = document.getElementById('heroLoadingScreen'); 311 | if (!loadingScreen) { 312 | loadingScreen = document.createElement('div'); 313 | loadingScreen.id = 'heroLoadingScreen'; 314 | loadingScreen.innerHTML = ` 315 |
316 |
317 |
Loading popular content...
318 |
319 |
320 |
321 |
322 | Click to skip and use fallback content 323 |
324 |
325 | `; 326 | document.body.appendChild(loadingScreen); 327 | } 328 | 329 | loadingScreen.style.cssText = ` 330 | position: fixed !important; 331 | top: 0 !important; left: 0 !important; 332 | width: 100vw !important; height: 100vh !important; 333 | z-index: 999999 !important; 334 | opacity: 1; visibility: visible; 335 | backdrop-filter: blur(10px); 336 | pointer-events: auto; 337 | background: linear-gradient(135deg, #0c0c0c 0%, #1a1a1a 50%, #0c0c0c 100%); 338 | display: flex; align-items: center; justify-content: center; 339 | `; 340 | 341 | document.body.style.overflow = 'hidden'; 342 | return loadingScreen; 343 | } 344 | 345 | function updateLoadingStatus(text, progress = null) { 346 | const loadingText = document.getElementById('loadingText'); 347 | const loadingProgress = document.getElementById('loadingProgress'); 348 | 349 | if (loadingText) { 350 | loadingText.textContent = text; 351 | } 352 | 353 | if (progress !== null && loadingProgress) { 354 | loadingProgress.style.width = `${progress}%`; 355 | } 356 | } 357 | 358 | function hideLoadingScreen() { 359 | const loadingScreen = document.getElementById('heroLoadingScreen'); 360 | if (loadingScreen) { 361 | loadingScreen.style.opacity = '0'; 362 | loadingScreen.style.visibility = 'hidden'; 363 | loadingScreen.style.pointerEvents = 'none'; 364 | document.body.style.overflow = ''; 365 | 366 | setTimeout(() => { 367 | if (loadingScreen.parentNode) { 368 | document.body.removeChild(loadingScreen); 369 | } 370 | }, 500); 371 | } 372 | } 373 | 374 | window.skipLoading = function() { 375 | hideLoadingScreen(); 376 | heroTitles = [...fallbackTitles]; 377 | createHeroDirect(); 378 | }; 379 | 380 | window.playTitle = function(titleId) { 381 | const element = document.querySelector(`a[id="${titleId}"]`); 382 | if (element) { 383 | element.click(); 384 | } else { 385 | const title = heroTitles.find(t => t.id === titleId); 386 | if (title) { 387 | const type = title.type === 'movie' ? 'movie' : 'series'; 388 | window.location.hash = `#/detail/${type}/${titleId}`; 389 | } 390 | } 391 | }; 392 | 393 | window.showMoreInfo = function(titleId) { 394 | const element = document.querySelector(`a[id="${titleId}"]`); 395 | if (element) { 396 | element.click(); 397 | } else { 398 | const title = heroTitles.find(t => t.id === titleId); 399 | if (title) { 400 | const type = title.type === 'movie' ? 'movie' : 'series'; 401 | window.location.hash = `#/detail/${type}/${titleId}`; 402 | } 403 | } 404 | }; 405 | 406 | window.goToTitle = function(index) { 407 | if (index !== currentIndex && index >= 0 && index < heroTitles.length) { 408 | currentIndex = index; 409 | updateHeroContent(heroTitles[currentIndex]); 410 | resetAutoRotate(); 411 | } 412 | }; 413 | 414 | window.nextTitle = function() { 415 | currentIndex = (currentIndex + 1) % heroTitles.length; 416 | updateHeroContent(heroTitles[currentIndex]); 417 | resetAutoRotate(); 418 | }; 419 | 420 | window.previousTitle = function() { 421 | currentIndex = (currentIndex - 1 + heroTitles.length) % heroTitles.length; 422 | updateHeroContent(heroTitles[currentIndex]); 423 | resetAutoRotate(); 424 | }; 425 | 426 | window.toggleAutoRotate = function() { 427 | isAutoRotating = !isAutoRotating; 428 | const toggleBtn = document.getElementById('autoToggle'); 429 | if (toggleBtn) { 430 | toggleBtn.textContent = isAutoRotating ? 'Pause' : 'Play'; 431 | } 432 | 433 | if (isAutoRotating) { 434 | startAutoRotate(); 435 | } else { 436 | stopAutoRotate(); 437 | } 438 | }; 439 | 440 | async function collectTitlesFromAPI() { 441 | const collectedTitles = []; 442 | updateLoadingStatus('Fetching popular movies...', 20); 443 | 444 | try { 445 | // Fetch movies and series in parallel 446 | const [movies, series] = await Promise.all([ 447 | fetchCatalogTitles('movie', 8), 448 | fetchCatalogTitles('series', 8) 449 | ]); 450 | 451 | updateLoadingStatus('Fetching popular series...', 40); 452 | 453 | // Interleave movies and series for variety 454 | const maxTitles = 10; 455 | let movieIndex = 0; 456 | let seriesIndex = 0; 457 | let expectMovie = true; 458 | 459 | for (let i = 0; i < maxTitles && (movieIndex < movies.length || seriesIndex < series.length); i++) { 460 | let titleToAdd = null; 461 | 462 | if (expectMovie && movieIndex < movies.length) { 463 | titleToAdd = movies[movieIndex]; 464 | movieIndex++; 465 | } else if (!expectMovie && seriesIndex < series.length) { 466 | titleToAdd = series[seriesIndex]; 467 | seriesIndex++; 468 | } else if (movieIndex < movies.length) { 469 | titleToAdd = movies[movieIndex]; 470 | movieIndex++; 471 | } else if (seriesIndex < series.length) { 472 | titleToAdd = series[seriesIndex]; 473 | seriesIndex++; 474 | } 475 | 476 | expectMovie = !expectMovie; 477 | 478 | if (titleToAdd) { 479 | updateLoadingStatus(`Getting details for ${titleToAdd.title}...`, 50 + (i * 4)); 480 | 481 | // Get detailed metadata for better info 482 | const detailedMeta = await getDetailedMetaData(titleToAdd.id, titleToAdd.type); 483 | if (detailedMeta) { 484 | titleToAdd.year = detailedMeta.year; 485 | titleToAdd.duration = detailedMeta.duration; 486 | titleToAdd.rating = detailedMeta.rating; 487 | titleToAdd.numericRating = detailedMeta.numericRating; 488 | titleToAdd.seasons = detailedMeta.seasons; 489 | titleToAdd.type = detailedMeta.type; // Update with correct type 490 | titleToAdd.genres = detailedMeta.genres; 491 | titleToAdd.cast = detailedMeta.cast; 492 | titleToAdd.director = detailedMeta.director; 493 | titleToAdd.awards = detailedMeta.awards; 494 | if (detailedMeta.description && detailedMeta.description !== titleToAdd.description) { 495 | titleToAdd.description = detailedMeta.description; 496 | } 497 | } 498 | 499 | collectedTitles.push(titleToAdd); 500 | 501 | // Small delay to avoid overwhelming the API 502 | await new Promise(resolve => setTimeout(resolve, 50)); 503 | } 504 | } 505 | 506 | } catch (error) { 507 | console.error('Error collecting titles from API:', error); 508 | updateLoadingStatus('Error occurred, using fallbacks...', 85); 509 | } 510 | 511 | return collectedTitles; 512 | } 513 | 514 | function createHeroHTML(title) { 515 | const infoItems = [title.year]; 516 | 517 | // Add duration if available and not "Unknown" 518 | if (title.duration && title.duration !== "Unknown") { 519 | infoItems.push(title.duration); 520 | } 521 | 522 | // Add seasons/type info 523 | if (title.seasons && title.seasons !== "Unknown") { 524 | infoItems.push(title.seasons); 525 | } 526 | 527 | return ` 528 |
529 | Hero Background 530 |
531 | 532 |

${title.description}

533 |
534 | ${infoItems.map(item => `

${item}

`).join('')} 535 | ${title.rating && title.rating !== "na" ? 536 | `

537 | ⭐ ${title.rating}/10 538 |

` : '' 539 | } 540 |
541 |
542 | 546 | 550 |
551 |
552 |
553 | 556 | 557 | 558 |
559 |
560 | ${heroTitles.map((_, index) => 561 | `
` 563 | ).join('')} 564 |
565 |
566 | `; 567 | } 568 | 569 | function updateHeroContent(title, animate = true) { 570 | const heroImage = document.getElementById('heroImage'); 571 | const heroLogo = document.getElementById('heroLogo'); 572 | const heroDescription = document.getElementById('heroDescription'); 573 | const heroInfo = document.getElementById('heroInfo'); 574 | const heroAdditionalInfo = document.getElementById('heroAdditionalInfo'); 575 | const watchButton = document.querySelector('.hero-overlay-button-watch'); 576 | const moreInfoButton = document.querySelector('.hero-overlay-button'); 577 | 578 | if (!heroImage || !heroLogo || !heroDescription || !heroInfo) return; 579 | 580 | const infoItems = [title.year]; 581 | 582 | // Add duration if available and not "Unknown" 583 | if (title.duration && title.duration !== "Unknown") { 584 | infoItems.push(title.duration); 585 | } 586 | 587 | // Add seasons/type info 588 | if (title.seasons && title.seasons !== "Unknown") { 589 | infoItems.push(title.seasons); 590 | } 591 | 592 | const infoHTML = infoItems.map(item => `

${item}

`).join('') + 593 | (title.rating && title.rating !== "na" ? 594 | `

595 | ⭐ ${title.rating}/10 596 |

` : '' 597 | ); 598 | 599 | // Generate additional info HTML 600 | let additionalInfoHTML = ''; 601 | if (title.genres && title.genres.length > 0) { 602 | additionalInfoHTML += `
${title.genres.join(' • ')}
`; 603 | } 604 | if (title.cast && title.cast.length > 0) { 605 | additionalInfoHTML += `
Starring: ${title.cast.slice(0, 3).join(', ')}
`; 606 | } 607 | if (title.director) { 608 | additionalInfoHTML += `
Directed by ${title.director}
`; 609 | } 610 | if (title.awards) { 611 | additionalInfoHTML += `
${title.awards}
`; 612 | } 613 | 614 | if (animate) { 615 | heroImage.style.opacity = '0'; 616 | heroLogo.style.opacity = '0'; 617 | heroDescription.style.opacity = '0'; 618 | heroInfo.style.opacity = '0'; 619 | if (heroAdditionalInfo) heroAdditionalInfo.style.opacity = '0'; 620 | 621 | setTimeout(() => { 622 | heroImage.src = title.background; 623 | heroLogo.src = title.logo; 624 | heroDescription.textContent = title.description; 625 | heroInfo.innerHTML = infoHTML; 626 | if (heroAdditionalInfo) heroAdditionalInfo.innerHTML = additionalInfoHTML; 627 | 628 | if (watchButton) { 629 | watchButton.setAttribute('onclick', `event.stopPropagation(); playTitle('${title.id}')`); 630 | } 631 | if (moreInfoButton) { 632 | moreInfoButton.setAttribute('onclick', `event.stopPropagation(); showMoreInfo('${title.id}')`); 633 | } 634 | 635 | setTimeout(() => { 636 | heroImage.style.opacity = '1'; 637 | heroLogo.style.opacity = '1'; 638 | heroDescription.style.opacity = '1'; 639 | heroInfo.style.opacity = '1'; 640 | if (heroAdditionalInfo) heroAdditionalInfo.style.opacity = '1'; 641 | }, 50); 642 | 643 | updateIndicators(); 644 | }, 300); 645 | } else { 646 | heroImage.src = title.background; 647 | heroLogo.src = title.logo; 648 | heroDescription.textContent = title.description; 649 | heroInfo.innerHTML = infoHTML; 650 | if (heroAdditionalInfo) heroAdditionalInfo.innerHTML = additionalInfoHTML; 651 | 652 | if (watchButton) { 653 | watchButton.setAttribute('onclick', `event.stopPropagation(); playTitle('${title.id}')`); 654 | } 655 | if (moreInfoButton) { 656 | moreInfoButton.setAttribute('onclick', `event.stopPropagation(); showMoreInfo('${title.id}')`); 657 | } 658 | 659 | updateIndicators(); 660 | } 661 | } 662 | 663 | function updateIndicators() { 664 | const indicators = document.querySelectorAll('.hero-indicator'); 665 | indicators.forEach((indicator, index) => { 666 | indicator.classList.toggle('active', index === currentIndex); 667 | }); 668 | } 669 | 670 | function createHeroDirect() { 671 | if (!shouldShowHero()) { 672 | return; 673 | } 674 | 675 | const parent = findParentElement(); 676 | if (!parent) { 677 | return; 678 | } 679 | 680 | const existingHero = parent.querySelector(".hero-container"); 681 | if (existingHero) { 682 | existingHero.remove(); 683 | } 684 | 685 | if (heroTitles.length === 0) { 686 | heroTitles = [...fallbackTitles]; 687 | } 688 | 689 | currentIndex = 0; 690 | 691 | const heroHTML = createHeroHTML(heroTitles[0]); 692 | parent.insertAdjacentHTML("afterbegin", heroHTML); 693 | 694 | const insertedHero = parent.querySelector(".hero-container"); 695 | if (insertedHero) { 696 | const heroImage = document.getElementById('heroImage'); 697 | const heroLogo = document.getElementById('heroLogo'); 698 | const heroDescription = document.getElementById('heroDescription'); 699 | const heroInfo = document.getElementById('heroInfo'); 700 | 701 | if (heroImage) heroImage.style.transition = 'opacity 0.3s ease-in-out'; 702 | if (heroLogo) heroLogo.style.transition = 'opacity 0.3s ease-in-out'; 703 | if (heroDescription) heroDescription.style.transition = 'opacity 0.3s ease-in-out'; 704 | if (heroInfo) heroInfo.style.transition = 'opacity 0.3s ease-in-out'; 705 | 706 | startAutoRotate(); 707 | 708 | insertedHero.addEventListener('mouseenter', () => { 709 | if (isAutoRotating) stopAutoRotate(); 710 | }); 711 | 712 | insertedHero.addEventListener('mouseleave', () => { 713 | if (isAutoRotating) startAutoRotate(); 714 | }); 715 | } 716 | } 717 | 718 | function startAutoRotate() { 719 | if (autoRotateInterval) clearInterval(autoRotateInterval); 720 | if (isAutoRotating) { 721 | autoRotateInterval = setInterval(() => { 722 | currentIndex = (currentIndex + 1) % heroTitles.length; 723 | updateHeroContent(heroTitles[currentIndex]); 724 | }, ROTATION_INTERVAL); 725 | } 726 | } 727 | 728 | function stopAutoRotate() { 729 | if (autoRotateInterval) { 730 | clearInterval(autoRotateInterval); 731 | autoRotateInterval = null; 732 | } 733 | } 734 | 735 | function resetAutoRotate() { 736 | if (isAutoRotating) { 737 | stopAutoRotate(); 738 | startAutoRotate(); 739 | } 740 | } 741 | 742 | async function initializeTitles() { 743 | if (heroState.isInitializing) { 744 | return false; 745 | } 746 | heroState.isInitializing = true; 747 | showLoadingScreen(); 748 | updateLoadingStatus('Fetching popular content...', 10); 749 | 750 | try { 751 | const timeoutPromise = new Promise((resolve) => { 752 | setTimeout(() => resolve([]), 12000); 753 | }); 754 | 755 | const collectionPromise = collectTitlesFromAPI(); 756 | const collectedTitles = await Promise.race([collectionPromise, timeoutPromise]); 757 | 758 | updateLoadingStatus('Finalizing...', 90); 759 | 760 | if (collectedTitles.length > 0) { 761 | heroTitles = collectedTitles; 762 | updateLoadingStatus(`Ready! Found ${collectedTitles.length} popular titles`, 100); 763 | } else { 764 | heroTitles = [...fallbackTitles]; 765 | updateLoadingStatus('Using fallback content...', 100); 766 | } 767 | 768 | await new Promise(resolve => setTimeout(resolve, 800)); 769 | hideLoadingScreen(); 770 | 771 | heroState.initializationComplete = true; 772 | heroState.titlesReady = true; 773 | return true; 774 | 775 | } catch (error) { 776 | heroTitles = [...fallbackTitles]; 777 | heroState.titlesReady = true; 778 | updateLoadingStatus('Error - using fallback content...', 100); 779 | await new Promise(resolve => setTimeout(resolve, 1000)); 780 | hideLoadingScreen(); 781 | heroState.initializationComplete = true; 782 | return true; 783 | } finally { 784 | heroState.isInitializing = false; 785 | } 786 | } 787 | 788 | async function addHeroDiv() { 789 | if (!shouldShowHero()) { 790 | return; 791 | } 792 | 793 | const existingHero = document.querySelector('.hero-container'); 794 | if (existingHero) { 795 | return; 796 | } 797 | 798 | if (heroState.isInitializing) { 799 | return; 800 | } 801 | 802 | const boardElementsReady = await waitForBoardElements(3000); 803 | if (!boardElementsReady) { 804 | return; 805 | } 806 | 807 | if (heroTitles.length > 0 && heroState.titlesReady) { 808 | createHeroDirect(); 809 | return; 810 | } 811 | 812 | if (heroTitles.length === 0 || !heroState.titlesReady) { 813 | const success = await initializeTitles(); 814 | if (success) { 815 | heroState.titlesReady = true; 816 | createHeroDirect(); 817 | } else { 818 | if (heroState.retryCount < MAX_RETRIES) { 819 | heroState.retryCount++; 820 | setTimeout(() => addHeroDiv(), 3000); 821 | } else { 822 | heroTitles = [...fallbackTitles]; 823 | heroState.titlesReady = true; 824 | createHeroDirect(); 825 | } 826 | } 827 | } 828 | } 829 | 830 | function handleNavigation() { 831 | const currentHash = window.location.hash; 832 | const heroExists = document.querySelector('.hero-container'); 833 | const shouldShow = shouldShowHero(); 834 | 835 | if (!shouldShow && heroExists) { 836 | heroExists.remove(); 837 | resetHeroState(); 838 | return; 839 | } 840 | 841 | if (shouldShow && !heroExists) { 842 | setTimeout(() => addHeroDiv(), 100); 843 | setTimeout(() => addHeroDiv(), 500); 844 | setTimeout(() => addHeroDiv(), 1000); 845 | } 846 | 847 | heroState.lastKnownHash = currentHash; 848 | } 849 | 850 | window.addEventListener('hashchange', () => { 851 | handleNavigation(); 852 | }); 853 | 854 | window.addEventListener('popstate', () => { 855 | setTimeout(handleNavigation, 100); 856 | }); 857 | 858 | window.addEventListener('focus', () => { 859 | setTimeout(handleNavigation, 200); 860 | }); 861 | 862 | document.addEventListener('visibilitychange', () => { 863 | if (!document.hidden) { 864 | setTimeout(handleNavigation, 300); 865 | } 866 | }); 867 | 868 | window.heroObserver = new MutationObserver((mutations) => { 869 | let relevantMutation = false; 870 | 871 | mutations.forEach(mutation => { 872 | if (mutation.addedNodes.length > 0) { 873 | for (let node of mutation.addedNodes) { 874 | if (node.nodeType === 1) { 875 | if (node.classList?.contains('board-container-DTN_b') || 876 | node.querySelector?.('.board-container-DTN_b') || 877 | node.classList?.contains('board-row-CoJrZ') || 878 | node.querySelector?.('.board-row-CoJrZ')) { 879 | relevantMutation = true; 880 | break; 881 | } 882 | } 883 | } 884 | } 885 | }); 886 | 887 | if (relevantMutation) { 888 | setTimeout(handleNavigation, 200); 889 | } 890 | }); 891 | 892 | window.heroObserver.observe(document.body, { 893 | childList: true, 894 | subtree: true, 895 | attributes: false, 896 | characterData: false 897 | }); 898 | 899 | setInterval(() => { 900 | const heroExists = document.querySelector('.hero-container'); 901 | const shouldShow = shouldShowHero(); 902 | 903 | if (shouldShow && !heroExists && !heroState.isInitializing && !document.getElementById('heroLoadingScreen')) { 904 | addHeroDiv(); 905 | } 906 | }, 3000); 907 | 908 | setTimeout(() => { 909 | handleNavigation(); 910 | }, 1000); 911 | 912 | })(); -------------------------------------------------------------------------------- /themes/liquid-glass.theme.css: -------------------------------------------------------------------------------- 1 | /** 2 | * @name Modern Glass 3 | * @description A theme that takes advantage of Modern Glass Styles with Light and Dark Theme. 4 | * @version 1.0.0 5 | * @updateUrl https://github.com/Fxy6969/Streamio-Glass-Theme/tree/cover 6 | * @author Fxy/Moerat 7 | */ 8 | 9 | @import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"); 10 | 11 | * { 12 | font-family: 'Inter', sans-serif !important; 13 | 14 | scrollbar-width: none; 15 | } 16 | 17 | /* change the accent color from purple to white */ 18 | :root { 19 | --primary-accent-color: #fff; 20 | --background: rgb(20, 20, 20); 21 | 22 | --bg-color: rgb(250, 251, 255, 0.74); 23 | --bg-color-img: linear-gradient(45deg, #f4f4fc, #f4f4fc); 24 | --bg-progress-color: #0c0c0c; 25 | --bg-hover-color: rgba(12, 12, 12, 0.05); 26 | --bg-input-color: rgba(157, 157, 157, 0.74); 27 | 28 | --border-radius: 12px; 29 | 30 | --box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2), 31 | 0 8px 40px rgba(0, 0, 0, 0.55); 32 | } 33 | 34 | /* glass effect: */ 35 | /* background: rgba(70, 70, 70, 0.22) !important; 36 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 37 | backdrop-filter: var(--backdrop-filter) !important; 38 | border: 1px solid rgba(255, 255, 255, 0.04) !important; */ 39 | 40 | html body { 41 | background: var(--background) !important; 42 | overflow-y: scroll !important; 43 | } 44 | 45 | ::-webkit-scrollbar { 46 | width: 0; /* removes scrollbar track */ 47 | height: 0; 48 | } 49 | 50 | /* ========================= NAV BAR / HEADER ========================= */ 51 | 52 | .search-bar-container-asfq1 { 53 | position: fixed; 54 | bottom: 20px; 55 | left: 50%; 56 | transform: translateX(-50%); 57 | width: 50px; /* Smaller collapsed width - just for icon */ 58 | background: rgba(20, 20, 20, 0.42) !important; 59 | border-radius: 999px !important; 60 | backdrop-filter: blur(8px) saturate(210%) !important; 61 | opacity: 1 !important; 62 | display: flex; 63 | justify-content: center; 64 | align-items: center; 65 | padding: 10px; 66 | z-index: 9999; 67 | overflow: hidden; /* Hide overflowing content when collapsed */ 68 | 69 | /* Smooth animation */ 70 | transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; 71 | } 72 | 73 | /* Expanded state */ 74 | .search-bar-container-asfq1:focus-within, 75 | .search-bar-container-asfq1.expanded { 76 | width: 30% !important; /* Your original expanded width */ 77 | justify-content: space-between !important; 78 | } 79 | 80 | .search-bar-container-asfq1 .submit-button-container-MImNa { 81 | align-items: center; 82 | display: flex; 83 | flex: none; 84 | flex-direction: row; 85 | height: var(--search-bar-size); 86 | justify-content: center; 87 | padding: 0 0.5rem; 88 | min-width: 40px; /* Ensure icon always has space */ 89 | order: 2; /* Icon goes to the right when expanded */ 90 | } 91 | 92 | /* Hide input when collapsed */ 93 | .search-bar-container-asfq1 .search-input-IQ0ZW { 94 | opacity: 0 !important; 95 | width: 0 !important; 96 | padding: 0 !important; 97 | border: none !important; 98 | background: transparent !important; 99 | order: 1; /* Input goes to the left when expanded */ 100 | 101 | transition: opacity 0.2s ease-in-out 0.15s, width 0.4s cubic-bezier(0.4, 0, 0.2, 1), padding 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; 102 | } 103 | 104 | /* Show input when expanded */ 105 | .search-bar-container-asfq1:focus-within .search-input-IQ0ZW, 106 | .search-bar-container-asfq1.expanded .search-input-IQ0ZW { 107 | opacity: 1 !important; 108 | width: 100% !important; 109 | padding: 0 0.5rem 0 0.5rem !important; 110 | flex: 1 !important; 111 | } 112 | 113 | 114 | 115 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja { 116 | width: 45px !important; 117 | background: rgba(90, 90, 90, 0.22) !important; 118 | border-radius: 999px !important; 119 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 120 | backdrop-filter: blur(4.7px) !important; 121 | border: 1px solid rgba(255, 255, 255, 0.2) !important; 122 | opacity: 1 !important; 123 | overflow: hidden !important; 124 | display: flex !important 125 | ; 126 | align-items: center !important; 127 | justify-content: center !important; 128 | transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; 129 | } 130 | 131 | /* Expanded state for horizontal nav search bar */ 132 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja:hover, 133 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja:focus, 134 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja:focus-within, 135 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja.expanded { 136 | width: 300px !important; /* Expanded width */ 137 | justify-content: space-between !important; 138 | } 139 | 140 | /* Hide input when collapsed in horizontal nav */ 141 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja .search-input-IQ0ZW { 142 | opacity: 0 !important; 143 | width: 0 !important; 144 | padding: 0 !important; 145 | border: none !important; 146 | background: transparent !important; 147 | 148 | transition: opacity 0.2s ease-in-out 0.15s, width 0.4s cubic-bezier(0.4, 0, 0.2, 1), padding 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; 149 | } 150 | 151 | /* Show input when expanded in horizontal nav */ 152 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja:hover .search-input-IQ0ZW, 153 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja:focus .search-input-IQ0ZW, 154 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja:focus-within .search-input-IQ0ZW, 155 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja.expanded .search-input-IQ0ZW { 156 | opacity: 1 !important; 157 | width: 100% !important; 158 | padding: 8px 16px !important; 159 | flex: 1 !important; 160 | } 161 | 162 | /* Keep the search icon visible */ 163 | .horizontal-nav-bar-container-Y_zvK .search-bar-h60ja .submit-button-container-MImNa { 164 | flex-shrink: 0 !important; 165 | display: flex !important; 166 | align-items: center !important; 167 | justify-content: center !important; 168 | min-width: 35px !important; 169 | order: 2 !important; /* Icon goes to the right when expanded */ 170 | } 171 | 172 | /* Style any menu/button container in the top nav */ 173 | #app nav[class*="horizontal-nav-bar"] [class*="buttons-container"] > div[class*="button-container"], 174 | #app nav[class*="horizontal-nav-bar"] [class*="buttons-container"] > div[class*="menu-button-container"] { 175 | background: rgba(90, 90, 90, 0.22) !important; 176 | border-radius: 999px !important; 177 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.4), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 178 | backdrop-filter: var(--backdrop-filter2) !important; 179 | border: 1px solid rgba(255, 255, 255, 0.1) !important; 180 | transform: scale(0.8) !important; 181 | opacity: 1 !important; 182 | } 183 | 184 | 185 | /* Logo styling in header */ 186 | #app [class*="horizontal-nav-bar"] [class*="logo-container"] [class*="logo"] { 187 | filter: grayscale(1) brightness(1) !important; 188 | } 189 | 190 | /* ========================= VERTICAL NAV / SIDEBAR ========================= */ 191 | 192 | /* Position the vertical nav itself */ 193 | #app [class*="main-nav-bars-container"] [class*="vertical-nav-bar"] { 194 | position: absolute !important; 195 | left: 91px !important; 196 | top: 0.5px !important; 197 | z-index: 1 !important; 198 | } 199 | 200 | /* Style the vertical nav container (layout, spacing, scroll) */ 201 | #app [class*="vertical-nav-bar-container"] { 202 | align-items: center !important; 203 | background-color: transparent !important; 204 | display: flex !important; 205 | flex-direction: row !important; 206 | gap: 1rem !important; 207 | overflow-y: auto !important; 208 | padding: 1rem 0 !important; 209 | scrollbar-width: none !important; 210 | width: auto !important; 211 | position: relative !important; 212 | } 213 | 214 | /* Optional custom label you add in markup */ 215 | .nav-label { 216 | color: var(--primary-accent-color) !important; 217 | font-weight: 600 !important; 218 | padding: 0 5px !important; 219 | } 220 | 221 | /* Selected tab look */ 222 | #app [class*="nav-tab-button-container"].selected { 223 | background: rgba(70, 70, 70, 0.22) !important; 224 | border-radius: 999px !important; 225 | box-shadow: 226 | 0 8px 32px rgba(0, 0, 0, 0.2), 227 | 0 4px 16px rgba(0, 0, 0, 0.1) , 228 | inset 0 1px 0 rgba(255, 255, 255, 0.15), 229 | inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 230 | backdrop-filter: var(--backdrop-filter) !important; 231 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 232 | opacity: 1 !important; 233 | transform: translateY(0px) scale(1) !important; 234 | } 235 | 236 | /* Ensure nav content is flush left */ 237 | #app [class*="main-nav-bars-container"] [class*="nav-content-container"] { 238 | left: 0 !important; 239 | } 240 | 241 | /* Nav button sizing/padding */ 242 | #app [class*="vertical-nav-bar-container"] [class*="nav-tab-button"] { 243 | min-height: auto !important; 244 | height: auto !important; 245 | width: auto !important; 246 | padding: 7px 10px !important; 247 | transition: padding 0.2s ease-out !important; 248 | } 249 | 250 | .meta-row-container-xtlB1 .meta-items-container-qcuUA .meta-item-QFHCh.poster-shape-poster-LKBza { 251 | flex: calc(1 / var(--poster-shape-ratio)) 0 250px !important; 252 | } 253 | 254 | /* account dropdown */ 255 | /* settings menu */ 256 | .poster-image-NiV7O:hover{ 257 | cursor:pointer; 258 | } 259 | 260 | /* settings menu */ 261 | 262 | .nav-menu-container-Pl25j, .nav-menu-container-Pl25j { 263 | background-color: transparent !important; 264 | } 265 | 266 | .label-container-XOyzm, .menu-container-B6cqK { 267 | background-color: transparent !important; 268 | } 269 | 270 | .label-container-XOyzm { 271 | background-color: transparent !important; 272 | box-shadow: none !important; 273 | } 274 | 275 | .menu-container-B6cqK { 276 | background-color: transparent !important; 277 | box-shadow: none !important; 278 | } 279 | 280 | .modal-container-OuxEF .modal-dialog-container-DZMKq { 281 | background-color: #00000093; 282 | backdrop-filter: var(--backdrop-filter); 283 | border-radius: var(--border-radius); 284 | box-shadow: var(--box-shadow); 285 | } 286 | 287 | .label-container-_VXZt { 288 | display: none !important; 289 | } 290 | 291 | .player-container-wIELK .layer-qalDW.menu-layer-HZFG9 { 292 | background: rgba(70, 70, 70, 0.22) !important; 293 | border-radius: 999px !important; 294 | box-shadow: 295 | 0 8px 32px rgba(0, 0, 0, 0.2) , 296 | 0 4px 16px rgba(0, 0, 0, 0.1) , 297 | inset 0 1px 0 rgba(255, 255, 255, 0.15) , 298 | inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 299 | backdrop-filter: var(--backdrop-filter) !important; 300 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 301 | opacity: 1 !important; 302 | } 303 | 304 | .option-container-m_jZq { 305 | height: 1.5rem; 306 | border-radius: 0.4rem; 307 | padding: 0 0.7rem; 308 | } 309 | 310 | .slider-container-nJz5F .track-gItfW { 311 | background-color: #ffffff; 312 | } 313 | 314 | .seek-bar-container-JGGTa .slider-hBDOf .thumb-PiTF5, .seek-bar-container-JGGTa .slider-hBDOf .track-after-pUXC0 { 315 | background-color: #ffffff; 316 | } 317 | 318 | .seek-bar-container-JGGTa .slider-hBDOf .thumb-PiTF5:after { 319 | box-shadow: none; 320 | } 321 | 322 | .control-bar-container-xsWA7 .seek-bar-I7WeY { 323 | --thumb-size: .9rem; 324 | } 325 | 326 | /* title container */ 327 | [class*="meta-item-container"] [class*="title-bar-container"] { 328 | display: flex; 329 | flex-direction: column; 330 | align-items: stretch; 331 | justify-content: flex-start; 332 | height: auto; 333 | overflow: visible; 334 | padding: 0; 335 | position: relative; 336 | } 337 | 338 | /* progress-bar container */ 339 | [class*="meta-item-container"] [class*="title-bar-container"] [class*="progress-bar-layer"] { 340 | height: 0.45rem; 341 | border-radius: 0.45rem; 342 | overflow: hidden; 343 | align-self: stretch; 344 | padding: inherit; 345 | margin-top: 10px; 346 | margin-left: 1.8rem; 347 | margin-right: 1.8rem; 348 | background-color: rgba(255, 255, 255, 0.1); 349 | } 350 | 351 | /* foreground */ 352 | [class*="meta-item-container"] [class*="progress-bar-layer"] [class*="progress-bar-w"] { 353 | background-color: var(--primary-foreground-color); 354 | height: 100%; 355 | position: relative; 356 | } 357 | 358 | [class*="meta-item-container"] [class*="progress-bar-layer"] [class*="progress-bar-background"] { 359 | background-color: transparent; 360 | opacity: 0.3; 361 | height: 100%; 362 | position: absolute; 363 | top: 0; 364 | left: 0; 365 | width: 100%; 366 | } 367 | 368 | [class*="meta-item-container"] [class*="title-bar-container"] > *:not([class*="progress-bar-layer"]) { 369 | order: 1; 370 | align-self: stretch; 371 | display: flex; 372 | align-items: center; 373 | margin: none; 374 | min-height: 1.3rem; 375 | } 376 | 377 | .meta-item-container-Tj0Ib .title-bar-container-1Ba0x .menu-label-container-ChuX8 .icon-gh1t9 { 378 | visibility: hidden; 379 | } 380 | 381 | [class*="meta-item-container"] [class*="title-bar-container"] [class*="title"], 382 | [class*="meta-item-container"] [class*="title-bar-container"] [class*="title-bar"] { 383 | margin-top: 0; 384 | line-height: 1.1; 385 | white-space: nowrap; 386 | overflow: hidden; 387 | text-overflow: ellipsis; 388 | } 389 | 390 | [class*="meta-item-container"] [class*="title-bar-container"]:not(:has(> [class*="progress-bar-layer"])) > *:first-child { 391 | margin-top: 0.35rem; 392 | } 393 | 394 | /* scroll fix for hero */ 395 | .main-nav-bars-container-wNjS5 .nav-content-container-zl9hQ { 396 | top: calc(var(--horizontal-nav-bar-size) - 80px); 397 | } 398 | 399 | /* Hero Section */ 400 | .hero-container { 401 | position: relative; 402 | display: inline-block; 403 | width: 100%; 404 | height: 80%; 405 | overflow: hidden; 406 | } 407 | 408 | .hero-image { 409 | width: 100%; 410 | height: 100%; 411 | object-fit: cover; 412 | display: block; 413 | 414 | -webkit-mask-image: 415 | linear-gradient(to top, transparent, black 45%), 416 | linear-gradient(to right, transparent, black 75%); 417 | -webkit-mask-repeat: no-repeat; 418 | -webkit-mask-size: cover; 419 | -webkit-mask-composite: intersect; 420 | 421 | mask-image: 422 | linear-gradient(to top, transparent, black 45%), 423 | linear-gradient(to right, transparent, black 75%); 424 | mask-repeat: no-repeat; 425 | mask-size: cover; 426 | mask-composite: intersect; 427 | 428 | 429 | 430 | } 431 | 432 | .hero-overlay { 433 | position: absolute; 434 | width: 100%; 435 | padding-left: 6%; 436 | bottom: 0; 437 | 438 | color: white; 439 | 440 | font-family: 'Inter', sans-serif !important; 441 | } 442 | 443 | .hero-overlay-image { 444 | width: 90%; 445 | max-width: 420px; 446 | margin-bottom: 30px; 447 | } 448 | 449 | .hero-overlay-description { 450 | max-width: 500px; 451 | font-size: 17px; 452 | margin-bottom: 20px; 453 | color: white; 454 | font: normal; 455 | } 456 | 457 | .hero-overlay-info { 458 | display: flex; 459 | gap: 15px; 460 | align-items: center; 461 | margin-bottom: 30px; 462 | font-weight: 600; 463 | color: rgba(190, 190, 190, 1) 464 | } 465 | 466 | .hero-overlay-actions { 467 | display: flex; 468 | gap: 10px; 469 | margin-bottom: 50px; 470 | } 471 | 472 | .hero-overlay-button-watch, .hero-overlay-button { 473 | border: 0; 474 | outline: 0; 475 | padding: 8px 20px; 476 | display: inline-flex; 477 | align-items: center; 478 | gap: 10px; 479 | font-size: 15px; 480 | border-radius: 4px; 481 | cursor: pointer; 482 | color: white; 483 | transition: all 0.3s ease; 484 | } 485 | 486 | .hero-overlay-button { 487 | background: rgba(70, 70, 70, 0.22) !important; 488 | border-radius: 999px !important; 489 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 490 | backdrop-filter: var(--backdrop-filter); 491 | border: 1px solid rgba(255, 255, 255, 0.1) !important; 492 | opacity: 1 !important; 493 | } 494 | 495 | .hero-overlay-button-watch { 496 | background: rgb(0 0 0 / 41%) !important; 497 | border-radius: 999px !important; 498 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 rgba(0, 0, 0, 0.1); 499 | backdrop-filter: var(--backdrop-filter); 500 | opacity: 1 !important; 501 | } 502 | 503 | .hero-overlay-button-watch:hover, 504 | .hero-overlay-button:hover { 505 | background: rgba(255, 255, 255, 0.1) !important; 506 | } 507 | 508 | /* only do this if */ 509 | #app [class*="nav-tab-button-container"]:not(.selected) .board-container-DTN_b .board-content-container-ToQTz .board-content-nPWv1 { 510 | padding: 0; 511 | } 512 | 513 | .discover-container-L6OGL .discover-content-CRsRg .catalog-container-VNK_T .selectable-inputs-container-IRz50 { 514 | margin-top: 60px !important; 515 | } 516 | 517 | #app [class*="nav-tab-button-container"]:not(.selected) .meta-item-container-Tj0Ib { 518 | overflow: visible; 519 | padding: 0.2rem; 520 | } 521 | 522 | .library-container-zM_bj .library-content-PgX4O .selectable-inputs-container-hR3or { 523 | margin-top: 4.3rem !important; 524 | } 525 | 526 | .calendar-cH2jw .content-wBwrQ { 527 | margin-top: 6rem !important; 528 | padding: 0 !important; 529 | } 530 | 531 | .addons-container-ogGYu .addons-content-zhFBl .selectable-inputs-container-tUul1 { 532 | margin-top: 4.6rem !important; 533 | } 534 | 535 | .settings-container-_g1tS .settings-content-co5eU .sections-container-ZaZpD { 536 | padding: 5rem 3rem !important; 537 | } 538 | 539 | .discover-container-L6OGL .discover-content-CRsRg .catalog-container-VNK_T .meta-items-container-n8vNz { 540 | padding: 0; 541 | z-index: 1; 542 | } 543 | 544 | .discover-container-L6OGL .discover-content-CRsRg .catalog-container-VNK_T .meta-items-container-n8vNz { 545 | align-items: center; 546 | align-self: stretch; 547 | display: grid; 548 | flex: 1; 549 | grid-auto-rows: max-content; 550 | grid-gap: 0; 551 | margin-right: 1rem; 552 | overflow-y: auto; 553 | } 554 | 555 | .search-container-uXEFf .search-content-LX6un { 556 | height: 100%; 557 | overflow-y: auto; 558 | padding: 0 1rem; 559 | padding-top: 4.5rem; 560 | width: 100%; 561 | } 562 | 563 | /* hero */ 564 | .hero-controls { 565 | position: absolute; 566 | top: 20px; 567 | right: 20px; 568 | display: flex; 569 | gap: 8px; 570 | z-index: 10; 571 | } 572 | 573 | .hero-control-btn { 574 | background: rgba(0, 0, 0, 0.5); 575 | color: white; 576 | border: none; 577 | padding: 8px 12px; 578 | border-radius: 20px; 579 | cursor: pointer; 580 | font-size: 12px; 581 | font-weight: 500; 582 | transition: all 0.2s ease; 583 | backdrop-filter: blur(10px); 584 | border: 1px solid rgba(255, 255, 255, 0.1); 585 | visibility: hidden; 586 | } 587 | 588 | .hero-control-btn:hover { 589 | background: rgba(0, 0, 0, 0.7); 590 | transform: scale(1.05); 591 | } 592 | 593 | .hero-indicators { 594 | position: absolute; 595 | bottom: 10px; 596 | left: 50%; 597 | transform: translateX(-50%); 598 | display: flex; 599 | gap: 8px; 600 | z-index: 10; 601 | } 602 | 603 | .hero-indicator { 604 | width: 10px; 605 | height: 10px; 606 | border-radius: 50%; 607 | background: rgba(255, 255, 255, 0.4); 608 | cursor: pointer; 609 | transition: all 0.3s ease; 610 | border: 1px solid rgba(255, 255, 255, 0.2); 611 | } 612 | 613 | .hero-indicator:hover { 614 | background: rgba(255, 255, 255, 0.6); 615 | transform: scale(1.2); 616 | } 617 | 618 | .hero-indicator.active { 619 | background: rgba(255, 255, 255, 0.9); 620 | } 621 | 622 | #heroImage, #heroLogo, #heroDescription, #heroInfo { 623 | transition: opacity 0.3s ease-in-out; 624 | } 625 | 626 | .hero-overlay-button-watch svg, 627 | .hero-overlay-button svg { 628 | margin-right: 4px; 629 | } 630 | 631 | /* IMDB Icon and Rating Styles */ 632 | .rating-item { 633 | display: flex; 634 | align-items: center; 635 | gap: 4px; 636 | } 637 | 638 | .imdb-icon { 639 | width: 16px; 640 | height: 16px; 641 | fill: #f5c518; 642 | color: #f5c518; 643 | flex-shrink: 0; 644 | } 645 | 646 | #heroLoadingScreen { 647 | position: fixed !important; 648 | top: 0 !important; 649 | left: 0 !important; 650 | width: 100vw !important; 651 | height: 100vh !important; 652 | z-index: 999999 !important; 653 | transform: none !important; 654 | margin: 0 !important; 655 | padding: 0 !important; 656 | display: flex !important; 657 | align-items: center !important; 658 | justify-content: center !important; 659 | } 660 | 661 | .loading-backdrop { 662 | position: absolute; 663 | top: 0; 664 | left: 0; 665 | width: 100%; 666 | height: 100%; 667 | background: linear-gradient(135deg, #0c0c0c 0%, #1a1a1a 50%, #0c0c0c 100%); 668 | background-size: 400% 400%; 669 | animation: gradientShift 8s ease-in-out infinite; 670 | } 671 | 672 | .loading-content { 673 | position: relative !important; 674 | z-index: 10; 675 | text-align: center; 676 | color: white; 677 | transform: none !important; 678 | top: auto !important; 679 | left: auto !important; 680 | } 681 | 682 | #heroLoadingScreen .loading-content { 683 | position: absolute !important; 684 | top: 50% !important; 685 | left: 50% !important; 686 | transform: translate(-50%, -50%) !important; 687 | } 688 | 689 | /* Prevent any interference during ghost clicks */ 690 | body.ghost-clicking { 691 | overflow: hidden !important; 692 | } 693 | 694 | body.ghost-clicking #heroLoadingScreen { 695 | position: fixed !important; 696 | top: 0 !important; 697 | left: 0 !important; 698 | transform: none !important; 699 | } 700 | 701 | 702 | 703 | .loading-logo-container { 704 | position: relative; 705 | display: inline-block; 706 | height: 100px; 707 | margin-bottom: 30px; 708 | } 709 | 710 | .loading-logo { 711 | width: 80px; 712 | height: 80px; 713 | object-fit: contain; 714 | animation: logoFloat 3s ease-in-out infinite; 715 | position: relative; 716 | z-index: 2; 717 | } 718 | 719 | .loading-pulse { 720 | position: absolute; 721 | top: 50%; 722 | left: 50%; 723 | transform: translate(-50%, -50%); 724 | width: 120px; 725 | height: 120px; 726 | border-radius: 50%; 727 | animation: pulse 2s ease-in-out infinite; 728 | } 729 | 730 | .loading-text { 731 | font-size: 16px; 732 | font-weight: 400; 733 | color: rgba(255, 255, 255, 0.9); 734 | margin-bottom: 20px; 735 | min-height: 20px; 736 | transition: all 0.3s ease; 737 | text-shadow: 0 0 10px rgba(139, 69, 255, 0.3); 738 | } 739 | 740 | .loading-bar { 741 | width: 200px; 742 | height: 2px; 743 | background: rgba(255, 255, 255, 0.1); 744 | border-radius: 1px; 745 | overflow: hidden; 746 | margin: 0 auto; 747 | position: relative; 748 | } 749 | 750 | .loading-progress { 751 | height: 100%; 752 | background: linear-gradient(90deg, #fff); 753 | background-size: 200% 100%; 754 | border-radius: 1px; 755 | width: 0%; 756 | transition: width 0.5s ease; 757 | animation: shimmer 2s linear infinite; 758 | } 759 | 760 | @keyframes gradientShift { 761 | 0%, 100% { background-position: 0% 50%; } 762 | 50% { background-position: 100% 50%; } 763 | } 764 | 765 | @keyframes logoFloat { 766 | 0%, 100% { transform: translateY(0px); } 767 | 50% { transform: translateY(-10px); } 768 | } 769 | 770 | @keyframes pulse { 771 | 0%, 100% { 772 | transform: translate(-50%, -50%) scale(1); 773 | opacity: 0.7; 774 | } 775 | 50% { 776 | transform: translate(-50%, -50%) scale(1.2); 777 | opacity: 0.3; 778 | } 779 | } 780 | 781 | @keyframes shimmer { 782 | 0% { background-position: -200% 0%; } 783 | 100% { background-position: 200% 0%; } 784 | } 785 | 786 | /* ========================= ENHANCED VERTICAL NAV ANIMATIONS ========================= */ 787 | 788 | /* Base nav container with smooth positioning */ 789 | #app [class*="vertical-nav-bar-container"] { 790 | align-items: center !important; 791 | background-color: transparent !important; 792 | display: flex !important; 793 | flex-direction: row !important; 794 | gap: 1rem !important; 795 | overflow-y: auto !important; 796 | padding: 1rem 0 !important; 797 | scrollbar-width: none !important; 798 | width: auto !important; 799 | position: relative !important; 800 | } 801 | 802 | /* Enhanced nav button base styling with smooth transitions */ 803 | #app [class*="nav-tab-button-container"] { 804 | position: relative !important; 805 | overflow: hidden !important; 806 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 807 | border-radius: 999px !important; 808 | transform: translateZ(0) !important; /* Hardware acceleration */ 809 | will-change: transform, background-color, box-shadow !important; 810 | } 811 | 812 | /* Smooth hover effects for non-selected tabs */ 813 | #app [class*="nav-tab-button-container"]:not(.selected):hover { 814 | background: rgba(90, 90, 90, 0.15) !important; 815 | transform: translateY(-2px) scale(1.02) !important; 816 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important; 817 | } 818 | 819 | /* Enhanced selected tab styling with smoother appearance */ 820 | #app [class*="nav-tab-button-container"].selected { 821 | background: rgba(70, 70, 70, 0.22) !important; 822 | border-radius: 999px !important; 823 | box-shadow: 824 | 0 8px 32px rgba(0, 0, 0, 0.2) , 825 | 0 4px 16px rgba(0, 0, 0, 0.1) , 826 | inset 0 1px 0 rgba(255, 255, 255, 0.15) , 827 | inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 828 | backdrop-filter: var(--backdrop-filter) !important; 829 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 830 | opacity: 1 !important; 831 | transform: translateY(0px) scale(1) !important; 832 | } 833 | 834 | /* Smooth nav label animations */ 835 | .nav-label { 836 | color: var(--primary-accent-color) !important; 837 | font-weight: 600 !important; 838 | padding: 0 5px !important; 839 | transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important; 840 | will-change: color, transform !important; 841 | } 842 | 843 | /* Selected label enhancement */ 844 | #app [class*="nav-tab-button-container"].selected .nav-label { 845 | color: #ffffff !important; 846 | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) !important; 847 | transform: translateY(0) !important; 848 | } 849 | 850 | /* Non-selected label subtle animation */ 851 | #app [class*="nav-tab-button-container"]:not(.selected) .nav-label { 852 | color: rgba(255, 255, 255, 0.7) !important; 853 | transform: translateY(1px) !important; 854 | } 855 | 856 | /* Hover effect for labels */ 857 | #app [class*="nav-tab-button-container"]:not(.selected):hover .nav-label { 858 | color: rgba(255, 255, 255, 0.9) !important; 859 | transform: translateY(0) !important; 860 | } 861 | 862 | /* Enhanced nav button sizing/padding with transitions */ 863 | #app [class*="vertical-nav-bar-container"] [class*="nav-tab-button"] { 864 | min-height: auto !important; 865 | height: auto !important; 866 | width: auto !important; 867 | padding: 7px 10px !important; 868 | transition: padding 0.2s ease-out !important; 869 | } 870 | 871 | /* Subtle active/press animation */ 872 | #app [class*="nav-tab-button-container"]:active { 873 | transform: translateY(1px) scale(0.98) !important; 874 | transition: all 0.1s ease-out !important; 875 | } 876 | 877 | /* Smooth focus states */ 878 | #app [class*="nav-tab-button-container"]:focus { 879 | outline: 2px solid rgba(255, 255, 255, 0.3) !important; 880 | outline-offset: 2px !important; 881 | transition: outline 0.2s ease-out !important; 882 | } 883 | 884 | /* Activate the indicator when any tab is hovered */ 885 | #app [class*="vertical-nav-bar-container"]:hover::before { 886 | transform: translateY(-50%) scaleX(1) !important; 887 | } 888 | 889 | .menu-xeE06 { 890 | padding: 7rem 1.5rem !important; 891 | } 892 | 893 | .custom-episode-title { 894 | font-size: 1em !important; 895 | font-weight: normal !important; 896 | margin-left: 11px !important; 897 | color: rgb(204, 204, 204) !important; 898 | } 899 | 900 | .custom-series-name { 901 | font-size: 2.4rem !important; 902 | font-weight: bold !important; 903 | margin-bottom: 4px !important; 904 | margin-left: 11px !important; 905 | color: rgb(255, 255, 255) !important; 906 | } 907 | 908 | .seek-bar-container-JGGTa .label-QFbsS { 909 | width: none !important; 910 | } 911 | 912 | .control-bar-container-xsWA7 .control-bar-buttons-container-SWhkU .control-bar-button-FQUsj .icon-qy6I6 { 913 | height: 2.3rem !important; 914 | } 915 | 916 | .control-bar-container-xsWA7 .control-bar-buttons-container-SWhkU .control-bar-button-FQUsj { 917 | height: none !important; 918 | } 919 | 920 | .control-bar-container-xsWA7 .control-bar-buttons-container-SWhkU { 921 | align-items: center; 922 | display: flex; 923 | flex-direction: row; 924 | background: rgba(70, 70, 70, 0.22) !important; 925 | border-radius: 20px !important; 926 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 927 | backdrop-filter: var(--backdrop-filter) !important; 928 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 929 | margin-bottom: 15px !important; 930 | margin-top: 5px !important; 931 | height: 50px !important; 932 | } 933 | 934 | .slider-container-nJz5F .track-gItfW { 935 | background: rgba(255, 255, 255, 0.62) !important; 936 | border-radius: 999px !important; 937 | backdrop-filter: var(--backdrop-filter) !important; 938 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 939 | flex: 1; 940 | height: var(--track-size); 941 | width: 100%; 942 | z-index: 0; 943 | } 944 | 945 | .seek-bar-container-JGGTa .slider-hBDOf { 946 | margin: none !important; 947 | } 948 | 949 | .icon-qy6I6 { 950 | width: 2.3rem !important; 951 | } 952 | 953 | .control-bar-container-xsWA7 .control-bar-buttons-container-SWhkU .control-bar-button-FQUsj:hover { 954 | background: rgba(255, 255, 255, 0.1) !important; 955 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important; 956 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 957 | } 958 | 959 | .player-container-wIELK .layer-qalDW.side-drawer-button-layer-RrB8k { 960 | left: initial; 961 | position: fixed; 962 | right: -4rem; 963 | top: 50%; 964 | transform: translateY(-50%); 965 | background: rgba(70, 70, 70, 0.22) !important; 966 | border-radius: 999px !important; 967 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 968 | backdrop-filter: var(--backdrop-filter) !important; 969 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 970 | } 971 | 972 | /* ========================= PLAY BUTTON CLEAN HOVER EFFECT ========================= */ 973 | 974 | /* Ensure poster container is positioned for absolute overlays */ 975 | .meta-item-container-Tj0Ib .poster-container-qkw48 { 976 | position: relative !important; 977 | overflow: hidden !important; 978 | } 979 | 980 | /* DEFAULT STATE: Center play button */ 981 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo { 982 | position: absolute !important; 983 | top: 50% !important; 984 | left: 50% !important; 985 | transform: translate(-50%, -50%) !important; 986 | z-index: 10 !important; 987 | display: flex !important; 988 | align-items: center !important; 989 | justify-content: center !important; 990 | margin: 0 !important; 991 | padding: 0 !important; 992 | } 993 | 994 | /* Hide ALL background layers that create dark squares/boxes behind play button */ 995 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo .play-icon-background-Uazjh, 996 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo .play-icon-background-Uazjh::before, 997 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo .play-icon-background-Uazjh::after, 998 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo [class*="background"], 999 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo [class*="backdrop"] { 1000 | display: none !important; 1001 | opacity: 0 !important; 1002 | visibility: hidden !important; 1003 | background: transparent !important; 1004 | } 1005 | 1006 | /* Default play button ring - subtle and clean */ 1007 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo .play-icon-outer-r3iKR { 1008 | background: rgba(255, 255, 255, 0.3) !important; 1009 | border-radius: 999px !important; 1010 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.5) !important; 1011 | backdrop-filter: blur(12px) saturate(160%) !important; 1012 | border: 1px solid rgba(255, 255, 255, 0.2) !important; 1013 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1014 | } 1015 | 1016 | /* Default play icon color */ 1017 | .meta-item-container-Tj0Ib .poster-container-qkw48 .play-icon-layer-vpQIo .play-icon-QmEEA { 1018 | color: rgba(255, 255, 255, 0.9) !important; 1019 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1020 | } 1021 | 1022 | /* Create full-poster gray overlay on hover (hidden by default) */ 1023 | .meta-item-container-Tj0Ib .poster-container-qkw48::before { 1024 | content: ''; 1025 | position: absolute !important; 1026 | top: 0 !important; 1027 | left: 0 !important; 1028 | right: 0 !important; 1029 | bottom: 0 !important; 1030 | width: 100% !important; 1031 | height: 100% !important; 1032 | background: rgba(0, 0, 0, 0.4) !important; 1033 | opacity: 0 !important; 1034 | z-index: 5 !important; 1035 | pointer-events: none !important; 1036 | transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1037 | border-radius: inherit !important; 1038 | } 1039 | 1040 | /* HOVER STATE: Show gray overlay over entire poster */ 1041 | .meta-item-container-Tj0Ib .poster-container-qkw48:hover::before { 1042 | opacity: 1 !important; 1043 | } 1044 | 1045 | /* HOVER STATE: Frosted white glass play button ring */ 1046 | .meta-item-container-Tj0Ib .poster-container-qkw48:hover .play-icon-layer-vpQIo .play-icon-outer-r3iKR { 1047 | background: rgba(255, 255, 255, 0.45) !important; 1048 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.6), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1049 | backdrop-filter: blur(16px) saturate(200%) brightness(110%) !important; 1050 | border: 1.5px solid rgba(255, 255, 255, 0.5) !important; 1051 | transform: scale(1.02) !important; 1052 | } 1053 | 1054 | /* HOVER STATE: Bright white play icon */ 1055 | .meta-item-container-Tj0Ib .poster-container-qkw48:hover .play-icon-layer-vpQIo .play-icon-QmEEA { 1056 | color: rgba(255, 255, 255, 1) !important; 1057 | filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3)) !important; 1058 | } 1059 | 1060 | /* ========================= WATCHED FLAG GLASS STYLING ========================= */ 1061 | 1062 | /* Watched flag container - keep original position */ 1063 | .upcoming-watched-container-msCaq { 1064 | z-index: 20 !important; 1065 | } 1066 | 1067 | /* Watched flag inner container - glass morphism with yellow tinge */ 1068 | .upcoming-watched-container-msCaq .watched-container-gvzs3 { 1069 | display: flex !important; 1070 | align-items: center !important; 1071 | gap: 6px !important; 1072 | padding: 6px 12px !important; 1073 | background: rgba(255, 220, 100, 0.35) !important; 1074 | border-radius: 999px !important; 1075 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 240, 150, 0.5) !important; 1076 | backdrop-filter: blur(12px) saturate(160%) !important; 1077 | border: 1px solid rgba(255, 200, 80, 0.4) !important; 1078 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1079 | } 1080 | 1081 | /* Hover effect for watched flag */ 1082 | .upcoming-watched-container-msCaq .watched-container-gvzs3:hover { 1083 | background: rgba(255, 210, 80, 0.45) !important; 1084 | box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 240, 150, 0.6) !important; 1085 | backdrop-filter: blur(14px) saturate(180%) brightness(105%) !important; 1086 | border: 1px solid rgba(255, 190, 60, 0.5) !important; 1087 | transform: scale(1.02) !important; 1088 | } 1089 | 1090 | /* Watched flag icon */ 1091 | .upcoming-watched-container-msCaq .flag-icon-RDrvf { 1092 | width: 14px !important; 1093 | height: 14px !important; 1094 | color: rgba(255, 255, 255, 0.95) !important; 1095 | filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3)) !important; 1096 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1097 | } 1098 | 1099 | /* Watched flag label */ 1100 | .upcoming-watched-container-msCaq .flag-label-zJloD { 1101 | font-size: 12px !important; 1102 | font-weight: 600 !important; 1103 | color: rgba(255, 255, 255, 0.95) !important; 1104 | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) !important; 1105 | letter-spacing: 0.3px !important; 1106 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1107 | } 1108 | 1109 | /* Enhance on hover */ 1110 | .upcoming-watched-container-msCaq .watched-container-gvzs3:hover .flag-icon-RDrvf, 1111 | .upcoming-watched-container-msCaq .watched-container-gvzs3:hover .flag-label-zJloD { 1112 | color: rgba(255, 255, 255, 1) !important; 1113 | filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.4)) !important; 1114 | } 1115 | 1116 | /* ========================= UPCOMING FLAG GLASS STYLING (GREEN) ========================= */ 1117 | 1118 | /* Upcoming flag container - keep original position */ 1119 | .upcoming-watched-container-msCaq { 1120 | z-index: 20 !important; 1121 | } 1122 | 1123 | /* Upcoming flag inner container - glass morphism with green tinge */ 1124 | .upcoming-watched-container-msCaq .upcoming-container-LXfQ7 { 1125 | display: flex !important; 1126 | align-items: center !important; 1127 | gap: 6px !important; 1128 | padding: 6px 12px !important; 1129 | background: rgba(100, 255, 150, 0.35) !important; 1130 | border-radius: 999px !important; 1131 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(150, 255, 180, 0.5) !important; 1132 | backdrop-filter: blur(12px) saturate(160%) !important; 1133 | border: 1px solid rgba(80, 255, 120, 0.4) !important; 1134 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1135 | } 1136 | 1137 | /* Hover effect for upcoming flag */ 1138 | .upcoming-watched-container-msCaq .upcoming-container-LXfQ7:hover { 1139 | background: rgba(90, 255, 140, 0.45) !important; 1140 | box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(150, 255, 180, 0.6) !important; 1141 | backdrop-filter: blur(14px) saturate(180%) brightness(105%) !important; 1142 | border: 1px solid rgba(70, 255, 110, 0.5) !important; 1143 | transform: scale(1.02) !important; 1144 | } 1145 | 1146 | /* Upcoming flag label */ 1147 | .upcoming-watched-container-msCaq .upcoming-container-LXfQ7 .flag-label-zJloD { 1148 | font-size: 12px !important; 1149 | font-weight: 600 !important; 1150 | color: rgba(255, 255, 255, 0.95) !important; 1151 | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) !important; 1152 | letter-spacing: 0.3px !important; 1153 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1154 | } 1155 | 1156 | /* Enhance on hover */ 1157 | .upcoming-watched-container-msCaq .upcoming-container-LXfQ7:hover .flag-label-zJloD { 1158 | color: rgba(255, 255, 255, 1) !important; 1159 | filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.4)) !important; 1160 | } 1161 | 1162 | .meta-item-container-Tj0Ib { 1163 | overflow: hidden; 1164 | } 1165 | 1166 | .custom-icon { 1167 | width: 1.9rem !important; 1168 | height: 1.6rem !important; 1169 | } 1170 | 1171 | /* SHIT CODE WARNING 1172 | TODO: Clean up this code cant rn cuz im lazy */ 1173 | .nav-menu-container-Pl25j, .nav-menu-container-Pl25j { 1174 | background: rgba(70, 70, 70, 0.22) !important; 1175 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1176 | backdrop-filter: var(--backdrop-filter) !important; 1177 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1178 | } 1179 | 1180 | .meta-links-container-dh69_ .links-container-C8Mw9 .link-container-gHxPW { 1181 | background: rgba(70, 70, 70, 0.22) !important; 1182 | backdrop-filter: var(--backdrop-filter) !important; 1183 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1184 | box-shadow: 0 0px 0px rgba(0, 0, 0, 0.2), 0 0px 10px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1185 | } 1186 | 1187 | .meta-preview-container-o22hc .action-buttons-container-XbKVa .action-button-XIZa3.wide { 1188 | background: rgba(70, 70, 70, 0.22) !important; 1189 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1190 | backdrop-filter: var(--backdrop-filter) !important; 1191 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1192 | } 1193 | 1194 | .meta-preview-container-o22hc .ratings-zUtHH { 1195 | background: rgba(70, 70, 70, 0.22) !important; 1196 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1197 | backdrop-filter: var(--backdrop-filter) !important; 1198 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1199 | } 1200 | 1201 | .meta-preview-container-o22hc .action-buttons-container-XbKVa .action-button-XIZa3 { 1202 | background: rgba(70, 70, 70, 0.22) !important; 1203 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1204 | backdrop-filter: var(--backdrop-filter) !important; 1205 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1206 | } 1207 | 1208 | .chip-L3r9A.active-jnhyP { 1209 | background: rgba(70, 70, 70, 0.22) !important; 1210 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1211 | backdrop-filter: var(--backdrop-filter) !important; 1212 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1213 | } 1214 | 1215 | .addon-details-modal-container-aBFaQ .cancel-button-zuUX6 { 1216 | background: rgba(70, 70, 70, 0.22) !important; 1217 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1218 | backdrop-filter: var(--backdrop-filter) !important; 1219 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1220 | opacity: 1; 1221 | } 1222 | 1223 | .modal-container-OuxEF .modal-dialog-container-DZMKq { 1224 | background: rgba(70, 70, 70, 0.22) !important; 1225 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1226 | backdrop-filter: var(--backdrop-filter) !important; 1227 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1228 | } 1229 | 1230 | .meta-item-container-Tj0Ib .poster-container-qkw48, 1231 | .meta-item-container-Tj0Ib .poster-image-NiV7O { 1232 | position: relative !important; /* ensure overlay absolutely positions over poster */ 1233 | } 1234 | 1235 | /* Make sure the watched layer covers the full poster image (not the small icon circle) */ 1236 | .meta-item-container-Tj0Ib .poster-container-qkw48 .watched-icon-layer-bi3DO, 1237 | .meta-item-container-Tj0Ib .poster-image-NiV7O .watched-icon-layer-bi3DO { 1238 | position: absolute !important; 1239 | top: 0 !important; 1240 | left: 0 !important; 1241 | width: 100% !important; 1242 | height: 100% !important; 1243 | display: flex !important; 1244 | flex-direction: column !important; 1245 | align-items: center !important; 1246 | justify-content: center !important; 1247 | gap: 8px !important; 1248 | background: rgba(0, 0, 0, 0.55) !important; /* darken the poster image */ 1249 | color: #fff !important; 1250 | z-index: 50 !important; 1251 | border-radius: inherit !important; 1252 | backdrop-filter: var(--backdrop-filter) !important; 1253 | border: 0 !important; 1254 | pointer-events: none !important; /* let clicks pass through if needed */ 1255 | opacity: 1 !important; 1256 | transition: opacity 0.25s ease !important; 1257 | } 1258 | 1259 | /* Hide any existing inner icons/svg so only our pseudo-elements show */ 1260 | .meta-item-container-Tj0Ib .poster-container-qkw48 .watched-icon-layer-bi3DO > *, 1261 | .meta-item-container-Tj0Ib .poster-image-NiV7O .watched-icon-layer-bi3DO > *, 1262 | .meta-item-container-Tj0Ib .poster-container-qkw48 .watched-icon-layer-bi3DO svg, 1263 | .meta-item-container-Tj0Ib .poster-image-NiV7O .watched-icon-layer-bi3DO svg, 1264 | .meta-item-container-Tj0Ib .poster-container-qkw48 .watched-icon-layer-bi3DO .icon, 1265 | .meta-item-container-Tj0Ib .poster-image-NiV7O .watched-icon-layer-bi3DO .icon { 1266 | display: none !important; 1267 | } 1268 | 1269 | /* Ensure no padding/margins interfere with centering */ 1270 | .meta-item-container-Tj0Ib .poster-container-qkw48 .watched-icon-layer-bi3DO, 1271 | .meta-item-container-Tj0Ib .poster-image-NiV7O .watched-icon-layer-bi3DO { 1272 | padding: 0 !important; 1273 | margin: 0 !important; 1274 | box-sizing: border-box !important; 1275 | } 1276 | 1277 | /* White checkmark */ 1278 | .meta-item-container-Tj0Ib .poster-container-qkw48 .watched-icon-layer-bi3DO::before, 1279 | .meta-item-container-Tj0Ib .poster-image-NiV7O .watched-icon-layer-bi3DO::before { 1280 | content: ''; 1281 | display: block; 1282 | width: 32px; 1283 | height: 20px; 1284 | border-left: 4px solid #fff; 1285 | border-bottom: 4px solid #fff; 1286 | transform: rotate(-45deg); 1287 | margin-bottom: 6px; /* spacing between check and label */ 1288 | box-sizing: border-box; 1289 | } 1290 | 1291 | /* Watched label */ 1292 | .meta-item-container-Tj0Ib .poster-container-qkw48 .watched-icon-layer-bi3DO::after, 1293 | .meta-item-container-Tj0Ib .poster-image-NiV7O .watched-icon-layer-bi3DO::after { 1294 | content: 'Watched'; 1295 | display: block; 1296 | color: #fff; 1297 | font-weight: 700; 1298 | font-size: 14px; 1299 | letter-spacing: 0.6px; 1300 | text-transform: none; 1301 | } 1302 | 1303 | .dropdown-MWaxp { 1304 | background: rgba(70, 70, 70, 0.22) !important; 1305 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1306 | backdrop-filter: var(--backdrop-filter) !important; 1307 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1308 | } 1309 | 1310 | .search-bar-container-p4tSt { 1311 | background: rgba(70, 70, 70, 0.22) !important; 1312 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1313 | backdrop-filter: var(--backdrop-filter) !important; 1314 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1315 | } 1316 | 1317 | .addons-container-ogGYu .addons-content-zhFBl .selectable-inputs-container-tUul1 .select-input-container-KqG8N { 1318 | background: rgba(70, 70, 70, 0.22) !important; 1319 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1320 | backdrop-filter: var(--backdrop-filter) !important; 1321 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1322 | } 1323 | 1324 | .add-addon-modal-container-KR5ny .modal-dialog-content-Xgv7Z .addon-url-input-ucetZ:focus, .add-addon-modal-container-KR5ny .modal-dialog-content-Xgv7Z .addon-url-input-ucetZ:hover { 1325 | background: rgba(70, 70, 70, 0.22) !important; 1326 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1327 | backdrop-filter: var(--backdrop-filter) !important; 1328 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1329 | } 1330 | 1331 | .option-vFOAS .content-P2T0i .button { 1332 | background: rgba(70, 70, 70, 0.22) !important; 1333 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1334 | backdrop-filter: var(--backdrop-filter) !important; 1335 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1336 | } 1337 | 1338 | .multiselect-menu-qMdaj .multiselect-button-XXdgA { 1339 | background: rgba(70, 70, 70, 0.22) !important; 1340 | box-shadow: 0 8px 0.1px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1341 | backdrop-filter: var(--backdrop-filter) !important; 1342 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1343 | } 1344 | 1345 | .cell-l3eWl.today-G8kuO .heading-TYXvp .day-nttmc { 1346 | background: rgba(70, 70, 70, 0.22) !important; 1347 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1348 | backdrop-filter: var(--backdrop-filter) !important; 1349 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1350 | } 1351 | 1352 | .shortcut-container-iOrn9 kbd { 1353 | background: rgba(70, 70, 70, 0.22) !important; 1354 | box-shadow: 0 8px 0px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1355 | backdrop-filter: var(--backdrop-filter) !important; 1356 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1357 | } 1358 | 1359 | .library-container-zM_bj .library-content-PgX4O .selectable-inputs-container-hR3or .select-input-container-H1VZ1 { 1360 | /* background-color: var(--overlay-color); */ 1361 | flex-basis: 20rem; 1362 | flex-grow: 0; 1363 | flex-shrink: 1; 1364 | height: 3.2rem; 1365 | background: rgba(70, 70, 70, 0.22) !important; 1366 | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.1) !important; 1367 | backdrop-filter: var(--backdrop-filter) !important; 1368 | border: 1px solid rgba(255, 255, 255, 0.04) !important; 1369 | } 1370 | 1371 | /* ========================= SIDE DRAWER (EPISODE LIST) GLASS STYLING ========================= */ 1372 | 1373 | /* Side drawer main container - glass background */ 1374 | .side-drawer-r9EuA.side-drawer-layer-CZtJ1 { 1375 | background: rgba(20, 20, 20, 0.85) !important; 1376 | backdrop-filter: blur(20px) saturate(140%) !important; 1377 | border-left: 1px solid rgba(255, 255, 255, 0.08) !important; 1378 | box-shadow: -4px 0 24px rgba(0, 0, 0, 0.3) !important; 1379 | } 1380 | 1381 | /* Close button - glass style */ 1382 | .side-drawer-r9EuA .close-button-ruzkn { 1383 | background: rgba(70, 70, 70, 0.25) !important; 1384 | border-radius: 999px !important; 1385 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2) !important; 1386 | backdrop-filter: blur(10px) !important; 1387 | border: 1px solid rgba(255, 255, 255, 0.1) !important; 1388 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1389 | } 1390 | 1391 | .side-drawer-r9EuA .close-button-ruzkn:hover { 1392 | background: rgba(90, 90, 90, 0.35) !important; 1393 | box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.3) !important; 1394 | transform: scale(1.05) !important; 1395 | } 1396 | 1397 | /* Season navigation buttons */ 1398 | .seasons-bar-container-nOZjG .prev-season-button-bs1GQ, 1399 | .seasons-bar-container-nOZjG .next-season-button-RrYAq { 1400 | background: rgba(70, 70, 70, 0.25) !important; 1401 | border-radius: 8px !important; 1402 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.15) !important; 1403 | backdrop-filter: blur(10px) !important; 1404 | border: 1px solid rgba(255, 255, 255, 0.1) !important; 1405 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1406 | } 1407 | 1408 | .seasons-bar-container-nOZjG .prev-season-button-bs1GQ:not(.disabled):hover, 1409 | .seasons-bar-container-nOZjG .next-season-button-RrYAq:not(.disabled):hover { 1410 | background: rgba(90, 90, 90, 0.35) !important; 1411 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25) !important; 1412 | transform: translateY(-1px) !important; 1413 | } 1414 | 1415 | .seasons-bar-container-nOZjG .prev-season-button-bs1GQ.disabled, 1416 | .seasons-bar-container-nOZjG .next-season-button-RrYAq.disabled { 1417 | opacity: 0.4 !important; 1418 | } 1419 | 1420 | /* Season selector dropdown */ 1421 | .seasons-bar-container-nOZjG .multiselect-menu-qMdaj .multiselect-button-XXdgA { 1422 | background: rgba(70, 70, 70, 0.25) !important; 1423 | border-radius: 8px !important; 1424 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.15) !important; 1425 | backdrop-filter: blur(10px) !important; 1426 | border: 1px solid rgba(255, 255, 255, 0.1) !important; 1427 | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; 1428 | } 1429 | 1430 | .seasons-bar-container-nOZjG .multiselect-menu-qMdaj .multiselect-button-XXdgA:hover { 1431 | background: rgba(90, 90, 90, 0.35) !important; 1432 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25) !important; 1433 | } 1434 | 1435 | /* Episode list items - glass cards */ 1436 | .side-drawer-r9EuA .video-container-ezBpK { 1437 | background: rgba(50, 50, 50, 0.2) !important; 1438 | border-radius: 12px !important; 1439 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.08) !important; 1440 | backdrop-filter: blur(8px) !important; 1441 | border: 1px solid rgba(255, 255, 255, 0.06) !important; 1442 | margin-bottom: 8px !important; 1443 | } 1444 | 1445 | /* Episode thumbnail styling */ 1446 | .side-drawer-r9EuA .thumbnail-container-Zm8Cl { 1447 | border-radius: 8px !important; 1448 | overflow: hidden !important; 1449 | position: relative !important; 1450 | } 1451 | 1452 | /* Play button icon in side drawer - frosted glass style */ 1453 | .side-drawer-r9EuA .icon-rAZvO, 1454 | .side-drawer-r9EuA svg[viewBox="0 0 512 512"]:has(path[d*="231.137"]) { 1455 | width: 48px !important; 1456 | height: 48px !important; 1457 | padding: 12px !important; 1458 | background: rgba(255, 255, 255, 0.3) !important; 1459 | border-radius: 999px !important; 1460 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.5) !important; 1461 | backdrop-filter: blur(12px) saturate(160%) !important; 1462 | border: 1px solid rgba(255, 255, 255, 0.2) !important; 1463 | color: rgba(255, 255, 255, 0.95) !important; 1464 | } 1465 | 1466 | /* Container for play icon if it exists */ 1467 | .side-drawer-r9EuA .thumbnail-container-Zm8Cl > svg, 1468 | .side-drawer-r9EuA .thumbnail-container-Zm8Cl [class*="icon"] { 1469 | position: absolute !important; 1470 | top: 50% !important; 1471 | left: 50% !important; 1472 | transform: translate(-50%, -50%) !important; 1473 | z-index: 10 !important; 1474 | } 1475 | 1476 | 1477 | 1478 | /* Episode progress bar - glass style */ 1479 | .side-drawer-r9EuA .progress-bar-container-w8eFT { 1480 | background: rgba(255, 255, 255, 0.1) !important; 1481 | border-radius: 2px !important; 1482 | overflow: hidden !important; 1483 | } 1484 | 1485 | .side-drawer-r9EuA .progress-bar-E23CT { 1486 | background: rgba(255, 255, 255, 0.9) !important; 1487 | box-shadow: 0 0 8px rgba(255, 255, 255, 0.5) !important; 1488 | border-radius: 2px !important; 1489 | } 1490 | 1491 | .side-drawer-r9EuA .progress-bar-background-Q7aEH { 1492 | background: rgba(0, 0, 0, 0.2) !important; 1493 | } 1494 | 1495 | /* Episode title styling */ 1496 | .side-drawer-r9EuA .title-container-NcfV9 { 1497 | font-weight: 600 !important; 1498 | color: rgba(255, 255, 255, 0.95) !important; 1499 | } 1500 | 1501 | /* Release date label */ 1502 | .side-drawer-r9EuA .released-container-XLPqf { 1503 | color: rgba(255, 255, 255, 0.6) !important; 1504 | font-size: 11px !important; 1505 | } 1506 | 1507 | /* Meta preview container at top */ 1508 | .side-drawer-r9EuA .side-drawer-meta-preview-pB8v6 { 1509 | background: rgba(50, 50, 50, 0.25) !important; 1510 | border-radius: 12px !important; 1511 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1) !important; 1512 | backdrop-filter: blur(12px) !important; 1513 | border: 1px solid rgba(255, 255, 255, 0.08) !important; 1514 | padding: 16px !important; 1515 | margin-bottom: 16px !important; 1516 | } 1517 | 1518 | /* Show logo */ 1519 | .side-drawer-r9EuA .logo-X3hTV { 1520 | filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.5)) !important; 1521 | } 1522 | 1523 | /* Description text */ 1524 | .side-drawer-r9EuA .description-container-yi8iU { 1525 | color: rgba(255, 255, 255, 0.8) !important; 1526 | line-height: 1.5 !important; 1527 | } 1528 | 1529 | /* Runtime and release labels */ 1530 | .side-drawer-r9EuA .runtime-label-TzAGI, 1531 | .side-drawer-r9EuA .release-info-label-LPJMB { 1532 | color: rgba(255, 255, 255, 0.7) !important; 1533 | font-size: 13px !important; 1534 | } --------------------------------------------------------------------------------