Index: app/(app)/add/actions.ts
===================================================================
--- app/(app)/add/actions.ts	(revision 8563782f7b44a1553af5f70be2d12ab25a84d6bd)
+++ app/(app)/add/actions.ts	(revision 8b31e7717a6c248f51f8baf6380aa8689d137d04)
@@ -112,4 +112,5 @@
     const amountRaw = String(formData.get('amount') ?? '').trim();
     const tagsJson = String(formData.get('tags') ?? '[]');
+    const pendingTag = String(formData.get('pendingTag') ?? '').trim().toLowerCase();
     const note = String(formData.get('note') ?? '').trim();
     const breakdownsJson = String(formData.get('breakdowns') ?? '[]');
@@ -136,4 +137,9 @@
     } catch {
         return { error: 'Invalid tags data.' };
+    }
+
+    // Include any tag the user typed but didn't press Enter for
+    if (pendingTag && !pendingTag.startsWith('__note:') && !tags.includes(pendingTag)) {
+        tags.push(pendingTag);
     }
 
Index: app/(app)/add/add-transaction-form.tsx
===================================================================
--- app/(app)/add/add-transaction-form.tsx	(revision 8563782f7b44a1553af5f70be2d12ab25a84d6bd)
+++ app/(app)/add/add-transaction-form.tsx	(revision 8b31e7717a6c248f51f8baf6380aa8689d137d04)
@@ -127,4 +127,5 @@
             {/* Hidden serialised fields */}
             <input type="hidden" name="tags" value={JSON.stringify(selectedTags)} />
+            <input type="hidden" name="pendingTag" value={tagInput.trim().toLowerCase()} />
             <input
                 type="hidden"
Index: app/lib/queries.ts
===================================================================
--- app/lib/queries.ts	(revision 8563782f7b44a1553af5f70be2d12ab25a84d6bd)
+++ app/lib/queries.ts	(revision 8b31e7717a6c248f51f8baf6380aa8689d137d04)
@@ -141,4 +141,5 @@
         FROM tag_assigned_to_transaction tat
         JOIN tag ON tag.tag_id = tat.tag_id
+        WHERE tag.tag_name NOT LIKE '__note:%'
         GROUP BY tat.transaction_id
         )
@@ -218,17 +219,78 @@
 
     const rows = await sql<HistoryTransaction[]>`
-        SELECT
-            t.transaction_id,
-            t.transaction_name,
-            t.date::text AS date,
-            (
-                COALESCE(SUM(COALESCE(tb.earned_amount, 0)), 0)
-                -
-                COALESCE(SUM(COALESCE(tb.spent_amount, 0)), 0)
-            )::text AS net_amount,
+        WITH filtered_tx AS (
+            SELECT
+                t.transaction_id,
+                t.transaction_name,
+                t.date,
+                (
+                    COALESCE(SUM(COALESCE(tb.earned_amount, 0)), 0)
+                    -
+                    COALESCE(SUM(COALESCE(tb.spent_amount, 0)), 0)
+                )::text AS net_amount
+            FROM transaction t
+            JOIN transaction_breakdown tb ON tb.transaction_id = t.transaction_id
+            JOIN transaction_account ta ON ta.transaction_account_id = tb.transaction_account_id
+            WHERE ta.user_id = ${userId}
+                AND (${accountId ?? null}::int IS NULL OR tb.transaction_account_id = ${accountId ?? null})
+                AND (
+                    ${searchPattern}::text IS NULL
+                    OR t.transaction_name ILIKE ${searchPattern}
+                    OR ta.account_name ILIKE ${searchPattern}
+                    OR EXISTS (
+                        SELECT 1
+                        FROM tag_assigned_to_transaction tat2
+                        JOIN tag tg2 ON tg2.tag_id = tat2.tag_id
+                        WHERE tat2.transaction_id = t.transaction_id
+                            AND tg2.tag_name ILIKE ${searchPattern}
+                    )
+                )
+                AND (
+                    ${tagCount}::int = 0
+                    OR (
+                        SELECT COUNT(DISTINCT tg_f.tag_name)
+                        FROM tag_assigned_to_transaction tat_f
+                        JOIN tag tg_f ON tg_f.tag_id = tat_f.tag_id
+                        WHERE tat_f.transaction_id = t.transaction_id
+                            AND tg_f.tag_name = ANY(${tagFilter ?? []}::text[])
+                    ) = ${tagCount}
+                )
+            GROUP BY t.transaction_id
+            ORDER BY t.date DESC
+            LIMIT ${HISTORY_ITEMS_PER_PAGE}
+            OFFSET ${offset}
+        )
+        SELECT
+            ft.transaction_id,
+            ft.transaction_name,
+            ft.date::text AS date,
+            ft.net_amount,
             COALESCE(
                 ARRAY_REMOVE(ARRAY_AGG(DISTINCT tg.tag_name), NULL),
                 ARRAY[]::text[]
             ) AS tags
+        FROM filtered_tx ft
+        LEFT JOIN tag_assigned_to_transaction tat ON tat.transaction_id = ft.transaction_id
+        LEFT JOIN tag tg ON tg.tag_id = tat.tag_id
+        GROUP BY ft.transaction_id, ft.transaction_name, ft.date, ft.net_amount
+        ORDER BY ft.date DESC
+    `;
+
+    return rows;
+}
+
+export async function getHistoryTransactionPages(params: {
+    userId: number;
+    accountId?: number;
+    query?: string;
+    tags?: string[];
+}) {
+    const { userId, accountId, query, tags } = params;
+    const searchPattern = query ? `%${query}%` : null;
+    const tagFilter = tags && tags.length > 0 ? tags : null;
+    const tagCount = tagFilter ? tagFilter.length : 0;
+
+    const countResult = await sql<{ count: string }[]>`
+        SELECT COUNT(DISTINCT t.transaction_id)::text AS count
         FROM transaction t
         JOIN transaction_breakdown tb ON tb.transaction_id = t.transaction_id
@@ -260,55 +322,4 @@
                 ) = ${tagCount}
             )
-        GROUP BY t.transaction_id
-        ORDER BY t.date DESC
-        LIMIT ${HISTORY_ITEMS_PER_PAGE}
-        OFFSET ${offset}
-    `;
-
-    return rows;
-}
-
-export async function getHistoryTransactionPages(params: {
-    userId: number;
-    accountId?: number;
-    query?: string;
-    tags?: string[];
-}) {
-    const { userId, accountId, query, tags } = params;
-    const searchPattern = query ? `%${query}%` : null;
-    const tagFilter = tags && tags.length > 0 ? tags : null;
-    const tagCount = tagFilter ? tagFilter.length : 0;
-
-    const countResult = await sql<{ count: string }[]>`
-        SELECT COUNT(DISTINCT t.transaction_id)::text AS count
-        FROM transaction t
-        JOIN transaction_breakdown tb ON tb.transaction_id = t.transaction_id
-        JOIN transaction_account ta ON ta.transaction_account_id = tb.transaction_account_id
-        LEFT JOIN tag_assigned_to_transaction tat ON tat.transaction_id = t.transaction_id
-        LEFT JOIN tag tg ON tg.tag_id = tat.tag_id
-        WHERE ta.user_id = ${userId}
-            AND (${accountId ?? null}::int IS NULL OR tb.transaction_account_id = ${accountId ?? null})
-            AND (
-                ${searchPattern}::text IS NULL
-                OR t.transaction_name ILIKE ${searchPattern}
-                OR ta.account_name ILIKE ${searchPattern}
-                OR EXISTS (
-                    SELECT 1
-                    FROM tag_assigned_to_transaction tat2
-                    JOIN tag tg2 ON tg2.tag_id = tat2.tag_id
-                    WHERE tat2.transaction_id = t.transaction_id
-                        AND tg2.tag_name ILIKE ${searchPattern}
-                )
-            )
-            AND (
-                ${tagCount}::int = 0
-                OR (
-                    SELECT COUNT(DISTINCT tg_f.tag_name)
-                    FROM tag_assigned_to_transaction tat_f
-                    JOIN tag tg_f ON tg_f.tag_id = tat_f.tag_id
-                    WHERE tat_f.transaction_id = t.transaction_id
-                        AND tg_f.tag_name = ANY(${tagFilter ?? []}::text[])
-                ) = ${tagCount}
-            )
     `;
 
