Better Youtube

Prettier youtube with red sub button and less rounded edges

  1. // ==UserScript==
  2. // @name Better Youtube
  3. // @version 9.2
  4. // @author tiramifue
  5. // @description Prettier youtube with red sub button and less rounded edges
  6. // @match https://*.youtube.com/*
  7. // @exclude *://music.youtube.com/*
  8. // @exclude *://*.music.youtube.com/*
  9. // @exclude *://studio.youtube.com/*
  10. // @run-at document-end
  11. // @grant GM_addStyle
  12. // @grant GM_registerMenuCommand
  13. // @grant GM_unregisterMenuCommand
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @namespace https://greasyfork.org/users/570213
  17. // @license Apache-2.0
  18. // ==/UserScript==
  19.  
  20. // updated 2025-06-20
  21.  
  22. (function(){
  23. "use strict";
  24.  
  25. const isBlackModeScript = false;
  26.  
  27. // ---------- Persistent Settings ----------
  28. const features = [
  29. {
  30. key: "cleanButtonMode",
  31. name: "Clean Button Mode",
  32. defaultValue: false,
  33. onToggle: updateCustomStyleContent
  34. },
  35. {
  36. key: "animatedPopups",
  37. name: "Animated Popups",
  38. defaultValue: true,
  39. onToggle: updateCustomStyleContent
  40. },
  41. {
  42. key: "blackMode",
  43. name: "Black Mode",
  44. defaultValue: isBlackModeScript,
  45. onToggle: () => {
  46. updateCinematicsBackground();
  47. updateCustomStyleContent();
  48. }
  49. },
  50. {
  51. key: "hideShorts",
  52. name: "Hide Shorts",
  53. defaultValue: false,
  54. onToggle: updateCustomStyleContent
  55. }
  56. ]
  57.  
  58. class ToggleSystem {
  59. static getState(key) {
  60. const feature = features.find(f => f.key === key);
  61. const defaultValue = feature.defaultValue;
  62. return GM_getValue(key, defaultValue);
  63. }
  64.  
  65. static setState(key, state) {
  66. GM_setValue(key, state);
  67. }
  68.  
  69. static registerFeature(feature) {
  70. const currentState = this.getState(feature.key);
  71. const stateText = currentState ? "☑️" : "⬜";
  72. const menuText = `${stateText} ${feature.name}`;
  73.  
  74. const menuCommandId = GM_registerMenuCommand(menuText, () => {
  75. this.toggleFeature(feature);
  76. });
  77.  
  78. feature.menuCommandId = menuCommandId;
  79. }
  80.  
  81. static unregisterFeature(feature) {
  82. GM_unregisterMenuCommand(feature.menuCommandId);
  83. }
  84.  
  85. static toggleFeature(feature) {
  86. const currentState = this.getState(feature.key);
  87. const newState = !currentState;
  88. this.setState(feature.key, newState);
  89.  
  90. this.unregisterAll(features);
  91. this.registerAll(features);
  92.  
  93. feature.onToggle();
  94. }
  95.  
  96. static registerAll(features) {
  97. features.forEach(feature => {
  98. this.registerFeature(feature);
  99. })
  100. }
  101.  
  102. static unregisterAll(features) {
  103. features.forEach(feature => {
  104. this.unregisterFeature(feature);
  105. })
  106. }
  107. }
  108.  
  109. // ---------- Iframe Handling ----------
  110. if (window.top !== window.self) {
  111. switch (location.pathname) {
  112. case "/live_chat":
  113. case "/live_chat_replay":
  114. GM_addStyle(getCustomStyleContent("live_chat"));
  115. break;
  116. }
  117. return;
  118. }
  119.  
  120. ToggleSystem.registerAll(features);
  121.  
  122.  
  123. // ---------- Infocards popup ----------
  124.  
  125. function addInfocardsPopupFeature() {
  126. let dropdown;
  127. let originalParent;
  128. let movedSection;
  129.  
  130. new MutationObserver((_, obs) => {
  131. const btn = document.querySelector('button.ytp-cards-button');
  132. if (!btn) return;
  133. btn.addEventListener('click', (e) => onInfoClick(e, btn), true);
  134. obs.disconnect();
  135. }).observe(document.body, { childList: true, subtree: true });
  136.  
  137. function onInfoClick(e, btn) {
  138. e.preventDefault();
  139. e.stopImmediatePropagation();
  140. openInfoDropdown(btn);
  141. }
  142.  
  143. function openInfoDropdown(anchorBtn) {
  144. const wrapper = document.querySelector('ytd-app > ytd-popup-container');
  145. if (!wrapper) {
  146. console.warn('Could not find <ytd-popup-container>');
  147. return;
  148. }
  149.  
  150. const cards = document.querySelector('ytd-video-description-infocards-section-renderer > #infocards-section');
  151. if (cards) {
  152. originalParent = cards.parentElement;
  153. movedSection = cards;
  154.  
  155. dropdown = document.createElement('tp-yt-iron-dropdown');
  156. dropdown.id = 'gm-info-dropdown';
  157. dropdown.className = 'style-scope ytd-popup-container';
  158.  
  159. movedSection.removeAttribute('id');
  160. movedSection.setAttribute('slot', 'dropdown-content');
  161.  
  162. Object.assign(movedSection.style, {
  163. display: 'block',
  164. visibility: 'visible',
  165. opacity: '1',
  166. width: 'auto',
  167. maxWidth: '600px',
  168. overflow: 'visible',
  169. maxHeight: 'none',
  170. height: 'auto',
  171. padding: '12px',
  172. boxShadow: '0 2px 10px rgba(0,0,0,0.4)',
  173. borderRadius: '8px',
  174. zIndex: '10000',
  175. boxSizing: 'border-box'
  176. });
  177.  
  178. wrapper.appendChild(dropdown);
  179. dropdown.querySelector("#contentWrapper").appendChild(movedSection);
  180. }
  181.  
  182. dropdown.opened = true;
  183.  
  184. setTimeout(() => {
  185. const buttonRect = anchorBtn.getBoundingClientRect();
  186. const popup = dropdown;
  187.  
  188. const popupWidth = movedSection.offsetWidth;
  189. popup.style.position = 'fixed';
  190. popup.style.left = `${buttonRect.right - popupWidth}px`;
  191. popup.style.top = `${buttonRect.bottom + 6}px`;
  192. popup.style.transform = 'none';
  193.  
  194. popup.style.maxHeight = 'none';
  195. popup.style.height = 'auto';
  196. }, 0);
  197. }
  198. }
  199.  
  200. addInfocardsPopupFeature();
  201.  
  202.  
  203. // ---------- Black Mode cinematics ----------
  204. const fillRectOriginal = CanvasRenderingContext2D.prototype.fillRect;
  205.  
  206. function updateCinematicsBackground() {
  207. const defaultCinematicsBackground = "#0f0f0f";
  208. const blackModeCinematicsBackground = "#000";
  209.  
  210. if (ToggleSystem.getState("blackMode")) {
  211. CanvasRenderingContext2D.prototype.fillRect = function(x, y, w, h) {
  212. if (typeof this.fillStyle === "string" && this.fillStyle === defaultCinematicsBackground) {
  213. this.fillStyle = blackModeCinematicsBackground;
  214. }
  215. return fillRectOriginal.call(this, x, y, w, h);
  216. }
  217. } else {
  218. CanvasRenderingContext2D.prototype.fillRect = fillRectOriginal;
  219. }
  220. }
  221.  
  222. updateCinematicsBackground();
  223.  
  224.  
  225. // ---------- Theater cinematics ----------
  226. let isSetup = false;
  227. let isFullscreen = false;
  228.  
  229. // Wait for DOM to be ready
  230. if (document.readyState === 'loading') {
  231. document.addEventListener('DOMContentLoaded', init);
  232. } else {
  233. init();
  234. }
  235.  
  236. function init() {
  237. waitForElements();
  238. document.addEventListener("fullscreenchange", onFullscreenChange);
  239. }
  240.  
  241. function waitForElements() {
  242. if (isSetup) return;
  243.  
  244. const observer = new MutationObserver(function() {
  245. if (isSetup) return;
  246.  
  247. const cinematics = document.querySelector("#cinematics-container");
  248. const defaultPlayer = document.querySelector("#primary-inner > #player");
  249. const theaterPlayer = document.querySelector("#full-bleed-container");
  250.  
  251. if (cinematics && defaultPlayer && theaterPlayer) {
  252. isSetup = true;
  253. observer.disconnect();
  254. setupTheaterModeWatcher(cinematics, defaultPlayer, theaterPlayer);
  255. }
  256. });
  257.  
  258. observer.observe(document.body, {
  259. childList: true,
  260. subtree: true
  261. });
  262.  
  263. // Check if elements already exist
  264. const cinematics = document.querySelector("#cinematics-container");
  265. const defaultPlayer = document.querySelector("#primary-inner > #player");
  266. const theaterPlayer = document.querySelector("#full-bleed-container");
  267.  
  268. if (cinematics && defaultPlayer && theaterPlayer && !isSetup) {
  269. isSetup = true;
  270. observer.disconnect();
  271. setupTheaterModeWatcher(cinematics, defaultPlayer, theaterPlayer);
  272. }
  273. }
  274.  
  275. function setupTheaterModeWatcher(cinematics, defaultPlayer, theaterPlayer) {
  276. fixMastheadOpacity();
  277.  
  278. const watchFlexy = document.querySelector('ytd-watch-flexy');
  279. if (!watchFlexy) return;
  280.  
  281. const theaterObserver = new MutationObserver(function() {
  282. const isTheaterMode = watchFlexy.hasAttribute('theater');
  283.  
  284. if (isTheaterMode) {
  285. theaterPlayer.prepend(cinematics);
  286. } else {
  287. defaultPlayer.prepend(cinematics);
  288. }
  289. });
  290.  
  291. theaterObserver.observe(watchFlexy, {
  292. attributes: true,
  293. attributeFilter: ['theater']
  294. });
  295.  
  296. if (watchFlexy.hasAttribute('theater')) {
  297. theaterPlayer.prepend(cinematics);
  298. }
  299. }
  300.  
  301. function fixMastheadOpacity() {
  302. const mastheadBg = document.querySelector('#background.style-scope.ytd-masthead');
  303. if (!mastheadBg) return;
  304.  
  305. const observer = new MutationObserver(function(mutations) {
  306. const isTheaterMode = Boolean(document.querySelector("ytd-watch-flexy[theater]"));
  307. if (isTheaterMode && !isFullscreen) {
  308. let opacity = window.scrollY * 0.01;
  309. if (opacity > 1) opacity = 1;
  310. mastheadBg.style.setProperty('opacity', opacity);
  311. }
  312. });
  313.  
  314. observer.observe(mastheadBg, {
  315. attributes: true,
  316. attributeFilter: ['style']
  317. });
  318.  
  319. // Set initial state
  320. const isTheaterMode = document.querySelector("ytd-watch-flexy[theater]");
  321. if (isTheaterMode) {
  322. mastheadBg.style.setProperty('opacity', '0');
  323. }
  324. }
  325.  
  326. function onFullscreenChange() {
  327. isFullscreen = Boolean(document.fullscreenElement);
  328. if (!isFullscreen) {
  329. const mastheadBg = document.querySelector('#background.style-scope.ytd-masthead');
  330. if (!mastheadBg) return;
  331. mastheadBg.style.setProperty('opacity', '0');
  332. }
  333. }
  334.  
  335.  
  336. // ---------- Styles ----------
  337. const customStyle = GM_addStyle(getCustomStyleContent());
  338.  
  339. function updateCustomStyleContent() {
  340. customStyle.textContent = getCustomStyleContent();
  341. }
  342.  
  343. function getCustomStyleContent(target = "main") {
  344. const bm = ToggleSystem.getState("blackMode");
  345. const rgbBg = bm ? "0 0 0" : "15 15 15";
  346. const scrollbarRgbColor = bm ? "60 60 60" : "78 78 78";
  347. const bgVariables = bm ? `
  348. --yt-spec-brand-background-solid: #000;
  349. --yt-spec-brand-background-primary: #000;
  350. --yt-spec-brand-background-secondary: #000;
  351. --yt-spec-general-background-a: #000;
  352. --yt-spec-base-background: #000;
  353. ` : "";
  354.  
  355. switch (target) {
  356.  
  357. case "live_chat":
  358. return `
  359. html:not(.style-scope)[dark],:not(.style-scope)[dark]{
  360. --custom-bg-98: rgb(${rgbBg} / 98%);
  361. --custom-bg-80: rgb(${rgbBg} / 80%);
  362.  
  363. ${bgVariables}
  364.  
  365. --yt-spec-10-percent-layer: rgb(255 255 255 / 10%);
  366. --yt-spec-badge-chip-background: rgb(255 255 255 / 7%);
  367. --yt-spec-additive-background: rgb(255 255 255 / 7%);
  368. --yt-spec-menu-background: var(--custom-bg-98);
  369. --yt-live-chat-banner-gradient-scrim: linear-gradient(rgb(${rgbBg} / 95%), transparent);
  370. --yt-live-chat-toast-background-color: rgb(${rgbBg});
  371. scrollbar-color: rgb(${scrollbarRgbColor}) transparent;
  372. }
  373. yt-live-chat-toast-renderer[is-showing-message] {
  374. border-top: 1px solid rgb(255 255 255 / 10%);
  375. }
  376. yt-live-chat-banner-renderer {
  377. backdrop-filter: blur(48px);
  378. border: 1px solid rgb(255 255 255 / 10%);
  379. box-shadow: 0px 0px 30px 6px rgba(0, 0, 0, 0.7);
  380. background: var(--custom-bg-98);
  381. --yt-live-chat-primary-text-color: var(--yt-spec-text-primary);
  382. }
  383. tp-yt-iron-dropdown.style-scope.yt-live-chat-app {
  384. backdrop-filter: blur(48px);
  385. border: 1px solid rgb(255 255 255 / 10%);
  386. border-radius: 12px !important;
  387. box-shadow: 0px 0px 30px 6px rgba(0, 0, 0, 0.7);
  388. background: var(--custom-bg-80) !important;
  389. }
  390. ytd-menu-popup-renderer {
  391. background: transparent;
  392. backdrop-filter: none;
  393. }
  394. #card.yt-live-chat-viewer-engagement-message-renderer {
  395. background: transparent;
  396. border: 1px solid rgb(255 255 255 / 10%);
  397. }
  398. .yt-spec-button-shape-next--mono-inverse.yt-spec-button-shape-next--text {
  399. color: #f1f1f1;
  400. }
  401. `;
  402.  
  403. case "main":
  404. return `
  405. html:not(.style-scope)[dark],:not(.style-scope)[dark]{
  406. --custom-bg-98: rgb(${rgbBg} / 98%);
  407. --custom-bg-80: rgb(${rgbBg} / 80%);
  408. --custom-bg-50: rgb(${rgbBg} / 50%);
  409. --custom-base-bg: rgb(${rgbBg});
  410.  
  411. ${bgVariables}
  412.  
  413. --yt-spec-10-percent-layer: rgb(255 255 255 / 10%);
  414. --yt-spec-badge-chip-background: rgb(255 255 255 / 7%);
  415. --yt-spec-additive-background: rgb(255 255 255 / 7%);
  416. --yt-spec-menu-background: var(--custom-bg-98);
  417. scrollbar-color: rgb(${scrollbarRgbColor}) transparent;
  418. --yt-frosted-glass-desktop: var(--custom-bg-80);
  419. }
  420.  
  421. ${bm ? `
  422. html[dark] {
  423. background: #000 !important;
  424. }
  425. ` : ""}
  426.  
  427. .YtSearchboxComponentSuggestionsContainer, .ytSearchboxComponentSuggestionsContainer, #ytp-id-18, .ytp-popup, tp-yt-iron-dropdown.style-scope.ytd-popup-container, tp-yt-paper-dialog[modern], ytd-voice-search-dialog-renderer[dialog] {
  428. backdrop-filter: blur(48px);
  429. border: 1px solid rgb(255 255 255 / 10%);
  430. border-radius: 12px !important;
  431. box-shadow: 0px 0px 30px 6px rgba(0, 0, 0, 0.7);
  432. background: var(--custom-bg-80) !important;
  433. }
  434. #background.ytd-masthead {
  435. backdrop-filter: blur(48px);
  436. background: var(--custom-bg-80);
  437. }
  438. ytd-menu-popup-renderer, ytd-multi-page-menu-renderer, ytd-simple-menu-header-renderer, .yt-contextual-sheet-layout-wiz, .yt-sheet-view-model-wiz--contextual, tp-yt-paper-dialog {
  439. background: transparent;
  440. backdrop-filter: none;
  441. }
  442. ytd-thumbnail a.ytd-thumbnail, ytd-thumbnail:before {
  443. border-radius: 1px;
  444. }
  445. #thumbnail {
  446. border-radius: 1px;
  447. }
  448. #subscribe-button-shape button {
  449. color: var(--yt-spec-text-primary);
  450. background: #cc0000;
  451. border-radius: 2px;
  452. text-transform: uppercase;
  453. }
  454. #subscribe-button-shape button:hover {
  455. background: #880000;
  456. }
  457. #sponsor-button button {
  458. background: var(--yt-spec-badge-chip-background);
  459. color: var(--yt-spec-text-primary);
  460. }
  461. #sponsor-button button:hover {
  462. background: ${bm ? "#333333" : "#414141"};
  463. }
  464. .yt-spec-button-shape-next--size-m {
  465. border-radius: 2px;
  466. }
  467. .yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--segmented-start {
  468. border-radius: 2px 0 0 2px;
  469. }
  470. .yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--segmented-end {
  471. border-radius: 0 2px 2px 0;
  472. }
  473. yt-chip-cloud-chip-renderer[modern-chips][chip-style] {
  474. border-radius: 2px;
  475. }
  476. #container.ytd-searchbox {
  477. border-radius: 2px 0 0 2px;
  478. }
  479. #search-icon-legacy.ytd-searchbox {
  480. border-radius: 0 2px 2px 0;
  481. }
  482. .sbdd_b {
  483. border-radius: 8px;
  484. }
  485. ytd-watch-metadata[modern-metapanel] #description.ytd-watch-metadata {
  486. border-radius: 2px;
  487. }
  488. ytd-guide-entry-renderer[guide-refresh] {
  489. border-radius: 2px;
  490. }
  491. .yt-spec-touch-feedback-shape {
  492. border-radius: 2px;
  493. }
  494. ytd-rich-metadata-renderer[rounded] {
  495. border-radius: 2px;
  496. }
  497. .shortsLockupViewModelHostThumbnailContainerRounded {
  498. border-radius: 2px;
  499. }
  500. #tooltip {
  501. display: none;
  502. }
  503. ytd-engagement-panel-section-list-renderer[dialog] #content.ytd-engagement-panel-section-list-renderer {
  504. background: transparent;
  505. }
  506. #header.ytd-engagement-panel-title-header-renderer {
  507. background: var(--custom-bg-80);
  508. border-bottom: 1px solid rgb(255 255 255 / 5%);
  509. }
  510. ytd-engagement-panel-section-list-renderer[dialog] #header.ytd-engagement-panel-section-list-renderer {
  511. margin: 0;
  512. }
  513. ytd-engagement-panel-section-list-renderer[dialog] ytd-section-list-renderer.ytd-engagement-panel-section-list-renderer {
  514. background: var(--custom-bg-50);
  515. }
  516. ytd-engagement-panel-section-list-renderer[dialog][target-id=engagement-panel-comments-section] {
  517. width: 40vmax;
  518. }
  519. #menu.ytd-engagement-panel-title-header-renderer:not(:empty) {
  520. flex: 1;
  521. }
  522. #title-container.ytd-engagement-panel-title-header-renderer {
  523. max-width: 150px;
  524. }
  525. tp-yt-iron-overlay-backdrop.opened {
  526. opacity: 0.6;
  527. }
  528. ytd-dismissal-follow-up-renderer[darker-dark-theme][dialog][dialog][dialog] {
  529. background-color: transparent;
  530. }
  531. ytd-guide-entry-renderer[guide-refresh] #endpoint.yt-simple-endpoint.ytd-guide-entry-renderer:hover, ytd-guide-entry-renderer[guide-refresh] #endpoint.yt-simple-endpoint.ytd-guide-entry-renderer:focus {
  532. border-radius: 2px;
  533. }
  534. ytd-guide-entry-renderer[guide-refresh] #endpoint.yt-simple-endpoint.ytd-guide-entry-renderer:active {
  535. border-radius: 2px;
  536. }
  537. ytd-guide-entry-renderer[guide-refresh] yt-interaction.ytd-guide-entry-renderer {
  538. border-radius: 2px;
  539. }
  540. .yt-spec-button-shape-next--size-s {
  541. border-radius: 2px;
  542. }
  543. button.yt-spec-button-shape-next.yt-spec-button-shape-next--text.yt-spec-button-shape-next--call-to-action.yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-leading.yt-spec-button-shape-next--align-by-text:hover {
  544. background-color: rgb(38 56 80 / 55%);
  545. }
  546. .yt-spec-button-shape-next--size-l {
  547. border-radius: 2px;
  548. }
  549. .yt-spec-button-shape-next--size-l.yt-spec-button-shape-next--icon-button {
  550. width: 44px;
  551. height: 44px;
  552. }
  553. #content.ytd-engagement-panel-section-list-renderer, ytd-item-section-renderer[static-comments-header] #header.ytd-item-section-renderer, .watch-while-engagement-panel.ytd-reel-video-renderer {
  554. background: var(--custom-base-bg);
  555. }
  556. ytd-reel-video-renderer[is-watch-while-mode] .watch-while-engagement-panel.ytd-reel-video-renderer {
  557. border-radius: 12px;
  558. }
  559. ytd-item-section-renderer[static-comments-header] #header.ytd-item-section-renderer {
  560. border-top: 1px solid rgb(255 255 255 / 10%);
  561. }
  562. yt-chip-cloud-chip-renderer, ytd-guide-entry-renderer, #endpoint.yt-simple-endpoint.ytd-guide-entry-renderer:active, #endpoint.yt-simple-endpoint.ytd-guide-entry-renderer:hover, #endpoint.yt-simple-endpoint.ytd-guide-entry-renderer:focus, yt-interaction.ytd-guide-entry-renderer, #description.ytd-watch-metadata, .ytChipShapeChip {
  563. border-radius: 2px;
  564. }
  565. tp-yt-paper-item.ytd-guide-entry-renderer {
  566. --paper-item-focused-before-border-radius: 2px;
  567. }
  568. #sponsor-button > ytd-button-renderer {
  569. background: rgb(${bm ? "18 18 18" : "35 35 35"});
  570. border-radius: 2px;
  571. }
  572. #sponsor-button > ytd-button-renderer > yt-button-shape > button {
  573. border: none;
  574. }
  575. #navigation-button-down > ytd-button-renderer > yt-button-shape > button > yt-touch-feedback-shape > div {
  576. border-radius: 28px;
  577. }
  578. #voice-search-button.ytd-masthead, #microphone.ytd-voice-search-dialog-renderer[state=try-again] #microphone-circle.ytd-voice-search-dialog-renderer, #microphone-levels.ytd-voice-search-dialog-renderer {
  579. background-color: transparent;
  580. }
  581. yt-interaction.rounded-large .fill.yt-interaction, yt-interaction.rounded-large .stroke.yt-interaction {
  582. border-radius: 2px;
  583. }
  584. #target[title="Email"] > yt-icon > span > div {
  585. filter: invert(1);
  586. }
  587. ytd-engagement-panel-section-list-renderer[modern-panels]:not([live-chat-engagement-panel]) {
  588. border-radius: 2px;
  589. }
  590. ytd-reel-video-renderer:not([enable-player-metadata-container]) .watch-while-engagement-panel.ytd-reel-video-renderer {
  591. background: rgb(15 15 15);
  592. }
  593. yt-interaction.circular .fill.yt-interaction, yt-interaction.circular .stroke.yt-interaction {
  594. border-radius: 2px;
  595. }
  596. yt-icon-button.ytd-masthead:hover, ytd-topbar-menu-button-renderer.ytd-masthead:hover, ytd-notification-topbar-button-renderer.ytd-masthead:hover, .ytSearchboxComponentClearButton:hover {
  597. border-radius: 2px;
  598. }
  599. #overlays > yt-thumbnail-overlay-badge-view-model {
  600. display: none;
  601. }
  602. ytd-watch-flexy[rounded-player] #ytd-player.ytd-watch-flexy {
  603. border-radius: 2px;
  604. }
  605. .YtSearchboxComponentInputBox, .ytSearchboxComponentInputBox {
  606. border-radius: 2px 0 0 2px;
  607. }
  608. .YtSearchboxComponentSearchButton, .ytSearchboxComponentSearchButton {
  609. border-radius: 0 2px 2px 0;
  610. }
  611. .ytSearchboxComponentClearButton {
  612. margin-right: 6px;
  613. }
  614. #chip-container.yt-chip-cloud-chip-renderer {
  615. border-radius: 2px;
  616. }
  617. .ytVideoMetadataCarouselViewModelHost {
  618. background: var(--yt-spec-badge-chip-background);
  619. border-radius: 2px;
  620. }
  621. #cinematics-container > #cinematics > div > div {
  622. transform: scale(1.5, 2) !important;
  623. }
  624. ytd-live-chat-frame[round-background] #show-hide-button.ytd-live-chat-frame>ytd-toggle-button-renderer.ytd-live-chat-frame, ytd-live-chat-frame[round-background] #show-hide-button.ytd-live-chat-frame>ytd-button-renderer.ytd-live-chat-frame {
  625. border-radius: 2px;
  626. }
  627. #movie_player .annotation.iv-branding {
  628. display: none;
  629. }
  630. ytd-mini-guide-entry-renderer {
  631. border-radius: 2px;
  632. }
  633. tp-yt-paper-dialog > ytd-voice-search-dialog-renderer.ytd-popup-container {
  634. margin-bottom: 0 !important;
  635. }
  636. tp-yt-paper-dialog {
  637. border-radius: 12px;
  638. }
  639. ytd-channel-renderer.ytd-item-section-renderer {
  640. display: none;
  641. }
  642.  
  643.  
  644. ${ToggleSystem.getState("animatedPopups") ? `
  645. /* 1) iPhone-style popup animation */
  646. @keyframes popupAnimation {
  647. 0% { opacity: 0; transform: scale(0.9); }
  648. 70% { opacity: 1; transform: scale(1.02); }
  649. 100% { transform: scale(1); }
  650. }
  651.  
  652. @keyframes popupAnimationUp {
  653. 0% { opacity: 0; transform: scale(0.9) translateY(25px); }
  654. 60% { opacity: 1; transform: scale(1.02) translateY(-5px); }
  655. 100% { transform: scale(1) translateY(0); }
  656. }
  657.  
  658. tp-yt-iron-dropdown.ytd-popup-container {
  659. transform-origin: top center !important;
  660. animation: popupAnimation 300ms cubic-bezier(0.25,0.1,0.25,1) both !important;
  661. overflow: visible !important; /* never scroll the wrapper */
  662. }
  663.  
  664. /* 2) Remove YouTube’s inline size caps so menus fit exactly */
  665. tp-yt-iron-dropdown.ytd-popup-container
  666. yt-sheet-view-model,
  667. tp-yt-iron-dropdown.ytd-popup-container
  668. ytd-menu-popup-renderer,
  669. tp-yt-iron-dropdown.ytd-popup-container
  670. ytd-multi-page-menu-renderer {
  671. max-width: none !important;
  672. max-height: none !important;
  673. overflow: visible !important;
  674. }
  675.  
  676. /* 3) If content actually overflows, allow only vertical scrolling */
  677. tp-yt-iron-dropdown.ytd-popup-container
  678. ytd-menu-popup-renderer,
  679. tp-yt-iron-dropdown.ytd-popup-container
  680. ytd-multi-page-menu-renderer {
  681. overflow-x: hidden !important;
  682. overflow-y: auto !important;
  683. /* optional: cap height so huge menus don’t fill the whole screen */
  684. /* max-height: 80vh !important; */
  685. }
  686.  
  687. /* popup animation for search suggestions */
  688. div.ytSearchboxComponentSuggestionsContainer[role="listbox"] {
  689. transform-origin: top center !important;
  690. animation: popupAnimation 300ms cubic-bezier(0.25, 0.1, 0.25, 1) both !important;
  691. }
  692.  
  693. /* — apply animation to the gear/settings menu */
  694. div.ytp-popup.ytp-settings-menu {
  695. transform-origin: bottom center !important;
  696. animation: popupAnimation 300ms cubic-bezier(0.25,0.1,0.25,1) both !important;
  697. overflow-x: hidden !important;
  698. overflow-y: auto !important;
  699. }
  700. ` : ""}
  701.  
  702.  
  703. ${ToggleSystem.getState("cleanButtonMode") ? `
  704. .yt-spec-button-shape-next--mono.yt-spec-button-shape-next--tonal, .ytChipShapeInactive, .yt-spec-button-shape-next--overlay.yt-spec-button-shape-next--tonal {
  705. background: none;
  706. }
  707. ` : ""}
  708.  
  709.  
  710. ${ToggleSystem.getState("hideShorts") ? `
  711. ytd-rich-shelf-renderer[is-shorts], ytd-reel-shelf-renderer {
  712. display: none;
  713. }
  714. ` : ""}
  715.  
  716.  
  717. `;
  718. }
  719. }
  720. })();