Faith Roswell is a Senior Writer on Screen Rant’s Classic TV team. Since earning her degree in Creative Writing over a decade ago, Faith has written articles on film and TV from a variety of different angles. Faith now combines her knowledge of psychology with her love of monster movies to give more insight into what makes the best ones.

You may have read her Screen Rant lists and features covering horror, sci-fi, and fantasy, or read her Amazon Top 10 book, “Movie Monsters of the Deep.”

Faith has had an extensive career as a writer, appearing on BBC live radio, researching true crime for Rotten Mango podcast, and writing for publications including Mental Floss, Atlas Obscura, and The Daily Jaws before beginning here at Screen Rant.

Game of Thrones was a groundbreaking show that illustrated what the fantasy genre could be when given an enormous budget and a compelling story. George R. R. Martin’s novel series was the perfect story to adapt, and while the final season’s drop in quality has overshadowed the incredibly strong start the show had, Game of Thrones is well worth watching for its immersive worldbuilding.

The dragons and battles might provide many of Game of Thrones’ best scenes, but the different family factions at the center of the story drive the story forward with their well-written journeys and excellent character building. Of all the major houses in Game of Thrones, the Starks are the undisputed heroes after their resilience and moral strength won over audiences.

Ned’s brother Benjen is one of the most mysterious members of the Stark family, with season 1 introducing him as a brave and honorable man. He is reluctant to reveal the true nature of The Night’s Watch to Jon, despite his position as the First Ranger, and the show looked as though Benjen would become a main character and possible equivalent to Ned.

However, while his disappearance is a catalyst for Jon’s character development, the show does little else with him, leaving fans with several unanswered questions about Benjen Stark. After a seemingly fascinating journey, surviving being stabbed by the White Walkers and saved by the Children of the Forest, one fan theory suggests that Benjen is not as dead as the show later appeared to imply.

As the youngest of the Stark children, Rickon does not have a great role to play in the show for the first seasons. He is generally seen with his direwolf, Shaggydog, or playing. However, Rickon Stark’s death in the season 6 episode “Battle of the Bastards” at the hands of Ramsey Bolton ensures that he remains a memorable, if tragic, member of the Stark family.

Of all the Stark family’s Game of Thrones character arcs, Rickon’s is one of the least developed as he never had the chance to grow older, but he still affected the events of the show. Helplessly witnessing his death had a major effect on Jon, setting the events of the battle into motion. Unfortunately, George R. R. Martin’s books do not explore his character much either.

While Lyanna Stark only appears onscreen during flashback scenes, she is the catalyst for the major events in Game of Thrones. Originally betrothed to Robert Baratheon, who never got over her death, she fell in love with Rhaegar Targaryen, secretly marrying him and giving birth to their child. Though Lyanna died in childbirth, Robert’s belief that she was murdered fueled his rage against the Targaryens.

Lyanna is Ned’s sister, and most of what we know about her is told through Ned, who often compares her to the fierce and independent Arya. Now, another Game of Thrones spinoff will tell her story, but unlike the other stories set in Westeros, this will play out as a theater production at the Royal Shakespeare Theatre in Stratford-upon-Avon, UK,

For fans who missed Game of Thrones’ controversial King Bran setup at the start of the series, Bran Stark’s character arc is one of the least predictable in the entire series. The Stark family’s second son was shown to be mischievous, with a talent for climbing, before Jaime’s attempted murder left him paralyzed, with the Three Eyed Raven mysteriously telling him that he would fly.

Bran might not have been the most well-written character, especially as the series progressed, but he was a solid addition to the show. With noble intentions and a focus on serving the realm rather than a family legacy, Bran Stark’s eventual position as the King was not a bad choice, but it suffered from bad writing and was not set up well enough in advance.

As the Lady of Winterfell and Ned’s wife, Catelyn is one of the most divisive characters in Game of Thrones who is not an outright villain or antihero. Her treatment of Jon was criticized, but her commitment to the Stark way of life is clear, and she has flaws like most well-written characters. Still, there was more potential for Catelyn’s role in the show.

Catelyn was originally going to be played by Jennifer Ehle, who filmed the pilot but did not return for the rest of the show, with Michelle Fairley taking her place.

Catelyn Stark does not suffer from the final seasons’ lapse in writing due to her death in The Red Wedding in the episode “The Rains of Castamere.” However, if Game of Thrones had followed the source material, Catelyn would have returned as Lady Stoneheart, the cold and vengeful undead character left after being resurrected, whose role in the story is currently unfinished.

Ned and Catelyn’s eldest son and the heir to Winterfell, Robb Stark, had one of the best-written character arcs in Game of Thrones. Robb looked set up to be one of the show’s heroes, taking on the role of The King in the North and showing himself to be brave, good at commanding, and dangerous when underestimated. However, like Ned, this did not save him.

Robb was killed in the Red Wedding massacre before he had the chance to reveal his full potential. The Game of Thrones show changed Robb’s character considerably, with his choices being more impulsive than logical as the books present. However, this leads to the infamous Red Wedding, which has gone down in fantasy TV legend as one of the best scenes of all time.

Jon Snow’s ending brought his Game of Thrones story arc full-circle, with him being sent to the Wall after killing Daenerys Targaryen. However, his greatest ambition had been to go beyond the Wall in the first place, and this bittersweet ending was one of the most fitting possibilities for a character who once looked as though he would take the throne.

Eldest daughter and eventually “Queen of the North”

Son of Lyanna Stark and Rhaegar Targaryen, but brought up as Ned Stark’s bastard

Assumed to be Ned Stark’s bastard, Jon is the son of Lyanna Stark and Rhaegar Targaryen, so while he could be considered among the best Targaryens in Game of Thrones, he also belongs with House Stark. Jon was raised alongside the Stark children, who have always seen him as a brother, and his commitment to the North is fitting for the member of the Stark family.

Out of all the characters in Game of Thrones, the Stark family’s youngest daughter Arya was often the most exciting. Early on, she tells Ned “that’s not me” when he presents a marriage and children as her future, and she looks set to forge her own path. The moment Ned allows her to take sword fighting lessons is one of the best for their relationship.

Arya’s eventual fate gives her the adventurous life that she always wanted, and she is the character that most Game of Thrones fans still rooted for, even by the end of the show. Now that an Arya Stark sequel is reportedly in development, this may satisfy viewers who want to see more of the iconic character as she leaves to discover “what’s West of Westeros.”

For viewers familiar with either the source material or Sean Bean’s work, the fact that Ned Stark dies in the show’s first season would not have come as a surprise. However, for many others, Ned’s execution was one of the most shocking scenes in Game of Thrones, and it is this moment that set the events into motion.

The head of the Stark family was one of the most morally-upstanding characters in the show, setting aside his reputation to protect his sister, and remaining committed to justice at his own expense. Unfortunately, Ned’s goodness was no match for the characters who knew how to “play the game of thrones,” but his legacy and lessons lived on in his surviving children.

Sansa Stark’s beginning as a naive and idealistic child did not endear her to Game of Thrones viewers, especially when she put Joffrey above her family. However, by the time she tells Littlefinger “I’m a slow learner, it’s true. But I learn,” Sansa had become one of the best Game of Thrones characters, and a fantasy genre icon.

The Stark family’s eldest daughter has some of Game of Thrones’ most cathartic revenge scenes. However, unlike many other characters before her, these felt well-earned after a long journey in the show. Sansa grew to embody the values of House Stark, and her eventual crowning as Quen of the North was the perfect ending for her, and for House Stark’s legacy.

Game Of Thrones ](/db/tv-show/game-of-thrones/)

](/tag/action-movies/)

](/tag/adventure/)

](/tag/fantasy/)

2011 - 2019-00-00

David Benioff, D.B. Weiss

Kit Harington

window.isUserVerified = false;

document.addEventListener(‘DOMContentLoaded’, function () { var queryString = window.location.search || ”; var keyValPairs = []; var params = {};

queryString = queryString.substr(1); if (queryString.length) keyValPairs = queryString.split(’&’); for (var i = 0; i

/** For Read More button on LP **/ window.toggleReadmoreButton=()=>{ let e=document.getElementsByClassName(‘listing-desc’);

const QUIZ_BANK = [ gameName: “Game of Thrones”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/game-of-thrones-quiz-dark-1.png”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/game-of-thrones-quiz-light-1.png”, sentinelSlug: “game-of-thrones-quiz”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/01/the-catspaw-dagger-on-a-history-of-the-seven-kingdoms-in-game-of-thrones.jpg”, “Who Created A Song of Ice and Fire?”, “George R.R. Martin”, “Brandon Sanderson”, “James S.A. Corey”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/jon-snow-baby-game-of-thrones.png”, “Who is Jon Snow’s Mother?”, “Lyanna Stark”, “Ashara Dayne”, “Catelyn Stark”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/beric-dondarrion-game-of-thrones.png”, “How Many Times Does Beric Dondarrion Die?”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/house-lannister-game-of-thrones.png”, “What is House Lannister’s Motto?”, “Hear Me Roar!”, “A Lannister Always Pays His Debts”, “So End Our Foes”, “Honor, Not Honors”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/rob-stark-game-of-thrones.png”, “How Many Battles Does Robb Stark Lose?”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/qyburn-game-of-thrones.png”, “Who Saves Qyburn’s Life?”, “Jaime Lannister”, “Cersei Lannister”, “Brienne of Tarth”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/white-walker-game-of-thrones.png”, “Who Was the First Character to Kill a White Walker?”, “Samwell Tarly”, “Qhorin Halfhand”, “Jeor Mormont”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/jaime-lannister-game-of-thrones.png”, “What is the Name of Jaime Lannister’s Valyrian Steel Sword?”, “Widow’s Wail”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/viserys-daenerys-game-of-thrones.png”, “How Many Targaryens Are Alive at the Start of Game of Thrones?”, “https://static0.gamerantimages.com/wordpress/wp-content/uploads/2026/02/long-night-game-of-thrones.png”, “What is the Longest Episode of Game of Thrones?”, “The Long Night”, “The Iron Throne”, “The Dragon and the Wolf”,

const ACTIVE_QUIZ_INDEX = 0; const ACTIVE_QUIZ = QUIZ_BANK[ACTIVE_QUIZ_INDEX] || QUIZ_BANK[0];

const QUIZ_SETTINGS = { title: ACTIVE_QUIZ?.gameName || “GameRant Quiz”, date: ACTIVE_QUIZ?.date || "", secondsPerQuestion: { easy: 15, medium: 10, hard: 5 },

const DIFFICULTY_MULTIPLIERS = { easy: { correct: 100, time: 10 }, medium: { correct: 150, time: 15 }, hard: { correct: 200, time: 20 },

const GAME_SLUG = ACTIVE_QUIZ?.sentinelSlug || “game-name-quiz”;

function trackSentinel(category, action, label = GAME_SLUG) { if (window.websiteSentinel?.sendEvent) { window.websiteSentinel.sendEvent(category, action, label);

function trackGameStart() { trackSentinel(“mini-game”, “game_start”, GAME_SLUG); function trackGameEnd() { trackSentinel(“mini-game”, “game_end”, GAME_SLUG);

function shuffle(arr) { const a = arr.slice(); for (let i = a.length - 1; i > 0; i—) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]];

function ext(url) { const clean = String(url || "") .split(”#”)[0]; const dot = clean.lastIndexOf(”.”); return dot >= 0 ? clean.slice(dot + 1).toLowerCase() : "";

function clamp(n, min, max) { return Math.max(min, Math.min(max, n));

function setFeedback(html, kind = "") { if (!els.feedback) return; els.feedback.classList.remove(“good”, “bad”); if (kind) els.feedback.classList.add(kind); els.feedback.innerHTML = html || "";

function crossfadeTo(nextNode) { const slot = els.mediaSlot; if (!slot) return;

const layer = document.createElement(“div”); layer.className = “mediaLayer”; layer.appendChild(nextNode);

slot.appendChild(layer);

requestAnimationFrame(() => { layer.classList.add(“is-live”);

layer.addEventListener( “transitionend”, const layers = Array.from(slot.querySelectorAll(“.mediaLayer”)); layers.slice(0, -1).forEach((l) => l.remove()); { once: true },

const PRELOAD = { imgs: new Map(), vids: new Map(), auds: new Map(),

function normalizeQuestions(raw) { return (raw || []).map((row) => { const [num, type, mediaUrl, question, a1, a2, a3, a4] = row; num: Number(num), type: String(type || "").toLowerCase(), mediaUrl: String(mediaUrl || ""), question: String(question || ""), correct: String(a1 || ""), String(a1 || ""), String(a2 || ""), String(a3 || ""), String(a4 || ""),

function pickQuestions(allQuestions, count) { const shuffled = shuffle(allQuestions); return shuffled.slice(0, Math.min(count, shuffled.length));

function uniqueMediaUrlsFromRaw(rawQuestions) { const set = new Set(); normalizeQuestions(rawQuestions).forEach((q) => { if (q.mediaUrl) set.add(q.mediaUrl); return […set];

function preloadAllMedia() { const urls = uniqueMediaUrlsFromRaw( ACTIVE_QUIZ && ACTIVE_QUIZ.questions ? ACTIVE_QUIZ.questions : [], urls.forEach((url) => { const e = ext(url); const isVideoLike = e === “mp4” || e === “webm” || e === “ogg”; const isAudioLike = e === “mp3” || e === “wav” || e === “m4a” || e === “aac” || e === “flac”;

if (!isVideoLike && !isAudioLike) { if (PRELOAD.imgs.has(url)) return; const im = new Image(); im.decoding = “async”; im.loading = “eager”; PRELOAD.imgs.set(url, im);

if (isVideoLike) { if (PRELOAD.vids.has(url)) return; const v = document.createElement(“video”); v.preload = “auto”; PRELOAD.vids.set(url, v);

if (isAudioLike) { if (PRELOAD.auds.has(url)) return; const a = document.createElement(“audio”); a.preload = “auto”; PRELOAD.auds.set(url, a);

PRELOAD.done = true;

root: document.getElementById(“grntg”), stage: document.getElementById(“stage”), qmWrap: document.getElementById(“qmWrap”), dummyShell: document.getElementById(“dummyShell”),

panelStart: document.getElementById(“panelStart”), panelQuiz: document.getElementById(“panelQuiz”), panelResults: document.getElementById(“panelResults”),

uiTitle: document.getElementById(“uiTitle”), uiDate: document.getElementById(“uiDate”), startLogo: document.getElementById(“startLogo”),

difficultyShell: document.getElementById(“difficultyShell”), difficultySelect: document.getElementById(“difficultySelect”),

startBtn: document.getElementById(“startBtn”), quitBtn: document.getElementById(“quitBtn”), playAgainBtn: document.getElementById(“playAgainBtn”),

qCountText: document.getElementById(“qCountText”), qText: document.getElementById(“qText”), mediaFrame: document.getElementById(“mediaFrame”), mediaSlot: document.getElementById(“mediaSlot”), answers: document.getElementById(“answers”), feedback: document.getElementById(“feedback”),

timerBar: document.getElementById(“timerBar”), timerFill: document.getElementById(“timerFill”),

rFinalBig: document.getElementById(“rFinalBig”), rBreakdown: document.getElementById(“rBreakdown”),

function mountQuestionMarks() { if (!els.qmWrap) return; els.qmWrap.innerHTML = "";

window.matchMedia && window.matchMedia(“(prefers-reduced-motion: reduce)“).matches; if (reduce) return;

const count = 16; for (let i = 0; i { const active = p.key === which; p.el.classList.toggle(“is-active”, active); p.el.setAttribute(“aria-hidden”, active ? “false” : “true”);

els.root.classList.toggle(“is-start”, which === “start”); els.root.classList.toggle(“is-quiz”, which === “quiz”); els.root.classList.toggle(“is-results”, which === “results”);

const state = { correctCount: 0,

difficulty: “easy”, perQuestionSeconds: 0,

qTimerStartTs: 0,

totalTimeRemaining: 0, pendingAdvance: false,

activeMedia: null, activePlayBtn: null,

function clearQuestionTimer() { if (state.qRafId) { cancelAnimationFrame(state.qRafId); state.qRafId = null; state.qTimerStartTs = 0;

function stopActiveMedia() { if (state.activeMedia) { state.activeMedia.pause(); state.activeMedia = null; els.mediaFrame.querySelectorAll(“video,audio”).forEach((m) => {

if (state.activePlayBtn) { renderPlayIcon(state.activePlayBtn, false); state.activePlayBtn = null;

function isDarkMode() { window.matchMedia && window.matchMedia(“(prefers-color-scheme: dark)“).matches

function applyLogo() { const light = ACTIVE_QUIZ?.logoLightUrl || ""; const dark = ACTIVE_QUIZ?.logoDarkUrl || light; if (!els.startLogo) return; els.startLogo.src = isDarkMode() ? dark : light; els.startLogo.alt = QUIZ_SETTINGS.title || “Quiz”;

function applySettingsToStart() { els.uiTitle.textContent = QUIZ_SETTINGS.title || “GameRant Quiz”;

const d = QUIZ_SETTINGS.date; els.uiDate.style.display = ""; els.uiDate.textContent = d; els.uiDate.style.display = “none”; els.uiDate.textContent = "";

state.timed = !!QUIZ_SETTINGS.timed; els.difficultyShell.style.display = state.timed ? "" : “none”;

if (state.timed && els.difficultySelect) { els.difficultySelect.value = “medium”;

state.difficulty = state.timed ? els.difficultySelect.value || “easy”

function resetRun() { stopActiveMedia(); clearQuestionTimer();

const raw = ACTIVE_QUIZ && ACTIVE_QUIZ.questions ? ACTIVE_QUIZ.questions : []; const normalizedAll = normalizeQuestions(raw); const picked = pickQuestions(normalizedAll, 10);

state.questions = picked; state.correctCount = 0; state.totalTimeRemaining = 0;

state.pendingAdvance = false; state.qToken = 0;

state.timed = !!QUIZ_SETTINGS.timed; state.difficulty = state.timed ? els.difficultySelect.value || “easy” state.perQuestionSeconds = state.timed ? QUIZ_SETTINGS.secondsPerQuestion[state.difficulty] || 10

els.timerBar.style.display = state.timed ? "" : “none”; if (state.timed) { state.qTimeLeft = state.perQuestionSeconds; els.timerFill.style.width = “100%”;

function lockAnswers() { .querySelectorAll(“button”) .forEach((b) => b.setAttribute(“aria-disabled”, “true”)); function unlockAnswers() { .querySelectorAll(“button”) .forEach((b) => b.removeAttribute(“aria-disabled”)); function clearAnswerHighlights() { .querySelectorAll(“button”) .forEach((b) => b.classList.remove(“is-correct”, “is-wrong”));

function highlightClickedOnly(clickedBtn, isCorrect, correctText) { clearAnswerHighlights();

if (clickedBtn) { clickedBtn.classList.add(isCorrect ? “is-correct” : “is-wrong”);

if (correctText) { const correctBtn = […els.answers.querySelectorAll(“button”)].find( (b) => b.dataset.answer === correctText, if (correctBtn) correctBtn.classList.add(“is-correct”);

function resetPerQuestionTimer() { if (!state.timed) return; clearQuestionTimer();

state.qTimeLeft = state.perQuestionSeconds; state.qTimerStartTs = 0;

els.timerFill.style.width = “100%”;

function setTimerBar(remaining) { if (!state.timed) return; state.perQuestionSeconds > 0 ? remaining / state.perQuestionSeconds : 0; els.timerFill.style.width = ${clamp(frac, 0, 1) * 100}%;

function startQuestionTimerTicking(token) { if (!state.timed) return; if (state.qRafId) return; if (token !== state.qToken) return;

state.qTimerStartTs = performance.now();

const tick = () => { if (token !== state.qToken) return;

const elapsed = (performance.now() - state.qTimerStartTs) / 1000; const remaining = Math.max(0, state.perQuestionSeconds - elapsed);

state.qTimeLeft = remaining; setTimerBar(remaining);

if (remaining Time! It was ${q.correct}.`, “bad”); scheduleAdvanceOnce();

state.qRafId = requestAnimationFrame(tick);

state.qRafId = requestAnimationFrame(tick);

function renderPlayIcon(btn, isPlaying) { btn.innerHTML = ""; if (isPlaying) { const wrap = document.createElement(“div”); wrap.className = “pauseicon”; wrap.innerHTML = ""; btn.appendChild(wrap); const tri = document.createElement(“div”); tri.className = “playicon”; btn.appendChild(tri);

function waitForImageReady(img) { if (img.decode) return img.decode().catch(() => {}); return new Promise((res) => { if (img.complete) return res(); img.onload = () => res(); img.onerror = () => res();

function waitForVideoReady(vid) { return new Promise((res) => { const done = () => { const cleanup = () => { vid.removeEventListener(“loadeddata”, done); vid.removeEventListener(“canplay”, done); vid.removeEventListener(“error”, done);

vid.addEventListener(“loadeddata”, done, { once: true }); vid.addEventListener(“canplay”, done, { once: true }); vid.addEventListener(“error”, done, { once: true });

if (vid.readyState >= 2) done();

function waitForAudioReady(aud) { return new Promise((res) => { const done = () => { const cleanup = () => { aud.removeEventListener(“canplay”, done); aud.removeEventListener(“loadedmetadata”, done); aud.removeEventListener(“error”, done);

aud.addEventListener(“canplay”, done, { once: true }); aud.addEventListener(“loadedmetadata”, done, { once: true }); aud.addEventListener(“error”, done, { once: true });

if (aud.readyState >= 1) done();

async function buildMedia(question, token) { const frame = els.mediaFrame; const slot = els.mediaSlot; if (!slot) return;

stopActiveMedia();

frame.classList.remove(“audio”);

const t = question.type;

let nextEl = null; let readyPromise = Promise.resolve();

if (t === “image”) { const img = document.createElement(“img”); img.alt = “Question image”; img.decoding = “async”; img.loading = “eager”; img.src = question.mediaUrl; readyPromise = waitForImageReady(img); } else if (t === “video”) { const vid = document.createElement(“video”); vid.src = question.mediaUrl; vid.playsInline = true; vid.controls = true; vid.preload = “auto”;

state.activeMedia = vid;

if (state.timed) { vid.addEventListener( if (token !== state.qToken) return; startQuestionTimerTicking(token); { once: true },

readyPromise = waitForVideoReady(vid); } else if (t === “audio”) { frame.classList.add(“audio”);

const wrap = document.createElement(“div”); wrap.style.position = “absolute”; wrap.style.inset = “0”;

const overlay = document.createElement(“div”); overlay.className = “playbtn”;

const play = document.createElement(“button”); play.type = “button”; play.setAttribute(“aria-label”, “Play audio”); renderPlayIcon(play, false);

overlay.appendChild(play); wrap.appendChild(overlay);

const url = question.mediaUrl; const e = ext(url);

if (e === “mp4”) { player = document.createElement(“video”); player.src = url; player.preload = “auto”; player.playsInline = true; player.muted = false;

player.style.position = “absolute”; player.style.left = “-99999px”; player.style.top = “0”; player.style.width = “1px”; player.style.height = “1px”; wrap.appendChild(player); player = document.createElement(“audio”); player.src = url; player.preload = “auto”; wrap.appendChild(player);

state.activeMedia = player; state.activePlayBtn = play;

if (state.timed) { player.addEventListener( if (token !== state.qToken) return; startQuestionTimerTicking(token); { once: true },

play.addEventListener(“click”, () => { const isPlaying = !player.paused && !player.ended;

if (isPlaying) { player.pause(); renderPlayIcon(play, false);

renderPlayIcon(play, true); renderPlayIcon(play, false);

player.addEventListener(“ended”, () => { renderPlayIcon(play, false);

readyPromise = waitForAudioReady(player); const fallback = document.createElement(“div”); fallback.style.padding = “14px”; fallback.style.color = “var(—ink)”; fallback.style.opacity = “.9”; fallback.textContent = “Unsupported media type.”; nextEl = fallback; readyPromise = Promise.resolve();

await readyPromise;

if (token !== state.qToken) return;

crossfadeTo(nextEl);

if (t === “image” && state.timed) { startQuestionTimerTicking(token);

function currentQuestion() { return state.questions[state.idx] || null;

function scheduleAdvanceOnce() { if (state.pendingAdvance) return; state.pendingAdvance = true; setTimeout(() => advanceQuestion(), 2500);

async function renderQuestion() { stopActiveMedia(); clearAnswerHighlights(); setFeedback(""); unlockAnswers(); resetPerQuestionTimer();

state.pendingAdvance = false; state.qToken += 1; const token = state.qToken;

const q = currentQuestion();

els.qCountText.textContent = QUESTION ${state.idx + 1}/${state.questions.length}; els.qText.textContent = q.question || ”—”;

if (state.timed) { els.timerBar.style.display = ""; els.timerFill.style.width = “100%”; els.timerBar.style.display = “none”;

await buildMedia(q, token);

const shuffled = shuffle( q.answers.map((text, i) => ({ text, isCorrect: i === 0 })),

els.answers.innerHTML = ""; shuffled.forEach((opt) => { const btn = document.createElement(“button”); btn.type = “button”; btn.className = “answerbtn”; btn.textContent = opt.text; btn.dataset.answer = opt.text; btn.addEventListener(“click”, () => onAnswer(btn, opt.isCorrect)); els.answers.appendChild(btn);

function onAnswer(clickedBtn, isCorrect) { const anyLocked = […els.answers.querySelectorAll(“button”)].every( (b) => b.getAttribute(“aria-disabled”) === “true”, if (anyLocked || state.pendingAdvance) return;

clearQuestionTimer();

stopActiveMedia();

const q = currentQuestion(); if (!q) return;

if (isCorrect) state.correctCount += 1;

highlightClickedOnly(clickedBtn, isCorrect, q.correct); scheduleAdvanceOnce();

if (isCorrect) { setFeedback(✅ Correct! It was ${q.correct}., “good”); setFeedback(❌ Nope. It was ${q.correct}., “bad”);

function advanceQuestion() { stopActiveMedia(); clearQuestionTimer();

if (state.timed) { state.totalTimeRemaining += Math.max(0, Math.floor(state.qTimeLeft || 0));

state.idx += 1;

if (state.idx >= state.questions.length) {

renderQuestion();

function computeFinalScore() { const total = state.questions.length; const correct = state.correctCount;

DIFFICULTY_MULTIPLIERS[state.difficulty] || DIFFICULTY_MULTIPLIERS.easy; const correctPts = correct * mult.correct; const timePts = state.totalTimeRemaining * mult.time;

totalPoints: correctPts + timePts,

function finishQuiz() { trackGameEnd(); stopActiveMedia(); clearQuestionTimer();

const total = state.questions.length; const correct = state.correctCount;

if (state.timed) { const s = computeFinalScore();

els.rFinalBig.textContent = ${s.totalPoints.toLocaleString()} Points; els.rBreakdown.innerHTML = Correct Answers: ${s.correctPts.toLocaleString()} Points (${correct}/${total}) + Time Bonus: ${s.timePts.toLocaleString()} Points (${state.totalTimeRemaining} Seconds Remaining); els.rFinalBig.textContent = ${correct}/${total}; els.rBreakdown.textContent = "";

showPanel(“results”);

function updateDummyForSettings() { if (!els.dummyShell) return;

if (!els.dummyShell.dataset.built) { els.dummyShell.dataset.built = “1”; els.dummyShell.innerHTML = `

WHICH GAME IS THIS?