diff --git a/containers/libreportal/frontend/core/setup/css/setup-wizard.css b/containers/libreportal/frontend/core/setup/css/setup-wizard.css
index 3c82c30..447d8b8 100755
--- a/containers/libreportal/frontend/core/setup/css/setup-wizard.css
+++ b/containers/libreportal/frontend/core/setup/css/setup-wizard.css
@@ -1391,3 +1391,32 @@ body.setup-wizard-open .eo-modal { z-index: 10000; }
other dropdowns rather than showing stock white chrome. */
.setup-storage-default select,
.setup-storage-default .custom-select { flex: 1; min-width: 180px; }
+
+/* Two choices above the drive list. The list below is reference, not input. */
+.setup-storage-choice {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ margin-bottom: 10px;
+}
+.setup-storage-choice-label {
+ flex: 0 0 120px;
+ font-size: 0.92em;
+ opacity: 0.92;
+}
+.setup-storage-choice select,
+.setup-storage-choice .custom-select { flex: 1; min-width: 180px; }
+.setup-storage-choice-msg {
+ margin: 2px 0 4px;
+ padding: 9px 11px;
+ border-radius: 8px;
+ border: 1px solid rgba(255, 190, 60, 0.32);
+ background: rgba(255, 190, 60, 0.09);
+ font-size: 0.86em;
+ line-height: 1.5;
+}
+.setup-storage-choice-msg code {
+ display: inline-block;
+ margin-top: 4px;
+ word-break: break-all;
+}
diff --git a/containers/libreportal/frontend/core/setup/js/setup-wizard.js b/containers/libreportal/frontend/core/setup/js/setup-wizard.js
index bbc84af..4c72abc 100755
--- a/containers/libreportal/frontend/core/setup/js/setup-wizard.js
+++ b/containers/libreportal/frontend/core/setup/js/setup-wizard.js
@@ -34,6 +34,8 @@ class SetupWizard {
this.fstabWanted = [];
// Which drive new apps default to: 'primary' or a ticked drive's path.
this.storageDefault = 'primary';
+ // Where LibrePortal's own tree should live (root-only to change post-install).
+ this.storageSystemChoice = 'primary';
this.installLevel = 'beginner';
this.totalSteps = this._effectiveTotalSteps();
this.domainCount = 0; // tracked dynamically as the user adds rows
@@ -238,8 +240,9 @@ class SetupWizard {
Storage
?
+
+
Drives
-
@@ -476,39 +479,27 @@ class SetupWizard {
title="${used}% used, ${100 - used}% free">`;
}
- // One card, one line.
+ // One card, one line — informational.
+ //
+ // No checkbox: the dropdowns above ARE the selection, and a drive picked
+ // there is registered automatically. Two ways to say the same thing (tick it
+ // AND choose it) is how you end up with a ticked drive nobody selected.
//
// The badge carries severity and Details carries the explanation, so the card
- // itself stays a single row — listing every warning here pushed each drive to
- // three lines and made the step tall for no gain.
- //
- // `locked` renders it ticked and non-interactive: the system drive is what
- // apps fall back to, so it cannot be deselected. Details still works, which
- // is the point of showing it at all on a single-disk box.
+ // stays a single row.
_storageCard(c, key, opts) {
const o = opts || {};
const refused = c.verdict === 'refuse';
- const badge = o.locked
- ? 'default'
+ const badge = o.system
+ ? 'system'
: (refused ? 'can\u2019t be used'
: (c.verdict === 'warn' ? 'needs care' : ''));
- const title = o.locked ? 'System disk' : c.path;
-
- // The system disk carries NO checkbox — not even a disabled one. Apps fall
- // back to it whatever happens, so it is not a choice, and a control that
- // can never change state reads as "locked option" rather than "this is
- // simply where things go". It is a