diff --git a/crates/layout/src/flow.rs b/crates/layout/src/flow.rs
--- a/crates/layout/src/flow.rs
+++ b/crates/layout/src/flow.rs
@@ -333,8 +333,8 @@ fn place_para_in_flow(ctx: &mut Ctx, pb: &mut PageBuilder, p: &Paragraph, block:
                 wordcraft_doc::props::LineSpacing::Multiple(m)
                     if m > 1.0 && at_margin && pb.notes.is_empty() && new_notes.is_empty() && line_notes.is_empty() =>
                 {
-                    // `baseline` is from the paragraph's top; the text ends a descent below it.
-                    (l.baseline - l.top + l.text_desc).clamp(0.0, l.height)
+                    // The text (or a taller picture) ends `leading` above the line's bottom.
+                    (l.height - l.leading).clamp(0.0, l.height)
                 }
                 _ => l.height,
             };
diff --git a/crates/layout/src/para/lines.rs b/crates/layout/src/para/lines.rs
--- a/crates/layout/src/para/lines.rs
+++ b/crates/layout/src/para/lines.rs
@@ -436,6 +436,8 @@ pub(super) fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u32, l
         // The tallest picture on the line (it sits on the baseline).
         let mut obj_asc = 0.0f32;
         let mut any = false;
+        // The line's text alone, without its pictures' runs: the multiple's leading below a picture
+        let (mut tasc, mut tdesc) = (0.0f32, 0.0f32);
         let dropped = pl.drop_cap.map_or(0, |d| d.0);
         for (k, c) in pl.clusters.get(c0..c1).into_iter().flatten().enumerate() {
             // Spaces and tabs never make a line taller, whatever their size: Word sizes a line by
@@ -461,6 +463,8 @@ pub(super) fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u32, l
                 } else {
                     // `obj_h` is set on text clusters only under ruby text, which the line grows to fit.
                     let (a, d) = st.line_extent();
+                    tasc = tasc.max(a);
+                    tdesc = tdesc.max(d);
                     (a.max(c.obj_h + st.shift), d)
                 };
                 asc = asc.max(a);
@@ -497,11 +501,34 @@ pub(super) fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u32, l
         // no rule tried so far (none, only the text's descent) matched both; it needs Word probes.
         let natural = asc + desc;
         let pictures = if obj_asc > asc { obj_asc + desc } else { 0.0 };
+        // Below a picture taller than the text Word puts the multiple's leading, (m - 1) x the
+        // natural height, of the line's text after its descent, or of the paragraph mark's font
+        // alone on a line of only pictures, never of a picture's own run. Word for Mac 16.93,
+        // a 2cm picture: next to 14pt Times New Roman text at double spacing 3.0 + 16.1pt below it,
+        // under a default 11pt Cambria mark 12.9pt, in a 20pt Arial run under an 8pt Times New
+        // Roman mark 9.2pt; at 1.15 spacing 0.15 x 12.9pt, less than the descent. Word for
+        // Windows: a 472pt picture in 1.5-spaced 12pt text takes 478.3pt. (height, leading)
+        let multiple_pictures = match rp.line_spacing {
+            LineSpacing::Multiple(m) if text_pictures > 0.0 && m > 1.0 => {
+                let (below, leading) = if tasc + tdesc > 0.0 {
+                    let leading = (m - 1.0) * (tasc + tdesc);
+                    (tdesc + leading, leading)
+                } else {
+                    let natural = pl.styles.get(mark_style as usize).map_or(text_natural, |st| {
+                        let (a, d) = st.line_extent();
+                        a + d
+                    });
+                    ((m - 1.0) * natural, (m - 1.0) * natural)
+                };
+                Some((obj_asc + below, leading))
+            }
+            _ => None,
+        };
         // Document grid: the line takes whole line pitches, its text centred in them.
         let (height, centred) = match (rp.line_spacing, grid) {
             (LineSpacing::Multiple(m), Some(g)) => ((g.snap_height(natural) * m).max(g.snap_height(pictures)), true),
             (LineSpacing::AtLeast(v), Some(g)) => (g.snap_height(natural.max(pictures)).max(v), true),
-            (LineSpacing::Multiple(m), None) => ((text_natural * m + label_extra).max(text_pictures), false),
+            (LineSpacing::Multiple(m), None) => ((text_natural * m + label_extra).max(multiple_pictures.map_or(text_pictures, |p| p.0)), false),
             (LineSpacing::AtLeast(v), None) => (natural.max(text_pictures).max(v), false),
             (LineSpacing::Exactly(v), _) => (v, false),
         };
@@ -509,7 +536,18 @@ pub(super) fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u32, l
             let up = asc.max(obj_asc);
             top + ((height - up - desc) / 2.0).max(0.0) + up
         } else {
-            top + baseline_offset(rp.line_spacing, asc, height, desc).max(obj_asc.min(height - desc))
+            // A picture that sets the line's height under multiple spacing stands at its top: the
+            // room below it may be less than the descent.
+            let floor = if multiple_pictures.is_some_and(|p| height <= p.0) { obj_asc } else { obj_asc.min(height - desc) };
+            top + baseline_offset(rp.line_spacing, asc, height, desc).max(floor)
+        };
+        // Below a picture that sets the line's height the leading is the multiple's, as below text:
+        // Word keeps such a line on the page when the picture fits above the bottom margin (with
+        // 1.7pt to spare, under the descent, in the same document).
+        let leading = if let Some((h, lead)) = multiple_pictures.filter(|p| !centred && height <= p.0) {
+            lead.min(top + h - baseline).max(0.0)
+        } else {
+            (top + height - baseline - text_desc).max(0.0)
         };
 
         // Alignment / justification (trailing spaces hang).
@@ -601,6 +639,7 @@ pub(super) fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u32, l
             baseline,
             text_asc,
             text_desc,
+            leading,
             c0,
             c1,
             xs,
@@ -643,12 +682,14 @@ pub(super) fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u32, l
                 };
                 let x0 = rp.indent_left;
                 let (x0, left, right) = if rtl_para { (width - x0, width - base_right, width - x0) } else { (x0, x0, base_right) };
+                let below = if grid.is_some() { h - desc } else { baseline_offset(rp.line_spacing, asc, h, desc) };
                 lines.push(Line {
                     top,
                     height: h,
-                    baseline: top + if grid.is_some() { h - desc } else { baseline_offset(rp.line_spacing, asc, h, desc) },
+                    baseline: top + below,
                     text_asc: asc,
                     text_desc: desc,
+                    leading: (h - below - desc).max(0.0),
                     c0: n,
                     c1: n,
                     xs: vec![x0],
diff --git a/crates/layout/src/para/model.rs b/crates/layout/src/para/model.rs
--- a/crates/layout/src/para/model.rs
+++ b/crates/layout/src/para/model.rs
@@ -158,6 +158,9 @@ pub struct Line {
     /// The text's own ascent and descent on this line, without line-spacing leading (the caret's extent).
     pub text_asc: f32,
     pub text_desc: f32,
+    /// Room at the bottom of the line below its text or picture: multiple spacing's extra
+    /// leading, which Word lets a page's last line run into the bottom margin.
+    pub leading: f32,
     /// Cluster index range.
     pub c0: usize,
     pub c1: usize,
diff --git a/crates/layout/src/tests.rs b/crates/layout/src/tests.rs
--- a/crates/layout/src/tests.rs
+++ b/crates/layout/src/tests.rs
@@ -4814,12 +4814,97 @@ fn line_spacing_does_not_scale_pictures() {
     let l = lay(&d);
     let Some(Placed::Lines { para, .. }) = l.pages[0].items.iter().find(|i| matches!(i, Placed::Lines { .. })) else { panic!() };
     let line = &para.lines[0];
-    let desc = para.styles[0].descent;
-    // Word: the picture plus the font's descent, not (picture + descent) x 1.15.
-    assert!((line.height - (144.0 + desc)).abs() < 0.01, "line {} for a 144pt picture (descent {desc})", line.height);
+    let st = &para.styles[0];
+    // Word: the picture plus 0.15 of the paragraph mark's natural height, not (picture + descent)
+    // x 1.15, and not the descent either (Word for Mac 16.93: 1.9pt under a 2cm picture, 11pt Cambria).
+    let want = 144.0 + 0.15 * (st.ascent + st.descent);
+    assert!((line.height - want).abs() < 0.01, "line {} for a 144pt picture, want {want}", line.height);
     assert!((line.baseline - line.top - 144.0).abs() < 0.01, "the picture stands on the baseline");
 }
 
+#[test]
+fn a_picture_line_in_multiple_spacing_takes_the_leading_of_its_text_or_the_paragraph_mark() {
+    // Word for Mac 16.93, a 2cm picture at double spacing: alone on its line it gets the
+    // paragraph mark's natural height below it, whatever its own run's size (20pt run, 8pt mark:
+    // 9.2pt); next to text, the text's descent and natural height (20pt Arial: 4.2 + 23pt).
+    use wordcraft_doc::CharProps;
+    use wordcraft_doc::props::LineSpacing;
+    let pic = 56.7;
+    let size = |pt: f32| CharProps { size: Some(pt), ..Default::default() };
+    let para = |m: f32, mark: f32, picture_run: Option<f32>, text: Option<f32>| {
+        let mut p = wordcraft_doc::Paragraph::with_text(if text.is_some() { "x" } else { "" }, size(text.unwrap_or(mark)));
+        p.mark = size(mark);
+        p.props.line_spacing = Some(LineSpacing::Multiple(m));
+        p.props.space_before = Some(0.0);
+        p.props.space_after = Some(0.0);
+        if let Some(run) = picture_run {
+            p.insert_object(0, picture(40.0, pic, Default::default()), &size(run)).unwrap();
+        }
+        wordcraft_doc::para_block(p)
+    };
+    let mut d = Document::from_text("");
+    d.body = vec![
+        para(1.0, 8.0, None, Some(8.0)),
+        para(1.0, 8.0, None, Some(20.0)),
+        para(2.0, 8.0, Some(20.0), None),
+        para(2.0, 8.0, Some(14.0), Some(20.0)),
+    ];
+    let l = lay(&d);
+    let lines: Vec<crate::para::Line> =
+        l.pages[0].items.iter().filter_map(|i| if let Placed::Lines { para, l0, .. } = i { Some(para.lines[*l0].clone()) } else { None }).collect();
+    let (small, big) = (&lines[0], &lines[1]);
+    let alone = lines[2].height;
+    assert!((alone - (pic + small.height)).abs() < 0.01, "alone: {alone}, want {pic} + the 8pt mark's {}", small.height);
+    let beside = lines[3].height;
+    let want = pic + big.text_desc + big.height;
+    assert!((beside - want).abs() < 0.01, "next to 20pt text: {beside}, want {want}");
+    assert!((lines[3].baseline - lines[3].top - pic).abs() < 0.01, "the picture stands at the line top");
+}
+
+#[test]
+fn a_picture_in_one_and_a_half_spacing_takes_the_texts_leading_and_fits_at_the_page_bottom() {
+    // Word for Windows (a 472pt picture in 1.5-spaced 12pt text): the line is the picture plus
+    // half the text's natural height, and at the foot of a page the picture only has to fit above
+    // the bottom margin: it stayed with 1.7pt to spare, less than the descent.
+    use wordcraft_doc::props::LineSpacing;
+    let pic = 400.0;
+    let doc = |spare: f32| {
+        let mut d = Document::from_text("Text");
+        let s = d.last_section.clone();
+        let p = d.para_mut(StoryRef::Body, &Path::top(0)).unwrap();
+        p.props.line_spacing = Some(LineSpacing::Exactly(20.0));
+        p.props.space_before = Some(0.0);
+        p.props.space_after = Some(s.page_h - s.margin_bottom - s.margin_top - 20.0 - pic - spare);
+        let mut q = wordcraft_doc::Paragraph::with_text("", Default::default());
+        q.props.line_spacing = Some(LineSpacing::Multiple(1.5));
+        q.props.space_before = Some(0.0);
+        q.insert_object(0, picture(100.0, pic, Default::default()), &Default::default()).unwrap();
+        d.body.push(wordcraft_doc::para_block(q));
+        d
+    };
+    let l = lay(&doc(1.0));
+    let lines = |l: &DocLayout, page: usize| {
+        l.pages[page]
+            .items
+            .iter()
+            .filter_map(|i| if let Placed::Lines { para, l0, .. } = i { Some((para.clone(), *l0)) } else { None })
+            .collect::<Vec<_>>()
+    };
+    let on_first = lines(&l, 0);
+    let Some((para, l0)) = on_first.iter().find(|(p, _)| !p.lines.is_empty() && p.lines[0].text_asc >= pic) else {
+        panic!("the picture should stay on page 1 ({} pages)", l.pages.len())
+    };
+    let line = &para.lines[*l0];
+    let st = &para.styles[para.clusters[0].style as usize];
+    assert!(st.descent > 1.0, "the spare room is under the descent");
+    let want = pic + 0.5 * (st.ascent + st.descent);
+    assert!((line.height - want).abs() < 0.01, "line {} for a {pic}pt picture, want {want}", line.height);
+    assert!((line.baseline - line.top - pic).abs() < 0.01, "the picture stands at the line top");
+    // A picture that ends past the margin still goes to the next page.
+    let l = lay(&doc(-0.5));
+    assert!(!lines(&l, 0).iter().any(|(p, _)| p.lines.first().is_some_and(|x| x.text_asc >= pic)), "the picture should move on");
+}
+
 #[test]
 fn multiple_line_spacing_adds_its_leading_below_the_text() {
     use wordcraft_doc::props::LineSpacing;
@@ -4868,8 +4953,10 @@ fn list_label_does_not_inflate_an_inline_picture_floor() {
         let l = lay(&d);
         let Some(Placed::Lines { para, .. }) = l.pages[0].items.iter().find(|i| matches!(i, Placed::Lines { .. })) else { panic!() };
         let line = &para.lines[0];
-        let desc = para.styles[para.clusters[0].style as usize].descent;
-        assert!((line.height - (144.0 + desc)).abs() < 0.01, "{spacing:?}: {}", line.height);
+        let st = &para.styles[para.clusters[0].style as usize];
+        // Under the picture: the descent, or the text's own multiple leading when larger.
+        let below = if let LineSpacing::Multiple(m) = spacing { st.descent.max((m - 1.0) * (st.ascent + st.descent)) } else { st.descent };
+        assert!((line.height - (144.0 + below)).abs() < 0.01, "{spacing:?}: {}", line.height);
         assert!((line.baseline - line.top - 144.0).abs() < 0.01);
     }
 }
diff --git a/docs/layout-parity.md b/docs/layout-parity.md
--- a/docs/layout-parity.md
+++ b/docs/layout-parity.md
@@ -266,6 +266,7 @@ layout suite are pending; this is not a new Word/native-IME acceptance claim.
 
 | Date | Change | Summary |
 |---|---|---|
+| 2026-10-26 | trivial | A line set by an inline picture in multiple spacing above single takes the text's leading, (m - 1) x its natural height, below the picture instead of the descent (when larger), and at the foot of a page only the picture has to fit above the bottom margin, as for text. Word for Windows put a 472pt picture in 1.5-spaced 12pt text on the page with 1.7pt to spare and spaced the next line 6.3pt below it; the 64-page document now has 64 pages, not 65 (`layout::tests::a_picture_in_one_and_a_half_spacing_takes_the_texts_leading_and_fits_at_the_page_bottom`) |
 | 2026-10-25 | trivial | Arabic list labels: `arabicAlpha` and `arabicAbjad` draw the 28 Arabic letters (alphabetical and abjad order), doubling past the last letter; Hebrew, Hindi, Thai and Vietnamese still show decimal (`doc::section::tests::arabic_letters_count_in_both_orders`) |
 | 2026-10-24 | trivial | Preserve grapheme edit/wrap boundaries across independently drawn font/style pieces; original emoji regression retained, new mixed-style/bundled-font LTR/bidi controls pending managed validation |
 | 2026-10-24 | trivial | Exact-spacing table contact uses the specified line height in row selection and word skipping; large/small mark regressions in modes 11/12/14/15 (#3977); shape estimates unchanged |
