diff --git a/index.html b/index.html
new file mode 100644
index 0000000..0d07995
--- /dev/null
+++ b/index.html
@@ -0,0 +1,122 @@
+
+
+
+
+
+ 學科刷題系統
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..84e3f0e
--- /dev/null
+++ b/script.js
@@ -0,0 +1,469 @@
+const elements = {
+ menu: document.getElementById("menu"),
+ questionSection: document.getElementById("questionSection"),
+ questionNumber: document.getElementById("questionNumber"),
+ questionText: document.getElementById("questionText"),
+ questionFigure: document.getElementById("questionFigure"),
+ questionImage: document.getElementById("questionImage"),
+ imageCaption: document.getElementById("imageCaption"),
+ options: document.getElementById("optionsContainer"),
+ feedback: document.getElementById("feedback"),
+ prevBtn: document.getElementById("prevBtn"),
+ nextBtn: document.getElementById("nextBtn"),
+ jumpForm: document.getElementById("jumpForm"),
+ jumpInput: document.getElementById("jumpInput"),
+ bookmarkBtn: document.getElementById("bookmarkBtn"),
+ backToMenu: document.getElementById("backToMenu"),
+ statusToggle: document.getElementById("statusToggle"),
+ statusPanel: document.getElementById("statusPanel"),
+ closeStatus: document.getElementById("closeStatus"),
+ statusList: document.getElementById("statusList"),
+ progressContainer: document.getElementById("progressContainer"),
+ progressCount: document.getElementById("progressCount"),
+ progressTotal: document.getElementById("progressTotal"),
+ progressFill: document.getElementById("progressFill"),
+ finishBtn: document.getElementById("finishBtn"),
+ modeLabel: document.getElementById("modeLabel"),
+ resultsModal: document.getElementById("resultsModal"),
+ closeResults: document.getElementById("closeResults"),
+ resultsBody: document.getElementById("resultsBody"),
+ modalBack: document.getElementById("modalBack"),
+ modalReview: document.getElementById("modalReview"),
+ themeToggle: document.getElementById("themeToggle")
+};
+
+const state = {
+ questions: [],
+ mode: null,
+ questionOrder: [],
+ currentIndex: 0,
+ userAnswers: [],
+ bookmarks: new Set(),
+ showSolutions: false
+};
+
+const MODE_TEXT = {
+ practice: "自由參考模式",
+ custom: "自訂範圍測驗",
+ exam: "模擬考試模式"
+};
+
+fetch("question.json")
+ .then((res) => {
+ if (!res.ok) {
+ throw new Error("無法載入題庫");
+ }
+ return res.json();
+ })
+ .then((data) => {
+ state.questions = Array.isArray(data) ? data : [];
+ if (!state.questions.length) {
+ showMessage("尚未提供題目資料。", true);
+ }
+ })
+ .catch((err) => {
+ console.error(err);
+ showMessage("題庫載入失敗,請稍後再試。", true);
+ });
+
+function showMessage(message, sticky = false) {
+ elements.feedback.textContent = message;
+ if (sticky) {
+ elements.feedback.classList.remove("correct", "incorrect");
+ }
+}
+
+function startPractice() {
+ startMode("practice", state.questions.map((_, idx) => idx));
+}
+
+function startCustomRange(start, end) {
+ const total = state.questions.length;
+ if (!total) return;
+ const realStart = Math.max(1, Math.min(start, end));
+ const realEnd = Math.min(total, Math.max(start, end));
+ const available = [];
+ for (let i = realStart - 1; i < realEnd; i += 1) {
+ available.push(i);
+ }
+ if (!available.length) {
+ alert("指定範圍內沒有題目。");
+ return;
+ }
+ const selection = shuffleArray(available).slice(0, Math.min(50, available.length));
+ startMode("custom", selection);
+}
+
+function startExam() {
+ if (!state.questions.length) return;
+ const indexes = state.questions.map((_, idx) => idx);
+ const selection = shuffleArray(indexes).slice(0, Math.min(50, indexes.length));
+ startMode("exam", selection);
+}
+
+function shuffleArray(arr) {
+ const copy = [...arr];
+ for (let i = copy.length - 1; i > 0; i -= 1) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [copy[i], copy[j]] = [copy[j], copy[i]];
+ }
+ return copy;
+}
+
+function startMode(mode, order) {
+ if (!order.length) {
+ alert("沒有可使用的題目。");
+ return;
+ }
+ state.mode = mode;
+ state.questionOrder = order;
+ state.currentIndex = 0;
+ state.userAnswers = Array(order.length).fill(null);
+ state.bookmarks = new Set();
+ state.showSolutions = mode === "practice";
+ elements.modeLabel.textContent = `模式:${MODE_TEXT[mode] || ""}`;
+
+ elements.menu.classList.add("hidden");
+ elements.questionSection.classList.remove("hidden");
+ elements.progressContainer.classList.remove("hidden");
+ elements.finishBtn.classList.toggle("hidden", mode === "practice");
+ elements.feedback.textContent = "";
+ elements.feedback.classList.remove("correct", "incorrect");
+
+ elements.progressTotal.textContent = state.questionOrder.length;
+ updateQuestionView();
+ updateProgress();
+ updateStatusPanel();
+ closeStatusPanel();
+}
+
+function updateQuestionView() {
+ const qIndex = state.questionOrder[state.currentIndex];
+ const originalNumber = qIndex + 1;
+ const total = state.questionOrder.length;
+ const currentDisplay = state.currentIndex + 1;
+ elements.questionNumber.textContent = `第 ${originalNumber} 題(${currentDisplay}/${total})`;
+
+ const question = state.questions[qIndex];
+ elements.questionText.textContent = question.question || "";
+
+ if (question.questionimage) {
+ elements.questionFigure.classList.remove("hidden");
+ elements.questionImage.src = `image/${question.questionimage}`;
+ elements.questionImage.alt = question.question || "題目圖片";
+ elements.imageCaption.textContent = "";
+ } else {
+ elements.questionFigure.classList.add("hidden");
+ elements.questionImage.src = "";
+ elements.imageCaption.textContent = "";
+ }
+
+ elements.options.innerHTML = "";
+ const optionSuffix = question.optionend || "";
+ question.option.forEach((text, idx) => {
+ const btn = document.createElement("button");
+ btn.type = "button";
+ btn.className = "option-btn";
+ btn.dataset.optionIndex = idx;
+ const prefix = String.fromCharCode(65 + idx);
+ const prefixSpan = document.createElement("span");
+ prefixSpan.className = "option-prefix";
+ prefixSpan.textContent = `${prefix}.`;
+ const textSpan = document.createElement("span");
+ textSpan.className = "option-text";
+ textSpan.textContent = `${text}${optionSuffix}`;
+ btn.append(prefixSpan, textSpan);
+ if (state.userAnswers[state.currentIndex] === idx) {
+ btn.classList.add("selected");
+ }
+ btn.addEventListener("click", () => handleAnswer(idx));
+ elements.options.appendChild(btn);
+ });
+
+ const isBookmarked = state.bookmarks.has(state.currentIndex);
+ elements.bookmarkBtn.setAttribute("aria-pressed", isBookmarked);
+ elements.bookmarkBtn.classList.toggle("active", isBookmarked);
+
+ renderFeedback();
+ updateNavButtons();
+ updateStatusPanel();
+}
+
+function handleAnswer(optionIndex) {
+ state.userAnswers[state.currentIndex] = optionIndex;
+ updateOptionSelection();
+ if (state.mode === "practice") {
+ renderFeedback();
+ } else if (state.showSolutions) {
+ renderFeedback();
+ } else {
+ elements.feedback.textContent = `已選擇選項 ${String.fromCharCode(65 + optionIndex)}`;
+ elements.feedback.classList.remove("correct", "incorrect");
+ }
+ updateProgress();
+ updateStatusPanel();
+}
+
+function updateOptionSelection() {
+ const buttons = elements.options.querySelectorAll(".option-btn");
+ buttons.forEach((btn) => {
+ const idx = Number(btn.dataset.optionIndex);
+ btn.classList.toggle("selected", state.userAnswers[state.currentIndex] === idx);
+ });
+}
+
+function renderFeedback() {
+ const qIndex = state.questionOrder[state.currentIndex];
+ const question = state.questions[qIndex];
+ const answer = question.answer;
+ const selected = state.userAnswers[state.currentIndex];
+ const optionSuffix = question.optionend || "";
+
+ elements.feedback.classList.remove("correct", "incorrect");
+ elements.feedback.innerHTML = "";
+
+ if (selected == null) {
+ if (state.showSolutions && state.mode !== "practice") {
+ const correctText = question.option[answer] + optionSuffix;
+ elements.feedback.innerHTML = `正確答案:${String.fromCharCode(65 + answer)}. ${correctText}
`;
+ }
+ return;
+ }
+
+ const isCorrect = selected === answer;
+ const correctText = question.option[answer] + optionSuffix;
+ const explainBlock = question.explain ? `${question.explain}
` : "";
+ const psBlock = question.ps ? `${question.ps}
` : "";
+
+ if (state.mode === "practice" || state.showSolutions) {
+ elements.feedback.classList.add(isCorrect ? "correct" : "incorrect");
+ const statusLine = isCorrect ? "答對了!" : "答錯了。";
+ elements.feedback.innerHTML = `${statusLine}
正確答案:${String.fromCharCode(65 + answer)}. ${correctText}
${explainBlock}${psBlock}`;
+ } else {
+ elements.feedback.textContent = `已選擇選項 ${String.fromCharCode(65 + selected)}`;
+ }
+}
+
+function updateProgress() {
+ const answered = state.userAnswers.filter((ans) => ans != null).length;
+ const total = state.questionOrder.length;
+ elements.progressCount.textContent = answered;
+ elements.progressTotal.textContent = total;
+ const percent = total ? (answered / total) * 100 : 0;
+ elements.progressFill.style.width = `${percent}%`;
+}
+
+function updateNavButtons() {
+ elements.prevBtn.disabled = state.currentIndex === 0;
+ elements.nextBtn.disabled = state.currentIndex === state.questionOrder.length - 1;
+}
+
+function goToQuestion(targetIndex) {
+ if (targetIndex < 0 || targetIndex >= state.questionOrder.length) return;
+ state.currentIndex = targetIndex;
+ updateQuestionView();
+ closeStatusPanel();
+}
+
+function updateStatusPanel() {
+ elements.statusList.innerHTML = "";
+ state.questionOrder.forEach((originalIndex, idx) => {
+ const item = document.createElement("button");
+ item.type = "button";
+ item.className = "status-item";
+ if (idx === state.currentIndex) {
+ item.classList.add("current");
+ }
+ if (state.userAnswers[idx] != null) {
+ item.classList.add("answered");
+ }
+ if (state.bookmarks.has(idx)) {
+ item.classList.add("bookmarked");
+ }
+ item.innerHTML = `#${originalIndex + 1}`;
+ if (state.bookmarks.has(idx)) {
+ item.innerHTML += '🔖';
+ }
+ item.addEventListener("click", () => goToQuestion(idx));
+ elements.statusList.appendChild(item);
+ });
+}
+
+function toggleBookmark() {
+ if (state.bookmarks.has(state.currentIndex)) {
+ state.bookmarks.delete(state.currentIndex);
+ } else {
+ state.bookmarks.add(state.currentIndex);
+ }
+ updateQuestionView();
+ updateStatusPanel();
+}
+
+function nextQuestion() {
+ if (state.currentIndex < state.questionOrder.length - 1) {
+ state.currentIndex += 1;
+ updateQuestionView();
+ }
+}
+
+function prevQuestion() {
+ if (state.currentIndex > 0) {
+ state.currentIndex -= 1;
+ updateQuestionView();
+ }
+}
+
+function handleJump(event) {
+ event.preventDefault();
+ const value = Number(elements.jumpInput.value);
+ if (!value) return;
+ const targetOriginal = value - 1;
+ const targetIndex = state.questionOrder.indexOf(targetOriginal);
+ if (targetIndex >= 0) {
+ goToQuestion(targetIndex);
+ elements.jumpInput.value = "";
+ } else {
+ alert("目前測驗中不包含此題號。");
+ }
+}
+
+function finishAssessment() {
+ if (state.mode === "practice") return;
+ const total = state.questionOrder.length;
+ const results = state.questionOrder.map((questionIdx, idx) => {
+ const question = state.questions[questionIdx];
+ const userAnswer = state.userAnswers[idx];
+ const correct = userAnswer === question.answer;
+ return {
+ questionNumber: questionIdx + 1,
+ userAnswer,
+ correctAnswer: question.answer,
+ correct
+ };
+ });
+
+ const answered = results.filter((item) => item.userAnswer != null).length;
+ const correctCount = results.filter((item) => item.correct).length;
+ const unanswered = total - answered;
+ const score = Math.round((correctCount / total) * 100);
+
+ elements.resultsBody.innerHTML = `
+
+
得分:${score} 分
+
+ - 作答題數:${answered} 題
+ - 答對題數:${correctCount} 題
+ - 未作答題數:${unanswered} 題
+
+
+ `;
+
+ elements.resultsModal.classList.remove("hidden");
+ state.showSolutions = true;
+ renderFeedback();
+}
+
+function closeResultsModal() {
+ elements.resultsModal.classList.add("hidden");
+}
+
+function returnToMenu() {
+ closeResultsModal();
+ state.mode = null;
+ state.questionOrder = [];
+ state.userAnswers = [];
+ state.bookmarks = new Set();
+ state.showSolutions = false;
+ elements.modeLabel.textContent = "";
+ elements.questionSection.classList.add("hidden");
+ elements.menu.classList.remove("hidden");
+ elements.progressContainer.classList.add("hidden");
+ closeStatusPanel();
+}
+
+function closeStatusPanel() {
+ elements.statusPanel.classList.remove("open");
+ elements.statusPanel.classList.add("hidden");
+ elements.statusPanel.setAttribute("aria-hidden", "true");
+ elements.statusToggle.setAttribute("aria-expanded", "false");
+}
+
+function toggleStatusPanel() {
+ if (elements.statusPanel.classList.contains("open")) {
+ closeStatusPanel();
+ } else {
+ elements.statusPanel.classList.remove("hidden");
+ elements.statusPanel.classList.add("open");
+ elements.statusPanel.setAttribute("aria-hidden", "false");
+ elements.statusToggle.setAttribute("aria-expanded", "true");
+ }
+}
+
+function applySavedTheme() {
+ const saved = localStorage.getItem("quiz-theme");
+ if (saved) {
+ document.documentElement.setAttribute("data-theme", saved);
+ }
+}
+
+function toggleTheme() {
+ const current = document.documentElement.getAttribute("data-theme") || "light";
+ const next = current === "dark" ? "light" : "dark";
+ document.documentElement.setAttribute("data-theme", next);
+ localStorage.setItem("quiz-theme", next);
+}
+
+applySavedTheme();
+
+document.querySelectorAll("button[data-mode]").forEach((btn) => {
+ btn.addEventListener("click", (event) => {
+ const mode = event.currentTarget.dataset.mode;
+ if (!state.questions.length) {
+ alert("題庫尚未載入完成。");
+ return;
+ }
+ if (mode === "practice") {
+ startPractice();
+ } else if (mode === "exam") {
+ startExam();
+ }
+ });
+});
+
+document.getElementById("customForm").addEventListener("submit", (event) => {
+ event.preventDefault();
+ if (!state.questions.length) {
+ alert("題庫尚未載入完成。");
+ return;
+ }
+ const start = Number(document.getElementById("startInput").value);
+ const end = Number(document.getElementById("endInput").value);
+ if (!start || !end) {
+ alert("請輸入有效的題號範圍。");
+ return;
+ }
+ startCustomRange(start, end);
+});
+
+elements.prevBtn.addEventListener("click", prevQuestion);
+elements.nextBtn.addEventListener("click", nextQuestion);
+elements.jumpForm.addEventListener("submit", handleJump);
+elements.bookmarkBtn.addEventListener("click", toggleBookmark);
+elements.backToMenu.addEventListener("click", returnToMenu);
+elements.statusToggle.addEventListener("click", toggleStatusPanel);
+elements.closeStatus.addEventListener("click", closeStatusPanel);
+elements.finishBtn.addEventListener("click", finishAssessment);
+elements.closeResults.addEventListener("click", closeResultsModal);
+elements.modalReview.addEventListener("click", closeResultsModal);
+elements.modalBack.addEventListener("click", returnToMenu);
+elements.themeToggle.addEventListener("click", toggleTheme);
+
+document.addEventListener("keydown", (event) => {
+ if (event.key === "Escape") {
+ if (!elements.resultsModal.classList.contains("hidden")) {
+ closeResultsModal();
+ } else if (elements.statusPanel.classList.contains("open")) {
+ closeStatusPanel();
+ }
+ }
+});
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..c4b72c9
--- /dev/null
+++ b/style.css
@@ -0,0 +1,494 @@
+:root {
+ --bg: #f5f5f5;
+ --surface: #ffffff;
+ --text: #1f1f1f;
+ --subtle-text: #555;
+ --accent: #2563eb;
+ --accent-contrast: #fff;
+ --border: #d9d9d9;
+ --success: #16a34a;
+ --error: #dc2626;
+}
+
+:root[data-theme="dark"], .dark {
+ --bg: #101418;
+ --surface: #1d242c;
+ --text: #e5ecf5;
+ --subtle-text: #9fb3c8;
+ --accent: #60a5fa;
+ --accent-contrast: #0b1120;
+ --border: #2d3845;
+ --success: #4ade80;
+ --error: #f87171;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ font-family: "Noto Sans TC", "Helvetica Neue", Arial, sans-serif;
+ background: var(--bg);
+ color: var(--text);
+ min-height: 100vh;
+}
+
+.app {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.top-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 1rem;
+}
+
+.title-area {
+ display: flex;
+ align-items: baseline;
+ gap: 1rem;
+ flex-wrap: wrap;
+}
+
+.mode-label {
+ font-size: 0.95rem;
+ color: var(--subtle-text);
+}
+
+.header-actions {
+ display: flex;
+ gap: 0.75rem;
+ align-items: center;
+}
+
+.icon-btn {
+ border: 1px solid var(--border);
+ background: var(--surface);
+ color: var(--text);
+ padding: 0.4rem 0.75rem;
+ border-radius: 999px;
+ cursor: pointer;
+ font-size: 0.95rem;
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
+}
+
+.icon-btn:hover,
+button.primary:hover,
+button.secondary:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px rgba(15, 23, 42, 0.15);
+}
+
+button.primary,
+button.secondary {
+ border-radius: 999px;
+ border: 1px solid transparent;
+ padding: 0.6rem 1.25rem;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
+}
+
+button.primary {
+ background: var(--accent);
+ color: var(--accent-contrast);
+ border-color: var(--accent);
+}
+
+button.secondary {
+ background: transparent;
+ color: var(--text);
+ border-color: var(--border);
+}
+
+button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ box-shadow: none;
+ transform: none;
+}
+
+.progress-container {
+ background: var(--surface);
+ border: 1px solid var(--border);
+ border-radius: 16px;
+ padding: 0.75rem 1rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.progress-text {
+ font-weight: 600;
+}
+
+.progress-bar {
+ width: 100%;
+ background: var(--border);
+ height: 12px;
+ border-radius: 999px;
+ overflow: hidden;
+}
+
+.progress-fill {
+ height: 100%;
+ width: 0;
+ background: var(--accent);
+ transition: width 0.2s ease;
+}
+
+.menu {
+ display: grid;
+ gap: 1.5rem;
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
+}
+
+.menu-card {
+ background: var(--surface);
+ border: 1px solid var(--border);
+ border-radius: 18px;
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
+}
+
+.menu-card h2 {
+ margin: 0;
+}
+
+.range-form {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.field {
+ display: flex;
+ flex-direction: column;
+ gap: 0.4rem;
+}
+
+input[type="number"] {
+ padding: 0.6rem 0.75rem;
+ border-radius: 12px;
+ border: 1px solid var(--border);
+ background: var(--surface);
+ color: var(--text);
+ font-size: 1rem;
+}
+
+.question-section {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.question-card {
+ background: var(--surface);
+ border: 1px solid var(--border);
+ border-radius: 20px;
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ box-shadow: 0 12px 35px rgba(15, 23, 42, 0.08);
+}
+
+.question-text {
+ font-size: 1.15rem;
+ line-height: 1.7;
+}
+
+.question-image {
+ margin: 0;
+ border: 1px solid var(--border);
+ border-radius: 16px;
+ overflow: hidden;
+ background: var(--bg);
+}
+
+.question-image img {
+ width: 100%;
+ display: block;
+}
+
+.options {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.option-btn {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 0.75rem;
+ border-radius: 16px;
+ padding: 0.75rem 1rem;
+ border: 1px solid var(--border);
+ background: var(--surface);
+ cursor: pointer;
+ text-align: left;
+ transition: background 0.2s ease, border-color 0.2s ease;
+}
+
+.option-btn:hover {
+ border-color: var(--accent);
+}
+
+.option-btn.selected {
+ border-color: var(--accent);
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
+}
+
+.option-prefix {
+ font-weight: 600;
+}
+
+.feedback {
+ min-height: 2rem;
+ font-weight: 600;
+}
+
+.feedback.correct {
+ color: var(--success);
+}
+
+.feedback.incorrect {
+ color: var(--error);
+}
+
+.feedback .explain,
+.feedback .ps {
+ font-weight: 400;
+ margin-top: 0.5rem;
+ color: var(--subtle-text);
+ line-height: 1.6;
+}
+
+.question-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.nav-buttons {
+ display: flex;
+ gap: 0.75rem;
+}
+
+.jump-form {
+ display: flex;
+ gap: 0.5rem;
+ align-items: center;
+}
+
+.jump-form input {
+ width: 90px;
+}
+
+.status-panel {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: min(320px, 90vw);
+ height: 100%;
+ background: var(--surface);
+ border-left: 1px solid var(--border);
+ box-shadow: -12px 0 30px rgba(15, 23, 42, 0.25);
+ transform: translateX(100%);
+ transition: transform 0.3s ease;
+ display: flex;
+ flex-direction: column;
+ padding: 1.25rem;
+ gap: 1rem;
+ z-index: 1000;
+}
+
+.status-panel.open {
+ transform: translateX(0);
+}
+
+.status-panel header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.status-legend {
+ display: flex;
+ gap: 0.75rem;
+ align-items: center;
+ font-size: 0.9rem;
+ flex-wrap: wrap;
+}
+
+.status-list {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
+ gap: 0.5rem;
+ overflow-y: auto;
+ padding-bottom: 1rem;
+}
+
+.status-item {
+ padding: 0.65rem 0.4rem;
+ border-radius: 12px;
+ border: 1px solid var(--border);
+ text-align: center;
+ cursor: pointer;
+ font-size: 0.9rem;
+ background: var(--surface);
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+}
+
+.status-item.current {
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
+}
+
+.status-item.answered {
+ border-color: var(--success);
+}
+
+.status-item.bookmarked {
+ border-color: var(--accent);
+}
+
+.status-item .bookmark-flag {
+ font-size: 0.75rem;
+}
+
+.dot {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ display: inline-block;
+}
+
+.dot.answered {
+ background: var(--success);
+}
+
+.dot.unanswered {
+ background: var(--border);
+}
+
+.dot.bookmarked {
+ background: var(--accent);
+}
+
+.modal {
+ position: fixed;
+ inset: 0;
+ background: rgba(15, 23, 42, 0.55);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 1rem;
+ z-index: 1200;
+}
+
+.modal.hidden,
+.hidden {
+ display: none;
+}
+
+.modal-content {
+ background: var(--surface);
+ border-radius: 20px;
+ padding: 1.5rem;
+ max-width: 520px;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ border: 1px solid var(--border);
+ box-shadow: 0 18px 45px rgba(15, 23, 42, 0.25);
+}
+
+.modal-actions {
+ display: flex;
+ justify-content: flex-end;
+ gap: 0.75rem;
+ flex-wrap: wrap;
+}
+
+.results-summary {
+ display: grid;
+ gap: 0.75rem;
+}
+
+.results-summary .score {
+ font-size: 1.4rem;
+ font-weight: 700;
+}
+
+.results-summary ul {
+ margin: 0;
+ padding-left: 1.2rem;
+ color: var(--subtle-text);
+}
+
+@media (max-width: 768px) {
+ .app {
+ padding: 1rem;
+ }
+
+ .question-card {
+ padding: 1.1rem;
+ }
+
+ .question-text {
+ font-size: 1.05rem;
+ }
+
+ .question-actions {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .nav-buttons,
+ .jump-form,
+ .modal-actions {
+ width: 100%;
+ }
+
+ .jump-form {
+ justify-content: space-between;
+ }
+
+ .jump-form input {
+ flex: 1;
+ }
+
+ .nav-buttons {
+ justify-content: space-between;
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ :root:not([data-theme="light"]) {
+ --bg: #101418;
+ --surface: #1d242c;
+ --text: #e5ecf5;
+ --subtle-text: #9fb3c8;
+ --accent: #60a5fa;
+ --accent-contrast: #0b1120;
+ --border: #2d3845;
+ --success: #4ade80;
+ --error: #f87171;
+ }
+}