From 9b4c7b6344468bedd7a9150f729e11766d5a7e3e Mon Sep 17 00:00:00 2001 From: ACertainCoder Date: Sat, 20 Dec 2025 22:02:35 +0100 Subject: [PATCH 01/11] Convert 3-letter country codes to 2-letter if necessary --- slideshowpure.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/slideshowpure.js b/slideshowpure.js index cfe3562..479aeb5 100644 --- a/slideshowpure.js +++ b/slideshowpure.js @@ -491,15 +491,9 @@ const LocalizationUtils = { try { const userId = window.ApiClient.getCurrentUserId(); if (userId) { - const userUrl = window.ApiClient.getUrl(`Users/${userId}`); - const userResponse = await fetch(userUrl, { - headers: ApiUtils.getAuthHeaders(), - }); - if (userResponse.ok) { - const userData = await userResponse.json(); - if (userData.Configuration?.AudioLanguagePreference) { - locale = userData.Configuration.AudioLanguagePreference.toLowerCase(); - } + const userData = await window.ApiClient.getUser(userId); + if (userData.Configuration?.AudioLanguagePreference) { + locale = userData.Configuration.AudioLanguagePreference.toLowerCase(); } } } catch (error) { @@ -539,6 +533,15 @@ const LocalizationUtils = { locale = navLang ? navLang.toLowerCase() : "en-us"; } + // Convert 3-letter country codes to 2-letter if necessary + if (locale.length === 3) { + const countriesData = await window.ApiClient.getCountries(); + const countryData = Object.values(countriesData).find(countryData => countryData.ThreeLetterISORegionName === locale.toUpperCase()); + if (countryData) { + locale = countryData.TwoLetterISORegionName.toLowerCase(); + } + } + this.cachedLocale = locale; return locale; }, @@ -599,7 +602,7 @@ const LocalizationUtils = { } const chunkText = await response.text(); - + let jsonMatch = chunkText.match(/JSON\.parse\(['"](.*?)['"]\)/); if (jsonMatch) { let jsonString = jsonMatch[1] @@ -614,7 +617,7 @@ const LocalizationUtils = { // Try direct extraction } } - + const jsonStart = chunkText.indexOf('{'); const jsonEnd = chunkText.lastIndexOf('}') + 1; if (jsonStart !== -1 && jsonEnd > jsonStart) { From 1a4d0ce0f744a984574b99b9907e9fd9e8030c0e Mon Sep 17 00:00:00 2001 From: ACertainCoder Date: Sat, 20 Dec 2025 22:15:35 +0100 Subject: [PATCH 02/11] Use getCurrentUser instead of getUser --- slideshowpure.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/slideshowpure.js b/slideshowpure.js index 479aeb5..3e309f7 100644 --- a/slideshowpure.js +++ b/slideshowpure.js @@ -489,12 +489,9 @@ const LocalizationUtils = { if (window.ApiClient && STATE.jellyfinData?.accessToken) { try { - const userId = window.ApiClient.getCurrentUserId(); - if (userId) { - const userData = await window.ApiClient.getUser(userId); - if (userData.Configuration?.AudioLanguagePreference) { - locale = userData.Configuration.AudioLanguagePreference.toLowerCase(); - } + const userData = window.ApiClient.getCurrentUser(); + if (userData.Configuration?.AudioLanguagePreference) { + locale = userData.Configuration.AudioLanguagePreference.toLowerCase(); } } catch (error) { console.warn("Could not fetch user language preference:", error); From 57e8cf77b3ea67c309470ca1f85080c617129601 Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Sat, 27 Dec 2025 16:19:56 +0530 Subject: [PATCH 03/11] Revise README for compatibility and support updates Updated README to reflect current compatibility status and support changes. --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8a7beef..ed0aeb9 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,7 @@ # Jellyfin-Media-Bar - Now with Play Now Function -> [!NOTE] -> The Media Bar is currently partly compatible with the Jellyfin 10.11.x update. We’re aware of the changes required to make it fully compatible and will be addressing them soon. -> -> I’ll be away on vacation for a short while, so there will be a temporary delay in releasing the next update. I kindly ask that you refrain from opening new bug reports related to 10.11.x compatibility during this period — we’ve got it on our radar. -> -> Thank you for your patience and understanding! The fixes will be rolled out shortly after I return. +![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hw/makd/Jellyfin-Media-Bar?style=for-the-badge&logo=javascript&logoColor=white&labelColor=F0DB4F&color=323330) + **IMP UPDATE — We have dropped support for the normal CSS version (for now). _(It still works, but there will be no further updates till the fullscreen mode is stabilized)_** From 0fec1ce8e5ac4b9df4cd59dfa71fbbbb2ef4cf8f Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Sat, 27 Dec 2025 16:20:38 +0530 Subject: [PATCH 04/11] Fix badge link and update CSS support notice Updated badge link and noted CSS support drop. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed0aeb9..88d51a4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Jellyfin-Media-Bar - Now with Play Now Function -![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hw/makd/Jellyfin-Media-Bar?style=for-the-badge&logo=javascript&logoColor=white&labelColor=F0DB4F&color=323330) +![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hm/makd/Jellyfin-Media-Bar?style=for-the-badge&logo=javascript&logoColor=white&labelColor=F0DB4F&color=323330) From fe37d614b2fe8da1f1b065d597823d5dd527b271 Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Sat, 27 Dec 2025 16:23:25 +0530 Subject: [PATCH 05/11] Fix badge URL in README.md Updated badge URL to include cache duration. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 88d51a4..b1f4c2b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Jellyfin-Media-Bar - Now with Play Now Function -![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hm/makd/Jellyfin-Media-Bar?style=for-the-badge&logo=javascript&logoColor=white&labelColor=F0DB4F&color=323330) +![jsDelivr hits (GitHub)](https://img.shields.io/jsdelivr/gh/hm/makd/Jellyfin-Media-Bar?style=for-the-badge&logo=javascript&logoColor=white&labelColor=F0DB4F&color=323330&cacheSeconds=3600) From 1b54a43ee4a69a6b700196189356008e5622dcef Mon Sep 17 00:00:00 2001 From: ACertainCoder Date: Sun, 4 Jan 2026 20:16:25 +0100 Subject: [PATCH 06/11] Use scale3d to avoid stuttering on some browsers --- slideshowpure.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slideshowpure.css b/slideshowpure.css index 8982932..bd20aee 100644 --- a/slideshowpure.css +++ b/slideshowpure.css @@ -28,11 +28,11 @@ @keyframes kenBurnsZoomIn { from { - transform: scale(1); + transform: scale3d(1, 1, 0); } to { - transform: scale(1.1); + transform: scale3d(1.1, 1.1, 0.1); } } From 46187718d7c57bdb5adbd2a57c602369e99d0a99 Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Mon, 5 Jan 2026 09:37:29 +0530 Subject: [PATCH 07/11] Update slideshowpure.js Fixed Bug where the loader didn't get removed on `/home?tab=n` --- slideshowpure.js | 166 +++++++++++++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 57 deletions(-) diff --git a/slideshowpure.js b/slideshowpure.js index 3e309f7..2daa43e 100644 --- a/slideshowpure.js +++ b/slideshowpure.js @@ -1,5 +1,5 @@ /* - * Jellyfin Slideshow by M0RPH3US v3.0.6 + * Jellyfin Slideshow by M0RPH3US v3.0.7 */ //Core Module Configuration @@ -215,31 +215,53 @@ const initLoadingScreen = () => { const checkInterval = setInterval(() => { const loginFormLoaded = document.querySelector(".manualLoginForm"); - const homePageLoaded = - document.querySelector(".homeSectionsContainer") && - document.querySelector("#slides-container"); + const activeTab = document.querySelector(".pageTabContent.is-active"); - if (loginFormLoaded || homePageLoaded) { - clearInterval(progressInterval); - clearInterval(checkInterval); + if (loginFormLoaded) { + finishLoading(); + return; + } - progressBar.style.transition = "width 300ms ease-in-out"; - progressBar.style.width = "100%"; - unfilledBar.style.width = "0%"; + if (activeTab) { + const tabIndex = activeTab.getAttribute("data-index"); - progressBar.addEventListener('transitionend', () => { - requestAnimationFrame(() => { - const loader = document.querySelector(".bar-loading"); - if (loader) { - loader.style.opacity = '0'; - setTimeout(() => { - loader.remove(); - }, 300); - } - }); - }) + if (tabIndex === "0") { + const homeSections = document.querySelector(".homeSectionsContainer"); + const slidesContainer = document.querySelector("#slides-container"); + + if (homeSections && slidesContainer) { + finishLoading(); + } + } else { + if ( + activeTab.children.length > 0 || + activeTab.innerText.trim().length > 0 + ) { + finishLoading(); + } + } } }, CONFIG.loadingCheckInterval); + + const finishLoading = () => { + clearInterval(progressInterval); + clearInterval(checkInterval); + progressBar.style.transition = "width 300ms ease-in-out"; + progressBar.style.width = "100%"; + unfilledBar.style.width = "0%"; + + progressBar.addEventListener("transitionend", () => { + requestAnimationFrame(() => { + const loader = document.querySelector(".bar-loading"); + if (loader) { + loader.style.opacity = "0"; + setTimeout(() => { + loader.remove(); + }, 300); + } + }); + }); + }; }; /** @@ -500,7 +522,7 @@ const LocalizationUtils = { if (!locale && window.ApiClient && STATE.jellyfinData?.accessToken) { try { - const configUrl = window.ApiClient.getUrl('System/Configuration'); + const configUrl = window.ApiClient.getUrl("System/Configuration"); const configResponse = await fetch(configUrl, { headers: ApiUtils.getAuthHeaders(), }); @@ -533,7 +555,10 @@ const LocalizationUtils = { // Convert 3-letter country codes to 2-letter if necessary if (locale.length === 3) { const countriesData = await window.ApiClient.getCountries(); - const countryData = Object.values(countriesData).find(countryData => countryData.ThreeLetterISORegionName === locale.toUpperCase()); + const countryData = Object.values(countriesData).find( + (countryData) => + countryData.ThreeLetterISORegionName === locale.toUpperCase() + ); if (countryData) { locale = countryData.TwoLetterISORegionName.toLowerCase(); } @@ -549,7 +574,7 @@ const LocalizationUtils = { * @returns {string|null} URL to translation chunk or null */ findTranslationChunkUrl(locale) { - const localePrefix = locale.split('-')[0]; + const localePrefix = locale.split("-")[0]; if (this.chunkUrlCache[localePrefix]) { return this.chunkUrlCache[localePrefix]; @@ -557,10 +582,14 @@ const LocalizationUtils = { if (window.performance && window.performance.getEntriesByType) { try { - const resources = window.performance.getEntriesByType('resource'); + const resources = window.performance.getEntriesByType("resource"); for (const resource of resources) { const url = resource.name || resource.url; - if (url && url.includes(`${localePrefix}-json`) && url.includes('.chunk.js')) { + if ( + url && + url.includes(`${localePrefix}-json`) && + url.includes(".chunk.js") + ) { this.chunkUrlCache[localePrefix] = url; return url; } @@ -595,7 +624,9 @@ const LocalizationUtils = { const response = await fetch(chunkUrl); if (!response.ok) { - throw new Error(`Failed to fetch translations: ${response.statusText}`); + throw new Error( + `Failed to fetch translations: ${response.statusText}` + ); } const chunkText = await response.text(); @@ -604,8 +635,8 @@ const LocalizationUtils = { if (jsonMatch) { let jsonString = jsonMatch[1] .replace(/\\"/g, '"') - .replace(/\\n/g, '\n') - .replace(/\\\\/g, '\\') + .replace(/\\n/g, "\n") + .replace(/\\\\/g, "\\") .replace(/\\'/g, "'"); try { this.translations[locale] = JSON.parse(jsonString); @@ -615,8 +646,8 @@ const LocalizationUtils = { } } - const jsonStart = chunkText.indexOf('{'); - const jsonEnd = chunkText.lastIndexOf('}') + 1; + const jsonStart = chunkText.indexOf("{"); + const jsonEnd = chunkText.lastIndexOf("}") + 1; if (jsonStart !== -1 && jsonEnd > jsonStart) { const jsonString = chunkText.substring(jsonStart, jsonEnd); try { @@ -644,17 +675,17 @@ const LocalizationUtils = { * @returns {string} Localized string or fallback */ getLocalizedString(key, fallback, ...args) { - const locale = this.cachedLocale || 'en-us'; + const locale = this.cachedLocale || "en-us"; let translated = this.translations[locale]?.[key] || fallback; if (args.length > 0) { for (let i = 0; i < args.length; i++) { - translated = translated.replace(new RegExp(`\\{${i}\\}`, 'g'), args[i]); + translated = translated.replace(new RegExp(`\\{${i}\\}`, "g"), args[i]); } } return translated; - } + }, }; /** @@ -822,7 +853,8 @@ const ApiUtils = { async getSessionId() { try { const response = await fetch( - `${STATE.jellyfinData.serverAddress + `${ + STATE.jellyfinData.serverAddress }/Sessions?deviceId=${encodeURIComponent(STATE.jellyfinData.deviceId)}`, { headers: this.getAuthHeaders(), @@ -875,7 +907,7 @@ const ApiUtils = { } catch (error) { console.error("Error toggling favorite:", error); } - } + }, }; /** @@ -988,7 +1020,11 @@ const SlideCreator = { // Handle Backdrop images if (imageType === "Backdrop") { // Check BackdropImageTags array first - if (item.BackdropImageTags && Array.isArray(item.BackdropImageTags) && item.BackdropImageTags.length > 0) { + if ( + item.BackdropImageTags && + Array.isArray(item.BackdropImageTags) && + item.BackdropImageTags.length > 0 + ) { const backdropIndex = index !== undefined ? index : 0; if (backdropIndex < item.BackdropImageTags.length) { tag = item.BackdropImageTags[backdropIndex]; @@ -1016,7 +1052,7 @@ const SlideCreator = { // Build URL with tag and quality if tag is available, otherwise quality-only fallback if (tag) { // Use both tag and quality for cacheable, quality-controlled images - const qualityParam = quality !== undefined ? `&quality=${quality}` : ''; + const qualityParam = quality !== undefined ? `&quality=${quality}` : ""; return `${baseUrl}?tag=${tag}${qualityParam}`; } else { // Fallback to quality-only URL if no tag is available @@ -1051,7 +1087,7 @@ const SlideCreator = { const backdrop = SlideUtils.createElement("img", { className: "backdrop high-quality", src: this.buildImageUrl(item, "Backdrop", 0, serverAddress, 60), - alt: LocalizationUtils.getLocalizedString('Backdrop', 'Backdrop'), + alt: LocalizationUtils.getLocalizedString("Backdrop", "Backdrop"), loading: "eager", }); @@ -1112,7 +1148,7 @@ const SlideCreator = { const genreElement = SlideUtils.createElement("div", { className: "genre", - innerHTML: SlideUtils.parseGenres(item.Genres) + innerHTML: SlideUtils.parseGenres(item.Genres), }); const buttonContainer = SlideUtils.createElement("div", { @@ -1161,7 +1197,9 @@ const SlideCreator = { if (typeof communityRating === "number") { const container = SlideUtils.createElement("div", { className: "star-rating-container", - innerHTML: `${communityRating.toFixed(1)}`, + innerHTML: `${communityRating.toFixed( + 1 + )}`, }); miscInfo.appendChild(container); miscInfo.appendChild(SlideUtils.createSeparator()); @@ -1169,14 +1207,17 @@ const SlideCreator = { // Critic Rating Section (Rotten Tomatoes) if (typeof criticRating === "number") { - const svgIcon = criticRating < 60 ? CONFIG.IMAGE_SVG.rottenTomato : CONFIG.IMAGE_SVG.freshTomato; + const svgIcon = + criticRating < 60 + ? CONFIG.IMAGE_SVG.rottenTomato + : CONFIG.IMAGE_SVG.freshTomato; const container = SlideUtils.createElement("div", { className: "critic-rating", innerHTML: `${svgIcon}${criticRating.toFixed(0)}%`, - }) + }); miscInfo.appendChild(container); miscInfo.appendChild(SlideUtils.createSeparator()); - }; + } // Year Section if (typeof premiereDate === "string" && !isNaN(new Date(premiereDate))) { @@ -1186,7 +1227,7 @@ const SlideCreator = { }); miscInfo.appendChild(container); miscInfo.appendChild(SlideUtils.createSeparator()); - }; + } // Age Rating Section if (typeof ageRating === "string") { @@ -1199,7 +1240,7 @@ const SlideCreator = { }); miscInfo.appendChild(container); miscInfo.appendChild(SlideUtils.createSeparator()); - }; + } // Runtime / Seasons Section if (seasonCount !== undefined || runtime !== undefined) { @@ -1207,7 +1248,13 @@ const SlideCreator = { className: "runTime", }); if (seasonCount) { - const seasonText = seasonCount <= 1 ? LocalizationUtils.getLocalizedString('Season', 'Season') : LocalizationUtils.getLocalizedString('TypeOptionPluralSeason', 'Seasons'); + const seasonText = + seasonCount <= 1 + ? LocalizationUtils.getLocalizedString("Season", "Season") + : LocalizationUtils.getLocalizedString( + "TypeOptionPluralSeason", + "Seasons" + ); container.innerHTML = `${seasonCount} ${seasonText}`; } else { const milliseconds = runtime / 10000; @@ -1215,7 +1262,11 @@ const SlideCreator = { const endTime = new Date(currentTime.getTime() + milliseconds); const options = { hour: "2-digit", minute: "2-digit", hour12: false }; const formattedEndTime = endTime.toLocaleTimeString([], options); - const endsAtText = LocalizationUtils.getLocalizedString('EndsAtValue', 'Ends at {0}', formattedEndTime); + const endsAtText = LocalizationUtils.getLocalizedString( + "EndsAtValue", + "Ends at {0}", + formattedEndTime + ); container.innerText = endsAtText; } miscInfo.appendChild(container); @@ -1230,7 +1281,7 @@ const SlideCreator = { * @returns {HTMLElement} Play button element */ createPlayButton(itemId) { - const playText = LocalizationUtils.getLocalizedString('Play', 'Play'); + const playText = LocalizationUtils.getLocalizedString("Play", "Play"); return SlideUtils.createElement("button", { className: "detailButton btnPlay play-button", innerHTML: ` @@ -1290,7 +1341,6 @@ const SlideCreator = { return button; }, - /** * Creates a placeholder slide for loading * @param {string} itemId - Item ID to load @@ -1349,7 +1399,6 @@ const SlideCreator = { * Manages slideshow functionality */ const SlideshowManager = { - createPaginationDots() { let dotsContainer = document.querySelector(".dots-container"); if (!dotsContainer) { @@ -1579,17 +1628,20 @@ const SlideshowManager = { togglePause() { STATE.slideshow.isPaused = !STATE.slideshow.isPaused; - const pauseButton = document.querySelector('.pause-button'); + const pauseButton = document.querySelector(".pause-button"); if (STATE.slideshow.isPaused) { STATE.slideshow.slideInterval.stop(); pauseButton.innerHTML = 'play_arrow'; - const playLabel = LocalizationUtils.getLocalizedString('Play', 'Play'); + const playLabel = LocalizationUtils.getLocalizedString("Play", "Play"); pauseButton.setAttribute("aria-label", playLabel); pauseButton.setAttribute("title", playLabel); } else { STATE.slideshow.slideInterval.start(); pauseButton.innerHTML = 'pause'; - const pauseLabel = LocalizationUtils.getLocalizedString('ButtonPause', 'Pause'); + const pauseLabel = LocalizationUtils.getLocalizedString( + "ButtonPause", + "Pause" + ); pauseButton.setAttribute("aria-label", pauseLabel); pauseButton.setAttribute("title", pauseLabel); } @@ -1768,13 +1820,13 @@ const initArrowNavigation = () => { className: "pause-button", innerHTML: 'pause', tabIndex: "0", - "aria-label": LocalizationUtils.getLocalizedString('ButtonPause', 'Pause'), - title: LocalizationUtils.getLocalizedString('ButtonPause', 'Pause'), + "aria-label": LocalizationUtils.getLocalizedString("ButtonPause", "Pause"), + title: LocalizationUtils.getLocalizedString("ButtonPause", "Pause"), onclick: (e) => { e.preventDefault(); e.stopPropagation(); SlideshowManager.togglePause(); - } + }, }); container.appendChild(leftArrow); From 5fdafeef68b05aa2ff72f2b46e57c251ad58e849 Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Mon, 5 Jan 2026 09:37:57 +0530 Subject: [PATCH 08/11] Update slideshowpure.css --- slideshowpure.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slideshowpure.css b/slideshowpure.css index 8982932..0e0635f 100644 --- a/slideshowpure.css +++ b/slideshowpure.css @@ -1,5 +1,5 @@ /* - * Jellyfin Slideshow by M0RPH3US v3.0.6 + * Jellyfin Slideshow by M0RPH3US v3.0.7 */ @import url(https://fonts.googleapis.com/css2?family=Archivo+Narrow:ital,wght@0,400..700;1,400..700&display=swap); From 48af2e54233c6f75ec2e135f415d78fa9ff80c7f Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Wed, 7 Jan 2026 00:07:55 +0530 Subject: [PATCH 09/11] Update slideshowpure.css --- slideshowpure.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slideshowpure.css b/slideshowpure.css index da94ba5..2c8d5e0 100644 --- a/slideshowpure.css +++ b/slideshowpure.css @@ -1,5 +1,5 @@ /* - * Jellyfin Slideshow by M0RPH3US v3.0.7 + * Jellyfin Slideshow by M0RPH3US v3.0.8 */ @import url(https://fonts.googleapis.com/css2?family=Archivo+Narrow:ital,wght@0,400..700;1,400..700&display=swap); From 7506bedfa981240cff1f2a017878cdbfb5580113 Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Wed, 7 Jan 2026 00:08:14 +0530 Subject: [PATCH 10/11] Update slideshowpure.js --- slideshowpure.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slideshowpure.js b/slideshowpure.js index 2daa43e..b4daa2e 100644 --- a/slideshowpure.js +++ b/slideshowpure.js @@ -1,5 +1,5 @@ /* - * Jellyfin Slideshow by M0RPH3US v3.0.7 + * Jellyfin Slideshow by M0RPH3US v3.0.8 */ //Core Module Configuration From 4618b8b9fa72db3c12f9632d8757d4c5cb6c59ff Mon Sep 17 00:00:00 2001 From: M0RPH3US Date: Wed, 7 Jan 2026 00:12:34 +0530 Subject: [PATCH 11/11] Update slideshowpure.css --- slideshowpure.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/slideshowpure.css b/slideshowpure.css index 2c8d5e0..7a7e1c7 100644 --- a/slideshowpure.css +++ b/slideshowpure.css @@ -115,6 +115,10 @@ transition: width 0.2s ease-in-out; } +.layout-mobile .splashLogo { +height: 12%; +} + .backdrop.low-quality { filter: blur(0.5px); transform: scale(1.01);