diff --git a/src/components/status.css b/src/components/status.css
index 9d5f7560..2c50b04a 100644
--- a/src/components/status.css
+++ b/src/components/status.css
@@ -149,7 +149,7 @@
   margin: 4px 0 0 0;
   gap: 4px;
   align-items: center;
-  color: var(--reply-to-color);
+  color: var(--reply-to-text-color);
   background: var(--bg-color);
   border: 1px solid var(--reply-to-color);
   border-radius: 4px;
diff --git a/src/components/status.jsx b/src/components/status.jsx
index a6bb7f3f..2b246b80 100644
--- a/src/components/status.jsx
+++ b/src/components/status.jsx
@@ -270,30 +270,32 @@ function Status({
               </span>
             ))}
         </div>
-        {!!inReplyToId &&
-          !!inReplyToAccountId &&
-          !withinContext &&
-          size !== 's' && (
-            <>
-              {inReplyToAccountId === status.account.id ? (
-                <div class="status-thread-badge">
-                  <Icon icon="thread" size="s" />
-                  Thread
+        {!withinContext && size !== 's' && (
+          <>
+            {inReplyToAccountId === status.account?.id ||
+            !!snapStates.statusThreadNumber[id] ? (
+              <div class="status-thread-badge">
+                <Icon icon="thread" size="s" />
+                Thread
+                {snapStates.statusThreadNumber[id]
+                  ? ` ${snapStates.statusThreadNumber[id]}/X`
+                  : ''}
+              </div>
+            ) : (
+              !!inReplyToId &&
+              !!inReplyToAccount &&
+              (!!spoilerText ||
+                !mentions.find((mention) => {
+                  return mention.id === inReplyToAccountId;
+                })) && (
+                <div class="status-reply-badge">
+                  <Icon icon="reply" />{' '}
+                  <NameText account={inReplyToAccount} short />
                 </div>
-              ) : (
-                !!inReplyToAccount &&
-                (!!spoilerText ||
-                  !mentions.find((mention) => {
-                    return mention.id === inReplyToAccountId;
-                  })) && (
-                  <div class="status-reply-badge">
-                    <Icon icon="reply" />{' '}
-                    <NameText account={inReplyToAccount} short />
-                  </div>
-                )
-              )}
-            </>
-          )}
+              )
+            )}
+          </>
+        )}
         <div
           class={`content-container ${
             sensitive || spoilerText ? 'has-spoiler' : ''
diff --git a/src/index.css b/src/index.css
index d8230b9c..e592aef5 100644
--- a/src/index.css
+++ b/src/index.css
@@ -24,6 +24,7 @@
   --reblog-color: var(--purple-color);
   --reblog-faded-color: #892be220;
   --reply-to-color: var(--orange-color);
+  --reply-to-text-color: #b36200;
   --favourite-color: var(--red-color);
   --reply-to-faded-color: #ffa6001a;
   --outline-color: rgba(128, 128, 128, 0.2);
diff --git a/src/utils/states.js b/src/utils/states.js
index 2c52034c..4c37863c 100644
--- a/src/utils/states.js
+++ b/src/utils/states.js
@@ -3,6 +3,7 @@ import { proxy } from 'valtio';
 const states = proxy({
   history: [],
   statuses: {},
+  statusThreadNumber: {},
   home: [],
   homeNew: [],
   homeLastFetchTime: null,
@@ -22,11 +23,57 @@ const states = proxy({
 export default states;
 
 export function saveStatus(status, opts) {
-  const { override } = Object.assign({ override: true }, opts);
+  const { override, skipThreading } = Object.assign(
+    { override: true, skipThreading: false },
+    opts,
+  );
   if (!status) return;
   if (!override && states.statuses[status.id]) return;
   states.statuses[status.id] = status;
   if (status.reblog) {
     states.statuses[status.reblog.id] = status.reblog;
   }
+
+  // THREAD TRAVERSER
+  if (!skipThreading) {
+    requestAnimationFrame(() => {
+      threadifyStatus(status);
+    });
+  }
+}
+
+function threadifyStatus(status) {
+  // Return all statuses in the thread, via inReplyToId, if inReplyToAccountId === account.id
+  let fetchIndex = 0;
+  async function traverse(status, index = 0) {
+    const { inReplyToId, inReplyToAccountId } = status;
+    if (!inReplyToId || inReplyToAccountId !== status.account.id) {
+      return [status];
+    }
+    if (inReplyToId && inReplyToAccountId !== status.account.id) {
+      throw 'Not a thread';
+      // Possibly thread of replies by multiple people?
+    }
+    let prevStatus = states.statuses[inReplyToId];
+    if (!prevStatus) {
+      if (fetchIndex++ > 3) throw 'Too many fetches for thread'; // Some people revive old threads
+      await new Promise((r) => setTimeout(r, 500 * fetchIndex)); // Be nice to rate limits
+      prevStatus = await masto.v1.statuses.fetch(inReplyToId);
+      saveStatus(prevStatus, { skipThreading: true });
+    }
+    // Prepend so that first status in thread will be index 0
+    return [...(await traverse(prevStatus, ++index)), status];
+  }
+  return traverse(status)
+    .then((statuses) => {
+      if (statuses.length > 1) {
+        console.debug('THREAD', statuses);
+        statuses.forEach((status, index) => {
+          states.statusThreadNumber[status.id] = index + 1;
+        });
+      }
+    })
+    .catch((e) => {
+      console.error(e, status);
+    });
 }