diff --git a/web/index.html b/web/index.html
index 63a5423d..dc99437f 100644
--- a/web/index.html
+++ b/web/index.html
@@ -6,13 +6,14 @@
SkillHub
-
-
-
+
+
diff --git a/web/public/fonts/fonts.css b/web/public/fonts/fonts.css
new file mode 100644
index 00000000..7d643dab
--- /dev/null
+++ b/web/public/fonts/fonts.css
@@ -0,0 +1,109 @@
+/*
+ * Self-hosted web fonts (Inter, JetBrains Mono).
+ *
+ * Replaces the runtime dependency on fonts.googleapis.com / fonts.gstatic.com,
+ * which is slow or unreachable on some networks and blocks first paint
+ * (see #716). Files are the same woff2 Google serves, vendored from the
+ * @fontsource distribution. latin / latin-ext are split by unicode-range so
+ * the browser only fetches the subset a glyph actually needs.
+ */
+
+/* ---------- Inter ---------- */
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 400;
+ font-display: swap;
+ src: url('/fonts/inter-latin-400-normal.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 400;
+ font-display: swap;
+ src: url('/fonts/inter-latin-ext-400-normal.woff2') format('woff2');
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 500;
+ font-display: swap;
+ src: url('/fonts/inter-latin-500-normal.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 500;
+ font-display: swap;
+ src: url('/fonts/inter-latin-ext-500-normal.woff2') format('woff2');
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 600;
+ font-display: swap;
+ src: url('/fonts/inter-latin-600-normal.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 600;
+ font-display: swap;
+ src: url('/fonts/inter-latin-ext-600-normal.woff2') format('woff2');
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 700;
+ font-display: swap;
+ src: url('/fonts/inter-latin-700-normal.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+@font-face {
+ font-family: 'Inter';
+ font-style: normal;
+ font-weight: 700;
+ font-display: swap;
+ src: url('/fonts/inter-latin-ext-700-normal.woff2') format('woff2');
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+
+/* ---------- JetBrains Mono ---------- */
+@font-face {
+ font-family: 'JetBrains Mono';
+ font-style: normal;
+ font-weight: 400;
+ font-display: swap;
+ src: url('/fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+@font-face {
+ font-family: 'JetBrains Mono';
+ font-style: normal;
+ font-weight: 400;
+ font-display: swap;
+ src: url('/fonts/jetbrains-mono-latin-ext-400-normal.woff2') format('woff2');
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+@font-face {
+ font-family: 'JetBrains Mono';
+ font-style: normal;
+ font-weight: 500;
+ font-display: swap;
+ src: url('/fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+@font-face {
+ font-family: 'JetBrains Mono';
+ font-style: normal;
+ font-weight: 500;
+ font-display: swap;
+ src: url('/fonts/jetbrains-mono-latin-ext-500-normal.woff2') format('woff2');
+ unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
diff --git a/web/public/fonts/inter-latin-400-normal.woff2 b/web/public/fonts/inter-latin-400-normal.woff2
new file mode 100644
index 00000000..f15b025d
Binary files /dev/null and b/web/public/fonts/inter-latin-400-normal.woff2 differ
diff --git a/web/public/fonts/inter-latin-500-normal.woff2 b/web/public/fonts/inter-latin-500-normal.woff2
new file mode 100644
index 00000000..54f0a595
Binary files /dev/null and b/web/public/fonts/inter-latin-500-normal.woff2 differ
diff --git a/web/public/fonts/inter-latin-600-normal.woff2 b/web/public/fonts/inter-latin-600-normal.woff2
new file mode 100644
index 00000000..d1897949
Binary files /dev/null and b/web/public/fonts/inter-latin-600-normal.woff2 differ
diff --git a/web/public/fonts/inter-latin-700-normal.woff2 b/web/public/fonts/inter-latin-700-normal.woff2
new file mode 100644
index 00000000..a68fb101
Binary files /dev/null and b/web/public/fonts/inter-latin-700-normal.woff2 differ
diff --git a/web/public/fonts/inter-latin-ext-400-normal.woff2 b/web/public/fonts/inter-latin-ext-400-normal.woff2
new file mode 100644
index 00000000..5243e4b2
Binary files /dev/null and b/web/public/fonts/inter-latin-ext-400-normal.woff2 differ
diff --git a/web/public/fonts/inter-latin-ext-500-normal.woff2 b/web/public/fonts/inter-latin-ext-500-normal.woff2
new file mode 100644
index 00000000..2ab7ebf6
Binary files /dev/null and b/web/public/fonts/inter-latin-ext-500-normal.woff2 differ
diff --git a/web/public/fonts/inter-latin-ext-600-normal.woff2 b/web/public/fonts/inter-latin-ext-600-normal.woff2
new file mode 100644
index 00000000..bad65d4b
Binary files /dev/null and b/web/public/fonts/inter-latin-ext-600-normal.woff2 differ
diff --git a/web/public/fonts/inter-latin-ext-700-normal.woff2 b/web/public/fonts/inter-latin-ext-700-normal.woff2
new file mode 100644
index 00000000..c9507e3f
Binary files /dev/null and b/web/public/fonts/inter-latin-ext-700-normal.woff2 differ
diff --git a/web/public/fonts/jetbrains-mono-latin-400-normal.woff2 b/web/public/fonts/jetbrains-mono-latin-400-normal.woff2
new file mode 100644
index 00000000..58588733
Binary files /dev/null and b/web/public/fonts/jetbrains-mono-latin-400-normal.woff2 differ
diff --git a/web/public/fonts/jetbrains-mono-latin-500-normal.woff2 b/web/public/fonts/jetbrains-mono-latin-500-normal.woff2
new file mode 100644
index 00000000..be878e68
Binary files /dev/null and b/web/public/fonts/jetbrains-mono-latin-500-normal.woff2 differ
diff --git a/web/public/fonts/jetbrains-mono-latin-ext-400-normal.woff2 b/web/public/fonts/jetbrains-mono-latin-ext-400-normal.woff2
new file mode 100644
index 00000000..9d97c9b7
Binary files /dev/null and b/web/public/fonts/jetbrains-mono-latin-ext-400-normal.woff2 differ
diff --git a/web/public/fonts/jetbrains-mono-latin-ext-500-normal.woff2 b/web/public/fonts/jetbrains-mono-latin-ext-500-normal.woff2
new file mode 100644
index 00000000..5cc89b16
Binary files /dev/null and b/web/public/fonts/jetbrains-mono-latin-ext-500-normal.woff2 differ