OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      ab3fe4c0f9c8
DATE      2025-11-16
SUBJECT   web: player profile season toggle
FILES     3 CHANGED
HASH      ab3fe4c0f9c8
DATE      2025-11-16
SUBJECT   web: player profile season toggle
FILES     3 CHANGED
 

diff --git a/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.astro 
b/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.astro
index 50bc417..92dbb8b 100644
--- a/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.astro
+++ b/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.astro
@@ -10,6 +10,11 @@ import { getDungeonIconUrl } from "../../../lib/dungeonIcons";
 import { getEffectiveRealmSlug } from "../../../lib/realms";
 import "./PlayerBestRuns.scss";
 
+interface SeasonOption {
+  id: string;
+  label: string;
+}
+
 interface Props {
   bestRuns?: Record<string, BestRun>;
   mode?: "full" | "compact";
@@ -18,6 +23,8 @@ interface Props {
   playerRegion?: string;
   playerRealmSlug?: string;
   seasonId?: string | number;
+  seasonOptions?: SeasonOption[];
+  seasonRuns?: Record<string, Record<string, BestRun>>;
 }
 
 const {
@@ -28,177 +35,258 @@ const {
   playerRegion,
   playerRealmSlug,
   seasonId,
+  seasonOptions = [],
+  seasonRuns,
 } = Astro.props;
 
-const runsArray = bestRuns ? Object.values(bestRuns) : [];
-const seasonNumber = seasonId ? Number(seasonId) : undefined;
-const leaderboardUrlOpts = seasonNumber ? { season: seasonNumber } : undefined;
+const baseRunsArray = bestRuns ? Object.values(bestRuns) : [];
+const normalizedSeasonId =
+  typeof seasonId === "number" ? String(seasonId) : seasonId || null;
 const leaderboardRealmSlug =
   getEffectiveRealmSlug(playerRegion, playerRealmSlug) || playerRealmSlug || "";
+const componentId = "player-best-runs";
+const seasonSelectId = "player-best-runs-season-select";
 
-const formatTime = (ms: number) => formatDurationMMSS(ms);
-
-const formatDate = (timestamp: number) => {
-  return new Date(timestamp).toLocaleDateString("en-US", {
-    month: "short",
-    day: "numeric",
-    year: "numeric",
-  });
+type SeasonEntry = {
+  id: string;
+  label: string;
+  runs: BestRun[];
 };
+
+const seasonEntries: SeasonEntry[] =
+  seasonOptions.length > 0
+    ? seasonOptions.map((option) => ({
+        id: option.id,
+        label: option.label,
+        runs:
+          (seasonRuns && seasonRuns[option.id]
+            ? Object.values(seasonRuns[option.id])
+            : option.id === normalizedSeasonId
+              ? baseRunsArray
+              : []) || [],
+      }))
+    : [
+        {
+          id: normalizedSeasonId || "current",
+          label: normalizedSeasonId ? `Season ${normalizedSeasonId}` : "Season",
+          runs: baseRunsArray,
+        },
+      ];
+
+const selectedSeasonId =
+  seasonEntries.find((entry) => entry.id === normalizedSeasonId)?.id ||
+  seasonEntries[0]?.id ||
+  null;
+
+const shouldShowSeasonSelector = seasonEntries.length > 1;
+
+const formatTime = (ms: number) => formatDurationMMSS(ms);
 ---
 
 {
   showSectionWrapper && (
     <div class="profile-section">
       <h3 class="section-title">Best Times Per Dungeon</h3>
-      <div class={`player-best-runs ${className || ""}`.trim()}>
-        {runsArray.length > 0 ? (
-          <Table mode="best-runs">
-            <div slot="header" class="table-header-cell">
-              Dungeon
-            </div>
-            <div slot="header" class="table-header-cell">
-              Time
-            </div>
-            <div slot="header" class="table-header-cell">
-              Team
-            </div>
-            <div slot="header" class="table-header-cell">
-              Global
-            </div>
-            <div slot="header" class="table-header-cell">
-              Region
-            </div>
-            <div slot="header" class="table-header-cell">
-              Realm
+      <div
+        id={componentId}
+        class={`player-best-runs ${className || ""}`.trim()}
+        data-component="player-best-runs"
+      >
+        {shouldShowSeasonSelector && (
+          <div class="best-runs-controls">
+            <div class="filter-group">
+              <label for={seasonSelectId}>Season</label>
+              <select id={seasonSelectId} data-season-select>
+                {seasonEntries.map((entry) => (
+                  <option
+                    value={entry.id}
+                    selected={entry.id === selectedSeasonId}
+                  >
+                    {entry.label}
+                  </option>
+                ))}
+              </select>
             </div>
+          </div>
+        )}
 
-            {runsArray.map((run) => {
-              const duration = formatTime(run.duration);
-              const dungeonSlug = (run as any).dungeon_slug || "";
-              const iconUrl = getDungeonIconUrl(dungeonSlug, run.dungeon_name);
-
-              const globalRankingValue =
-                typeof (run as any).global_ranking_filtered === "number" &&
-                (run as any).global_ranking_filtered > 0
-                  ? (run as any).global_ranking_filtered
-                  : (run as any).global_ranking;
-              const globalBracket =
-                (run as any).global_percentile_bracket ||
-                (run as any).percentile_bracket ||
-                "";
-
-              const regionalRankingValue =
-                typeof (run as any).regional_ranking_filtered === "number" &&
-                (run as any).regional_ranking_filtered > 0
-                  ? (run as any).regional_ranking_filtered
-                  : run.regional_ranking;
-              const realmRankingValue =
-                typeof (run as any).realm_ranking_filtered === "number" &&
-                (run as any).realm_ranking_filtered > 0
-                  ? (run as any).realm_ranking_filtered
-                  : run.realm_ranking;
-
-              const regionalBracket =
-                (run as any).regional_percentile_bracket ||
-                run.percentile_bracket ||
-                "";
-              const realmBracket =
-                (run as any).realm_percentile_bracket ||
-                run.percentile_bracket ||
-                "";
-
-              const globalURL = buildLeaderboardURL(
-                "global",
-                "all",
-                dungeonSlug,
-                undefined,
-                leaderboardUrlOpts,
-              );
-              const regionalURL = playerRegion
-                ? buildLeaderboardURL(
-                    playerRegion,
-                    "all",
-                    dungeonSlug,
-                    undefined,
-                    leaderboardUrlOpts,
-                  )
-                : "#";
-              const realmURL =
-                playerRegion && leaderboardRealmSlug
-                  ? buildLeaderboardURL(
-                      playerRegion,
-                      leaderboardRealmSlug,
+        {seasonEntries.map((entry) => {
+          const seasonNumber = Number(entry.id);
+          const leaderboardUrlOpts =
+            !Number.isNaN(seasonNumber) && entry.id !== "current"
+              ? { season: seasonNumber }
+              : undefined;
+
+          return (
+            <div
+              class="best-runs-season"
+              data-season={entry.id}
+              data-active={entry.id === selectedSeasonId ? "true" : "false"}
+            >
+              {entry.runs.length > 0 ? (
+                <Table mode="best-runs">
+                  <div slot="header" class="table-header-cell">
+                    Dungeon
+                  </div>
+                  <div slot="header" class="table-header-cell">
+                    Time
+                  </div>
+                  <div slot="header" class="table-header-cell">
+                    Team
+                  </div>
+                  <div slot="header" class="table-header-cell">
+                    Global
+                  </div>
+                  <div slot="header" class="table-header-cell">
+                    Region
+                  </div>
+                  <div slot="header" class="table-header-cell">
+                    Realm
+                  </div>
+
+                  {entry.runs.map((run) => {
+                    const duration = formatTime(run.duration);
+                    const dungeonSlug = (run as any).dungeon_slug || "";
+                    const iconUrl = getDungeonIconUrl(
+                      dungeonSlug,
+                      run.dungeon_name,
+                    );
+
+                    const globalRankingValue =
+                      typeof (run as any).global_ranking_filtered ===
+                        "number" && (run as any).global_ranking_filtered > 0
+                        ? (run as any).global_ranking_filtered
+                        : (run as any).global_ranking;
+                    const globalBracket =
+                      (run as any).global_percentile_bracket ||
+                      (run as any).percentile_bracket ||
+                      "";
+
+                    const regionalRankingValue =
+                      typeof (run as any).regional_ranking_filtered ===
+                        "number" && (run as any).regional_ranking_filtered > 0
+                        ? (run as any).regional_ranking_filtered
+                        : run.regional_ranking;
+                    const realmRankingValue =
+                      typeof (run as any).realm_ranking_filtered === "number" &&
+                      (run as any).realm_ranking_filtered > 0
+                        ? (run as any).realm_ranking_filtered
+                        : run.realm_ranking;
+
+                    const regionalBracket =
+                      (run as any).regional_percentile_bracket ||
+                      run.percentile_bracket ||
+                      "";
+                    const realmBracket =
+                      (run as any).realm_percentile_bracket ||
+                      run.percentile_bracket ||
+                      "";
+
+                    const globalURL = buildLeaderboardURL(
+                      "global",
+                      "all",
                       dungeonSlug,
                       undefined,
                       leaderboardUrlOpts,
-                    )
-                  : "#";
-
+                    );
+                    const regionalURL = playerRegion
+                      ? buildLeaderboardURL(
+                          playerRegion,
+                          "all",
+                          dungeonSlug,
+                          undefined,
+                          leaderboardUrlOpts,
+                        )
+                      : "#";
+                    const realmURL =
+                      playerRegion && leaderboardRealmSlug
+                        ? buildLeaderboardURL(
+                            playerRegion,
+                            leaderboardRealmSlug,
+                            dungeonSlug,
+                            undefined,
+                            leaderboardUrlOpts,
+                          )
+                        : "#";
 
-              const members = (run as any).all_members || (run as any).team_membe
rs || [];
+                    const members =
+                      (run as any).all_members ||
+                      (run as any).team_members ||
+                      [];
 
-              return (
-                <TableRow>
-                  <TableCell label="Dungeon">
-                    <div class="dungeon-cell">
-                      {iconUrl && (
-                        <img
-                          src={iconUrl}
-                          alt={run.dungeon_name}
-                          class="dungeon-icon"
-                        />
-                      )}
-                      <span class="dungeon-name">{run.dungeon_name}</span>
-                    </div>
-                  </TableCell>
-                  <TableCell label="Time">{duration}</TableCell>
-                  <TableCell label="Team">
-                    <TeamComposition
-                      members={members}
-                      currentRegion={playerRegion || ""}
-                      currentRealm={playerRealmSlug || ""}
-                    />
-                  </TableCell>
-                  <TableCell label="Global" class="ranking-cell ranking-global">
-                    <a
-                      href={globalURL}
-                      class="rank-link"
-                      set:html={formatRankingWithBracket(
-                        globalRankingValue,
-                        globalBracket,
-                      )}
-                    />
-                  </TableCell>
-                  <TableCell label="Region" class="ranking-cell ranking-region">
-                    <a
-                      href={regionalURL}
-                      class="rank-link"
-                      set:html={formatRankingWithBracket(
-                        regionalRankingValue,
-                        regionalBracket,
-                      )}
-                    />
-                  </TableCell>
-                  <TableCell label="Realm" class="ranking-cell ranking-realm">
-                    <a
-                      href={realmURL}
-                      class="rank-link"
-                      set:html={formatRankingWithBracket(
-                        realmRankingValue,
-                        realmBracket,
-                      )}
-                    />
-                  </TableCell>
-                </TableRow>
-              );
-            })}
-          </Table>
-        ) : (
-          <div class="no-runs-message">
-            <p>No best runs found for this player.</p>
-          </div>
-        )}
+                    return (
+                      <TableRow>
+                        <TableCell label="Dungeon">
+                          <div class="dungeon-cell">
+                            {iconUrl && (
+                              <img
+                                src={iconUrl}
+                                alt={run.dungeon_name}
+                                class="dungeon-icon"
+                              />
+                            )}
+                            <span class="dungeon-name">{run.dungeon_name}</span>
+                          </div>
+                        </TableCell>
+                        <TableCell label="Time">{duration}</TableCell>
+                        <TableCell label="Team">
+                          <TeamComposition
+                            members={members}
+                            currentRegion={playerRegion || ""}
+                            currentRealm={playerRealmSlug || ""}
+                          />
+                        </TableCell>
+                        <TableCell
+                          label="Global"
+                          class="ranking-cell ranking-global"
+                        >
+                          <a
+                            href={globalURL}
+                            class="rank-link"
+                            set:html={formatRankingWithBracket(
+                              globalRankingValue,
+                              globalBracket,
+                            )}
+                          />
+                        </TableCell>
+                        <TableCell
+                          label="Region"
+                          class="ranking-cell ranking-region"
+                        >
+                          <a
+                            href={regionalURL}
+                            class="rank-link"
+                            set:html={formatRankingWithBracket(
+                              regionalRankingValue,
+                              regionalBracket,
+                            )}
+                          />
+                        </TableCell>
+                        <TableCell
+                          label="Realm"
+                          class="ranking-cell ranking-realm"
+                        >
+                          <a
+                            href={realmURL}
+                            class="rank-link"
+                            set:html={formatRankingWithBracket(
+                              realmRankingValue,
+                              realmBracket,
+                            )}
+                          />
+                        </TableCell>
+                      </TableRow>
+                    );
+                  })}
+                </Table>
+              ) : (
+                <div class="no-runs-message">
+                  <p>No best runs found for this season.</p>
+                </div>
+              )}
+            </div>
+          );
+        })}
       </div>
     </div>
   )
@@ -206,154 +294,236 @@ const formatDate = (timestamp: number) => {
 
 {
   !showSectionWrapper && (
-    <div class={`player-best-runs ${className || ""}`.trim()}>
-      {runsArray.length > 0 ? (
-        <Table mode="best-runs">
-          <div slot="header" class="table-header-cell">
-            Dungeon
-          </div>
-          <div slot="header" class="table-header-cell">
-            Time
-          </div>
-          <div slot="header" class="table-header-cell">
-            Team
-          </div>
-          <div slot="header" class="table-header-cell">
-            Global
-          </div>
-          <div slot="header" class="table-header-cell">
-            Region
-          </div>
-          <div slot="header" class="table-header-cell">
-            Realm
+    <div
+      id={componentId}
+      class={`player-best-runs ${className || ""}`.trim()}
+      data-component="player-best-runs"
+    >
+      {shouldShowSeasonSelector && (
+        <div class="best-runs-controls">
+          <div class="filter-group">
+            <label for={seasonSelectId}>Season</label>
+            <select id={seasonSelectId} data-season-select>
+              {seasonEntries.map((entry) => (
+                <option
+                  value={entry.id}
+                  selected={entry.id === selectedSeasonId}
+                >
+                  {entry.label}
+                </option>
+              ))}
+            </select>
           </div>
+        </div>
+      )}
+
+      {seasonEntries.map((entry) => {
+        const seasonNumber = Number(entry.id);
+        const leaderboardUrlOpts =
+          !Number.isNaN(seasonNumber) && entry.id !== "current"
+            ? { season: seasonNumber }
+            : undefined;
+
+        return (
+          <div
+            class="best-runs-season"
+            data-season={entry.id}
+            data-active={entry.id === selectedSeasonId ? "true" : "false"}
+          >
+            {entry.runs.length > 0 ? (
+              <Table mode="best-runs">
+                <div slot="header" class="table-header-cell">
+                  Dungeon
+                </div>
+                <div slot="header" class="table-header-cell">
+                  Time
+                </div>
+                <div slot="header" class="table-header-cell">
+                  Team
+                </div>
+                <div slot="header" class="table-header-cell">
+                  Global
+                </div>
+                <div slot="header" class="table-header-cell">
+                  Region
+                </div>
+                <div slot="header" class="table-header-cell">
+                  Realm
+                </div>
 
-          {runsArray.map((run) => {
-            const duration = formatTime(run.duration);
-            const dungeonSlug = (run as any).dungeon_slug || "";
-            const iconUrl = getDungeonIconUrl(dungeonSlug, run.dungeon_name);
-
-            const globalRankingValue =
-              typeof (run as any).global_ranking_filtered === "number" &&
-              (run as any).global_ranking_filtered > 0
-                ? (run as any).global_ranking_filtered
-                : (run as any).global_ranking;
-            const globalBracket =
-              (run as any).global_percentile_bracket ||
-              (run as any).percentile_bracket ||
-              "";
-
-            const regionalRankingValue =
-              typeof (run as any).regional_ranking_filtered === "number" &&
-              (run as any).regional_ranking_filtered > 0
-                ? (run as any).regional_ranking_filtered
-                : run.regional_ranking;
-            const realmRankingValue =
-              typeof (run as any).realm_ranking_filtered === "number" &&
-              (run as any).realm_ranking_filtered > 0
-                ? (run as any).realm_ranking_filtered
-                : run.realm_ranking;
-
-            const regionalBracket =
-              (run as any).regional_percentile_bracket ||
-              run.percentile_bracket ||
-              "";
-            const realmBracket =
-              (run as any).realm_percentile_bracket ||
-              run.percentile_bracket ||
-              "";
-
-            const globalURL = buildLeaderboardURL(
-              "global",
-              "all",
-              dungeonSlug,
-              undefined,
-              leaderboardUrlOpts,
-            );
-            const regionalURL = playerRegion
-              ? buildLeaderboardURL(
-                  playerRegion,
-                  "all",
-                  dungeonSlug,
-                  undefined,
-                  leaderboardUrlOpts,
-                )
-              : "#";
-            const realmURL =
-              playerRegion && leaderboardRealmSlug
-                ? buildLeaderboardURL(
-                    playerRegion,
-                    leaderboardRealmSlug,
+                {entry.runs.map((run) => {
+                  const duration = formatTime(run.duration);
+                  const dungeonSlug = (run as any).dungeon_slug || "";
+                  const iconUrl = getDungeonIconUrl(
+                    dungeonSlug,
+                    run.dungeon_name,
+                  );
+
+                  const globalRankingValue =
+                    typeof (run as any).global_ranking_filtered === "number" &&
+                    (run as any).global_ranking_filtered > 0
+                      ? (run as any).global_ranking_filtered
+                      : (run as any).global_ranking;
+                  const globalBracket =
+                    (run as any).global_percentile_bracket ||
+                    (run as any).percentile_bracket ||
+                    "";
+
+                  const regionalRankingValue =
+                    typeof (run as any).regional_ranking_filtered ===
+                      "number" && (run as any).regional_ranking_filtered > 0
+                      ? (run as any).regional_ranking_filtered
+                      : run.regional_ranking;
+                  const realmRankingValue =
+                    typeof (run as any).realm_ranking_filtered === "number" &&
+                    (run as any).realm_ranking_filtered > 0
+                      ? (run as any).realm_ranking_filtered
+                      : run.realm_ranking;
+
+                  const regionalBracket =
+                    (run as any).regional_percentile_bracket ||
+                    run.percentile_bracket ||
+                    "";
+                  const realmBracket =
+                    (run as any).realm_percentile_bracket ||
+                    run.percentile_bracket ||
+                    "";
+
+                  const globalURL = buildLeaderboardURL(
+                    "global",
+                    "all",
                     dungeonSlug,
                     undefined,
                     leaderboardUrlOpts,
-                  )
-                : "#";
-
-
-            const members = (run as any).all_members || (run as any).team_members
 || [];
-
-            return (
-              <TableRow>
-                <TableCell label="Dungeon">
-                  <div class="dungeon-cell">
-                    {iconUrl && (
-                      <img
-                        src={iconUrl}
-                        alt={run.dungeon_name}
-                        class="dungeon-icon"
-                      />
-                    )}
-                    <span class="dungeon-name">{run.dungeon_name}</span>
-                  </div>
-                </TableCell>
-                <TableCell label="Time">{duration}</TableCell>
-                <TableCell label="Team">
-                  <TeamComposition
-                    members={members}
-                    currentRegion={playerRegion || ""}
-                    currentRealm={playerRealmSlug || ""}
-                  />
-                </TableCell>
-                <TableCell label="Global" class="ranking-cell ranking-global">
-                  <a
-                    href={globalURL}
-                    class="rank-link"
-                    set:html={formatRankingWithBracket(
-                      globalRankingValue,
-                      globalBracket,
-                    )}
-                  />
-                </TableCell>
-                <TableCell label="Region" class="ranking-cell ranking-region">
-                  <a
-                    href={regionalURL}
-                    class="rank-link"
-                    set:html={formatRankingWithBracket(
-                      regionalRankingValue,
-                      regionalBracket,
-                    )}
-                  />
-                </TableCell>
-                <TableCell label="Realm" class="ranking-cell ranking-realm">
-                  <a
-                    href={realmURL}
-                    class="rank-link"
-                    set:html={formatRankingWithBracket(
-                      realmRankingValue,
-                      realmBracket,
-                    )}
-                  />
-                </TableCell>
-              </TableRow>
-            );
-          })}
-        </Table>
-      ) : (
-        <div class="no-runs-message">
-          <p>No best runs found for this player.</p>
-        </div>
-      )}
+                  );
+                  const regionalURL = playerRegion
+                    ? buildLeaderboardURL(
+                        playerRegion,
+                        "all",
+                        dungeonSlug,
+                        undefined,
+                        leaderboardUrlOpts,
+                      )
+                    : "#";
+                  const realmURL =
+                    playerRegion && leaderboardRealmSlug
+                      ? buildLeaderboardURL(
+                          playerRegion,
+                          leaderboardRealmSlug,
+                          dungeonSlug,
+                          undefined,
+                          leaderboardUrlOpts,
+                        )
+                      : "#";
+
+                  const members =
+                    (run as any).all_members || (run as any).team_members || [];
+
+                  return (
+                    <TableRow>
+                      <TableCell label="Dungeon">
+                        <div class="dungeon-cell">
+                          {iconUrl && (
+                            <img
+                              src={iconUrl}
+                              alt={run.dungeon_name}
+                              class="dungeon-icon"
+                            />
+                          )}
+                          <span class="dungeon-name">{run.dungeon_name}</span>
+                        </div>
+                      </TableCell>
+                      <TableCell label="Time">{duration}</TableCell>
+                      <TableCell label="Team">
+                        <TeamComposition
+                          members={members}
+                          currentRegion={playerRegion || ""}
+                          currentRealm={playerRealmSlug || ""}
+                        />
+                      </TableCell>
+                      <TableCell
+                        label="Global"
+                        class="ranking-cell ranking-global"
+                      >
+                        <a
+                          href={globalURL}
+                          class="rank-link"
+                          set:html={formatRankingWithBracket(
+                            globalRankingValue,
+                            globalBracket,
+                          )}
+                        />
+                      </TableCell>
+                      <TableCell
+                        label="Region"
+                        class="ranking-cell ranking-region"
+                      >
+                        <a
+                          href={regionalURL}
+                          class="rank-link"
+                          set:html={formatRankingWithBracket(
+                            regionalRankingValue,
+                            regionalBracket,
+                          )}
+                        />
+                      </TableCell>
+                      <TableCell
+                        label="Realm"
+                        class="ranking-cell ranking-realm"
+                      >
+                        <a
+                          href={realmURL}
+                          class="rank-link"
+                          set:html={formatRankingWithBracket(
+                            realmRankingValue,
+                            realmBracket,
+                          )}
+                        />
+                      </TableCell>
+                    </TableRow>
+                  );
+                })}
+              </Table>
+            ) : (
+              <div class="no-runs-message">
+                <p>No best runs found for this season.</p>
+              </div>
+            )}
+          </div>
+        );
+      })}
     </div>
   )
 }
+
+<script is:inline>
+  (() => {
+    const container = document.getElementById("player-best-runs");
+    if (!container) return;
+    const select = container.querySelector("[data-season-select]");
+    if (!select) return;
+
+    select.addEventListener("change", (event) => {
+      const target = event.target;
+      if (!(target instanceof HTMLSelectElement)) {
+        return;
+      }
+      const selectedSeason = target.value;
+      container.querySelectorAll("[data-season]").forEach((section) => {
+        const isActive = section.getAttribute("data-season") === selectedSeason;
+        section.setAttribute("data-active", isActive ? "true" : "false");
+      });
+
+      const url = new URL(window.location.href);
+      if (selectedSeason) {
+        url.searchParams.set("season", selectedSeason);
+      } else {
+        url.searchParams.delete("season");
+      }
+
+      const newSearch = url.searchParams.toString();
+      const nextUrl = newSearch ? `${url.pathname}?${newSearch}` : url.pathname;
+      window.history.replaceState({}, "", nextUrl);
+    });
+  })();
+</script>

diff --git a/web/src/components/PlayerProfil
e/PlayerBestRuns/PlayerBestRuns.astro b/web/
src/components/PlayerProfile/PlayerBestRuns/
PlayerBestRuns.astro
index 50bc417..92dbb8b 100644
--- a/web/src/components/PlayerProfile/Playe
rBestRuns/PlayerBestRuns.astro
+++ b/web/src/components/PlayerProfile/Playe
rBestRuns/PlayerBestRuns.astro
@@ -10,6 +10,11 @@ import { getDungeonIconUr
l } from "../../../lib/dungeonIcons";
 import { getEffectiveRealmSlug } from "../.
./../lib/realms";
 import "./PlayerBestRuns.scss";
 
+interface SeasonOption {
+  id: string;
+  label: string;
+}
+
 interface Props {
   bestRuns?: Record<string, BestRun>;
   mode?: "full" | "compact";
@@ -18,6 +23,8 @@ interface Props {
   playerRegion?: string;
   playerRealmSlug?: string;
   seasonId?: string | number;
+  seasonOptions?: SeasonOption[];
+  seasonRuns?: Record<string, Record<string
, BestRun>>;
 }
 
 const {
@@ -28,177 +35,258 @@ const {
   playerRegion,
   playerRealmSlug,
   seasonId,
+  seasonOptions = [],
+  seasonRuns,
 } = Astro.props;
 
-const runsArray = bestRuns ? Object.values(
bestRuns) : [];
-const seasonNumber = seasonId ? Number(seas
onId) : undefined;
-const leaderboardUrlOpts = seasonNumber ? {
 season: seasonNumber } : undefined;
+const baseRunsArray = bestRuns ? Object.val
ues(bestRuns) : [];
+const normalizedSeasonId =
+  typeof seasonId === "number" ? String(sea
sonId) : seasonId || null;
 const leaderboardRealmSlug =
   getEffectiveRealmSlug(playerRegion, playe
rRealmSlug) || playerRealmSlug || "";
+const componentId = "player-best-runs";
+const seasonSelectId = "player-best-runs-se
ason-select";
 
-const formatTime = (ms: number) => formatDu
rationMMSS(ms);
-
-const formatDate = (timestamp: number) => {
-  return new Date(timestamp).toLocaleDateSt
ring("en-US", {
-    month: "short",
-    day: "numeric",
-    year: "numeric",
-  });
+type SeasonEntry = {
+  id: string;
+  label: string;
+  runs: BestRun[];
 };
+
+const seasonEntries: SeasonEntry[] =
+  seasonOptions.length > 0
+    ? seasonOptions.map((option) => ({
+        id: option.id,
+        label: option.label,
+        runs:
+          (seasonRuns && seasonRuns[option.
id]
+            ? Object.values(seasonRuns[opti
on.id])
+            : option.id === normalizedSeaso
nId
+              ? baseRunsArray
+              : []) || [],
+      }))
+    : [
+        {
+          id: normalizedSeasonId || "curren
t",
+          label: normalizedSeasonId ? `Seas
on ${normalizedSeasonId}` : "Season",
+          runs: baseRunsArray,
+        },
+      ];
+
+const selectedSeasonId =
+  seasonEntries.find((entry) => entry.id ==
= normalizedSeasonId)?.id ||
+  seasonEntries[0]?.id ||
+  null;
+
+const shouldShowSeasonSelector = seasonEntr
ies.length > 1;
+
+const formatTime = (ms: number) => formatDu
rationMMSS(ms);
 ---
 
 {
   showSectionWrapper && (
     <div class="profile-section">
       <h3 class="section-title">Best Times 
Per Dungeon</h3>
-      <div class={`player-best-runs ${class
Name || ""}`.trim()}>
-        {runsArray.length > 0 ? (
-          <Table mode="best-runs">
-            <div slot="header" class="table
-header-cell">
-              Dungeon
-            </div>
-            <div slot="header" class="table
-header-cell">
-              Time
-            </div>
-            <div slot="header" class="table
-header-cell">
-              Team
-            </div>
-            <div slot="header" class="table
-header-cell">
-              Global
-            </div>
-            <div slot="header" class="table
-header-cell">
-              Region
-            </div>
-            <div slot="header" class="table
-header-cell">
-              Realm
+      <div
+        id={componentId}
+        class={`player-best-runs ${classNam
e || ""}`.trim()}
+        data-component="player-best-runs"
+      >
+        {shouldShowSeasonSelector && (
+          <div class="best-runs-controls">
+            <div class="filter-group">
+              <label for={seasonSelectId}>S
eason</label>
+              <select id={seasonSelectId} d
ata-season-select>
+                {seasonEntries.map((entry) 
=> (
+                  <option
+                    value={entry.id}
+                    selected={entry.id === 
selectedSeasonId}
+                  >
+                    {entry.label}
+                  </option>
+                ))}
+              </select>
             </div>
+          </div>
+        )}
 
-            {runsArray.map((run) => {
-              const duration = formatTime(r
un.duration);
-              const dungeonSlug = (run as a
ny).dungeon_slug || "";
-              const iconUrl = getDungeonIco
nUrl(dungeonSlug, run.dungeon_name);
-
-              const globalRankingValue =
-                typeof (run as any).global_
ranking_filtered === "number" &&
-                (run as any).global_ranking
_filtered > 0
-                  ? (run as any).global_ran
king_filtered
-                  : (run as any).global_ran
king;
-              const globalBracket =
-                (run as any).global_percent
ile_bracket ||
-                (run as any).percentile_bra
cket ||
-                "";
-
-              const regionalRankingValue =
-                typeof (run as any).regiona
l_ranking_filtered === "number" &&
-                (run as any).regional_ranki
ng_filtered > 0
-                  ? (run as any).regional_r
anking_filtered
-                  : run.regional_ranking;
-              const realmRankingValue =
-                typeof (run as any).realm_r
anking_filtered === "number" &&
-                (run as any).realm_ranking_
filtered > 0
-                  ? (run as any).realm_rank
ing_filtered
-                  : run.realm_ranking;
-
-              const regionalBracket =
-                (run as any).regional_perce
ntile_bracket ||
-                run.percentile_bracket ||
-                "";
-              const realmBracket =
-                (run as any).realm_percenti
le_bracket ||
-                run.percentile_bracket ||
-                "";
-
-              const globalURL = buildLeader
boardURL(
-                "global",
-                "all",
-                dungeonSlug,
-                undefined,
-                leaderboardUrlOpts,
-              );
-              const regionalURL = playerReg
ion
-                ? buildLeaderboardURL(
-                    playerRegion,
-                    "all",
-                    dungeonSlug,
-                    undefined,
-                    leaderboardUrlOpts,
-                  )
-                : "#";
-              const realmURL =
-                playerRegion && leaderboard
RealmSlug
-                  ? buildLeaderboardURL(
-                      playerRegion,
-                      leaderboardRealmSlug,
+        {seasonEntries.map((entry) => {
+          const seasonNumber = Number(entry
.id);
+          const leaderboardUrlOpts =
+            !Number.isNaN(seasonNumber) && 
entry.id !== "current"
+              ? { season: seasonNumber }
+              : undefined;
+
+          return (
+            <div
+              class="best-runs-season"
+              data-season={entry.id}
+              data-active={entry.id === sel
ectedSeasonId ? "true" : "false"}
+            >
+              {entry.runs.length > 0 ? (
+                <Table mode="best-runs">
+                  <div slot="header" class=
"table-header-cell">
+                    Dungeon
+                  </div>
+                  <div slot="header" class=
"table-header-cell">
+                    Time
+                  </div>
+                  <div slot="header" class=
"table-header-cell">
+                    Team
+                  </div>
+                  <div slot="header" class=
"table-header-cell">
+                    Global
+                  </div>
+                  <div slot="header" class=
"table-header-cell">
+                    Region
+                  </div>
+                  <div slot="header" class=
"table-header-cell">
+                    Realm
+                  </div>
+
+                  {entry.runs.map((run) => 
{
+                    const duration = format
Time(run.duration);
+                    const dungeonSlug = (ru
n as any).dungeon_slug || "";
+                    const iconUrl = getDung
eonIconUrl(
+                      dungeonSlug,
+                      run.dungeon_name,
+                    );
+
+                    const globalRankingValu
e =
+                      typeof (run as any).g
lobal_ranking_filtered ===
+                        "number" && (run as
 any).global_ranking_filtered > 0
+                        ? (run as any).glob
al_ranking_filtered
+                        : (run as any).glob
al_ranking;
+                    const globalBracket =
+                      (run as any).global_p
ercentile_bracket ||
+                      (run as any).percenti
le_bracket ||
+                      "";
+
+                    const regionalRankingVa
lue =
+                      typeof (run as any).r
egional_ranking_filtered ===
+                        "number" && (run as
 any).regional_ranking_filtered > 0
+                        ? (run as any).regi
onal_ranking_filtered
+                        : run.regional_rank
ing;
+                    const realmRankingValue
 =
+                      typeof (run as any).r
ealm_ranking_filtered === "number" &&
+                      (run as any).realm_ra
nking_filtered > 0
+                        ? (run as any).real
m_ranking_filtered
+                        : run.realm_ranking
;
+
+                    const regionalBracket =
+                      (run as any).regional
_percentile_bracket ||
+                      run.percentile_bracke
t ||
+                      "";
+                    const realmBracket =
+                      (run as any).realm_pe
rcentile_bracket ||
+                      run.percentile_bracke
t ||
+                      "";
+
+                    const globalURL = build
LeaderboardURL(
+                      "global",
+                      "all",
                       dungeonSlug,
                       undefined,
                       leaderboardUrlOpts,
-                    )
-                  : "#";
-
+                    );
+                    const regionalURL = pla
yerRegion
+                      ? buildLeaderboardURL
(
+                          playerRegion,
+                          "all",
+                          dungeonSlug,
+                          undefined,
+                          leaderboardUrlOpt
s,
+                        )
+                      : "#";
+                    const realmURL =
+                      playerRegion && leade
rboardRealmSlug
+                        ? buildLeaderboardU
RL(
+                            playerRegion,
+                            leaderboardReal
mSlug,
+                            dungeonSlug,
+                            undefined,
+                            leaderboardUrlO
pts,
+                          )
+                        : "#";
 
-              const members = (run as any).
all_members || (run as any).team_members || 
[];
+                    const members =
+                      (run as any).all_memb
ers ||
+                      (run as any).team_mem
bers ||
+                      [];
 
-              return (
-                <TableRow>
-                  <TableCell label="Dungeon
">
-                    <div class="dungeon-cel
l">
-                      {iconUrl && (
-                        <img
-                          src={iconUrl}
-                          alt={run.dungeon_
name}
-                          class="dungeon-ic
on"
-                        />
-                      )}
-                      <span class="dungeon-
name">{run.dungeon_name}</span>
-                    </div>
-                  </TableCell>
-                  <TableCell label="Time">{
duration}</TableCell>
-                  <TableCell label="Team">
-                    <TeamComposition
-                      members={members}
-                      currentRegion={player
Region || ""}
-                      currentRealm={playerR
ealmSlug || ""}
-                    />
-                  </TableCell>
-                  <TableCell label="Global"
 class="ranking-cell ranking-global">
-                    <a
-                      href={globalURL}
-                      class="rank-link"
-                      set:html={formatRanki
ngWithBracket(
-                        globalRankingValue,
-                        globalBracket,
-                      )}
-                    />
-                  </TableCell>
-                  <TableCell label="Region"
 class="ranking-cell ranking-region">
-                    <a
-                      href={regionalURL}
-                      class="rank-link"
-                      set:html={formatRanki
ngWithBracket(
-                        regionalRankingValu
e,
-                        regionalBracket,
-                      )}
-                    />
-                  </TableCell>
-                  <TableCell label="Realm" 
class="ranking-cell ranking-realm">
-                    <a
-                      href={realmURL}
-                      class="rank-link"
-                      set:html={formatRanki
ngWithBracket(
-                        realmRankingValue,
-                        realmBracket,
-                      )}
-                    />
-                  </TableCell>
-                </TableRow>
-              );
-            })}
-          </Table>
-        ) : (
-          <div class="no-runs-message">
-            <p>No best runs found for this 
player.</p>
-          </div>
-        )}
+                    return (
+                      <TableRow>
+                        <TableCell label="D
ungeon">
+                          <div class="dunge
on-cell">
+                            {iconUrl && (
+                              <img
+                                src={iconUr
l}
+                                alt={run.du
ngeon_name}
+                                class="dung
eon-icon"
+                              />
+                            )}
+                            <span class="du
ngeon-name">{run.dungeon_name}</span>
+                          </div>
+                        </TableCell>
+                        <TableCell label="T
ime">{duration}</TableCell>
+                        <TableCell label="T
eam">
+                          <TeamComposition
+                            members={member
s}
+                            currentRegion={
playerRegion || ""}
+                            currentRealm={p
layerRealmSlug || ""}
+                          />
+                        </TableCell>
+                        <TableCell
+                          label="Global"
+                          class="ranking-ce
ll ranking-global"
+                        >
+                          <a
+                            href={globalURL
}
+                            class="rank-lin
k"
+                            set:html={forma
tRankingWithBracket(
+                              globalRanking
Value,
+                              globalBracket
,
+                            )}
+                          />
+                        </TableCell>
+                        <TableCell
+                          label="Region"
+                          class="ranking-ce
ll ranking-region"
+                        >
+                          <a
+                            href={regionalU
RL}
+                            class="rank-lin
k"
+                            set:html={forma
tRankingWithBracket(
+                              regionalRanki
ngValue,
+                              regionalBrack
et,
+                            )}
+                          />
+                        </TableCell>
+                        <TableCell
+                          label="Realm"
+                          class="ranking-ce
ll ranking-realm"
+                        >
+                          <a
+                            href={realmURL}
+                            class="rank-lin
k"
+                            set:html={forma
tRankingWithBracket(
+                              realmRankingV
alue,
+                              realmBracket,
+                            )}
+                          />
+                        </TableCell>
+                      </TableRow>
+                    );
+                  })}
+                </Table>
+              ) : (
+                <div class="no-runs-message
">
+                  <p>No best runs found for
 this season.</p>
+                </div>
+              )}
+            </div>
+          );
+        })}
       </div>
     </div>
   )
@@ -206,154 +294,236 @@ const formatDate = (
timestamp: number) => {
 
 {
   !showSectionWrapper && (
-    <div class={`player-best-runs ${classNa
me || ""}`.trim()}>
-      {runsArray.length > 0 ? (
-        <Table mode="best-runs">
-          <div slot="header" class="table-h
eader-cell">
-            Dungeon
-          </div>
-          <div slot="header" class="table-h
eader-cell">
-            Time
-          </div>
-          <div slot="header" class="table-h
eader-cell">
-            Team
-          </div>
-          <div slot="header" class="table-h
eader-cell">
-            Global
-          </div>
-          <div slot="header" class="table-h
eader-cell">
-            Region
-          </div>
-          <div slot="header" class="table-h
eader-cell">
-            Realm
+    <div
+      id={componentId}
+      class={`player-best-runs ${className 
|| ""}`.trim()}
+      data-component="player-best-runs"
+    >
+      {shouldShowSeasonSelector && (
+        <div class="best-runs-controls">
+          <div class="filter-group">
+            <label for={seasonSelectId}>Sea
son</label>
+            <select id={seasonSelectId} dat
a-season-select>
+              {seasonEntries.map((entry) =>
 (
+                <option
+                  value={entry.id}
+                  selected={entry.id === se
lectedSeasonId}
+                >
+                  {entry.label}
+                </option>
+              ))}
+            </select>
           </div>
+        </div>
+      )}
+
+      {seasonEntries.map((entry) => {
+        const seasonNumber = Number(entry.i
d);
+        const leaderboardUrlOpts =
+          !Number.isNaN(seasonNumber) && en
try.id !== "current"
+            ? { season: seasonNumber }
+            : undefined;
+
+        return (
+          <div
+            class="best-runs-season"
+            data-season={entry.id}
+            data-active={entry.id === selec
tedSeasonId ? "true" : "false"}
+          >
+            {entry.runs.length > 0 ? (
+              <Table mode="best-runs">
+                <div slot="header" class="t
able-header-cell">
+                  Dungeon
+                </div>
+                <div slot="header" class="t
able-header-cell">
+                  Time
+                </div>
+                <div slot="header" class="t
able-header-cell">
+                  Team
+                </div>
+                <div slot="header" class="t
able-header-cell">
+                  Global
+                </div>
+                <div slot="header" class="t
able-header-cell">
+                  Region
+                </div>
+                <div slot="header" class="t
able-header-cell">
+                  Realm
+                </div>
 
-          {runsArray.map((run) => {
-            const duration = formatTime(run
.duration);
-            const dungeonSlug = (run as any
).dungeon_slug || "";
-            const iconUrl = getDungeonIconU
rl(dungeonSlug, run.dungeon_name);
-
-            const globalRankingValue =
-              typeof (run as any).global_ra
nking_filtered === "number" &&
-              (run as any).global_ranking_f
iltered > 0
-                ? (run as any).global_ranki
ng_filtered
-                : (run as any).global_ranki
ng;
-            const globalBracket =
-              (run as any).global_percentil
e_bracket ||
-              (run as any).percentile_brack
et ||
-              "";
-
-            const regionalRankingValue =
-              typeof (run as any).regional_
ranking_filtered === "number" &&
-              (run as any).regional_ranking
_filtered > 0
-                ? (run as any).regional_ran
king_filtered
-                : run.regional_ranking;
-            const realmRankingValue =
-              typeof (run as any).realm_ran
king_filtered === "number" &&
-              (run as any).realm_ranking_fi
ltered > 0
-                ? (run as any).realm_rankin
g_filtered
-                : run.realm_ranking;
-
-            const regionalBracket =
-              (run as any).regional_percent
ile_bracket ||
-              run.percentile_bracket ||
-              "";
-            const realmBracket =
-              (run as any).realm_percentile
_bracket ||
-              run.percentile_bracket ||
-              "";
-
-            const globalURL = buildLeaderbo
ardURL(
-              "global",
-              "all",
-              dungeonSlug,
-              undefined,
-              leaderboardUrlOpts,
-            );
-            const regionalURL = playerRegio
n
-              ? buildLeaderboardURL(
-                  playerRegion,
-                  "all",
-                  dungeonSlug,
-                  undefined,
-                  leaderboardUrlOpts,
-                )
-              : "#";
-            const realmURL =
-              playerRegion && leaderboardRe
almSlug
-                ? buildLeaderboardURL(
-                    playerRegion,
-                    leaderboardRealmSlug,
+                {entry.runs.map((run) => {
+                  const duration = formatTi
me(run.duration);
+                  const dungeonSlug = (run 
as any).dungeon_slug || "";
+                  const iconUrl = getDungeo
nIconUrl(
+                    dungeonSlug,
+                    run.dungeon_name,
+                  );
+
+                  const globalRankingValue 
=
+                    typeof (run as any).glo
bal_ranking_filtered === "number" &&
+                    (run as any).global_ran
king_filtered > 0
+                      ? (run as any).global
_ranking_filtered
+                      : (run as any).global
_ranking;
+                  const globalBracket =
+                    (run as any).global_per
centile_bracket ||
+                    (run as any).percentile
_bracket ||
+                    "";
+
+                  const regionalRankingValu
e =
+                    typeof (run as any).reg
ional_ranking_filtered ===
+                      "number" && (run as a
ny).regional_ranking_filtered > 0
+                      ? (run as any).region
al_ranking_filtered
+                      : run.regional_rankin
g;
+                  const realmRankingValue =
+                    typeof (run as any).rea
lm_ranking_filtered === "number" &&
+                    (run as any).realm_rank
ing_filtered > 0
+                      ? (run as any).realm_
ranking_filtered
+                      : run.realm_ranking;
+
+                  const regionalBracket =
+                    (run as any).regional_p
ercentile_bracket ||
+                    run.percentile_bracket 
||
+                    "";
+                  const realmBracket =
+                    (run as any).realm_perc
entile_bracket ||
+                    run.percentile_bracket 
||
+                    "";
+
+                  const globalURL = buildLe
aderboardURL(
+                    "global",
+                    "all",
                     dungeonSlug,
                     undefined,
                     leaderboardUrlOpts,
-                  )
-                : "#";
-
-
-            const members = (run as any).al
l_members || (run as any).team_members || []
;
-
-            return (
-              <TableRow>
-                <TableCell label="Dungeon">
-                  <div class="dungeon-cell"
>
-                    {iconUrl && (
-                      <img
-                        src={iconUrl}
-                        alt={run.dungeon_na
me}
-                        class="dungeon-icon
"
-                      />
-                    )}
-                    <span class="dungeon-na
me">{run.dungeon_name}</span>
-                  </div>
-                </TableCell>
-                <TableCell label="Time">{du
ration}</TableCell>
-                <TableCell label="Team">
-                  <TeamComposition
-                    members={members}
-                    currentRegion={playerRe
gion || ""}
-                    currentRealm={playerRea
lmSlug || ""}
-                  />
-                </TableCell>
-                <TableCell label="Global" c
lass="ranking-cell ranking-global">
-                  <a
-                    href={globalURL}
-                    class="rank-link"
-                    set:html={formatRanking
WithBracket(
-                      globalRankingValue,
-                      globalBracket,
-                    )}
-                  />
-                </TableCell>
-                <TableCell label="Region" c
lass="ranking-cell ranking-region">
-                  <a
-                    href={regionalURL}
-                    class="rank-link"
-                    set:html={formatRanking
WithBracket(
-                      regionalRankingValue,
-                      regionalBracket,
-                    )}
-                  />
-                </TableCell>
-                <TableCell label="Realm" cl
ass="ranking-cell ranking-realm">
-                  <a
-                    href={realmURL}
-                    class="rank-link"
-                    set:html={formatRanking
WithBracket(
-                      realmRankingValue,
-                      realmBracket,
-                    )}
-                  />
-                </TableCell>
-              </TableRow>
-            );
-          })}
-        </Table>
-      ) : (
-        <div class="no-runs-message">
-          <p>No best runs found for this pl
ayer.</p>
-        </div>
-      )}
+                  );
+                  const regionalURL = playe
rRegion
+                    ? buildLeaderboardURL(
+                        playerRegion,
+                        "all",
+                        dungeonSlug,
+                        undefined,
+                        leaderboardUrlOpts,
+                      )
+                    : "#";
+                  const realmURL =
+                    playerRegion && leaderb
oardRealmSlug
+                      ? buildLeaderboardURL
(
+                          playerRegion,
+                          leaderboardRealmS
lug,
+                          dungeonSlug,
+                          undefined,
+                          leaderboardUrlOpt
s,
+                        )
+                      : "#";
+
+                  const members =
+                    (run as any).all_member
s || (run as any).team_members || [];
+
+                  return (
+                    <TableRow>
+                      <TableCell label="Dun
geon">
+                        <div class="dungeon
-cell">
+                          {iconUrl && (
+                            <img
+                              src={iconUrl}
+                              alt={run.dung
eon_name}
+                              class="dungeo
n-icon"
+                            />
+                          )}
+                          <span class="dung
eon-name">{run.dungeon_name}</span>
+                        </div>
+                      </TableCell>
+                      <TableCell label="Tim
e">{duration}</TableCell>
+                      <TableCell label="Tea
m">
+                        <TeamComposition
+                          members={members}
+                          currentRegion={pl
ayerRegion || ""}
+                          currentRealm={pla
yerRealmSlug || ""}
+                        />
+                      </TableCell>
+                      <TableCell
+                        label="Global"
+                        class="ranking-cell
 ranking-global"
+                      >
+                        <a
+                          href={globalURL}
+                          class="rank-link"
+                          set:html={formatR
ankingWithBracket(
+                            globalRankingVa
lue,
+                            globalBracket,
+                          )}
+                        />
+                      </TableCell>
+                      <TableCell
+                        label="Region"
+                        class="ranking-cell
 ranking-region"
+                      >
+                        <a
+                          href={regionalURL
}
+                          class="rank-link"
+                          set:html={formatR
ankingWithBracket(
+                            regionalRanking
Value,
+                            regionalBracket
,
+                          )}
+                        />
+                      </TableCell>
+                      <TableCell
+                        label="Realm"
+                        class="ranking-cell
 ranking-realm"
+                      >
+                        <a
+                          href={realmURL}
+                          class="rank-link"
+                          set:html={formatR
ankingWithBracket(
+                            realmRankingVal
ue,
+                            realmBracket,
+                          )}
+                        />
+                      </TableCell>
+                    </TableRow>
+                  );
+                })}
+              </Table>
+            ) : (
+              <div class="no-runs-message">
+                <p>No best runs found for t
his season.</p>
+              </div>
+            )}
+          </div>
+        );
+      })}
     </div>
   )
 }
+
+<script is:inline>
+  (() => {
+    const container = document.getElementBy
Id("player-best-runs");
+    if (!container) return;
+    const select = container.querySelector(
"[data-season-select]");
+    if (!select) return;
+
+    select.addEventListener("change", (even
t) => {
+      const target = event.target;
+      if (!(target instanceof HTMLSelectEle
ment)) {
+        return;
+      }
+      const selectedSeason = target.value;
+      container.querySelectorAll("[data-sea
son]").forEach((section) => {
+        const isActive = section.getAttribu
te("data-season") === selectedSeason;
+        section.setAttribute("data-active",
 isActive ? "true" : "false");
+      });
+
+      const url = new URL(window.location.h
ref);
+      if (selectedSeason) {
+        url.searchParams.set("season", sele
ctedSeason);
+      } else {
+        url.searchParams.delete("season");
+      }
+
+      const newSearch = url.searchParams.to
String();
+      const nextUrl = newSearch ? `${url.pa
thname}?${newSearch}` : url.pathname;
+      window.history.replaceState({}, "", n
extUrl);
+    });
+  })();
+</script>
 

diff --git a/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.scss b
/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.scss
index 9d31361..32a8c56 100644
--- a/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.scss
+++ b/web/src/components/PlayerProfile/PlayerBestRuns/PlayerBestRuns.scss
@@ -2,11 +2,39 @@
 
 .player-best-runs {
   width: 100%;
+
+  .dungeon-cell {
+    display: inline-flex;
+    align-items: center;
+
+    .dungeon-icon {
+      margin-right: 0.4rem;
+    }
+  }
+
+  .best-runs-controls {
+    display: flex;
+    justify-content: flex-end;
+    flex-wrap: wrap;
+    gap: $spacing-sm;
+    margin-bottom: $spacing-md;
+
+    .filter-group {
+      margin-bottom: 0;
+    }
+  }
+
+  .best-runs-season {
+    &[data-active="false"] {
+      display: none;
+    }
+  }
 }
 
 // Mobile layout
 @media (max-width: 1024px) {
   .player-best-runs {
+
     .table-container[data-mode="best-runs"] {
       .table-row {
         display: grid;

diff --git a/web/src/components/PlayerProfil
e/PlayerBestRuns/PlayerBestRuns.scss b/web/s
rc/components/PlayerProfile/PlayerBestRuns/P
layerBestRuns.scss
index 9d31361..32a8c56 100644
--- a/web/src/components/PlayerProfile/Playe
rBestRuns/PlayerBestRuns.scss
+++ b/web/src/components/PlayerProfile/Playe
rBestRuns/PlayerBestRuns.scss
@@ -2,11 +2,39 @@
 
 .player-best-runs {
   width: 100%;
+
+  .dungeon-cell {
+    display: inline-flex;
+    align-items: center;
+
+    .dungeon-icon {
+      margin-right: 0.4rem;
+    }
+  }
+
+  .best-runs-controls {
+    display: flex;
+    justify-content: flex-end;
+    flex-wrap: wrap;
+    gap: $spacing-sm;
+    margin-bottom: $spacing-md;
+
+    .filter-group {
+      margin-bottom: 0;
+    }
+  }
+
+  .best-runs-season {
+    &[data-active="false"] {
+      display: none;
+    }
+  }
 }
 
 // Mobile layout
 @media (max-width: 1024px) {
   .player-best-runs {
+
     .table-container[data-mode="best-runs"]
 {
       .table-row {
         display: grid;
 

diff --git a/web/src/layouts/PlayerProfileLayout.astro b/web/src/layouts/PlayerPro
fileLayout.astro
index 43eb110..c152908 100644
--- a/web/src/layouts/PlayerProfileLayout.astro
+++ b/web/src/layouts/PlayerProfileLayout.astro
@@ -6,7 +6,7 @@ import PlayerHeader from "../components/PlayerProfile/PlayerHeader
/PlayerHeader.
 import PlayerEquipment from "../components/PlayerProfile/PlayerEquipment/PlayerEq
uipment.astro";
 import PlayerBestRuns from "../components/PlayerProfile/PlayerBestRuns/PlayerBest
Runs.astro";
 import PageLayout from "./PageLayout.astro";
-import type { PlayerProfileData } from "../lib/types";
+import type { PlayerProfileData, BestRun } from "../lib/types";
 import "../styles/global.scss";
 import "./PlayerProfileLayout.scss";
 
@@ -31,16 +31,39 @@ const pageTitle = `${playerName} - ${realmSlug} | Player Profi
le`;
 const player = playerData?.player;
 const equipment = playerData?.equipment || {};
 
+const requestedSeason =
+  typeof Astro.url?.searchParams?.get === "function"
+    ? Astro.url.searchParams.get("season")
+    : null;
+
 let currentSeasonId: string | null = null;
 let currentSeasonData = null;
+let seasonOptions: { id: string; label: string }[] = [];
+const seasonRunsMap: Record<string, Record<string, BestRun>> = {};
 
 if (player && player.seasons) {
   const seasonIds = Object.keys(player.seasons).sort(
     (a, b) => Number(b) - Number(a),
   );
+  seasonOptions = seasonIds.map((id) => ({
+    id,
+    label: `Season ${id}`,
+  }));
+
   if (seasonIds.length > 0) {
-    currentSeasonId = seasonIds[0];
-    currentSeasonData = player.seasons[currentSeasonId];
+    if (requestedSeason && seasonIds.includes(requestedSeason)) {
+      currentSeasonId = requestedSeason;
+    } else {
+      currentSeasonId = seasonIds[0];
+    }
+    currentSeasonData = currentSeasonId
+      ? player.seasons[currentSeasonId]
+      : null;
+  }
+
+  for (const seasonId of seasonIds) {
+    const data = player.seasons[seasonId];
+    seasonRunsMap[seasonId] = data?.best_runs || {};
   }
 }
 
@@ -96,6 +119,8 @@ const bestRuns = currentSeasonData?.best_runs || {};
                 playerRegion={player.region}
                 playerRealmSlug={player.realm_slug}
                 seasonId={currentSeasonId}
+                seasonOptions={seasonOptions}
+                seasonRuns={seasonRunsMap}
                 mode="full"
               />
             </>

diff --git a/web/src/layouts/PlayerProfileLa
yout.astro b/web/src/layouts/PlayerProfileLa
yout.astro
index 43eb110..c152908 100644
--- a/web/src/layouts/PlayerProfileLayout.as
tro
+++ b/web/src/layouts/PlayerProfileLayout.as
tro
@@ -6,7 +6,7 @@ import PlayerHeader from "..
/components/PlayerProfile/PlayerHeader/Playe
rHeader.
 import PlayerEquipment from "../components/
PlayerProfile/PlayerEquipment/PlayerEquipmen
t.astro";
 import PlayerBestRuns from "../components/P
layerProfile/PlayerBestRuns/PlayerBestRuns.a
stro";
 import PageLayout from "./PageLayout.astro"
;
-import type { PlayerProfileData } from "../
lib/types";
+import type { PlayerProfileData, BestRun } 
from "../lib/types";
 import "../styles/global.scss";
 import "./PlayerProfileLayout.scss";
 
@@ -31,16 +31,39 @@ const pageTitle = `${pla
yerName} - ${realmSlug} | Player Profile`;
 const player = playerData?.player;
 const equipment = playerData?.equipment || 
{};
 
+const requestedSeason =
+  typeof Astro.url?.searchParams?.get === "
function"
+    ? Astro.url.searchParams.get("season")
+    : null;
+
 let currentSeasonId: string | null = null;
 let currentSeasonData = null;
+let seasonOptions: { id: string; label: str
ing }[] = [];
+const seasonRunsMap: Record<string, Record<
string, BestRun>> = {};
 
 if (player && player.seasons) {
   const seasonIds = Object.keys(player.seas
ons).sort(
     (a, b) => Number(b) - Number(a),
   );
+  seasonOptions = seasonIds.map((id) => ({
+    id,
+    label: `Season ${id}`,
+  }));
+
   if (seasonIds.length > 0) {
-    currentSeasonId = seasonIds[0];
-    currentSeasonData = player.seasons[curr
entSeasonId];
+    if (requestedSeason && seasonIds.includ
es(requestedSeason)) {
+      currentSeasonId = requestedSeason;
+    } else {
+      currentSeasonId = seasonIds[0];
+    }
+    currentSeasonData = currentSeasonId
+      ? player.seasons[currentSeasonId]
+      : null;
+  }
+
+  for (const seasonId of seasonIds) {
+    const data = player.seasons[seasonId];
+    seasonRunsMap[seasonId] = data?.best_ru
ns || {};
   }
 }
 
@@ -96,6 +119,8 @@ const bestRuns = currentS
easonData?.best_runs || {};
                 playerRegion={player.region
}
                 playerRealmSlug={player.rea
lm_slug}
                 seasonId={currentSeasonId}
+                seasonOptions={seasonOption
s}
+                seasonRuns={seasonRunsMap}
                 mode="full"
               />
             </>
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET