diff --git a/crates/develop/src/lib.rs b/crates/develop/src/lib.rs
--- a/crates/develop/src/lib.rs
+++ b/crates/develop/src/lib.rs
@@ -363,4 +363,22 @@ mod tests {
         s.reset_section(Section::Detail);
         assert_eq!(s.enhance.denoise_on, None);
     }
+
+    /// Issue #3056 (review): a refitted crop keeps an explicit aspect lock, also on the whole photo,
+    /// and an "Original" lock follows the new photo's shape; the lock stays true to the crop.
+    #[test]
+    fn crop_refit_honours_the_aspect_lock() {
+        let (land, tall) = ((6000.0, 4000.0), (4000.0, 6000.0));
+        let three_two = Crop { aspect: Some((300, 200)), ..Crop::default() };
+        let r = three_two.refit(land, tall);
+        assert_eq!(r.aspect, Some((300, 200)));
+        assert!((r.geometry.rect_px(tall.0, tall.1).aspect() - 1.5).abs() < 1e-9, "{:?}", r.geometry);
+        let original = Crop { aspect: Some(Crop::original_aspect(land.0, land.1)), flip_h: true, ..Crop::default() };
+        let r = original.refit(land, tall);
+        assert_eq!(r.aspect, Some(Crop::original_aspect(tall.0, tall.1)));
+        assert_eq!(r.geometry, lightcraft_geom::CropGeometry::default());
+        assert!(r.flip_h);
+        // unlocked, the whole photo stays the whole photo
+        assert_eq!(Crop::default().refit(land, tall), Crop::default());
+    }
 }
diff --git a/crates/develop/src/settings.rs b/crates/develop/src/settings.rs
--- a/crates/develop/src/settings.rs
+++ b/crates/develop/src/settings.rs
@@ -3,7 +3,7 @@
 //! exception is `process`: missing (or unreadable), it is V1, the rendering those older files were
 //! made with.
 
-use lightcraft_geom::{CropGeometry, Homography, Orientation, Point};
+use lightcraft_geom::{CropGeometry, Homography, Orientation, Point, RefitShape};
 use serde::{Deserialize, Serialize};
 
 pub const SCHEMA_VERSION: u32 = 1;
@@ -814,12 +814,36 @@ impl Geometry {
 #[serde(default)]
 pub struct Crop {
     pub geometry: CropGeometry,
-    /// Locked aspect (w, h); None = free / original.
+    /// Locked aspect (w × 100, h × 100); None = free. "Original" is the photo's own size as
+    /// oriented ([`Crop::original_aspect`]).
     pub aspect: Option<(u32, u32)>,
     pub flip_h: bool,
     pub flip_v: bool,
 }
 
+impl Crop {
+    /// The "Original" aspect lock of a `w × h` photo (as oriented): its own size, in hundredths.
+    pub fn original_aspect(w: f64, h: f64) -> (u32, u32) {
+        ((w * 100.0) as u32, (h * 100.0) as u32)
+    }
+
+    /// This crop, made on a photo `from` (w, h, as oriented) in size, for a photo of size `to`
+    /// (pasting or syncing it, [`CropGeometry::refit`]): a locked aspect ratio is kept, also by a
+    /// crop of the whole photo, and an "Original" lock takes the new photo's shape (and becomes its
+    /// Original lock); unlocked, the whole photo stays the whole photo and any other crop keeps its
+    /// aspect ratio.
+    pub fn refit(&self, from: (f64, f64), to: (f64, f64)) -> Crop {
+        let valid = |(w, h): (f64, f64)| w.is_finite() && h.is_finite() && w > 0.0 && h > 0.0;
+        let shape = match self.aspect {
+            None => RefitShape::Free,
+            Some(a) if valid(from) && a == Self::original_aspect(from.0, from.1) => RefitShape::Photo,
+            Some(_) => RefitShape::Locked,
+        };
+        let aspect = if shape == RefitShape::Photo && valid(to) { Some(Self::original_aspect(to.0, to.1)) } else { self.aspect };
+        Crop { geometry: self.geometry.refit(from, to, shape), aspect, ..*self }
+    }
+}
+
 // ---------------------------------------------------------------------------------------------
 // Masks and local adjustments
 
diff --git a/crates/engine/src/cmd/develop.rs b/crates/engine/src/cmd/develop.rs
--- a/crates/engine/src/cmd/develop.rs
+++ b/crates/engine/src/cmd/develop.rs
@@ -6,7 +6,7 @@ use lightcraft_geom::{CropGeometry, CropHandle, MIN_CROP_FRACTION, Point, Rect,
 use serde_json::{Value, json};
 
 use super::{CommandSpec, always, bad, bool_or, cmd, f64_or, f64_req, has_active, has_clipboard, has_selection, index_req, ok, str_param};
-use crate::{Result, Session, media::SourceLevel};
+use crate::{Result, Session, SettingsClipboard, media::SourceLevel};
 
 fn active(s: &Session, c: &str) -> Result<PhotoId> {
     s.active().ok_or_else(|| bad(c, "no active photo"))
@@ -33,6 +33,20 @@ fn groups_param(p: &Value, c: &str) -> Result<Option<Vec<SettingsGroup>>> {
     }
 }
 
+/// The settings `partial` (groups taken from a photo `from` in size, as oriented) pasted onto photo
+/// `id`'s settings `to`. A pasted crop keeps its shape on a photo of another shape, as in Lightroom
+/// ([`lightcraft_develop::Crop::refit`]); without both sizes it is pasted as it is. The size of `id`
+/// is taken with the pasted orientation (the Crop group carries it).
+fn paste_onto(s: &Session, partial: &Value, from: Option<(f64, f64)>, id: PhotoId, to: &DevelopSettings) -> DevelopSettings {
+    let mut d = lightcraft_develop::apply_partial(to, partial, 1.0);
+    if partial.get("crop").is_some()
+        && let (Some(from), Some(dims)) = (from, s.oriented_dims(id, d.orientation))
+    {
+        d.crop = d.crop.refit(from, dims);
+    }
+    d
+}
+
 fn crop_dims(s: &Session, id: PhotoId) -> (f64, f64) {
     let p = s.catalog.photo(id);
     let (w, h) = p.map(|p| (p.width.max(1) as f64, p.height.max(1) as f64)).unwrap_or((3.0, 2.0));
@@ -683,7 +697,7 @@ pub fn specs() -> Vec<CommandSpec> {
                 let aspect = match p.get("aspect") {
                     Some(Value::String(a)) if a == "toggle" => None,
                     Some(Value::String(a)) if a == "free" => None,
-                    Some(Value::String(a)) if a == "original" => Some(((w * 100.0) as u32, (h * 100.0) as u32)),
+                    Some(Value::String(a)) if a == "original" => Some(lightcraft_develop::Crop::original_aspect(w, h)),
                     Some(Value::String(a)) => {
                         let (x, y) = a.split_once('x').ok_or_else(|| bad("crop.aspect", "use WxH"))?;
                         let (x, y): (f64, f64) =
@@ -826,8 +840,10 @@ pub fn specs() -> Vec<CommandSpec> {
                 if let Some(g) = groups_param(p, c)? {
                     s.copy_groups = g;
                 }
-                let d = s.develop_of(id).unwrap_or_default();
-                s.clipboard = Some(lightcraft_develop::extract_groups(&d, &s.copy_groups));
+                // the whole settings: Paste Selected can paste a group the copy left out (#3056)
+                let settings = s.develop_of(id).unwrap_or_default();
+                let dims = s.oriented_dims(id, settings.orientation);
+                s.clipboard = Some(SettingsClipboard { settings, dims });
                 Ok(json!({"groups": s.copy_groups}))
             }
         ),
@@ -843,12 +859,14 @@ pub fn specs() -> Vec<CommandSpec> {
                 let prev =
                     s.previous_active.filter(|id| s.catalog.photo(*id).is_some_and(|ph| !ph.deleted)).ok_or_else(|| bad(c, "no previous photo"))?;
                 let groups = groups_param(p, c)?.unwrap_or_else(|| s.copy_groups.clone());
-                let partial = lightcraft_develop::extract_groups(&s.develop_of(prev).unwrap_or_default(), &groups);
+                let from = s.develop_of(prev).unwrap_or_default();
+                let partial = lightcraft_develop::extract_groups(&from, &groups);
+                let dims = s.oriented_dims(prev, from.orientation);
                 let ids: Vec<PhotoId> = s.targets(p)?.into_iter().filter(|id| *id != prev).collect();
                 let ops = ids
                     .iter()
                     .filter_map(|id| s.develop_of(*id).map(|d| (*id, d)))
-                    .filter_map(|(id, d)| s.develop_op(id, lightcraft_develop::apply_partial(&d, &partial, 1.0), "Paste from Previous"))
+                    .filter_map(|(id, d)| s.develop_op(id, paste_onto(s, &partial, dims, id, &d), "Paste from Previous"))
                     .collect::<Vec<_>>();
                 let n = ops.len();
                 s.commit("Paste from Previous", Op::Batch { ops })?;
@@ -860,22 +878,18 @@ pub fn specs() -> Vec<CommandSpec> {
             "Paste Edit Settings",
             ["Edit"],
             Some("Cmd+V"),
-            "{ids?, groups?: [settingsGroup] (paste only these of the copied groups)}",
+            "{ids?, groups?: [settingsGroup] (default: the groups chosen when copying; any group of the copied photo, Paste Selected Settings)}",
             has_clipboard,
             |s, p| {
                 let c = "develop.paste";
-                let mut clip = s.clipboard.clone().unwrap_or_default();
-                if let Some(only) = groups_param(p, c)? {
-                    // the clipboard holds whole groups: rebuild it with just the chosen (copied) ones
-                    let only: Vec<_> = only.into_iter().filter(|g| s.copy_groups.contains(g)).collect();
-                    let full = lightcraft_develop::apply_partial(&DevelopSettings::default(), &clip, 1.0);
-                    clip = lightcraft_develop::extract_groups(&full, &only);
-                }
+                let clip = s.clipboard.clone().ok_or_else(|| bad(c, "no settings copied"))?;
+                let groups = groups_param(p, c)?.unwrap_or_else(|| s.copy_groups.clone());
+                let partial = lightcraft_develop::extract_groups(&clip.settings, &groups);
                 let ids = s.targets(p)?;
                 let ops = ids
                     .iter()
                     .filter_map(|id| s.develop_of(*id).map(|d| (*id, d)))
-                    .filter_map(|(id, d)| s.develop_op(id, lightcraft_develop::apply_partial(&d, &clip, 1.0), "Paste Settings"))
+                    .filter_map(|(id, d)| s.develop_op(id, paste_onto(s, &partial, clip.dims, id, &d), "Paste Settings"))
                     .collect::<Vec<_>>();
                 let n = ops.len();
                 s.commit("Paste Settings", Op::Batch { ops })?;
@@ -895,6 +909,7 @@ pub fn specs() -> Vec<CommandSpec> {
                 let groups = groups_param(p, c)?.unwrap_or_else(SettingsGroup::default_copy);
                 let d = s.develop_of(id).unwrap_or_default();
                 let partial = lightcraft_develop::extract_groups(&d, &groups);
+                let dims = s.oriented_dims(id, d.orientation);
                 let ops = s
                     .selection
                     .ids
@@ -902,7 +917,7 @@ pub fn specs() -> Vec<CommandSpec> {
                     .into_iter()
                     .filter(|x| *x != id)
                     .filter_map(|x| s.develop_of(x).map(|d| (x, d)))
-                    .filter_map(|(x, dd)| s.develop_op(x, lightcraft_develop::apply_partial(&dd, &partial, 1.0), "Sync Settings"))
+                    .filter_map(|(x, dd)| s.develop_op(x, paste_onto(s, &partial, dims, x, &dd), "Sync Settings"))
                     .collect::<Vec<_>>();
                 let n = ops.len();
                 s.commit("Sync Settings", Op::Batch { ops })?;
@@ -1013,6 +1028,8 @@ pub fn specs() -> Vec<CommandSpec> {
             let amount = f64_or(p, "amount", 100.0).clamp(0.0, 200.0) / 100.0;
             // `id` names the preset here: the photos are `ids`, else the selection
             let ids = s.targets(&json!({"ids": p.get("ids")}))?;
+            // a preset's crop is applied as stored: it has no source photo whose shape a refit
+            // could start from (unlike Paste and Sync, issue #3056)
             let ops = ids
                 .iter()
                 .filter_map(|id| s.develop_of(*id).map(|d| (*id, d)))
diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs
--- a/crates/engine/src/lib.rs
+++ b/crates/engine/src/lib.rs
@@ -224,6 +224,18 @@ fn filter_depends_on_clock(filter: &Filter, catalog: &Catalog) -> bool {
 static VISIBLE_GEN: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
 static LIBRARY_GEN: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
 
+/// Copied develop settings (Copy Edit Settings). The copied photo's settings are kept whole, so
+/// Paste Selected Settings can paste any group, also one the copy left out (crop, Remove, …; issue
+/// #3056); a plain Paste applies [`Session::copy_groups`].
+#[derive(Clone, Debug)]
+pub struct SettingsClipboard {
+    /// The copied photo's settings, every group.
+    pub settings: Arc<DevelopSettings>,
+    /// The copied photo's size as oriented, to refit a pasted crop to a photo of another shape;
+    /// `None` when unknown (the crop is then pasted as it is).
+    pub dims: Option<(f64, f64)>,
+}
+
 pub struct Session {
     library_generation: u64,
     /// Auto Sync: edits to the active photo also change the other selected photos (the settings
@@ -294,8 +306,8 @@ pub struct Session {
     /// Reading focus points for photos imported before they were read (`photo.readFocusPoints`, `focus.pump`).
     #[cfg(not(target_arch = "wasm32"))]
     pub(crate) focus_scan: focus_scan::FocusScan,
-    /// Copied develop settings (partial JSON) for Paste.
-    pub clipboard: Option<Value>,
+    /// Copied develop settings for Paste (Copy Edit Settings).
+    pub clipboard: Option<SettingsClipboard>,
     /// The folder on disk the [`LibrarySource::Folder`] view browses.
     pub browse: Option<Browse>,
     /// The folder the [`LibrarySource::LibraryFolder`] view shows: the library's photos imported
@@ -305,7 +317,7 @@ pub struct Session {
     pub meta_clipboard: Option<Value>,
     /// The photo that was active before the current one (Paste Settings from Previous).
     pub previous_active: Option<PhotoId>,
-    /// Groups last used for Copy (Lightroom remembers them).
+    /// Groups last used for Copy (Lightroom remembers them): what a plain Paste applies.
     pub copy_groups: Vec<lightcraft_develop::SettingsGroup>,
     /// Built-in then user presets; its generation tells savers and caches when it changed.
     pub presets: presets::PresetList,
@@ -969,8 +981,11 @@ impl Session {
     /// With Auto Sync on, the ops that carry an edit of the active photo `id` (to `new`, as asked,
     /// before its crop is fitted) over to the other selected photos: only the settings that changed;
     /// never spot removal or red eye (they belong to one photo's pixels), nor the rendering process
-    /// (Sync doesn't carry it either), nor history / snapshot restores. Constrain Crop then fits each
-    /// photo's own crop: the active photo's fitted crop is never copied over another's.
+    /// (Sync doesn't carry it either), nor history / snapshot restores. A changed crop rect or aspect
+    /// lock is refitted to each photo's shape as Sync does ([`lightcraft_develop::Crop::refit`]),
+    /// leaving the crop fields the edit didn't change (a rect edit keeps each photo's angle).
+    /// Constrain Crop then fits each photo's own crop: the active photo's fitted crop is never
+    /// copied over another's.
     fn auto_sync_ops(&self, id: PhotoId, new: &DevelopSettings, label: &str) -> Vec<Op> {
         if !self.auto_sync
             || self.active() != Some(id)
@@ -1005,12 +1020,45 @@ impl Session {
             .filter(|x| **x != id)
             .filter_map(|x| self.develop_of(*x).map(|d| (*x, d)))
             .filter_map(|(x, d)| {
-                let synced = self.fit_constrained_crop(x, lightcraft_develop::apply_partial(&d, &delta, 1.0));
+                let mut synced = lightcraft_develop::apply_partial(&d, &delta, 1.0);
+                // a changed crop takes this photo's shape, as Sync and Paste give it (issue #3056).
+                // Only what changed: the refit starts from this photo's crop with the changed leaves
+                // applied (a new rect keeps this photo's angle) under the lock the edit was made with,
+                // and sets only the rect and lock the edit changed (the refit keeps angle and flips).
+                let crop = delta.get("crop");
+                let rect_changed = crop.and_then(|c| c.get("geometry")).is_some_and(|g| g.get("rect").is_some());
+                let aspect_changed = crop.is_some_and(|c| c.get("aspect").is_some());
+                if (rect_changed || aspect_changed)
+                    && let (Some(from), Some(to)) = (self.oriented_dims(id, new.orientation), self.oriented_dims(x, synced.orientation))
+                {
+                    let mut start = lightcraft_develop::Crop { aspect: new.crop.aspect, ..synced.crop };
+                    // a dragged edge or two mean nothing in a photo of another shape: it refits the
+                    // active photo's whole rect (at its own angle); one of the same shape takes the edges
+                    let same_shape = (from.0 * to.1 - to.0 * from.1).abs() <= 1e-6 * (to.0 * from.1);
+                    if rect_changed && !same_shape {
+                        start.geometry.rect = new.crop.geometry.rect;
+                    }
+                    let fit = start.refit(from, to);
+                    if rect_changed {
+                        synced.crop.geometry.rect = fit.geometry.rect;
+                    }
+                    if aspect_changed {
+                        synced.crop.aspect = fit.aspect;
+                    }
+                }
+                let synced = self.fit_constrained_crop(x, synced);
                 (synced != *d).then(|| self.develop_op(x, synced, label)).flatten()
             })
             .collect()
     }
 
+    /// Photo `id`'s size as oriented with `orientation`; `None` when the catalog doesn't know it.
+    pub(crate) fn oriented_dims(&self, id: PhotoId, orientation: lightcraft_geom::Orientation) -> Option<(f64, f64)> {
+        let p = self.catalog.photo(id)?;
+        let (w, h) = (p.width as f64, p.height as f64);
+        (w > 0.0 && h > 0.0).then_some(if orientation.swaps_axes() { (h, w) } else { (w, h) })
+    }
+
     /// The op that sets a photo's develop settings and appends a History entry (for batches).
     pub fn develop_op(&self, id: PhotoId, settings: DevelopSettings, label: &str) -> Option<Op> {
         self.catalog.photo(id)?;
diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs
--- a/crates/engine/src/tests.rs
+++ b/crates/engine/src/tests.rs
@@ -568,22 +568,255 @@ fn memory_report_counts_decoded_sources_and_renders() {
 }
 
 #[test]
-fn paste_selected_settings_pastes_only_chosen_copied_groups() {
+fn paste_selected_settings_pastes_any_chosen_group_of_the_copied_photo() {
     let mut s = demo();
     let ids: Vec<_> = s.visible().iter().copied().take(2).collect();
     s.execute("library.select", &json!({"ids": [ids[0].0]})).unwrap();
     s.execute("develop.set", &json!({"values": {"light.exposure": 1.0, "color.vibrance": 30, "detail.sharpenAmount": 90}})).unwrap();
     s.execute("develop.copy", &json!({"groups": ["light", "color"]})).unwrap();
-    // `detail` was not copied: asking for it pastes nothing for it
+    // `detail` was left out of the copy: Paste Selected still pastes it, and only what was chosen
     s.execute("develop.paste", &json!({"ids": [ids[1].0], "groups": ["light", "detail"]})).unwrap();
     let d = s.develop_of(ids[1]).unwrap();
     let base = lightcraft_develop::DevelopSettings::default();
     assert_eq!(d.light.exposure, 1.0);
+    assert_eq!(d.detail.sharpen_amount, 90.0);
     assert_eq!(d.color.vibrance, base.color.vibrance);
-    assert_ne!(d.detail.sharpen_amount, 90.0);
-    // without groups: everything copied
+    // without groups: the copied groups
+    s.execute("develop.reset", &json!({"ids": [ids[1].0]})).unwrap();
     s.execute("develop.paste", &json!({"ids": [ids[1].0]})).unwrap();
-    assert_eq!(s.develop_of(ids[1]).unwrap().color.vibrance, 30.0);
+    let d = s.develop_of(ids[1]).unwrap();
+    assert_eq!((d.light.exposure, d.color.vibrance), (1.0, 30.0));
+    assert_eq!(d.detail.sharpen_amount, base.detail.sharpen_amount, "a plain paste leaves out what the copy left out");
+}
+
+/// Two demo photos of the same shape and one of the other (landscape / portrait).
+fn photos_by_shape(s: &mut Session) -> (lightcraft_catalog::PhotoId, lightcraft_catalog::PhotoId, lightcraft_catalog::PhotoId) {
+    let vis = s.visible_cloned();
+    let portrait = |id: &lightcraft_catalog::PhotoId| s.catalog.photo(*id).is_some_and(|p| p.height > p.width);
+    let land: Vec<_> = vis.iter().copied().filter(|id| !portrait(id)).take(2).collect();
+    let tall = vis.iter().copied().find(portrait).expect("the demo library has a portrait photo");
+    (land[0], land[1], tall)
+}
+
+/// The crop of `id` in pixels of its oriented frame.
+fn crop_px(s: &Session, id: lightcraft_catalog::PhotoId) -> lightcraft_geom::Rect {
+    let p = s.catalog.photo(id).unwrap();
+    let (w, h) = if p.develop.orientation.swaps_axes() { (p.height, p.width) } else { (p.width, p.height) };
+    p.develop.crop.geometry.rect_px(w as f64, h as f64)
+}
+
+/// Issue #3056: Copy leaves crop and Remove out by default, as Lightroom does, so a plain paste
+/// doesn't carry them; ticking them in Paste Selected Settings pastes them (they used to be dropped
+/// because the clipboard held only the copied groups) onto every target, in one undo step.
+#[test]
+fn paste_selected_settings_pastes_crop_and_remove_left_out_of_the_copy() {
+    let mut s = demo();
+    let (a, b, c) = photos_by_shape(&mut s);
+    let c2 = s.visible_cloned().into_iter().find(|id| ![a, b, c].contains(id) && s.catalog.photo(*id).is_some_and(|p| p.width > p.height)).unwrap();
+    s.execute("library.select", &json!({"ids": [a.0]})).unwrap();
+    s.execute("crop.set", &json!({"rect": [0.1, 0.2, 0.7, 0.8]})).unwrap();
+    s.execute("spot.add", &json!({"points": [[0.4, 0.5]], "size": 0.05, "mode": "heal"})).unwrap();
+    s.execute("develop.set", &json!({"values": {"light.exposure": 0.5}})).unwrap();
+    let src = (*s.develop_of(a).unwrap()).clone();
+    s.execute("develop.copy", &json!({})).unwrap();
+
+    s.execute("develop.paste", &json!({"ids": [b.0]})).unwrap();
+    let d = s.develop_of(b).unwrap();
+    assert_eq!(d.light.exposure, 0.5);
+    assert!(d.crop.geometry.is_identity() && d.spots.is_empty(), "a plain paste carries no crop or Remove: {:?}", d.crop);
+
+    let before: Vec<_> = [b, c2].iter().map(|id| (*s.develop_of(*id).unwrap()).clone()).collect();
+    let r = s.execute("develop.paste", &json!({"ids": [b.0, c2.0], "groups": ["crop", "spots"]})).unwrap();
+    assert_eq!(r["changed"], 2);
+    for id in [b, c2] {
+        let d = s.develop_of(id).unwrap();
+        assert_eq!(d.crop.geometry, src.crop.geometry, "same shape: the same crop");
+        assert_eq!(d.spots, src.spots);
+    }
+    s.execute("edit.undo", &json!({})).unwrap();
+    for (id, was) in [b, c2].iter().zip(&before) {
+        assert_eq!(*s.develop_of(*id).unwrap(), *was, "one undo step takes back the whole paste");
+    }
+}
+
+/// A crop pasted (or synced) onto a photo of another shape keeps its aspect ratio, as in Lightroom,
+/// instead of its normalized rectangle (which would stretch it).
+#[test]
+fn pasted_crop_keeps_its_aspect_on_a_photo_of_another_shape() {
+    let mut s = demo();
+    let (a, _, tall) = photos_by_shape(&mut s);
+    s.execute("library.select", &json!({"ids": [a.0]})).unwrap();
+    // a square on the 3:2 landscape (6000 × 4000 nominal)
+    s.execute("crop.set", &json!({"rect": [0.3, 0.2, 0.3 + 0.6 * 4.0 / 6.0, 0.8]})).unwrap();
+    let src = crop_px(&s, a);
+    assert!((src.aspect() - 1.0).abs() < 1e-6, "{src:?}");
+    s.execute("develop.copy", &json!({})).unwrap();
+    s.execute("develop.paste", &json!({"ids": [tall.0], "groups": ["crop"]})).unwrap();
+    let r = crop_px(&s, tall);
+    assert!((r.aspect() - 1.0).abs() < 1e-6, "the square stays square on the portrait photo: {r:?}");
+    let d = s.develop_of(tall).unwrap();
+    let (w, h) = (s.catalog.photo(tall).unwrap().width as f64, s.catalog.photo(tall).unwrap().height as f64);
+    assert!(d.crop.geometry.is_within_image(w, h));
+
+    // Sync Settings with the crop does the same
+    s.execute("develop.reset", &json!({"ids": [tall.0]})).unwrap();
+    s.execute("library.select", &json!({"ids": [a.0, tall.0], "active": a.0})).unwrap();
+    s.execute("develop.sync", &json!({"groups": ["crop"]})).unwrap();
+    let r = crop_px(&s, tall);
+    assert!((r.aspect() - 1.0).abs() < 1e-6, "sync: {r:?}");
+}
+
+fn near(r: lightcraft_geom::Rect, want: [f64; 4]) -> bool {
+    [r.x0, r.y0, r.x1, r.y1].iter().zip(want).all(|(a, b)| (a - b).abs() < 1e-6)
+}
+
+/// Review of #3056: a 3:2 lock chosen on a 3:2 photo crops nothing, yet it is a lock: pasted onto a
+/// portrait photo it gives a centred 3:2 crop and keeps the lock, while an "Original" lock takes the
+/// portrait's own shape (and becomes its Original lock).
+#[test]
+fn pasted_crop_keeps_an_explicit_aspect_lock_that_crops_nothing() {
+    let mut s = demo();
+    let (a, _, tall) = photos_by_shape(&mut s);
+    s.execute("library.select", &json!({"ids": [a.0]})).unwrap();
+    s.execute("crop.aspect", &json!({"aspect": "3x2"})).unwrap();
+    let d = s.develop_of(a).unwrap();
+    assert_eq!((d.crop.geometry.rect, d.crop.aspect), (lightcraft_geom::Rect::UNIT, Some((300, 200))), "3:2 on 6000 × 4000");
+    s.execute("develop.copy", &json!({})).unwrap();
+    s.execute("develop.paste", &json!({"ids": [tall.0], "groups": ["crop"]})).unwrap();
+    let d = s.develop_of(tall).unwrap();
+    assert!(near(d.crop.geometry.rect, [0.0, 1.0 / 3.6, 1.0, 1.0 - 1.0 / 3.6]), "a centred 3:2 band: {:?}", d.crop);
+    assert_eq!(d.crop.aspect, Some((300, 200)), "the lock is kept");
+    assert!((crop_px(&s, tall).aspect() - 1.5).abs() < 1e-9);
+
+    s.execute("crop.aspect", &json!({"aspect": "original"})).unwrap();
+    assert_eq!(s.develop_of(a).unwrap().crop.aspect, Some((600_000, 400_000)));
+    s.execute("develop.copy", &json!({})).unwrap();
+    s.execute("develop.paste", &json!({"ids": [tall.0], "groups": ["crop"]})).unwrap();
+    let d = s.develop_of(tall).unwrap();
+    assert_eq!((d.crop.geometry.rect, d.crop.aspect), (lightcraft_geom::Rect::UNIT, Some((400_000, 600_000))), "Original: the whole portrait");
+}
+
+/// The Crop group carries the orientation: the target's shape is the one it has after the paste. A
+/// crop from a landscape photo turned upright lands as it is on another landscape photo (turned
+/// upright by the same paste), not refitted to the target's old landscape shape.
+#[test]
+fn pasted_crop_refits_to_the_orientation_it_carries() {
+    let mut s = demo();
+    let (a, b, _) = photos_by_shape(&mut s);
+    s.execute("library.select", &json!({"ids": [a.0]})).unwrap();
+    s.execute("photo.rotateRight", &json!({"ids": [a.0]})).unwrap();
+    // a square on the upright 4000 × 6000 frame
+    s.execute("crop.set", &json!({"rect": [0.2, 0.1, 0.8, 0.5]})).unwrap();
+    let src = s.develop_of(a).unwrap();
+    assert!(src.orientation.swaps_axes());
+    assert!((crop_px(&s, a).aspect() - 1.0).abs() < 1e-9);
+    s.execute("develop.copy", &json!({})).unwrap();
+    s.execute("develop.paste", &json!({"ids": [b.0], "groups": ["crop"]})).unwrap();
+    let d = s.develop_of(b).unwrap();
+    assert_eq!(d.orientation, src.orientation);
+    assert_eq!(d.crop, src.crop, "same shape once turned: the crop as it is");
+}
+
+/// Paste Settings from Previous refits a crop as Paste does.
+#[test]
+fn paste_from_previous_refits_the_crop() {
+    let mut s = demo();
+    let (a, _, tall) = photos_by_shape(&mut s);
+    s.execute("library.select", &json!({"ids": [a.0]})).unwrap();
+    s.execute("crop.set", &json!({"rect": [0.3, 0.2, 0.7, 0.8]})).unwrap();
+    s.execute("library.select", &json!({"ids": [tall.0]})).unwrap();
+    s.execute("develop.pastePrevious", &json!({"groups": ["crop"]})).unwrap();
+    let r = crop_px(&s, tall);
+    assert!((r.aspect() - 1.0).abs() < 1e-6, "the square stays square: {r:?}");
+}
+
+/// Auto Sync carries a crop as Sync Settings does: refitted to each photo's shape, not as the same
+/// normalized rectangle (which stretches it).
+#[test]
+fn auto_sync_refits_a_crop_like_sync() {
+    let crop_of_tall = |auto: bool| {
+        let mut s = demo();
+        let (a, _, tall) = photos_by_shape(&mut s);
+        s.execute("library.select", &json!({"ids": [a.0, tall.0], "active": a.0})).unwrap();
+        if auto {
+            s.execute("develop.autoSync", &json!({"on": true})).unwrap();
+        }
+        s.execute("crop.set", &json!({"rect": [0.3, 0.2, 0.7, 0.8]})).unwrap();
+        if !auto {
+            s.execute("develop.sync", &json!({"groups": ["crop"]})).unwrap();
+        }
+        (s.develop_of(tall).unwrap().crop, crop_px(&s, tall))
+    };
+    let (synced, auto) = (crop_of_tall(false), crop_of_tall(true));
+    assert!((auto.1.aspect() - 1.0).abs() < 1e-6, "the square stays square: {:?}", auto.1);
+    assert_eq!(auto.0, synced.0);
+}
+
+/// Review of #3056: Auto Sync carries only the crop fields the edit changed. A new crop rect on the
+/// active photo is refitted to each other photo at that photo's own angle, which it keeps.
+#[test]
+fn auto_sync_of_a_crop_rect_keeps_each_photos_angle() {
+    let mut s = demo();
+    let (a, b, tall) = photos_by_shape(&mut s);
+    for (id, angle) in [(b, 5.0), (tall, -3.0)] {
+        s.execute("library.select", &json!({"ids": [id.0]})).unwrap();
+        s.execute("crop.straighten", &json!({"angle": angle})).unwrap();
+    }
+    s.execute("library.select", &json!({"ids": [a.0, b.0, tall.0], "active": a.0})).unwrap();
+    s.execute("develop.autoSync", &json!({"on": true})).unwrap();
+    s.execute("crop.set", &json!({"rect": [0.3, 0.2, 0.7, 0.8]})).unwrap();
+    let src = s.develop_of(a).unwrap().crop.geometry;
+    assert_eq!(src.angle, 0.0);
+    let d = s.develop_of(b).unwrap();
+    assert_eq!((d.crop.geometry.rect, d.crop.geometry.angle), (src.rect, 5.0), "same shape: the rect, at b's own angle");
+    let d = s.develop_of(tall).unwrap();
+    assert_eq!(d.crop.geometry.angle, -3.0, "the portrait keeps its angle");
+    let p = s.catalog.photo(tall).unwrap();
+    assert!(d.crop.geometry.is_within_image(p.width as f64, p.height as f64), "{:?}", d.crop.geometry);
+    let r = crop_px(&s, tall);
+    assert!((r.aspect() - 1.0).abs() < 1e-6, "the square, refitted at the portrait's angle: {r:?}");
+}
+
+/// Review of #3056: dragging one edge changes one leaf of the rect. A photo of another shape takes
+/// the active photo's whole crop refitted, not its own rect with that edge spliced in.
+#[test]
+fn auto_sync_of_one_crop_edge_refits_the_whole_crop_onto_another_shape() {
+    let mut s = demo();
+    let (a, _, tall) = photos_by_shape(&mut s);
+    s.execute("library.select", &json!({"ids": [tall.0]})).unwrap();
+    s.execute("crop.set", &json!({"rect": [0.1, 0.1, 0.9, 0.9], "angle": -3.0})).unwrap();
+    s.execute("library.select", &json!({"ids": [a.0, tall.0], "active": a.0})).unwrap();
+    s.execute("develop.autoSync", &json!({"on": true})).unwrap();
+    s.execute("crop.set", &json!({"rect": [0.0, 0.0, 0.6, 1.0]})).unwrap();
+    let (src, r) = (crop_px(&s, a), crop_px(&s, tall));
+    assert!((r.aspect() - src.aspect()).abs() < 1e-6, "the active crop's shape: {src:?} vs {r:?}");
+    assert_eq!(s.develop_of(tall).unwrap().crop.geometry.angle, -3.0, "the portrait keeps its angle");
+}
+
+/// Review of #3056: a new angle on the active photo (its crop still fits, so only the angle
+/// changes) turns the other photos and leaves their own crop rect and aspect lock alone.
+#[test]
+fn auto_sync_of_a_crop_angle_keeps_each_photos_rect_and_lock() {
+    let mut s = demo();
+    let (a, b, tall) = photos_by_shape(&mut s);
+    s.execute("library.select", &json!({"ids": [a.0]})).unwrap();
+    s.execute("crop.set", &json!({"rect": [0.35, 0.35, 0.65, 0.65]})).unwrap();
+    s.execute("library.select", &json!({"ids": [b.0]})).unwrap();
+    s.execute("crop.set", &json!({"rect": [0.15, 0.15, 0.5, 0.6]})).unwrap();
+    s.execute("library.select", &json!({"ids": [tall.0]})).unwrap();
+    s.execute("crop.aspect", &json!({"aspect": "4x5"})).unwrap();
+    let before: Vec<_> = [b, tall].iter().map(|id| s.develop_of(*id).unwrap().crop).collect();
+    assert_eq!(before[1].aspect, Some((400, 500)));
+    s.execute("library.select", &json!({"ids": [a.0, b.0, tall.0], "active": a.0})).unwrap();
+    s.execute("develop.autoSync", &json!({"on": true})).unwrap();
+    let rect = s.develop_of(a).unwrap().crop.geometry.rect;
+    s.execute("crop.straighten", &json!({"angle": 3.0})).unwrap();
+    assert_eq!(s.develop_of(a).unwrap().crop.geometry.rect, rect, "the small crop still fits: only the angle changed");
+    for (id, was) in [b, tall].iter().zip(&before) {
+        let d = s.develop_of(*id).unwrap();
+        assert_eq!(d.crop.geometry.angle, 3.0, "the angle is synced");
+        assert_eq!((d.crop.geometry.rect, d.crop.aspect), (was.geometry.rect, was.aspect), "its own rect and lock");
+    }
 }
 
 /// A crop of no size (or a hair wide), as a sidecar can set it, made the render's
diff --git a/crates/geom/src/crop.rs b/crates/geom/src/crop.rs
--- a/crates/geom/src/crop.rs
+++ b/crates/geom/src/crop.rs
@@ -23,6 +23,18 @@ impl Default for CropGeometry {
     }
 }
 
+/// The shape a crop takes when [`CropGeometry::refit`] moves it to an image of another shape.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum RefitShape {
+    /// No aspect lock: the uncropped image (straightened or not) becomes the whole new image; any
+    /// other crop keeps its pixel aspect ratio.
+    Free,
+    /// An aspect ratio lock: the crop keeps its pixel aspect ratio, also when it is the whole image.
+    Locked,
+    /// Locked to the image's own shape ("Original"): the crop takes the new image's aspect ratio.
+    Photo,
+}
+
 impl CropGeometry {
     pub fn is_identity(&self) -> bool {
         self.angle == 0.0 && self.rect == Rect::UNIT
@@ -125,6 +137,36 @@ impl CropGeometry {
         CropGeometry { rect: Rect::from_center(f.center(), f.width() * s, f.height() * s).scale(1.0 / w, 1.0 / h), angle: angle_deg }
     }
 
+    /// This crop, made on a `from` (w, h) image, for an image of size `to` (pasting or syncing a crop,
+    /// as Lightroom does): the same crop when the two have the same shape. Otherwise the crop keeps
+    /// its angle, its size relative to the largest crop of its aspect, and its centre (in normalized
+    /// coordinates) as far as the turned image allows (a crop that would stick out is moved in, so a
+    /// straightened crop off the centre can move), and takes the shape `shape` gives it: its own pixel
+    /// aspect ratio, or the new image's. Sizes that are not finite and positive, and a crop of no
+    /// size, keep the crop as it is.
+    pub fn refit(&self, (fw, fh): (f64, f64), (tw, th): (f64, f64), shape: RefitShape) -> CropGeometry {
+        if ![fw, fh, tw, th].iter().all(|v| v.is_finite() && *v > 0.0) || ((fw / fh) - (tw / th)).abs() <= 1e-6 * (tw / th) {
+            return *self;
+        }
+        let own = crop_fit_angle(fw, fh, self.angle, None).rect;
+        let same = |a: Rect, b: Rect| [(a.x0, b.x0), (a.y0, b.y0), (a.x1, b.x1), (a.y1, b.y1)].iter().all(|(a, b)| (a - b).abs() < 1e-9);
+        if shape == RefitShape::Free && same(self.rect, own) {
+            return crop_fit_angle(tw, th, self.angle, None);
+        }
+        let r = self.rect_px(fw, fh);
+        // a degenerate rect has no aspect to keep: left as it is (the render copes with it)
+        let Some(aspect) = Some(r.width() / r.height()).filter(|a| a.is_finite() && *a > 0.0) else {
+            return *self;
+        };
+        let largest = crop_fit_angle(fw, fh, self.angle, Some(aspect)).rect_px(fw, fh);
+        let k = Some(r.width() / largest.width()).filter(|k| k.is_finite() && *k > 0.0).map_or(1.0, |k| k.min(1.0));
+        let new_aspect = if shape == RefitShape::Photo { tw / th } else { aspect };
+        let t = crop_fit_angle(tw, th, self.angle, Some(new_aspect)).rect_px(tw, th);
+        let c = self.rect.center();
+        let rect = Rect::from_center(Point::new(c.x * tw, c.y * th), t.width() * k, t.height() * k).scale(1.0 / tw, 1.0 / th);
+        CropGeometry { rect, angle: self.angle }.constrained(tw, th)
+    }
+
     /// The largest scale, at most 1, at which this crop shrunk about its own centre lies inside the
     /// rotated image; `None` when its centre is outside it.
     fn fit_scale_about_centre(&self, w: f64, h: f64) -> Option<f64> {
@@ -309,4 +351,87 @@ mod tests {
             }
         }
     }
+
+    #[test]
+    fn refit_keeps_the_same_crop_on_a_photo_of_the_same_shape() {
+        let c = CropGeometry { rect: Rect::new(0.1, 0.2, 0.6, 0.9), angle: 4.0 };
+        assert_eq!(c.refit((600.0, 400.0), (3000.0, 2000.0), RefitShape::Free), c);
+    }
+
+    #[test]
+    fn refit_keeps_the_crop_aspect_on_a_photo_of_another_shape() {
+        let px = |c: CropGeometry, w: f64, h: f64| c.rect_px(w, h);
+        // a square crop left of centre in a 3:2 landscape, pasted onto a 2:3 portrait
+        let sq = CropGeometry { rect: Rect::new(0.3 - 100.0 / 600.0, 0.1, 0.3 + 100.0 / 600.0, 0.6), angle: 0.0 };
+        assert!((px(sq, 600.0, 400.0).aspect() - 1.0).abs() < 1e-9);
+        let t = sq.refit((600.0, 400.0), (400.0, 600.0), RefitShape::Free);
+        let r = px(t, 400.0, 600.0);
+        assert!((r.aspect() - 1.0).abs() < 1e-9, "{r:?}");
+        // half the largest square on either photo (400 px tall there, 400 px wide here)
+        assert!((r.width() - 200.0).abs() < 1e-6, "{r:?}");
+        let (c0, c1) = (sq.rect.center(), t.rect.center());
+        assert!((c0.x - c1.x).abs() < 1e-9 && (c0.y - c1.y).abs() < 1e-9, "centred where it was: {:?}", t.rect);
+        assert!(t.is_within_image(400.0, 600.0));
+        // a 16:9 crop straightened by 8° onto a square photo stays 16:9 and inside the turned photo
+        let wide = crop_fit_angle(600.0, 400.0, 8.0, Some(16.0 / 9.0));
+        let t = wide.refit((600.0, 400.0), (500.0, 500.0), RefitShape::Free);
+        assert!((px(t, 500.0, 500.0).aspect() - 16.0 / 9.0).abs() < 1e-9);
+        assert_eq!(t.angle, 8.0);
+        assert!(t.is_within_image(500.0, 500.0));
+    }
+
+    #[test]
+    fn refit_of_an_uncropped_photo_is_the_whole_new_photo() {
+        assert_eq!(CropGeometry::default().refit((600.0, 400.0), (400.0, 600.0), RefitShape::Free), CropGeometry::default());
+        let straight = crop_fit_angle(600.0, 400.0, 5.0, None);
+        assert_eq!(straight.refit((600.0, 400.0), (400.0, 600.0), RefitShape::Free), crop_fit_angle(400.0, 600.0, 5.0, None));
+    }
+
+    fn near(a: Rect, b: [f64; 4]) -> bool {
+        [a.x0, a.y0, a.x1, a.y1].iter().zip(b).all(|(a, b)| (a - b).abs() < 1e-6)
+    }
+
+    #[test]
+    fn refit_keeps_a_locked_aspect_also_on_the_whole_photo() {
+        // 3:2 chosen on a 3:2 photo is the whole photo; on a 2:3 one it is a centred 3:2 band
+        let t = CropGeometry::default().refit((6000.0, 4000.0), (4000.0, 6000.0), RefitShape::Locked);
+        assert!(near(t.rect, [0.0, 1.0 / 3.6, 1.0, 1.0 - 1.0 / 3.6]), "{:?}", t.rect);
+        assert!((t.rect_px(4000.0, 6000.0).aspect() - 1.5).abs() < 1e-9);
+        // straightened as well: the largest 3:2 crop at that angle
+        let straight = crop_fit_angle(600.0, 400.0, 5.0, None);
+        let t = straight.refit((600.0, 400.0), (400.0, 600.0), RefitShape::Locked);
+        let want = crop_fit_angle(400.0, 600.0, 5.0, Some(1.5));
+        assert!(t.angle == 5.0 && near(t.rect, [want.rect.x0, want.rect.y0, want.rect.x1, want.rect.y1]), "{t:?} vs {want:?}");
+    }
+
+    #[test]
+    fn refit_of_an_original_lock_takes_the_new_photos_shape() {
+        assert_eq!(CropGeometry::default().refit((600.0, 400.0), (400.0, 600.0), RefitShape::Photo), CropGeometry::default());
+        // half the photo, 3:2, centred left of the middle: half the portrait, 2:3, centred there too
+        let c = CropGeometry { rect: Rect::from_center(Point::new(0.4, 0.5), 0.5, 0.5), angle: 0.0 };
+        let t = c.refit((600.0, 400.0), (400.0, 600.0), RefitShape::Photo);
+        assert!(near(t.rect, [0.15, 0.25, 0.65, 0.75]), "{:?}", t.rect);
+    }
+
+    #[test]
+    fn refit_moves_a_turned_crop_off_the_centre_inside_the_new_photo() {
+        // a square turned 20° left of centre: kept square and turned, but moved in to fit
+        let c = CropGeometry { rect: Rect::new(0.1, 0.2, 0.5, 0.8), angle: 20.0 };
+        assert!((c.rect_px(600.0, 400.0).aspect() - 1.0).abs() < 1e-9);
+        let t = c.refit((600.0, 400.0), (400.0, 600.0), RefitShape::Free);
+        assert_eq!(t.angle, 20.0);
+        assert!((t.rect_px(400.0, 600.0).aspect() - 1.0).abs() < 1e-9, "{:?}", t.rect);
+        assert!(t.is_within_image(400.0, 600.0), "{:?}", t.rect);
+        assert!(near(t.rect, [0.08125, 0.3, 0.68125, 0.7]), "{:?}", t.rect);
+    }
+
+    #[test]
+    fn refit_survives_degenerate_crops_and_sizes() {
+        let flat = CropGeometry { rect: Rect::new(0.0, 0.5, 1.0, 0.5), angle: 0.0 };
+        assert_eq!(flat.refit((600.0, 400.0), (400.0, 600.0), RefitShape::Free), flat);
+        let c = CropGeometry { rect: Rect::new(0.1, 0.1, 0.5, 0.5), angle: 0.0 };
+        for (from, to) in [((0.0, 400.0), (400.0, 600.0)), ((600.0, 400.0), (f64::NAN, 600.0)), ((600.0, 400.0), (400.0, f64::INFINITY))] {
+            assert_eq!(c.refit(from, to, RefitShape::Free), c);
+        }
+    }
 }
diff --git a/crates/geom/src/lib.rs b/crates/geom/src/lib.rs
--- a/crates/geom/src/lib.rs
+++ b/crates/geom/src/lib.rs
@@ -10,7 +10,7 @@ mod crop_drag;
 mod homography;
 mod real;
 
-pub use crop::{CropGeometry, crop_fit_angle, max_inscribed_scale};
+pub use crop::{CropGeometry, RefitShape, crop_fit_angle, max_inscribed_scale};
 pub use crop_drag::{CropHandle, MAX_RATIO, MIN_CROP_FRACTION, drag_crop};
 pub use homography::Homography;
 pub use real::{Interval, Real};
diff --git a/crates/ui-egui/locales/cs-formats.json b/crates/ui-egui/locales/cs-formats.json
--- a/crates/ui-egui/locales/cs-formats.json
+++ b/crates/ui-egui/locales/cs-formats.json
@@ -110,7 +110,7 @@
   "New Folder in “{name}”": "Nová složka v „{name}“",
   "On {have} of {of} selected photos": "Na {have} z {of} vybraných fotografií",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Nanášení „{k}“: kliknutím na fotografie přidáte nebo odeberete slovo · Esc ukončí režim",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Vložit do fotografií: {n}{:.0} — vloží se pouze zkopírovaná nastavení",
+  "Paste into {n} photo{}": "Vložit do fotografií: {n}{:.0}",
   "Preset: {name}": "Přednastavení: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Pouze náhled — úpravy vloženého JPEG z fotoaparátu ({})",
   "Preview only — {}": "Pouze náhled — {}",
diff --git a/crates/ui-egui/locales/de-formats.json b/crates/ui-egui/locales/de-formats.json
--- a/crates/ui-egui/locales/de-formats.json
+++ b/crates/ui-egui/locales/de-formats.json
@@ -90,7 +90,7 @@
   "Move {what} to Recently Deleted?": "{what} nach „Zuletzt gelöscht“ verschieben?",
   "Named ({named_n})": "Benannt ({named_n})",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "„{k}“ auftragen: Fotos anklicken, um es hinzuzufügen oder zu entfernen · Esc beendet",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "In {n} Foto{} einfügen – nur kopierte Einstellungen werden eingefügt",
+  "Paste into {n} photo{}": "In {n} Foto{} einfügen",
   "Preset: {name}": "Vorgabe: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Nur Vorschau – das eingebettete Kamera-JPEG wird bearbeitet ({})",
   "Preview only — {}": "Nur Vorschau – {}",
diff --git a/crates/ui-egui/locales/es-formats.json b/crates/ui-egui/locales/es-formats.json
--- a/crates/ui-egui/locales/es-formats.json
+++ b/crates/ui-egui/locales/es-formats.json
@@ -90,7 +90,7 @@
   "Move {what} to Recently Deleted?": "¿Mover {what} a Eliminadas recientemente?",
   "Named ({named_n})": "Con nombre ({named_n})",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Pintando “{k}”: hacer clic en las fotos para añadirla o quitarla · Esc para terminar",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Pegar en {n} foto{}: solo se pegan los ajustes copiados",
+  "Paste into {n} photo{}": "Pegar en {n} foto{}",
   "Preset: {name}": "Ajuste preestablecido: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Solo vista previa: editando el JPEG incrustado de la cámara ({})",
   "Preview only — {}": "Solo vista previa: {}",
diff --git a/crates/ui-egui/locales/fi-formats.json b/crates/ui-egui/locales/fi-formats.json
--- a/crates/ui-egui/locales/fi-formats.json
+++ b/crates/ui-egui/locales/fi-formats.json
@@ -136,7 +136,7 @@
   "New Folder in “{name}”": "Uusi kansio kohteessa ”{name}”",
   "On {have} of {of} selected photos": "{have} / {of} valitulla kuvalla",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Maalataan ”{k}”: napsauta kuvia lisätäksesi tai poistaaksesi sen · Esc lopettaa",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Liitä kuviin: {n}{:.0} — vain kopioidut asetukset liitetään",
+  "Paste into {n} photo{}": "Liitä kuviin: {n}{:.0}",
   "Preset: {name}": "Esiasetus: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Vain esikatselu — muokataan kameran upotettua JPEG-kuvaa ({})",
   "Preview only — {}": "Vain esikatselu — {}",
diff --git a/crates/ui-egui/locales/fr-formats.json b/crates/ui-egui/locales/fr-formats.json
--- a/crates/ui-egui/locales/fr-formats.json
+++ b/crates/ui-egui/locales/fr-formats.json
@@ -90,7 +90,7 @@
   "Move {what} to Recently Deleted?": "Déplacer {what} vers « Supprimés récemment » ?",
   "Named ({named_n})": "Nommés ({named_n})",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Application de « {k} » : cliquez sur les photos pour l’ajouter ou le retirer · Échap pour arrêter",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Coller dans {n} photo{} — seuls les réglages copiés seront collés",
+  "Paste into {n} photo{}": "Coller dans {n} photo{}",
   "Preset: {name}": "Préréglage : {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Aperçu uniquement — modification du JPEG intégré de l’appareil photo ({})",
   "Preview only — {}": "Aperçu uniquement — {}",
diff --git a/crates/ui-egui/locales/id-formats.json b/crates/ui-egui/locales/id-formats.json
--- a/crates/ui-egui/locales/id-formats.json
+++ b/crates/ui-egui/locales/id-formats.json
@@ -46,7 +46,7 @@
   "Move {what} to Recently Deleted?": "Pindahkan {what} ke Baru dihapus?",
   "Moved {n} photo{} to “{}”. Edit → Undo moves them back.": "{n} foto dipindahkan ke “{1}”{0:.0}. Pilih Edit → Urungkan untuk mengembalikannya.",
   "Named ({named_n})": "Bernama ({named_n})",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Tempel ke {n} foto{:.0} — hanya menempelkan pengaturan yang disalin",
+  "Paste into {n} photo{}": "Tempel ke {n} foto{:.0}",
   "Preset: {name}": "Preset: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Hanya pratinjau — yang diedit adalah JPEG bawaan kamera ({})",
   "Preview only — {}": "Hanya pratinjau — {}",
diff --git a/crates/ui-egui/locales/it-formats.json b/crates/ui-egui/locales/it-formats.json
--- a/crates/ui-egui/locales/it-formats.json
+++ b/crates/ui-egui/locales/it-formats.json
@@ -88,7 +88,7 @@
   "Move {what} to Recently Deleted?": "Spostare {what} in Eliminate di recente?",
   "Named ({named_n})": "Con nome ({named_n})",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Pennello “{k}”: fai clic sulle foto per aggiungerla o toglierla · Esc interrompe",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Incolla in {n} foto{:.0}: vengono incollate solo le impostazioni copiate",
+  "Paste into {n} photo{}": "Incolla in {n} foto{:.0}",
   "Preset: {name}": "Preset: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Solo anteprima: si modifica il JPEG incorporato dalla fotocamera ({})",
   "Preview only — {}": "Solo anteprima: {}",
diff --git a/crates/ui-egui/locales/ja-formats.json b/crates/ui-egui/locales/ja-formats.json
--- a/crates/ui-egui/locales/ja-formats.json
+++ b/crates/ui-egui/locales/ja-formats.json
@@ -46,7 +46,7 @@
   "Move {what} to Recently Deleted?": "{what}を「最近削除した写真」に移動しますか？",
   "Moved {n} photo{} to “{}”. Edit → Undo moves them back.": "{n}枚を「{1}」に移動しました。編集 → 取り消す で元に戻せます。{0:.0}",
   "Named ({named_n})": "名前付き（{named_n}）",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "{n}枚に貼り付け{:.0}（コピーされた設定だけを適用）",
+  "Paste into {n} photo{}": "{n}枚に貼り付け{:.0}",
   "Preset: {name}": "プリセット：{name}",
   "Preview only — editing the camera's embedded JPEG ({})": "プレビューのみ：カメラ内蔵のJPEGを編集中（{}）",
   "Preview only — {}": "プレビューのみ：{}",
diff --git a/crates/ui-egui/locales/ka-formats.json b/crates/ui-egui/locales/ka-formats.json
--- a/crates/ui-egui/locales/ka-formats.json
+++ b/crates/ui-egui/locales/ka-formats.json
@@ -110,7 +110,7 @@
   "New Folder in “{name}”": "ახალი საქაღალდე „{name}“-ში",
   "On {have} of {of} selected photos": "{of} მონიშნული ფოტოდან {have}-ზე",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "„{k}“-ის მინიჭება: დაწკაპეთ ფოტოებზე მის დასამატებლად ან მოსახსნელად · Esc ასრულებს",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "ჩასმა ფოტოებში: {n}{:.0} — ჩაისმება მხოლოდ კოპირებული პარამეტრები",
+  "Paste into {n} photo{}": "ჩასმა ფოტოებში: {n}{:.0}",
   "Preset: {name}": "პრესეტი: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "მხოლოდ წინასწარი ხედი — რედაქტირდება კამერის ჩაშენებული JPEG ({})",
   "Preview only — {}": "მხოლოდ წინასწარი ხედი — {}",
diff --git a/crates/ui-egui/locales/pl-formats.json b/crates/ui-egui/locales/pl-formats.json
--- a/crates/ui-egui/locales/pl-formats.json
+++ b/crates/ui-egui/locales/pl-formats.json
@@ -81,7 +81,7 @@
   "Move {what} to Recently Deleted?": "Przenieść {what} do Ostatnio usuniętych?",
   "Named ({named_n})": "Nazwane ({named_n})",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Przypisywanie „{k}”: klikaj zdjęcia, aby dodać lub usunąć słowo kluczowe · Esc kończy",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Wklej do zdjęć ({n}){:.0} — wklejone zostaną tylko skopiowane ustawienia",
+  "Paste into {n} photo{}": "Wklej do zdjęć ({n}){:.0}",
   "Preset: {name}": "Ustawienie wstępne: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Tylko podgląd — edycja pliku JPEG osadzonego przez aparat ({})",
   "Preview only — {}": "Tylko podgląd — {}",
diff --git a/crates/ui-egui/locales/pt-br-formats.json b/crates/ui-egui/locales/pt-br-formats.json
--- a/crates/ui-egui/locales/pt-br-formats.json
+++ b/crates/ui-egui/locales/pt-br-formats.json
@@ -63,7 +63,7 @@
   "Move {what} to Recently Deleted?": "Mover {what} para Excluídos recentemente?",
   "Moved {n} photo{} to “{}”. Edit → Undo moves them back.": "{n} foto{0} movida{0} para “{1}”. Editar → Desfazer as traz de volta.",
   "Named ({named_n})": "Nomeadas ({named_n})",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Colar em {n} foto{} — somente os ajustes copiados são colados",
+  "Paste into {n} photo{}": "Colar em {n} foto{}",
   "Preset: {name}": "Predefinição: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Somente pré-visualização — editando o JPEG incorporado da câmera ({})",
   "Preview only — {}": "Somente pré-visualização — {}",
diff --git a/crates/ui-egui/locales/ru-formats.json b/crates/ui-egui/locales/ru-formats.json
--- a/crates/ui-egui/locales/ru-formats.json
+++ b/crates/ui-egui/locales/ru-formats.json
@@ -95,7 +95,7 @@
   "Moved; {} photo(s) relinked": "Перемещено; перепривязано фото: {}",
   "Named ({named_n})": "Именованные ({named_n})",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Назначение «{k}»: щёлкайте по фото, чтобы добавить или снять его · Esc — завершить",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Вставка в фото: {n}{:.0} — вставляются только скопированные настройки",
+  "Paste into {n} photo{}": "Вставка в фото: {n}{:.0}",
   "Preset: {name}": "Пресет: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Только просмотр — правка встроенного в камеру JPEG ({})",
   "Preview only — {}": "Только просмотр — {}",
diff --git a/crates/ui-egui/locales/sv-formats.json b/crates/ui-egui/locales/sv-formats.json
--- a/crates/ui-egui/locales/sv-formats.json
+++ b/crates/ui-egui/locales/sv-formats.json
@@ -132,7 +132,7 @@
   "not added to Apple Photos: {e}": "inte tillagt i Apple Photos: {e}",
   "On {have} of {of} selected photos": "På {have} av {of} markerade foton",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Målar ”{k}”: klicka på foton för att lägga till eller ta bort det · Esc avslutar",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Klistra in i {n} foto{} – endast inställningar som kopierades klistras in",
+  "Paste into {n} photo{}": "Klistra in i {n} foto{}",
   "Preset: {name}": "Förinställning: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Endast förhandsgranskning – du redigerar kamerans inbäddade JPEG ({})",
   "Preview only — {}": "Endast förhandsgranskning – {}",
diff --git a/crates/ui-egui/locales/uk-formats.json b/crates/ui-egui/locales/uk-formats.json
--- a/crates/ui-egui/locales/uk-formats.json
+++ b/crates/ui-egui/locales/uk-formats.json
@@ -90,7 +90,7 @@
   "Move {what} to Recently Deleted?": "Перемістити {what} до нещодавно видалених?",
   "Named ({named_n})": "З іменами ({named_n})",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Призначення «{k}»: клацайте фото, щоб додати або вилучити його · Esc завершує",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Вставка у фото: {n}{:.0} — вставляються лише скопійовані налаштування",
+  "Paste into {n} photo{}": "Вставка у фото: {n}{:.0}",
   "Preset: {name}": "Набір налаштувань: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Лише перегляд — редагування вбудованого JPEG камери ({})",
   "Preview only — {}": "Лише перегляд — {}",
diff --git a/crates/ui-egui/locales/vi-formats.json b/crates/ui-egui/locales/vi-formats.json
--- a/crates/ui-egui/locales/vi-formats.json
+++ b/crates/ui-egui/locales/vi-formats.json
@@ -136,7 +136,7 @@
   "New Folder in “{name}”": "Thư mục mới trong «{name}»",
   "On {have} of {of} selected photos": "Trên {have} / {of} ảnh đã chọn",
   "Painting “{k}”: click photos to add or remove it · Esc stops": "Gán «{k}»: nhấp ảnh để thêm hoặc gỡ · Esc dừng",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "Dán vào {n} ảnh{:.0} — chỉ dán các thiết lập đã sao chép",
+  "Paste into {n} photo{}": "Dán vào {n} ảnh{:.0}",
   "Preset: {name}": "Thiết lập sẵn: {name}",
   "Preview only — editing the camera's embedded JPEG ({})": "Chỉ xem trước — chỉnh sửa JPEG nhúng của máy ảnh ({})",
   "Preview only — {}": "Chỉ xem trước — {}",
diff --git a/crates/ui-egui/locales/zh-hans-formats.json b/crates/ui-egui/locales/zh-hans-formats.json
--- a/crates/ui-egui/locales/zh-hans-formats.json
+++ b/crates/ui-egui/locales/zh-hans-formats.json
@@ -46,7 +46,7 @@
   "Move {what} to Recently Deleted?": "将 {what} 移到最近删除？",
   "Moved {n} photo{} to “{}”. Edit → Undo moves them back.": "已将 {n} 张照片移到“{1}”{0:.0}。编辑 → 撤销 可移回。",
   "Named ({named_n})": "已命名（{named_n}）",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "粘贴到 {n} 张照片 — 仅粘贴已复制的设置{0:.0}",
+  "Paste into {n} photo{}": "粘贴到 {n} 张照片{0:.0}",
   "Preset: {name}": "预设：{name}",
   "Preview only — editing the camera's embedded JPEG ({})": "仅预览 — 正在编辑相机内嵌的 JPEG（{0}）",
   "Preview only — {}": "仅预览 — {0}",
diff --git a/crates/ui-egui/locales/zh-hant-formats.json b/crates/ui-egui/locales/zh-hant-formats.json
--- a/crates/ui-egui/locales/zh-hant-formats.json
+++ b/crates/ui-egui/locales/zh-hant-formats.json
@@ -60,7 +60,7 @@
   "Move {what} to Recently Deleted?": "要將{what}移至「最近刪除」嗎？",
   "Moved {n} photo{} to “{}”. Edit → Undo moves them back.": "已將 {n} 張照片移到「{1}」{0:.0}。編輯 → 復原 可移回。",
   "Named ({named_n})": "已命名（{named_n}）",
-  "Paste into {n} photo{} — only settings that were copied are pasted": "貼上至 {n} 張照片{:.0} — 只貼上已複製的設定",
+  "Paste into {n} photo{}": "貼上至 {n} 張照片{:.0}",
   "Preset: {name}": "預設集：{name}",
   "Preview only — editing the camera's embedded JPEG ({})": "僅供預覽 — 正在編輯相機內嵌的 JPEG（{}）",
   "Preview only — {}": "僅供預覽 — {}",
diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs
--- a/crates/ui-egui/src/dialogs.rs
+++ b/crates/ui-egui/src/dialogs.rs
@@ -648,10 +648,7 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context, blocked: bool) {
                 Dialog::CopySettings { groups } => group_checklist(ui, "copyGroup", groups),
                 Dialog::PasteSettings { groups } => {
                     let n = app.session.selected().len();
-                    ui.label(
-                        egui::RichText::new(crate::i18n::tr_format!("Paste into {n} photo{} — only settings that were copied are pasted", if n == 1 { "" } else { "s" }, n = n))
-                            .color(t.text_dim),
-                    );
+                    ui.label(egui::RichText::new(crate::i18n::tr_format!("Paste into {n} photo{}", if n == 1 { "" } else { "s" }, n = n)).color(t.text_dim));
                     group_checklist(ui, "pasteGroup", groups);
                 }
                 Dialog::SlideshowExport { settings } => slideshow_export_body(app, ui, settings),
diff --git a/crates/ui-egui/src/state/dialog.rs b/crates/ui-egui/src/state/dialog.rs
--- a/crates/ui-egui/src/state/dialog.rs
+++ b/crates/ui-egui/src/state/dialog.rs
@@ -214,7 +214,7 @@ pub enum Dialog {
     CopySettings {
         groups: Vec<String>,
     },
-    /// Paste Selected Settings: which of the copied groups to paste.
+    /// Paste Selected Settings: which groups of the copied photo to paste.
     PasteSettings {
         groups: Vec<String>,
     },
diff --git a/crates/ui-egui/src/tests/copy_paste_dialogs.rs b/crates/ui-egui/src/tests/copy_paste_dialogs.rs
--- a/crates/ui-egui/src/tests/copy_paste_dialogs.rs
+++ b/crates/ui-egui/src/tests/copy_paste_dialogs.rs
@@ -89,3 +89,20 @@ fn escape_closes_paste_settings_without_pasting() {
     assert!(h.app.ui.dialog.is_none(), "Esc closes the dialog");
     assert_eq!(exposure(&h, ids[1]), 0.0, "Esc pastes nothing");
 }
+
+/// Issue #3056: ticking Crop in Paste Selected Settings pastes the crop, which the copy (light and
+/// colour) left out; it used to be dropped silently.
+#[test]
+fn ticking_crop_pastes_the_crop_the_copy_left_out() {
+    let (mut h, ids) = edited();
+    exec(&mut h, "crop.set", json!({"rect": [0.1, 0.2, 0.7, 0.8]}));
+    paste_dialog(&mut h, ids);
+    let r = h.request("ui.clickWidget", json!({"id": "pasteGroup:crop"}), T);
+    assert_eq!(r["ok"], true, "{r}");
+    h.settle(SETTLE);
+    key(&mut h, json!({"key": "Enter"}));
+    assert!(h.app.ui.dialog.is_none(), "Return closes the dialog");
+    let crop = h.app.session.develop_of(PhotoId(ids[1])).map(|d| d.crop.geometry).unwrap_or_default();
+    assert!(!crop.is_identity(), "the crop is pasted: {crop:?}");
+    assert_eq!(exposure(&h, ids[1]), 1.0, "with the copied settings");
+}
diff --git a/docs/parity-checklist.md b/docs/parity-checklist.md
--- a/docs/parity-checklist.md
+++ b/docs/parity-checklist.md
@@ -1,6 +1,6 @@
 # Lightroom parity checklist
 
-> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-25 · **Change:** minor (LR-BEHAV-TITLEBAR: a double-click follows the system setting, and a panel over the bar keeps the window still; KEYC-METADATA, LRC-LIB-KEYWORDS: ⌥0 / ⌥⇧0 go to the next / previous keyword set; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings; KEYC-METADATA: ⌘K / Ctrl+K Add Keywords; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
+> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-27 · **Change:** minor (MENU-EDIT-PASTESELECTED, LR-SYNC-PASTE: Paste Selected Settings pastes crop and Remove left out of the copy, and a pasted crop keeps its aspect on a photo of another shape, #3056; LR-BEHAV-TITLEBAR: a double-click follows the system setting, and a panel over the bar keeps the window still; KEYC-METADATA, LRC-LIB-KEYWORDS: ⌥0 / ⌥⇧0 go to the next / previous keyword set; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings; KEYC-METADATA: ⌘K / Ctrl+K Add Keywords; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
 
 The measured, row-by-row checklist: one row per Lightroom feature, menu item and shortcut, what we
 have and what is missing. It answers *does the feature exist?* (feature breadth). Whether it is good
@@ -276,7 +276,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
 | LR-REM-REFLECT | Remove reflections | P2 | ⬜ | | |
 | LR-REM-DUST | Dust detection | P2 | ✅ | `cmd:spot.findDust`, `crates/pipeline/src/dust.rs` | Remove panel ▸ Find Dust Spots: small, soft, round dark spots on smooth areas become heal spots (sensitivity; one undo step); Visualize Spots for checking by eye |
 | LR-REM-BLEMISH | Find blemishes on faces (beyond Lightroom) | P2 | ✅ | `cmd:spot.findBlemishes`, `crates/pipeline/src/blemish.rs`, `crates/engine/src/cmd/face_detect.rs` | Remove panel ▸ Find Blemishes: with the YuNet detector installed, small darker-or-redder round spots on each face's skin (eyes, brows, nostrils and mouth cut out around the landmarks) become heal spots (one undo step); faces under 160 px and faces with more than 12 candidates (stubble, freckles) get none, at most 6 per face; sensitivity 0–100. Classical, no learned model beyond the detector; not a Lightroom feature |
-| LR-REM-SYNC | Sync spots | P1 | ✅ | `cmd:develop.copy` (`groups`), `crates/develop/src/presets.rs` | |
+| LR-REM-SYNC | Sync spots | P1 | ✅ | `cmd:develop.copy` (`groups`), `cmd:develop.paste` (`groups`), `crates/develop/src/presets.rs` | left out of Copy by default, as in Lightroom; ticking Remove in Copy or in Paste Selected Settings pastes the spots (#3056) |
 
 ## J. Red eye (EYE)
 
@@ -312,7 +312,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
 | LR-MASK-OVERLAYALL | Show all mask overlays | P1 | ✅ | `cmd:view.maskOverlayAll`, `crates/ui-egui/src/panels/masking.rs`, `crates/pipeline/src/visualize.rs` | one diagnostic tint over every visible mask at once (CPU + GPU): the masks still stack their adjustments as before — this only paints each mask's region together, so you can see all masked areas at a glance (⌘⇧O / Ctrl+Shift+O) |
 | LR-MASK-PINS | Pins | P1 | ✅ | `cmd:view.maskPins`, `cmd:view.toolOverlay`, `crates/ui-egui/src/panels/detail.rs`, `crates/ui-egui/src/tests/tool_overlay.rs` | a pin per radial/linear/brush component: click selects its mask, drag moves it; Show Pins on follows the Tool Overlay mode (Auto: while the pointer is over the photo, hidden while brushing; Always; Selected: the selected mask's; Never; ⇧H cycles, #224); no pins for range/AI components |
 | LR-MASK-UPDATE | Recompute AI masks | P2 | ⬜ | | |
-| LR-MASK-SYNC | Copy masks to other photos | P1 | ✅ | `cmd:develop.copy` (`groups`) | |
+| LR-MASK-SYNC | Copy masks to other photos | P1 | ✅ | `cmd:develop.copy` (`groups`), `cmd:develop.paste` (`groups`) | left out of Copy by default, as in Lightroom; ticking Masking in Copy or in Paste Selected Settings pastes them |
 | LR-MASK-ADAPTIVE | Adaptive presets | P2 | ⬜ | | |
 
 ## L. Presets (PRE)
@@ -344,7 +344,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
 |---|---|---|---|---|---|
 | LR-SYNC-COPY | Copy edit settings | P0 | ✅ | `cmd:develop.copy` | |
 | LR-SYNC-CHOOSE | Choose settings to copy | P0 | ✅ | `cmd:dialog.copySettings` | groups are coarser than per-slider |
-| LR-SYNC-PASTE | Paste to selection | P0 | ✅ | `cmd:develop.paste` | no separate "paste selected" (choose at copy time instead) |
+| LR-SYNC-PASTE | Paste to selection | P0 | ✅ | `cmd:develop.paste`, `crates/geom/src/crop.rs` (`CropGeometry::refit`) | pastes the groups chosen at copy time onto every selected photo, one undo step; Paste Selected Settings (MENU-EDIT-PASTESELECTED) chooses at paste time. A crop pasted, synced or Auto Synced onto a photo of another shape keeps its aspect ratio, angle and relative size, as in Lightroom, centred where it was unless that would leave the turned photo; a locked ratio is kept even on an uncropped photo, an Original lock or an unlocked uncropped photo takes the new photo's shape (`Crop::refit`); Auto Sync carries only the crop fields the edit changed (a new rect keeps each photo's angle, a new angle each photo's rect); presets apply their crop as stored |
 | LR-SYNC-SYNCBTN | Sync active → selected | P1 | ✅ | `cmd:develop.sync` | |
 | LR-SYNC-PREVIOUS | Paste from previous / auto sync [Classic] | P2 | ✅ | `cmd:develop.pastePrevious`, `cmd:develop.autoSync` | ⌥⌘V pastes the previously active photo's settings (copy groups); Auto Sync (⌥⇧⌘A) |
 
@@ -522,7 +522,7 @@ visible menu bar yet: the menu model is only exposed through the control channel
 | MENU-EDIT-REDO | Redo | P0 | ✅ | `cmd:edit.redo` | |
 | MENU-EDIT-COPYPASTE | Copy / paste (edit settings) | P0 | ✅ | `cmd:develop.copy`, `cmd:develop.paste` | |
 | MENU-EDIT-CHOOSECOPY | Choose Edit Settings to Copy… | P0 | ✅ | `cmd:dialog.copySettings` | Return copies, Esc cancels |
-| MENU-EDIT-PASTESELECTED | Paste Selected Settings | P0 | ✅ | `cmd:dialog.pasteSettings`, `cmd:develop.paste` (`groups`) | checklist prefilled with the copied groups; only copied groups can be pasted; Return pastes, Esc cancels |
+| MENU-EDIT-PASTESELECTED | Paste Selected Settings | P0 | ✅ | `cmd:dialog.pasteSettings`, `cmd:develop.paste` (`groups`) | checklist prefilled with the copied groups; any group of the copied photo can be pasted, also one the copy left out (Crop, Remove, Masking, Red Eye: the clipboard keeps the photo's whole settings, #3056); Return pastes, Esc cancels |
 | MENU-EDIT-SELECTALL | Select All | P0 | ✅ | `cmd:library.selectAll` | |
 | MENU-EDIT-SELECTNONE | Select None | P0 | ✅ | `cmd:library.selectNone` | |
 | MENU-EDIT-SELECTBY | Select by flag / rating | P1 | ✅ | `cmd:library.selectBy` | Edit → Select by: picks, rejects, unflagged, ★…★★★★★ and higher, unrated, colour labels; `add` extends the selection |
@@ -799,6 +799,7 @@ Latin stays upright. Advanced Japanese composition remains open. Regression cove
 
 | Date | Change | Summary |
 |---|---|---|
+| 2026-10-27 | minor | MENU-EDIT-PASTESELECTED, LR-SYNC-PASTE, LR-REM-SYNC, LR-MASK-SYNC: the settings clipboard keeps the copied photo's whole settings, so Paste Selected Settings pastes any ticked group, also Crop and Remove left out of the copy (issue #3056); a crop pasted, pasted from previous, synced or Auto Synced onto a photo of another shape keeps its aspect ratio and aspect lock (`CropGeometry::refit`, `Crop::refit`), Auto Sync refitting only the crop fields the edit changed; LR-SYNC-PASTE no longer says there is no Paste Selected; status counts unchanged |
 | 2026-10-25 | patch | LR-BEHAV-TITLEBAR: the top bar's title-bar gestures come from craft-window's `title_bar`: a double-click follows the system setting, and a press on a button, the search field or a panel floating over the bar never moves the window; status counts unchanged |
 | 2026-10-24 | minor | KEYC-METADATA, LRC-LIB-KEYWORDS: ⌥0 / ⌥⇧0 (`keyword.nextSet`, `keyword.previousSet`) go to the next / previous keyword set; status counts unchanged (KEYC-METADATA stays 🟡) |
 | 2026-10-24 | minor | KEYC-METADATA: ⌘K / Ctrl+K (`panel.addKeywords`, Add Keywords) shows the Keywords panel, opens Keywording and puts the cursor in the Add keyword box; status counts unchanged (KEYC-METADATA stays 🟡) |
diff --git a/docs/whats-new.md b/docs/whats-new.md
--- a/docs/whats-new.md
+++ b/docs/whats-new.md
@@ -1,5 +1,18 @@
 # What's new in LightCraft
 
+## 2026-10-27
+
+### Paste Selected Settings pastes the crop and Remove
+- Copy Edit Settings still leaves Crop, Remove, Masking and Red Eye out by default, as Lightroom does, so a plain
+  Paste doesn't change them. Ticking one of them in Paste Selected Settings (⇧⌘V) now pastes it from the copied photo;
+  before, a group the copy had left out was silently skipped.
+- A crop pasted, pasted from the previous photo, synced or carried by Auto Sync onto a photo of another shape keeps its
+  aspect ratio, angle and relative size instead of being stretched, and stays centred where it was as far as the photo
+  allows (a straightened crop off the centre can move in to stay inside the turned photo). A locked ratio such as 3:2
+  is kept even when it crops nothing on the copied photo; an Original lock takes the new photo's own shape. On a photo
+  of the same shape the crop is pasted as it is. Presets apply their crop as stored. Auto Sync carries only what the
+  edit changed: a new crop rectangle keeps each photo's own angle, and a new angle each photo's own rectangle.
+
 ## 2026-10-24
 
 ### Relative-date filters and smart albums follow the clock
