diff --git a/script copy.js b/script copy.js new file mode 100644 index 0000000..b5e5d5c --- /dev/null +++ b/script copy.js @@ -0,0 +1,652 @@ +let title = 'Spotlight'; // Title of the slideshow +let listFileName = 'list.txt'; // Name of the file containing the list of movie IDs +let token = 'YOURAPIKEYHERE'; // Your Jellyfin API key +let moviesSeriesBoth = 3; // 1 for movies, 2 for series, 3 for both +let shuffleInterval = 15000; // Time in milliseconds before the next slide is shown, unless trailer is playing +let useTrailers = true; // Set to false to disable trailers +let setRandomMovie = true; // Set to false to disable random movie selection from the list +let showOnOtherPages = false; // Set to true to show the slideshow on all pages eg. favorites tab, requests tab, etc. +let showTitle = true; // Set to false to hide the title +let plotMaxLength = 550; // Maximum number of characters in the plot +let trailerMaxLength = 0; // Default value 0; length measured in ms + +let isChangingSlide = false, player = null, slideChangeTimeout = null, isHomePageActive = false; +let currentLocation = window.top.location.href; +let movieList = [], currentMovieIndex = 0; +let previousMovies = []; +let forwardMovies = []; + +// Ensure that the video player is muted initially and can be unmuted on hover +const initPlayer = () => { + player = new YT.Player(videoElement, { + height: '100%', + width: '100%', + videoId, + playerVars: { + mute: isMuted ? 1 : 0, + }, + events: { + 'onReady': (event) => { + event.target.playVideo(); + event.target.setVolume(isMuted ? 0 : 100); + }, + 'onStateChange': (event) => { + if (event.data === YT.PlayerState.ENDED) { + setTimeout(fetchRandomMovie, 100); + } + }, + 'onError': () => { + console.error(`Error with YouTube video`); + cleanup(); + } + } + }); +}; + +const slidesContainer = document.getElementById('slides-container'); +slidesContainer.addEventListener('mouseenter', () => { + if (player) { + player.unMute(); + isMuted = false; + } +}); + +slidesContainer.addEventListener('mouseleave', () => { + if (player) { + player.mute(); + isMuted = true; + } +}); +const createElem = (tag, className, textContent, src, alt) => { + const elem = document.createElement(tag); + if (className) elem.className = className; + if (textContent) elem.textContent = textContent; + if (src) elem.src = src; + if (alt) elem.alt = alt; + return elem; +}; + +// Check for screen size below 1000px +function isMobile() { + return window.innerWidth <= 1000; +} + +const truncateText = (text, maxLength) => text.length > maxLength ? text.substr(0, maxLength) + '...' : text; + +const cleanup = () => { + if (player && typeof player.destroy === 'function') { + player.destroy(); + } + player = null; + clearTimeout(slideChangeTimeout); + slideChangeTimeout = null; + const container = document.getElementById('slides-container'); + if (container) container.innerHTML = ''; +}; + +const createSlideElement = (movie, hasVideo = false) => { + cleanup(); + const container = document.getElementById('slides-container'); + const slide = createElem('div', 'slide'); + + if (movie && (!previousMovies.length || previousMovies[previousMovies.length - 1].Id !== movie.Id)) { + previousMovies.push(movie); + } + + if (previousMovies.length > 50) { + previousMovies.shift(); + } + ['backdrop', 'logo'].forEach(type => slide.appendChild(createElem('img', type, null, `/Items/${movie.Id}/Images/${type.charAt(0).toUpperCase() + type.slice(1)}${type === 'backdrop' ? '/0' : ''}`, type))); + slide.appendChild(createElem('div', 'heading', title)); + + const textContainer = createElem('div', 'text-container'); + const premiereYear = movie.PremiereDate ? new Date(movie.PremiereDate).getFullYear() : 'Unknown'; + + let additionalInfo; + + if (movie.Type === 'Series') { + additionalInfo = movie.ChildCount + ? `${movie.ChildCount} Season${movie.ChildCount > 1 ? 's' : ''}` + : 'Unknown Seasons'; + } else if (movie.Type === 'BoxSet') { + additionalInfo = movie.ChildCount + ? `${movie.ChildCount} Movie${movie.ChildCount > 1 ? 's' : ''}` + : 'Unknown Movies'; + } else { + additionalInfo = movie.RunTimeTicks + ? `${Math.round(movie.RunTimeTicks / 600000000)} min` + : 'Unknown Runtime'; + } + + let loremText = ` + ${additionalInfo} + ${premiereYear} `; + + if (movie.CommunityRating) { + loremText += ` + ${movie.CommunityRating.toFixed(1)} + `; + } + if (movie.CriticRating) { + loremText += ` + Rotten Tomatoes + ${movie.CriticRating}%`; + } + + // Age Rating + + const ageRating = movie.OfficialRating ? movie.OfficialRating : 'NR'; + const ratingClass = ageRating.toLowerCase().replace(/ /g, '-'); + + const ageRatingDiv = createElem('div', 'age-rating'); + const ageRatingSpan = createElem('span', ratingClass, ageRating); + ageRatingSpan.style.cssText = 'border: 0.09em solid currentColor; border-radius: .1em; padding: 0.2em; padding-top: 0.125em; padding-bottom: 0.26em; display: inline-block; text-align: center; line-height: 0.8em;'; + ageRatingDiv.appendChild(ageRatingSpan); + slide.appendChild(ageRatingDiv); + + // Genres Section + const genresDiv = createElem('div', 'genres'); + if (movie.Genres && movie.Genres.length > 0) { + movie.Genres.forEach((genre, index) => { + const genreElem = createElem('span', 'genre-item'); + genreElem.textContent = genre; + genreElem.style.backgroundColor = 'transparent'; + genreElem.style.paddingLeft = '0.5em'; + genreElem.style.paddingRight = '0.5em'; + genreElem.style.paddingTop = '0.1em'; + genreElem.style.paddingBottom = '0.1em'; + genreElem.style.color = 'white'; + genreElem.style.borderRadius = '0em'; + genreElem.style.marginRight = '0em'; + genresDiv.appendChild(genreElem); + + if (index < movie.Genres.length - 1) { + const separator = createElem('span', 'material-symbols-outlined'); + separator.textContent = 'stat_0'; // The separator symbol + genresDiv.appendChild(separator); + } + }); + } else { + genresDiv.textContent = 'Genres: N/A'; + } + slide.appendChild(genresDiv); + + const loremDiv = createElem('div', 'lorem-ipsum'); + loremDiv.innerHTML = loremText; + textContainer.appendChild(loremDiv); + textContainer.appendChild(createElem('div', 'plot', truncateText(movie.Overview, plotMaxLength))); + slide.appendChild(textContainer); + + const backButton = createElem('div', 'back-button'); + const backIcon = createElem('i', 'material-icons'); + backIcon.textContent = 'chevron_left'; + backButton.appendChild(backIcon); + backButton.onclick = (e) => { + e.stopPropagation(); + navigateBack(); + }; + + // Skip button logic + const skipButton = createElem('div', 'skip-button'); + const skipIcon = createElem('i', 'material-icons'); + skipIcon.textContent = 'chevron_right'; + skipButton.appendChild(skipIcon); + skipButton.onclick = (e) => { + e.stopPropagation(); + navigateForward(); + }; + + slide.appendChild(backButton); + slide.appendChild(skipButton); + + // Create Details buttons + const buttonsContainer = createElem('div', 'buttons-container'); + + // Details Button + const detailsButton = createElem('button', 'details-button'); + const playIcon = createElem('i', 'fas fa-play'); + detailsButton.appendChild(playIcon); + detailsButton.appendChild(document.createTextNode(' Play')); + detailsButton.onclick = (e) => { + e.stopPropagation(); + window.top.location.href = `/#!/details?id=${movie.Id}`; // Navigate to details page + }; + + // Append buttons to the container + buttonsContainer.appendChild(detailsButton); + slide.appendChild(buttonsContainer); + + const overlay = createElem('div', 'clickable-overlay'); + overlay.onclick = () => window.top.location.href = `/#!/details?id=${movie.Id}`; + slide.appendChild(overlay); + + if (hasVideo && movie.RemoteTrailers && movie.RemoteTrailers.length > 0) { + const trailerUrl = movie.RemoteTrailers[0].Url; + const watchTrailerButton = createElem('button', 'watch-trailer-button'); + const trailerIcon = document.createElement('i'); + trailerIcon.className = 'fas fa-film'; + watchTrailerButton.appendChild(trailerIcon); + watchTrailerButton.appendChild(document.createTextNode('Trailer')); + + watchTrailerButton.onclick = (e) => { + e.stopPropagation(); + if (isMobile()) { + // Show the video in an overlay for mobile + showVideoOverlay(trailerUrl); + } else { + // Open the trailer in a new tab for desktop + window.open(trailerUrl, '_blank'); + } + }; + + buttonsContainer.appendChild(watchTrailerButton); + } + + if (useTrailers && hasVideo && movie.RemoteTrailers?.length > 0) { + const videoId = new URL(movie.RemoteTrailers[0].Url).searchParams.get('v'); + const videoContainer = createElem('div', 'video-container'); + const videoElement = createElem('div', 'video-player'); + videoContainer.appendChild(videoElement); + slide.appendChild(videoContainer); + + player = new YT.Player(videoElement, { + height: '100%', + width: '100%', + videoId, + playerVars: { + mute: 0, // Change to start the video muted MARK: set muted, not officaly refreneced by youtube API, but working... + // autoplay: 1, // Autoplay the video, maybe not necessary here + controls: 0, // Hide the controls + disablekb: 1, // Disable keyboard controls + fs: 1, // Enavle fullscreen + rel: 0, // Disable related videos + modestbranding: 1, // Hide the YouTube logo + showinfo: 0, // Hide the video title + }, + events: { + 'onReady': event => { + if (trailerMaxLength > 0) { + clearTimeout(slideChangeTimeout); + slideChangeTimeout = setTimeout(() => { + if (player) { + player.stopVideo(); + player.destroy(); + player = null; + } + fetchRandomMovie(); + }, trailerMaxLength); + } + if (isMuted) { + event.target.setVolume(0); // Mute the video if the setting is MuteOn + } else { + event.target.setVolume(4); + } + event.target.playVideo(); + }, + 'onStateChange': event => { + if (event.data === YT.PlayerState.PLAYING) { + // Only show when YT video is successfully playing + const backdrop = document.querySelector('.backdrop'); + if (backdrop) { + backdrop.style.width = 'calc(100% - 23vw)'; + backdrop.style.left = '0vw'; + } + // MARK: mod css + const plot = document.querySelector('.plot'); + if (plot) { + plot.style.left = '33vw'; + plot.style.maxWidth = '63vw'; + } + + const genres = document.querySelector('.genres'); + if (genres) { + genres.style.left = 'calc(50% - 17vw)'; + } + + /* + const plot = document.querySelector('.plot'); + if (plot) plot.style.width = 'calc(100% - 36.4vw)'; + + const loremIpsum = document.querySelector('.lorem-ipsum'); + if (loremIpsum) loremIpsum.style.paddingRight = '32.4vw'; + + const logo = document.querySelector('.logo'); + if (logo) logo.style.left = 'calc(50% - 14.2vw)'; + */ + + const loremIpsum = document.querySelector('.lorem-ipsum'); + if (loremIpsum) loremIpsum.style.left = 'calc(50% - 17vw)'; + + const logo = document.querySelector('.logo'); + if (logo) logo.style.left = 'calc(50% - 17vw)'; + + videoContainer.style.width = '34.4vw'; + } else if (event.data === YT.PlayerState.ENDED) { + setTimeout(fetchRandomMovie, 100); + } + }, + 'onError': () => { + console.error(`YouTube prevented playback of '${movie.Name}'`); + if (player) { + player.destroy(); + player = null; + } + + // Reset style when a YT error occurs + const backdrop = document.querySelector('.backdrop'); + if (backdrop) backdrop.style.width = '100%'; + + const plot = document.querySelector('.plot'); + if (plot) plot.style.width = '98%'; + + const loremIpsum = document.querySelector('.lorem-ipsum'); + if (loremIpsum) loremIpsum.style.paddingRight = '0'; + + const logo = document.querySelector('.logo'); + if (logo) logo.style.left = '50%'; + + videoContainer.style.width = '0'; + + startSlideChangeTimer(); + } + } + }); + } else { + startSlideChangeTimer(); + } + + + container.innerHTML = ''; + container.appendChild(slide); +}; + +function addSwipeListeners(slide) { + let startX, startY, distX, distY; + const threshold = 50; + const restraint = 100; + + slide.addEventListener('touchstart', e => { + const touch = e.touches[0]; + startX = touch.clientX; + startY = touch.clientY; + }); + + slide.addEventListener('touchmove', e => { + const touch = e.touches[0]; + distX = touch.clientX - startX; + distY = touch.clientY - startY; + }); + + slide.addEventListener('touchend', () => { + if (Math.abs(distX) > threshold && Math.abs(distY) < restraint) { + if (distX > 0) { + console.log('Swipe Right'); + } else { + console.log('Swipe Left'); + fetchRandomMovie(); + } + } + distX = distY = 0; + }); +} + +const navigateBack = () => { + if (previousMovies.length < 2) { + console.log("No previous slides in history."); + return; + } + + const currentMovie = previousMovies.pop(); + forwardMovies.unshift(currentMovie); + + const previousMovie = previousMovies[previousMovies.length - 1]; + createSlideElement(previousMovie, true); +}; + +const navigateForward = () => { + if (forwardMovies.length === 0) { + console.log("No forward slides in history."); + fetchRandomMovie(); + return; + } + + const currentMovie = forwardMovies.shift(); + previousMovies.push(currentMovie); + + + createSlideElement(currentMovie, true); +}; + +// Show the video overlay +function showVideoOverlay(trailerUrl) { + const videoOverlay = document.getElementById('video-overlay'); + const videoFrame = document.getElementById('trailer-video'); + const closeOverlay = document.getElementById('close-overlay'); + + // Extract video ID from trailer URL + const videoId = new URL(trailerUrl).searchParams.get('v'); + const embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1`; + + // Set iframe's source to trailer URL + videoFrame.src = embedUrl; + + // Show the overlay + videoOverlay.style.display = 'block'; + + // Pause the slide timer when the video overlay is open + clearSlideChangeTimeout(); + + // Close the overlay when the X is clicked + closeOverlay.onclick = () => { + videoOverlay.style.display = 'none'; + videoFrame.src = ''; // Stop the video + }; + + // Close the overlay when clicking outside content + window.onclick = (event) => { + if (event.target === videoOverlay) { + videoOverlay.style.display = 'none'; + videoFrame.src = ''; + } + }; +} + +// Close video overlay and restart slide timer +function closeVideoOverlay() { + const videoOverlay = document.getElementById('video-overlay'); + const videoFrame = document.getElementById('trailer-video'); + + // Hide overlay + videoOverlay.style.display = 'none'; + + // Reset the iframe source + videoFrame.src = ''; + + // Restart slide change timer when video overlay is closed + startSlideChangeTimer(); +} + +function clearSlideChangeTimeout() { + if (slideChangeTimeout) { + clearTimeout(slideChangeTimeout); + slideChangeTimeout = null; + } +} + +const startSlideChangeTimer = () => { clearTimeout(slideChangeTimeout); slideChangeTimeout = setTimeout(fetchRandomMovie, shuffleInterval); }; + +const checkBackdropAndLogo = movie => { + Promise.all(['/Images/Backdrop/0', '/Images/Logo'].map(url => + fetch(`/Items/${movie.Id}${url}`, { method: 'HEAD' }).then(response => response.ok) + )).then(([backdropExists, logoExists]) => + backdropExists && logoExists ? createSlideElement(movie, true) : fetchRandomMovie() + ).catch(() => fetchRandomMovie()); +}; + +const readCustomList = () => + fetch(listFileName + '?' + new Date().getTime()) + .then(response => response.ok ? response.text() : null) + .then(text => { + if (!text || !text.trim()) { + console.warn('List.txt is empty or could not be loaded.'); + return null; // Fallback to random selection + } + const lines = text.split('\n').filter(Boolean); + + const firstLine = lines.shift().trim(); + const [parsedTitle, muteSetting] = firstLine.split(/\s+/); + + title = parsedTitle || title; + + // Check for mute + // MARK: set mute + isMuted = muteSetting === "MuteOn"; + + // Remaining lines are media IDs + const mediaList = lines.map(line => line.trim().substring(0, 32)); + if (setRandomMovie) { + return shuffleArray(mediaList); // Shuffle the list before returning it if set + } + return mediaList; // return exact list + }) + .catch(() => { + console.error('Error reading List.txt. Falling back to random selection.'); + return null; + }); + + +const fetchRandomMovie = () => { + if (isChangingSlide) return; + isChangingSlide = true; + + if (movieList.length === 0) { + readCustomList().then(list => { + if (list && list.length > 0) { + movieList = list; + currentMovieIndex = 0; + fetchNextMovie(); + } else { + console.warn("Fallback to random selection."); + fetchNextMovie(true); + } + }); + } else { + fetchNextMovie(); + } +}; + +const shuffleArray = (array) => { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; +}; + +const fetchNextMovie = (useRandom = false) => { + const fetchCurrentUserId = () => + fetch('/Sessions', { headers: { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` } }) + .then(response => response.json()) + .then(sessions => { + const currentSession = sessions.find(session => session.UserId); + return currentSession ? currentSession.UserId : null; + }) + .catch(() => null); + + fetchCurrentUserId().then(currentUserId => { + if (!currentUserId) { + console.error('Could not retrieve the current user ID.'); + isChangingSlide = false; + return; + } + + const headers = { 'Authorization': `MediaBrowser Client="Jellyfin Web", Device="YourDeviceName", DeviceId="YourDeviceId", Version="YourClientVersion", Token="${token}"` }; + + if (!useRandom && movieList.length > 0) { + if (currentMovieIndex >= movieList.length) currentMovieIndex = 0; + const movieId = movieList[currentMovieIndex]; + currentMovieIndex++; + + fetch(`/Users/${currentUserId}/Items/${movieId}?Fields=Overview,RemoteTrailers,PremiereDate,RunTimeTicks,ChildCount,Genres`, { headers }) + .then(response => response.json()) + .then(checkBackdropAndLogo) + .catch(() => startSlideChangeTimer()) + .finally(() => { isChangingSlide = false; }); + } else { + const itemTypes = moviesSeriesBoth === 1 ? 'Movie' : (moviesSeriesBoth === 2 ? 'Series' : 'Movie,Series'); + fetch(`/Users/${currentUserId}/Items?IncludeItemTypes=${itemTypes}&Recursive=true&Limit=1&SortBy=random&Fields=Id,Overview,RemoteTrailers,PremiereDate,RunTimeTicks,ChildCount,Genres`, { headers }) + .then(response => response.json()) + .then(data => { if (data.Items[0]) checkBackdropAndLogo(data.Items[0]); }) + .catch(() => startSlideChangeTimer()) + .finally(() => { isChangingSlide = false; }); + } + }); +}; + +const checkNavigation = () => { + const newLocation = window.top.location.href; + if (newLocation !== currentLocation) { + currentLocation = newLocation; + const isHomePage = url => url.includes('/home') || url.endsWith('/web/') || url.endsWith('/web/index.html'); + + if (!isHomePage(newLocation) && isHomePageActive) { + console.log("Leaving homepage, cleaning up slideshow and stopping video"); + isHomePageActive = false; + stopBackgroundVideo(); + cleanup(); + } + + if (isHomePage(newLocation) && !isHomePageActive) { + console.log("Returning to homepage, reactivating slideshow"); + isHomePageActive = true; + fetchRandomMovie(); + } + } + + // Check if parent is available and if the iframe is in an embedded environment + if (!showOnOtherPages && window.parent && window.parent !== window) { + const homeTab = window.parent.document.getElementById('homeTab'); + const isHomeTabActive = homeTab && homeTab.classList.contains('is-active'); + + // Check if the user is switching tabs while on the homepage to eg. favorites or requests, if so, stop the slideshow + if (isHomeTabActive && !isHomePageActive) { + console.log("HomeTab is active, reactivating slideshow"); + isHomePageActive = true; + window.parent.document.querySelector('.featurediframe').style.display = 'block'; + cleanup(); + fetchRandomMovie(); + } else if (!isHomeTabActive && isHomePageActive) { + console.log("Leaving HomeTab, cleaning up slideshow"); + isHomePageActive = false; + window.parent.document.querySelector('.featurediframe').style.display = 'none'; + cleanup(); + } + } else { + console.error("Spotlight iframe is not in an embedded environment, has a different domain or showOnOtherPages is set to true"); + } +}; + +const stopBackgroundVideo = () => { + if (player && typeof player.stopVideo === 'function') { + player.stopVideo(); + player.destroy(); + } + player = null; +}; + +setInterval(checkNavigation, 60); + +document.addEventListener('DOMContentLoaded', () => { + if (window.innerWidth < 1001) useTrailers = false; + const isHomePage = url => url.includes('/home') || url.endsWith('/web/') || url.endsWith('/web/index.html'); + if (isHomePage(window.top.location.href)) { + isHomePageActive = true; + readCustomList().then(list => { + if (list) { movieList = list; currentMovieIndex = 0; } + fetchRandomMovie(); + }); + } +}); + +window.addEventListener('unload', cleanup); +window.addEventListener('popstate', checkNavigation); \ No newline at end of file diff --git a/spotlight.html b/spotlight.html index ee3ac53..7d34947 100644 --- a/spotlight.html +++ b/spotlight.html @@ -1,8 +1,8 @@ - - Jellyfin Spotlight v2.3.2 Fork v1.0 + + Jellyfin Spotlight v2.3.2 Fork v1.1 diff --git a/styles copy.css b/styles copy.css new file mode 100644 index 0000000..1425809 --- /dev/null +++ b/styles copy.css @@ -0,0 +1,1075 @@ +@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap'); + +body { + margin: 0; + padding: 0; + overflow: hidden; +} + +.slide { + position: relative; + width: 100vw; + height: 22em; + cursor: pointer; + border-radius: 2em; +} + +.slide:focus { + outline: 2px solid #fff; +} + +.backdrop { + position: absolute; + top: 0em; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center 30%; + z-index: 1; + transition: width 0.5s ease, filter 0.8s ease, scale 2s ease; + transform-origin: top; + animation: objectPositionAnimation 45s ease-in-out infinite; + border-radius: 2.1em; +} + +.logo { + position: relative; + transform: translateX(-50%) translateY(-50%); + top: 56%; + max-height: 9em; + max-width: 29em; + width: auto; + z-index: 7; + text-shadow: -2px 2px 4px rgba(0, 0, 0, 0.5); + filter: drop-shadow(1px 1px 1px); + pointer-events: none; + transition: transform 0.3s ease, max-height 0.3s ease, max-width 0.3s ease, left 0.5s ease; +} + +.heading::before { + content: ''; + position: absolute; + top: 2.27em; + left: 0; + width: 100%; + height: 100vh; + background: linear-gradient(0deg, rgb(0% 0% 0%) 0%, rgb(0% 0% 0% / 0.9990234375) 6.25%, rgba(0, 0, 0, 0.99) 12.5%, rgba(0, 0, 0, 0.97) 18.75%, rgba(0, 0, 0, 0.94) 25%, rgba(0, 0, 0, 0.88) 31.25%, rgba(0, 0, 0, 0.79) 37.5%, rgba(0, 0, 0, 0.67) 43.75%, rgba(0, 0, 0, 0.5) 50%, rgba(0, 0, 0, 0.33) 56.25%, rgba(0, 0, 0, 0.21) 62.5%, rgba(0, 0, 0, 0.12) 68.75%, rgba(0, 0, 0, 0.06) 75%, rgba(0, 0, 0, 0.03) 81.25%, rgba(0, 0, 0, 0.01) 87.5%, rgba(0, 0, 0, 0) 93.75%, rgba(0, 0, 0, 0) 100%); + z-index: 7; + opacity: 0; +} + +.heading { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 2.3em; + background-color: transparent; + font-family: "Titillium Web", sans-serif; + color: #D3D3D3; + font-size: 22px; + display: none; + align-items: center; + justify-content: flex-start; + z-index: 2; + padding: 10px; + padding-left: 0px; + box-sizing: border-box; + text-shadow: 1px 1px 4px rgba(0, 0, 0, 1); +} + +.back-button, +.skip-button { + position: absolute; + color: #fff; + cursor: pointer; + z-index: 10; + font-family: "Titillium Web", sans-serif; + text-shadow: 1px 1px 4px rgba(0, 0, 0, 1); + font-size: 2em; +} + +.details-button { + display: none; +} + +.material-icons { + font-size: 1em; +} + +.video-container { + position: absolute; + right: 0; + top: 0px; + width: 0; + height: calc(100%); + overflow: hidden; + transition: width 0.5s ease; + z-index: 5; + border-top-right-radius: 0.5em; + border-bottom-right-radius: 0.5em; +} + +.video-player { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 7; +} + +.clickable-overlay { + position: absolute; + top: 50px; + left: 0; + width: 100%; + height: calc(100% - 50px); + z-index: 2; + cursor: pointer; + background: transparent; + transition: background 0.8s ease, backdrop-filter 0.8s ease; +} + +.lorem-ipsum { + position: absolute; + bottom: 20.1em; + Right: 2.5em; + font-family: "Titillium Web", sans-serif; + font-size: 1em; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); + opacity: 1; + color: #fff; + z-index: 9; + box-sizing: border-box; + background: transparent; + max-width: fit-content; + padding-left: 90vw; + padding-right: 0.3em; + display: flex; + flex-direction: row; + max-height: 1.9em; + padding-top: 0.15em; + white-space: nowrap; + transition: padding-right 0.3s ease; +} + +.lorem-ipsum span { + margin-right: 0.2em; +} + +.age-rating { + position: absolute; + top: 0.5em; + left: 2em; + text-align: left; + font-family: "Titillium Web", sans-serif; + font-size: 1.2em; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); + opacity: 1; + color: #fff; + z-index: 7; + box-sizing: border-box; + background: transparent; + max-width: fit-content; + padding-left: 0.3em; + padding-right: 0.3em; + display: flex; + flex-direction: row; + max-height: 1.9em; + padding-top: 0.15em; + white-space: nowrap; +} + +.plot { + position: absolute; + top: -0.3em; + left: 50vw; + transform: translateX(-50%); + color: #fff; + font-family: "Titillium Web", sans-serif; + font-size: 0.95em; + font-weight: 500; + background: transparent; + padding: 10px; + z-index: 7; + box-sizing: border-box; + padding-bottom: 3px; + padding-top: 0.5em; + line-height: 1.2em; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: hidden; + border-bottom-left-radius: 0.45em; + transition: opacity 0.1s ease, max-height 0.8s ease, width 0.3s ease, left 0.3s ease; + opacity: 0; + max-width: 96vw; + opacity: 1; + -webkit-line-clamp: 2; + max-height: 7.8em; + text-align: center; +} + +.genres { + position: absolute; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); + top: -0.25em; + color: #fff; + font-family: "Titillium Web", sans-serif; + font-size: 1em; + opacity: 1; + transition: opacity 0.3s ease; + max-width: 39em; + overflow: hidden; + height: 1.95em; + padding-top: 0.25em; + line-height: 2em; + white-space: nowrap; +} + +.premiere-year { + position: absolute; + top: 5.75em; + left: 0.5em; + font-size: 0.9em; + font-family: "Titillium Web", sans-serif; + color: #fff; + z-index: 3; + opacity: 0; + transition: opacity 0.3s; + text-align: center; + width: 3.5em; +} + +.additional-info { + position: absolute; + top: 7.3em; + left: 31em; + font-size: 0.9em; + font-family: "Titillium Web", sans-serif; + color: #fff; + z-index: 3; + opacity: 1; + transition: opacity 0.3s; + text-align: right; + width: 5em; +} + +.community-rating { + position: absolute; + font-family: "Titillium Web", sans-serif; + color: #fff; + z-index: 3; + opacity: 1; + transition: opacity 0.3s; + text-align: center; + width: 3.6em; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.critic-rating { + position: absolute; + top: 5.75em; + right: 73%; + font-size: 0.9em; + font-family: "Titillium Web", sans-serif; + color: #fff; + z-index: 3; + opacity: 1; + transition: opacity 0.3s; + text-align: center; + width: 3.9em; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +@keyframes objectPositionAnimation { + 0% { + object-position: center 30%; + } + + 40% { + object-position: center 80%; + } + + 80% { + object-position: center 20%; + } + + 100% { + object-position: center 30%; + } +} + +.slide:hover .backdrop { + filter: brightness(95%) contrast(105%) saturate(105%); + transform: scale(1); +} + +.slide:hover .clickable-overlay {} + +.slide:hover .clickable-overlay::before { + opacity: 0; + backdrop-filter: blur(0px); +} + +.slide:hover .logo {} + +.slide:hover .plot {} + +.slide:hover .lorem-ipsum::before { + opacity: 1; + backdrop-filter: blur(2px); + transform: translateX(0); +} + +.star-icon { + color: gold; + font-size: 0.9em; + padding-right: 0.2em; + margin-left: -0.1em; +} + +@media (max-width: 1000px) { + .age-rating { + position: absolute; + top: 1em; + left: 1em; + font-size: 0.85em; + } + + .lorem-ipsum { + font-size: 0.7em; + transform: translateX(50%); + right: 50vw !important; + padding-left: 0; + padding-right: 1em; + } + + .logo { + transform: translateX(-50%) translateY(-50%); + top: 6.5em; + left: 50% !important; + max-width: 70%; + max-height: 45%; + transform-origin: 50% 50%; + } + + .plot { + display: none; + opacity: 1 !important; + font-size: 90%; + bottom: 0.5em; + -webkit-line-clamp: 2; + max-height: 3.3em; + overflow: hidden; + width: 98vw !important; + max-width: 98vw; + line-height: 1.45em; + } + + .lorem-ipsum::before { + opacity: 0; + padding-bottom: 0.25em; + } + + .clickable-overlay { + background: linear-gradient(0deg, rgb(0% 0% 0%) 0%, rgb(0% 0% 0% / 0.9990234375) 6.25%, rgba(0, 0, 0, 0.99) 12.5%, rgba(0, 0, 0, 0.97) 18.75%, rgba(0, 0, 0, 0.94) 25%, rgba(0, 0, 0, 0.88) 31.25%, rgba(0, 0, 0, 0.79) 37.5%, rgba(0, 0, 0, 0.67) 43.75%, rgba(0, 0, 0, 0.5) 50%, rgba(0, 0, 0, 0.33) 56.25%, rgba(0, 0, 0, 0.21) 62.5%, rgba(0, 0, 0, 0.12) 68.75%, rgba(0, 0, 0, 0.06) 75%, rgba(0, 0, 0, 0.03) 81.25%, rgba(0, 0, 0, 0.01) 87.5%, rgba(0, 0, 0, 0) 93.75%, rgba(0, 0, 0, 0) 100%); + opacity: 0.8; + } + + .backdrop { + left: 0% !important; + width: 100% !important; + top: 0em; + } + + .lorem-ipsum .full-content { + opacity: 1; + max-width: 100%; + } + + .lorem-ipsum::before { + opacity: 1; + backdrop-filter: blur(2px); + transform: translateX(0); + } + + .clickable-overlay::before { + opacity: 0.98; + backdrop-filter: blur(0px); + } + + .slide:hover .clickable-overlay::before { + opacity: 0.98; + } + + .genres { + bottom: 4em; + left: unset !important; + overflow: hidden; + max-width: 100vw !important; + white-space: nowrap; + left: 0; + z-index: 8; + color: #fff; + font-size: 0.7em; + } + + .additional-info { + left: 18.5%; + top: 5em; + text-align: right; + } + + .community-rating { + left: 86vw !important; + top: 19.45em !important; + text-align: left; + z-index: 8; + font-size: 0.85em !important; + } + + .critic-rating { + font-size: 0.85em !important; + left: 70vw !important; + top: 19.45em !important; + z-index: 8; + } + + .additional-info { + left: 18.5%; + top: 5em; + text-align: left; + } + + .heading { + z-index: 0; + } + + .heading::before { + display: none; + } + + .video-container { + max-width: 0 !important; + } + + .watch-trailer-button { + display: flex !important; + top: unset !important; + bottom: 0.4em; + font-size: 0.7em !important; + background: #fff9 !important; + color: #000e !important; + font-weight: 600; + transform: translateX(-100%) !important; + left: 47% !important; + } + + .slide { + box-shadow: none; + } + + .text-container::before { + display: none !important; + } + + .buttons-container { + display: flex; + position: absolute; + bottom: 0.6em; + left: 0em; + width: 100vw; + z-index: 10; + } + + .details-button { + position: absolute; + border: none; + border-radius: 5px; + padding: 0.5em 1.5em; + font-family: "Titillium Web", sans-serif; + cursor: pointer; + z-index: 10; + transition: background-color 0.3s ease; + align-items: center; + justify-content: center; + bottom: 0.4em; + font-size: 0.7em !important; + background: #fff9; + color: #000e; + font-weight: 600; + transform: translateX(100%) !important; + right: 47%; + display: flex; + padding-right: 2em; + } + + .details-button:hover { + background-color: #fffc; + } + + .watch-trailer-button:hover { + background-color: #fffc !important; + } + + .fas { + padding: 0.5em; + } +} + +@media (max-width:1000px) and (orientation:portrait) { + .back-button { + top: 5em !important; + left: 0.5em; + } + + .skip-button { + top: 5em !important; + right: 0.5em; + } + + .genres { + right: 50vw; + position: absolute; + max-width: 80vw !important; + overflow: hidden; + top: unset; + transform: translateX(50%); + bottom: 6.5em; + } + + .lorem-ipsum { + position: absolute; + left: unset; + bottom: 4.75em; + } +} + +@media (max-width:1000px) and (orientation:landscape) { + .slide { + height: 70vh; + } + + .community-rating { + left: 89vw !important; + } + + .critic-rating { + left: 76vw !important; + } + + .back-button { + top: 4em !important; + left: 0.5em; + } + + .skip-button { + top: 4em !important; + right: 0.5em; + } + + .genres { + position: absolute; + bottom: 6.5em; + top: unset; + transform: translateX(50%); + right: 50vw; + } + + .lorem-ipsum { + position: absolute; + left: unset; + bottom: 4.75em; + } +} + +@media (min-width: 1001px) { + .logo { + max-height: 45%; + top: 34vh; + max-width: 47em; + left: 50%; + transition: transform 0.1s ease, left 0.3s ease, max-height 0.3s ease; + } + + .lorem-ipsum { + left: 50vw; + transition: left 0.3s ease; + transform: translateX(-50%); + top: unset; + bottom: 3.2em; + padding-left: unset; + } + + .watch-trailer-button { + display: none; + } + + .backdrop { + left: 0em; + width: 100%; + transition: width 0.5s ease, left 0.5s ease, filter 0.8s ease, transform 2s ease; + } + + .genres { + left: 50vw; + top: unset; + bottom: 5em; + transition: left 0.3s; + z-index: 9; + max-width: 39em; + transform: translateX(-50%); + } + + .community-rating { + top: 16.45em; + left: 31em; + font-size: 1em; + } + + .critic-rating { + position: absolute; + top: 16.45em; + left: 26.5em; + font-size: 1em; + } + + .back-button { + display: inline-flex; + justify-content: center; + align-items: center; + width: 1em; + height: 1em; + border-radius: 50%; + overflow: hidden; + transition: background 0.3s, color 0.3s; + color: #ffffffa1; + left: 0.5em; + top: 5em; + } + + .skip-button { + display: inline-flex; + justify-content: center; + align-items: center; + width: 1em; + height: 1em; + border-radius: 50%; + overflow: hidden; + transition: background 0.3s, color 0.3s; + color: #ffffffa1; + right: 0.5em; + top: 5em; + } + + .text-container::before { + content: ''; + z-index: 5; + display: flex; + position: absolute; + width: 100vw; + top: -19.3em; + height: 3em; + background: transparent; + backdrop-filter: blur(0px); + border-top-right-radius: 1em; + border-top-left-radius: 1em; + -webkit-mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%); + } + + .text-container::after { + content: ''; + background: linear-gradient(0deg, rgb(0% 0% 0% / 0.98) 0%, rgb(0% 0% 0% / 0.9705847873975829) 6.25%, rgb(0% 0% 0% / 0.9427009709305305) 12.5%, rgb(0% 0% 0% / 0.8974201100282472) 18.75%, rgb(0% 0% 0% / 0.8364823227814083) 25%, rgb(0% 0% 0% / 0.7622294141796051) 31.25%, rgb(0% 0% 0% / 0.6775148818588941) 37.5%, rgb(0% 0% 0% / 0.5855942577879029) 43.75%, rgb(0% 0% 0% / 0.49000000000000005) 50%, rgb(0% 0% 0% / 0.39440574221209723) 56.25%, rgb(0% 0% 0% / 0.3024851181411061) 62.5%, rgb(0% 0% 0% / 0.217770585820395) 68.75%, rgb(0% 0% 0% / 0.14351767721859177) 75%, rgb(0% 0% 0% / 0.0825798899717528) 81.25%, rgb(0% 0% 0% / 0.03729902906946947) 87.5%, rgb(0% 0% 0% / 0.009415212602417067) 93.75%, rgb(0% 0% 0% / 0) 100%); + z-index: 5; + display: flex; + position: absolute; + width: 100vw; + border-bottom-left-radius: 1em; + bottom: 0em; + height: 22.5em; + opacity: 1; + backdrop-filter: blur(0px); + -webkit-mask-image: linear-gradient(0deg, rgb(0% 0% 0% / 0.98) 0%, rgb(0% 0% 0% / 0.9705847873975829) 6.25%, rgb(0% 0% 0% / 0.9427009709305305) 12.5%, rgb(0% 0% 0% / 0.8974201100282472) 18.75%, rgb(0% 0% 0% / 0.8364823227814083) 25%, rgb(0% 0% 0% / 0.7622294141796051) 31.25%, rgb(0% 0% 0% / 0.6775148818588941) 37.5%, rgb(0% 0% 0% / 0.5855942577879029) 43.75%, rgb(0% 0% 0% / 0.49000000000000005) 50%, rgb(0% 0% 0% / 0.39440574221209723) 56.25%, rgb(0% 0% 0% / 0.3024851181411061) 62.5%, rgb(0% 0% 0% / 0.217770585820395) 68.75%, rgb(0% 0% 0% / 0.14351767721859177) 75%, rgb(0% 0% 0% / 0.0825798899717528) 81.25%, rgb(0% 0% 0% / 0.03729902906946947) 87.5%, rgb(0% 0% 0% / 0.009415212602417067) 93.75%, rgb(0% 0% 0% / 0) 100%); + pointer-events: none; + } + + .skip-button:hover { + background: #101010a8; + color: #fff; + } + + .back-button:hover { + background: #101010a8; + color: #fff; + } +} + +.age-rating { + font-weight: 600; + font-size: 1.1em; +} + +.additional-info { + display: none; +} + +.age-rating span.gb-u, +.age-rating span.u { + background-color: #078c6d; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.gb-pg, +.age-rating span.pg { + background-color: #d7a203; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.gb-12a, +.age-rating span.\31 2A { + background-color: #ee7600; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.gb-12, +.age-rating span.\31 2, +.age-rating span.gb-15, +.age-rating span.\31 2 { + background-color: #e19887; + color: #e2002d; + border: 0.09em solid white !important; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.pg-13 { + background-color: #157c0d; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.tv-y7, +.age-rating span.tv-13, +.age-rating span.tv-14, +.age-rating span.\31 6, +.age-rating span.tv-ma, +.age-rating span.tv-y, +.age-rating span.tv-g, +.age-rating span.tv-pg { + background-color: #157c0d; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.nc-17, +.age-rating span.gb-18, +.age-rating span.\31 8, +.age-rating span.r { + background-color: #c10f1f; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.au-g, +.age-rating span.nz-g, +.age-rating span.eu-pg, +.age-rating span.ca-g, +.age-rating span.jp-g, +.age-rating span.de-0 { + background-color: #078c6d; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.au-pg, +.age-rating span.nz-pg, +.age-rating span.eu-12, +.age-rating span.ca-pg, +.age-rating span.jp-pg12, +.age-rating span.de-6 { + background-color: #d7a203; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.au-m, +.age-rating span.nz-m, +.age-rating span.eu-16, +.age-rating span.ca-14a, +.age-rating span.jp-r15, +.age-rating span.de-12 { + background-color: #07b1e0; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.au-ma15, +.age-rating span.nz-r15, +.age-rating span.eu-18, +.age-rating span.ca-18a, +.age-rating span.jp-r18, +.age-rating span.de-16 { + background-color: #fc9712; + color: white; + border: 0.09em solid white !important; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.age-rating span.au-r18, +.age-rating span.nz-r18, +.age-rating span.ca-r, +.age-rating span.jp-r18+, +.age-rating span.de-18 { + background-color: #c10f1f; + color: white; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 1); +} + +.video-container { + overflow: visible; +} + +.watch-trailer-button { + position: absolute; + border: none; + border-radius: 5px; + padding: 0.5em 1em; + font-size: 0.9em; + font-family: "Titillium Web", sans-serif; + cursor: pointer; + z-index: 10; + transition: background-color 0.3s ease; + align-items: center; + justify-content: center; + padding-right: 1.5em; +} + +.watch-trailer-button .fa-play { + margin-right: 0.5em; +} + +.slide { + position: relative; + width: 100%; + overflow: hidden; + opacity: 1; + transition: opacity 0.31s ease-in-out, font-size 1s ease; +} + +.fade-in { + opacity: 0; + visibility: hidden; + transition: opacity 0.31s ease-in-out; +} + +.fade-in-active { + opacity: 1; + visibility: visible; +} + +.fade-out { + opacity: 0; +} + +.backdrop { + transition: opacity 0.3s ease-in-out, width 0.5s ease, transform 1.5s ease, filter 1s ease; +} + +@media (min-width: 2000px) { + .slide { + font-size: 133%; + } + + .backdrop {} + + .age-rating {} + + .video-container {} + + .text-container::before {} + + .genres {} + + .lorem-ipsum {} +} + +@media (min-width: 3000px) { + .slide { + font-size: 200%; + } + + .age-rating {} + + .skip-button {} + + .backdrop {} + + .text-container::before {} + + .genres {} + + .lorem-ipsum {} +} + +#video-overlay { + position: fixed; + top: 10vh; + border-radius: 1em; + left: 0vw; + width: 94.5vw; + height: 55vh; + background-color: rgb(0, 0, 0); + z-index: 1000; + display: flex; + background-size: cover; + padding: 6vh; + padding-top: 10vh; + margin-top: -10vh; +} + +#video-overlay-content { + position: relative; + width: 100%; + max-width: 100%; + height: 100%; + background-color: #000; +} + +@media (orientation: portrait) { + #video-overlay { + position: fixed; + top: 10vh; + border-radius: 1em; + left: 0vw; + width: 87.5vw; + height: 68vh; + background-color: rgb(0, 0, 0); + z-index: 1000; + display: flex; + background-size: cover; + padding: 6vh; + padding-top: 10vh; + margin-top: -10vh; + } +} + +#close-overlay { + position: absolute; + top: -1em; + right: 0em; + font-size: 1.5em; + color: #7b7b7b; + cursor: pointer; +} + +#countdown-bar-container { + display: none; + position: absolute; + left: 0%; + top: 3.1em; + width: 110%; + height: 0.15em !important; + background-color: rgba(0, 0, 0, 0); + z-index: 10; +} + +#countdown-bar { + height: 100%; + width: 0%; + background-color: #ffffff; + opacity: 0.5; + transition: width 0.1s linear; + border-radius: 1em; +} + +.video-player { + mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%); + -webkit-mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.25) 3%, rgba(0, 0, 0, 0.5) 7%, rgba(0, 0, 0, 0.75) 15%, rgba(0, 0, 0, 0.9) 25%, rgba(0, 0, 0, 1) 35%, rgba(0, 0, 0, 1) 100%); + transition: mask-image 5s ease, -webkit-mask-image 5s ease; +} + +.video-container:hover .video-player { + mask-image: none; + -webkit-mask-image: none; +} + +.text-container { + z-index: 5; + display: flex; + position: absolute; + width: 100vw; + bottom: 0em; + height: 2.7em; + opacity: 1; +} + +.material-symbols-outlined { + vertical-align: middle; + font-size: 0.85em; + opacity: 0.75; +} + +.logo { + opacity: 0; + animation: fadeIn 1.5s ease-in forwards; + animation-delay: 1s; +} + +@keyframes fadeIn { + to { + opacity: 1; + } +} + +.plot { + opacity: 0; + animation: fadeIn 1s ease-in forwards; + animation-delay: 2s; +} + +@keyframes fadeIn { + to { + opacity: 1; + } +} + +.genres { + opacity: 0; + animation: fadeIn 1s ease-in forwards; + animation-delay: 1.5s; +} + +@keyframes fadeIn { + to { + opacity: 1; + } +} + +.lorem-ipsum { + opacity: 0; + animation: fadeIn 1s ease-in forwards; + animation-delay: 1.5s; +} + +@keyframes fadeIn { + to { + opacity: 1; + } +} + +.text-container::after { + opacity: 0.7; + animation: fadeIn 1.5s ease-in forwards; + animation-delay: 1s; +} + +@keyframes fadeIn { + to { + opacity: 1; + } +} \ No newline at end of file