diff --git a/ROADMAP.md b/ROADMAP.md
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -745,3 +745,5 @@ Newest first: the date, what moved, and the new overall estimate.
 - **2026-10-18 (renderer, hayro patches 19/35):** A mesh shading (types 4–7) is sampled over its own triangles instead of the whole path: a BricsCAD plan with 310 one-triangle `sh` fills took 2 s per 1024 px tile at every zoom (and hit the 20 s watchdog on a busy machine); now about 70 ms, so zooming into dense topology drawings stays fluid. Estimates unchanged.
 
 - **2026-10-22 (PR #3227 integration):** M11: integrate upstream `80b7d215`; retain partial target-version compatibility and upstream content-boundary and image-size regression coverage. Scope and estimates unchanged.
+- **2026-10-26 (M7, #4864):** Add text remembers its Format panel (font, bold/italic, size, colour, alignment, character spacing) across restarts, saved as `text_style` with the other settings; each field is validated on its own, so a damaged value keeps the current one. Tested through `persist`/`restore`.
+
diff --git a/crates/edit/src/added.rs b/crates/edit/src/added.rs
--- a/crates/edit/src/added.rs
+++ b/crates/edit/src/added.rs
@@ -31,7 +31,7 @@ use layout::Piece;
 pub(crate) use layout::WRAP_CALLS;
 pub use layout::{PASTE_STEP, first_undrawable, lines, paste_place, paste_rect, text_rect, text_width};
 pub use store::{add_content, delete_content, isolate_content, list_added, scan_markers, update_content};
-pub use types::{Added, AddedImage, AddedText, Align, CHAR_SPACING_LIMIT, Family, MarkerScan};
+pub use types::{Added, AddedImage, AddedText, Align, CHAR_SPACING_LIMIT, FONT_SIZE_RANGE, Family, MarkerScan};
 
 #[derive(Clone, Debug, PartialEq)]
 pub enum Content {
diff --git a/crates/edit/src/added/store.rs b/crates/edit/src/added/store.rs
--- a/crates/edit/src/added/store.rs
+++ b/crates/edit/src/added/store.rs
@@ -1,6 +1,6 @@
 use super::draw::{draw, params};
 use super::layout::{first_undrawable, is_thai, nums, shaped_arabic, thai_error};
-use super::types::{Added, AddedImage, AddedText, Align, CHAR_SPACING_LIMIT, Family, MarkerScan, TAG};
+use super::types::{Added, AddedImage, AddedText, Align, CHAR_SPACING_LIMIT, FONT_SIZE_RANGE, Family, MarkerScan, TAG};
 use super::*;
 
 fn parse(doc: &Document, d: &Dict) -> Option<Content> {
@@ -123,7 +123,7 @@ fn validate(c: &Content) -> Result<(), EditError> {
             if t.text.trim().is_empty() {
                 return Err(EditError::Invalid("type some text first".into()));
             }
-            if !(t.size.is_finite() && (1.0..=500.0).contains(&t.size)) {
+            if !(t.size.is_finite() && FONT_SIZE_RANGE.contains(&t.size)) {
                 return Err(EditError::Invalid("the font size must be between 1 and 500 points".into()));
             }
             if !(t.char_spacing.is_finite() && (-CHAR_SPACING_LIMIT..=CHAR_SPACING_LIMIT).contains(&t.char_spacing)) {
diff --git a/crates/edit/src/added/types.rs b/crates/edit/src/added/types.rs
--- a/crates/edit/src/added/types.rs
+++ b/crates/edit/src/added/types.rs
@@ -6,6 +6,9 @@ pub(super) const TAG: &str = "Added";
 /// The most character spacing an added text takes either way, in points: as far as the font size goes.
 pub const CHAR_SPACING_LIMIT: f64 = 500.0;
 
+/// The font sizes an added text takes, in points.
+pub const FONT_SIZE_RANGE: std::ops::RangeInclusive<f64> = 1.0..=500.0;
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
 pub enum Family {
     #[default]
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
@@ -78,8 +78,8 @@ pub use pdfcraft_organize::view::{InitialView, Layout as InitialLayout, Magnific
 pub use pdfcraft_cos::Algorithm;
 pub use pdfcraft_create::{CONVERTIBLE, CreateError, ImageResolution, SourceKind, decode_text, source_kind};
 pub use pdfcraft_edit::added::{
-    CHAR_SPACING_LIMIT as ADDED_CHAR_SPACING_LIMIT, paste_place as added_paste_place, paste_rect as added_paste_rect, text_rect as added_text_rect,
-    text_width as added_text_width,
+    CHAR_SPACING_LIMIT as ADDED_CHAR_SPACING_LIMIT, FONT_SIZE_RANGE as ADDED_FONT_SIZE_RANGE, paste_place as added_paste_place,
+    paste_rect as added_paste_rect, text_rect as added_text_rect, text_width as added_text_width,
 };
 pub use pdfcraft_edit::{
     Added, AddedImage, AddedText, Align as TextAlign, Background, Content as AddedContent, Family as FontFamily, HeaderFooter, MarkKind, Watermark,
diff --git a/crates/ui-egui/src/app/prefs.rs b/crates/ui-egui/src/app/prefs.rs
--- a/crates/ui-egui/src/app/prefs.rs
+++ b/crates/ui-egui/src/app/prefs.rs
@@ -19,6 +19,54 @@ pub(crate) const MAX_AUTHOR_CHARS: usize = 200;
 /// A restored colour: an `[r, g, b]` array of finite numbers, each clamped to 0–1 (restored
 /// settings are untrusted). Anything else (a string, a wrong length, a null or a non-finite
 /// number) is refused whole, so the caller keeps its default.
+/// The format Add text gives new text, without the text or its box (#4864).
+fn text_style_json(s: &pdfcraft_engine::AddedText) -> serde_json::Value {
+    use pdfcraft_engine::{FontFamily, TextAlign};
+    serde_json::json!({
+        "family": match s.family { FontFamily::Helvetica => "helvetica", FontFamily::Times => "times", FontFamily::Courier => "courier" },
+        "bold": s.bold,
+        "italic": s.italic,
+        "size": s.size,
+        "color": s.color,
+        "align": match s.align { TextAlign::Left => "left", TextAlign::Center => "center", TextAlign::Right => "right", TextAlign::Justify => "justify" },
+        "char_spacing": s.char_spacing,
+    })
+}
+
+/// Read [`text_style_json`] back. Settings are untrusted: each field is taken on its own, and one
+/// that is missing, unknown or out of range keeps the current value.
+fn restore_text_style(style: &mut pdfcraft_engine::AddedText, v: &serde_json::Value) {
+    use pdfcraft_engine::{FontFamily, TextAlign};
+    match v["family"].as_str() {
+        Some("helvetica") => style.family = FontFamily::Helvetica,
+        Some("times") => style.family = FontFamily::Times,
+        Some("courier") => style.family = FontFamily::Courier,
+        _ => {}
+    }
+    match v["align"].as_str() {
+        Some("left") => style.align = TextAlign::Left,
+        Some("center") => style.align = TextAlign::Center,
+        Some("right") => style.align = TextAlign::Right,
+        Some("justify") => style.align = TextAlign::Justify,
+        _ => {}
+    }
+    if let Some(on) = v["bold"].as_bool() {
+        style.bold = on;
+    }
+    if let Some(on) = v["italic"].as_bool() {
+        style.italic = on;
+    }
+    if let Some(size) = v["size"].as_f64().filter(|s| pdfcraft_engine::ADDED_FONT_SIZE_RANGE.contains(s)) {
+        style.size = size;
+    }
+    if let Some(color) = rgb_triple(&v["color"]) {
+        style.color = color;
+    }
+    if let Some(gap) = v["char_spacing"].as_f64().filter(|g| g.abs() <= pdfcraft_engine::ADDED_CHAR_SPACING_LIMIT) {
+        style.char_spacing = gap;
+    }
+}
+
 fn rgb_triple(v: &serde_json::Value) -> Option<[f64; 3]> {
     let a = v.as_array()?;
     if a.len() != 3 {
@@ -102,6 +150,7 @@ impl PdfCraftApp {
             "ui_scale": self.ui_scale,
             "flatten_fill_sign": self.flatten_fill_sign_on_save,
             "fill_text_size": self.fill_text_size,
+            "text_style": text_style_json(&self.text_style),
             "date_format": self.session.date_format(),
             // Null follows the interface language.
             "date_language": self.session.date_language(),
@@ -248,6 +297,7 @@ impl PdfCraftApp {
         if let Some(size) = v["fill_text_size"].as_f64().and_then(fill_sign::valid_text_size) {
             self.fill_text_size = size;
         }
+        restore_text_style(&mut self.text_style, &v["text_style"]);
         if let Some(prefs) = RedactPrefs::from_json(&v["redact_prefs"]) {
             self.redact_prefs = prefs.clone();
             self.redact_defaults = prefs;
diff --git a/crates/ui-egui/tests/it/fill_sign.rs b/crates/ui-egui/tests/it/fill_sign.rs
--- a/crates/ui-egui/tests/it/fill_sign.rs
+++ b/crates/ui-egui/tests/it/fill_sign.rs
@@ -1765,3 +1765,51 @@ fn mode_tabs_keep_the_hand_over_a_type_box_scrolled_under_them() {
     h.run_steps(3);
     assert_eq!(h.state().mode, pdfcraft_ui_egui::Mode::Convert, "the tab takes the click, not the text box");
 }
+
+/// #4864: the format Add text gives new text survives a restart; a damaged value keeps the
+/// current one, field by field.
+#[test]
+fn add_text_format_survives_settings_restore() {
+    use pdfcraft_engine::{AddedText, FontFamily, TextAlign};
+    let mut app = PdfCraftApp::new();
+    app.text_style = AddedText {
+        family: FontFamily::Courier,
+        bold: true,
+        italic: true,
+        size: 24.0,
+        color: [1.0, 0.0, 0.5],
+        align: TextAlign::Justify,
+        char_spacing: 2.0,
+        ..AddedText::default()
+    };
+    let settings = app.persist();
+
+    let mut restored = PdfCraftApp::new();
+    assert_ne!(restored.text_style, app.text_style);
+    restored.restore(&settings);
+    assert_eq!(restored.text_style, app.text_style);
+
+    // Every size the edit accepts (1 to 500 pt) comes back, including those outside Fill & Sign's.
+    for size in [1.0, 3.5, 400.0, 500.0] {
+        let mut app = PdfCraftApp::new();
+        app.text_style.size = size;
+        let mut back = PdfCraftApp::new();
+        back.restore(&app.persist());
+        assert_eq!(back.text_style.size, size);
+    }
+    for size in [0.5, 500.5] {
+        let mut app = PdfCraftApp::new();
+        app.text_style.size = size;
+        let mut back = PdfCraftApp::new();
+        back.restore(&app.persist());
+        assert_eq!(back.text_style.size, 12.0, "{size} pt is refused");
+    }
+
+    // Each field is judged alone: the bad ones keep what was there, the good one applies.
+    restored.restore(r#"{"text_style":{"family":"comic","bold":"yes","size":1e9,"color":[2,0],"align":7,"char_spacing":1e9,"italic":false}}"#);
+    let want = AddedText { italic: false, ..app.text_style.clone() };
+    assert_eq!(restored.text_style, want);
+    restored.restore(r#"{"text_style":"junk"}"#);
+    restored.restore(r#"{"text_style":{"size":null,"color":[0,0,0]}}"#);
+    assert_eq!(restored.text_style, AddedText { color: [0.0; 3], ..want });
+}
diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml
--- a/parity/acrobat-features.toml
+++ b/parity/acrobat-features.toml
@@ -2022,8 +2022,8 @@ milestone = "M7"
 status = "shipped"
 commands = ["edit.text"]
 tools = ["page_add_text", "content_update"]
-evidence = ["crates/ui-egui/tests/it/content.rs::typing_moving_styling_and_deleting_added_content", "crates/ui-egui/tests/it/content.rs::clicking_elsewhere_keeps_the_text_and_starts_a_new_box", "crates/automation/tests/it/automation.rs::adding_content_through_tools", "crates/edit/src/tests.rs::added_text_and_images_are_page_content_that_stays_editable", "crates/engine/src/tests.rs::added_text_and_images_render_and_stay_editable", "crates/edit/src/tests.rs::added_arabic_text_is_shaped_in_display_order_and_stays_searchable", "crates/automation/tests/it/automation.rs::thai_text_through_tools_saves_reopens_extracts_and_renders", "crates/ui-egui/tests/it/content.rs::typing_thai_text_keeps_marks_and_commits_to_page", "crates/automation/tests/it/automation.rs::added_arabic_text_keeps_copy_search_and_editor_order_after_retyping_and_reopen", "crates/edit/src/tests.rs::added_hebrew_text_is_drawn_right_to_left_and_stays_searchable", "crates/automation/tests/it/automation.rs::hebrew_text_through_tools_saves_reopens_extracts_and_renders"]
-notes = "page content, editable later (retype, move, restyle); standard fonts, Windows-1252 text. Arabic text is shaped with the craft-fonts Arab face (Type 3 outlines with ToUnicode) and laid out in bidirectional display order; per-line ActualText keeps copy, search and editor text in typing order through retyping and save/reopen; it is drawn regular whatever the bold/italic setting, and typing in the box is still left to right (misc.rtl-ui). Hebrew (#128) takes the same path with the craft-fonts Hebr face (Noto Sans Hebrew): right-to-left display order, points and cantillation kept on their letter as one glyph, ToUnicode and per-line ActualText; regular style only, and right-to-left scripts other than Arabic and Hebrew are not covered. Thai Add Text uses the craft-fonts Thai face, with shaped clusters and ToUnicode; Thai is regular style, wrapping preserves clusters but is not dictionary-based, and forms/Fill and Sign are not covered by this change. Each click on the page keeps the box being typed and starts a new one; Done and Discard beside the box"
+evidence = ["crates/ui-egui/tests/it/content.rs::typing_moving_styling_and_deleting_added_content", "crates/ui-egui/tests/it/content.rs::clicking_elsewhere_keeps_the_text_and_starts_a_new_box", "crates/automation/tests/it/automation.rs::adding_content_through_tools", "crates/edit/src/tests.rs::added_text_and_images_are_page_content_that_stays_editable", "crates/engine/src/tests.rs::added_text_and_images_render_and_stay_editable", "crates/edit/src/tests.rs::added_arabic_text_is_shaped_in_display_order_and_stays_searchable", "crates/automation/tests/it/automation.rs::thai_text_through_tools_saves_reopens_extracts_and_renders", "crates/ui-egui/tests/it/content.rs::typing_thai_text_keeps_marks_and_commits_to_page", "crates/automation/tests/it/automation.rs::added_arabic_text_keeps_copy_search_and_editor_order_after_retyping_and_reopen", "crates/edit/src/tests.rs::added_hebrew_text_is_drawn_right_to_left_and_stays_searchable", "crates/automation/tests/it/automation.rs::hebrew_text_through_tools_saves_reopens_extracts_and_renders", "crates/ui-egui/tests/it/fill_sign.rs::add_text_format_survives_settings_restore"]
+notes = "page content, editable later (retype, move, restyle); standard fonts, Windows-1252 text. Arabic text is shaped with the craft-fonts Arab face (Type 3 outlines with ToUnicode) and laid out in bidirectional display order; per-line ActualText keeps copy, search and editor text in typing order through retyping and save/reopen; it is drawn regular whatever the bold/italic setting, and typing in the box is still left to right (misc.rtl-ui). Hebrew (#128) takes the same path with the craft-fonts Hebr face (Noto Sans Hebrew): right-to-left display order, points and cantillation kept on their letter as one glyph, ToUnicode and per-line ActualText; regular style only, and right-to-left scripts other than Arabic and Hebrew are not covered. Thai Add Text uses the craft-fonts Thai face, with shaped clusters and ToUnicode; Thai is regular style, wrapping preserves clusters but is not dictionary-based, and forms/Fill and Sign are not covered by this change. Each click on the page keeps the box being typed and starts a new one; Done and Discard beside the box The Format panel's font, style, size, colour, alignment and character spacing for new text are saved with the settings and restored on start-up, each field checked alone (#4864); the text size on Fill & Sign is separate."
 
 [[feature]]
 id = "edit.find-replace"
