diff --git a/crates/ui-egui/src/app.rs b/crates/ui-egui/src/app.rs
--- a/crates/ui-egui/src/app.rs
+++ b/crates/ui-egui/src/app.rs
@@ -118,6 +118,8 @@ pub struct LauncherUi {
     pub(crate) detail_shot: usize,
     /// The screenshot is enlarged over the whole window.
     pub(crate) detail_zoom: bool,
+    /// The drawer just opened on an app: its page starts at the top, wherever the last one was.
+    pub(crate) detail_scroll_top: bool,
     /// The details pictures the backend has sent (or been asked for), by app and picture key.
     pub(crate) pictures: std::collections::HashMap<(String, String), crate::details::Picture>,
     started: bool,
@@ -187,6 +189,7 @@ impl LauncherUi {
             detail_shown: None,
             detail_shot: 0,
             detail_zoom: false,
+            detail_scroll_top: false,
             pictures: std::collections::HashMap::new(),
             started: false,
             applied_theme: None,
diff --git a/crates/ui-egui/src/details.rs b/crates/ui-egui/src/details.rs
--- a/crates/ui-egui/src/details.rs
+++ b/crates/ui-egui/src/details.rs
@@ -89,6 +89,7 @@ impl LauncherUi {
             self.detail_shown = Some(id.clone());
             self.detail_shot = 0;
             self.detail_zoom = false;
+            self.detail_scroll_top = true;
             let app = id.clone();
             self.request_pictures(&app);
         }
@@ -132,7 +133,13 @@ impl LauncherUi {
             // A bar that stays on screen says there is more below the fold. egui's default one is
             // floating and invisible until the pointer is over it, so the drawer uses the solid style.
             ui.spacing_mut().scroll = egui::style::ScrollStyle::solid();
-            egui::ScrollArea::vertical().auto_shrink([false, false]).show(ui, |ui| {
+            // One scroll area serves every app's page: a page just opened starts at the top
+            // rather than where the last one was scrolled to (#428).
+            let mut scroll = egui::ScrollArea::vertical().auto_shrink([false, false]);
+            if std::mem::take(&mut self.detail_scroll_top) {
+                scroll = scroll.vertical_scroll_offset(0.0);
+            }
+            scroll.show(ui, |ui| {
                 ui.set_width(ui.available_width());
                 ui.spacing_mut().item_spacing.y = 8.0;
                 self.details_hero(ui, &entry, details, &t);
diff --git a/crates/ui-egui/tests/ui.rs b/crates/ui-egui/tests/ui.rs
--- a/crates/ui-egui/tests/ui.rs
+++ b/crates/ui-egui/tests/ui.rs
@@ -1051,6 +1051,39 @@ fn clicking_a_card_opens_its_details_drawer() {
     assert!(h.query_by_label_contains("The image editor you already know").is_none());
 }
 
+/// A page opened after another was scrolled starts at the top (#428).
+#[test]
+fn an_apps_page_opens_at_the_top_however_far_the_last_one_was_scrolled() {
+    let (mut h, _sent) = harness(ViewMode::Grid, egui::Theme::Dark, true);
+    h.run_steps(8);
+    h.get_by_label("PhotoCraft details").click();
+    h.run_steps(10);
+    let top = h.get_by_label("Website ↗").rect().top();
+    // Scroll the page down: the wheel over the drawer, which sits at the right.
+    h.hover_at(egui::pos2(1180.0 - 200.0, 500.0));
+    h.run_steps(2);
+    for _ in 0..3 {
+        h.event(egui::Event::MouseWheel {
+            unit: egui::MouseWheelUnit::Line,
+            delta: egui::vec2(0.0, -20.0),
+            phase: egui::TouchPhase::Move,
+            modifiers: egui::Modifiers::NONE,
+        });
+        h.run_steps(5);
+    }
+    h.run_steps(30);
+    let scrolled = h.get_by_label("Website ↗").rect().top();
+    assert!(scrolled < top - 50.0, "the page didn't scroll: {top} → {scrolled}");
+    // Close it, open another app's page: that one starts at the top.
+    h.key_press(egui::Key::Escape);
+    h.run_steps(12);
+    assert!(h.query_by_label("Website ↗").is_none());
+    h.get_by_label("VectorCraft details").click();
+    h.run_steps(12);
+    let next = h.get_by_label("Website ↗").rect().top();
+    assert!((next - top).abs() < 1.0, "opened scrolled: top {top}, now {next}");
+}
+
 #[test]
 fn details_drawer_in_the_light_theme() {
     let (mut h, _sent) = harness(ViewMode::Grid, egui::Theme::Light, true);
