diff --git a/containers/libreportal/frontend/components/apps/overview/css/overview.css b/containers/libreportal/frontend/components/apps/overview/css/overview.css
index 051c7d4..a9dbc51 100644
--- a/containers/libreportal/frontend/components/apps/overview/css/overview.css
+++ b/containers/libreportal/frontend/components/apps/overview/css/overview.css
@@ -135,7 +135,8 @@
/* The Backups tab mounts the real BackupPage. Its own page-header replaces the
generic fleet header, and its left sidebar is restyled into a horizontal
nested tab strip so the whole thing reads as tabs-within-tabs. */
-#overview-view.ov-backups-active .overview-header { display: none; }
+#overview-view.ov-backups-active .overview-header,
+#overview-view.ov-migrate-active .overview-header { display: none; }
#overview-view #ov-pane-backups .backup-layout { display: block; }
#overview-view #ov-pane-backups .backup-layout > .sidebar {
@@ -164,7 +165,7 @@
min-width: 0;
align-items: center;
justify-content: center;
- gap: 8px;
+ gap: 6px;
margin: 0;
padding: 12px 14px;
white-space: nowrap;
diff --git a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js
index d87c4d3..0a76f7f 100644
--- a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js
+++ b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js
@@ -117,10 +117,15 @@ class OverviewManager {
_applyTab(id) {
if (this.tabs) this.tabs.switch(id);
- // The Backups tab embeds the full backup center, which brings its own header
- // and a nested sub-tab strip — hide the generic fleet header for it.
+ // Backups embeds the full backup center (its own header + nested sub-tab
+ // strip) and Migrate carries its own in-content .config-title header above
+ // its sub-tabs — both supply their own heading, so hide the generic fleet
+ // header for them.
const root = document.getElementById('overview-view');
- if (root) root.classList.toggle('ov-backups-active', id === 'backups');
+ if (root) {
+ root.classList.toggle('ov-backups-active', id === 'backups');
+ root.classList.toggle('ov-migrate-active', id === 'migrate');
+ }
this.updateHeader(id);
this.renderTab(id);
this.current = id;
diff --git a/containers/libreportal/frontend/core/theme/css/base.css b/containers/libreportal/frontend/core/theme/css/base.css
index c9dee56..5026085 100755
--- a/containers/libreportal/frontend/core/theme/css/base.css
+++ b/containers/libreportal/frontend/core/theme/css/base.css
@@ -526,7 +526,14 @@ html[data-theme="nebula"]::after {
min-width: 0;
text-align: center;
white-space: nowrap;
+ /* Lay the icon + label out as flex children with a fixed gap so spacing is
+ identical whether or not the markup has whitespace between the two spans
+ (the per-app Config sub-tabs rely on source whitespace; the Migrate
+ sub-tabs don't — this makes both render the same). */
+ display: flex;
+ align-items: center;
justify-content: center;
+ gap: 6px;
}
/* Task Status Indicator */