commit e449edf887ced9ec1e7dda2bceb8efffc1b55819
Author: CatAClock <CatAClock@proton.me>
Date:   Tue Apr 15 11:59:49 2025 -0700

    codeberg copy

diff --git a/ContentScripts/StudioModify.js b/ContentScripts/StudioModify.js
new file mode 100644
index 0000000..222a8b9
--- /dev/null
+++ b/ContentScripts/StudioModify.js
@@ -0,0 +1,406 @@
+let TheHref = document.location.href;
+let TheTimeout = null;
+let SettingsStay = false;
+
+const StringArray = ["What was the video about? Can you give an in-depth explaination of what you did?", 
+					"START - What are some things that you can do to improve this video? What can you start doing? List the sections you want improved WITH TIMESTAMPS.", 
+					"STOP - What are things that shouldn't be done or should not have began in the first place?", 
+					"CONTINUE - What can you keep doing to make the same effect happen? These are things that don't need to be changed.",
+					"You did it! No Further typing is needed."];
+
+// Observe changes to the Href and do things accordingly.
+const observer = new MutationObserver(mutations => {
+	if (TheHref !== document.location.href) {
+		TheHref = document.location.href;
+		clearTimeout(TheTimeout);
+		TheTimeout = setTimeout(() => VideoOrChannel(), 1500);
+	}
+});
+observer.observe(document.body, { childList: true, subtree: true });
+
+// Do some things on load.
+window.onload = function() {
+	setTimeout(() => {
+		VideoOrChannel();
+	}, 2000);
+	document.getElementsByTagName("ytcp-send-feedback-button")[0].remove();
+	if (document.location.href.includes("channel")) {
+		document.getElementsByTagName("ytcp-ve")[9].parentElement.remove();
+		SettingsStay = true;
+	}
+};
+
+// Simple function to not have stuff die.
+function VideoOrChannel(){
+	if (TheHref.includes("channel") && SettingsStay == false) {
+		document.getElementsByTagName("ytcp-ve")[9].parentElement.remove();
+		SettingsStay = true;
+	}
+	
+	if (document.location.href.includes("channel")) {
+		ModifyChannelElements();
+	}
+	else {
+		ModifyVideoElements();
+	}
+}
+
+// Remove and add elements in the video area.
+function ModifyVideoElements() {
+	SettingsStay = false;
+	if (document.location.href.includes("analytics")) {
+		if (document.location.href.includes("tab-overview")) {
+			console.log("Do nothing here");
+		}
+		if (document.location.href.includes("tab-reach_viewers")) {
+			console.log("Do nothing here");
+		}
+		if (document.location.href.includes("tab-interest_viewers")) {
+			console.log("Do nothing here");
+		}
+		if (document.location.href.includes("tab-build_audience")) {
+			console.log("Do nothing here");
+		}
+		console.log("You are in analytics!");
+		return;
+	}
+	
+	if (document.location.href.includes("editor")) {
+		console.log("You are in the editor!");
+		return;
+	}
+	
+	if (document.location.href.includes("comments")) {
+		console.log("You are in comments!");
+		return;
+	}
+	
+	if (document.location.href.includes("translations")) {
+		console.log("You are in the translations!");
+		return;
+	}
+	
+	if (document.location.href.includes("copyright")) {
+		console.log("You are in copyright!");
+		return;
+	}
+	
+	// Livestream is seperated? Why?
+	if (document.location.href.includes("livestreaming")) {
+		console.log("You are streemin!");
+		return;
+	}
+	console.log("You are in the overview!");
+}
+
+// Remove and add elements in the channel area.
+function ModifyChannelElements() {
+	if (document.location.href.includes("videos") || document.location.href.includes("content")) {
+		if (document.getElementsByTagName("ytcp-primary-action-bar")[0].classList.contains("PersistentElements") == false) {
+			document.getElementsByTagName("ytcp-primary-action-bar")[0].classList.add("PersistentElements");
+			document.getElementsByTagName("tp-yt-paper-tab")[7].remove();
+		}
+		console.log("Content elements have been altered!");
+		return;
+	}
+	
+	if (document.location.href.includes("analytics")) {
+		if (document.location.href.includes("tab-overview")) {
+			let Items = document.getElementsByTagName("yta-personalized-overview-bottom-card");
+			Items[0].remove();
+			if (document.getElementsByTagName("yta-section")[0].classList.contains("PersistentElements") == false) {
+				document.getElementsByTagName("yta-section")[0].classList.add("PersistentElements");
+				Items = document.getElementsByTagName("yta-entity-snapshot-carousel");
+				Items[0].remove();
+			}
+			
+			// Create Topic Buttons.
+			browser.storage.local.get("TopicList").then(
+				(List) => {
+					let Card = document.createElement("tp-yt-paper-card");
+					Card.classList.add("staple-card");
+					Card.classList.add("style-scope");
+					Card.classList.add("yta-card-container");
+					Card.style.marginTop = "24px";
+					let Text = document.createElement("div");
+					Text.classList.add("style-scope");
+					Text.style.margin = "24px";
+					Text.style.fontSize = "18px";
+					Text.style.fontWeight = "bold";
+					Text.innerHTML = "Interesting topics from the week!";
+					Card.appendChild(Text);
+					document.getElementsByTagName("yta-key-metric-card")[0].appendChild(Card);
+					// Yes, if there is nothing in storage, this errors.
+					// This is my fix: ignore it. Also fuck off.
+					for (let i of Object.values(List)[0]) {
+						// Style elements
+						let Button = document.createElement("button");
+						Button.style.width = "45%";
+						Button.style.height = "50px";
+						Button.style.border = "25%";
+						Button.style.margin = "12px";
+						Button.style.background = "rgba(255, 255, 255, 0.1)";
+						Button.style.color = "white";
+						Button.style.border = "0px solid";
+						Button.style.borderRadius = "20px";
+						Button.style.fontSize = "20px";
+						Button.style.fontWeight = "bold";
+						// Events to behave like a button
+						Button.addEventListener("mouseenter", (event) => {
+							Button.style.background = "rgba(255, 255, 255, 0.2)";
+						});
+						Button.addEventListener("mouseleave", (event) => {
+							Button.style.background = "rgba(255, 255, 255, 0.1)";
+						});
+						Button.addEventListener("mousedown", (event) => {
+							Button.style.background = "rgba(255, 255, 255, 0.15)";
+						});
+						Button.addEventListener("mouseup", (event) => {
+							Button.style.background = "rgba(255, 255, 255, 0.2)";
+						});
+						Button.innerHTML = i;
+						i = i.replaceAll(" ", "+");
+						Button.addEventListener("click", (event) => {
+							document.location.href = "https://www.google.com/search?q=" + i + "&udm=7&tbs=qdr:w";
+						});
+						Card.appendChild(Button);
+					}
+				}
+			);
+		}
+		if (document.location.href.includes("tab-content")) {
+			console.log("Do nothing here");
+		}
+		if (document.location.href.includes("tab-build_audience")) {
+			console.log("Do nothing here");
+		}
+		if (document.location.href.includes("tab-research")) {
+			console.log("Do nothing here");
+		}
+		console.log("Analytic elements have been altered!");
+		return;
+	}
+	
+	if (document.location.href.includes("comments")) {
+		console.log("You are in comments!");
+		return;
+	}
+	
+	if (document.location.href.includes("translations")) {
+		console.log("You are in translations!");
+		return;
+	}
+	
+	if (document.location.href.includes("copyright")) {
+		console.log("you are in copyright!");
+		return;
+	}
+	
+	if (document.location.href.includes("monetization")) {
+		console.log("You are in monitization");
+		return;
+	}
+	
+	if (document.location.href.includes("editing")) {
+		console.log("You are in customization!");
+		return;
+	}
+	
+	// Dashboard
+	// Remove the quick actions (they are useless)
+	if (document.getElementsByTagName("ytcp-quick-actions").length > 0) {
+		document.getElementsByTagName("ytcp-quick-actions")[0].remove();
+	}
+	
+	// Adjust the cards in certain columns.
+	for (let Element of document.getElementsByTagName("ytcd-card")) {
+		// remove cards
+		if (Element.getAttribute("test-id") == "channel-dashboard-snapshot-card") {
+			Element.remove();
+		}
+	}
+	
+	// Livestream is seperated? Why?
+	if (document.location.href.includes("livestreaming")) {
+		console.log("You are streemin!");
+		return;
+	}
+	
+	// Past this point is the dashboard.
+	// Alter all of the columns to suit the needs of me.
+	let Counter = 0;
+	while (Counter <= 2) {
+		switch (Counter) {
+			case 0:
+				document.getElementsByTagName("ytcd-card-column")[Counter].setAttribute("style", "width: calc(50% - var(--card-margin));");
+			case 1:
+				document.getElementsByTagName("ytcd-card-column")[Counter].setAttribute("style", "width: calc(50% - var(--card-margin));");
+				break;
+			case 2:
+				document.getElementsByTagName("ytcd-card-column")[Counter].remove();
+				break;
+		}
+		Counter++;
+	}
+	
+	// Create objects in the Dashboard.
+	// This if statement is for elements that don't go away once deleted.
+	const Dashboard = document.getElementsByTagName("ytcd-channel-dashboard")
+	if (document.getElementsByClassName("PersistentObject").length == 0) {
+		// Create the progress bar.
+		let Progress = document.createElement("div");
+		Progress.classList.add("PersistentObject");
+		// Style elements.
+		Progress.style.height = "50px";
+		Progress.style.width = "100% - 24px";
+		Progress.style.margin = "24px";
+		Progress.style.border = "1px solid rgba(255, 255, 255, 0.1";
+		// Create the inside of the progress bar.
+		let Meter = document.createElement("div");
+		// Style elements.
+		Meter.style.background = "rgb(255, 0, 0)";
+		Meter.classList.add("liquid");
+		Meter.style.width = "0%";
+		Meter.style.height = "100%";
+		Progress.appendChild(Meter);
+		// Place the progress bar on top.
+		Dashboard[0].parentElement.insertBefore(Progress, Dashboard[0]);
+		// Create the text box.
+		let Textbox = document.createElement("textarea");
+		// Style elements.
+		Textbox.style.marginLeft = "24px";
+		Textbox.style.marginRight = "24px";
+		Textbox.style.height = "200px";
+		Textbox.style.background = "rgba(0, 0, 0, 0.2)";
+		Textbox.style.border = "1px solid rgba(255, 255, 255, 0.1";
+		Textbox.style.color = "white";
+		Textbox.placeholder = StringArray[0];
+		Textbox.style.resize = "none";
+		Dashboard[0].parentElement.insertBefore(Textbox, Dashboard[0]);
+		// Create the continue button.
+		let Button = document.createElement("button");
+		// Style elements.
+		Button.style.width = "250px";
+		Button.style.height = "40px";
+		Button.style.border = "25%";
+		Button.style.margin = "24px";
+		Button.style.marginBottom = "0";
+		Button.innerHTML = "Continue";
+		Button.style.background = "rgba(255, 255, 255, 0.1)";
+		Button.style.color = "white";
+		Button.style.border = "0px solid";
+		Button.style.borderRadius = "20px";
+		Button.style.fontSize = "18px";
+		Button.style.fontWeight = "bold";
+		// Change style like a button
+		Button.addEventListener("mouseenter", (event) => {
+			Button.style.background = "rgba(255, 255, 255, 0.2)";
+		});
+		Button.addEventListener("mouseleave", (event) => {
+			Button.style.background = "rgba(255, 255, 255, 0.1)";
+		});
+		Button.addEventListener("mousedown", (event) => {
+			Button.style.background = "rgba(255, 255, 255, 0.15)";
+		});
+		Button.addEventListener("mouseup", (event) => {
+			Button.style.background = "rgba(255, 255, 255, 0.2)";
+		});
+		Button.addEventListener("click", (event) => {
+			// Button to not only progress the bar, but to also clear the textbox!
+			const Liquid = document.getElementsByClassName("liquid")[0];
+			if (Liquid.clientWidth != Liquid.parentElement.clientWidth) {
+				// If the thing is full, don't do anything
+				if (Liquid.clientWidth - 1 == Liquid.parentElement.clientWidth) {
+					Textbox.disabled = true;
+				}
+				else {
+					let BigAssCalc = (Liquid.clientWidth + (Liquid.parentElement.clientWidth / 4)) / Liquid.parentElement.clientWidth;
+					document.cookie = "ProgressAmount=" + (BigAssCalc * 100).toString() + ";max-age=28800";
+					Liquid.style.width = (BigAssCalc * 100) + "%";
+					Textbox.value = "";
+					Textbox.placeholder = StringArray[parseInt(Liquid.style.width) / 25];
+				}
+			}
+		});
+		Dashboard[0].parentElement.insertBefore(Button, Dashboard[0]);
+		// Check for cookies.
+		if (document.cookie.split("; ").find((row) => row.startsWith("ProgressAmount="))?.split("=")[1] != undefined) {
+			const Liquid = document.getElementsByClassName("liquid")[0];
+			document.getElementsByClassName("liquid")[0].style.width = document.cookie.split("; ").find((row) => row.startsWith("ProgressAmount="))?.split("=")[1] + "%";
+			Textbox.placeholder = StringArray[parseInt(Liquid.style.width) / 25];
+			if (Liquid.clientWidth - 1 == Liquid.parentElement.clientWidth) {
+				Textbox.disabled = true;
+			}
+		}
+	}
+	
+	// Elements that go away go here.
+	// Create Channel Buttons.
+	browser.storage.local.get("ChannelList").then(
+		(List) => {
+			let Card = document.createElement("ytcd-card");
+			Card.classList.add("card");
+			Card.classList.add("style-scope");
+			Card.classList.add("ytcd-card");
+			let Text = document.createElement("div");
+			Text.classList.add("title-text");
+			Text.classList.add("style-scope");
+			Text.classList.add("ytcd-list-card");
+			Text.classList.add("card-title");
+			Text.innerHTML = "Cool channels on YouYube!";
+			Text.style.fontSize = "18px";
+			Text.style.margin = "24px 24px 0px 24px";
+			Card.appendChild(Text);
+			Dashboard[0].getElementsByTagName("ytcd-card-column")[0].appendChild(Card);
+			// Yes, if there is nothing in storage, this errors.
+			// This is my fix: ignore it. Also fuck off.
+			for (let i of Object.values(List)[0]) {
+				// Style elements
+				let Button = document.createElement("button");
+				Button.style.minWidth = "300px";
+				Button.style.height = "30px";
+				Button.style.border = "25%";
+				Button.style.margin = "12px";
+				Button.style.background = "rgba(255, 255, 255, 0.1)";
+				Button.style.color = "white";
+				Button.style.border = "0px solid";
+				Button.style.borderRadius = "20px";
+				Button.style.fontSize = "13px";
+				Button.style.fontWeight = "bold";
+				// Change style like a button.
+				Button.addEventListener("mouseenter", (event) => {
+					Button.style.background = "rgba(255, 255, 255, 0.2)";
+				});
+				Button.addEventListener("mouseleave", (event) => {
+					Button.style.background = "rgba(255, 255, 255, 0.1)";
+				});
+				Button.addEventListener("mousedown", (event) => {
+					Button.style.background = "rgba(255, 255, 255, 0.15)";
+				});
+				Button.addEventListener("mouseup", (event) => {
+					Button.style.background = "rgba(255, 255, 255, 0.2)";
+				});
+				// Different cases for what the user wants to do.
+				if (i.indexOf("http://") == 0) {
+					i = i.slice(7);
+				}
+				if (i.indexOf("https://") == 0) {
+					i = i.slice(8);
+				}
+				if (i.indexOf("@") == 0) {
+					i = "www.youtube.com/" + i;
+				}
+				if (i.indexOf("http://") != 0 && i.indexOf("https://") != 0 && i.indexOf("@") != 0 && i.indexOf("www.youtube.com")) {
+					console.warn("The extension has no idea what to do with this string. Please consider removing it.");
+					console.warn(i);
+				}
+				Button.innerHTML = i;
+				Button.addEventListener("click", (event) => {
+					document.location.href = "https://" + i;
+				});
+				Card.appendChild(Button);
+			}
+		}
+	);
+	console.log("Home elements have been altered!");
+}
diff --git a/Icons/Icon.png b/Icons/Icon.png
new file mode 100644
index 0000000..25613f0
Binary files /dev/null and b/Icons/Icon.png differ
diff --git a/Icons/Icon.svg b/Icons/Icon.svg
new file mode 100644
index 0000000..c640766
--- /dev/null
+++ b/Icons/Icon.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+
+<svg
+   sodipodi:docname="Icon.svg"
+   xml:space="preserve"
+   viewBox="0 0 36.88008 36.88008"
+   id="Layer_1"
+   version="1.1"
+   width="64"
+   height="64"
+   inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs9" /><sodipodi:namedview
+   id="namedview7"
+   pagecolor="#505050"
+   bordercolor="#eeeeee"
+   borderopacity="1"
+   inkscape:showpageshadow="0"
+   inkscape:pageopacity="0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#505050"
+   showgrid="false"
+   inkscape:zoom="8.42"
+   inkscape:cx="35.807601"
+   inkscape:cy="44.833729"
+   inkscape:window-width="1920"
+   inkscape:window-height="1011"
+   inkscape:window-x="1600"
+   inkscape:window-y="204"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="layer1" />
+
+<g
+   inkscape:groupmode="layer"
+   id="layer1"
+   inkscape:label="Icon"><path
+     style="fill:#f61c0d;stroke:#000000;stroke-width:0.56558;stroke-dasharray:none;stroke-opacity:1"
+     d="M 29.055355,5.4690511 H 7.8249675 c -4.1653666,0 -7.54205637,3.3520816 -7.54205637,7.4870919 v 10.535605 c 0,4.13501 3.37668977,7.487092 7.54205637,7.487092 H 29.055355 c 4.165367,0 7.542056,-3.352082 7.542056,-7.487092 V 12.956143 c 0,-4.1350103 -3.376689,-7.4870919 -7.542056,-7.4870919 z m -5.10064,13.2674889 -9.930143,4.701564 c -0.2646,0.125274 -0.570239,-0.06623 -0.570239,-0.357213 v -9.696999 c 0,-0.295124 0.313675,-0.486398 0.578825,-0.352991 l 9.930143,4.995435 c 0.295242,0.1485 0.290122,0.568821 -0.0086,0.710204 z"
+     id="path2"
+     inkscape:label="Logo" /><path
+     style="fill:#a53d00;fill-opacity:1;stroke:#000000;stroke-width:0.864377;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
+     d="m 32.816038,30.181436 c -6.721004,1.134313 -6.281454,1.752767 -7.290779,-2.242656 -0.743965,-4.708547 -1.416971,-3.973407 5.691576,-5.325395 l -6.391144,-1.412823 -4.828585,4.100428 -15.5875085,3.171506 0.814735,5.717867 15.8452785,-2.717766 6.242811,1.974352 z"
+     id="path722"
+     sodipodi:nodetypes="cccccccccc"
+     inkscape:label="Tool" /></g></svg>
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..fe70743
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,131 @@
+# PolyForm Noncommercial License 1.0.0
+
+<https://polyformproject.org/licenses/noncommercial/1.0.0>
+
+## Acceptance
+
+In order to get any license under these terms, you must agree
+to them as both strict obligations and conditions to all
+your licenses.
+
+## Copyright License
+
+The licensor grants you a copyright license for the
+software to do everything you might do with the software
+that would otherwise infringe the licensor's copyright
+in it for any permitted purpose.  However, you may
+only distribute the software according to [Distribution
+License](#distribution-license) and make changes or new works
+based on the software according to [Changes and New Works
+License](#changes-and-new-works-license).
+
+## Distribution License
+
+The licensor grants you an additional copyright license
+to distribute copies of the software.  Your license
+to distribute covers distributing the software with
+changes and new works permitted by [Changes and New Works
+License](#changes-and-new-works-license).
+
+## Notices
+
+You must ensure that anyone who gets a copy of any part of
+the software from you also gets a copy of these terms or the
+URL for them above, as well as copies of any plain-text lines
+beginning with `Required Notice:` that the licensor provided
+with the software.  For example:
+
+> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
+
+## Changes and New Works License
+
+The licensor grants you an additional copyright license to
+make changes and new works based on the software for any
+permitted purpose.
+
+## Patent License
+
+The licensor grants you a patent license for the software that
+covers patent claims the licensor can license, or becomes able
+to license, that you would infringe by using the software.
+
+## Noncommercial Purposes
+
+Any noncommercial purpose is a permitted purpose.
+
+## Personal Uses
+
+Personal use for research, experiment, and testing for
+the benefit of public knowledge, personal study, private
+entertainment, hobby projects, amateur pursuits, or religious
+observance, without any anticipated commercial application,
+is use for a permitted purpose.
+
+## Noncommercial Organizations
+
+Use by any charitable organization, educational institution,
+public research organization, public safety or health
+organization, environmental protection organization,
+or government institution is use for a permitted purpose
+regardless of the source of funding or obligations resulting
+from the funding.
+
+## Fair Use
+
+You may have "fair use" rights for the software under the
+law. These terms do not limit them.
+
+## No Other Rights
+
+These terms do not allow you to sublicense or transfer any of
+your licenses to anyone else, or prevent the licensor from
+granting licenses to anyone else.  These terms do not imply
+any other licenses.
+
+## Patent Defense
+
+If you make any written claim that the software infringes or
+contributes to infringement of any patent, your patent license
+for the software granted under these terms ends immediately. If
+your company makes such a claim, your patent license ends
+immediately for work on behalf of your company.
+
+## Violations
+
+The first time you are notified in writing that you have
+violated any of these terms, or done anything with the software
+not covered by your licenses, your licenses can nonetheless
+continue if you come into full compliance with these terms,
+and take practical steps to correct past violations, within
+32 days of receiving notice.  Otherwise, all your licenses
+end immediately.
+
+## No Liability
+
+***As far as the law allows, the software comes as is, without
+any warranty or condition, and the licensor will not be liable
+to you for any damages arising out of these terms or the use
+or nature of the software, under any kind of legal claim.***
+
+## Definitions
+
+The **licensor** is the individual or entity offering these
+terms, and the **software** is the software the licensor makes
+available under these terms.
+
+**You** refers to the individual or entity agreeing to these
+terms.
+
+**Your company** is any legal entity, sole proprietorship,
+or other kind of organization that you work for, plus all
+organizations that have control over, are under the control of,
+or are under common control with that organization.  **Control**
+means ownership of substantially all the assets of an entity,
+or the power to direct its management and policies by vote,
+contract, or otherwise.  Control can be direct or indirect.
+
+**Your licenses** are all the licenses granted to you for the
+software under these terms.
+
+**Use** means anything you do with the software requiring one
+of your licenses.
\ No newline at end of file
diff --git a/Options/Main.html b/Options/Main.html
new file mode 100644
index 0000000..e6e281c
--- /dev/null
+++ b/Options/Main.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+	</head>
+	<body>
+		<p>The extension does everything automatically.</p>
+		
+		<h1>FAQ</h1>
+		<h2>The extension does not work when loading into YouTube Studio!</h2>
+		<p>Solution 1: This is because you are using an adblocker or another javascript-intensive extension. It's weird, I know. Get it to only disable on studio.youtube.com and the extension should work.</p>
+		<p>Solution 2: Try bookmarking "https://studio.youtube.com/channel/" instead of your personal link to give it more time to load and respond.</p>
+		<h2>Where are the items in the extension popup located?</h2>
+		<p>In the dashboard and analytics respectively.</p>
+	</body>
+</html>
diff --git a/Popups/Main.css b/Popups/Main.css
new file mode 100644
index 0000000..e59fc65
--- /dev/null
+++ b/Popups/Main.css
@@ -0,0 +1,39 @@
+html {
+	background: rgba(0, 0, 50, 0.8);
+	text-align: center;
+	color: white;
+	font-size: 13px;
+}
+
+input, button {
+	border: 2px solid rgb(0, 0, 255);
+	background: rgb(0, 0, 127);
+	border-radius: 20px;
+	color: white;
+}
+
+input {
+	width: 250px;
+}
+
+button {
+	width: 125px;
+}
+
+input:hover, button:hover {
+	background: rgb(0, 0, 180);
+}
+
+input:active, button:active {
+	background: rgb(0, 0, 70);
+}
+
+.Important {
+	font-weight: bold;
+}
+
+.Results {
+	border: 4px dotted rgb(0, 0, 127);
+	background: rgba(0, 0, 255, 0.8);
+	color: rgb(255, 255, 255);
+}
diff --git a/Popups/Main.html b/Popups/Main.html
new file mode 100644
index 0000000..82be8b2
--- /dev/null
+++ b/Popups/Main.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<link href="Main.css" rel="stylesheet" />
+	</head>
+	<body>
+		<p>The extension does everything automatically.</p>
+		<p class="Important">Refresh the page in order for changes to take affect.</p>
+		<table>
+			<tr>
+				<th><input type="url" name="AddChannel" required></input></th>
+				<th><input type="url" name="RemoveChannel" required></input></th>
+			</tr>
+			<tr>
+				<td><button name="AddChannel">Add Channel</button></td>
+				<td><button name="RemoveChannel">Remove Channel</button></td>
+			</tr>
+		</table>
+		<p class="Results"></p>
+		<table>
+			<tr>
+				<th><input type="url" name="AddTopic" required></input></th>
+				<th><input type="url" name="RemoveTopic" required></input></th>
+			</tr>
+			<tr>
+				<td><button name="AddTopic">Add Topic</button></td>
+				<td><button name="RemoveTopic">Remove Topic</button></td>
+			</tr>
+		</table>
+		<p class="Results"></p>
+		<p>More stuff available in the options menu.</p>
+		
+		<script src="Main.js" type="text/javascript"></script>
+	</body>
+</html>
diff --git a/Popups/Main.js b/Popups/Main.js
new file mode 100644
index 0000000..383c940
--- /dev/null
+++ b/Popups/Main.js
@@ -0,0 +1,103 @@
+// Removes at given index and then put last element at said index.
+// Returns modified Array.
+function RemoveAtIndex(arr, index) {
+	let Temp1 = arr[index];
+	let Temp2 = arr[arr.length - 1];
+	arr[index] = Temp2;
+	arr.pop();
+	return arr;
+}
+
+function AddChannel() {
+	browser.storage.local.get("ChannelList").then(
+		(List) => {
+			if (document.getElementsByName("AddChannel")[0].value == "") {
+				console.log("nothing in input, cancelling...");
+				return;
+			}
+			// If there is no array, make new array.
+			if (Object.values(List).length == 0) {
+				browser.storage.local.set({ChannelList: [document.getElementsByName("AddChannel")[0].value]});
+			}
+			// push a value to the existing array.
+			else {
+				let TempArray = Array.from(Object.values(List)[0]);
+				TempArray.push(document.getElementsByName("AddChannel")[0].value);
+				browser.storage.local.set({ChannelList: TempArray});
+			}
+		}
+	);
+}
+
+function RemoveChannel() {
+	browser.storage.local.get("ChannelList").then(
+		(List) => {
+			if (Object.values(List).length != 0) {
+				let TempArray = Array.from(Object.values(List)[0]);
+				let index = TempArray.indexOf(document.getElementsByName("RemoveChannel")[0].value);
+				if (index != -1) {
+					TempArray = RemoveAtIndex(TempArray, index);
+					browser.storage.local.set({ChannelList: TempArray});
+				}
+			}
+		}
+	);
+}
+
+function AddTopic() {
+	browser.storage.local.get("TopicList").then(
+		(List) => {
+			if (document.getElementsByName("AddTopic")[0].value == "") {
+				console.log("nothing in input, cancelling...");
+				return;
+			}
+			// If there is no array, make new array.
+			if (Object.values(List).length == 0) {
+				browser.storage.local.set({TopicList: [document.getElementsByName("AddTopic")[0].value]});
+			}
+			// push a value to the existing array.
+			else {
+				let TempArray = Array.from(Object.values(List)[0]);
+				TempArray.push(document.getElementsByName("AddTopic")[0].value);
+				browser.storage.local.set({TopicList: TempArray});
+			}
+		}
+	);
+}
+
+function RemoveTopic() {
+	browser.storage.local.get("TopicList").then(
+		(List) => {
+			if (Object.values(List).length != 0) {
+				let TempArray = Array.from(Object.values(List)[0]);
+				let index = TempArray.indexOf(document.getElementsByName("RemoveTopic")[0].value);
+				if (index != -1) {
+					TempArray = RemoveAtIndex(TempArray, index);
+					browser.storage.local.set({TopicList: TempArray});
+				}
+			}
+		}
+	);
+}
+
+// Now... load stuff!
+window.onload = (event) => {
+	document.getElementsByName("AddChannel")[1].addEventListener("click", AddChannel);
+	document.getElementsByName("RemoveChannel")[1].addEventListener("click", RemoveChannel);
+	browser.storage.local.get("ChannelList").then(
+		(List) => {
+			for (let i of Object.values(List)[0]) {
+				document.getElementsByClassName("Results")[0].innerHTML += "<p> "+ i + " </p>";
+			}
+		}
+	);
+	document.getElementsByName("AddTopic")[1].addEventListener("click", AddTopic);
+	document.getElementsByName("RemoveTopic")[1].addEventListener("click", RemoveTopic);
+	browser.storage.local.get("TopicList").then(
+		(List) => {
+			for (let i of Object.values(List)[0]) {
+				document.getElementsByClassName("Results")[1].innerHTML += "<p> "+ i + " </p>";
+			}
+		}
+	);
+};
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..23b9bf1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# StudioModifier
+
+Customizes the YouTube Studio to remove all stats and competitiveness. This makes posting YouTube videos a lot more fun.
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..db28b28
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,25 @@
+{
+	"manifest_version": 2,
+	"name": "Studio Modifier",
+	"author": "CatAClock",
+	"version": "1.0.3",
+	"description": "Customizes the YouTube Studio to remove all stats and competitiveness. This makes posting YouTube videos a lot more fun.",
+	"icons": {
+		"64": "Icons/Icon.png"
+	},
+	"browser_action": {
+		"default_icon": "Icons/Icon.png",
+		"default_title": "Studio Modifier",
+		"default_popup": "Popups/Main.html"
+	},
+	"options_ui": {
+		"page": "Options/Main.html"
+	},
+	"content_scripts": [
+		{
+			"matches": ["*://studio.youtube.com/*"],
+			"js": ["ContentScripts/StudioModify.js"]
+		}
+	],
+	"permissions": ["storage"]
+}