diff --git a/content/echoes/arcaea.dj b/content/echoes/arcaea.dj
index 0f36505..8bf5e59 100644
--- a/content/echoes/arcaea.dj
+++ b/content/echoes/arcaea.dj
@@ -52,7 +52,7 @@ Let $`m`, $`p`, $`f` and $`l` denote the amount of MAX PURE, PURE, FAR and LOST
 $$`m + \left\lfloor (2(m + p) + f) \frac{10'000'000}{2(m + p + f + l)} \right\rfloor`
 :::
 
-While full recalls and max-PMs are certainly celebrated by players and the larger community alike, PMs are usually the sweet spot between accurate play and fun which many Arcaea players strive for. This is usually the case because the game hardly rewards (if acknowledge at all) plays that are better than a PM (this will become obvious when we discuss the game's rating system).
+While full recalls and max-PMs are certainly celebrated by players and the larger community alike, PMs are usually the sweet spot between accurate play and fun which many Arcaea players strive for. This is often the case because the game hardly rewards (if acknowledges at all) plays that are better than a PM.
 
 {title="Lagrange's extras: ΞΆ-scoring" character="lagrange" id="ex-scoring"}
 ::: long-aside
diff --git a/content/echoes/games/index.dj b/content/echoes/games/index.dj
index 04e57af..a1c1102 100644
--- a/content/echoes/games/index.dj
+++ b/content/echoes/games/index.dj
@@ -2,6 +2,9 @@
 
 This article contains a highly subjective tier list of most of the games I've played. You can click on the different tiers or games to be taken to the section of the article exploring my thoughts on said game. Everything in this article is spoiler-free, unless otherwise stated in a certain game's section. Enjoy!
 
+::: toc
+:::
+
 { role="tier-list" }
 ``` =yaml
 id: games-tier-list
diff --git a/public/styles.css b/public/styles.css
index f654577..661ea99 100644
--- a/public/styles.css
+++ b/public/styles.css
@@ -27,7 +27,7 @@ h6 {
     display: inline-block;
     text-decoration: none;
     /* Note: I need to check whether this only aligns things better with the font I use */
-    translate: translateY(-2px);
+    transform: translateY(-2px);
   }
 }
 
@@ -206,6 +206,46 @@ math[display="block"] {
   /* }}} */
 }
 /* }}} */
+/* {{{ Tables of contents */
+.toc {
+  border-radius: 3px;
+  border: 1px solid black;
+
+  box-sizing: border-box;
+  padding: 1rem;
+  margin: 1.5rem 0;
+
+  summary span {
+    margin-left: 0.5rem;
+  }
+
+  nav {
+    margin-left: 1rem;
+  }
+
+  li {
+    padding: 0.25rem;
+  }
+
+  ol {
+    margin-bottom: 0;
+  }
+
+  ol ol {
+    position: relative;
+    &::before {
+      content: "";
+      position: absolute;
+      top: 0.5rem;
+      bottom: 0.5rem;
+      left: -1.25rem;
+      border-left: 1px solid white;
+      width: 2px;
+      background: #003f5233;
+    }
+  }
+}
+/* }}} */
 
 /* {{{ Light theme */
 @media (prefers-color-scheme: light) {
diff --git a/src/html.rs b/src/html.rs
index 2836d20..a110070 100644
--- a/src/html.rs
+++ b/src/html.rs
@@ -313,51 +313,63 @@ impl<'s> Writer<'s> {
 					}
 					// }}}
 					// {{{ Table of contents
+					// This component renders out a nice tree of all the headings in the article.
 					Container::Div { class: "toc" } => {
 						template!("templates/table-of-contents.html", out)?.feed_fully(
 							out,
 							|label, out| {
 								if label == "content" {
+									// Sometimes we can have TOCs that look like this:
+									// # foo
+									//   ## bar
+									//     ### goo
+									// # help
+									//
+									// In this case, we need to close two different sublists when
+									// going from ### goo to # help. To achieve this, we use this
+									// vec as a stack of all the different levels we are yet to
+									// close out.
+									//
+									// Note that the list for the initial level is included in the
+									// template, as it would never get opened/closed out otherwise
+									// (there can be no level smaller than 1).
 									let mut level_stack = Vec::with_capacity(6);
-									level_stack.push(1);
+									level_stack.push(2);
 
 									for (i, heading) in self.metadata.toc.iter().enumerate() {
-										loop {
-											let level = level_stack.last().unwrap();
-											match heading.level.cmp(level) {
-												Ordering::Greater => {
-													writeln!(out, "<ol>")?;
-													level_stack.push(heading.level);
-													break;
-												}
-												Ordering::Equal => {
-													if i != 0 {
-														writeln!(out, "</li>")?;
-													}
-
-													break;
-												}
-												Ordering::Less => {
-													writeln!(out, "</li></ol>")?;
-													level_stack.pop();
-												}
-											}
+										// We exclude the article title from the table of contents.
+										if heading.level == 1 {
+											continue;
 										}
 
 										write!(out, r##"<li><a href="#{}">"##, heading.id)?;
-
 										for event in &heading.events {
 											self.render_event(event, out)?;
 										}
 
-										writeln!(out, "</a>")?;
-									}
+										// We only close the <a> here, as we might want to include a
+										// sublist inside the same <li> element.
+										write!(out, "</a>")?;
 
-									for _ in 0..level_stack.len() - 1 {
-										writeln!(out, "</li></ol>")?;
-									}
+										let next_level =
+											self.metadata.toc.get(i + 1).map_or(2, |h| h.level);
 
-									writeln!(out, "</li>")?;
+										match heading.level.cmp(&next_level) {
+											Ordering::Equal => {
+												write!(out, "</li>")?;
+											}
+											Ordering::Less => {
+												write!(out, "<ol>")?;
+												level_stack.push(next_level);
+											}
+											Ordering::Greater => {
+												while level_stack.last().unwrap() > &next_level {
+													write!(out, "</ol></li>")?;
+													level_stack.pop();
+												}
+											}
+										}
+									}
 
 									Ok(true)
 								} else {
diff --git a/src/templates/table-of-contents.html b/src/templates/table-of-contents.html
index f27d8de..08c6524 100644
--- a/src/templates/table-of-contents.html
+++ b/src/templates/table-of-contents.html
@@ -1,7 +1,7 @@
-<details>
-  <summary>Toggle table of contents</summary>
+<details class="toc">
+  <summary><span>Toggle table of contents</span></summary>
   <nav role="doc-toc" aria-labelledby="toc-title">
-    <h2 id="toc-title">Table of Contents</h2>
+    <h3 id="toc-title">Table of Contents</h3>
     <ol>
       {{content}}
     </ol>