diff --git a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx
index 523f76f..004f948 100644
--- a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx
+++ b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx
@@ -7,6 +7,8 @@ import {
countPosts,
resolvePosters,
getUserPostCount,
+ getAccountCharactersForForum,
+ getForumCharacterPick,
} from '@/lib/forum'
import { formatForumDate } from '@/lib/forum-format'
import { localizeWowheadLinks } from '@/lib/forum-wowhead'
@@ -17,6 +19,7 @@ import { PageShell } from '@/components/PageShell'
import { ForumBreadcrumb } from '@/components/ForumBreadcrumb'
import { Pagination } from '@/components/Pagination'
import { ReplyForm } from '@/components/ReplyForm'
+import { ForumCharacterPicker } from '@/components/ForumCharacterPicker'
import { EditPostForm } from '@/components/EditPostForm'
import { ForumModActions } from '@/components/ForumModActions'
import { WowheadRefresh } from '@/components/WowheadRefresh'
@@ -58,6 +61,10 @@ export default async function TopicPage({
await Promise.all(uniquePosters.map(async (pid) => [pid, await getUserPostCount(pid)] as const)),
)
+ const [forumChars, forumPick] = session.accountId
+ ? await Promise.all([getAccountCharactersForForum(session.accountId), getForumCharacterPick(session.accountId)])
+ : [[], null]
+
const path = await getTopicPath(id, locale)
const canReply = Boolean(session.username) && (!topic.locked || isMod)
@@ -199,7 +206,22 @@ export default async function TopicPage({
{canReply ? (
page === totalPages ? (
-
{t('replyOnLastPage')}
diff --git a/web-next/app/api/forum/character/route.ts b/web-next/app/api/forum/character/route.ts
new file mode 100644
index 0000000..3c0984a
--- /dev/null
+++ b/web-next/app/api/forum/character/route.ts
@@ -0,0 +1,34 @@
+import { type NextRequest, NextResponse } from 'next/server'
+import { getSession } from '@/lib/session'
+import { getAccountCharactersForForum, getForumCharacterPick, setForumCharacterPick } from '@/lib/forum'
+
+export const runtime = 'nodejs'
+export const dynamic = 'force-dynamic'
+
+/** Lista de personajes de la cuenta + el fijado actualmente. */
+export async function GET() {
+ const session = await getSession()
+ const accountId = session.accountId ?? 0
+ if (!accountId) return NextResponse.json({ characters: [], current: null }, { status: 401 })
+ const [characters, current] = await Promise.all([
+ getAccountCharactersForForum(accountId),
+ getForumCharacterPick(accountId),
+ ])
+ return NextResponse.json({ characters, current })
+}
+
+/** Fija el personaje del foro para la cuenta en sesión. */
+export async function POST(req: NextRequest) {
+ const session = await getSession()
+ const accountId = session.accountId ?? 0
+ if (!accountId) return NextResponse.json({ ok: false }, { status: 401 })
+ let guid = 0
+ try {
+ const body = await req.json()
+ guid = Number(body?.guid) || 0
+ } catch {
+ /* body inválido */
+ }
+ const ok = await setForumCharacterPick(accountId, guid)
+ return NextResponse.json({ ok }, { status: ok ? 200 : 400 })
+}
diff --git a/web-next/app/forum.css b/web-next/app/forum.css
index 5120585..eec4724 100644
--- a/web-next/app/forum.css
+++ b/web-next/app/forum.css
@@ -298,3 +298,43 @@ a.nice_button:focus {
/* Nombre de hermandad junto al personaje en el foro */
.username_guild { color: #c8a24c; font-weight: 400; font-size: .8em; }
+
+/* ===== Selector de personaje del foro ===== */
+.forum-charpick { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
+ background: #17140f; border: 1px solid #2b2620; border-radius: 8px; padding: 10px 14px; }
+.forum-charpick-as { color: #9a948a; font-size: 13px; }
+.forum-charpick-as b { font-weight: 700; }
+.forum-charpick-auto { color: #b8b0a2 !important; font-weight: 600; }
+.forum-charpick-btn { display: inline-flex; align-items: center; gap: 7px; background: #241f19;
+ border: 1px solid #3a342b; color: #e6ddc9; border-radius: 6px; padding: 7px 13px; cursor: pointer;
+ font-family: inherit; font-size: 13px; transition: border-color .15s, color .15s; }
+.forum-charpick-btn:hover { border-color: #c8a24c; color: #fff; }
+.forum-charpick-btn > i { color: #c8a24c; }
+
+.forum-charpick-overlay { position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,.65);
+ display: flex; align-items: center; justify-content: center; padding: 20px; }
+.forum-charpick-modal { width: 100%; max-width: 460px; max-height: 80vh; display: flex; flex-direction: column;
+ background: #14110c; border: 1px solid #c8a24c; border-radius: 12px; box-shadow: 0 12px 40px rgba(0,0,0,.6); overflow: hidden; }
+.forum-charpick-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px;
+ border-bottom: 1px solid #2b2620; }
+.forum-charpick-head h3 { margin: 0; font-size: 18px; font-weight: 800; color: #e6b53c; }
+.forum-charpick-close { background: #241f19; border: 1px solid #3a342b; color: #d9c9a0; width: 32px; height: 32px;
+ border-radius: 6px; cursor: pointer; display: flex; align-items: center; justify-content: center; }
+.forum-charpick-close:hover { border-color: #c8a24c; color: #fff; }
+.forum-charpick-search { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid #201c16; }
+.forum-charpick-search > i { color: #7d7568; }
+.forum-charpick-search input { flex: 1; background: #17140f; border: 1px solid #3a342b; color: #e6ddc9;
+ border-radius: 6px; padding: 8px 10px; font-family: inherit; font-size: 14px; }
+.forum-charpick-search input:focus { outline: none; border-color: #c8a24c; }
+.forum-charpick-list { overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 6px; }
+.forum-charpick-empty { color: #8a847a; text-align: center; padding: 20px; margin: 0; }
+.forum-charpick-item { display: flex; align-items: center; gap: 12px; background: #17140f; border: 1px solid #2b2620;
+ border-radius: 8px; padding: 8px 10px; cursor: pointer; font-family: inherit; text-align: left; width: 100%;
+ transition: border-color .15s, background .15s; }
+.forum-charpick-item:hover { border-color: #c8a24c; background: #1e1a13; }
+.forum-charpick-item.active { border-color: #c8a24c; background: #241f19; }
+.forum-charpick-ava { width: 48px; height: 48px; border-radius: 8px; border: 1px solid #3a342b; flex: 0 0 auto; }
+.forum-charpick-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
+.forum-charpick-name { font-weight: 700; font-size: 15px; }
+.forum-charpick-sub { color: #9a948a; font-size: 12px; }
+.forum-charpick-chk { color: #4ade5f; margin-left: auto; }
diff --git a/web-next/components/ForumCharacterPicker.tsx b/web-next/components/ForumCharacterPicker.tsx
new file mode 100644
index 0000000..cb2e730
--- /dev/null
+++ b/web-next/components/ForumCharacterPicker.tsx
@@ -0,0 +1,123 @@
+'use client'
+
+import { useEffect, useState } from 'react'
+import { useRouter } from 'next/navigation'
+import { className, classColor, raceName } from '@/lib/wow-data'
+
+type Char = { guid: number; name: string; race: number; gender: number; class: number; level: number }
+
+const RACE_SLUG: Record {labels.empty}{labels.title}
+
+