diff --git a/package.json b/package.json
index 68277343b1a8c91cba01540c252c58d1ffa73a12..89d1c748418279f6d9ca53f15d6768114edc7e3e 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
 		"@urql/core": "^5.0.6",
 		"formsnap": "^1.0.1",
 		"gql.tada": "^1.8.6",
+		"http-status-codes": "^2.3.0",
 		"msgpackr": "^1.11.0",
 		"sveltekit-superforms": "^2.17.0",
 		"zod": "^3.23.8"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3fd4d270bab5ef2ce52a051bc4f11acba485fb04..25cde9dca77458c459ad06d3cab1fb0686e7fb4f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,6 +17,9 @@ importers:
       gql.tada:
         specifier: ^1.8.6
         version: 1.8.6(graphql@15.9.0)(typescript@5.5.4)
+      http-status-codes:
+        specifier: ^2.3.0
+        version: 2.3.0
       msgpackr:
         specifier: ^1.11.0
         version: 1.11.0
@@ -1232,6 +1235,9 @@ packages:
     resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
     engines: {node: '>= 0.4'}
 
+  http-status-codes@2.3.0:
+    resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==}
+
   ignore@5.3.2:
     resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
     engines: {node: '>= 4'}
@@ -3295,6 +3301,8 @@ snapshots:
     dependencies:
       function-bind: 1.1.2
 
+  http-status-codes@2.3.0: {}
+
   ignore@5.3.2: {}
 
   import-fresh@3.3.0:
diff --git a/src/app.css b/src/app.css
index a31e444117d00d0d7238ebc538007f6e224877da..716762262c022815d8a8ee32af068a1f67555d3e 100644
--- a/src/app.css
+++ b/src/app.css
@@ -1,3 +1,27 @@
 @import 'tailwindcss/base';
 @import 'tailwindcss/components';
 @import 'tailwindcss/utilities';
+
+@font-face {
+	font-family: 'Londrina Solid';
+	font-weight: 100;
+	src: url('/fonts/LondrinaSolid-Thin.ttf');
+}
+
+@font-face {
+	font-family: 'Londrina Solid';
+	font-weight: 300;
+	src: url('/fonts/LondrinaSolid-Light.ttf');
+}
+
+@font-face {
+	font-family: 'Londrina Solid';
+	font-weight: 400;
+	src: url('/fonts/LondrinaSolid-Regular.ttf');
+}
+
+@font-face {
+	font-family: 'Londrina Solid';
+	font-weight: 900;
+	src: url('/fonts/LondrinaSolid-Black.ttf');
+}
diff --git a/src/app.html b/src/app.html
index 9c53e5672bcb5fee0c05adb61df69174c7fe9682..e3461df3eff6b42492ae91ff9d5fb087d96b2242 100644
--- a/src/app.html
+++ b/src/app.html
@@ -4,10 +4,6 @@
 		<meta charset="utf-8" />
 		<link rel="icon" href="%sveltekit.assets%/favicon.png" />
 		<meta name="viewport" content="width=device-width, initial-scale=1" />
-		<link
-			rel="stylesheet"
-			href="https://fonts.googleapis.com/css?family=Londrina+Solid|Nunito:400,300"
-		/>
 		%sveltekit.head%
 	</head>
 	<body data-sveltekit-preload-data="hover" class="h-full">
diff --git a/src/lib/graphql/error.ts b/src/lib/graphql/error.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9f6cf2354cdb6cbd1f280a107a62131b9027321a
--- /dev/null
+++ b/src/lib/graphql/error.ts
@@ -0,0 +1,8 @@
+import { error } from '@sveltejs/kit';
+import type { OperationResult } from '@urql/core';
+
+export function handleGqlError(result: OperationResult): void {
+	if (result.error) {
+		error(500, { message: result.error.message });
+	}
+}
diff --git a/src/lib/graphql/query.ts b/src/lib/graphql/query.ts
index c8d69de0300d6ce6a6862e21e007e172305cd762..3dad155df05315ae4f09297fd47c1232ba29928b 100644
--- a/src/lib/graphql/query.ts
+++ b/src/lib/graphql/query.ts
@@ -1,5 +1,6 @@
 import { client } from '$lib/graphql';
 import type { DocumentInput } from '@urql/core';
+import { handleGqlError } from './error';
 
 type Page<T> = {
 	page: {
@@ -29,9 +30,8 @@ export async function* pageIterator<T, Variables extends PageArgs>(
 			.query(query, { first: pageSize, after: cursor, ...variables } as Variables)
 			.toPromise();
 
-		if (result.error) {
-			throw result.error;
-		}
+		handleGqlError(result);
+
 		const page: Page<T>['page'] | undefined = result.data?.page;
 		if (!page) return;
 
diff --git a/src/routes/quiz/+error.svelte b/src/routes/quiz/+error.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..cdc25a7647395fbf44348924fe78dcf053a495cb
--- /dev/null
+++ b/src/routes/quiz/+error.svelte
@@ -0,0 +1,14 @@
+<script>
+	import { page } from '$app/stores';
+	import { getReasonPhrase } from 'http-status-codes';
+</script>
+
+<main class="grid min-h-full place-items-center px-6 py-24 sm:py-32 lg:px-8">
+	<div class="max-w-lg text-center">
+		<p class="text-7xl font-semibold text-red-200">{$page.status}</p>
+		<h1 class="mt-4 text-3xl tracking-tight text-white sm:text-5xl">
+			{getReasonPhrase($page.status)}
+		</h1>
+		<p class="mt-6 text-lg font-light leading-7 text-red-100">{$page.error?.message}</p>
+	</div>
+</main>
diff --git a/src/routes/quiz/+layout.svelte b/src/routes/quiz/+layout.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..7afeea526e29313a4ff9b89c17910b58a8ff93fb
--- /dev/null
+++ b/src/routes/quiz/+layout.svelte
@@ -0,0 +1,11 @@
+<slot></slot>
+
+<style>
+	:global(body) {
+		background-color: #f65a52;
+		font-family: 'Londrina Solid', monospace;
+		font-size: 16px;
+		line-height: 1.875em;
+		color: #333;
+	}
+</style>
diff --git a/src/routes/quiz/+page.server.ts b/src/routes/quiz/+page.server.ts
index 59811a9af769bc9bfdeb49f6c1fe64a494e3b35f..ec9a25ef5e591c1b492d3ed9d296b267d27f31f0 100644
--- a/src/routes/quiz/+page.server.ts
+++ b/src/routes/quiz/+page.server.ts
@@ -7,6 +7,7 @@ import { GameStage, Game } from '$lib/game';
 import { getPromotion } from '$lib/data';
 import { client } from '$lib/graphql';
 import { USER_DETAILS_QUERY } from '$lib/graphql/queries';
+import { handleGqlError } from '$lib/graphql/error';
 
 type Option = {
 	value: string;
@@ -34,9 +35,7 @@ export async function load(event) {
 		.query(USER_DETAILS_QUERY, { idList: game.state.options })
 		.toPromise();
 
-	if (details.error) {
-		throw details.error;
-	}
+	handleGqlError(details);
 
 	const users = details.data!.page.nodes ?? [];
 
diff --git a/src/routes/quiz/+page.svelte b/src/routes/quiz/+page.svelte
index bb662e8e1f27b871325aa59050e3ac33fa8ef6ab..3e97318a09828ab4261ed41f97d5cf4a0a69518d 100644
--- a/src/routes/quiz/+page.svelte
+++ b/src/routes/quiz/+page.svelte
@@ -87,13 +87,3 @@
 		</section>
 	</div>
 </form>
-
-<style>
-	:global(body) {
-		background-color: #f65a52;
-		font-family: 'Londrina Solid', monospace;
-		font-size: 16px;
-		line-height: 1.875em;
-		color: #333;
-	}
-</style>
diff --git a/static/fonts/LondrinaSolid-Black.ttf b/static/fonts/LondrinaSolid-Black.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..3840ff320bb52ca4a61a191d48e797b9adeaf5ac
Binary files /dev/null and b/static/fonts/LondrinaSolid-Black.ttf differ
diff --git a/static/fonts/LondrinaSolid-Light.ttf b/static/fonts/LondrinaSolid-Light.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..651cf53a45a5c2d94b2271e9fb3e7f59fc12f5f1
Binary files /dev/null and b/static/fonts/LondrinaSolid-Light.ttf differ
diff --git a/static/fonts/LondrinaSolid-Regular.ttf b/static/fonts/LondrinaSolid-Regular.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..7bf49231a6447864f6d726a4ca5b42d46f45d891
Binary files /dev/null and b/static/fonts/LondrinaSolid-Regular.ttf differ
diff --git a/static/fonts/LondrinaSolid-Thin.ttf b/static/fonts/LondrinaSolid-Thin.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..3b4f77122f6950aaf4bb8a937ebcf1a1728f9de7
Binary files /dev/null and b/static/fonts/LondrinaSolid-Thin.ttf differ