diff --git a/crates/ui-egui/src/edit_window.rs b/crates/ui-egui/src/edit_window.rs
--- a/crates/ui-egui/src/edit_window.rs
+++ b/crates/ui-egui/src/edit_window.rs
@@ -2301,15 +2301,14 @@ fn drive_drag(app: &mut SoundApp, ctx: &egui::Context) {
     let (s, tl) = (app.engine.session_arc(), rect(app.edit_layout.timeline));
     let p = ctx.pointer_latest_pos();
     if !ctx.input(|i| i.pointer.any_down()) {
-        finish_drag(app, &s, tl, p);
+        finish_drag(app, &s, tl, p, ctx);
         return;
     }
     let Some(p) = p else { return };
     let at = sample_at(&s, tl, p.x).max(0);
     let inside = pos2(p.x.max(tl.min.x).min(tl.max.x), p.y.max(tl.min.y).min(tl.max.y));
     let rows = &app.edit_layout.rows;
-    let gap = |r: &[f32; 4]| (r[1] - inside.y).max(inside.y - r[3]).max(0.0);
-    let to_track = rows.iter().min_by(|a, b| gap(&a.1).total_cmp(&gap(&b.1))).map(|(i, _)| TrackId(*i));
+    let to_track = drag_track(rows, tl, p);
     let mut invalid_fade = false;
     match &mut app.gesture {
         Some(Gesture::Select { track, tracks, .. }) => {
@@ -2416,9 +2415,24 @@ fn drive_drag(app: &mut SoundApp, ctx: &egui::Context) {
     }
 }
 
-fn finish_drag(app: &mut SoundApp, s: &Session, tl: Rect, p: Option<Pos2>) {
+fn drag_track(rows: &[(u64, [f32; 4])], tl: Rect, p: Pos2) -> Option<TrackId> {
+    let y = p.y.max(tl.min.y).min(tl.max.y);
+    let gap = |r: &[f32; 4]| (r[1] - y).max(y - r[3]).max(0.0);
+    rows.iter().min_by(|a, b| gap(&a.1).total_cmp(&gap(&b.1))).map(|(id, _)| TrackId(*id))
+}
+
+fn finish_drag(app: &mut SoundApp, s: &Session, tl: Rect, p: Option<Pos2>, ctx: &egui::Context) {
     match app.gesture.take() {
-        Some(Gesture::MoveClips { clips, delta, from_track, to_track, .. }) => drop_clips(app, clips, delta, from_track, to_track),
+        Some(Gesture::MoveClips { clips, mut delta, from_track, mut to_track, grab_at }) => {
+            // A release can carry a new pointer position without an intervening held
+            // frame. Commit that position rather than the previous frame's preview.
+            if let Some(p) = p {
+                to_track = drag_track(&app.edit_layout.rows, tl, p).unwrap_or(to_track);
+                let plan = drag_plan(ctx, s, app.engine.revision, &clips, (from_track, to_track), grab_at);
+                delta = move_delta(&plan, s, from_track, sample_at(s, tl, p.x).max(0) - grab_at, ctx.input(|i| i.modifiers.command));
+            }
+            drop_clips(app, clips, delta, from_track, to_track);
+        }
         Some(Gesture::Fade { clip, fade_in, to, .. }) => {
             let to = p.map_or(to, |p| sample_at(s, tl, p.x).max(0));
             if let Some(fade) = s.find_clip(clip).and_then(|(_, c)| fade_drag_preview(c, fade_in, to)) {
diff --git a/crates/ui-egui/tests/edit_modes.rs b/crates/ui-egui/tests/edit_modes.rs
--- a/crates/ui-egui/tests/edit_modes.rs
+++ b/crates/ui-egui/tests/edit_modes.rs
@@ -8,6 +8,37 @@ use soundcraft_ui_egui::{Services, SoundApp, edit_window};
 
 const SEC: i64 = 48_000;
 
+#[test]
+fn sliced_stereo_clip_uses_the_track_and_position_where_the_pointer_is_released() {
+    for (mode, tool) in [("slip", "grabber"), ("slip", "smart"), ("grid", "grabber"), ("grid", "smart")] {
+        let (mut app, ctx, tracks, _) = tracks(mode, tool, &[&[(0, 4 * SEC)], &[]]);
+        for t in &tracks {
+            app.engine.session_mut().track_mut(*t).unwrap().format = soundcraft_model::ChannelFormat::Stereo;
+        }
+        app.engine.session_mut().sources[0].channels = 2;
+        app.engine.execute("edit.select", &json!({"tracks": [tracks[0].0], "start": 2 * SEC, "end": 2 * SEC})).unwrap();
+        app.engine.execute("edit.separate", &json!({})).unwrap();
+        frame(&ctx, &mut app, vec![]);
+        let clip = app.engine.session().track(tracks[0]).unwrap().clips()[1].clone();
+        let before = app.engine.session().clone();
+        let from = point(&app, tracks[0], 3 * SEC);
+        let held = from + vec2(20.0, 0.0);
+        let release = point(&app, tracks[1], 3 * SEC + SEC / 2);
+        frame(&ctx, &mut app, vec![Event::PointerMoved(from), button(from, true)]);
+        frame(&ctx, &mut app, vec![Event::PointerMoved(held)]);
+        frame(&ctx, &mut app, vec![]);
+        // A release may arrive at a new position with no preceding held-pointer frame there.
+        frame(&ctx, &mut app, vec![Event::PointerMoved(release), button(release, false)]);
+        let (track, moved) = app.engine.session().find_clip(clip.id).unwrap();
+        assert_eq!(track, tracks[1], "{tool}: clip stayed on the previous hover track");
+        assert_eq!(moved.start, clip.start + SEC / 2, "{tool}: final pointer position was ignored");
+        assert_eq!(moved.length, clip.length);
+        assert_eq!(moved.content, clip.content);
+        assert!(app.engine.undo());
+        assert_eq!(app.engine.session(), &before);
+    }
+}
+
 fn frame(ctx: &egui::Context, app: &mut SoundApp, events: Vec<Event>) {
     let raw = RawInput { screen_rect: Some(Rect::from_min_size(Pos2::ZERO, vec2(1600.0, 1000.0))), events, ..Default::default() };
     ctx.run_ui(raw, |ui| {
