Browse Source

fix: make BYTM ThemeSong compatible

Sv443 8 months ago
parent
commit
6f5edb38f7

+ 1 - 1
assets/resources.json

@@ -3,9 +3,9 @@
   "css-anchor_improvements": "style/anchorImprovements.css",
   "css-auto_like": "style/autoLike.css",
   "css-fix_hdr": "style/fixHDR.css",
+  "css-fix_playerpage_theming": "style/fixPlayerPageTheming.css",
   "css-fix_spacing": "style/fixSpacing.css",
   "css-fix_sponsorblock": "style/fixSponsorBlock.css",
-  "css-fix_themesong": "style/fixThemeSong.css",
   "css-show_votes": "style/showVotes.css",
   "css-vol_slider_size": "style/volSliderSize.css",
   "doc-changelog": "/changelog.md",

+ 1 - 1
assets/style/aboveQueueBtns.css

@@ -5,7 +5,7 @@
   z-index: 2;
   padding: 16px 8px;
   margin: unset;
-  background-color: #030303;
+  background-color: var(--bytm-themed-bg);
   border-bottom: 1px solid var(--ytmusic-divider);
 }
 

+ 1 - 1
assets/style/fixHDR.css

@@ -1,5 +1,5 @@
 #side-panel ytmusic-player-queue-item[play-button-state="loading"],
 #side-panel ytmusic-player-queue-item[play-button-state="playing"],
 #side-panel ytmusic-player-queue-item[play-button-state="paused"] {
-  background-color: #1D1D1D !important;
+  background-color: var(--ts-palette-darkmuted-hex, rgba(255, 255, 255, 0.1));
 }

+ 44 - 0
assets/style/fixPlayerPageTheming.css

@@ -0,0 +1,44 @@
+/* This file should only be loaded if the ThemeSong extension is ***NOT*** installed */
+
+:root #side-panel ytmusic-player-queue-item[play-button-state="loading"],
+:root #side-panel ytmusic-player-queue-item[play-button-state="playing"],
+:root #side-panel ytmusic-player-queue-item[play-button-state="paused"] {
+  background-color: #1d1d1d !important;
+}
+
+:root
+  #side-panel
+  ytmusic-player-queue-item[play-button-state="loading"]
+  .bytm-queue-btn-container,
+:root
+  #side-panel
+  ytmusic-player-queue-item[play-button-state="playing"]
+  .bytm-queue-btn-container,
+:root
+  #side-panel
+  ytmusic-player-queue-item[play-button-state="paused"]
+  .bytm-queue-btn-container {
+  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #030303 15%);
+}
+
+:root
+  #side-panel
+  ytmusic-player-queue-item[selected][play-button-state="loading"]
+  .bytm-queue-btn-container,
+:root
+  #side-panel
+  ytmusic-player-queue-item[selected][play-button-state="playing"]
+  .bytm-queue-btn-container,
+:root
+  #side-panel
+  ytmusic-player-queue-item[selected][play-button-state="paused"]
+  .bytm-queue-btn-container {
+  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #1d1d1d 15%);
+}
+
+:root
+  #side-panel
+  ytmusic-player-queue-item[selected]
+  .bytm-queue-btn-container {
+  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #1d1d1d 15%);
+}

+ 0 - 1
assets/style/fixThemeSong.css

@@ -1 +0,0 @@
-/* TODO: */

+ 42 - 35
assets/translations/README.md

@@ -17,14 +17,14 @@ To submit or edit a translation, please follow [this guide](../../contributing.m
 |   | Locale | Translated keys | Based on |
 | :----: | ------ | --------------- | :------: |
 | ─ | [`en_US`](./en_US.json) | 287 (default locale) |  |
-| ‼️ | [`de_DE`](./de_DE.json) | `204/287` (71.1%) | ─ |
+| ‼️ | [`de_DE`](./de_DE.json) | `203/287` (70.7%) | ─ |
 | ─ | [`en_UK`](./en_UK.json) | `287` (100%) | `en_US` |
-| ‼️ | [`es_ES`](./es_ES.json) | `204/287` (71.1%) | ─ |
-| ‼️ | [`fr_FR`](./fr_FR.json) | `204/287` (71.1%) | ─ |
-| ‼️ | [`hi_IN`](./hi_IN.json) | `204/287` (71.1%) | ─ |
-| ‼️ | [`ja_JA`](./ja_JA.json) | `204/287` (71.1%) | ─ |
-| ‼️ | [`pt_BR`](./pt_BR.json) | `204/287` (71.1%) | ─ |
-| ‼️ | [`zh_CN`](./zh_CN.json) | `204/287` (71.1%) | ─ |
+| ‼️ | [`es_ES`](./es_ES.json) | `203/287` (70.7%) | ─ |
+| ‼️ | [`fr_FR`](./fr_FR.json) | `203/287` (70.7%) | ─ |
+| ‼️ | [`hi_IN`](./hi_IN.json) | `203/287` (70.7%) | ─ |
+| ‼️ | [`ja_JA`](./ja_JA.json) | `203/287` (70.7%) | ─ |
+| ‼️ | [`pt_BR`](./pt_BR.json) | `203/287` (70.7%) | ─ |
+| ‼️ | [`zh_CN`](./zh_CN.json) | `203/287` (70.7%) | ─ |
 
 <sub>
 ✅ - Fully translated
@@ -45,7 +45,7 @@ This means to figure out which keys are untranslated, you will need to manually
 
 ### Missing keys:
 
-<details><summary><code>de_DE</code> - 83 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>de_DE</code> - 84 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
@@ -120,10 +120,11 @@ This means to figure out which keys are untranslated, you will need to manually
 | `feature_desc_autoLikeOpenMgmtDialog` | `Open the dialog to manage auto-liked channels` |
 | `feature_btn_autoLikeOpenMgmtDialog` | `Open dialog` |
 | `feature_btn_autoLikeOpenMgmtDialog_running` | `Opening...` |
+| `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
 | `feature_desc_sponsorBlockIntegration` | `Make some fixes to the layout in case SponsorBlock is installed` |
-| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
-| `feature_desc_themeSongIntegration` | `Make the styling of the page match the theme set by the ThemeSong extension` |
-| `feature_helptext_themeSongIntegration` | `If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.` |
+| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
+| `feature_desc_themeSongIntegration` | `Fix some styling issues if the ThemeSong extension is installed` |
+| `feature_helptext_themeSongIntegration` | `If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!` |
 | `feature_desc_initTimeout` | `How many seconds to wait for features to initialize before considering them to likely be in an errored state` |
 | `feature_helptext_initTimeout` | `This is the amount of time in milliseconds that the script will wait for features to initialize before considering them to likely be in an errored state.\nThis will not affect the script's behavior in a significant way, but if one of your plugins can't initialize in time, you should try increasing this value.` |
 | `feature_desc_toastDuration` | `For how many seconds custom toast notifications should be shown - 0 to disable them entirely` |
@@ -135,7 +136,7 @@ This means to figure out which keys are untranslated, you will need to manually
 
 <br></details>
 
-<details><summary><code>es_ES</code> - 83 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>es_ES</code> - 84 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
@@ -210,10 +211,11 @@ This means to figure out which keys are untranslated, you will need to manually
 | `feature_desc_autoLikeOpenMgmtDialog` | `Open the dialog to manage auto-liked channels` |
 | `feature_btn_autoLikeOpenMgmtDialog` | `Open dialog` |
 | `feature_btn_autoLikeOpenMgmtDialog_running` | `Opening...` |
+| `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
 | `feature_desc_sponsorBlockIntegration` | `Make some fixes to the layout in case SponsorBlock is installed` |
-| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
-| `feature_desc_themeSongIntegration` | `Make the styling of the page match the theme set by the ThemeSong extension` |
-| `feature_helptext_themeSongIntegration` | `If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.` |
+| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
+| `feature_desc_themeSongIntegration` | `Fix some styling issues if the ThemeSong extension is installed` |
+| `feature_helptext_themeSongIntegration` | `If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!` |
 | `feature_desc_initTimeout` | `How many seconds to wait for features to initialize before considering them to likely be in an errored state` |
 | `feature_helptext_initTimeout` | `This is the amount of time in milliseconds that the script will wait for features to initialize before considering them to likely be in an errored state.\nThis will not affect the script's behavior in a significant way, but if one of your plugins can't initialize in time, you should try increasing this value.` |
 | `feature_desc_toastDuration` | `For how many seconds custom toast notifications should be shown - 0 to disable them entirely` |
@@ -225,7 +227,7 @@ This means to figure out which keys are untranslated, you will need to manually
 
 <br></details>
 
-<details><summary><code>fr_FR</code> - 83 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>fr_FR</code> - 84 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
@@ -300,10 +302,11 @@ This means to figure out which keys are untranslated, you will need to manually
 | `feature_desc_autoLikeOpenMgmtDialog` | `Open the dialog to manage auto-liked channels` |
 | `feature_btn_autoLikeOpenMgmtDialog` | `Open dialog` |
 | `feature_btn_autoLikeOpenMgmtDialog_running` | `Opening...` |
+| `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
 | `feature_desc_sponsorBlockIntegration` | `Make some fixes to the layout in case SponsorBlock is installed` |
-| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
-| `feature_desc_themeSongIntegration` | `Make the styling of the page match the theme set by the ThemeSong extension` |
-| `feature_helptext_themeSongIntegration` | `If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.` |
+| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
+| `feature_desc_themeSongIntegration` | `Fix some styling issues if the ThemeSong extension is installed` |
+| `feature_helptext_themeSongIntegration` | `If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!` |
 | `feature_desc_initTimeout` | `How many seconds to wait for features to initialize before considering them to likely be in an errored state` |
 | `feature_helptext_initTimeout` | `This is the amount of time in milliseconds that the script will wait for features to initialize before considering them to likely be in an errored state.\nThis will not affect the script's behavior in a significant way, but if one of your plugins can't initialize in time, you should try increasing this value.` |
 | `feature_desc_toastDuration` | `For how many seconds custom toast notifications should be shown - 0 to disable them entirely` |
@@ -315,7 +318,7 @@ This means to figure out which keys are untranslated, you will need to manually
 
 <br></details>
 
-<details><summary><code>hi_IN</code> - 83 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>hi_IN</code> - 84 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
@@ -390,10 +393,11 @@ This means to figure out which keys are untranslated, you will need to manually
 | `feature_desc_autoLikeOpenMgmtDialog` | `Open the dialog to manage auto-liked channels` |
 | `feature_btn_autoLikeOpenMgmtDialog` | `Open dialog` |
 | `feature_btn_autoLikeOpenMgmtDialog_running` | `Opening...` |
+| `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
 | `feature_desc_sponsorBlockIntegration` | `Make some fixes to the layout in case SponsorBlock is installed` |
-| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
-| `feature_desc_themeSongIntegration` | `Make the styling of the page match the theme set by the ThemeSong extension` |
-| `feature_helptext_themeSongIntegration` | `If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.` |
+| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
+| `feature_desc_themeSongIntegration` | `Fix some styling issues if the ThemeSong extension is installed` |
+| `feature_helptext_themeSongIntegration` | `If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!` |
 | `feature_desc_initTimeout` | `How many seconds to wait for features to initialize before considering them to likely be in an errored state` |
 | `feature_helptext_initTimeout` | `This is the amount of time in milliseconds that the script will wait for features to initialize before considering them to likely be in an errored state.\nThis will not affect the script's behavior in a significant way, but if one of your plugins can't initialize in time, you should try increasing this value.` |
 | `feature_desc_toastDuration` | `For how many seconds custom toast notifications should be shown - 0 to disable them entirely` |
@@ -405,7 +409,7 @@ This means to figure out which keys are untranslated, you will need to manually
 
 <br></details>
 
-<details><summary><code>ja_JA</code> - 83 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>ja_JA</code> - 84 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
@@ -480,10 +484,11 @@ This means to figure out which keys are untranslated, you will need to manually
 | `feature_desc_autoLikeOpenMgmtDialog` | `Open the dialog to manage auto-liked channels` |
 | `feature_btn_autoLikeOpenMgmtDialog` | `Open dialog` |
 | `feature_btn_autoLikeOpenMgmtDialog_running` | `Opening...` |
+| `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
 | `feature_desc_sponsorBlockIntegration` | `Make some fixes to the layout in case SponsorBlock is installed` |
-| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
-| `feature_desc_themeSongIntegration` | `Make the styling of the page match the theme set by the ThemeSong extension` |
-| `feature_helptext_themeSongIntegration` | `If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.` |
+| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
+| `feature_desc_themeSongIntegration` | `Fix some styling issues if the ThemeSong extension is installed` |
+| `feature_helptext_themeSongIntegration` | `If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!` |
 | `feature_desc_initTimeout` | `How many seconds to wait for features to initialize before considering them to likely be in an errored state` |
 | `feature_helptext_initTimeout` | `This is the amount of time in milliseconds that the script will wait for features to initialize before considering them to likely be in an errored state.\nThis will not affect the script's behavior in a significant way, but if one of your plugins can't initialize in time, you should try increasing this value.` |
 | `feature_desc_toastDuration` | `For how many seconds custom toast notifications should be shown - 0 to disable them entirely` |
@@ -495,7 +500,7 @@ This means to figure out which keys are untranslated, you will need to manually
 
 <br></details>
 
-<details><summary><code>pt_BR</code> - 83 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>pt_BR</code> - 84 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
@@ -570,10 +575,11 @@ This means to figure out which keys are untranslated, you will need to manually
 | `feature_desc_autoLikeOpenMgmtDialog` | `Open the dialog to manage auto-liked channels` |
 | `feature_btn_autoLikeOpenMgmtDialog` | `Open dialog` |
 | `feature_btn_autoLikeOpenMgmtDialog_running` | `Opening...` |
+| `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
 | `feature_desc_sponsorBlockIntegration` | `Make some fixes to the layout in case SponsorBlock is installed` |
-| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
-| `feature_desc_themeSongIntegration` | `Make the styling of the page match the theme set by the ThemeSong extension` |
-| `feature_helptext_themeSongIntegration` | `If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.` |
+| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
+| `feature_desc_themeSongIntegration` | `Fix some styling issues if the ThemeSong extension is installed` |
+| `feature_helptext_themeSongIntegration` | `If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!` |
 | `feature_desc_initTimeout` | `How many seconds to wait for features to initialize before considering them to likely be in an errored state` |
 | `feature_helptext_initTimeout` | `This is the amount of time in milliseconds that the script will wait for features to initialize before considering them to likely be in an errored state.\nThis will not affect the script's behavior in a significant way, but if one of your plugins can't initialize in time, you should try increasing this value.` |
 | `feature_desc_toastDuration` | `For how many seconds custom toast notifications should be shown - 0 to disable them entirely` |
@@ -585,7 +591,7 @@ This means to figure out which keys are untranslated, you will need to manually
 
 <br></details>
 
-<details><summary><code>zh_CN</code> - 83 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>zh_CN</code> - 84 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
@@ -660,10 +666,11 @@ This means to figure out which keys are untranslated, you will need to manually
 | `feature_desc_autoLikeOpenMgmtDialog` | `Open the dialog to manage auto-liked channels` |
 | `feature_btn_autoLikeOpenMgmtDialog` | `Open dialog` |
 | `feature_btn_autoLikeOpenMgmtDialog_running` | `Opening...` |
+| `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
 | `feature_desc_sponsorBlockIntegration` | `Make some fixes to the layout in case SponsorBlock is installed` |
-| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
-| `feature_desc_themeSongIntegration` | `Make the styling of the page match the theme set by the ThemeSong extension` |
-| `feature_helptext_themeSongIntegration` | `If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.` |
+| `feature_helptext_sponsorBlockIntegration` | `If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.` |
+| `feature_desc_themeSongIntegration` | `Fix some styling issues if the ThemeSong extension is installed` |
+| `feature_helptext_themeSongIntegration` | `If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!` |
 | `feature_desc_initTimeout` | `How many seconds to wait for features to initialize before considering them to likely be in an errored state` |
 | `feature_helptext_initTimeout` | `This is the amount of time in milliseconds that the script will wait for features to initialize before considering them to likely be in an errored state.\nThis will not affect the script's behavior in a significant way, but if one of your plugins can't initialize in time, you should try increasing this value.` |
 | `feature_desc_toastDuration` | `For how many seconds custom toast notifications should be shown - 0 to disable them entirely` |

+ 0 - 1
assets/translations/de_DE.json

@@ -166,7 +166,6 @@
     "feature_desc_hideCursorOnIdleDelay": "Wie viele Sekunden Inaktivität vergehen müssen, bevor der Cursor versteckt wird",
     "feature_desc_fixHdrIssues": "Verhindere einige Rendering-Probleme bei der Verwendung einer HDR-kompatiblen Grafikkarte mit Monitor",
     "feature_desc_disableDarkReaderSites": "Auf welchen Seiten soll die Dark Reader Erweiterung deaktiviert werden, um Layoutprobleme zu beheben?",
-    "feature_helptext_disableDarkReaderSites": "Die Dark Reader Erweiterung kann Probleme mit dem Layout der Seite verursachen.\nDiese Funktion ermöglicht es dir, Dark Reader auf bestimmten oder allen Seiten zu deaktivieren, um diese Probleme zu verhindern.\nWenn die Erweiterung nicht installiert ist, hat diese Funktion keine Auswirkungen und kann aktiviert bleiben.",
 
     "feature_desc_scrollToActiveSongBtn": "Füge einen Knopf über der Wiedergabeliste hinzu, um zum aktuell abgespielten Song zu scrollen",
     "feature_desc_clearQueueBtn": "Füge einen Knopf über der Wiedergabeliste hinzu, um sie schnell zu leeren",

+ 4 - 4
assets/translations/en_US.json

@@ -285,11 +285,11 @@
     "feature_helptext_advancedLyricsFilter": "Advanced filtering includes multiple layers of filters that aim to make the lyrics lookups more reliable.\nThese filters may not work well for songs in your language, and songs and artists with less unique titles in general.\nWarning: This feature is still experimental and might not actually perform any better than the default lyrics lookup. Make sure to confirm the prompt that appears if you changed this setting.",
 
     "feature_desc_disableDarkReaderSites": "On which sites should the Dark Reader extension be disabled to fix layout issues?",
-    "feature_helptext_disableDarkReaderSites": "The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.",
+    "feature_helptext_disableDarkReaderSites": "The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\n\nIf the extension is not installed, this feature will have no effect and can be left activated.",
     "feature_desc_sponsorBlockIntegration": "Make some fixes to the layout in case SponsorBlock is installed",
-    "feature_helptext_sponsorBlockIntegration": "If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\nThis feature will have no effect if the extension is not installed and can be left activated in that case.",
-    "feature_desc_themeSongIntegration": "Make the styling of the page match the theme set by the ThemeSong extension",
-    "feature_helptext_themeSongIntegration": "If you have the ThemeSong extension installed, this feature will make the styling of the page match the theme set by ThemeSong.\nThis feature might mess up the layout of the page if the extension is not installed, so make sure to disable it in that case.",
+    "feature_helptext_sponsorBlockIntegration": "If you have the SponsorBlock extension installed, this feature will make some fixes to the layout of the site to prevent issues that might occur.\n\nThis feature will have no effect if the extension is not installed and can be left activated in that case.",
+    "feature_desc_themeSongIntegration": "Fix some styling issues if the ThemeSong extension is installed",
+    "feature_helptext_themeSongIntegration": "If the ThemeSong extension is installed but this feature is turned off (or vice versa), you might notice broken styling on the site.\n\nPlease always make sure this feature reflects whether the extension is installed or not!",
 
     "feature_desc_locale": "Language",
     "feature_desc_localeFallback": "Use English as a fallback for missing translations (disable if you are contributing translations)",

+ 0 - 1
assets/translations/es_ES.json

@@ -166,7 +166,6 @@
     "feature_desc_hideCursorOnIdleDelay": "¿Cuántos segundos de inactividad antes de que se oculte el cursor?",
     "feature_desc_fixHdrIssues": "Prevenir algunos problemas de renderizado al usar una GPU y un monitor compatibles con HDR",
     "feature_desc_disableDarkReaderSites": "En qué sitios debería deshabilitarse la extensión Dark Reader para corregir problemas de diseño",
-    "feature_helptext_disableDarkReaderSites": "La extensión Dark Reader puede causar problemas con el diseño del sitio.\nEsta función le permite deshabilitar Dark Reader en ciertos o todos los sitios para evitar esos problemas.\nSi la extensión no está instalada, esta función no tendrá efecto y se puede dejar activada.",
 
     "feature_desc_scrollToActiveSongBtn": "Agregue un botón para desplazarse hasta la canción que se está reproduciendo actualmente",
     "feature_desc_clearQueueBtn": "Agregue un botón para borrar rápidamente la cola de reproducción o la lista de reproducción actual",

+ 0 - 1
assets/translations/fr_FR.json

@@ -166,7 +166,6 @@
     "feature_desc_hideCursorOnIdleDelay": "Combien de secondes d'inactivité avant que le curseur ne soit masqué?",
     "feature_desc_fixHdrIssues": "Prévenir certains problèmes de rendu lors de l'utilisation d'un GPU et d'un moniteur compatibles HDR",
     "feature_desc_disableDarkReaderSites": "Sur quels sites devrait-on désactiver l'extension Dark Reader pour corriger les problèmes de mise en page?",
-    "feature_helptext_disableDarkReaderSites": "L'extension Dark Reader peut causer des problèmes de mise en page sur le site.\nCette fonctionnalité vous permet de désactiver Dark Reader sur certains ou tous les sites pour éviter ces problèmes.\nSi l'extension n'est pas installée, cette fonctionnalité n'aura aucun effet et peut être laissée activée.",
 
     "feature_desc_scrollToActiveSongBtn": "Ajouter un bouton au-dessus de la file d'attente pour faire défiler jusqu'à la chanson en cours de lecture",
     "feature_desc_clearQueueBtn": "Ajouter un bouton au-dessus de la file d'attente ou de la liste de lecture en cours pour la vider rapidement",

+ 0 - 1
assets/translations/hi_IN.json

@@ -166,7 +166,6 @@
     "feature_desc_hideCursorOnIdleDelay": "कितने सेकंड निष्क्रियता के बाद कर्सर छुपाना चाहिए?",
     "feature_desc_fixHdrIssues": "एचडीआर-संगत जीपीयू और मॉनिटर का उपयोग करते समय कुछ रेंडरिंग समस्याओं को रोकें",
     "feature_desc_disableDarkReaderSites": "लेआउट समस्याओं को ठीक करने के लिए किन साइटों पर \"डार्क रीडर\" एक्सटेंशन को अक्षम किया जाना चाहिए?",
-    "feature_helptext_disableDarkReaderSites": "डार्क रीडर एक्सटेंशन साइट के लेआउट में समस्याओं का कारण बन सकता है।\nइस सुविधा की मदद से आप इन साइटों पर डार्क रीडर को अक्षम कर सकते हैं ताकि उन समस्याओं को रोक सकें।\nयदि एक्सटेंशन स्थापित नहीं है, तो इस सुविधा का कोई प्रभाव नहीं होगा और इसे सक्रिय रखा जा सकता है।",
 
     "feature_desc_scrollToActiveSongBtn": "कतार में वर्तमान गीत के ऊपर स्क्रॉल करने के लिए एक बटन जोड़ें",
     "feature_desc_clearQueueBtn": "वर्तमान में चल रही कतार या प्लेलिस्ट के ऊपर त्वरित रूप से इसे साफ करने के लिए एक बटन जोड़ें",

+ 0 - 1
assets/translations/ja_JA.json

@@ -166,7 +166,6 @@
     "feature_desc_hideCursorOnIdleDelay": "カーソルを非表示にするまでのアイドル時間(秒)",
     "feature_desc_fixHdrIssues": "HDR 互換 GPU とモニターを使用しているときの一部のレンダリング問題を防止する",
     "feature_desc_disableDarkReaderSites": "レイアウト問題を修正するために Dark Reader 拡張機能を無効にするサイト",
-    "feature_helptext_disableDarkReaderSites": "Dark Reader 拡張機能はサイトのレイアウトに問題を引き起こす可能性があります。\nこの機能を使用すると、それらの問題を防ぐために特定のサイトまたはすべてのサイトで Dark Reader を無効にできます。\n拡張機能がインストールされていない場合、この機能は効果がありませんので、有効にしたままにしておいてください。",
 
     "feature_desc_scrollToActiveSongBtn": "現在再生中の曲にスクロールするボタンをキューの上に追加する",
     "feature_desc_clearQueueBtn": "現在再生中のキューまたはプレイリストの上にボタンを追加して、すばやくクリアする",

+ 0 - 1
assets/translations/pt_BR.json

@@ -166,7 +166,6 @@
     "feature_desc_hideCursorOnIdleDelay": "Quantos segundos de inatividade antes de ocultar o cursor?",
     "feature_desc_fixHdrIssues": "Corrigir problemas de renderização ao usar um GPU e monitor compatíveis com HDR",
     "feature_desc_disableDarkReaderSites": "Em quais sites o Dark Reader deve ser desativado para corrigir problemas de layout?",
-    "feature_helptext_disableDarkReaderSites": "A extensão Dark Reader pode causar problemas de layout no site.\nEste recurso permite desativar o Dark Reader em determinados ou todos os sites para evitar esses problemas.\nSe a extensão não estiver instalada, este recurso não terá efeito e pode ser deixado ativado.",
 
     "feature_desc_scrollToActiveSongBtn": "Adicione um botão acima da fila para rolar para a música que está tocando atualmente",
     "feature_desc_clearQueueBtn": "Adicione um botão acima da fila de reprodução ou lista de reprodução atual para limpar rapidamente",

+ 0 - 1
assets/translations/zh_CN.json

@@ -166,7 +166,6 @@
     "feature_desc_hideCursorOnIdleDelay": "在几秒钟的不活动后隐藏光标?",
     "feature_desc_fixHdrIssues": "在 HDR 兼容的 GPU 和显示器上防止一些渲染问题",
     "feature_desc_disableDarkReaderSites": "在哪些网站上应该禁用 Dark Reader 扩展以修复布局问题?",
-    "feature_helptext_disableDarkReaderSites": "Dark Reader 扩展可能会导致网站布局问题。\n此功能允许您禁用某些或所有网站上的 Dark Reader 以防止这些问题。\n如果未安装扩展,此功能将不起作用,可以保持激活。",
 
     "feature_desc_scrollToActiveSongBtn": "在队列中添加一个按钮,以滚动到当前播放的歌曲",
     "feature_desc_clearQueueBtn": "在当前播放的队列或播放列表上方添加一个按钮,以快速清除它",

+ 179 - 91
dist/BetterYTM.css

@@ -10,8 +10,7 @@
 
 /* TODO: after cfg menu migration, leave only dialog styles here */
 #bytm-cfg-dialog-bg,
-#bytm-cfg-menu-bg
-{
+#bytm-cfg-menu-bg {
   --bytm-dialog-width-max: 1150px;
   --bytm-menu-width-max: 1150px;
   --bytm-dialog-height-max: 800px;
@@ -166,7 +165,8 @@
 #bytm-welcome-menu-footer-cont {
   display: flex;
   justify-content: space-between;
-  border-radius: 0px 0px var(--bytm-menu-border-radius) var(--bytm-menu-border-radius);
+  border-radius: 0px 0px var(--bytm-menu-border-radius)
+    var(--bytm-menu-border-radius);
 }
 
 #bytm-auto-like-channels-dialog-body {
@@ -246,7 +246,8 @@
   background-color: var(--bytm-dialog-bg);
   border: 2px solid var(--bytm-dialog-separator-color);
   border-style: none none solid none !important;
-  border-radius: var(--bytm-dialog-border-radius) var(--bytm-dialog-border-radius) 0px 0px;
+  border-radius: var(--bytm-dialog-border-radius)
+    var(--bytm-dialog-border-radius) 0px 0px;
 }
 
 .bytm-dialog-header.small {
@@ -333,15 +334,13 @@
 }
 
 .bytm-dialog-header-img,
-.bytm-dialog-close
-{
+.bytm-dialog-close {
   width: 32px;
   height: 32px;
 }
 
 .bytm-dialog-header-img.small,
-.bytm-dialog-close.small
-{
+.bytm-dialog-close.small {
   width: 24px;
   height: 24px;
 }
@@ -359,10 +358,16 @@
   margin-top: 6px;
   padding: 15px 20px;
   background: var(--bytm-dialog-bg);
-  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, var(--bytm-dialog-bg) 30%, var(--bytm-dialog-bg) 100%);
+  background: linear-gradient(
+    to bottom,
+    rgba(0, 0, 0, 0) 0%,
+    var(--bytm-dialog-bg) 30%,
+    var(--bytm-dialog-bg) 100%
+  );
   border: 2px solid var(--bytm-dialog-separator-color);
   border-style: solid none none none !important;
-  border-radius: 0px 0px var(--bytm-dialog-border-radius) var(--bytm-dialog-border-radius);
+  border-radius: 0px 0px var(--bytm-dialog-border-radius)
+    var(--bytm-dialog-border-radius);
 }
 
 .bytm-dialog-footer-buttons-cont button:not(:last-of-type) {
@@ -451,19 +456,19 @@
   min-width: 80px;
 }
 
-.bytm-ftconf-input[type=number] {
+.bytm-ftconf-input[type="number"] {
   width: 75px;
 }
 
-.bytm-ftconf-input[type=range] {
+.bytm-ftconf-input[type="range"] {
   width: 200px;
 }
 
-.bytm-ftconf-input[type=text] {
+.bytm-ftconf-input[type="text"] {
   width: 200px;
 }
 
-.bytm-ftconf-input[type=checkbox] {
+.bytm-ftconf-input[type="checkbox"] {
   margin-left: 5px;
 }
 
@@ -472,7 +477,8 @@ select.bytm-ftconf-input {
   cursor: revert;
 }
 
-#bytm-export-dialog-text, #bytm-import-dialog-text {
+#bytm-export-dialog-text,
+#bytm-import-dialog-text {
   font-size: 1.6em;
   margin-bottom: 15px;
 }
@@ -486,7 +492,8 @@ select.bytm-ftconf-input {
   overflow-y: auto;
 }
 
-#bytm-export-dialog-textarea, #bytm-import-dialog-textarea {
+#bytm-export-dialog-textarea,
+#bytm-import-dialog-textarea {
   width: 100%;
   height: 150px;
   resize: none;
@@ -502,7 +509,8 @@ select.bytm-ftconf-input {
 
 /* Markdown stuff */
 
-.bytm-markdown-container kbd, .bytm-kbd {
+.bytm-markdown-container kbd,
+.bytm-kbd {
   --bytm-kbd-easing: cubic-bezier(0.31, 0.58, 0.24, 1.15);
   display: inline-block;
   vertical-align: bottom;
@@ -514,16 +522,21 @@ select.bytm-ftconf-input {
   border: 1px solid #777;
   border-radius: 5px;
   box-shadow: inset 0 -2px 0 #515559;
-  transition: padding 0.1s var(--bytm-kbd-easing), margin-top 0.1s var(--bytm-kbd-easing), box-shadow 0.1s var(--bytm-kbd-easing);
+  transition:
+    padding 0.1s var(--bytm-kbd-easing),
+    margin-top 0.1s var(--bytm-kbd-easing),
+    box-shadow 0.1s var(--bytm-kbd-easing);
 }
 
-.bytm-markdown-container kbd:active, .bytm-kbd:active {
+.bytm-markdown-container kbd:active,
+.bytm-kbd:active {
   padding-bottom: 2px;
   margin-top: 2px;
   box-shadow: inset 0 0 0 initial;
 }
 
-.bytm-markdown-container kbd::selection, .bytm-kbd::selection {
+.bytm-markdown-container kbd::selection,
+.bytm-kbd::selection {
   background: rgba(0, 0, 0, 0);
 }
 
@@ -553,7 +566,8 @@ select.bytm-ftconf-input {
   font-weight: bolder;
 }
 
-#bytm-feat-help-dialog-desc, #bytm-feat-help-dialog-text {
+#bytm-feat-help-dialog-desc,
+#bytm-feat-help-dialog-text {
   overflow-wrap: break-word;
   white-space: pre-wrap;
   font-size: 1.5em;
@@ -624,7 +638,8 @@ body .bytm-ripple.slower {
   transform: translate(-50%, -50%);
   pointer-events: none;
   border-radius: 50%;
-  animation: bytm-scale-ripple var(--bytm-ripple-anim-duration, 0.55s) cubic-bezier(0.375, 0.330, 0.225, 0.930);
+  animation: bytm-scale-ripple var(--bytm-ripple-anim-duration, 0.55s)
+    cubic-bezier(0.375, 0.33, 0.225, 0.93);
 }
 
 @keyframes bytm-scale-ripple {
@@ -635,8 +650,18 @@ body .bytm-ripple.slower {
   }
   100% {
     /* Variable is added to .bytm-ripple by JS at runtime since there's no better way of getting the parent's width inside of here */
-    width: calc(max(var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2, var(--bytm-ripple-min-size)));
-    height: calc(max(var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2, var(--bytm-ripple-min-size)));
+    width: calc(
+      max(
+        var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2,
+        var(--bytm-ripple-min-size)
+      )
+    );
+    height: calc(
+      max(
+        var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2,
+        var(--bytm-ripple-min-size)
+      )
+    );
     opacity: 0;
   }
 }
@@ -705,7 +730,9 @@ body .bytm-ripple.slower {
   background-color: var(--bytm-toast-bg-color);
   color: var(--bytm-toast-text-color);
 
-  transition: opacity var(--bytm-toast-transition-time) ease, transform var(--bytm-toast-transition-time) ease;
+  transition:
+    opacity var(--bytm-toast-transition-time) ease,
+    transform var(--bytm-toast-transition-time) ease;
 }
 
 #bytm-toast.clickable {
@@ -744,8 +771,7 @@ body .bytm-ripple.slower {
 #bytm-toast.visible.pos-tl,
 #bytm-toast.visible.pos-tr,
 #bytm-toast.visible.pos-br,
-#bytm-toast.visible.pos-bl
-{
+#bytm-toast.visible.pos-bl {
   transform: translate(0, 0);
 }
 
@@ -757,8 +783,7 @@ body .bytm-ripple.slower {
 }
 
 .bytm-toast-icon.img,
-.bytm-toast-icon svg
-{
+.bytm-toast-icon svg {
   width: 24px;
   height: 24px;
 }
@@ -806,7 +831,9 @@ body .bytm-ripple.slower {
   padding: var(--toggle-knob-offset);
   cursor: pointer;
   background-color: var(--toggle-color-off);
-  transition: justify-content 0.2s ease, background-color 0.2s ease;
+  transition:
+    justify-content 0.2s ease,
+    background-color 0.2s ease;
 }
 
 .bytm-toggle-input input[data-toggled="true"] {
@@ -814,8 +841,12 @@ body .bytm-ripple.slower {
 }
 
 .bytm-toggle-input input .bytm-toggle-input-knob {
-  --toggle-knob-calc-width: calc(var(--toggle-height) - (var(--toggle-knob-offset) * 2));
-  --toggle-knob-calc-height: calc(var(--toggle-height) - (var(--toggle-knob-offset) * 2));
+  --toggle-knob-calc-width: calc(
+    var(--toggle-height) - (var(--toggle-knob-offset) * 2)
+  );
+  --toggle-knob-calc-height: calc(
+    var(--toggle-height) - (var(--toggle-knob-offset) * 2)
+  );
   width: var(--toggle-knob-calc-width);
   height: var(--toggle-knob-calc-height);
   background-color: var(--toggle-knob-color);
@@ -828,8 +859,12 @@ body .bytm-ripple.slower {
 }
 
 .bytm-toggle-input input[data-toggled="true"] .bytm-toggle-input-knob {
-  left: calc(var(--toggle-width) - var(--toggle-knob-offset) - var(--toggle-knob-calc-width));
+  left: calc(
+    var(--toggle-width) - var(--toggle-knob-offset) -
+      var(--toggle-knob-calc-width)
+  );
 }
+
 .bytm-auto-like-channels-footer-wrapper {
   display: flex;
   justify-content: space-between;
@@ -899,7 +934,8 @@ body .bytm-ripple.slower {
   background-color: var(--bytm-menu-bg);
   border: 2px solid var(--bytm-menu-separator-color);
   border-style: none none solid none !important;
-  border-radius: var(--bytm-menu-border-radius) var(--bytm-menu-border-radius) 0px 0px;
+  border-radius: var(--bytm-menu-border-radius) var(--bytm-menu-border-radius)
+    0px 0px;
 }
 
 .bytm-menu-header.small {
@@ -958,11 +994,13 @@ body .bytm-ripple.slower {
   z-index: 7;
 }
 
-#bytm-menu-subtitle-cont, #bytm-menu-version-anchor {
+#bytm-menu-subtitle-cont,
+#bytm-menu-version-anchor {
   color: var(--bytm-menu-subtitle-color) !important;
 }
 
-#bytm-menu-subtitle-cont, #bytm-menu-mode-display {
+#bytm-menu-subtitle-cont,
+#bytm-menu-mode-display {
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
@@ -1000,7 +1038,9 @@ body .bytm-ripple.slower {
   border-radius: 50%;
   padding: 0px;
   transform: translateY(0px);
-  transition: transform 0.15s ease-out, padding 0.15s ease-out;
+  transition:
+    transform 0.15s ease-out,
+    padding 0.15s ease-out;
 }
 
 .bytm-menu-link:hover .bytm-menu-img {
@@ -1019,7 +1059,9 @@ body .bytm-ripple.slower {
   color: var(--bytm-menu-subtitle-color) !important;
   white-space: pre;
   font-size: 1.1rem;
-  transition: visibility 0.15s ease-out, opacity 0.15s ease-out;
+  transition:
+    visibility 0.15s ease-out,
+    opacity 0.15s ease-out;
 }
 
 .bytm-menu-link:hover .extended-link {
@@ -1054,10 +1096,16 @@ body .bytm-ripple.slower {
   margin-top: 6px;
   padding: 15px;
   background: var(--bytm-menu-bg);
-  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, var(--bytm-menu-bg) 30%, var(--bytm-menu-bg) 100%);
+  background: linear-gradient(
+    to bottom,
+    rgba(0, 0, 0, 0) 0%,
+    var(--bytm-menu-bg) 30%,
+    var(--bytm-menu-bg) 100%
+  );
   border: 2px solid var(--bytm-menu-separator-color);
   border-style: solid none none none !important;
-  border-radius: 0px 0px var(--bytm-menu-border-radius) var(--bytm-menu-border-radius);
+  border-radius: 0px 0px var(--bytm-menu-border-radius)
+    var(--bytm-menu-border-radius);
 }
 
 .bytm-menu-footer-buttons-cont button:not(:last-of-type) {
@@ -1150,15 +1198,16 @@ body .bytm-ripple.slower {
   min-width: 50px;
 }
 
-.bytm-ftconf-input[type=number] {
+.bytm-ftconf-input[type="number"] {
   width: 75px;
 }
 
-.bytm-ftconf-input[type=checkbox] {
+.bytm-ftconf-input[type="checkbox"] {
   margin-left: 5px;
 }
 
-#bytm-export-menu-text, #bytm-import-menu-text {
+#bytm-export-menu-text,
+#bytm-import-menu-text {
   white-space: pre-wrap;
   font-size: 1.6rem;
   margin-bottom: 15px;
@@ -1189,7 +1238,8 @@ body .bytm-ripple.slower {
   font-size: 2rem;
 }
 
-#bytm-export-menu-textarea, #bytm-import-menu-textarea {
+#bytm-export-menu-textarea,
+#bytm-import-menu-textarea {
   width: 100%;
   height: 150px;
   resize: none;
@@ -1217,7 +1267,9 @@ body .bytm-ripple.slower {
   border: 1px solid #777;
   border-radius: 5px;
   box-shadow: inset 0 -2px 0 #515559;
-  transition: padding 0.1s var(--bytm-easing), box-shadow 0.1s var(--bytm-easing);
+  transition:
+    padding 0.1s var(--bytm-easing),
+    box-shadow 0.1s var(--bytm-easing);
 }
 
 .bytm-markdown-container kbd:active {
@@ -1288,7 +1340,8 @@ body .bytm-ripple.slower {
   padding-top: 10px;
 }
 
-#bytm-feat-help-dialog-desc, #bytm-feat-help-dialog-text {
+#bytm-feat-help-dialog-desc,
+#bytm-feat-help-dialog-text {
   overflow-wrap: break-word;
   white-space: pre-wrap;
   font-size: 1.5rem;
@@ -1322,6 +1375,10 @@ hr {
 
 /* #region misc */
 
+:root {
+  --bytm-themed-bg: var(--ts-playerpage-color, #030303);
+}
+
 .bytm-disable-scroll {
   overflow: hidden !important;
 }
@@ -1494,13 +1551,15 @@ button.bytm-btn {
   line-height: 1.4em;
 }
 
-.bytm-link, .bytm-markdown-container a {
+.bytm-link,
+.bytm-markdown-container a {
   color: #369bff !important;
   text-decoration: none !important;
   cursor: pointer;
 }
 
-.bytm-link:hover, .bytm-markdown-container a:hover {
+.bytm-link:hover,
+.bytm-markdown-container a:hover {
   color: #369bff !important;
   text-decoration: underline !important;
 }
@@ -1576,7 +1635,10 @@ yt-multi-page-menu-section-renderer.ytd-multi-page-menu-renderer {
 }
 
 .bytm-yt-cfg-menu-option-inner:hover {
-  background-color: var(--yt-spec-badge-chip-background, rgba(255, 255, 255, 0.1));
+  background-color: var(
+    --yt-spec-badge-chip-background,
+    rgba(255, 255, 255, 0.1)
+  );
 }
 
 .bytm-yt-cfg-menu-option-icon {
@@ -1713,7 +1775,7 @@ ytmusic-player#player #bezel {
   padding-left: 3px;
 }
 
-ytmusic-app-layout[player-ui-state=FULLSCREEN] .bytm-vote-label {
+ytmusic-app-layout[player-ui-state="FULLSCREEN"] .bytm-vote-label {
   color: white;
 }
 
@@ -1724,19 +1786,37 @@ ytmusic-app-layout[player-ui-state=FULLSCREEN] .bytm-vote-label {
 /* #region fullscreen player bar */
 
 /* Increase specificity to override YTM's default styles without having to use !important */
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] {
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"] {
   width: 100%;
   background: rgba(0, 0, 0, 0.35);
   backdrop-filter: blur(10px) brightness(90%);
 }
 
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] .ytmusic-menu-renderer svg path,
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] tp-yt-paper-icon-button svg path
-{
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"]
+  .ytmusic-menu-renderer
+  svg
+  path,
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"]
+  tp-yt-paper-icon-button
+  svg
+  path {
   fill: #fff;
 }
 
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] .time-info {
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"]
+  .time-info {
   color: #fff;
 }
 
@@ -1797,7 +1877,8 @@ ytmusic-app-layout[player-ui-state=FULLSCREEN] .bytm-vote-label {
   background-color: var(--bytm-menu-bg-highlight);
 }
 
-.bytm-auto-like-channel-row .bytm-toggle-input-wrapper.bytm-auto-like-channel-toggle {
+.bytm-auto-like-channel-row
+  .bytm-toggle-input-wrapper.bytm-auto-like-channel-toggle {
   --toggle-height: 18px !important;
   --toggle-width: 36px !important;
 }
@@ -1843,7 +1924,10 @@ ytmusic-app-layout[player-ui-state=FULLSCREEN] .bytm-vote-label {
   background-color: rgba(255, 255, 255, 0.1);
 }
 
-body.bytm-dom-ytm ytmusic-subscribe-button-renderer #button-shape-subscribe:hover > button {
+body.bytm-dom-ytm
+  ytmusic-subscribe-button-renderer
+  #button-shape-subscribe:hover
+  > button {
   background-color: rgba(255, 255, 255, 0.1) !important;
 }
 
@@ -1872,9 +1956,10 @@ body.bytm-dom-ytm ytmusic-subscribe-button-renderer #button-shape-subscribe:hove
   transition: color 0.2s ease;
 }
 
-.bytm-generic-btn.long.bytm-auto-like-toggle-btn:active .bytm-generic-long-btn-txt,
-.bytm-generic-btn.long.bytm-auto-like-toggle-btn.toggled .bytm-generic-long-btn-txt
-{
+.bytm-generic-btn.long.bytm-auto-like-toggle-btn:active
+  .bytm-generic-long-btn-txt,
+.bytm-generic-btn.long.bytm-auto-like-toggle-btn.toggled
+  .bytm-generic-long-btn-txt {
   color: var(--ytmusic-subscribe-button-color, rgba(255, 255, 255, 0.7));
 }
 
@@ -1885,8 +1970,12 @@ body.bytm-dom-ytm ytmusic-subscribe-button-renderer #button-shape-subscribe:hove
 }
 
 #side-panel ytmusic-player-queue-item .bytm-queue-btn-container {
-  background: rgb(0, 0, 0);
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #030303 15%);
+  background: rgba(255, 255, 255, 0.1);
+  background: linear-gradient(
+    90deg,
+    rgba(0, 0, 0, 0) 0%,
+    var(--bytm-themed-bg) 15%
+  );
   display: none;
   position: absolute;
   right: 0;
@@ -1895,7 +1984,11 @@ body.bytm-dom-ytm ytmusic-subscribe-button-renderer #button-shape-subscribe:hove
 }
 
 #side-panel ytmusic-player-queue-item[selected] .bytm-queue-btn-container {
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #1D1D1D 15%);
+  background: linear-gradient(
+    90deg,
+    rgba(0, 0, 0, 0) 0%,
+    var(--ts-palette-darkmuted-hex, #1d1d1d) 15%
+  );
 }
 
 .bytm-generic-list-queue-btn-container {
@@ -1909,8 +2002,7 @@ ytmusic-shelf-renderer ytmusic-responsive-list-item-renderer:hover .bytm-queue-b
 /* same thing but with :focus-within */
 #side-panel ytmusic-player-queue-item:focus-within .bytm-queue-btn-container,
 ytmusic-playlist-shelf-renderer ytmusic-responsive-list-item-renderer:focus-within .bytm-queue-btn-container,
-ytmusic-shelf-renderer ytmusic-responsive-list-item-renderer:focus-within .bytm-queue-btn-container
-{
+ytmusic-shelf-renderer ytmusic-responsive-list-item-renderer:focus-within .bytm-queue-btn-container {
   display: inline-flex;
   align-items: center;
 }
@@ -1919,43 +2011,36 @@ ytmusic-responsive-list-item-renderer .title-column {
   align-items: center;
 }
 
-#side-panel ytmusic-player-queue-item[play-button-state="loading"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[play-button-state="playing"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[play-button-state="paused"] .bytm-queue-btn-container
-{
-  /* using a var() with predefined value from YTM is not viable since the nesting changes the actual value of the variable */
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #030303 15%);
-}
-
-#side-panel ytmusic-player-queue-item[selected][play-button-state="loading"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[selected][play-button-state="playing"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[selected][play-button-state="paused"] .bytm-queue-btn-container
-{
-  /* using a var() with predefined value from YTM is not viable since the nesting changes the actual value of the variable */
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #1D1D1D 15%);
-}
-
-ytmusic-app ytmusic-popup-container tp-yt-iron-dropdown[data-bytm-hidden=true] {
+ytmusic-app
+  ytmusic-popup-container
+  tp-yt-iron-dropdown[data-bytm-hidden="true"] {
   display: none !important;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns .bytm-generic-list-queue-btn-container {
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns
+  .bytm-generic-list-queue-btn-container {
   visibility: hidden;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns .bytm-generic-list-queue-btn-container a.bytm-generic-btn {
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns
+  .bytm-generic-list-queue-btn-container
+  a.bytm-generic-btn {
   visibility: hidden !important;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover .bytm-generic-list-queue-btn-container,
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within .bytm-generic-list-queue-btn-container
-{
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover
+  .bytm-generic-list-queue-btn-container,
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within
+  .bytm-generic-list-queue-btn-container {
   visibility: visible;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover .bytm-generic-list-queue-btn-container a.bytm-generic-btn,
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within .bytm-generic-list-queue-btn-container a.bytm-generic-btn
-{
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover
+  .bytm-generic-list-queue-btn-container
+  a.bytm-generic-btn,
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within
+  .bytm-generic-list-queue-btn-container
+  a.bytm-generic-btn {
   visibility: visible !important;
 }
 
@@ -1996,7 +2081,10 @@ ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within .bytm-gen
   opacity: 1;
 }
 
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] #bytm-vol-slider-label {
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  #bytm-vol-slider-label {
   color: #fff;
 }
 

+ 32 - 18
src/components/BytmDialog.css

@@ -70,7 +70,8 @@
   background-color: var(--bytm-dialog-bg);
   border: 2px solid var(--bytm-dialog-separator-color);
   border-style: none none solid none !important;
-  border-radius: var(--bytm-dialog-border-radius) var(--bytm-dialog-border-radius) 0px 0px;
+  border-radius: var(--bytm-dialog-border-radius)
+    var(--bytm-dialog-border-radius) 0px 0px;
 }
 
 .bytm-dialog-header.small {
@@ -157,15 +158,13 @@
 }
 
 .bytm-dialog-header-img,
-.bytm-dialog-close
-{
+.bytm-dialog-close {
   width: 32px;
   height: 32px;
 }
 
 .bytm-dialog-header-img.small,
-.bytm-dialog-close.small
-{
+.bytm-dialog-close.small {
   width: 24px;
   height: 24px;
 }
@@ -183,10 +182,16 @@
   margin-top: 6px;
   padding: 15px 20px;
   background: var(--bytm-dialog-bg);
-  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, var(--bytm-dialog-bg) 30%, var(--bytm-dialog-bg) 100%);
+  background: linear-gradient(
+    to bottom,
+    rgba(0, 0, 0, 0) 0%,
+    var(--bytm-dialog-bg) 30%,
+    var(--bytm-dialog-bg) 100%
+  );
   border: 2px solid var(--bytm-dialog-separator-color);
   border-style: solid none none none !important;
-  border-radius: 0px 0px var(--bytm-dialog-border-radius) var(--bytm-dialog-border-radius);
+  border-radius: 0px 0px var(--bytm-dialog-border-radius)
+    var(--bytm-dialog-border-radius);
 }
 
 .bytm-dialog-footer-buttons-cont button:not(:last-of-type) {
@@ -275,19 +280,19 @@
   min-width: 80px;
 }
 
-.bytm-ftconf-input[type=number] {
+.bytm-ftconf-input[type="number"] {
   width: 75px;
 }
 
-.bytm-ftconf-input[type=range] {
+.bytm-ftconf-input[type="range"] {
   width: 200px;
 }
 
-.bytm-ftconf-input[type=text] {
+.bytm-ftconf-input[type="text"] {
   width: 200px;
 }
 
-.bytm-ftconf-input[type=checkbox] {
+.bytm-ftconf-input[type="checkbox"] {
   margin-left: 5px;
 }
 
@@ -296,7 +301,8 @@ select.bytm-ftconf-input {
   cursor: revert;
 }
 
-#bytm-export-dialog-text, #bytm-import-dialog-text {
+#bytm-export-dialog-text,
+#bytm-import-dialog-text {
   font-size: 1.6em;
   margin-bottom: 15px;
 }
@@ -310,7 +316,8 @@ select.bytm-ftconf-input {
   overflow-y: auto;
 }
 
-#bytm-export-dialog-textarea, #bytm-import-dialog-textarea {
+#bytm-export-dialog-textarea,
+#bytm-import-dialog-textarea {
   width: 100%;
   height: 150px;
   resize: none;
@@ -326,7 +333,8 @@ select.bytm-ftconf-input {
 
 /* Markdown stuff */
 
-.bytm-markdown-container kbd, .bytm-kbd {
+.bytm-markdown-container kbd,
+.bytm-kbd {
   --bytm-kbd-easing: cubic-bezier(0.31, 0.58, 0.24, 1.15);
   display: inline-block;
   vertical-align: bottom;
@@ -338,16 +346,21 @@ select.bytm-ftconf-input {
   border: 1px solid #777;
   border-radius: 5px;
   box-shadow: inset 0 -2px 0 #515559;
-  transition: padding 0.1s var(--bytm-kbd-easing), margin-top 0.1s var(--bytm-kbd-easing), box-shadow 0.1s var(--bytm-kbd-easing);
+  transition:
+    padding 0.1s var(--bytm-kbd-easing),
+    margin-top 0.1s var(--bytm-kbd-easing),
+    box-shadow 0.1s var(--bytm-kbd-easing);
 }
 
-.bytm-markdown-container kbd:active, .bytm-kbd:active {
+.bytm-markdown-container kbd:active,
+.bytm-kbd:active {
   padding-bottom: 2px;
   margin-top: 2px;
   box-shadow: inset 0 0 0 initial;
 }
 
-.bytm-markdown-container kbd::selection, .bytm-kbd::selection {
+.bytm-markdown-container kbd::selection,
+.bytm-kbd::selection {
   background: rgba(0, 0, 0, 0);
 }
 
@@ -377,7 +390,8 @@ select.bytm-ftconf-input {
   font-weight: bolder;
 }
 
-#bytm-feat-help-dialog-desc, #bytm-feat-help-dialog-text {
+#bytm-feat-help-dialog-desc,
+#bytm-feat-help-dialog-text {
   overflow-wrap: break-word;
   white-space: pre-wrap;
   font-size: 1.5em;

+ 14 - 3
src/components/ripple.css

@@ -31,7 +31,8 @@ body .bytm-ripple.slower {
   transform: translate(-50%, -50%);
   pointer-events: none;
   border-radius: 50%;
-  animation: bytm-scale-ripple var(--bytm-ripple-anim-duration, 0.55s) cubic-bezier(0.375, 0.330, 0.225, 0.930);
+  animation: bytm-scale-ripple var(--bytm-ripple-anim-duration, 0.55s)
+    cubic-bezier(0.375, 0.33, 0.225, 0.93);
 }
 
 @keyframes bytm-scale-ripple {
@@ -42,8 +43,18 @@ body .bytm-ripple.slower {
   }
   100% {
     /* Variable is added to .bytm-ripple by JS at runtime since there's no better way of getting the parent's width inside of here */
-    width: calc(max(var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2, var(--bytm-ripple-min-size)));
-    height: calc(max(var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2, var(--bytm-ripple-min-size)));
+    width: calc(
+      max(
+        var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2,
+        var(--bytm-ripple-min-size)
+      )
+    );
+    height: calc(
+      max(
+        var(--bytm-ripple-cont-width, var(--bytm-ripple-min-size)) * 2,
+        var(--bytm-ripple-min-size)
+      )
+    );
     opacity: 0;
   }
 }

+ 5 - 5
src/components/toast.css

@@ -19,7 +19,9 @@
   background-color: var(--bytm-toast-bg-color);
   color: var(--bytm-toast-text-color);
 
-  transition: opacity var(--bytm-toast-transition-time) ease, transform var(--bytm-toast-transition-time) ease;
+  transition:
+    opacity var(--bytm-toast-transition-time) ease,
+    transform var(--bytm-toast-transition-time) ease;
 }
 
 #bytm-toast.clickable {
@@ -58,8 +60,7 @@
 #bytm-toast.visible.pos-tl,
 #bytm-toast.visible.pos-tr,
 #bytm-toast.visible.pos-br,
-#bytm-toast.visible.pos-bl
-{
+#bytm-toast.visible.pos-bl {
   transform: translate(0, 0);
 }
 
@@ -71,8 +72,7 @@
 }
 
 .bytm-toast-icon.img,
-.bytm-toast-icon svg
-{
+.bytm-toast-icon svg {
   width: 24px;
   height: 24px;
 }

+ 14 - 5
src/components/toggleInput.css

@@ -37,7 +37,9 @@
   padding: var(--toggle-knob-offset);
   cursor: pointer;
   background-color: var(--toggle-color-off);
-  transition: justify-content 0.2s ease, background-color 0.2s ease;
+  transition:
+    justify-content 0.2s ease,
+    background-color 0.2s ease;
 }
 
 .bytm-toggle-input input[data-toggled="true"] {
@@ -45,8 +47,12 @@
 }
 
 .bytm-toggle-input input .bytm-toggle-input-knob {
-  --toggle-knob-calc-width: calc(var(--toggle-height) - (var(--toggle-knob-offset) * 2));
-  --toggle-knob-calc-height: calc(var(--toggle-height) - (var(--toggle-knob-offset) * 2));
+  --toggle-knob-calc-width: calc(
+    var(--toggle-height) - (var(--toggle-knob-offset) * 2)
+  );
+  --toggle-knob-calc-height: calc(
+    var(--toggle-height) - (var(--toggle-knob-offset) * 2)
+  );
   width: var(--toggle-knob-calc-width);
   height: var(--toggle-knob-calc-height);
   background-color: var(--toggle-knob-color);
@@ -59,5 +65,8 @@
 }
 
 .bytm-toggle-input input[data-toggled="true"] .bytm-toggle-input-knob {
-  left: calc(var(--toggle-width) - var(--toggle-knob-offset) - var(--toggle-knob-calc-width));
-}
+  left: calc(
+    var(--toggle-width) - var(--toggle-knob-offset) -
+      var(--toggle-knob-calc-width)
+  );
+}

+ 3 - 3
src/dialogs/dialogs.css

@@ -10,8 +10,7 @@
 
 /* TODO: after cfg menu migration, leave only dialog styles here */
 #bytm-cfg-dialog-bg,
-#bytm-cfg-menu-bg
-{
+#bytm-cfg-menu-bg {
   --bytm-dialog-width-max: 1150px;
   --bytm-menu-width-max: 1150px;
   --bytm-dialog-height-max: 800px;
@@ -166,7 +165,8 @@
 #bytm-welcome-menu-footer-cont {
   display: flex;
   justify-content: space-between;
-  border-radius: 0px 0px var(--bytm-menu-border-radius) var(--bytm-menu-border-radius);
+  border-radius: 0px 0px var(--bytm-menu-border-radius)
+    var(--bytm-menu-border-radius);
 }
 
 #bytm-auto-like-channels-dialog-body {

+ 2 - 0
src/features/index.ts

@@ -646,11 +646,13 @@ export const featInfo = {
     type: "toggle",
     category: "integrations",
     default: true,
+    textAdornment: adornments.reloadRequired,
   },
   themeSongIntegration: {
     type: "toggle",
     category: "integrations",
     default: false,
+    textAdornment: adornments.reloadRequired,
   },
 
   //#region general

+ 10 - 5
src/features/input.css

@@ -55,7 +55,8 @@
   background-color: var(--bytm-menu-bg-highlight);
 }
 
-.bytm-auto-like-channel-row .bytm-toggle-input-wrapper.bytm-auto-like-channel-toggle {
+.bytm-auto-like-channel-row
+  .bytm-toggle-input-wrapper.bytm-auto-like-channel-toggle {
   --toggle-height: 18px !important;
   --toggle-width: 36px !important;
 }
@@ -101,7 +102,10 @@
   background-color: rgba(255, 255, 255, 0.1);
 }
 
-body.bytm-dom-ytm ytmusic-subscribe-button-renderer #button-shape-subscribe:hover > button {
+body.bytm-dom-ytm
+  ytmusic-subscribe-button-renderer
+  #button-shape-subscribe:hover
+  > button {
   background-color: rgba(255, 255, 255, 0.1) !important;
 }
 
@@ -130,8 +134,9 @@ body.bytm-dom-ytm ytmusic-subscribe-button-renderer #button-shape-subscribe:hove
   transition: color 0.2s ease;
 }
 
-.bytm-generic-btn.long.bytm-auto-like-toggle-btn:active .bytm-generic-long-btn-txt,
-.bytm-generic-btn.long.bytm-auto-like-toggle-btn.toggled .bytm-generic-long-btn-txt
-{
+.bytm-generic-btn.long.bytm-auto-like-toggle-btn:active
+  .bytm-generic-long-btn-txt,
+.bytm-generic-btn.long.bytm-auto-like-toggle-btn.toggled
+  .bytm-generic-long-btn-txt {
   color: var(--ytmusic-subscribe-button-color, rgba(255, 255, 255, 0.7));
 }

+ 4 - 4
src/features/integrations.ts

@@ -32,12 +32,12 @@ export async function fixSponsorBlock() {
 
 //#region ThemeSong
 
-/** Adjust the BetterYTM styles to respect the theme from ThemeSong */
-export async function fixThemeSong() {
+/** Adjust the BetterYTM styles if ThemeSong is ***not*** used */
+export async function fixPlayerPageTheming() {
   try {
-    return addStyleFromResource("css-fix_themesong");
+    return addStyleFromResource("css-fix_playerpage_theming");
   }
   catch(err) {
-    error("Failed to fix ThemeSong styling:", err);
+    error("Failed to fix BetterYTM player page theming:", err);
   }
 }

+ 36 - 9
src/features/layout.css

@@ -1,5 +1,9 @@
 /* #region misc */
 
+:root {
+  --bytm-themed-bg: var(--ts-playerpage-color, #030303);
+}
+
 .bytm-disable-scroll {
   overflow: hidden !important;
 }
@@ -172,13 +176,15 @@ button.bytm-btn {
   line-height: 1.4em;
 }
 
-.bytm-link, .bytm-markdown-container a {
+.bytm-link,
+.bytm-markdown-container a {
   color: #369bff !important;
   text-decoration: none !important;
   cursor: pointer;
 }
 
-.bytm-link:hover, .bytm-markdown-container a:hover {
+.bytm-link:hover,
+.bytm-markdown-container a:hover {
   color: #369bff !important;
   text-decoration: underline !important;
 }
@@ -254,7 +260,10 @@ yt-multi-page-menu-section-renderer.ytd-multi-page-menu-renderer {
 }
 
 .bytm-yt-cfg-menu-option-inner:hover {
-  background-color: var(--yt-spec-badge-chip-background, rgba(255, 255, 255, 0.1));
+  background-color: var(
+    --yt-spec-badge-chip-background,
+    rgba(255, 255, 255, 0.1)
+  );
 }
 
 .bytm-yt-cfg-menu-option-icon {
@@ -391,7 +400,7 @@ ytmusic-player#player #bezel {
   padding-left: 3px;
 }
 
-ytmusic-app-layout[player-ui-state=FULLSCREEN] .bytm-vote-label {
+ytmusic-app-layout[player-ui-state="FULLSCREEN"] .bytm-vote-label {
   color: white;
 }
 
@@ -402,18 +411,36 @@ ytmusic-app-layout[player-ui-state=FULLSCREEN] .bytm-vote-label {
 /* #region fullscreen player bar */
 
 /* Increase specificity to override YTM's default styles without having to use !important */
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] {
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"] {
   width: 100%;
   background: rgba(0, 0, 0, 0.35);
   backdrop-filter: blur(10px) brightness(90%);
 }
 
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] .ytmusic-menu-renderer svg path,
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] tp-yt-paper-icon-button svg path
-{
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"]
+  .ytmusic-menu-renderer
+  svg
+  path,
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"]
+  tp-yt-paper-icon-button
+  svg
+  path {
   fill: #fff;
 }
 
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] ytmusic-player-bar[slot=player-bar] .time-info {
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  ytmusic-player-bar[slot="player-bar"]
+  .time-info {
   color: #fff;
 }

+ 30 - 30
src/features/songLists.css

@@ -5,8 +5,12 @@
 }
 
 #side-panel ytmusic-player-queue-item .bytm-queue-btn-container {
-  background: rgb(0, 0, 0);
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #030303 15%);
+  background: rgba(255, 255, 255, 0.1);
+  background: linear-gradient(
+    90deg,
+    rgba(0, 0, 0, 0) 0%,
+    var(--bytm-themed-bg) 15%
+  );
   display: none;
   position: absolute;
   right: 0;
@@ -15,7 +19,11 @@
 }
 
 #side-panel ytmusic-player-queue-item[selected] .bytm-queue-btn-container {
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #1D1D1D 15%);
+  background: linear-gradient(
+    90deg,
+    rgba(0, 0, 0, 0) 0%,
+    var(--ts-palette-darkmuted-hex, #1d1d1d) 15%
+  );
 }
 
 .bytm-generic-list-queue-btn-container {
@@ -29,8 +37,7 @@ ytmusic-shelf-renderer ytmusic-responsive-list-item-renderer:hover .bytm-queue-b
 /* same thing but with :focus-within */
 #side-panel ytmusic-player-queue-item:focus-within .bytm-queue-btn-container,
 ytmusic-playlist-shelf-renderer ytmusic-responsive-list-item-renderer:focus-within .bytm-queue-btn-container,
-ytmusic-shelf-renderer ytmusic-responsive-list-item-renderer:focus-within .bytm-queue-btn-container
-{
+ytmusic-shelf-renderer ytmusic-responsive-list-item-renderer:focus-within .bytm-queue-btn-container {
   display: inline-flex;
   align-items: center;
 }
@@ -39,42 +46,35 @@ ytmusic-responsive-list-item-renderer .title-column {
   align-items: center;
 }
 
-#side-panel ytmusic-player-queue-item[play-button-state="loading"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[play-button-state="playing"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[play-button-state="paused"] .bytm-queue-btn-container
-{
-  /* using a var() with predefined value from YTM is not viable since the nesting changes the actual value of the variable */
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #030303 15%);
-}
-
-#side-panel ytmusic-player-queue-item[selected][play-button-state="loading"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[selected][play-button-state="playing"] .bytm-queue-btn-container,
-#side-panel ytmusic-player-queue-item[selected][play-button-state="paused"] .bytm-queue-btn-container
-{
-  /* using a var() with predefined value from YTM is not viable since the nesting changes the actual value of the variable */
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, #1D1D1D 15%);
-}
-
-ytmusic-app ytmusic-popup-container tp-yt-iron-dropdown[data-bytm-hidden=true] {
+ytmusic-app
+  ytmusic-popup-container
+  tp-yt-iron-dropdown[data-bytm-hidden="true"] {
   display: none !important;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns .bytm-generic-list-queue-btn-container {
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns
+  .bytm-generic-list-queue-btn-container {
   visibility: hidden;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns .bytm-generic-list-queue-btn-container a.bytm-generic-btn {
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns
+  .bytm-generic-list-queue-btn-container
+  a.bytm-generic-btn {
   visibility: hidden !important;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover .bytm-generic-list-queue-btn-container,
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within .bytm-generic-list-queue-btn-container
-{
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover
+  .bytm-generic-list-queue-btn-container,
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within
+  .bytm-generic-list-queue-btn-container {
   visibility: visible;
 }
 
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover .bytm-generic-list-queue-btn-container a.bytm-generic-btn,
-ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within .bytm-generic-list-queue-btn-container a.bytm-generic-btn
-{
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:hover
+  .bytm-generic-list-queue-btn-container
+  a.bytm-generic-btn,
+ytmusic-responsive-list-item-renderer.bytm-has-queue-btns:focus-within
+  .bytm-generic-list-queue-btn-container
+  a.bytm-generic-btn {
   visibility: visible !important;
 }

+ 4 - 1
src/features/volume.css

@@ -35,7 +35,10 @@
   opacity: 1;
 }
 
-:root body.bytm-dom-ytm ytmusic-app-layout[player-ui-state=FULLSCREEN] #bytm-vol-slider-label {
+:root
+  body.bytm-dom-ytm
+  ytmusic-app-layout[player-ui-state="FULLSCREEN"]
+  #bytm-vol-slider-label {
   color: #fff;
 }
 

+ 18 - 11
src/index.ts

@@ -29,7 +29,7 @@ import {
   addPlayerBarLyricsBtn, initLyricsCache,
   // integrations
   disableDarkReader, fixSponsorBlock,
-  fixThemeSong,
+  fixPlayerPageTheming,
   // general
   initVersionCheck,
   // menu
@@ -208,8 +208,8 @@ async function onDomLoad() {
       if(feats.sponsorBlockIntegration)
         ftInit.push(["sponsorBlockIntegration", fixSponsorBlock()]);
 
-      if(feats.themeSongIntegration)
-        ftInit.push(["themeSongIntegration", fixThemeSong()]);
+      if(!feats.themeSongIntegration)
+        ftInit.push(["themeSongIntegration", fixPlayerPageTheming()]);
     }
 
     //#region (ytm+yt) cfg menu
@@ -304,15 +304,22 @@ async function injectCssBundle() {
 
 /** Initializes global CSS variables */
 function initGlobalCssVars() {
-  const applyVars = () => setGlobalCssVars({
-    "inner-height": `${window.innerHeight}px`,
-    "outer-height": `${window.outerHeight}px`,
-    "inner-width": `${window.innerWidth}px`,
-    "outer-width": `${window.outerWidth}px`,
-  });
+  try {
+    const applyVars = () => {
+      setGlobalCssVars({
+        "inner-height": `${window.innerHeight}px`,
+        "outer-height": `${window.outerHeight}px`,
+        "inner-width": `${window.innerWidth}px`,
+        "outer-width": `${window.outerWidth}px`,
+      });
+    };
 
-  window.addEventListener("resize", applyVars);
-  applyVars();
+    window.addEventListener("resize", applyVars);
+    applyVars();
+  }
+  catch(err) {
+    error("Couldn't initialize global CSS variables:", err);
+  }
 }
 
 //#region dev menu cmds

+ 31 - 13
src/menu/menu_old.css

@@ -62,7 +62,8 @@
   background-color: var(--bytm-menu-bg);
   border: 2px solid var(--bytm-menu-separator-color);
   border-style: none none solid none !important;
-  border-radius: var(--bytm-menu-border-radius) var(--bytm-menu-border-radius) 0px 0px;
+  border-radius: var(--bytm-menu-border-radius) var(--bytm-menu-border-radius)
+    0px 0px;
 }
 
 .bytm-menu-header.small {
@@ -121,11 +122,13 @@
   z-index: 7;
 }
 
-#bytm-menu-subtitle-cont, #bytm-menu-version-anchor {
+#bytm-menu-subtitle-cont,
+#bytm-menu-version-anchor {
   color: var(--bytm-menu-subtitle-color) !important;
 }
 
-#bytm-menu-subtitle-cont, #bytm-menu-mode-display {
+#bytm-menu-subtitle-cont,
+#bytm-menu-mode-display {
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
@@ -163,7 +166,9 @@
   border-radius: 50%;
   padding: 0px;
   transform: translateY(0px);
-  transition: transform 0.15s ease-out, padding 0.15s ease-out;
+  transition:
+    transform 0.15s ease-out,
+    padding 0.15s ease-out;
 }
 
 .bytm-menu-link:hover .bytm-menu-img {
@@ -182,7 +187,9 @@
   color: var(--bytm-menu-subtitle-color) !important;
   white-space: pre;
   font-size: 1.1rem;
-  transition: visibility 0.15s ease-out, opacity 0.15s ease-out;
+  transition:
+    visibility 0.15s ease-out,
+    opacity 0.15s ease-out;
 }
 
 .bytm-menu-link:hover .extended-link {
@@ -217,10 +224,16 @@
   margin-top: 6px;
   padding: 15px;
   background: var(--bytm-menu-bg);
-  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, var(--bytm-menu-bg) 30%, var(--bytm-menu-bg) 100%);
+  background: linear-gradient(
+    to bottom,
+    rgba(0, 0, 0, 0) 0%,
+    var(--bytm-menu-bg) 30%,
+    var(--bytm-menu-bg) 100%
+  );
   border: 2px solid var(--bytm-menu-separator-color);
   border-style: solid none none none !important;
-  border-radius: 0px 0px var(--bytm-menu-border-radius) var(--bytm-menu-border-radius);
+  border-radius: 0px 0px var(--bytm-menu-border-radius)
+    var(--bytm-menu-border-radius);
 }
 
 .bytm-menu-footer-buttons-cont button:not(:last-of-type) {
@@ -313,15 +326,16 @@
   min-width: 50px;
 }
 
-.bytm-ftconf-input[type=number] {
+.bytm-ftconf-input[type="number"] {
   width: 75px;
 }
 
-.bytm-ftconf-input[type=checkbox] {
+.bytm-ftconf-input[type="checkbox"] {
   margin-left: 5px;
 }
 
-#bytm-export-menu-text, #bytm-import-menu-text {
+#bytm-export-menu-text,
+#bytm-import-menu-text {
   white-space: pre-wrap;
   font-size: 1.6rem;
   margin-bottom: 15px;
@@ -352,7 +366,8 @@
   font-size: 2rem;
 }
 
-#bytm-export-menu-textarea, #bytm-import-menu-textarea {
+#bytm-export-menu-textarea,
+#bytm-import-menu-textarea {
   width: 100%;
   height: 150px;
   resize: none;
@@ -380,7 +395,9 @@
   border: 1px solid #777;
   border-radius: 5px;
   box-shadow: inset 0 -2px 0 #515559;
-  transition: padding 0.1s var(--bytm-easing), box-shadow 0.1s var(--bytm-easing);
+  transition:
+    padding 0.1s var(--bytm-easing),
+    box-shadow 0.1s var(--bytm-easing);
 }
 
 .bytm-markdown-container kbd:active {
@@ -451,7 +468,8 @@
   padding-top: 10px;
 }
 
-#bytm-feat-help-dialog-desc, #bytm-feat-help-dialog-text {
+#bytm-feat-help-dialog-desc,
+#bytm-feat-help-dialog-text {
   overflow-wrap: break-word;
   white-space: pre-wrap;
   font-size: 1.5rem;

+ 66 - 1
src/utils/misc.ts

@@ -1,4 +1,4 @@
-import { compress, decompress, fetchAdvanced, openInNewTab, pauseFor, randomId } from "@sv443-network/userutils";
+import { clamp, compress, decompress, fetchAdvanced, openInNewTab, pauseFor, randomId } from "@sv443-network/userutils";
 import { marked } from "marked";
 import { branch, compressionFormat, repo, sessionStorageAvailable } from "../constants.js";
 import { type Domain, type ResourceKey } from "../types.js";
@@ -178,6 +178,71 @@ export async function tryToDecompressAndParse<TData = Record<string, unknown>>(i
   return parsed;
 }
 
+/** Converts a hex color string to a tuple of RGB values */
+export function hexToRgb(hex: string): [red: number, green: number, blue: number] {
+  const bigint = parseInt(hex.slice(1), 16);
+  const r = (bigint >> 16) & 255;
+  const g = (bigint >> 8) & 255;
+  const b = (bigint & 255);
+  return [clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255)];
+};
+
+/** Converts RGB values to a hex color string */
+export function rgbToHex(red: number, green: number, blue: number): string {
+  const toHexVal = (n: number) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, "0").toUpperCase();
+  return `#${toHexVal(red)}${toHexVal(green)}${toHexVal(blue)}`;
+};
+
+/**
+ * Lightens a CSS color value (in hex, RGB or RGBA format) by a given percentage.  
+ * Will not exceed the maximum range (00-FF or 0-255).
+ * @returns Returns the new color value in the same format as the input
+ * @throws Throws if the color format is invalid or not supported
+ */
+export function lightenColor(color: string, percent: number): string {
+  return darkenColor(color, percent * -1);
+}
+
+/**
+ * Darkens a CSS color value (in hex, RGB or RGBA format) by a given percentage.  
+ * Will not exceed the maximum range (00-FF or 0-255).
+ * @returns Returns the new color value in the same format as the input
+ * @throws Throws if the color format is invalid or not supported
+ */
+export function darkenColor(color: string, percent: number): string {
+  const darkenRgb = (r: number, g: number, b: number, percent: number): [number, number, number] => {
+    r = Math.max(0, Math.min(255, r - (r * percent / 100)));
+    g = Math.max(0, Math.min(255, g - (g * percent / 100)));
+    b = Math.max(0, Math.min(255, b - (b * percent / 100)));
+    return [r, g, b];
+  };
+
+  let r: number, g: number, b: number, a: number | undefined;
+
+  if(color.startsWith("#"))
+    [r, g, b] = hexToRgb(color);
+  else if(color.startsWith("rgb")) {
+    const rgbValues = color.match(/\d+(\.\d+)?/g)?.map(Number);
+    if (rgbValues)
+      [r, g, b, a] = rgbValues;
+    else
+      throw new Error("Invalid RGB/RGBA color format");
+  }
+  else
+    throw new Error("Unsupported color format");
+
+  [r, g, b] = darkenRgb(r, g, b, percent);
+
+  if (color.startsWith("#"))
+    return rgbToHex(r, g, b);
+  else if (color.startsWith("rgba"))
+    return `rgba(${r}, ${g}, ${b}, ${a})`;
+  else if (color.startsWith("rgb"))
+    return `rgb(${r}, ${g}, ${b})`;
+  else
+    throw new Error("Unsupported color format");
+}
+
 //#region resources
 
 /**