<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PAB Central Stores — Professional Training Assessment FY2026</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">

<!-- MathJax for rendering safety stock equations and other operational metrics -->
<script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
</script>

<style>
:root {
  --primary: #1a365d;
  --primary-light: #2c5282;
  --primary-pale: #ebf8ff;
  --accent: #d69e2e;
  --accent-light: #ecc94b;
  --bg: #f7fafc;
  --card-bg: #ffffff;
  --text: #2d3748;
  --text-light: #718096;
  --border: #e2e8f0;
  --border-light: #edf2f7;
  
  --correct: #2c7a7b;
  --correct-bg: #e6fffa;
  --incorrect: #9b2c2c;
  --incorrect-bg: #fff5f5;
  --warning: #dd6b20;
  --warning-bg: #fffbeb;
  
  --radius: 10px;
  --radius-lg: 16px;
  --sidebar-w: 320px;
  --header-h: 76px;
  --shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06);
  --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.7;
  font-size: 15px;
  min-height: 100vh;
}

.header {
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%);
  color: white;
  height: var(--header-h);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  box-shadow: var(--shadow-lg);
  display: flex;
  align-items: center;
}

.header-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0 24px;
}

.logo-area {
  display: flex;
  align-items: center;
  gap: 12px;
}

.logo-icon {
  background: rgba(255, 255, 255, 0.15);
  width: 44px;
  height: 44px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255,255,255,0.2);
}

.logo-text {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.5px;
  color: white;
  line-height: 1.2;
}

.logo-text span {
  color: var(--accent-light);
  font-weight: 400;
  font-size: 13px;
  display: block;
}

.header-timer {
  display: flex;
  align-items: center;
  gap: 8px;
  background: rgba(255, 255, 255, 0.1);
  padding: 8px 16px;
  border-radius: 30px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  font-weight: 700;
  color: var(--accent-light);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  transition: all 0.3s;
}

.header-timer.inactive {
  opacity: 0.35;
  color: #fff;
  border-color: transparent;
}

.hero {
  background: linear-gradient(135deg, var(--primary) 0%, #234876 50%, var(--primary-light) 100%);
  color: white;
  padding: 60px 24px;
  text-align: center;
  position: relative;
  overflow: hidden;
  margin-top: var(--header-h);
}

.hero::before {
  content: '';
  position: absolute;
  top: -50%;
  right: -20%;
  width: 600px;
  height: 600px;
  background: radial-gradient(circle, rgba(214,158,46,0.12) 0%, transparent 70%);
  border-radius: 50%;
}

.hero-content {
  max-width: 900px;
  margin: 0 auto;
  position: relative;
  z-index: 1;
}

.hero-badge {
  display: inline-block;
  background: var(--accent);
  color: white;
  padding: 6px 18px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin-bottom: 20px;
  box-shadow: 0 4px 10px rgba(0,0,0,0.15);
}

.hero h1 {
  font-size: 36px;
  font-weight: 800;
  margin-bottom: 12px;
  line-height: 1.2;
  letter-spacing: -1px;
}

.hero h1 span {
  color: var(--accent-light);
}

.hero-sub {
  font-size: 16px;
  opacity: 0.9;
  max-width: 700px;
  margin: 0 auto 24px;
  line-height: 1.6;
}

.hero-meta {
  display: flex;
  justify-content: center;
  gap: 24px;
  flex-wrap: wrap;
}

.hero-meta-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  background: rgba(255, 255, 255, 0.08);
  padding: 6px 14px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.05);
}

.hero-meta-item i {
  color: var(--accent-light);
}

.app-container {
  max-width: 1400px;
  margin: 0 auto;
  padding: 32px 24px;
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  gap: 32px;
}

.sidebar {
  position: sticky;
  top: calc(var(--header-h) + 32px);
  height: calc(100vh - var(--header-h) - 64px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-right: 8px;
}

.sidebar::-webkit-scrollbar {
  width: 5px;
}

.sidebar::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
}

.toc-title {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-light);
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--accent);
  display: inline-block;
  align-self: flex-start;
}

.nav-home-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 14px;
  font-weight: 700;
  color: var(--primary);
  cursor: pointer;
  transition: all 0.25s;
  box-shadow: var(--shadow);
}

.nav-home-btn:hover, .nav-home-btn.active {
  background: var(--primary);
  color: white;
  border-color: var(--primary);
}

.nav-topics-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.nav-topic-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: transparent;
  border-radius: 8px;
  color: var(--text);
  font-size: 13px;
  text-decoration: none;
  cursor: pointer;
  transition: all 0.2s;
  border-left: 3px solid transparent;
}

.nav-topic-item:hover {
  background: rgba(26, 54, 93, 0.05);
  border-left-color: var(--accent);
}

.nav-topic-item.active {
  background: var(--card-bg);
  border-left-color: var(--accent);
  color: var(--primary);
  font-weight: 700;
  box-shadow: var(--shadow);
}

.nav-topic-num {
  background: var(--border);
  color: var(--text);
  font-size: 11px;
  font-weight: 700;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.nav-topic-item.active .nav-topic-num {
  background: var(--primary);
  color: white;
}

.nav-topic-name {
  flex: 1;
  line-height: 1.3;
}

.nav-topic-badge {
  font-size: 9px;
  font-weight: 800;
  padding: 2px 6px;
  border-radius: 20px;
  text-transform: uppercase;
  flex-shrink: 0;
  display: none;
}

.nav-topic-badge.visible {
  display: block;
}

.nav-topic-badge.wip {
  background: var(--warning-bg);
  color: var(--warning);
  border: 1px solid #fde68a;
}

.nav-topic-badge.pass {
  background: var(--correct-bg);
  color: var(--correct);
  border: 1px solid #a7f3d0;
}

.nav-topic-badge.fail {
  background: var(--incorrect-bg);
  color: var(--incorrect);
  border: 1px solid #fecaca;
}

.sidebar-stats-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sidebar-stats-card .title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-light);
  border-bottom: 1px solid var(--border-light);
  padding-bottom: 8px;
}

.stat-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 13.5px;
}

.stat-row span:first-child {
  color: var(--text-light);
}

.stat-row span:last-child {
  font-weight: 700;
  color: var(--primary);
}

.progress-track {
  width: 100%;
  height: 6px;
  background: var(--border-light);
  border-radius: 3px;
  overflow: hidden;
  margin-top: 4px;
}

.progress-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-light) 100%);
  border-radius: 3px;
  transition: width 0.5s ease;
}

.main-content {
  background: var(--card-bg);
  border-radius: var(--radius-lg);
  padding: 40px;
  box-shadow: var(--shadow);
  min-height: 500px;
}

.page-view {
  display: none;
}

.page-view.active {
  display: block;
  animation: fadeUp 0.35s ease;
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}

.lo-badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%);
  color: white;
  padding: 12px 20px;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 13.5px;
  margin: 16px 0;
  box-shadow: var(--shadow);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
  margin: 24px 0;
}

.card {
  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 24px;
  transition: all 0.3s;
  position: relative;
  overflow: hidden;
}

.card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-light));
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

.card-title {
  font-weight: 700;
  font-size: 15px;
  color: var(--primary);
  margin-bottom: 8px;
}

.card p {
  font-size: 13px;
  margin: 0;
  color: var(--text-light);
  line-height: 1.5;
}

.key-point {
  background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);
  border-left: 4px solid var(--accent);
  padding: 20px 24px;
  margin: 24px 0;
  border-radius: 0 12px 12px 0;
  position: relative;
}

.key-point strong {
  color: var(--warning);
  font-weight: 700;
}

.key-point p {
  margin: 0;
  font-style: italic;
  color: #744210;
  font-size: 13.5px;
}

.formula-box {
  background: linear-gradient(135deg, #f0fff4 0%, #c6f6d5 100%);
  border-radius: var(--radius);
  padding: 20px 24px;
  margin: 20px 0;
  border: 1px solid #9ae6b4;
}

.formula-box dt {
  font-weight: 700;
  color: var(--correct);
  font-size: 14px;
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.formula-box dd {
  margin: 0;
  color: #22543d;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  font-weight: 600;
}

.def-box {
  background: linear-gradient(135deg, #ebf8ff 0%, #bee3f8 100%);
  border-radius: var(--radius);
  padding: 20px 24px;
  margin: 20px 0;
  border: 1px solid #90cdf4;
}

.def-box dt {
  font-weight: 700;
  color: var(--primary);
  font-size: 15px;
  margin-bottom: 8px;
}

.def-box dd {
  margin: 0 0 6px 0;
  color: #2a4365;
  font-size: 13.5px;
}

h2 {
  font-size: 24px;
  font-weight: 800;
  color: var(--primary);
  margin-bottom: 24px;
  padding-bottom: 12px;
  border-bottom: 3px solid var(--accent);
  display: flex;
  align-items: center;
  gap: 12px;
}

h2 .ch-num {
  background: var(--accent);
  color: white;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  font-size: 15px;
  flex-shrink: 0;
}

.landing-page {
  text-align: center;
  max-width: 720px;
  margin: 0 auto;
}

.landing-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--primary-pale);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin: 0 auto 16px;
}

.landing-session-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin-bottom: 6px;
}

.landing-topic-name {
  font-size: 24px;
  font-weight: 800;
  color: var(--primary);
  margin-bottom: 16px;
}

.landing-username-container {
  background: #fdfdfd;
  border: 1px dashed var(--accent);
  padding: 20px;
  border-radius: var(--radius);
  margin-bottom: 20px;
  text-align: left;
}

.landing-username-container label {
  display: block;
  font-size: 12px;
  font-weight: 800;
  color: var(--primary);
  text-transform: uppercase;
  margin-bottom: 8px;
}

.username-input-field {
  width: 100%;
  padding: 12px 16px;
  border: 2px solid var(--border);
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 14px;
  color: var(--text);
  outline: none;
  background: #fff;
  transition: all 0.25s ease;
}

.username-input-field:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(214, 158, 46, 0.15);
}

.landing-rules {
  text-align: left;
  background: #f8fafc;
  padding: 24px;
  border-radius: var(--radius);
  border: 1px solid var(--border-light);
  margin-bottom: 24px;
}

.landing-rules h3 {
  font-size: 14px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 12px;
}

.landing-rules li {
  font-size: 13.5px;
  margin-bottom: 8px;
  list-style-type: square;
  margin-left: 18px;
  color: var(--text-light);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 28px;
  font-size: 13.5px;
  font-weight: 700;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  transition: all 0.25s;
  font-family: inherit;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.btn-primary {
  background: var(--primary);
  color: #fff;
  box-shadow: 0 4px 10px rgba(26,54,93,0.2);
}

.btn-primary:hover {
  background: var(--primary-light);
  transform: translateY(-1px);
}

.btn-gold {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 4px 10px rgba(214,158,70,0.3);
}

.btn-gold:hover {
  background: #bd8720;
  transform: translateY(-1px);
}

.btn-outline {
  background: transparent;
  color: var(--primary);
  border: 2px solid var(--primary);
}

.btn-outline:hover {
  background: var(--primary);
  color: #fff;
  transform: translateY(-1px);
}

.btn-sm {
  padding: 8px 16px;
  font-size: 12px;
}

.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}

.exam-header-bar {
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%);
  color: white;
  border-radius: var(--radius-lg);
  padding: 24px;
  margin-bottom: 24px;
  box-shadow: var(--shadow);
}

.exam-header-bar h2 {
  border: none;
  margin-bottom: 8px;
  padding: 0;
  color: #fff;
}

.ehb-meta {
  display: flex;
  gap: 16px;
  font-size: 13px;
  opacity: 0.9;
  flex-wrap: wrap;
}

.ehb-meta span {
  display: flex;
  align-items: center;
  gap: 6px;
}

.ehb-meta i {
  color: var(--accent-light);
}

.ehb-progress {
  margin-top: 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.ehb-progress .track {
  flex: 1;
  height: 6px;
  background: rgba(255,255,255,0.2);
  border-radius: 3px;
  overflow: hidden;
}

.ehb-progress .fill {
  height: 100%;
  width: 0%;
  background: var(--accent-light);
  border-radius: 3px;
  transition: width 0.35s ease;
}

.ehb-progress .prog-text {
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  min-width: 48px;
  text-align: right;
}

.question-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
  margin-bottom: 16px;
  box-shadow: var(--shadow);
  transition: all 0.25s;
}

.question-card.is-correct {
  border-color: var(--correct);
  background: #f0fff4;
}

.question-card.is-incorrect {
  border-color: var(--incorrect);
  background: #fff5f5;
}

.q-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.q-label i {
  display: none;
}

.question-card.is-correct .q-label .icon-correct {
  display: inline-block;
  color: var(--correct);
}

.question-card.is-incorrect .q-label .icon-incorrect {
  display: inline-block;
  color: var(--incorrect);
}

.q-text {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 16px;
  line-height: 1.6;
}

.options-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.option-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
  background: #fff;
}

.option-row:hover {
  border-color: var(--primary-light);
  background: #f7fafc;
}

.option-row.selected {
  border-color: var(--primary);
  background: #ebf8ff;
}

.option-row.selected .option-dot {
  border-color: var(--primary);
  background: var(--primary);
}

.option-row.selected .option-dot::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 6px;
  height: 6px;
  background: white;
  border-radius: 50%;
}

.option-row.show-correct {
  border-color: var(--correct);
  background: #e6fffa;
}

.option-row.show-correct .option-dot {
  border-color: var(--correct);
  background: var(--correct);
}

.option-row.show-correct .option-dot::after {
  content: '\f00c';
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: white;
  font-size: 8px;
}

.option-row.show-wrong {
  border-color: var(--incorrect);
  background: #fff5f5;
}

.option-row.show-wrong .option-dot {
  border-color: var(--incorrect);
  background: var(--incorrect);
}

.option-row.show-wrong .option-dot::after {
  content: '\f00d';
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: white;
  font-size: 8px;
}

.option-row.locked {
  cursor: default;
  pointer-events: none;
}

.option-dot {
  width: 18px;
  height: 18px;
  border: 2px solid var(--border);
  border-radius: 50%;
  flex-shrink: 0;
  position: relative;
  top: 3px;
  transition: all 0.2s;
}

.opt-letter {
  font-weight: 700;
  color: var(--text-light);
  margin-right: 4px;
}

.opt-text {
  font-size: 13.5px;
  color: var(--text);
  line-height: 1.5;
}

.results-container {
  max-width: 580px;
  margin: 0 auto;
  text-align: center;
}

.res-candidate-tag {
  background: rgba(26, 54, 93, 0.05);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 18px;
  display: inline-block;
  font-size: 14px;
  font-weight: 700;
  color: var(--primary);
  margin-bottom: 20px;
}

.res-candidate-tag span {
  color: var(--accent);
}

.review-candidate-banner {
  background: var(--primary-pale);
  border-left: 4px solid var(--accent);
  padding: 14px 20px;
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-bottom: 24px;
  font-weight: 700;
  color: var(--primary);
  font-size: 14px;
}

.review-candidate-banner span {
  color: var(--accent);
}

.res-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  margin: 0 auto 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
}

.res-icon.grade-a { background: var(--correct-bg); color: var(--correct); }
.res-icon.grade-b { background: #fffbeb; color: var(--warning); }
.res-icon.grade-c { background: #fff5f5; color: #c53030; }
.res-icon.grade-f { background: var(--incorrect-bg); color: var(--incorrect); }

.res-title {
  font-size: 22px;
  font-weight: 800;
  color: var(--primary);
  margin-bottom: 4px;
}

.res-grade {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  margin-bottom: 24px;
  padding: 6px 16px;
  border-radius: 20px;
  display: inline-block;
}

.res-grade.grade-a { background: var(--correct-bg); color: var(--correct); }
.res-grade.grade-b { background: #fffbeb; color: var(--warning); }
.res-grade.grade-c { background: #fff5f5; color: #c53030; }
.res-grade.grade-f { background: var(--incorrect-bg); color: var(--incorrect); }

.res-score {
  font-size: 56px;
  font-weight: 800;
  color: var(--primary);
  line-height: 1;
  margin-bottom: 4px;
}

.res-score-label {
  font-size: 13px;
  color: var(--text-light);
  margin-bottom: 24px;
}

.res-breakdown {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-bottom: 28px;
}

.res-bd-item {
  background: var(--bg);
  border-radius: var(--radius);
  padding: 12px 8px;
  border: 1px solid var(--border-light);
}

.res-bd-item .bd-val {
  font-size: 20px;
  font-weight: 800;
}

.res-bd-item .bd-val.val-green { color: var(--correct); }
.res-bd-item .bd-val.val-red { color: var(--incorrect); }
.res-bd-item .bd-val.val-muted { color: var(--text-light); }

.res-bd-item .bd-lbl {
  font-size: 10px;
  color: var(--text-light);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-top: 2px;
}

.res-buttons {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}

.fixed-submit-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--border);
  padding: 16px 24px;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  box-shadow: 0 -4px 10px rgba(0,0,0,0.05);
  transition: transform 0.3s ease;
}

.fixed-submit-bar.hidden {
  transform: translateY(100%);
  display: none !important;
}

.fsb-content {
  width: 100%;
  max-width: 1400px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.fsb-text {
  font-size: 13.5px;
  color: var(--text-light);
}

.fsb-text strong {
  color: var(--primary);
  font-size: 15px;
}

.toast-notification {
  position: fixed;
  bottom: 96px;
  right: 24px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  padding: 14px 20px;
  font-size: 13.5px;
  color: var(--text);
  box-shadow: var(--shadow-lg);
  z-index: 3000;
  transform: translateX(120%);
  transition: transform 0.3s ease;
  max-width: 320px;
}

.toast-notification.show {
  transform: translateX(0);
}

.mobile-menu-btn {
  display: none;
  position: fixed;
  bottom: 24px;
  right: 24px;
  width: 48px;
  height: 48px;
  background: var(--primary);
  color: white;
  border: none;
  border-radius: 50%;
  font-size: 18px;
  cursor: pointer;
  z-index: 1050;
  box-shadow: var(--shadow-lg);
  align-items: center;
  justify-content: center;
}

.hidden {
  display: none !important;
}

@media(max-width: 1024px) {
  .app-container {
    grid-template-columns: 1fr;
  }
  .sidebar {
    position: fixed;
    top: var(--header-h);
    left: -100%;
    width: var(--sidebar-w);
    height: calc(100vh - var(--header-h));
    background: var(--card-bg);
    border-right: 1px solid var(--border);
    z-index: 990;
    padding: 24px;
    transition: left 0.3s ease;
  }
  .sidebar.open {
    left: 0;
    box-shadow: var(--shadow-lg);
  }
  .mobile-menu-btn {
    display: flex;
  }
}

@media(max-width: 640px) {
  .hero h1 {
    font-size: 24px;
  }
  .main-content {
    padding: 24px;
  }
}
</style>
</head>
<body>

<header class="header">
  <div class="header-top">
    <div class="logo-area">
      <div class="logo-icon" data-site-logo></div>
      <div class="logo-text" data-site-name>
        Padenga Agribusiness
        <span>Central Stores Academy FY2026</span>
      </div>
    </div>
    
    <div class="header-timer inactive" id="headerTimer">
      <i class="fa-regular fa-clock"></i>
      <span id="timerDisplay">00:00</span>
    </div>
  </div>
</header>

<section class="hero">
  <div class="hero-content">
    <div class="hero-badge">PAB Core Training Curriculum</div>
    <h1>Professional <span>Stores Qualification</span></h1>
    <p class="hero-sub">
      Validate your skills across all 11 core training domains. Sourced from the FY2026 training guidelines, each module functions as an independent, rigorous validation suite designed to test standard operating compliance, safety, and inventory optimization.
    </p>
    <div class="hero-meta">
      <div class="hero-meta-item">
        <i class="fa-solid fa-list-check"></i> 11 Topic Domains
      </div>
      <div class="hero-meta-item">
        <i class="fa-solid fa-circle-nodes"></i> 110 Comprehensive Questions
      </div>
      <div class="hero-meta-item">
        <i class="fa-solid fa-graduation-cap"></i> 75% Qualifying Score
      </div>
    </div>
  </div>
</section>

<div class="app-container">
  
  <aside class="sidebar" id="sidebar">
    <div class="toc-title">Control Hub</div>
    <div class="nav-home-btn active" id="navHomeBtn">
      <i class="fa-solid fa-grid-2"></i> Dashboard
    </div>
    
    <div class="toc-title">Validation Modules</div>
    <div class="nav-topics-list" id="navTopicsScroll"></div>
    
    <div class="sidebar-stats-card">
      <div class="title">Cumulative Statistics</div>
      <div class="stat-row">
        <span>Completed Modules</span>
        <span id="statsCompleted">0 / 11</span>
      </div>
      <div class="stat-row">
        <span>Passed Modules</span>
        <span id="statsPassed">0</span>
      </div>
      <div class="stat-row">
        <span>Average Score</span>
        <span id="statsAvgScore">--</span>
      </div>
      <div class="progress-track">
        <div class="progress-fill" id="statsBarFill"></div>
      </div>
    </div>
  </aside>

  <main class="main-content" id="mainContent">
    
    <!-- Dashboard panel view -->
    <div class="page-view active" id="pageDashboard">
      <h2><span class="ch-num"><i class="fa-solid fa-gauge-high"></i></span> Academy Program Summary</h2>
      
      <p style="margin-bottom: 24px;">
        Welcome to the Padenga Agribusiness (PAB) Central Stores validation portal. Sourced directly from the official <strong>PAB Central Stores Training Notes FY2026</strong>, these assessments guarantee that all warehouse operatives understand the compliance frameworks, environmental guidelines, and standard operations mandated at Central Stores.
      </p>
      
      <div class="lo-badge">
        <i class="fa-solid fa-circle-info"></i> How Sourcing Frameworks Function
      </div>
      
      <div class="card-grid">
        <div class="card">
          <div class="card-title">Dedicated Landing Pages</div>
          <p>Every validation topic launches into a full descriptive syllabus outline requiring candidate verification before launching questions.</p>
        </div>
        <div class="card">
          <div class="card-title">Localized Timers</div>
          <p>Timers calculate active durations strictly on an individual topic basis and pause immediately on navigation or suspension.</p>
        </div>
        <div class="card">
          <div class="card-title">Isolated Grading State</div>
          <p>Answers, calculations, scores, and status grades are isolated to each section. Resetting one exam leaves other records untouched.</p>
        </div>
      </div>

      <div class="key-point">
        <p><strong>RE-QUALIFICATION MATRIX:</strong> Operatives who score below 75% are permitted to review system feedback instantly and launch unlimited dynamic re-trials of that specific topic until they meet compliance thresholds.</p>
      </div>

      <div class="toc-title" style="margin-top: 16px;">Assessment Portal Navigation Grid</div>
      <div class="card-grid" id="dashTopicsGrid" style="margin-top: 12px; grid-template-columns: 1fr;"></div>
    </div>
    
    <!-- Topic and Session pages container -->
    <div id="topicPagesContainer"></div>
  </main>
</div>

<div class="fixed-submit-bar hidden" id="fixedSubmitBar">
  <div class="fsb-content">
    <div class="fsb-text" id="fsbText"><strong>0</strong> of 10 answered</div>
    <button class="btn btn-gold" id="btnSubmitExam" disabled>Submit Validation <i class="fa-solid fa-paper-plane" style="margin-left: 6px;"></i></button>
  </div>
</div>

<button class="mobile-menu-btn" id="mobileMenuBtn" aria-label="Toggle Navigation Panel">
  <i class="fa-solid fa-bars"></i>
</button>

<div class="toast-notification" id="toastNotification"></div>

<script>
/* ================================================================
   DATA — 11 topics, 10 questions each (Sourced from PAB Central Stores Notes)
   ================================================================ */
var TOPICS = [
  { 
    name:"Warehouse Management", 
    shortName:"Warehouse Mgmt", 
    icon:"fa-warehouse", 
    questions:[
      {q:"What does FIFO stand for in inventory management at PAB Central Stores?",o:["First Issued, First Out","First In, First Out","Fast In, Fast Out","Final Issue, Final Order"],a:1},
      {q:"Which document is used when goods are physically received into PAB Central Stores?",o:["Stores Issue Voucher","Purchase Order","Goods Received Note (GRN)","Adjustment Form"],a:2},
      {q:"What is the target Order Fill Rate for critical operational items at PAB Central Stores?",o:["&ge;90%","&ge;95%","&ge;99%","&ge;100%"],a:1},
      {q:"When should stock transactions be captured in the system according to PAB policy?",o:["At the end of each day in a batch","At the end of each week","At the point of transaction","At the end of each month"],a:2},
      {q:"Which of the following describes the core purpose of JIT (Just-in-Time) coordination?",o:["Minimizing storage holding costs by timing stock arrival exactly with production requirements","Keeping bulk inventory excess of six months cover at all times","Maximizing travel time of warehouse staff","Standardizing batch captures at week-end"],a:0},
      {q:"Where should fast-moving consumables be physically stored to optimize picking efficiency?",o:["In the highest racking bays","Near the dispatch counter","In general chemical locked zones","In the refrigerated cold store room"],a:1},
      {q:"How should heavy items be organized on warehouse racking units to maintain stability and compliance?",o:["Stored at higher levels","Stored in pedestrian pathways","Stored at low levels","Stacked directly in front of emergency exits"],a:2},
      {q:"When new stock arrives, what physical action is required to maintain stock rotation integrity?",o:["Physically rotate stock, placing the newest stock at the front","Physically rotate stock, placing older stock at the front","Avoid moving any current items and store the new items behind","Keep older items in secondary emergency locations"],a:1},
      {q:"If a warehouse item requires cool storage, what is the policy regarding its ambient temperature exposure?",o:["It may remain at ambient temperature indefinitely","It must never be left at ambient temperature for longer than specified","It should be kept at room temperature until system capture","It can be moved to refrigeration only after the end-of-shift check"],a:1},
      {q:"Which of the following is NOT required on the dispatch checklist before releasing goods?",o:["Verifying that the requisition is authorized","Confirming that quantities match the request","Inspecting that items are in acceptable condition","Checking the supplier's credit terms in the ledger"],a:3}
    ]
  },
  { 
    name:"Inventory Quality Management", 
    shortName:"Quality Mgmt", 
    icon:"fa-clipboard-check", 
    questions:[
      {q:"What does FEFO stand for in the context of inventory management?",o:["First Evaluated, First Out","First Expired, First Out","Fast Expired, Fast Out","Final Expiry, Final Order"],a:1},
      {q:"What is the FIRST step in the goods receipt inspection process?",o:["Physical inspection of items","Expiry date verification","Documentation check against the purchase order","Shelving the goods for later inspection"],a:2},
      {q:"What must be done with goods that fail the receiving inspection at PAB Central Stores?",o:["Shelve them and flag for later review","Quarantine them in the designated non-conforming area","Return them to the supplier immediately without documentation","Issue them to the requesting department with a warning"],a:1},
      {q:"How often must a full visual inspection of all storage areas be conducted at minimum?",o:["Daily","At least once per week","Once per month","Once per quarter"],a:1},
      {q:"To maintain product quality, what is the rule regarding the storage of acids and bases?",o:["They must be stored side-by-side in general zones","They must be physically separated on different shelves or compartments","They must be mixed before disposal","They must be stored in standard non-bunded containers"],a:1},
      {q:"For temperature-sensitive storage areas (like chemical cold rooms), what is the inspection frequency?",o:["Hourly","At the same time each day","Weekly on Fridays","At the end of each month"],a:1},
      {q:"What is the timeframe for compiling and sharing the 'Near-Expiry Alert List' with the Stores Manager?",o:["7 days prior to expiry","30 days prior to expiry","60 days prior to expiry","90 days prior to expiry"],a:1},
      {q:"What is PAB's default policy regarding the minimum remaining shelf life of items accepted into stores?",o:["3 months","6 months","12 months","No minimum limit as long as they are unexpired"],a:1},
      {q:"Under what circumstances can an expired item be issued to operations at PAB?",o:["If authorized by a team leader verbally","If the item's packaging is perfectly intact","Never under any circumstances","If it is discounted or flagged as slow-moving"],a:2},
      {q:"What label must be attached to failed or rejected deliveries placed in the quarantine area?",o:["\"HOLD — PENDING CLARIFICATION\"","\"REJECTED — DO NOT USE\"","\"SLOW-MOVING ASSET\"","\"STORES RECEIVAL COMPLETED\""],a:1}
    ]
  },
  { 
    name:"Inventory Control", 
    shortName:"Inventory Control", 
    icon:"fa-chart-line", 
    questions:[
      {q:"What is a bin card in the context of PAB Central Stores?",o:["A digital record in the ERP system","A physical record kept at each storage location showing receipts, issues, and balances","A purchase order document","A monthly report generated by the Stores Controller"],a:1},
      {q:"What is the correct mathematical formula for calculating the Reorder Point (ROP)?",o:["$$ROP = \\text{Average Daily Usage} \\times \\text{Lead Time}$$","$$ROP = (\\text{Average Daily Usage} \\times \\text{Lead Time}) + \\text{Safety Stock}$$","$$ROP = \\text{Safety Stock} \\div \\text{Lead Time}$$","$$ROP = \\text{Maximum Stock Level} - \\text{Safety Stock}$$"],a:1},
      {q:"What is the defining characteristic of cycle counting compared to a full monthly stocktake?",o:["It counts all inventory at once once a year","It counts a portion of inventory on a regular rotating schedule","It only counts high-value Category A items","It counts items only when they are received"],a:1},
      {q:"Who is authorised to approve system adjustments to correct inventory variances?",o:["Any stores team member","The requesting department head","The Stores Controller or Stores Manager","The procurement officer"],a:2},
      {q:"What is the target Stock Accuracy Rate that must be maintained at all times for PAB Central Stores?",o:["&ge;90%","&ge;95%","&ge;98%","&ge;100%"],a:2},
      {q:"How is a count discrepancy's variance value calculated during the reconciliation process?",o:["Quantity difference \\times unit cost","Quantity difference + total cost","Total cost / quantity difference","Opening balance \\times closing balance"],a:0},
      {q:"How long must completed physical cycle count sheets be retained for audit trails?",o:["3 months","6 months","12 months","24 months"],a:2},
      {q:"What is the absolute rule for counters before conducting a physical cycle count?",o:["Verify the ERP system balances first to crosscheck","Do not look at the system balance before counting","Adjust the bin cards in advance","Sign off on empty sheets"],a:1},
      {q:"In a two-bin inventory control system, what triggers a reorder of fast-moving consumables?",o:["When both bins are half-empty","When the first bin is completely emptied","When the system flags a cycle count","When a department head submits an inquiry"],a:1},
      {q:"How often must a formal Inventory Reconciliation Report be prepared and submitted to the Accountant?",o:["Weekly","Monthly","Quarterly","Annually"],a:1}
    ]
  },
  { 
    name:"Inventory Optimisation Techniques", 
    shortName:"Optimisation", 
    icon:"fa-sliders", 
    questions:[
      {q:"In ABC analysis, which category of items requires daily monitoring?",o:["Category A — high value, tightly controlled","Category B — medium value, moderate control","Category C — low value, bulk managed","All categories are monitored equally"],a:0},
      {q:"How is stock cover calculated?",o:["Average Daily Usage \\times Current Stock Balance","Current Stock Balance / Average Daily Usage","Maximum Stock Level - Current Stock Balance","Reorder Point / Lead Time"],a:1},
      {q:"What is the minimum stock cover required for critical operational items at PAB?",o:["7 days","14 days","30 days","62 days"],a:3},
      {q:"Stock that has had no movement for 6 months or more is classified as:",o:["Slow-moving stock","Dead stock","Safety stock","Buffer stock"],a:1},
      {q:"How often should Category B items (medium value, moderate control) be monitored under ABC guidelines?",o:["Daily","Weekly","Monthly","Quarterly"],a:1},
      {q:"Which of the following stock cover thresholds indicates that urgent reorder action is required?",o:["Fewer than 7 days of cover","Fewer than 14 days of cover","Fewer than 30 days of cover","Fewer than 62 days of cover"],a:0},
      {q:"What does the Economic Order Quantity (EOQ) tool seek to minimize?",o:["Purchasing price of the items","Combined ordering and holding costs","Supplier delivery lead times","The physical storage space occupied"],a:1},
      {q:"What is the primary risk of ordering items beyond their defined maximum stock level?",o:["Increasing the order fill rate unnecessarily","Excess capital lock-up and high risk of expiry or obsolescence","Improving stock accuracy rates too fast","Decreasing total warehouse maintenance costs"],a:1},
      {q:"During peak operational seasons, what adjustments must be made to replenishment cycles and order quantities?",o:["Replenishment cycles must be lengthened and quantities decreased","Replenishment cycles must be shortened and quantities increased","Replenishment cycles and quantities must remain completely static","All ordering must be suspended"],a:1},
      {q:"What is the main benefit of negotiating blanket purchase orders with high-frequency suppliers?",o:["It eliminates the need for any cycle counts","It reduces administrative burden and secures better pricing","It bypasses the need for receiving inspections","It ensures all stock is treated as Category C"],a:1}
    ]
  },
  { 
    name:"Inventory Data Management & Visualisation", 
    shortName:"Data & Visualisation", 
    icon:"fa-chart-pie", 
    questions:[
      {q:"What is the most important principle of inventory data integrity at PAB?",o:["Every transaction must reflect exactly what physically happened","Estimates are acceptable when time is limited","Rounding is permitted for small quantities","Retroactive corrections can be made informally"],a:0},
      {q:"Which type of chart is best suited for comparing current stock levels against minimum and maximum thresholds?",o:["Pie chart","Line graph","Bar chart","Scatter plot"],a:2},
      {q:"In a traffic-light dashboard system, what does an amber status indicate?",o:["On track — no action needed","Action required immediately","Monitor closely","No data available"],a:2},
      {q:"Which type of chart is best suited for visualising stock usage patterns and demand over time?",o:["Line graph","Bar chart","Pie chart","Donut chart"],a:0},
      {q:"What is the core rule regarding system transaction entries and source documents?",o:["Transactions can be entered without any document if a supervisor approves","Every system entry must trace back to a physical source document","Source documents should be discarded immediately after capture","Only adjustments require source documentation"],a:1},
      {q:"What is the primary focus of inventory exception reporting to management?",o:["Reporting every single transaction line sequentially","Highlighting out-of-specification items like critical shortages or near-expiries","Listing alphabetical classifications of Category C items","Summarizing overall personnel hours in the warehouse"],a:1},
      {q:"Why is sharing ERP system credentials strictly forbidden at PAB?",o:["It decreases overall system performance","It destroys the transaction audit trail","It prevents the generation of bar charts","It causes network connectivity errors"],a:1},
      {q:"If the ERP system is offline, when must manual transactions be captured in the system once restored?",o:["Within 48 hours","Within 1 week","On the same day","At the end of the monthly stocktake"],a:2},
      {q:"Which visualization tool is best suited for showing the proportion of total inventory value held by category?",o:["Line graph","Pie chart","Scatter plot","Gantt chart"],a:1},
      {q:"What is a direct consequence of a single incorrect goods receipt entry in the ERP?",o:["Immediate system shutdown","Delayed reorder triggers and incorrect financial valuations","Automatic replacement of all safety stock","A visual update to the dashboard color palette"],a:1}
    ]
  },
  { 
    name:"Inventory Risk Management", 
    shortName:"Risk Management", 
    icon:"fa-shield-halved", 
    questions:[
      {q:"Which of the following is identified as a theft risk indicator in the training notes?",o:["Items found on the floor rather than on shelves","Unexplained stock shortfalls persisting across consecutive counts","Items with no system movement for 3 months or more","Leaking containers causing secondary damage to nearby stock"],a:1},
      {q:"What is the purpose of dual custody for high-value items in stores?",o:["To reduce storage costs","To ensure two authorised people are involved in access and issue","To speed up the issuing process","To eliminate the need for documentation"],a:1},
      {q:"Within what timeframe must identified risks be logged in the Stores Risk Register?",o:["Within 48 hours","Within 24 hours","Within 1 week","By the end of the month"],a:1},
      {q:"Which of the following is a key physical damage risk indicator?",o:["Items stored close to the dispatch desk","Leaking containers creating secondary damage to nearby stock","A drop in Category C inventory turnover","An increase in system transaction frequency"],a:1},
      {q:"Why are near-miss incidents documented and reported in PAB Stores?",o:["To penalize the staff members involved","They serve as leading indicators to prevent future accidents","To reduce the number of weekly cycle counts","To replace physical inspections with system logs"],a:2},
      {q:"What is the immediate reporting requirement for a realized major risk event like confirmed theft or fire?",o:["Log it at the end of the month","Report to the Stores Manager immediately","Report it to the supplier first","Wait for the quarterly audit to document it"],a:1},
      {q:"Where should highly critical or high-value items be physically stored inside the warehouse?",o:["In the receiving bay area for fast access","In a locked cage or secure room requiring dual sign-off","Alongside general consumables to avoid drawing attention","On any open high-level racking shelf"],a:1},
      {q:"Who is responsible for maintaining the master list of authorized personnel allowed inside the stores?",o:["Any stores team clerk","The Stores Manager","The procurement officer","The external security contractor"],a:1},
      {q:"What should be checked regarding environmental risks during every daily inspection?",o:["Bait stations, fire safety equipment, and emergency exits","Supplier delivery notes","Total value of slow-moving items","The hourly temperature of ambient dry storage"],a:0},
      {q:"How often is the Stores Risk Register formally reviewed by the General Manager and Accountant?",o:["Weekly","Monthly","Quarterly","Annually"],a:2}
    ]
  },
  { 
    name:"Technology in Stores Management", 
    shortName:"Technology", 
    icon:"fa-laptop-code", 
    questions:[
      {q:"What must every stores team member have for ERP system access at PAB?",o:["A shared team login","Their own individual login credentials","A supervisor's login for all transactions","No login is required for viewing-only access"],a:1},
      {q:"What should a clerk do if the ERP system displays an error or unexpected result?",o:["Create informal manual records and continue working","Ignore the error and retry later without reporting","Report the issue immediately to the Stores Controller or IT/BI Officer","Attempt to fix the database error themselves"],a:2},
      {q:"What must a stores staff member complete before being authorized to capture live ERP transactions?",o:["An ERP navigation assessment","A six-month general warehousing internship","A manual stock count certification","A baseline financial accounting exam"],a:0},
      {q:"What must be verified in the ERP during a goods issue capture?",o:["The supplier's primary email address","That the requisition is signed and approved by the department head","The historical stock turnover ratio of the item","The physical dimensions of the storage bin"],a:1},
      {q:"What is the primary benefit of using barcode scanners where integrated into PAB's ERP?",o:["It eliminates the need for any safety stock","It completely automates goods dispatch without personnel","Eliminating manual data entry errors and speeding up transaction processing","It automatically generates monthly financial reconciliations"],a:2},
      {q:"How does the ERP inventory system interface with PAB's financial accounting?",o:["Every receipt automatically generates a pending financial liability","All issues are credited to the supplier's balance","It calculates warehouse rental values based on space usage","It replaces all manual payroll processing for stores staff"],a:0},
      {q:"What is the preferred method for preserving paper receipts, invoices, and GRNs?",o:["Storing them exclusively in physical binders","Scanning and attaching them directly to the ERP transaction","Throwing them away once entered into the system","Filing them at the end of the year in external archives"],a:1},
      {q:"What is the risk of batch-capturing several transactions days after they occur?",o:["It increases ERP system response times","It corrupts real-time inventory balances and delays replenishment triggers","It forces the system to require a password reset","It automatically deletes historical reports"],a:1},
      {q:"What is the required response when an automated ERP reorder alert is generated?",o:["Ignore it until the monthly stocktake","Raise the associated purchase request on the same day","Delete the notification to clear space","Wait for a verbal instruction from the department head"],a:1},
      {q:"Which standard ERP report shows a chronological audit trail of all receipts, issues, and adjustments for a single SKU?",o:["Stock Balance Report","Transaction History Report","Purchase Order Status Report","Slow-Moving Stock Report"],a:1}
    ]
  },
  { 
    name:"Safe Chemical Handling & Storage", 
    shortName:"Chemical Safety", 
    icon:"fa-flask", 
    questions:[
      {q:"Which document provides critical safety information about chemicals in storage?",o:["Goods Received Note","Safety Data Sheet (SDS)","Stores Issue Voucher","Purchase Order"],a:1},
      {q:"How must chemicals be stored in relation to food items according to PAB policy?",o:["Together in the same zone for operational efficiency","Chemicals must never be stored alongside food items","On the same shelf with clear separation labels","In adjacent bays separated only by a partition"],a:1},
      {q:"According to PAB storage rules, why must acids and bases be stored on separate shelves or zones?",o:["They can react violently if mixed or leaked","To make picking faster for operations","They have identical GHS classification labels","They have different expiration date formats"],a:0},
      {q:"Which GHS hazard pictogram is represented by a flame?",o:["Acute toxicity (skull/crossbones)","Flammable material","Corrosion hazard","Skin irritant"],a:1},
      {q:"Where must all chemicals be stored inside the PAB Central Stores?",o:["In any open area of the warehouse with good lighting","In the designated bunded and ventilated chemical storage bay","On the highest racking levels of Zone A","Directly adjacent to the pedestrian main entrance"],a:1},
      {q:"Where should a stores handler look to determine the exact PPE required for a chemical?",o:["Section 8 of the product's Safety Data Sheet (SDS)","The generic warehouse checklist on the notice board","The supplier's main marketing brochure","The chemical storage bay entrance sign"],a:0},
      {q:"When respiratory protection is required for chemical vapours, what is the rule?",o:["A basic dust mask is sufficient","A chemical vapour respirator with correct cartridges must be worn","A clean cloth wrapped around the face is acceptable","No respirator is needed if the ventilation fans are on"],a:1},
      {q:"What is the first step when containing a minor chemical spill?",o:["Clean it up quickly with a dry broom","Alert nearby colleagues and put on correct PPE","Hose it down with water into the general drain","Call the external emergency fire department first"],a:1},
      {q:"If a chemical splashes into a staff member's eyes, how long must they flush with water?",o:["At least 2 minutes","At least 5 minutes","At least 15 minutes at the eyewash station","They should avoid water and apply eyewash ointment"],a:2},
      {q:"What is the correct protocol when a major, high-hazard chemical spill occurs?",o:["Try to neutralize it using dry absorbent granules immediately","Evacuate the area immediately, sound the alarm, and call the Stores Manager","Ignore it and continue working in adjacent zones","Wait for the next shift to clean it up"],a:1}
    ]
  },
  { 
    name:"Food Safety and Hygiene Management", 
    shortName:"Food Safety", 
    icon:"fa-apple-whole", 
    questions:[
      {q:"What does HACCP stand for?",o:["Hazard Analysis and Critical Control Points","Health And Cleanliness Control Protocol","Handling And Contamination Prevention Code","Hygiene Assessment and Compliance Certification"],a:0},
      {q:"When must temperature readings for sensitive storage areas be recorded?",o:["Once per week","At least twice per day","Once per month","Only when a problem is suspected"],a:1},
      {q:"What is the 'danger zone' temperature range where bacterial growth in food occurs most rapidly?",o:["-18&deg;C to 0&deg;C","0&deg;C to 4&deg;C","5&deg;C to 60&deg;C","60&deg;C to 100&deg;C"],a:2},
      {q:"What is the cumulative time limit that food items may remain in the temperature danger zone?",o:["30 minutes","1 hour","2 hours","24 hours"],a:2},
      {q:"To prevent pest nesting, how much clearance must food pallets have from walls and floors?",o:["At least 5cm clearance","At least 15cm clearance","At least 50cm clearance","Pallets should be stored flush against walls"],a:1},
      {q:"Under what health condition is a stores staff member legally barred from handling food?",o:["Having a mild headache","Suffering from gastroenteritis, vomiting, or diarrhea","Having a sore muscle from physical counts","Wearing clean corrective eyeglasses"],a:1},
      {q:"What is the minimum hand washing duration required before handling food or after toilet use?",o:["5 seconds","10 seconds","20 seconds with soap and water","45 seconds with hand sanitizer only"],a:2},
      {q:"What is the correct order for surface maintenance in a food storage zone?",o:["Sanitise first, then clean to remove physical debris","Clean first to remove physical debris, then sanitise","Only clean; sanitation is unnecessary for dry food","Sweep only; liquids must never be used"],a:1},
      {q:"What is the PAB policy regarding wearing food handling uniforms outside the workplace?",o:["They can be worn anywhere during off-duty hours","Uniforms must not be worn outside the workplace","They must be worn during travel to prevent contamination","They are only required during physical stocktakes"],a:1},
      {q:"In a food stores environment, what constitutes a Critical Control Point (CCP)?",o:["The physical dimension of the receiving bay door","A process step where controls are applied to prevent or eliminate a food safety hazard","The clean uniform policy of the administration staff","The color of the cleaning mop handles"],a:1}
    ]
  },
  { 
    name:"Standard Operating Procedures", 
    shortName:"SOPs", 
    icon:"fa-file-lines", 
    questions:[
      {q:"According to the training notes, what is the authoritative reference for each topic?",o:["These training notes","The relevant Standard Operating Procedures (SOPs)","The Stores Manager's verbal instructions","Industry best practice guides"],a:1},
      {q:"Which SOP covers the process for removing expired or damaged inventory from the system?",o:["SOP for General Receiving of Goods","SOP for Issuing of Goods","SOP for Writing Off Inventory","SOP for Storage Space Planning"],a:2},
      {q:"On arrival of a goods delivery, what is the absolute first document step required?",o:["Physically unload all goods into the dispatch area","Confirm the delivery note matches a valid PAB Purchase Order","Record the vehicle's odometer reading","Prepare the system adjustment journal entry"],a:1},
      {q:"How often must the physical fuel issue log be reconciled against tank gauge balances?",o:["Daily","Weekly","Monthly","Quarterly"],a:0},
      {q:"What is the rule regarding issuing goods from stores without a signed requisition?",o:["It is allowed if the requester promises to sign later","It is permitted for Category C items only","Never issue goods under any circumstances against verbal or informal requests","It is acceptable during peak harvest seasons"],a:2},
      {q:"According to the Space Planning SOP, what is the minimum aisle width for lanes used by forklifts?",o:["1.2 metres","1.5 metres","2.5 metres","4.0 metres"],a:2},
      {q:"For high-value write-offs, whose countersignature is required alongside the Stores Manager?",o:["Any stores team clerk","The General Manager or Finance Manager","The external security lead","The procurement officer"],a:1},
      {q:"What is the correct method for verifying the quantity of incoming bulk fuel deliveries?",o:["Rely completely on the supplier's delivery note","Compare dip-stick or meter readings before and after delivery","Verify the truck's engine fuel consumption","Ask the driver for a verbal estimate"],a:1},
      {q:"When receiving a delivery of items, what is the standard for checking quantities?",o:["Accept the delivery note count without checking","Conduct an independent, item-by-item physical count","Count only the top boxes in each pallet","Perform a visual scan of the truck's interior"],a:1},
      {q:"In the Space Planning SOP, what determines the storage location of fast-moving inventory?",o:["Proximity to the chemical storage bay","Proximity to the dispatch counter to minimize travel time","Placement in the highest, least-used racking bays","Storage in the offline quarantine zone"],a:1}
    ]
  },
  { 
    name:"Sustainable Warehouse & EHS", 
    shortName:"Sustainability & EHS", 
    icon:"fa-leaf", 
    questions:[
      {q:"What is the core principle of 'green warehousing' as covered in the training programme?",o:["Painting the warehouse green for visual compliance","Minimising the environmental impact of warehouse operations","Using only green-coloured packaging materials","Exclusively storing organic and certified products"],a:1},
      {q:"What should be done immediately if a defect poses an immediate safety risk in the stores area?",o:["Report it at the end of shift using the Maintenance Request Form","Cordon off the area and notify the Stores Manager by phone immediately","Attempt to repair the defect yourself before reporting","Wait for the next scheduled inspection to document it"],a:1},
      {q:"According to the green waste hierarchy, what is the first and most preferred action?",o:["Recycle clean plastics","Reuse wooden pallets","Refuse — don't acquire what you don't need","Dispose in general landfill waste"],a:2},
      {q:"Why is it critical to keep cold store and freezer doors tightly sealed at all times?",o:["To prevent light from entering the room","Damaged seals cause refrigeration systems to use significantly more power","To comply with FIFO stock rotation layouts","To keep the barcode scanner batteries charged"],a:1},
      {q:"What are the four primary waste streams that must be segregated at source in PAB stores?",o:["Paper, plastic, metal, and glass","General, recyclable, chemical/hazardous, and scrap metal","Chemical, food, dry goods, and liquid waste","Supplier boxes, plastic wrap, office paper, and kitchen waste"],a:1},
      {q:"According to safe lifting protocols, which muscle group must bear the load?",o:["The upper back muscles","The lower spine and waist","The legs, keeping the back straight","The forearm and shoulder muscles"],a:2},
      {q:"What is the correct disposal method for empty chemical containers?",o:["Throw them in the general recyclable waste bin","Triple-rinse, crush, and hand over to an approved hazardous waste disposal contractor","Store them indefinitely under general racking units","Return them directly to the food packaging zone for reuse"],a:1},
      {q:"What is the safe rule when working on step ladders to reach high storage bays?",o:["Climb as fast as possible to minimize working at height","Maintain three points of physical contact at all times","Hold items in both hands while climbing","Always work alone without alerting colleagues"],a:1},
      {q:"Why must even a minor dripping tap or water hose leak be reported immediately under PAB ESG policy?",o:["Water conservation is a key performance area of PAB's environmental footprint","Leaking water automatically corrupts the ERP database","Water leaks immediately attract rodent infestations","Dripping water voids the forklift operating warranties"],a:0},
      {q:"Under what condition does a PAB stores employee have the right to refuse a task?",o:["If they find the task tedious or physically demanding","If the task poses an imminent, serious risk to their health or safety","If they did not receive a written memo the day before","If the task is outside their preferred product category zone"],a:1}
    ]
  }
];

var LETTERS = ['A','B','C','D'];
var TOTAL = TOPICS.length;

/* ================================================================
   STATE
   ================================================================ */
var state = [];
for (var i = 0; i < TOTAL; i++) {
  state.push({
    username: "",
    answers: {},
    phase: 'landing', // phases: 'landing', 'exam', 'results', 'review'
    score: null,
    grade: null,
    passed: null,
    seconds: 0,
    interval: null,
    submitted: false
  });
}
var currentPage = 'dashboard';

/* ================================================================
   HELPERS
   ================================================================ */
function el(id) { return document.getElementById(id); }

/* ================================================================
   BUILD SIDEBAR TOPICS — using DOM methods for reliability
   ================================================================ */
function buildSidebarTopics() {
  var container = el('navTopicsScroll');
  for (var i = 0; i < TOTAL; i++) {
    var item = document.createElement('div');
    item.className = 'nav-topic-item';
    item.setAttribute('data-idx', String(i));
    item.setAttribute('tabindex', '0');
    item.setAttribute('role', 'button');
    item.setAttribute('aria-label', 'Open ' + TOPICS[i].name + ' validation session');

    var num = document.createElement('div');
    num.className = 'nav-topic-num';
    num.textContent = String(i + 1);

    var name = document.createElement('span');
    name.className = 'nav-topic-name';
    name.textContent = TOPICS[i].shortName;

    var badge = document.createElement('span');
    badge.className = 'nav-topic-badge';
    badge.id = 'sbBadge' + i;

    item.appendChild(num);
    item.appendChild(name);
    item.appendChild(badge);
    container.appendChild(item);

    (function(idx) {
      item.addEventListener('click', function() { openTopic(idx); });
      item.addEventListener('keydown', function(e) {
        if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); openTopic(idx); }
      });
    })(i);
  }
}

/* ================================================================
   BUILD DASHBOARD GRID
   ================================================================ */
function buildDashboardGrid() {
  var grid = el('dashTopicsGrid');
  grid.innerHTML = '';
  for (var i = 0; i < TOTAL; i++) {
    var card = document.createElement('div');
    card.className = 'card';
    card.style.cursor = 'pointer';
    card.setAttribute('data-idx', String(i));

    var cardContent = `
      <div style="display:flex; justify-content:space-between; align-items:flex-start;">
        <div style="display:flex; gap:16px;">
          <div style="background:var(--primary-pale); color:var(--primary); width:40px; height:40px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:16px;">
            <i class="fa-solid ${TOPICS[i].icon}"></i>
          </div>
          <div>
            <div class="card-title">${TOPICS[i].name}</div>
            <p>${TOPICS[i].questions.length} Scenario Questions | Standard Pass Mark: 75%</p>
          </div>
        </div>
        <span class="nav-topic-badge" id="dbBadge${i}" style="margin-top:2px;"></span>
      </div>
    `;
    card.innerHTML = cardContent;
    grid.appendChild(card);

    (function(idx) {
      card.addEventListener('click', function() { openTopic(idx); });
    })(i);
  }
}

/* ================================================================
   BUILD ALL 11 TOPIC PAGES
   ================================================================ */
function buildTopicPages() {
  var container = el('topicPagesContainer');
  container.innerHTML = '';

  for (var ti = 0; ti < TOTAL; ti++) {
    var topic = TOPICS[ti];
    var qCount = topic.questions.length;

    var page = document.createElement('div');
    page.className = 'page-view';
    page.id = 'topicPage' + ti;

    /* Phase 1 — Landing Structure */
    var landing = document.createElement('div');
    landing.className = 'landing-page';
    landing.id = 'land' + ti;

    var landingHTML = `
      <div class="landing-icon"><i class="fa-solid ${topic.icon}"></i></div>
      <div class="landing-session-label">Session Module ${ti + 1} of ${TOTAL}</div>
      <div class="landing-topic-name">${topic.name}</div>
      
      <!-- Username registration box -->
      <div class="landing-username-container">
        <label for="userInp${ti}">Candidate Name / Operative ID</label>
        <input type="text" id="userInp${ti}" class="username-input-field" 
               placeholder="Enter full name or work identity code..." 
               onkeyup="validateInputs(${ti})">
      </div>

      <div class="landing-rules">
        <h3>Syllabus & Core Objectives</h3>
        <p style="font-size:13.5px; margin-bottom:12px; color:var(--text-light);">
          This assessment comprises exactly 10 contextual scenario questions. Sourced from standard operating procedures, this is a closed-source evaluation of the operational training curriculum. You must secure a score of at least 7.5 out of 10 (75%) to qualify for validation credit.
        </p>
        <ul>
          <li>Calculated localized validation timer initiates immediately on launch.</li>
          <li>Correct solutions, feedback logs, and rationales are locked until submission.</li>
          <li>System performance data remains isolated to this section.</li>
        </ul>
      </div>
      
      <button class="btn btn-primary" id="btnStart${ti}" disabled>
        Launch Validation Session <i class="fa-solid fa-arrow-right" style="margin-left:8px;"></i>
      </button>
    `;
    landing.innerHTML = landingHTML;
    page.appendChild(landing);

    /* Phase 2 — Exam Questions Module */
    var exam = document.createElement('div');
    exam.className = 'hidden';
    exam.id = 'exam' + ti;

    var eHead = document.createElement('div');
    eHead.className = 'exam-header-bar';
    eHead.innerHTML = `
      <div style="display:flex; align-items:center; gap:12px; margin-bottom:4px;">
        <h2>${topic.name}</h2>
      </div>
      <div class="ehb-meta">
        <span><i class="fa-solid fa-clipboard-list"></i> 10 Questions</span>
        <span><i class="fa-solid fa-clock"></i> Localized Timer Active</span>
        <span id="candidateNameBar${ti}"><i class="fa-solid fa-user"></i> Candidate: Unverified</span>
      </div>
      <div class="ehb-progress">
        <div class="track"><div class="fill" id="eFill${ti}"></div></div>
        <div class="prog-text" id="eText${ti}">0 / 10</div>
      </div>
    `;
    exam.appendChild(eHead);

    /* Grading Banner on review sheet */
    var reviewBanner = document.createElement('div');
    reviewBanner.className = 'review-candidate-banner hidden';
    reviewBanner.id = 'reviewBanner' + ti;
    reviewBanner.innerHTML = `Candidate Report Sheet: <span id="reviewCandidateName${ti}">N/A</span>`;
    exam.appendChild(reviewBanner);

    for (var qi = 0; qi < qCount; qi++) {
      var q = topic.questions[qi];
      var qCard = document.createElement('div');
      qCard.className = 'question-card';
      qCard.id = `qC${ti}_${qi}`;

      var qLbl = document.createElement('div');
      qLbl.className = 'q-label';
      qLbl.innerHTML = `Scenario Question ${qi + 1} <i class="fa-solid fa-circle-check icon-correct"></i> <i class="fa-solid fa-circle-xmark icon-incorrect"></i>`;

      var qTxt = document.createElement('div');
      qTxt.className = 'q-text';
      qTxt.innerHTML = q.q;

      var optsList = document.createElement('div');
      optsList.className = 'options-list';

      for (var oi = 0; oi < q.o.length; oi++) {
        var optRow = document.createElement('div');
        optRow.className = 'option-row';
        optRow.setAttribute('data-ti', String(ti));
        optRow.setAttribute('data-qi', String(qi));
        optRow.setAttribute('data-oi', String(oi));
        optRow.setAttribute('role', 'radio');
        optRow.setAttribute('aria-checked', 'false');
        optRow.setAttribute('tabindex', '0');

        var dot = document.createElement('div');
        dot.className = 'option-dot';

        var oText = document.createElement('div');
        oText.className = 'opt-text';
        oText.innerHTML = `<span class="opt-letter">${LETTERS[oi]}.</span> ${q.o[oi]}`;

        optRow.appendChild(dot);
        optRow.appendChild(oText);
        optsList.appendChild(optRow);
      }

      qCard.appendChild(qLbl);
      qCard.appendChild(qTxt);
      qCard.appendChild(optsList);
      exam.appendChild(qCard);
    }
    page.appendChild(exam);

    /* Phase 3 — Detailed Results reporting card */
    var results = document.createElement('div');
    results.className = 'hidden';
    results.id = 'res' + ti;
    
    results.innerHTML = `
      <div class="results-container">
        <div class="res-candidate-tag" id="rCandidateTag${ti}">
          Validated Candidate: <span id="rCandidateName${ti}" style="font-weight: 700; color: var(--accent);"></span>
        </div>
        <div class="res-icon" id="rIcon${ti}"><i class="fa-solid fa-trophy"></i></div>
        <div class="res-title" id="rTitle${ti}">Evaluation Completed</div>
        <div class="res-grade" id="rGrade${ti}">Grade A</div>
        <div class="res-score" id="rScore${ti}">0%</div>
        <div class="res-score-label" id="rLabel${ti}">0 out of 10 Correct</div>
        
        <div class="res-breakdown">
          <div class="res-bd-item">
            <div class="bd-val val-green" id="rOk${ti}">0</div>
            <div class="bd-lbl">Correct</div>
          </div>
          <div class="res-bd-item">
            <div class="bd-val val-red" id="rNo${ti}">0</div>
            <div class="bd-lbl">Incorrect</div>
          </div>
          <div class="res-bd-item">
            <div class="bd-val val-muted" id="rNa${ti}">0</div>
            <div class="bd-lbl">Unanswered</div>
          </div>
        </div>
        
        <div class="res-buttons">
          <button class="btn btn-primary btn-sm" id="rReview${ti}" style="display: none !important;"><i class="fa-solid fa-magnifying-glass"></i> Review Answers</button>
          <button class="btn btn-outline btn-sm" id="rRetry${ti}"><i class="fa-solid fa-rotate-right"></i> Retry Session</button>
          <button class="btn btn-outline btn-sm" id="rHome${ti}"><i class="fa-solid fa-grid-2"></i> All Modules</button>
        </div>
      </div>
    `;
    page.appendChild(results);

    container.appendChild(page);

    /* Bind action triggers inside closure */
    (function(idx) {
      el('btnStart' + idx).addEventListener('click', function() { beginExam(idx); });
      el('rRetry' + idx).addEventListener('click', function() { retryExam(idx); });
      el('rHome' + idx).addEventListener('click', function() { goHome(); });
    })(ti);
  }

  /* Delegated option click handler */
  container.addEventListener('click', handleOptClick);
  container.addEventListener('keydown', function(e) {
    if ((e.key === 'Enter' || e.key === ' ') && e.target.closest('.option-row')) {
      e.preventDefault(); handleOptClick(e);
    }
  });
}

/* ================================================================
   INPUT VALIDATION (Enforces username capture)
   ================================================================ */
function validateInputs(ti) {
  var val = el('userInp' + ti).value.trim();
  var launchBtn = el('btnStart' + ti);
  if (val.length >= 2) {
    launchBtn.removeAttribute('disabled');
  } else {
    launchBtn.setAttribute('disabled', 'true');
  }
}

/* ================================================================
   OPTION SELECTION
   ================================================================ */
function handleOptClick(e) {
  var row = e.target.closest('.option-row');
  if (!row || row.classList.contains('locked')) return;
  var ti = parseInt(row.getAttribute('data-ti'));
  var qi = parseInt(row.getAttribute('data-qi'));
  var oi = parseInt(row.getAttribute('data-oi'));
  if (state[ti].phase !== 'exam') return;

  var all = document.querySelectorAll(`.option-row[data-ti="${ti}"][data-qi="${qi}"]`);
  for (var i = 0; i < all.length; i++) {
    all[i].classList.remove('selected');
    all[i].setAttribute('aria-checked', 'false');
  }
  row.classList.add('selected');
  row.setAttribute('aria-checked', 'true');
  state[ti].answers[qi] = oi;
  
  if (!state[ti].submitted) {
    updateBadges(ti, 'wip');
  }

  updateProgress(ti);
}

/* ================================================================
   NAVIGATION ROUTING
   ================================================================ */
function goHome() {
  if (typeof currentPage === 'number') stopTimer(currentPage);
  currentPage = 'dashboard';

  el('pageDashboard').classList.add('active');
  var pages = document.querySelectorAll('#topicPagesContainer > .page-view');
  for (var i = 0; i < pages.length; i++) pages[i].classList.remove('active');

  el('fixedSubmitBar').classList.add('hidden');
  el('headerTimer').classList.add('inactive');

  el('navHomeBtn').classList.add('active');
  var items = document.querySelectorAll('.nav-topic-item');
  for (var j = 0; j < items.length; j++) items[j].classList.remove('active');

  window.scrollTo({top:0, behavior:'smooth'});
  closeMobile();
  updateGlobalStats();
}

function openTopic(idx) {
  if (typeof currentPage === 'number') stopTimer(currentPage);
  currentPage = idx;

  el('pageDashboard').classList.remove('active');
  var pages = document.querySelectorAll('#topicPagesContainer > .page-view');
  for (var i = 0; i < pages.length; i++) pages[i].classList.remove('active');
  el('topicPage' + idx).classList.add('active');

  el('navHomeBtn').classList.remove('active');
  var items = document.querySelectorAll('.nav-topic-item');
  for (var j = 0; j < items.length; j++) {
    items[j].classList.remove('active');
    if (parseInt(items[j].getAttribute('data-idx')) === idx) items[j].classList.add('active');
  }

  setPhase(idx, state[idx].phase);

  if (state[idx].phase === 'exam') {
    el('fixedSubmitBar').classList.remove('hidden');
    el('headerTimer').classList.remove('inactive');
    startTimer(idx);
    updateProgress(idx);
  } else {
    el('fixedSubmitBar').classList.add('hidden');
    el('headerTimer').classList.add('inactive');
    
    if (state[idx].phase === 'results') {
      var s = state[idx].seconds;
      el('timerDisplay').textContent = String(Math.floor(s/60)).padStart(2,'0') + ':' + String(s%60).padStart(2,'0');
    } else {
      el('timerDisplay').textContent = '00:00';
    }
  }

  window.scrollTo({top:0, behavior:'smooth'});
  closeMobile();
}

function setPhase(ti, phase) {
  state[ti].phase = phase;
  el('land' + ti).classList.toggle('hidden', phase !== 'landing');
  el('exam' + ti).classList.toggle('hidden', phase !== 'exam' && phase !== 'review');
  el('res' + ti).classList.toggle('hidden', phase !== 'results');
}

/* ================================================================
   TIMER CONTROLS
   ================================================================ */
function startTimer(ti) {
  if (state[ti].interval) clearInterval(state[ti].interval);
  state[ti].interval = setInterval(function() {
    state[ti].seconds++;
    var s = state[ti].seconds;
    el('timerDisplay').textContent = String(Math.floor(s/60)).padStart(2,'0') + ':' + String(s%60).padStart(2,'0');
  }, 1000);
}

function stopTimer(ti) {
  if (ti >= 0 && state[ti] && state[ti].interval) {
    clearInterval(state[ti].interval);
    state[ti].interval = null;
  }
}

function fmtTime(s) { 
  var m = Math.floor(s/60), sc = s%60; 
  return m > 0 ? m + 'm ' + sc + 's' : sc + 's'; 
}

/* ================================================================
   SESSION INITIALIZATION
   ================================================================ */
function beginExam(ti) {
  var usernameInput = el('userInp' + ti);
  var username = usernameInput ? usernameInput.value.trim() : "";
  if (username.length < 2) {
    showToast("Please provide a valid Username/ID to begin.");
    return;
  }
  
  // Set current session's validated candidate name
  state[ti].username = username;
  el('candidateNameBar' + ti).innerHTML = `<i class="fa-solid fa-user"></i> Candidate: ${username}`;

  state[ti].phase = 'exam';
  state[ti].seconds = 0;
  el('timerDisplay').textContent = '00:00';
  setPhase(ti, 'exam');
  el('fixedSubmitBar').classList.remove('hidden');
  el('headerTimer').classList.remove('inactive');
  startTimer(ti);
  updateProgress(ti);
  updateBadges(ti, 'wip');
  window.scrollTo({top:0, behavior:'smooth'});
}

/* ================================================================
   PROGRESS TRACKER
   ================================================================ */
function updateProgress(ti) {
  var answered = Object.keys(state[ti].answers).length;
  var total = TOPICS[ti].questions.length;
  var pct = (answered / total) * 100;
  var fill = el('eFill' + ti);
  var txt = el('eText' + ti);
  if (fill) fill.style.width = pct + '%';
  if (txt) txt.textContent = answered + ' / ' + total;
  el('fsbText').innerHTML = `Module Progress: <strong>${answered}</strong> of ${total} answered`;
  el('btnSubmitExam').disabled = (answered === 0);
}

/* ================================================================
   EXAM SUBMISSION (NO ANSWER REVEAL - GRADING ONLY)
   ================================================================ */
el('btnSubmitExam').addEventListener('click', function() {
  if (typeof currentPage !== 'number') return;
  submitExam(currentPage);
});

function submitExam(ti) {
  var st = state[ti];
  if (st.phase !== 'exam') return;
  st.phase = 'results';
  st.submitted = true;
  stopTimer(ti);
  el('fixedSubmitBar').classList.add('hidden');
  el('headerTimer').classList.add('inactive');

  var topic = TOPICS[ti];
  var ok = 0, no = 0, na = 0;

  for (var qi = 0; qi < topic.questions.length; qi++) {
    var q = topic.questions[qi];
    var card = el('qC' + ti + '_' + qi);
    
    // Reset and lock options so no changes can be made, without showing correct/incorrect colors
    card.classList.remove('is-correct', 'is-incorrect');
    var opts = card.querySelectorAll('.option-row');
    for (var o = 0; o < opts.length; o++) {
      opts[o].classList.add('locked');
      opts[o].classList.remove('show-correct', 'show-wrong');
    }

    var ua = st.answers[qi];
    if (ua === undefined) { 
      na++; 
    } else if (ua === q.a) { 
      ok++; 
      // Background calculation only — DO NOT add visual correct indicators
    } else { 
      no++; 
      // Background calculation only — DO NOT add visual incorrect indicators
    }
  }

  var pct = Math.round((ok / topic.questions.length) * 100);
  st.score = pct;
  st.passed = (pct >= 75);

  var gt, gc, ih, tt;
  if (pct >= 90) { 
    gt = 'Grade A — Distinguished Excellence'; gc = 'grade-a'; ih = '<i class="fa-solid fa-trophy"></i>'; tt = 'Outstanding Execution'; 
  } else if (pct >= 75) { 
    gt = 'Grade B — Merit Pass'; gc = 'grade-b'; ih = '<i class="fa-solid fa-medal"></i>'; tt = 'Qualified Operative'; 
  } else if (pct >= 50) { 
    gt = 'Grade C — Under Qualification Threshold'; gc = 'grade-c'; ih = '<i class="fa-solid fa-book-open"></i>'; tt = 'Improvement Required'; 
  } else { 
    gt = 'Grade F — Dynamic Re-trial Standard'; gc = 'grade-f'; ih = '<i class="fa-solid fa-rotate-right"></i>'; tt = 'Non-Qualified Standard'; 
  }
  st.grade = gt.charAt(6);

  var ic = el('rIcon'+ti); ic.className = 'res-icon ' + gc; ic.innerHTML = ih;
  el('rTitle'+ti).textContent = tt;
  
  var ge = el('rGrade'+ti); 
  ge.className = 'res-grade ' + gc;
  ge.textContent = gt;
  
  el('rScore'+ti).textContent = pct + '%';
  el('rLabel'+ti).textContent = `${ok} out of ${topic.questions.length} Scenario Points (${fmtTime(st.seconds)})`;
  
  el('rOk'+ti).textContent = ok;
  el('rNo'+ti).textContent = no;
  el('rNa'+ti).textContent = na;

  // Render the candidate's name in Phase 3 results box
  el('rCandidateName' + ti).textContent = st.username;

  setPhase(ti, 'results');
  updateBadges(ti, st.passed ? 'pass' : 'fail');
  updateGlobalStats();
  
  showToast(`${topic.shortName} Validation Completed! Score: ${pct}%`);
  window.scrollTo({top:0, behavior:'smooth'});
  
  if (window.MathJax) {
    window.MathJax.typesetPromise();
  }
}

/* ================================================================
   REVIEW & RETRY MODULES
   ================================================================ */
function reviewAnswers(ti) {
  // Bind username to review panel banner
  var banner = el('reviewBanner' + ti);
  var userSpan = el('reviewCandidateName' + ti);
  if (banner && userSpan) {
    userSpan.textContent = state[ti].username;
    banner.classList.remove('hidden');
  }

  setPhase(ti, 'review');
  window.scrollTo({top:0, behavior:'smooth'});
}

function retryExam(ti) {
  stopTimer(ti);
  
  state[ti] = {
    username: "",
    answers: {},
    phase: 'landing',
    score: null,
    grade: null,
    passed: null,
    seconds: 0,
    interval: null,
    submitted: false
  };

  var topic = TOPICS[ti];
  for (var qi = 0; qi < topic.questions.length; qi++) {
    var card = el('qC' + ti + '_' + qi);
    card.className = 'question-card';
    var opts = card.querySelectorAll('.option-row');
    for (var o = 0; o < opts.length; o++) {
      opts[o].classList.remove('locked', 'selected', 'show-correct', 'show-wrong');
      opts[o].setAttribute('aria-checked', 'false');
    }
  }

  // Clear username fields and disable start button
  var userField = el('userInp' + ti);
  if (userField) userField.value = "";
  var startBtn = el('btnStart' + ti);
  if (startBtn) startBtn.setAttribute('disabled', 'true');

  var banner = el('reviewBanner' + ti);
  if (banner) banner.classList.add('hidden');

  updateProgress(ti);
  updateBadges(ti, null);
  setPhase(ti, 'landing');
  updateGlobalStats();
  
  showToast('Syllabus session variables fully cleared. Re-launch ready.');
  window.scrollTo({top:0, behavior:'smooth'});
}

/* ================================================================
   GLOBAL STATISTICS AND BADGING
   ================================================================ */
function updateBadges(ti, type) {
  var sb = el('sbBadge' + ti);
  var db = el('dbBadge' + ti);
  
  if (!sb) return;

  sb.className = 'nav-topic-badge';
  if (db) db.className = 'nav-topic-badge';

  if (!type) {
    sb.classList.remove('visible');
    if (db) db.classList.remove('visible');
    return;
  }

  sb.classList.add('visible');
  if (db) db.classList.add('visible');

  if (type === 'wip') {
    sb.classList.add('wip'); sb.textContent = 'Active';
    if (db) { db.classList.add('wip'); db.textContent = 'Active'; }
  } else if (type === 'pass') {
    var scoreText = state[ti].score + '% Pass';
    sb.classList.add('pass'); sb.textContent = scoreText;
    if (db) { db.classList.add('pass'); db.textContent = scoreText; }
  } else if (type === 'fail') {
    var scoreText = state[ti].score + '% Fail';
    sb.classList.add('fail'); sb.textContent = scoreText;
    if (db) { db.classList.add('fail'); db.textContent = scoreText; }
  }
}

function updateGlobalStats() {
  var completed = 0;
  var passed = 0;
  var totalScore = 0;

  for (var i = 0; i < TOTAL; i++) {
    if (state[i].submitted) {
      completed++;
      totalScore += state[i].score;
      if (state[i].passed) passed++;
    }
  }

  var avg = completed > 0 ? Math.round(totalScore / completed) + '%' : '--';

  el('statsCompleted').textContent = completed + ' / ' + TOTAL;
  el('statsAvgScore').textContent = avg;
  el('statsPassed').textContent = passed;

  var progressPct = (completed / TOTAL) * 100;
  el('statsBarFill').style.width = progressPct + '%';
}

function showToast(msg) {
  var t = el('toastNotification');
  t.textContent = msg;
  t.classList.add('show');
  setTimeout(function() { t.classList.remove('show'); }, 3800);
}

/* ================================================================
   MOBILE RESPONSIVENESS CAPABILITIES
   ================================================================ */
var mobBtn = el('mobileMenuBtn');
var sbar = el('sidebar');

mobBtn.addEventListener('click', function() {
  sbar.classList.toggle('open');
  var isOpen = sbar.classList.contains('open');
  mobBtn.innerHTML = isOpen ? '<i class="fa-solid fa-xmark"></i>' : '<i class="fa-solid fa-bars"></i>';
});

function closeMobile() {
  sbar.classList.remove('open');
  mobBtn.innerHTML = '<i class="fa-solid fa-bars"></i>';
}

/* ================================================================
   INITIALIZATION LAUNCHPAD
   ================================================================ */
el('navHomeBtn').addEventListener('click', goHome);

window.onload = function() {
  buildSidebarTopics();
  buildDashboardGrid();
  buildTopicPages();
  updateGlobalStats();
  
  if (window.MathJax) {
    window.MathJax.typesetPromise();
  }
};
</script>
<script src="../assets/js/resources-header-injector.js"></script>
</body>
</html>
