diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 89fc307..c21af39 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -28,6 +28,7 @@ module.exports = {
 		}
 	],
 	rules: {
-		'@typescript-eslint/no-explicit-any': 'off'
+		'@typescript-eslint/no-explicit-any': 'off',
+		'no-undef': 'off'
 	}
 };
diff --git a/src/entries/popup/Popup.svelte b/src/entries/popup/Popup.svelte
index 46972fb..28957ff 100644
--- a/src/entries/popup/Popup.svelte
+++ b/src/entries/popup/Popup.svelte
@@ -1,117 +1,93 @@
 <script lang="ts">
-	import { matches } from '~/lib/match';
+	import { type Match, matches } from '~/lib/match';
 	import { Hosters, Other } from '~/lib/settings';
+	import Toggle from './toggle.svelte';
 
 	let hostersEnabled: boolean;
-	let hosters = [];
+	let hosters: (Match & { active: boolean; disabled: boolean })[] = [];
 	(async () => {
 		hostersEnabled = !(await Hosters.getAllDisabled());
 
 		const disabled = await Hosters.getDisabled();
-		hosters = Object.values(matches).map((m) => {
+		hosters = Object.values(matches).map((m: any) => {
 			m['active'] = disabled.findIndex((p) => p.id == m.id) == -1;
-			m['disabled'] = !hostersEnabled;
 			return m;
-		});
+		}) as typeof hosters;
+	})();
+
+	let isMobile: boolean;
+	(async () => {
+		// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+		// @ts-ignore
+		isMobile = (await browser.runtime.getPlatformInfo()).os === 'android';
 	})();
 
 	let ff2mpvEnabled: boolean;
 	(async () => {
-		ff2mpvEnabled = await Other.getFf2mpv();
+		ff2mpvEnabled = (await Other.getFf2mpv()) as boolean;
 	})();
 </script>
 
-<main>
-	<div>
-		<h3 class="header">Hosters</h3>
-		<div class="buttons super-buttons">
-			<button
-				class:active={hostersEnabled}
-				on:click={async () => {
-					await Hosters.enableAll();
-					hostersEnabled = true;
-					hosters = hosters.map((m) => {
-						m['disabled'] = false;
-						return m;
-					});
-				}}>On</button
-			>
-			<button
-				class:active={!hostersEnabled}
-				on:click={async () => {
-					await Hosters.disableAll();
-					hostersEnabled = false;
-					hosters = hosters.map((m) => {
-						m['disabled'] = true;
-						return m;
-					});
-				}}>Off</button
-			>
-		</div>
-		<table class="setting-table">
-			{#each hosters as hoster}
-				<tr>
-					<td class="setting-name">
-						<p>{hoster.name}</p>
-					</td>
-					<td class="buttons">
-						<button
-							class:disabled={hoster.disabled}
-							class:active={hoster.active}
-							on:click={async () => {
-								if (hoster.disabled) return;
+<main
+	style={isMobile
+		? 'height: 100vh; display: flex; flex-direction: column; align-items: center'
+		: 'height: 500px'}
+>
+	<fieldset>
+		<legend>Hoster</legend>
+		<div class="setting-container" style={isMobile ? 'grid-column-gap: 5rem' : ''}>
+			<label for="hosters-enabled">Enabled</label>
+			<div>
+				<Toggle
+					bind:checked={hostersEnabled}
+					id="hosters-enabled"
+					on:change={() => Hosters.setAll(hostersEnabled)}
+				/>
+			</div>
+			<hr />
+			{#each hosters as hoster, i}
+				<label for="hoster-{i}" style="cursor: {hostersEnabled ? 'pointer' : 'default'}"
+					>{hoster.name}</label
+				>
+				<div>
+					<Toggle
+						bind:checked={hoster.active}
+						disabled={!hostersEnabled}
+						id="hoster-{i}"
+						on:change={async () => {
+							if (hoster.active) {
 								await Hosters.enable(hoster);
-								hoster.active = true;
-							}}>On</button
-						>
-						<button
-							class:disabled={hoster.disabled}
-							class:active={!hoster.active}
-							on:click={async () => {
-								if (hoster.disabled) return;
+							} else {
 								await Hosters.disable(hoster);
-								hoster.active = false;
-							}}>Off</button
-						>
-					</td>
-				</tr>
+							}
+						}}
+					></Toggle>
+				</div>
 			{/each}
-		</table>
-	</div>
-	<hr />
-	<div>
-		<h3 class="header">Other</h3>
-		<table>
-			<tr>
-				<td class="setting-name">
-					<p>ff2mpv</p>
-				</td>
-				<td class="buttons">
-					<button
-						class:active={ff2mpvEnabled}
-						on:click={async () => {
-							await Other.setFf2mpv(true);
-							ff2mpvEnabled = true;
-						}}>On</button
-					>
-					<button
-						class:active={!ff2mpvEnabled}
-						on:click={async () => {
-							await Other.setFf2mpv(false);
-							ff2mpvEnabled = false;
-						}}>Off</button
-					>
+		</div>
+	</fieldset>
+	{#if !isMobile}
+		<fieldset>
+			<legend>Other</legend>
+			<div class="setting-container">
+				<label for="ff2mpv">ff2mpv</label>
+				<div>
+					<Toggle
+						bind:checked={ff2mpvEnabled}
+						id="ff2mpv"
+						on:change={async () => Other.setFf2mpv(ff2mpvEnabled)}
+					></Toggle>
 					<a
+						class="info-questionmark"
 						href="https://github.com/ByteDream/stream-bypass/tree/master#ff2mpv-use-mpv-to-directly-play-streams"
-						>🛈</a
+						>?</a
 					>
-				</td>
-			</tr>
-		</table>
-	</div>
-	<hr />
-	<a id="bug-notice" href="https://github.com/ByteDream/stream-bypass/issues"
-		>Something does not work</a
+				</div>
+			</div>
+		</fieldset>
+	{/if}
+	<a id="report-notice" href="https://github.com/ByteDream/stream-bypass/issues"
+		>Report issues or requests</a
 	>
 </main>
 
@@ -125,7 +101,12 @@
 		padding: 0 8px;
 	}
 
-	#bug-notice {
+	fieldset {
+		border-radius: 5px;
+		border-color: gray;
+	}
+
+	#report-notice {
 		border: none;
 		color: white;
 		display: block;
@@ -148,52 +129,33 @@
 		text-align: center;
 	}
 
-	.setting-table {
-		border-collapse: collapse;
-		border-spacing: 0;
-	}
+	.setting-container {
+		display: grid;
+		grid-template-columns: auto auto;
+		grid-column-gap: 5px;
+		grid-row-gap: 4px;
+		align-items: end;
+		width: 100%;
 
-	.setting-name {
-		height: 34px;
-
-		p {
+		& > label {
+			height: 34px;
 			margin: 0;
-			cursor: default;
-		}
-	}
-
-	.buttons {
-		display: flex;
-		flex-direction: row;
-		height: 34px;
-
-		button,
-		a {
-			border: 1px solid #281515;
-			background-color: transparent;
-			color: white;
+			user-select: none;
 			cursor: pointer;
-			padding: 5px 8px;
-			margin: 0;
-			text-decoration: none;
-
-			&.active {
-				background-color: rgba(255, 65, 65, 0.74);
-				cursor: default;
-			}
-
-			&.disabled {
-				background-color: gray;
-				cursor: not-allowed;
-			}
-		}
-
-		&.super-buttons {
 			display: flex;
-			justify-content: center;
-			gap: 4px;
-			width: 100%;
-			margin-bottom: 10px;
+			align-items: center;
 		}
+
+		& > hr {
+			grid-column: 1 / span 2;
+			width: 100%;
+		}
+	}
+
+	.info-questionmark {
+		display: inline-block;
+		transform: translateX(-40%) translateY(-100%);
+		color: black;
+		text-decoration: none;
 	}
 </style>
diff --git a/src/entries/popup/index.html b/src/entries/popup/index.html
index d8ffad5..e6fbe27 100644
--- a/src/entries/popup/index.html
+++ b/src/entries/popup/index.html
@@ -1,10 +1,11 @@
 <!doctype html>
-<html style="width: fit-content; height: 500px; overflow-y: hidden" lang="en">
+<html style="overflow-y: hidden" lang="en">
 	<head>
 		<meta charset="UTF-8" />
+		<meta name="viewport" content="width=device-width" />
 		<title>Stream Bypass</title>
 	</head>
-	<body style="width: fit-content; height: 500px; overflow-y: scroll">
+	<body style="overflow-y: scroll">
 		<script type="module">
 			import Popup from '~/entries/popup/Popup.svelte';
 
diff --git a/src/entries/popup/toggle.svelte b/src/entries/popup/toggle.svelte
new file mode 100644
index 0000000..b7986a3
--- /dev/null
+++ b/src/entries/popup/toggle.svelte
@@ -0,0 +1,65 @@
+<!-- https://flowbite.com/docs/forms/toggle/ -->
+<script lang="ts">
+	import { createEventDispatcher } from 'svelte';
+
+	export let checked = false;
+	export let disabled = false;
+	export let id: string | null = null;
+
+	const dispatch = createEventDispatcher();
+</script>
+
+<label class="toggle">
+	<slot />
+	<input type="checkbox" {id} bind:checked {disabled} on:change={(e) => dispatch('change', e)} />
+	<span />
+</label>
+
+<style lang="scss" global>
+	.toggle {
+		display: inline-flex;
+		align-items: center;
+		cursor: pointer;
+
+		input {
+			clip: rect(0, 0, 0, 0);
+			position: absolute;
+
+			&:checked + span {
+				background: limegreen;
+
+				&:after {
+					transform: translateX(100%);
+				}
+			}
+
+			&:disabled + span {
+				background: gray;
+			}
+		}
+
+		span {
+			position: relative;
+			width: 2.75rem;
+			height: 1.5rem;
+			background: #cf0000;
+			border-radius: 9999px;
+
+			&:after {
+				content: '';
+				position: absolute;
+				top: 2px;
+				inset-inline-start: 2px;
+				background: white;
+				border-radius: 9999px;
+				height: 1.25rem;
+				width: 1.25rem;
+				transition: all 0.15s;
+			}
+		}
+
+		&:has(input:disabled) {
+			cursor: default;
+		}
+	}
+</style>
diff --git a/src/lib/settings.ts b/src/lib/settings.ts
index 9d9ebae..985dabd 100644
--- a/src/lib/settings.ts
+++ b/src/lib/settings.ts
@@ -25,11 +25,8 @@ export const Hosters = {
 	getAllDisabled: async () => {
 		return await storageGet<boolean>('hosters.allDisabled', false);
 	},
-	disableAll: async () => {
-		await storageSet('hosters.allDisabled', true);
-	},
-	enableAll: async () => {
-		await storageSet('hosters.allDisabled', false);
+	setAll: async (enable: boolean) => {
+		await storageSet('hosters.allDisabled', !enable);
 	}
 };
 
@@ -47,7 +44,7 @@ export const Redirect = {
 
 export const Other = {
 	getFf2mpv: async () => {
-		return await storageGet('other.ff2mpv', true);
+		return await storageGet('other.ff2mpv', false);
 	},
 	setFf2mpv: async (enable: boolean) => {
 		await storageSet('other.ff2mpv', enable);