diff --git a/src/app/listings/ListingsPage.tsx b/src/app/listings/ListingsPage.tsx
index 5622121bc..fe49b51e1 100644
--- a/src/app/listings/ListingsPage.tsx
+++ b/src/app/listings/ListingsPage.tsx
@@ -40,6 +40,11 @@ import { api } from '@/lib/api'
 import { cn } from '@/lib/utils'
 import { type RouterInput } from '@/types/trpc'
 import { filterNullAndEmpty } from '@/utils/filter'
+import {
+  isAnchorNavigationTarget,
+  openInNewTab,
+  shouldOpenInNewTab,
+} from '@/utils/navigation-events'
 import { roleIncludesRole } from '@/utils/permission-system'
 import { hasRolePermission } from '@/utils/permissions'
 import { ms } from '@/utils/time'
@@ -516,149 +521,171 @@ function ListingsPage() {
                     listingsQuery.isFetching && 'opacity-50',
                   )}
                 >
-                  {listingsQuery.data?.listings.map((listing) => (
-                    <tr
-                      key={listing.id}
-                      className="hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors"
-                      onClick={() => router.push(`/listings/${listing.id}`)}
-                    >
-                      {columnVisibility.isColumnVisible('game') && (
-                        <td className="px-4 py-2 font-medium text-gray-900 dark:text-gray-100">
-                          <div className="flex items-center gap-2">
-                            <Tooltip>
-                              <TooltipTrigger asChild>
-                                <Link
-                                  href={`/listings/${listing.id}`}
-                                  className="hover:text-blue-600 dark:hover:text-blue-400"
-                                >
-                                  {listing.game.title.substring(0, 30)}
-                                  {listing.game.title.length > 30 && '...'}
-                                </Link>
-                              </TooltipTrigger>
-                              <TooltipContent side="top">{listing.game.title}</TooltipContent>
-                            </Tooltip>
-
-                            {listing.status === ApprovalStatus.PENDING && (
+                  {listingsQuery.data?.listings.map((listing) => {
+                    const listingHref = `/listings/${listing.id}`
+
+                    return (
+                      <tr
+                        key={listing.id}
+                        className="hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors"
+                        onClick={(event) => {
+                          if (isAnchorNavigationTarget(event)) return
+
+                          if (shouldOpenInNewTab(event)) {
+                            event.preventDefault()
+                            openInNewTab(listingHref)
+                            return
+                          }
+
+                          router.push(listingHref)
+                        }}
+                        onAuxClick={(event) => {
+                          if (isAnchorNavigationTarget(event) || !shouldOpenInNewTab(event)) return
+
+                          event.preventDefault()
+                          openInNewTab(listingHref)
+                        }}
+                      >
+                        {columnVisibility.isColumnVisible('game') && (
+                          <td className="px-4 py-2 font-medium text-gray-900 dark:text-gray-100">
+                            <div className="flex items-center gap-2">
                               <Tooltip>
-                                <TooltipTrigger>
-                                  <Clock className="w-4 h-4 text-amber-600 dark:text-amber-400" />
+                                <TooltipTrigger asChild>
+                                  <Link
+                                    href={`/listings/${listing.id}`}
+                                    className="hover:text-blue-600 dark:hover:text-blue-400"
+                                  >
+                                    {listing.game.title.substring(0, 30)}
+                                    {listing.game.title.length > 30 && '...'}
+                                  </Link>
                                 </TooltipTrigger>
-                                <TooltipContent>Under Review</TooltipContent>
+                                <TooltipContent side="top">{listing.game.title}</TooltipContent>
                               </Tooltip>
-                            )}
 
-                            <BannedUserBadge
-                              author={listing.author}
-                              canView={isModerator}
-                              label="BANNED"
-                              tooltip="This user has been banned"
-                            />
+                              {listing.status === ApprovalStatus.PENDING && (
+                                <Tooltip>
+                                  <TooltipTrigger>
+                                    <Clock className="w-4 h-4 text-amber-600 dark:text-amber-400" />
+                                  </TooltipTrigger>
+                                  <TooltipContent>Under Review</TooltipContent>
+                                </Tooltip>
+                              )}
+
+                              <BannedUserBadge
+                                author={listing.author}
+                                canView={isModerator}
+                                label="BANNED"
+                                tooltip="This user has been banned"
+                              />
 
-                            {listing.developerVerifications &&
-                              listing.developerVerifications.length > 0 && (
-                                <ListingVerificationBadge
-                                  verifications={listing.developerVerifications}
+                              {listing.developerVerifications &&
+                                listing.developerVerifications.length > 0 && (
+                                  <ListingVerificationBadge
+                                    verifications={listing.developerVerifications}
+                                    size="sm"
+                                    showTooltip={true}
+                                  />
+                                )}
+                            </div>
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('system') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {isSystemIconsHydrated &&
+                            showSystemIcons &&
+                            listing.game.system?.key ? (
+                              <div className="flex items-center gap-2">
+                                <SystemIcon
+                                  name={listing.game.system.name}
+                                  systemKey={listing.game.system.key}
                                   size="sm"
-                                  showTooltip={true}
                                 />
-                              )}
-                          </div>
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('system') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {isSystemIconsHydrated && showSystemIcons && listing.game.system?.key ? (
+                              </div>
+                            ) : (
+                              (listing.game.system?.name ?? 'Unknown')
+                            )}
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('device') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {listing.device
+                              ? `${listing.device.brand.name} ${listing.device.modelName}`
+                              : 'N/A'}
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('emulator') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
                             <div className="flex items-center gap-2">
-                              <SystemIcon
-                                name={listing.game.system.name}
-                                systemKey={listing.game.system.key}
-                                size="sm"
-                              />
+                              {listing.emulator ? (
+                                <EmulatorIcon
+                                  name={listing.emulator.name}
+                                  logo={listing.emulator.logo}
+                                  showLogo={isEmulatorLogosHydrated && showEmulatorLogos}
+                                  size="sm"
+                                />
+                              ) : (
+                                'N/A'
+                              )}
+                              {listing.isVerifiedDeveloper && <VerifiedDeveloperBadge size="sm" />}
                             </div>
-                          ) : (
-                            (listing.game.system?.name ?? 'Unknown')
-                          )}
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('device') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {listing.device
-                            ? `${listing.device.brand.name} ${listing.device.modelName}`
-                            : 'N/A'}
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('emulator') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          <div className="flex items-center gap-2">
-                            {listing.emulator ? (
-                              <EmulatorIcon
-                                name={listing.emulator.name}
-                                logo={listing.emulator.logo}
-                                showLogo={isEmulatorLogosHydrated && showEmulatorLogos}
-                                size="sm"
-                              />
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('performance') && (
+                          <td className="px-4 py-2">
+                            <PerformanceBadge
+                              rank={listing.performance?.rank ?? 8}
+                              label={listing.performance?.label ?? 'N/A'}
+                              description={listing.performance?.description}
+                            />
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('successRate') && (
+                          <td className="px-4 py-2">
+                            <SuccessRateBar
+                              rate={listing.successRate * 100}
+                              voteCount={listing._count.votes}
+                            />
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('author') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {listing.author?.id ? (
+                              <Link
+                                href={`/users/${listing.author.id}`}
+                                className="text-blue-600 dark:text-indigo-400 hover:underline"
+                                onClick={(event) => event.stopPropagation()}
+                              >
+                                {listing.author.name ?? 'Anonymous'}
+                              </Link>
                             ) : (
-                              'N/A'
+                              <span>{listing.author?.name ?? 'Anonymous'}</span>
                             )}
-                            {listing.isVerifiedDeveloper && <VerifiedDeveloperBadge size="sm" />}
-                          </div>
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('performance') && (
-                        <td className="px-4 py-2">
-                          <PerformanceBadge
-                            rank={listing.performance?.rank ?? 8}
-                            label={listing.performance?.label ?? 'N/A'}
-                            description={listing.performance?.description}
-                          />
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('successRate') && (
-                        <td className="px-4 py-2">
-                          <SuccessRateBar
-                            rate={listing.successRate * 100}
-                            voteCount={listing._count.votes}
-                          />
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('author') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {listing.author?.id ? (
-                            <Link
-                              href={`/users/${listing.author.id}`}
-                              className="text-blue-600 dark:text-indigo-400 hover:underline"
-                              onClick={(event) => event.stopPropagation()}
-                            >
-                              {listing.author.name ?? 'Anonymous'}
-                            </Link>
-                          ) : (
-                            <span>{listing.author?.name ?? 'Anonymous'}</span>
-                          )}
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('posted') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          <LocalizedDate date={listing.createdAt} format="timeAgo" />
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('actions') && (
-                        <td className="px-6 py-4 text-right" onClick={(e) => e.stopPropagation()}>
-                          <div className="flex items-center justify-end gap-2">
-                            {isAdmin && (
-                              <EditButton
-                                href={`/admin/listings/${listing.id}/edit`}
-                                title="Edit Report"
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('posted') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            <LocalizedDate date={listing.createdAt} format="timeAgo" />
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('actions') && (
+                          <td className="px-6 py-4 text-right" onClick={(e) => e.stopPropagation()}>
+                            <div className="flex items-center justify-end gap-2">
+                              {isAdmin && (
+                                <EditButton
+                                  href={`/admin/listings/${listing.id}/edit`}
+                                  title="Edit Report"
+                                />
+                              )}
+                              <ViewButton
+                                href={`/listings/${listing.id}`}
+                                title="View Report Details"
                               />
-                            )}
-                            <ViewButton
-                              href={`/listings/${listing.id}`}
-                              title="View Report Details"
-                            />
-                          </div>
-                        </td>
-                      )}
-                    </tr>
-                  ))}
+                            </div>
+                          </td>
+                        )}
+                      </tr>
+                    )
+                  })}
                 </tbody>
               )}
             </table>
diff --git a/src/app/pc-listings/PcListingsPage.tsx b/src/app/pc-listings/PcListingsPage.tsx
index f1e47f637..d1fbaf329 100644
--- a/src/app/pc-listings/PcListingsPage.tsx
+++ b/src/app/pc-listings/PcListingsPage.tsx
@@ -42,6 +42,11 @@ import { api } from '@/lib/api'
 import { cn } from '@/lib/utils'
 import { type RouterInput } from '@/types/trpc'
 import { filterNullAndEmpty } from '@/utils/filter'
+import {
+  isAnchorNavigationTarget,
+  openInNewTab,
+  shouldOpenInNewTab,
+} from '@/utils/navigation-events'
 import { roleIncludesRole } from '@/utils/permission-system'
 import { hasRolePermission } from '@/utils/permissions'
 import { Role, ApprovalStatus } from '@orm'
@@ -454,154 +459,178 @@ function PcListingsPage() {
                     listingsQuery.isFetching && 'opacity-50',
                   )}
                 >
-                  {listingsQuery.data?.pcListings.map((listing) => (
-                    <tr
-                      key={listing.id}
-                      className="hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors"
-                      onClick={() => router.push(`/pc-listings/${listing.id}`)}
-                    >
-                      {columnVisibility.isColumnVisible('game') && (
-                        <td className="px-4 py-2 font-medium text-gray-900 dark:text-gray-100">
-                          <div className="flex items-center gap-2">
-                            <Tooltip>
-                              <TooltipTrigger asChild>
-                                <Link
-                                  href={`/pc-listings/${listing.id}`}
-                                  className="hover:text-blue-600 dark:hover:text-blue-400"
-                                >
-                                  {listing.game.title.substring(0, 30)}
-                                  {listing.game.title.length > 30 && '...'}
-                                </Link>
-                              </TooltipTrigger>
-                              <TooltipContent side="top">{listing.game.title}</TooltipContent>
-                            </Tooltip>
-
-                            {listing.status === ApprovalStatus.PENDING && (
+                  {listingsQuery.data?.pcListings.map((listing) => {
+                    const listingHref = `/pc-listings/${listing.id}`
+
+                    return (
+                      <tr
+                        key={listing.id}
+                        className="hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors"
+                        onClick={(event) => {
+                          if (isAnchorNavigationTarget(event)) return
+
+                          if (shouldOpenInNewTab(event)) {
+                            event.preventDefault()
+                            openInNewTab(listingHref)
+                            return
+                          }
+
+                          router.push(listingHref)
+                        }}
+                        onAuxClick={(event) => {
+                          if (isAnchorNavigationTarget(event) || !shouldOpenInNewTab(event)) return
+
+                          event.preventDefault()
+                          openInNewTab(listingHref)
+                        }}
+                      >
+                        {columnVisibility.isColumnVisible('game') && (
+                          <td className="px-4 py-2 font-medium text-gray-900 dark:text-gray-100">
+                            <div className="flex items-center gap-2">
                               <Tooltip>
-                                <TooltipTrigger>
-                                  <Clock className="w-4 h-4 text-amber-600 dark:text-amber-400" />
+                                <TooltipTrigger asChild>
+                                  <Link
+                                    href={`/pc-listings/${listing.id}`}
+                                    className="hover:text-blue-600 dark:hover:text-blue-400"
+                                  >
+                                    {listing.game.title.substring(0, 30)}
+                                    {listing.game.title.length > 30 && '...'}
+                                  </Link>
                                 </TooltipTrigger>
-                                <TooltipContent>Under Review</TooltipContent>
+                                <TooltipContent side="top">{listing.game.title}</TooltipContent>
                               </Tooltip>
-                            )}
 
-                            <BannedUserBadge
-                              author={listing.author}
-                              canView={isModerator}
-                              label="BANNED"
-                              tooltip="This user has been banned"
-                            />
-                          </div>
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('system') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {isSystemIconsHydrated && showSystemIcons && listing.game.system?.key ? (
-                            <div className="flex items-center gap-2">
-                              <SystemIcon
-                                name={listing.game.system.name}
-                                systemKey={listing.game.system.key}
-                                size="sm"
+                              {listing.status === ApprovalStatus.PENDING && (
+                                <Tooltip>
+                                  <TooltipTrigger>
+                                    <Clock className="w-4 h-4 text-amber-600 dark:text-amber-400" />
+                                  </TooltipTrigger>
+                                  <TooltipContent>Under Review</TooltipContent>
+                                </Tooltip>
+                              )}
+
+                              <BannedUserBadge
+                                author={listing.author}
+                                canView={isModerator}
+                                label="BANNED"
+                                tooltip="This user has been banned"
                               />
                             </div>
-                          ) : (
-                            (listing.game.system?.name ?? 'Unknown')
-                          )}
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('cpu') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {listing.cpu
-                            ? `${listing.cpu.brand.name} ${listing.cpu.modelName}`
-                            : 'N/A'}
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('gpu') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {listing.gpu
-                            ? `${listing.gpu.brand.name} ${listing.gpu.modelName}`
-                            : 'Integrated'}
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('memory') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {listing.memorySize}GB
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('os') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">{listing.os}</td>
-                      )}
-                      {columnVisibility.isColumnVisible('emulator') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          <div className="flex items-center gap-2">
-                            {listing.emulator ? (
-                              <EmulatorIcon
-                                name={listing.emulator.name}
-                                logo={listing.emulator.logo}
-                                showLogo={isEmulatorLogosHydrated && showEmulatorLogos}
-                                size="sm"
-                              />
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('system') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {isSystemIconsHydrated &&
+                            showSystemIcons &&
+                            listing.game.system?.key ? (
+                              <div className="flex items-center gap-2">
+                                <SystemIcon
+                                  name={listing.game.system.name}
+                                  systemKey={listing.game.system.key}
+                                  size="sm"
+                                />
+                              </div>
                             ) : (
-                              'N/A'
-                            )}
-                          </div>
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('performance') && (
-                        <td className="px-4 py-2">
-                          <PerformanceBadge
-                            rank={listing.performance?.rank ?? 8}
-                            label={listing.performance?.label ?? 'N/A'}
-                            description={listing.performance?.description}
-                          />
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('verified') && (
-                        <td className="px-4 py-2">
-                          <SuccessRateBar
-                            rate={listing.successRate * 100}
-                            voteCount={listing._count.votes}
-                          />
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('author') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          {listing.author?.id ? (
-                            <Link
-                              href={`/users/${listing.author.id}`}
-                              className="text-blue-600 dark:text-indigo-400 hover:underline"
-                              onClick={(event) => event.stopPropagation()}
-                            >
-                              {listing.author.name ?? 'Anonymous'}
-                            </Link>
-                          ) : (
-                            <span>{listing.author?.name ?? 'Anonymous'}</span>
-                          )}
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('posted') && (
-                        <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
-                          <LocalizedDate date={listing.createdAt} format="timeAgo" />
-                        </td>
-                      )}
-                      {columnVisibility.isColumnVisible('actions') && (
-                        <td className="px-6 py-4 text-right" onClick={(e) => e.stopPropagation()}>
-                          <div className="flex items-center justify-end gap-2">
-                            {isAdmin && (
-                              <EditButton
-                                href={`/admin/pc-listings/${listing.id}/edit`}
-                                title="Edit PC Report"
-                              />
+                              (listing.game.system?.name ?? 'Unknown')
                             )}
-                            <ViewButton
-                              href={`/pc-listings/${listing.id}`}
-                              title="View PC Report Details"
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('cpu') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {listing.cpu
+                              ? `${listing.cpu.brand.name} ${listing.cpu.modelName}`
+                              : 'N/A'}
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('gpu') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {listing.gpu
+                              ? `${listing.gpu.brand.name} ${listing.gpu.modelName}`
+                              : 'Integrated'}
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('memory') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {listing.memorySize}GB
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('os') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {listing.os}
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('emulator') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            <div className="flex items-center gap-2">
+                              {listing.emulator ? (
+                                <EmulatorIcon
+                                  name={listing.emulator.name}
+                                  logo={listing.emulator.logo}
+                                  showLogo={isEmulatorLogosHydrated && showEmulatorLogos}
+                                  size="sm"
+                                />
+                              ) : (
+                                'N/A'
+                              )}
+                            </div>
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('performance') && (
+                          <td className="px-4 py-2">
+                            <PerformanceBadge
+                              rank={listing.performance?.rank ?? 8}
+                              label={listing.performance?.label ?? 'N/A'}
+                              description={listing.performance?.description}
                             />
-                          </div>
-                        </td>
-                      )}
-                    </tr>
-                  ))}
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('verified') && (
+                          <td className="px-4 py-2">
+                            <SuccessRateBar
+                              rate={listing.successRate * 100}
+                              voteCount={listing._count.votes}
+                            />
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('author') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            {listing.author?.id ? (
+                              <Link
+                                href={`/users/${listing.author.id}`}
+                                className="text-blue-600 dark:text-indigo-400 hover:underline"
+                                onClick={(event) => event.stopPropagation()}
+                              >
+                                {listing.author.name ?? 'Anonymous'}
+                              </Link>
+                            ) : (
+                              <span>{listing.author?.name ?? 'Anonymous'}</span>
+                            )}
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('posted') && (
+                          <td className="px-4 py-2 text-gray-700 dark:text-gray-300">
+                            <LocalizedDate date={listing.createdAt} format="timeAgo" />
+                          </td>
+                        )}
+                        {columnVisibility.isColumnVisible('actions') && (
+                          <td className="px-6 py-4 text-right" onClick={(e) => e.stopPropagation()}>
+                            <div className="flex items-center justify-end gap-2">
+                              {isAdmin && (
+                                <EditButton
+                                  href={`/admin/pc-listings/${listing.id}/edit`}
+                                  title="Edit PC Report"
+                                />
+                              )}
+                              <ViewButton
+                                href={`/pc-listings/${listing.id}`}
+                                title="View PC Report Details"
+                              />
+                            </div>
+                          </td>
+                        )}
+                      </tr>
+                    )
+                  })}
                 </tbody>
               )}
             </table>
diff --git a/src/app/v2/listings/components/ListingCard.tsx b/src/app/v2/listings/components/ListingCard.tsx
index 5d9d60ec7..b820e6a9f 100644
--- a/src/app/v2/listings/components/ListingCard.tsx
+++ b/src/app/v2/listings/components/ListingCard.tsx
@@ -16,6 +16,11 @@ import {
 } from '@/components/ui'
 import { cn } from '@/lib/utils'
 import getGameImageUrl from '@/utils/images/getGameImageUrl'
+import {
+  isAnchorNavigationTarget,
+  openInNewTab,
+  shouldOpenInNewTab,
+} from '@/utils/navigation-events'
 import { ApprovalStatus } from '@orm'
 import type { RouterOutput } from '@/types/trpc'
 
@@ -38,6 +43,8 @@ export function ListingCard({
 }: Props) {
   const router = useRouter()
   const [isLiked, setIsLiked] = useState(false)
+  const listingHref = `/listings/${listing.id}`
+  const gameHref = `/games/${listing.game.id}`
 
   const handleLike = () => {
     setIsLiked(!isLiked)
@@ -54,7 +61,33 @@ export function ListingCard({
 
   const navigateToGame = (ev: MouseEvent) => {
     ev.stopPropagation()
-    router.push(`/games/${listing.game.id}`)
+
+    if (shouldOpenInNewTab(ev)) {
+      ev.preventDefault()
+      openInNewTab(gameHref)
+      return
+    }
+
+    router.push(gameHref)
+  }
+
+  const navigateToListing = (ev: MouseEvent) => {
+    if (isAnchorNavigationTarget(ev)) return
+
+    if (shouldOpenInNewTab(ev)) {
+      ev.preventDefault()
+      openInNewTab(listingHref)
+      return
+    }
+
+    router.push(listingHref)
+  }
+
+  const openListingFromAuxClick = (ev: MouseEvent) => {
+    if (isAnchorNavigationTarget(ev) || !shouldOpenInNewTab(ev)) return
+
+    ev.preventDefault()
+    openInNewTab(listingHref)
   }
 
   // Get game cover image or placeholder
@@ -76,7 +109,8 @@ export function ListingCard({
     <SwipeableCard
       onSwipeLeft={handleComment}
       onSwipeRight={handleLike}
-      onClick={() => router.push(`/listings/${listing.id}`)}
+      onClick={navigateToListing}
+      onAuxClick={openListingFromAuxClick}
       className={cn(
         'bg-white dark:bg-gray-800 rounded-2xl border border-gray-200 dark:border-gray-700 overflow-hidden transition-all duration-300 group cursor-pointer',
         'hover:shadow-2xl hover:shadow-gray-200/50 dark:hover:shadow-gray-900/50',
@@ -139,6 +173,7 @@ export function ListingCard({
               variant="ghost"
               size="sm"
               onClick={navigateToGame}
+              onAuxClick={navigateToGame}
               className="absolute top-3 left-3 opacity-0 group-hover:opacity-100 transition-opacity bg-white/90 hover:bg-white text-gray-900 shadow-lg"
               aria-label={`View game: ${listing.game.title}`}
             >
diff --git a/src/components/ui/SwipeableCard.test.tsx b/src/components/ui/SwipeableCard.test.tsx
new file mode 100644
index 000000000..d85c470c9
--- /dev/null
+++ b/src/components/ui/SwipeableCard.test.tsx
@@ -0,0 +1,33 @@
+import { fireEvent, render, screen } from '@testing-library/react'
+import { describe, expect, it, vi } from 'vitest'
+import { SwipeableCard } from './SwipeableCard'
+import type { MouseEvent } from 'react'
+
+describe('SwipeableCard', () => {
+  it('passes click events to the click handler', () => {
+    const handleClick = vi.fn((event: MouseEvent) => {
+      expect(event.ctrlKey).toBe(true)
+    })
+
+    render(<SwipeableCard onClick={handleClick}>Open report</SwipeableCard>)
+
+    fireEvent.click(screen.getByText('Open report'), { ctrlKey: true })
+
+    expect(handleClick).toHaveBeenCalledTimes(1)
+  })
+
+  it('passes middle-click events to the auxiliary click handler', () => {
+    const handleAuxClick = vi.fn((event: MouseEvent) => {
+      expect(event.button).toBe(1)
+    })
+
+    render(<SwipeableCard onAuxClick={handleAuxClick}>Open report</SwipeableCard>)
+
+    fireEvent(
+      screen.getByText('Open report'),
+      new MouseEvent('auxclick', { bubbles: true, button: 1 }),
+    )
+
+    expect(handleAuxClick).toHaveBeenCalledTimes(1)
+  })
+})
diff --git a/src/components/ui/SwipeableCard.tsx b/src/components/ui/SwipeableCard.tsx
index 84cf78e1a..fe0c22ece 100644
--- a/src/components/ui/SwipeableCard.tsx
+++ b/src/components/ui/SwipeableCard.tsx
@@ -1,14 +1,15 @@
 'use client'
 
 import { motion, useMotionValue, useTransform } from 'framer-motion'
-import { type PropsWithChildren, useState } from 'react'
+import { type PropsWithChildren, type MouseEvent, useState } from 'react'
 import { cn } from '@/lib/utils'
 import type { PanInfo } from 'framer-motion'
 
 interface Props extends PropsWithChildren {
   onSwipeLeft?: () => void
   onSwipeRight?: () => void
-  onClick?: () => void
+  onClick?: (e: MouseEvent) => void
+  onAuxClick?: (e: MouseEvent) => void
   className?: string
   swipeThreshold?: number
   enableHaptics?: boolean
@@ -21,40 +22,36 @@ export function SwipeableCard(props: Props) {
   const [isSwiping, setIsSwiping] = useState(false)
   const x = useMotionValue(0)
 
-  // Transform the card's opacity and rotation based on the swipe distance
   const opacity = useTransform(x, [-swipeThreshold * 2, 0, swipeThreshold * 2], [0.5, 1, 0.5])
 
   const rotate = useTransform(x, [-swipeThreshold * 2, 0, swipeThreshold * 2], [-8, 0, 8])
 
-  // Handle drag end
   const handleDragEnd = (_event: unknown, _info: PanInfo) => {
     const xOffset = x.get()
 
-    // Reset position
     x.set(0)
 
-    // If the card was swiped far enough, trigger the appropriate callback
     if (xOffset < -swipeThreshold && props.onSwipeLeft) {
       props.onSwipeLeft()
 
-      // Trigger haptic feedback if available
       if (enableHaptics && navigator.vibrate) {
         navigator.vibrate(50)
       }
     } else if (xOffset > swipeThreshold && props.onSwipeRight) {
       props.onSwipeRight()
 
-      // Trigger haptic feedback if available
       if (enableHaptics && navigator.vibrate) navigator.vibrate(50)
     }
 
     setIsSwiping(false)
   }
 
-  // Handle click
-  const handleClick = () => {
-    // Only trigger click if we're not swiping
-    if (!isSwiping && props.onClick) props.onClick()
+  const handleClick = (e: MouseEvent) => {
+    if (!isSwiping && props.onClick) props.onClick(e)
+  }
+
+  const handleAuxClick = (e: MouseEvent) => {
+    if (!isSwiping && props.onAuxClick) props.onAuxClick(e)
   }
 
   return (
@@ -72,6 +69,7 @@ export function SwipeableCard(props: Props) {
       onDragStart={() => setIsSwiping(true)}
       onDragEnd={handleDragEnd}
       onClick={handleClick}
+      onAuxClick={handleAuxClick}
       whileTap={{ scale: isSwiping ? 1 : 0.98 }}
     >
       {props.children}
diff --git a/src/utils/navigation-events.test.ts b/src/utils/navigation-events.test.ts
new file mode 100644
index 000000000..5880a1093
--- /dev/null
+++ b/src/utils/navigation-events.test.ts
@@ -0,0 +1,61 @@
+import { afterEach, describe, expect, it, vi } from 'vitest'
+import {
+  isAnchorNavigationTarget,
+  openInNewTab,
+  shouldOpenInNewTab,
+  type NavigationClickEvent,
+} from './navigation-events'
+
+function createNavigationEvent(
+  overrides: Partial<NavigationClickEvent> = {},
+): NavigationClickEvent {
+  return {
+    button: 0,
+    ctrlKey: false,
+    metaKey: false,
+    shiftKey: false,
+    target: document.createElement('div'),
+    ...overrides,
+  }
+}
+
+describe('navigation-events', () => {
+  afterEach(() => {
+    vi.restoreAllMocks()
+  })
+
+  it('does not request a new tab for a normal primary click', () => {
+    expect(shouldOpenInNewTab(createNavigationEvent())).toBe(false)
+  })
+
+  it.each([
+    ['Ctrl-click', { ctrlKey: true }],
+    ['Cmd-click', { metaKey: true }],
+    ['Shift-click', { shiftKey: true }],
+    ['middle-click', { button: 1 }],
+  ])('requests a new tab for %s', (_label, overrides) => {
+    expect(shouldOpenInNewTab(createNavigationEvent(overrides))).toBe(true)
+  })
+
+  it('detects clicks from inside anchor elements', () => {
+    const anchor = document.createElement('a')
+    anchor.href = '/listings/123'
+
+    const child = document.createElement('span')
+    anchor.appendChild(child)
+
+    expect(isAnchorNavigationTarget(createNavigationEvent({ target: child }))).toBe(true)
+  })
+
+  it('does not treat non-anchor targets as anchor navigation', () => {
+    expect(isAnchorNavigationTarget(createNavigationEvent())).toBe(false)
+  })
+
+  it('opens URLs in a new tab without passing opener access', () => {
+    const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null)
+
+    openInNewTab('/listings/123')
+
+    expect(openSpy).toHaveBeenCalledWith('/listings/123', '_blank', 'noopener,noreferrer')
+  })
+})
diff --git a/src/utils/navigation-events.ts b/src/utils/navigation-events.ts
new file mode 100644
index 000000000..6b2e04fb0
--- /dev/null
+++ b/src/utils/navigation-events.ts
@@ -0,0 +1,23 @@
+export interface NavigationClickEvent {
+  button: number
+  ctrlKey: boolean
+  metaKey: boolean
+  shiftKey: boolean
+  target: EventTarget | null
+}
+
+export function shouldOpenInNewTab(event: NavigationClickEvent): boolean {
+  return event.button === 1 || event.ctrlKey || event.metaKey || event.shiftKey
+}
+
+export function isAnchorNavigationTarget(event: NavigationClickEvent): boolean {
+  if (typeof Element === 'undefined' || !(event.target instanceof Element)) {
+    return false
+  }
+
+  return event.target.closest('a[href]') !== null
+}
+
+export function openInNewTab(href: string): void {
+  window.open(href, '_blank', 'noopener,noreferrer')
+}
