diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs
--- a/crates/ui-egui/src/canvas.rs
+++ b/crates/ui-egui/src/canvas.rs
@@ -556,6 +556,8 @@ pub enum ViewAction {
     CameraLevel,
     /// After Enhance page: leave the tool for this command (Crop pages, Organize pages).
     CameraNext(&'static str),
+    /// Run a registered command on the app (e.g. from a context menu or panel).
+    Command(&'static str),
 }
 
 impl DocView {
diff --git a/crates/ui-egui/src/canvas/organize.rs b/crates/ui-egui/src/canvas/organize.rs
--- a/crates/ui-egui/src/canvas/organize.rs
+++ b/crates/ui-egui/src/canvas/organize.rs
@@ -392,6 +392,13 @@ pub(super) fn organize_grid(view: &mut DocView, info: &DocInfo, editable: bool,
                         view.pending_action = Some(ViewAction::ReplacePages);
                         ui.close();
                     }
+                    if ui
+                        .add_enabled(editable && (view.selected.len() >= 2 || info.pages.len() >= 2), egui::Button::new(tl!("Reverse pages")))
+                        .clicked()
+                    {
+                        view.pending_action = Some(ViewAction::Command("page.reverse"));
+                        ui.close();
+                    }
                     ui.separator();
                     if ui.add_enabled(editable, egui::Button::new(tl!("Cut"))).clicked() {
                         view.pending_action = Some(ViewAction::CopyPages { cut: true });
diff --git a/crates/ui-egui/src/commands.rs b/crates/ui-egui/src/commands.rs
--- a/crates/ui-egui/src/commands.rs
+++ b/crates/ui-egui/src/commands.rs
@@ -78,7 +78,7 @@ pub(crate) fn command_tip(ctx: &egui::Context, template: &str, id: &str) -> Stri
 impl PdfCraftApp {
     /// Whether a registered command can run now. The engine judges the document (security,
     /// contents, undo history); view state it can't see is checked here.
-    pub(crate) fn command_enabled(&self, spec: &CommandSpec) -> bool {
+    pub fn command_enabled(&self, spec: &CommandSpec) -> bool {
         // Undo and Redo act on the Combine files list while its tab shows.
         if self.combine_showing() && matches!(spec.needs, commands::Needs::Undo | commands::Needs::Redo) {
             return self.combine_can_undo(spec.needs == commands::Needs::Undo);
@@ -93,6 +93,7 @@ impl PdfCraftApp {
             && match spec.id {
                 "view.previous_view" => self.active.and_then(|i| self.views.get(i)).is_some_and(|v| !v.back.is_empty()),
                 "view.next_view" => self.active.and_then(|i| self.views.get(i)).is_some_and(|v| !v.forward.is_empty()),
+                "page.reverse" => self.active.and_then(|i| self.views.get(i)).is_some_and(|v| v.page_count() >= 2),
                 _ => true,
             }
     }
@@ -654,8 +655,10 @@ impl PdfCraftApp {
             // Two or more selected pages reverse among themselves; otherwise the whole document.
             "page.reverse" => {
                 let all = active.and_then(|i| self.views.get(i)).map_or(0, |v| v.page_count());
-                let pages = if targets.len() >= 2 { targets } else { (0..all).collect() };
-                self.apply_edit(Edit::ReversePages { pages });
+                if all >= 2 {
+                    let pages = if targets.len() >= 2 { targets } else { (0..all).collect() };
+                    self.apply_edit(Edit::ReversePages { pages });
+                }
             }
             "ocr.enhance_camera" => {
                 // The corners start on the document's edges when they can be found, else
diff --git a/crates/ui-egui/src/editing.rs b/crates/ui-egui/src/editing.rs
--- a/crates/ui-egui/src/editing.rs
+++ b/crates/ui-egui/src/editing.rs
@@ -134,6 +134,9 @@ impl PdfCraftApp {
                     }
                     Edit::InsertBlankPage { at, .. } => view.select_pages(&[at.min(info.pages.len() - 1)]),
                     Edit::DeletePages { .. } => view.select_pages(&[]),
+                    Edit::ReversePages { ref pages } => {
+                        view.select_pages(pages);
+                    }
                     // A stroke drawn with the pen stays unselected, so the selection box and
                     // author popup don't sit over the next stroke (#429).
                     Edit::AddAnnotation(a)
@@ -278,6 +281,9 @@ impl PdfCraftApp {
                 self.leave_camera(i);
                 self.execute(command);
             }
+            Some(crate::canvas::ViewAction::Command(command)) => {
+                self.execute(command);
+            }
             None => {}
         }
         applied
diff --git a/crates/ui-egui/src/panels/organize_panel.rs b/crates/ui-egui/src/panels/organize_panel.rs
--- a/crates/ui-egui/src/panels/organize_panel.rs
+++ b/crates/ui-egui/src/panels/organize_panel.rs
@@ -137,6 +137,9 @@ pub(crate) fn panel(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) {
             if row(ui, t, "scissors", tl!("Split"), Availability::Ready, false).clicked() {
                 act = Some(Act::View(ViewAction::Split));
             }
+            if row(ui, t, "arrow-up-down", tl!("Reverse pages"), Availability::Ready, false).clicked() {
+                act = Some(Act::Command("page.reverse"));
+            }
         });
         if row(ui, t, "hash", tl!("Bates numbering"), Availability::Ready, false).clicked() {
             act = Some(Act::Command("edit.bates"));
diff --git a/crates/ui-egui/src/panels/pages.rs b/crates/ui-egui/src/panels/pages.rs
--- a/crates/ui-egui/src/panels/pages.rs
+++ b/crates/ui-egui/src/panels/pages.rs
@@ -197,6 +197,10 @@ pub(super) fn pages(ui: &mut egui::Ui, t: &Tokens, info: &DocInfo, view: &mut cr
                     view.pending_action = Some(crate::canvas::ViewAction::ReplacePages);
                     ui.close();
                 }
+                if ui.add_enabled(editable && (view.selected.len() >= 2 || count >= 2), egui::Button::new(tl!("Reverse pages"))).clicked() {
+                    view.pending_action = Some(crate::canvas::ViewAction::Command("page.reverse"));
+                    ui.close();
+                }
                 ui.separator();
                 if ui.add_enabled(editable, egui::Button::new(tl!("Cut"))).clicked() {
                     view.pending_action = Some(crate::canvas::ViewAction::CopyPages { cut: true });
diff --git a/crates/ui-egui/tests/it/editing.rs b/crates/ui-egui/tests/it/editing.rs
--- a/crates/ui-egui/tests/it/editing.rs
+++ b/crates/ui-egui/tests/it/editing.rs
@@ -369,6 +369,42 @@ fn reverse_pages_reverses_the_selection_or_else_the_whole_document() {
     assert_eq!(page_texts(h.state()), ["Page 2", "Page 3", "Page 4", "Page 1"]);
 }
 
+#[test]
+fn reverse_pages_command_disabled_on_single_page_document() {
+    let mut h = harness(1, |_| ());
+    let spec = pdfcraft_engine::commands::command("page.reverse").unwrap();
+    assert!(!h.state().command_enabled(spec));
+    assert!(!h.state_mut().execute("page.reverse"));
+}
+
+#[test]
+fn reverse_pages_from_organize_panel_reverses_and_preserves_selection() {
+    let mut h = organize(3);
+    h.get_by_label("Reverse pages").click();
+    h.run_steps(3);
+    assert_eq!(page_texts(h.state()), ["Page 3", "Page 2", "Page 1"]);
+    assert_eq!(h.state().views[0].selected.iter().copied().collect::<Vec<_>>(), [0, 1, 2]);
+}
+
+#[test]
+fn reverse_pages_from_thumbnail_context_menu() {
+    let mut h = organize(3);
+    h.get_by_label("Page 2").click_button(egui::PointerButton::Secondary);
+    h.run_steps(2);
+    h.get_all_by_label("Reverse pages").last().unwrap().click();
+    h.run_steps(3);
+    assert_eq!(page_texts(h.state()), ["Page 3", "Page 2", "Page 1"]);
+    assert_eq!(h.state().views[0].selected.iter().copied().collect::<Vec<_>>(), [0, 1, 2]);
+}
+
+#[test]
+fn reverse_pages_context_menu_disabled_on_single_page() {
+    let mut h = organize(1);
+    h.get_by_label("Page 1").click_button(egui::PointerButton::Secondary);
+    h.run_steps(2);
+    assert!(h.query_by(|n| n.label().as_deref() == Some("Reverse pages") && n.is_disabled()).is_some());
+}
+
 #[test]
 fn command_click_toggles_and_rotation_applies_to_selection() {
     let mut h = organize(3);
diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml
--- a/parity/acrobat-features.toml
+++ b/parity/acrobat-features.toml
@@ -2871,8 +2871,8 @@ milestone = "M4"
 status = "shipped"
 commands = ["page.reverse"]
 tools = ["page_reverse"]
-evidence = ["crates/organize/src/tests.rs::reverse_pages_reorders", "crates/organize/src/tests.rs::cannot_reverse_missing_or_fewer_than_two_pages", "crates/automation/tests/it/automation.rs::reversing_pages_through_tools", "crates/ui-egui/tests/it/editing.rs::reverse_pages_reverses_the_selection_or_else_the_whole_document"]
-notes = "Organize Pages ▸ More ▸ Reverse pages, or the command palette: two or more selected pages swap among their own positions, otherwise the whole document reverses. One undo step. Not yet: an entry in the page thumbnails' right-click menu"
+evidence = ["crates/organize/src/tests.rs::reverse_pages_reorders", "crates/organize/src/tests.rs::cannot_reverse_missing_or_fewer_than_two_pages", "crates/automation/tests/it/automation.rs::reversing_pages_through_tools", "crates/ui-egui/tests/it/editing.rs::reverse_pages_reverses_the_selection_or_else_the_whole_document", "crates/ui-egui/tests/it/editing.rs::reverse_pages_from_thumbnail_context_menu"]
+notes = "Organize pages panel, thumbnails' right-click context menu, Edit ▸ Pages ▸ Reverse pages, or the command palette: two or more selected pages swap among their own positions, otherwise the whole document reverses. Disabled on single-page documents. One undo step."
 
 [[feature]]
 id = "organize.cut-copy-paste-pages"
