diff --git a/output/timetable.js b/output/timetable.js
index f8a7ec1..02792ca 100644
--- a/output/timetable.js
+++ b/output/timetable.js
@@ -1729,6 +1729,16 @@ function syntaxHighlight(json) {
const mainTable = document.getElementById("main-table");
if (!mainTable) return;
+ // Ensure the header row is inside a proper element.
+ // Some exports use a bare as the first row; move it into a thead so CSS/sticky headers work.
+ if (!mainTable.tHead) {
+ const firstRow = mainTable.querySelector('tr');
+ if (firstRow) {
+ const thead = mainTable.createTHead();
+ thead.appendChild(firstRow);
+ }
+ }
+
// Helper to remove highlight from all headers
function clearColHover() {
const ths = mainTable.querySelectorAll("th.col-hover");
@@ -1763,6 +1773,18 @@ $("#main-table").before(
``
);
+// Ensure main table header is sticky and compact
+if ($('#main-table-style').length === 0) {
+ $('head').append(`
+
+ `);
+}
+
// --- Modal show/hide logic ---
$("#show-display-settings").on("click", function() {
$("#display-settings-modal").show();
diff --git a/rota_generator/shifts.py b/rota_generator/shifts.py
index f5a2dd3..70927c1 100644
--- a/rota_generator/shifts.py
+++ b/rota_generator/shifts.py
@@ -5222,8 +5222,10 @@ class RotaBuilder(object):
timetable = []
+ # Run times and heading go outside the table; store for later insertion
+ run_times_html = ""
if self.run_start_time is not None and self.run_end_time is not None:
- timetable.append(
+ run_times_html = (
" Rota start date: {self.start_date.isoformat()} ({self.weeks[-1]} weeks)
"
- )
+ heading_html = f"Rota start date: {self.start_date.isoformat()} ({self.weeks[-1]} weeks)
"
date_row = [""]
@@ -5249,7 +5249,8 @@ class RotaBuilder(object):
f" Week {week}: {day} "
)
n = n + 1
- timetable.append(f"{''.join(date_row)} ")
+ # Header row (dates) should be placed in a proper thead
+ header_row_html = f"{''.join(date_row)} "
current_site = ""
@@ -5675,7 +5676,8 @@ class RotaBuilder(object):
else:
result_string = "Rota not run"
- joined_timetable = "\n".join(timetable)
+ # Wrap the remaining rows in a tbody and prepend the thead
+ joined_timetable = header_row_html + "\n