diff --git a/ROADMAP.md b/ROADMAP.md
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -137,6 +137,7 @@ app's JSON control channel (`deckcraft --control PORT`).
 
 | Date | What landed |
 |---|---|
+| 2026-10-27 | Set Up Slide Show ▸ Keep mouse cursor visible: a full-screen show no longer hides a still pointer, so the choices of a branching deck stay visible and clickable; the setting is kept with the user's preferences (`show.keepCursor`), off by default (#1445) |
 | 2026-10-25 | Windows installer: the Start menu shortcut takes the icon embedded in `deckcraft.exe` instead of an MSI `<Icon>`, so a taskbar pin keeps its icon after an update (#1114); a pin that already lost it has to be unpinned and pinned again once |
 | 2026-10-24 | AutoFormat as you type: a paragraph that starts with `*`, `-`, `--`, `>`, `<>`, `1.`, `1)`, `I.`, `i.`, `A.`, `a.` or `a)` and a space or tab becomes a bulleted or numbered list in that style; Backspace right after puts the typed text back, and Tools ▸ AutoCorrect and `text.autocorrect {lists}` turn it off |
 | 2026-10-24 | Tables: while the caret is in a cell, dragging into another cell selects that range of cells (shaded, merged cells taken in whole), and Shift+arrow grows or shrinks it; formatting applies to the selected cells only, and Delete clears their text and keeps the table |
diff --git a/crates/ui-egui/src/app/commands.rs b/crates/ui-egui/src/app/commands.rs
--- a/crates/ui-egui/src/app/commands.rs
+++ b/crates/ui-egui/src/app/commands.rs
@@ -163,6 +163,12 @@ impl SlideApp {
                 }
             }
             "show.presenter" => self.ui.presenter_view = self.flag(p, self.ui.presenter_view),
+            "show.keepCursor" => {
+                self.ui.show_keep_cursor = self.flag(p, self.ui.show_keep_cursor);
+                if let Some(s) = self.show.as_mut() {
+                    s.keep_cursor = self.ui.show_keep_cursor;
+                }
+            }
             "show.end" => {
                 self.show = None;
                 self.media.stop_owned(media::Owner::Show);
diff --git a/crates/ui-egui/src/app/playback.rs b/crates/ui-egui/src/app/playback.rs
--- a/crates/ui-egui/src/app/playback.rs
+++ b/crates/ui-egui/src/app/playback.rs
@@ -36,6 +36,7 @@ impl SlideApp {
             self.show_instance = self.show_instance.wrapping_add(1).max(1);
             let mut show = show::Show::new(&d.doc, from, reading, self.ui.presenter_view && !reading);
             show.instance = self.show_instance;
+            show.keep_cursor = self.ui.show_keep_cursor;
             self.show = Some(show);
         }
     }
diff --git a/crates/ui-egui/src/dialogs/body.rs b/crates/ui-egui/src/dialogs/body.rs
--- a/crates/ui-egui/src/dialogs/body.rs
+++ b/crates/ui-egui/src/dialogs/body.rs
@@ -206,6 +206,7 @@ pub(super) fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool {
             let nn = check(ui, d, "Show without narration", "nn", sh.without_narration);
             let na = check(ui, d, "Show without animation", "na", sh.without_animation);
             let ut = check(ui, d, "Use timings, if present", "ut", sh.use_timings);
+            let kc = check(ui, d, "Keep mouse cursor visible", "kc", app.ui.show_keep_cursor);
             let names: Vec<String> = app.session.active().map(|s| s.doc.custom_shows.iter().map(|c| c.name.clone()).collect()).unwrap_or_default();
             let chosen = d.fields.entry("custom".into()).or_insert_with(|| sh.custom_show.clone().unwrap_or_default()).clone();
             let field = ui.label("Slides");
@@ -226,6 +227,7 @@ pub(super) fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool {
                 let ty = d.get("type", "speaker");
                 let custom = d.fields.get("custom").cloned().unwrap_or_default();
                 run(app, "show.setup", json!({"type": ty, "loop": lp, "noNarration": nn, "noAnimation": na, "useTimings": ut, "custom": custom}));
+                run(app, "show.keepCursor", json!({"on": kc}));
             }
             ok || cancel
         }
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
@@ -110,6 +110,7 @@ pub const UI_COMMANDS: &[(&str, &str, Option<&str>, &str)] = &[
     ("view.newWindow", "New Window", None, "{on?: bool, slide?: index, delta?: int}"),
     ("show.start", "Slide Show", Some("F5"), "{from?: index, custom?: name}"),
     ("show.presenter", "Presenter View", None, "{on?: bool}"),
+    ("show.keepCursor", "Keep Mouse Cursor Visible", None, "{on?: bool}"),
     ("show.end", "End Show", None, "{}"),
     ("animation.preview", "Preview Animations", None, "{on?: bool, from?: effect index}"),
     ("app.home", "Home", None, "{on?}"),
diff --git a/crates/ui-egui/src/show.rs b/crates/ui-egui/src/show.rs
--- a/crates/ui-egui/src/show.rs
+++ b/crates/ui-egui/src/show.rs
@@ -44,6 +44,8 @@ pub struct Show {
     /// Play every step automatically (animation preview).
     pub autoplay: bool,
     pub rehearse: bool,
+    /// Set Up Slide Show ▸ Keep mouse cursor visible: a still pointer is not hidden (#1445).
+    pub keep_cursor: bool,
     timeline: Option<(usize, Timeline)>,
     step_start: f64,
     slide_start: f64,
@@ -206,6 +208,7 @@ impl Show {
             preview_only: false,
             autoplay: false,
             rehearse: false,
+            keep_cursor: false,
             timeline: None,
             step_start: 0.0,
             slide_start: 0.0,
@@ -362,6 +365,12 @@ impl Show {
         now - self.last_move < 2.5
     }
 
+    /// Whether a still pointer is hidden: after 2.5 s in a full-screen show, unless Keep mouse
+    /// cursor visible is on. Reading View always keeps it.
+    fn hides_idle_cursor(&self, now: f64) -> bool {
+        !self.pointer_awake(now) && !self.reading && !self.keep_cursor
+    }
+
     /// Pen and laser are different pointers: turning one on puts the other away.
     fn set_pen(&mut self, on: bool) {
         self.pen = on;
diff --git a/crates/ui-egui/src/show/tests.rs b/crates/ui-egui/src/show/tests.rs
--- a/crates/ui-egui/src/show/tests.rs
+++ b/crates/ui-egui/src/show/tests.rs
@@ -52,6 +52,79 @@ fn a_still_cursor_hides_over_a_clickable_shape() {
     assert_eq!(harness.output().platform_output.cursor_icon, egui::CursorIcon::None, "still for 3 s: hidden");
 }
 
+/// #1445: Keep mouse cursor visible leaves a still pointer showing over a link, so a branching
+/// deck's choices stay targetable; the setting outlives the show and the link still follows.
+#[test]
+fn keep_cursor_visible_leaves_a_still_cursor_over_a_link() {
+    let mut session = deckcraft_engine::Session::with_new();
+    let size = session.active().unwrap().doc.slide_size;
+    session.execute("slide.new", &json!({})).unwrap();
+    session.execute("slide.go", &json!({"index": 0})).unwrap();
+    let r = session.execute("shape.insert", &json!({"preset": "rect", "rect": [0.0, 0.0, size.width, size.height]})).unwrap();
+    session.execute("insert.hyperlink", &json!({"slide": 1, "ids": [r["id"]]})).unwrap();
+    let mut app = SlideApp::new(session, crate::Services::default());
+    app.ui.presenter_view = false;
+    app.run("show.keepCursor", json!({"on": true})).unwrap();
+    let mut harness = egui_kittest::Harness::builder().with_size(vec2(1000.0, 700.0)).with_step_dt(0.25).build_ui_state(
+        |ui, app: &mut SlideApp| {
+            app.logic(ui.ctx());
+            app.ui(ui);
+        },
+        app,
+    );
+    harness.run_steps(3);
+    harness.state_mut().start_show(0, false);
+    harness.run_steps(2);
+    harness.hover_at(pos2(500.0, 350.0));
+    harness.run_steps(14);
+    assert_eq!(harness.output().platform_output.cursor_icon, egui::CursorIcon::PointingHand, "still for 3 s: kept");
+    click_at(&mut harness, pos2(500.0, 350.0));
+    harness.run_steps(2);
+    assert_eq!(harness.state().show.as_ref().map(|s| s.state.slide), Some(1), "the link still follows");
+    assert!(harness.state().ui.show_keep_cursor, "the setting is kept for the next show");
+}
+
+/// #1445: Set Up Slide Show turns Keep mouse cursor visible on and off.
+#[test]
+fn set_up_slide_show_keeps_the_cursor_visible() {
+    use egui_kittest::kittest::Queryable;
+
+    let app = SlideApp::new(deckcraft_engine::Session::with_new(), crate::Services::default());
+    let mut harness = egui_kittest::Harness::builder().with_size(vec2(1200.0, 800.0)).build_ui_state(
+        |ui, app: &mut SlideApp| {
+            app.logic(ui.ctx());
+            app.ui(ui);
+        },
+        app,
+    );
+    for on in [true, false] {
+        harness.state_mut().run("app.dialog", json!({"id": "setupShow"})).unwrap();
+        harness.run_steps(6);
+        harness.get_by_label("Keep mouse cursor visible").click();
+        harness.run_steps(3);
+        harness.get_by_label("OK").click();
+        harness.run_steps(2);
+        assert!(harness.state().dialog.is_none());
+        assert_eq!(harness.state().ui.show_keep_cursor, on);
+    }
+}
+
+/// #1445: the idle hide follows the pointer's last move, Reading View and Keep mouse cursor visible.
+#[test]
+fn the_idle_cursor_hides_only_when_asked() {
+    let session = deckcraft_engine::Session::with_new();
+    let doc = session.active().unwrap().doc.clone();
+    let mut show = Show::new(&doc, 0, false, false);
+    show.last_move = 10.0;
+    assert!(!show.hides_idle_cursor(12.0), "moved 2 s ago");
+    assert!(show.hides_idle_cursor(13.0), "still for 3 s");
+    show.keep_cursor = true;
+    assert!(!show.hides_idle_cursor(13.0), "kept visible");
+    show.keep_cursor = false;
+    show.reading = true;
+    assert!(!show.hides_idle_cursor(13.0), "Reading View never hides it");
+}
+
 /// #1130: the Presenter View's All slides button opens the grid in that window, not on the audience screen.
 #[test]
 fn presenter_all_slides_does_not_cover_the_audience_screen() {
diff --git a/crates/ui-egui/src/show/ui.rs b/crates/ui-egui/src/show/ui.rs
--- a/crates/ui-egui/src/show/ui.rs
+++ b/crates/ui-egui/src/show/ui.rs
@@ -469,7 +469,7 @@ pub fn ui(app: &mut SlideApp, ui: &mut Ui) {
         ctx.set_cursor_icon(egui::CursorIcon::None);
     } else if show.zoom_arm || show.grid {
         ctx.set_cursor_icon(egui::CursorIcon::Crosshair);
-    } else if !show.pointer_awake(now) && !show.reading {
+    } else if show.hides_idle_cursor(now) {
         // Idle first: a still pointer hides also over a clickable shape, such as a playing clip.
         ctx.set_cursor_icon(egui::CursorIcon::None);
         ctx.request_repaint_after(std::time::Duration::from_millis(500));
diff --git a/crates/ui-egui/src/state.rs b/crates/ui-egui/src/state.rs
--- a/crates/ui-egui/src/state.rs
+++ b/crates/ui-egui/src/state.rs
@@ -76,6 +76,9 @@ pub struct UiState {
     pub sorter_zoom: f32,
     pub recent: Vec<String>,
     pub presenter_view: bool,
+    /// Set Up Slide Show ▸ Keep mouse cursor visible: full-screen shows never hide a still pointer,
+    /// for decks with clickable choices (#1445).
+    pub show_keep_cursor: bool,
     pub ui_scale: f32,
     /// Format Shape pane: tab (`fill`, `effects`, `size`, `picture`, `text`).
     pub format_tab: String,
@@ -115,6 +118,7 @@ impl Default for UiState {
             sorter_zoom: 1.0,
             recent: vec![],
             presenter_view: true,
+            show_keep_cursor: false,
             ui_scale: 1.0,
             format_tab: "fill".into(),
             smartart_row: 0,
diff --git a/docs/slideshow-parity.md b/docs/slideshow-parity.md
--- a/docs/slideshow-parity.md
+++ b/docs/slideshow-parity.md
@@ -1,6 +1,6 @@
 # Slide show and presenter view: parity with PowerPoint
 
-> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-24 · **Change:** minor (Ctrl+wheel zooms the show around the pointer, #1286; previous: major, community PR wave 2026-10-14: interactive decks, laser pointer, See All Slides and zoom, go-to-slide number, custom show playback, presenter timer, clock, notes size and keyboard, Show Media Controls, swipe; breadth 68%; duplicated rows and headers folded; previous: major, created) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
+> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-27 · **Change:** minor (Set Up Slide Show ▸ Keep mouse cursor visible, #1445; previous: minor, Ctrl+wheel zooms the show around the pointer, #1286; previous: major, community PR wave 2026-10-14: interactive decks, laser pointer, See All Slides and zoom, go-to-slide number, custom show playback, presenter timer, clock, notes size and keyboard, Show Media Controls, swipe; breadth 68%; duplicated rows and headers folded; previous: major, created) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
 
 Presenting is the job PowerPoint is hired for. This doc covers the show window, presenter view,
 rehearsal and recording. Transition and animation playback are in
@@ -34,7 +34,7 @@ ready** (estimated), **10–16 h** to parity.
 | Laser pointer | yes | yes in the show | Cmd/Ctrl+L and the on-screen button draw the show's laser colour and leave no ink. The presenter window does not move that dot |
 | Subtitles and live captions | yes (cloud speech) | no | AI dimension |
 | Custom shows | yes | yes: Show plays that list in order and does not change Set Up; Set Up Slide Show can keep one for Play from Start | Hidden slides in the list are skipped |
-| Set Up Show: loop until Esc, kiosk (browsed at a kiosk), show without animation/narration, pen colour, slides range | yes | yes, most options | |
+| Set Up Show: loop until Esc, kiosk (browsed at a kiosk), show without animation/narration, pen colour, slides range | yes | yes, most options | Keep mouse cursor visible (DeckCraft's own, #1445) stops the show hiding a still pointer after 2.5 s, for decks with clickable choices; it is a user preference (`ui.json`, `show.keepCursor`), since PPTX has no place for it |
 | Use rehearsed timings | yes | yes | |
 
 ## Presenter view
@@ -79,6 +79,7 @@ Reading View in a window with navigation: present (checklist row done).
 
 | Date | Change | Summary |
 |---|---|---|
+| 2026-10-27 | minor | Set Up Slide Show ▸ Keep mouse cursor visible: full-screen shows keep a still pointer, so clickable choices stay targetable; Reading View unchanged (#1445) |
 | 2026-10-22 | minor | See All Slides from presenter view opens in presenter view, not on the audience screen (#1130) |
 | 2026-10-14 | trivial | Community PR wave folded: one media playback row, the presenter pen/laser row matches the laser that exists, estimates keep only the open work (~9–16 h); checklist breadth 68% |
 | 2026-10-13 | minor | Click handling for interactive decks: triggers, per-slide state kept across visits, visible-shape hit testing with hand cursor, advance on click |
