diff --git a/crates/ui-egui/src/chrome.rs b/crates/ui-egui/src/chrome.rs
--- a/crates/ui-egui/src/chrome.rs
+++ b/crates/ui-egui/src/chrome.rs
@@ -8,6 +8,7 @@ use crate::icons::{self, Icon};
 use crate::theme::Tokens;
 
 pub mod annoscale;
+pub mod status;
 
 const TOOLBAR: &[&[(Icon, &str, &str, Option<&str>)]] = &[
     &[
@@ -296,6 +297,7 @@ pub fn status_bar(app: &mut CadApp, ui: &mut egui::Ui) {
     let t = Tokens::get();
     egui::Panel::bottom("cc_status").exact_size(26.0).frame(egui::Frame::NONE.fill(t.chrome)).show(ui, |ui| {
         let r = ui.max_rect();
+        let background = ui.interact(r, ui.scope_id().with("status_context"), Sense::click());
         let p = ui.painter().clone();
         let mut x = r.left() + 8.0;
         // Clear the status message on time even when no input arrives (the app only repaints on input).
@@ -326,7 +328,7 @@ pub fn status_bar(app: &mut CadApp, ui: &mut egui::Ui) {
         let s = app.session.settings.clone();
         let anno_all = app.session.doc().is_ok_and(|d| d.anno_all_visible());
         use cadcraft_engine::snap::mode;
-        let toggles: Vec<(Icon, bool, &str, &str)> = vec![
+        let mut toggles: Vec<(Icon, bool, &str, &str)> = vec![
             (Icon::Grid, s.gridmode, "grid", "Grid (F7)"),
             (Icon::Snap, s.snapmode, "snap", "Snap Mode (F9)"),
             (Icon::Ortho, s.orthomode, "ortho", "Ortho Mode (F8)"),
@@ -342,10 +344,11 @@ pub fn status_bar(app: &mut CadApp, ui: &mut egui::Ui) {
             (Icon::Workspace, false, "ui.noop", "Workspace Switching"),
             (Icon::Gear, false, "ui.dialog.dsettings", "Drafting Settings"),
         ];
+        toggles.retain(|(_, _, command, _)| status::visible(app, status::command_id(command)));
         let size = 20.0;
-        let mut rx = r.right() - 8.0 - toggles.len() as f32 * (size + 4.0);
+        let mut rx = r.right() - 32.0 - toggles.len() as f32 * (size + 4.0);
         // Coordinates.
-        let coord = app.canvas.cursor.map(|c| {
+        let coord = app.canvas.cursor.filter(|_| status::visible(app, "coordinates")).map(|c| {
             let (lu, lp) = app.session.doc().map(|d| (d.header.i64("LUNITS", 2), d.header.i64("LUPREC", 4))).unwrap_or((2, 4));
             format!(
                 "{}, {}, {}",
@@ -357,22 +360,28 @@ pub fn status_bar(app: &mut CadApp, ui: &mut egui::Ui) {
         // MODEL / PAPER (layouts only): toggles MSPACE and PSPACE like AutoCAD's status button.
         let mut coord_right = rx - 8.0;
         // The annotation scale list (model space).
-        coord_right = annoscale::status(app, ui, coord_right, r.center().y);
+        if status::visible(app, "annotationScale") {
+            coord_right = annoscale::status(app, ui, coord_right, r.center().y);
+        }
         if matches!(app.session.layout_space(), cadcraft_doc::Space::Paper(_)) {
-            let model = app.session.state().is_ok_and(|st| st.mspace.is_some());
-            let label = if model { "MODEL" } else { "PAPER" };
-            let br = Rect::from_min_max(pos2(rx - 60.0, r.center().y - 9.0), pos2(rx - 6.0, r.center().y + 9.0));
-            let resp = ui.interact(br, ui.scope_id().with("mspace_toggle"), Sense::click());
-            p.rect_filled(br, 3.0, if resp.hovered() { t.control_hover } else { t.toggle_on.gamma_multiply(0.25) });
-            p.text(br.center(), egui::Align2::CENTER_CENTER, crate::i18n::t(label), crate::theme::small(), t.text);
-            icons::describe_control(ui, &resp, label, None, false);
-            if resp.on_hover_text(crate::tl!("Switch between model space in a viewport and paper space")).clicked() {
-                let _ = app.run(if model { "pspace" } else { "mspace" }, json!({}));
-                app.canvas.list = None;
+            if status::visible(app, "paperSpace") {
+                let model = app.session.state().is_ok_and(|st| st.mspace.is_some());
+                let label = if model { "MODEL" } else { "PAPER" };
+                let br = Rect::from_min_max(pos2(rx - 60.0, r.center().y - 9.0), pos2(rx - 6.0, r.center().y + 9.0));
+                let resp = ui.interact(br, ui.scope_id().with("mspace_toggle"), Sense::click());
+                p.rect_filled(br, 3.0, if resp.hovered() { t.control_hover } else { t.toggle_on.gamma_multiply(0.25) });
+                p.text(br.center(), egui::Align2::CENTER_CENTER, crate::i18n::t(label), crate::theme::small(), t.text);
+                icons::describe_control(ui, &resp, label, None, false);
+                if resp.on_hover_text(crate::tl!("Switch between model space in a viewport and paper space")).clicked() {
+                    let _ = app.run(if model { "pspace" } else { "mspace" }, json!({}));
+                    app.canvas.list = None;
+                }
+                coord_right = br.left() - 10.0;
             }
-            coord_right = br.left() - 10.0;
             // Scale and lock of the active or selected viewport.
-            coord_right = crate::vpscale::status(app, ui, coord_right + 4.0, r.center().y) - 10.0;
+            if status::visible(app, "viewportScale") {
+                coord_right = crate::vpscale::status(app, ui, coord_right + 4.0, r.center().y) - 10.0;
+            }
         }
         // Layout tabs: Model, "+", then the layouts that fit before the right-hand controls (the
         // current one always); the layout list reaches the rest.
@@ -512,6 +521,13 @@ pub fn status_bar(app: &mut CadApp, ui: &mut egui::Ui) {
             Some(c) => crate::menus::run_transparent(app, c),
             None => {}
         }
+        let br = Rect::from_min_size(pos2(r.right() - 28.0, r.center().y - 10.0), vec2(20.0, 20.0));
+        let customize = ui.interact(br, ui.scope_id().with("status_customize"), Sense::click());
+        icons::paint(&p, br.shrink(2.5), Icon::Menu, false);
+        icons::describe_control(ui, &customize, "Status Bar Customization", None, false);
+        egui::Popup::menu(&customize).close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside).show(|ui| status::menu(app, ui));
+        customize.on_hover_text(crate::tl!("Status Bar Customization"));
+        egui::Popup::context_menu(&background).close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside).show(|ui| status::menu(app, ui));
     });
 }
 
diff --git a/crates/ui-egui/src/chrome/status.rs b/crates/ui-egui/src/chrome/status.rs
new file mode 100644
--- /dev/null
+++ b/crates/ui-egui/src/chrome/status.rs
@@ -0,0 +1,85 @@
+//! Status-item visibility is an application preference, independent of drafting settings.
+use crate::CadApp;
+use serde_json::{Value, json};
+
+/// Stable preference IDs paired with translated status-item labels.
+pub const ITEMS: &[(&str, &str)] = &[
+    ("coordinates", "Coordinates"),
+    ("paperSpace", "Paper Space"),
+    ("annotationScale", "Annotation scale"),
+    ("viewportScale", "Viewport scale"),
+    ("grid", "Grid (F7)"),
+    ("snap", "Snap Mode (F9)"),
+    ("ortho", "Ortho Mode (F8)"),
+    ("polar", "Polar Tracking (F10)"),
+    ("isodraft", "Isometric Drafting"),
+    ("otrack", "Object Snap Tracking (F11)"),
+    ("osnap", "Object Snap (F3)"),
+    ("lwdisplay", "Show/Hide Lineweight"),
+    ("transparencydisplay", "Show/Hide Transparency"),
+    ("dynmode", "Dynamic Input (F12)"),
+    ("qpmode", "Quick Properties"),
+    ("annotationVisibility", "Annotation Visibility"),
+    ("workspace", "Workspace Switching"),
+    ("draftingSettings", "Drafting Settings"),
+];
+/// Reject unknown or duplicate IDs before replacing stored preferences.
+pub fn validate(hidden: &[String]) -> Result<(), String> {
+    if hidden.len() > ITEMS.len()
+        || hidden.iter().enumerate().any(|(index, id)| !ITEMS.iter().any(|(known, _)| id == known) || hidden[..index].contains(id))
+    {
+        return Err("Invalid status bar items".into());
+    }
+    Ok(())
+}
+/// Whether a status item is shown, independently of its drafting setting.
+pub fn visible(app: &CadApp, id: &str) -> bool {
+    !app.ui.hidden_status_items.iter().any(|hidden| hidden == id)
+}
+pub(super) fn command_id(command: &str) -> &str {
+    match command {
+        "annovisible.toggle" => "annotationVisibility",
+        "ui.noop" => "workspace",
+        "ui.dialog.dsettings" => "draftingSettings",
+        _ => command,
+    }
+}
+pub(crate) fn route(app: &mut CadApp, id: &str, params: &Value) -> Option<Result<Value, String>> {
+    if id == "ui.status.reset" {
+        app.ui.hidden_status_items.clear();
+        return Some(Ok(json!({"hiddenStatusItems":[]})));
+    }
+    if id != "ui.status.item" {
+        return None;
+    }
+    Some((|| {
+        let item =
+            params.get("item").and_then(Value::as_str).filter(|id| ITEMS.iter().any(|(known, _)| known == id)).ok_or("Unknown status bar item")?;
+        let shown = match params.get("visible") {
+            None => !visible(app, item),
+            Some(v) => v.as_bool().ok_or("visible must be a boolean")?,
+        };
+        let mut hidden = app.ui.hidden_status_items.clone();
+        hidden.retain(|id| id != item);
+        if !shown {
+            hidden.push(item.to_string());
+        }
+        validate(&hidden)?;
+        app.ui.hidden_status_items = hidden;
+        Ok(json!({"item":item,"visible":shown}))
+    })())
+}
+pub(crate) fn menu(app: &mut CadApp, ui: &mut egui::Ui) {
+    if ui.button(crate::tl!("Show All Status Items")).clicked() {
+        let _ = app.run("ui.status.reset", json!({}));
+    }
+    ui.separator();
+    egui::ScrollArea::vertical().max_height(360.0).show(ui, |ui| {
+        for (id, label) in ITEMS {
+            let mut shown = visible(app, id);
+            if ui.checkbox(&mut shown, crate::i18n::t(label)).changed() {
+                let _ = app.run("ui.status.item", json!({"item":id,"visible":shown}));
+            }
+        }
+    });
+}
diff --git a/crates/ui-egui/src/control.rs b/crates/ui-egui/src/control.rs
--- a/crates/ui-egui/src/control.rs
+++ b/crates/ui-egui/src/control.rs
@@ -457,6 +457,9 @@ pub fn handle(app: &mut CadApp, ctx: &egui::Context, req: &ControlRequest) -> Ou
                     if let Err(error) = crate::docking::validate(&u.docking) {
                         return err(error);
                     }
+                    if let Err(error) = crate::chrome::status::validate(&u.hidden_status_items) {
+                        return err(error);
+                    }
                     app.ui = u;
                     ok(serde_json::to_value(&app.ui).unwrap_or_default())
                 }
diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv
--- a/crates/ui-egui/src/i18n/uk.tsv
+++ b/crates/ui-egui/src/i18n/uk.tsv
@@ -1371,3 +1371,7 @@
 	Check for Updates…	Перевірити оновлення…
 	CADCraft is up to date.	Встановлено найновішу версію CADCraft.
 	Could not check for updates.	Не вдалося перевірити оновлення.
+	Coordinates	Координати
+	Show All Status Items	Показати всі елементи рядка стану
+	Status Bar Customization	Налаштування рядка стану
+	Status Bar Item	Елемент рядка стану
diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs
--- a/crates/ui-egui/src/lib.rs
+++ b/crates/ui-egui/src/lib.rs
@@ -81,6 +81,7 @@ pub struct UiState {
     pub show_toolbar: bool,
     pub show_file_tabs: bool,
     pub show_status_bar: bool,
+    pub hidden_status_items: Vec<String>,
     pub show_command_line: bool,
     pub show_viewcube: bool,
     pub show_ucs_icon: bool,
@@ -169,6 +170,7 @@ impl Default for UiState {
             show_toolbar: true,
             show_file_tabs: true,
             show_status_bar: true,
+            hidden_status_items: Vec::new(),
             show_command_line: true,
             show_viewcube: true,
             show_ucs_icon: true,
@@ -437,12 +439,21 @@ impl CadApp {
         if let Some(dir) = &self.ui.last_lisp_dir {
             prefs["lispDir"] = json!(dir);
         }
+        if !self.ui.hidden_status_items.is_empty() {
+            prefs["hiddenStatusItems"] = json!(self.ui.hidden_status_items);
+        }
         prefs.to_string()
     }
 
     /// Restore preferences saved by [`Self::prefs_json`]; unknown or malformed values are ignored.
     pub fn load_prefs(&mut self, json: &str) {
         let Ok(v) = serde_json::from_str::<Value>(json) else { return };
+        if let Some(value) = v.get("hiddenStatusItems")
+            && let Ok(hidden) = serde_json::from_value::<Vec<String>>(value.clone())
+            && chrome::status::validate(&hidden).is_ok()
+        {
+            self.ui.hidden_status_items = hidden;
+        }
         if let Some(prefs) = v.get("spacemouse") {
             let _ = self.spacemouse.load_settings(prefs);
         }
diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs
--- a/crates/ui-egui/src/menus.rs
+++ b/crates/ui-egui/src/menus.rs
@@ -72,6 +72,8 @@ pub const UI_COMMANDS: &[(&str, &str, &[&str], Option<&str>)] = &[
     ("ui.cmdline.clear", "Clear Command History", &[], None),
     ("ui.dialog.language", "Interface Language", &["Edit", "Interface Language"], None),
     ("ui.language", "Language", &[], None),
+    ("ui.status.item", "Status Bar Item", &[], None),
+    ("ui.status.reset", "Show All Status Items", &["Window", "Show All Status Items"], None),
     ("ui.noop", "", &[], None),
     ("ui.quit", "Quit CADCraft", &[], Some("Cmd+Q")),
 ];
@@ -86,6 +88,9 @@ pub fn run_ui_command(app: &mut CadApp, id: &str, params: &Value) -> Option<Resu
 }
 
 fn run_ui_command_inner(app: &mut CadApp, id: &str, params: &Value) -> Option<Result<Value, String>> {
+    if let Some(result) = crate::chrome::status::route(app, id, params) {
+        return Some(result);
+    }
     if let Some(result) = crate::spacemouse::route(app, id, params) {
         return Some(result);
     }
@@ -339,7 +344,17 @@ fn run_ui_command_inner(app: &mut CadApp, id: &str, params: &Value) -> Option<Re
         "ui.resetpalettes" => {
             let (menu, theme, interface_language, save_format) = (app.ui.in_window_menu, app.ui.theme, app.ui.interface_language, app.ui.save_format);
             let (animations, save_version) = (app.ui.animations, std::mem::take(&mut app.ui.save_version));
-            app.ui = crate::UiState { in_window_menu: menu, theme, animations, interface_language, save_format, save_version, ..Default::default() };
+            let hidden_status_items = std::mem::take(&mut app.ui.hidden_status_items);
+            app.ui = crate::UiState {
+                in_window_menu: menu,
+                theme,
+                animations,
+                interface_language,
+                save_format,
+                save_version,
+                hidden_status_items,
+                ..Default::default()
+            };
             Ok(Value::Null)
         }
         "ui.start" => {
diff --git a/crates/ui-egui/tests/it/main.rs b/crates/ui-egui/tests/it/main.rs
--- a/crates/ui-egui/tests/it/main.rs
+++ b/crates/ui-egui/tests/it/main.rs
@@ -28,6 +28,7 @@ mod selection_cycling;
 mod shared_controls;
 mod shortcut_menus;
 mod status_bar_toggles;
+mod status_customization;
 mod style_dialogs;
 mod system_cursor;
 mod text_double_click;
diff --git a/crates/ui-egui/tests/it/status_customization.rs b/crates/ui-egui/tests/it/status_customization.rs
new file mode 100644
--- /dev/null
+++ b/crates/ui-egui/tests/it/status_customization.rs
@@ -0,0 +1,143 @@
+//! The drafting toggles on the status bar are transparent, as F7-F12 are: clicking Grid or Snap
+//! while drawing a line changes the setting and leaves LINE running (#1108).
+
+use cadcraft_engine::doc::{Drawing, EntityKind, Space};
+use cadcraft_engine::geom::Vec2;
+use cadcraft_engine::{Input, Session};
+use cadcraft_ui_egui::{CadApp, Services};
+use egui::vec2;
+use egui_kittest::Harness;
+use egui_kittest::kittest::Queryable;
+use serde_json::json;
+
+fn harness() -> Harness<'static, CadApp> {
+    let mut session = Session::empty();
+    session.open_drawing(Drawing::new_imperial(), "Status bar toggles", None);
+    let app = CadApp::new(session, Services::default());
+    let mut h = Harness::builder().with_size(vec2(1600.0, 1000.0)).build_ui_state(
+        |ui, app: &mut CadApp| {
+            app.logic(ui.ctx());
+            app.ui(ui);
+        },
+        app,
+    );
+    h.run_steps(3);
+    h
+}
+
+fn running(h: &Harness<'_, CadApp>) -> Option<String> {
+    h.state().session.running.as_ref().map(|r| r.id.clone())
+}
+
+#[test]
+fn status_readout_right_click_opens_customization() {
+    let mut h = harness();
+    h.state_mut().canvas.cursor = Some(Vec2::new(1.0, 2.0));
+    h.run_steps(3);
+    let at = egui::pos2(800.0, 987.0);
+    h.event(egui::Event::PointerMoved(at));
+    h.run_steps(2);
+    for pressed in [true, false] {
+        h.event(egui::Event::PointerButton { pos: at, button: egui::PointerButton::Secondary, pressed, modifiers: egui::Modifiers::NONE });
+        h.run_steps(2);
+    }
+    assert!(h.query_by_label("Show All Status Items").is_some());
+    h.get_by_role_and_label(egui::accesskit::Role::CheckBox, "Grid (F7)").click();
+    h.run_steps(4);
+    assert!(h.state().ui.hidden_status_items.iter().any(|id| id == "grid"));
+    assert!(h.query_by_label("Show All Status Items").is_some(), "right-click customization stays open after toggling an item");
+}
+
+#[test]
+fn status_visibility_is_atomic_persistent_and_separate_from_drafting_settings() {
+    use serde_json::json;
+    let mut h = harness();
+    let settings = h.state().session.settings.clone();
+    let dirty = h.state().session.state().unwrap().is_dirty();
+    for (item, _) in cadcraft_ui_egui::chrome::status::ITEMS {
+        h.state_mut().run("ui.status.item", json!({"item":item,"visible":false})).unwrap();
+    }
+    let before = h.state().ui.hidden_status_items.clone();
+    for params in [json!({"item":"unknown"}), json!({"item":"grid","visible":"no"}), json!({"visible":true})] {
+        assert!(h.state_mut().run("ui.status.item", params).is_err());
+        assert_eq!(h.state().ui.hidden_status_items, before);
+    }
+    let restored: cadcraft_ui_egui::UiState = serde_json::from_value(serde_json::to_value(&h.state().ui).unwrap()).unwrap();
+    assert_eq!(restored.hidden_status_items, before);
+    let prefs = h.state().prefs_json();
+    let mut restarted = CadApp::new(Session::new(), Services::default());
+    restarted.load_prefs(&prefs);
+    assert_eq!(restarted.ui.hidden_status_items, before);
+    for invalid in [json!(["grid", "grid"]), json!(["unknown"]), json!([false]), json!("grid")] {
+        restarted.load_prefs(&json!({"hiddenStatusItems":invalid}).to_string());
+        assert_eq!(restarted.ui.hidden_status_items, before, "invalid preferences must be ignored atomically");
+    }
+    restarted.load_prefs("{\"hiddenStatusItems\":[]}");
+    assert!(restarted.ui.hidden_status_items.is_empty());
+    assert!(serde_json::from_value::<cadcraft_ui_egui::UiState>(json!({})).unwrap().hidden_status_items.is_empty());
+    assert_eq!(h.state().session.settings.gridmode, settings.gridmode);
+    assert_eq!(h.state().session.settings.snapmode, settings.snapmode);
+    assert_eq!(h.state().session.state().unwrap().is_dirty(), dirty);
+    h.run_steps(4);
+    assert!(h.query_by_label("Grid (F7)").is_none());
+    h.get_by_label("Status Bar Customization").click();
+    h.run_steps(4);
+    h.get_by_label("Show All Status Items").click();
+    h.run_steps(4);
+    assert!(h.state().ui.hidden_status_items.is_empty());
+}
+
+#[test]
+fn status_customization_does_not_cancel_or_feed_a_point_to_a_running_line() {
+    use egui::accesskit::Role;
+    let mut h = harness();
+    h.state_mut().session.start("line").unwrap();
+    h.state_mut().session.input(Input::Point(Vec2::new(0.0, 0.0))).unwrap();
+    h.run_steps(3);
+    let grid = h.state().session.settings.gridmode;
+    h.get_by_label("Status Bar Customization").click();
+    h.run_steps(4);
+    h.get_by_role_and_label(Role::CheckBox, "Grid (F7)").click();
+    h.run_steps(4);
+    assert!(h.state().ui.hidden_status_items.iter().any(|id| id == "grid"));
+    assert_eq!(h.state().session.settings.gridmode, grid);
+    assert_eq!(running(&h).as_deref(), Some("line"));
+    h.get_by_label("Show All Status Items").click();
+    h.run_steps(3);
+    assert_eq!(running(&h).as_deref(), Some("line"));
+    h.state_mut().session.input(Input::Point(Vec2::new(10.0, 0.0))).unwrap();
+    let count = h.state().session.doc().unwrap().space(&Space::Model).unwrap().iter().filter(|e| matches!(e.kind, EntityKind::Line(_))).count();
+    assert_eq!(count, 1);
+}
+
+/// Resetting side palettes must not reset the independent status preferences.
+#[test]
+fn status_visibility_survives_palette_reset() {
+    let mut h = harness();
+    h.state_mut().run("ui.status.item", serde_json::json!({"item":"grid","visible":false})).unwrap();
+    h.state_mut().run("ui.resetpalettes", serde_json::json!({})).unwrap();
+    h.run_steps(4);
+    assert_eq!(h.state().ui.hidden_status_items, ["grid"]);
+    assert!(h.query_by_label("Grid (F7)").is_none());
+    h.state_mut().run("ui.status.reset", serde_json::json!({})).unwrap();
+    h.run_steps(4);
+    assert!(h.query_by_label("Grid (F7)").is_some());
+}
+/// The generic control route must reject an invalid list before changing any UI field.
+#[test]
+fn ui_set_rejects_invalid_status_items_atomically() {
+    use cadcraft_ui_egui::control::{ControlRequest, Outcome, handle};
+    let mut app = CadApp::new(Session::default(), Services::default());
+    let ctx = egui::Context::default();
+    let (request, _) = ControlRequest::new("ui.set", json!({"hiddenStatusItems":["grid"]}));
+    assert!(matches!(handle(&mut app, &ctx, &request), Outcome::Done(v) if v["ok"] == true));
+    let before = serde_json::to_value(&app.ui).unwrap();
+    for invalid in [json!(["grid", "grid"]), json!(["unknown"]), json!(vec!["grid"; 19]), json!("grid")] {
+        let (request, _) = ControlRequest::new("ui.set", json!({"hiddenStatusItems":invalid,"showToolbar":!app.ui.show_toolbar}));
+        assert!(matches!(handle(&mut app, &ctx, &request), Outcome::Done(v) if v["ok"] == false));
+        assert_eq!(serde_json::to_value(&app.ui).unwrap(), before);
+    }
+    let mut restored = CadApp::new(Session::default(), Services::default());
+    restored.load_prefs(&app.prefs_json());
+    assert_eq!(restored.ui.hidden_status_items, ["grid"]);
+}
diff --git a/docs/ui-parity.md b/docs/ui-parity.md
--- a/docs/ui-parity.md
+++ b/docs/ui-parity.md
@@ -1,6 +1,6 @@
 # UI parity
 
-> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-22 · **Change:** minor (distinct polyline midpoint grips) · **Target:** Autodesk AutoCAD 2027 for Mac (26.0)
+> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-26 · **Change:** minor (status item customization) · **Target:** Autodesk AutoCAD 2027 for Mac (26.0)
 
 How CADCraft's interaction compares with AutoCAD's: point entry, object snaps, tracking, dynamic
 input, grips, selection, the command line, chrome and navigation. A drafter's speed in AutoCAD
@@ -199,10 +199,30 @@ down-arrow options menu (DYNPROMPT), and DYNDIM.
   have menus too (#512). Still missing: in-place layout tab rename, Move or Copy, Select All
   Layouts.
 
+## Status item customization
+
+The status-bar customization menu shows or hides individual readouts and drafting controls.
+Visibility is an application preference: hiding Grid does not disable the drawing grid, change
+system variables, dirty the drawing, or cancel an active command. The customization button
+remains accessible when all items are hidden; Window > Show All Status Items also restores them.
+Unknown, duplicate or malformed saved item lists are ignored atomically.
+Both customization entry points keep the menu open when an item is toggled. Reset Palettes
+preserves status-item visibility; Show All Status Items is the dedicated recovery action.
+
+AutoCAD 2027 on Windows was observed black-box on 2026-10-26: toggling Coordinates in its
+customization menu updates the status bar while keeping the menu open. CADCraft's customization
+button follows that interaction. Native restart and browser reload preserve visibility; Windows
+right-click on the status readout also opens customization. Browser right-click was not confirmed.
+Actual release browser bundles were exercised with the default GPU backend and forced WebGL2;
+these runtime checks are separate from the WASM compilation gate.
+
 ## Revision history
 
 | Date | Change | Summary |
 |---|---|---|
+| 2026-10-26 | patch | Reject invalid status visibility through ui.set before changing any UI state; regression covers duplicates, unknown identifiers, oversized lists and malformed values (CC-037 review follow-up) |
+| 2026-10-26 | patch | Keep right-click status customization open for consecutive toggles and preserve hidden status items through Reset Palettes (CC-037 review corrections) |
+| 2026-10-26 | minor | Status item visibility, persistent application preferences, recovery command and command-isolation regressions (CC-037); no ribbon dependency |
 | 2026-10-22 | minor | Polyline segment midpoint grips use rectangles, distinct from square vertex grips, with matching hover and pick bounds (#1950) |
 | 2026-10-13 | minor | Filled-region highlight boundaries are traversed in deterministic coordinate order, fixing dash-phase jumps on CPU hover/selection redraws and GPU highlight rebuilds; CPU dash-position, pixel and GPU mesh regressions |
 | 2026-10-14 | minor | Selection cycling (#1143): the list and badge of SELECTIONCYCLING, Shift+Space through overlapping objects (#1145) |
diff --git a/xtask/src/parity.rs b/xtask/src/parity.rs
--- a/xtask/src/parity.rs
+++ b/xtask/src/parity.rs
@@ -136,7 +136,13 @@ mod tests {
         assert_eq!(day(20_736), "2026-10-10");
         assert_eq!(date(std::time::UNIX_EPOCH - std::time::Duration::from_secs(86_400)), "1970-01-01");
         // Past chrono's range keeps the proleptic Gregorian date, not the epoch (old `civil_from_days`).
-        assert_eq!(day(115_740_740), "318857-05-20");
+        // Checked on the day count: Windows' SystemTime ends in the year 30828, so building that
+        // SystemTime panics there.
+        assert_eq!(civil_from_days(115_740_740), (318_857, 5, 20));
+        // Also exercise the date formatter where the platform can represent this instant.
+        if let Some(large) = std::time::UNIX_EPOCH.checked_add(std::time::Duration::from_secs(115_740_740 * 86_400)) {
+            assert_eq!(date(large), "318857-05-20");
+        }
         // Windows' SystemTime can't hold u64::MAX / 2 seconds, so it is only checked where it exists.
         if let Some(far) = std::time::UNIX_EPOCH.checked_add(std::time::Duration::from_secs(u64::MAX / 2)) {
             assert_eq!(date(far), "292277026596-12-04");
diff --git a/xtask/src/stats.rs b/xtask/src/stats.rs
--- a/xtask/src/stats.rs
+++ b/xtask/src/stats.rs
@@ -134,7 +134,7 @@ pub fn run(_root: &Path, exact: bool) -> Result<(), String> {
 
 #[cfg(test)]
 mod tests {
-    use super::{Counts, count_tests, walk};
+    use super::{Counts, count_tests};
 
     #[test]
     fn counts_attributes_and_proptest_blocks() {
@@ -155,7 +155,7 @@ mod tests {
         // A directory symlink pointing back at `real` would be re-scanned if followed.
         symlink(&real, base.join("alias")).unwrap();
         let mut c = Counts::default();
-        walk(&base, &mut c).unwrap();
+        super::walk(&base, &mut c).unwrap();
         assert_eq!(c.files, 1, "the aliased directory was followed and counted twice");
         std::fs::remove_dir_all(&base).ok();
     }
