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
@@ -108,6 +108,7 @@
   "Moved; {} photo(s) relinked": "Přesunuto; znovu propojeno fotografií: {}",
   "Named ({named_n})": "Pojmenované ({named_n})",
   "New Folder in “{name}”": "Nová složka v „{name}“",
+  "Created folder “{name}” in “{parent}”": "Vytvořena složka „{name}“ v „{parent}“",
   "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í",
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
@@ -248,6 +248,7 @@
   "{what} merge cancelled": "{what}-Zusammenfügung abgebrochen",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Übersprungen: {n} lokale Fotos{0:.0} – Alben enthalten Bibliotheksfotos (zuerst zu „Meine Fotos“ hinzufügen)",
   "New Folder in “{name}”": "Neuer Ordner in „{name}“",
+  "Created folder “{name}” in “{parent}”": "Ordner „{name}“ in „{parent}“ erstellt",
   "Moved {} photo(s)": "{} Foto(s) verschoben",
   "not added to Apple Photos: {e}": "nicht zu Apple Fotos hinzugefügt: {e}",
   "{n} added to Apple Photos album “{album}”": "{n} zum Apple-Fotos-Album „{album}“ hinzugefügt",
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
@@ -248,6 +248,7 @@
   "{what} merge cancelled": "Combinación {what} cancelada",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Fotos locales omitidas: {n}{0:.0} — los álbumes contienen fotos de la biblioteca (añádelas primero a Mis fotos)",
   "New Folder in “{name}”": "Nueva carpeta en «{name}»",
+  "Created folder “{name}” in “{parent}”": "Carpeta «{name}» creada en «{parent}»",
   "Moved {} photo(s)": "{} foto(s) movida(s)",
   "not added to Apple Photos: {e}": "no se añadieron a Fotos de Apple: {e}",
   "{n} added to Apple Photos album “{album}”": "{n} añadidas al álbum “{album}” de Fotos de Apple",
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
@@ -134,6 +134,7 @@
   "Moved; {} photo(s) relinked": "Siirretty; yhdistetty uudelleen kuvia: {}",
   "Named ({named_n})": "Nimetyt ({named_n})",
   "New Folder in “{name}”": "Uusi kansio kohteessa ”{name}”",
+  "Created folder “{name}” in “{parent}”": "Kansio ”{name}” luotu kohteeseen ”{parent}”",
   "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",
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
@@ -248,6 +248,7 @@
   "{what} merge cancelled": "Fusion {what} annulée",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Photos locales ignorées : {n}{0:.0} — les albums contiennent des photos de la bibliothèque (ajoutez-les d’abord à Mes photos)",
   "New Folder in “{name}”": "Nouveau dossier dans « {name} »",
+  "Created folder “{name}” in “{parent}”": "Dossier « {name} » créé dans « {parent} »",
   "Moved {} photo(s)": "{} photo(s) déplacée(s)",
   "not added to Apple Photos: {e}": "non ajouté à Apple Photos : {e}",
   "{n} added to Apple Photos album “{album}”": "{n} ajouté(s) à l'album Apple Photos « {album} »",
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
@@ -251,6 +251,7 @@
   "{what} merge cancelled": "Penggabungan {what} dibatalkan",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "{n} foto Lokal{:.0} dilewati: album hanya dapat berisi foto pustaka (tambahkan ke Foto saya terlebih dahulu)",
   "New Folder in “{name}”": "Folder baru di “{name}”",
+  "Created folder “{name}” in “{parent}”": "Folder “{name}” dibuat di “{parent}”",
   "Moved {} photo(s)": "{} foto dipindahkan",
   "not added to Apple Photos: {e}": "tidak ditambahkan ke Apple Photos: {e}",
   "{n} added to Apple Photos album “{album}”": "{n} ditambahkan ke album Apple Photos “{album}”",
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
@@ -240,6 +240,7 @@
   "{what} merge cancelled": "Unione {what} annullata",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Foto locali saltate: {n}{0:.0}; gli album contengono foto della libreria (prima aggiungile a Le mie foto)",
   "New Folder in “{name}”": "Nuova cartella in “{name}”",
+  "Created folder “{name}” in “{parent}”": "Cartella “{name}” creata in “{parent}”",
   "Moved {} photo(s)": "Foto spostate: {}",
   "not added to Apple Photos: {e}": "non aggiunte a Foto di Apple: {e}",
   "{n} added to Apple Photos album “{album}”": "Aggiunte all'album “{album}” di Foto di Apple: {n}",
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
@@ -252,6 +252,7 @@
   "{what} merge cancelled": "{what}合成をキャンセルしました",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "ローカル写真{n}枚をスキップしました{0:.0}：アルバムに入れられるのはライブラリの写真です（先にマイフォトに追加してください）",
   "New Folder in “{name}”": "「{name}」に新規フォルダ",
+  "Created folder “{name}” in “{parent}”": "「{parent}」にフォルダ「{name}」を作成しました",
   "Moved {} photo(s)": "{} 枚の写真を移動しました",
   "not added to Apple Photos: {e}": "Appleの写真に追加されませんでした：{e}",
   "{n} added to Apple Photos album “{album}”": "{n}件をAppleの写真のアルバム「{album}」に追加しました",
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
@@ -108,6 +108,7 @@
   "Moved; {} photo(s) relinked": "გადატანილია; ხელახლა დაკავშირდა ფოტო: {}",
   "Named ({named_n})": "სახელიანი ({named_n})",
   "New Folder in “{name}”": "ახალი საქაღალდე „{name}“-ში",
+  "Created folder “{name}” in “{parent}”": "საქაღალდე „{name}“ შეიქმნა „{parent}“-ში",
   "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} — ჩაისმება მხოლოდ კოპირებული პარამეტრები",
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
@@ -236,6 +236,7 @@
   "Lightroom geometry was not preserved for {path}; {mode} will be recalculated.": "Geometria z Lightrooma dla {path} nie została zachowana; tryb {mode} zostanie obliczony ponownie.",
   "Moved {} photo(s)": "Przeniesione zdjęcia: {}",
   "New Folder in “{name}”": "Nowy folder w „{name}”",
+  "Created folder “{name}” in “{parent}”": "Utworzono folder „{name}” w „{parent}”",
   "Restored {} photo{} from Recently Deleted": "Przywrócone z Ostatnio usuniętych zdjęcia: {}{:.0}",
   "XMP adjustments were not imported for {path}: {fields}.": "Korekty XMP dla {path} nie zostały zaimportowane: {fields}.",
   "XMP profile \"{profile}\" was not applied for {path}; colors may differ from Lightroom.": "Profil XMP „{profile}” nie został zastosowany do {path}; kolory mogą się różnić od Lightrooma.",
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
@@ -252,6 +252,7 @@
   "{what} merge cancelled": "{what} mesclagem cancelada",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Fotos locais ignoradas: {n}{0:.0} — álbuns contêm fotos da biblioteca (adicione-as às Minhas fotos primeiro)",
   "New Folder in “{name}”": "Nova pasta em “{name}”",
+  "Created folder “{name}” in “{parent}”": "Pasta “{name}” criada em “{parent}”",
   "Moved {} photo(s)": "{} foto(s) movida(s)",
   "not added to Apple Photos: {e}": "não adicionadas ao Fotos da Apple: {e}",
   "{n} added to Apple Photos album “{album}”": "{n} adicionadas ao álbum “{album}” do Fotos da Apple",
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
@@ -248,6 +248,7 @@
   "{what} merge cancelled": "{what}: слияние отменено",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Пропущено локальных фото: {n}{0:.0} — в альбомах только фото из библиотеки (сначала добавьте их в «Мои фото»)",
   "New Folder in “{name}”": "Новая папка в «{name}»",
+  "Created folder “{name}” in “{parent}”": "Папка «{name}» создана в «{parent}»",
   "Moved {} photo(s)": "Перемещено фото: {}",
   "not added to Apple Photos: {e}": "не добавлено в Apple Фото: {e}",
   "{n} added to Apple Photos album “{album}”": "Добавлено в альбом «{album}» Apple Фото: {n}",
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
@@ -127,6 +127,7 @@
   "Moved; {} photo(s) relinked": "Flyttat; {} foto(n) har länkats om",
   "Named ({named_n})": "Namngivna ({named_n})",
   "New Folder in “{name}”": "Ny mapp i ”{name}”",
+  "Created folder “{name}” in “{parent}”": "Mappen ”{name}” skapad i ”{parent}”",
   "new, inside {parent}": "ny, inuti {parent}",
   "none (CPU rendering): {why}": "ingen (CPU-rendering): {why}",
   "not added to Apple Photos: {e}": "inte tillagt i Apple Photos: {e}",
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
@@ -248,6 +248,7 @@
   "{what} merge cancelled": "Об’єднання {what} скасовано",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "Пропущено локальних фото: {n}{0:.0} — в альбомах лише фото з бібліотеки (спершу додайте їх до моїх фото)",
   "New Folder in “{name}”": "Нова тека в «{name}»",
+  "Created folder “{name}” in “{parent}”": "Теку «{name}» створено в «{parent}»",
   "Moved {} photo(s)": "Переміщено фото: {}",
   "not added to Apple Photos: {e}": "не додано до Apple Фото: {e}",
   "{n} added to Apple Photos album “{album}”": "Додано до альбому Apple Фото «{album}»: {n}",
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
@@ -134,6 +134,7 @@
   "Moved; {} photo(s) relinked": "Đã di chuyển; liên kết lại {} ảnh",
   "Named ({named_n})": "Có tên ({named_n})",
   "New Folder in “{name}”": "Thư mục mới trong «{name}»",
+  "Created folder “{name}” in “{parent}”": "Đã tạo thư mục «{name}» trong «{parent}»",
   "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",
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
@@ -252,6 +252,7 @@
   "{what} merge cancelled": "已取消 {what} 合并",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "已跳过 {n} 张本地照片{0:.0}：相册只能收录图库中的照片（请先添加到我的照片）",
   "New Folder in “{name}”": "在“{name}”中新建文件夹",
+  "Created folder “{name}” in “{parent}”": "已在“{parent}”中创建文件夹“{name}”",
   "Moved {} photo(s)": "已移动 {} 张照片",
   "not added to Apple Photos: {e}": "未添加到 Apple 照片：{e}",
   "{n} added to Apple Photos album “{album}”": "已将 {n} 个添加到 Apple 照片相册“{album}”",
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
@@ -252,6 +252,7 @@
   "{what} merge cancelled": "已取消{what}合併",
   "{n} Local photo{} skipped: albums hold library photos (Add to My Photos first)": "已略過 {n} 張本機照片{0:.0}：相簿只能收錄照片庫中的照片（請先加入我的照片）",
   "New Folder in “{name}”": "在「{name}」中新增資料夾",
+  "Created folder “{name}” in “{parent}”": "已在「{parent}」中建立資料夾「{name}」",
   "Moved {} photo(s)": "已移動 {} 張照片",
   "not added to Apple Photos: {e}": "未加入 Apple 照片：{e}",
   "{n} added to Apple Photos album “{album}”": "已將 {n} 個加入 Apple 照片相簿「{album}」",
diff --git a/crates/ui-egui/src/control.rs b/crates/ui-egui/src/control.rs
--- a/crates/ui-egui/src/control.rs
+++ b/crates/ui-egui/src/control.rs
@@ -414,7 +414,7 @@ pub fn handle(app: &mut LightcraftApp, ctx: &egui::Context, req: &ControlRequest
         "ui.dialog.confirm" => match app.ui.dialog.take() {
             Some(d) => {
                 let r = crate::panels::dialogs::confirm_dialog(app, &d);
-                // the import review and the rule editor stay open on an error, as with their buttons
+                // the import review, the rule editor and the one-line prompts stay open on an error, as with their buttons
                 if (r.is_err()
                     && matches!(
                         d,
@@ -423,6 +423,7 @@ pub fn handle(app: &mut LightcraftApp, ctx: &egui::Context, req: &ControlRequest
                             | crate::state::Dialog::SmartRules { .. }
                             | crate::state::Dialog::SaveEffect { .. }
                             | crate::state::Dialog::CaptureTime { .. }
+                            | crate::state::Dialog::TextPrompt { .. }
                     ))
                     || (r.is_ok() && crate::panels::dialogs::keeps_open(app, &d))
                     || (r.is_err() && crate::lightroom_destination::keeps_open_on_error(app, &d))
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
@@ -1440,6 +1440,16 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context, blocked: bool) {
                     *error = Some(e);
                 }
             }
+            // a one-line prompt that is refused stays open with its text, so the name can be fixed
+            Err(e) if matches!(dlg, Dialog::TextPrompt { .. }) => app.toast_error(ctx, e),
+            // a folder made on disk says so (the new folder holds no photos yet)
+            Ok(r) if matches!(&dlg, Dialog::TextPrompt { command, .. } if command == "folder.create") => {
+                if let Dialog::TextPrompt { params, .. } = &dlg {
+                    let (path, parent) = (r["path"].as_str().unwrap_or_default(), params["parent"].as_str().unwrap_or_default());
+                    app.toast(ctx, crate::panels::left::created_text(path, parent));
+                }
+                close = true;
+            }
             Ok(r) if matches!(dlg, Dialog::NewAlbum { .. }) && r.get("skipped").and_then(serde_json::Value::as_u64).is_some_and(|n| n > 0) => {
                 // albums hold library photos (issue #684): say which part of the selection stayed out
                 crate::panels::grid::toast_skipped(app, ctx, &r);
diff --git a/crates/ui-egui/src/panels/left.rs b/crates/ui-egui/src/panels/left.rs
--- a/crates/ui-egui/src/panels/left.rs
+++ b/crates/ui-egui/src/panels/left.rs
@@ -23,7 +23,7 @@ pub use albums::{album_drag_feedback, auto_scroll_speed};
 use albums::{albums_rows, drag_auto_scroll};
 pub(crate) use dates::browse_all_photos;
 use dates::date_rows;
-pub(crate) use folders::{folder_row_of, move_photos, moved_text};
+pub(crate) use folders::{created_text, folder_row_of, move_photos, moved_text};
 use folders::{folder_rows, reveal_chosen};
 use keywords::keyword_rows;
 pub(crate) use local::{fs_cached, fs_cached_running, same_folder};
diff --git a/crates/ui-egui/src/panels/left/folders.rs b/crates/ui-egui/src/panels/left/folders.rs
--- a/crates/ui-egui/src/panels/left/folders.rs
+++ b/crates/ui-egui/src/panels/left/folders.rs
@@ -482,6 +482,13 @@ pub(crate) fn moved_text(n: u64, name: &str) -> String {
     }
 }
 
+/// What `folder.create` of the folder at `path` inside `parent` says when it succeeds: the folder
+/// is on disk now, but it has no photos, so the Folders list may not show it yet.
+pub(crate) fn created_text(path: &str, parent: &str) -> String {
+    let name = std::path::Path::new(path).file_name().map_or_else(|| path.to_string(), |f| f.to_string_lossy().to_string());
+    crate::i18n::tr_format!("Created folder “{name}” in “{parent}”", name = name, parent = lightcraft_catalog::folders::folder_label(parent))
+}
+
 /// [`move_photos`], saying how it went in a toast.
 fn move_photos_here(app: &mut LightcraftApp, ctx: &egui::Context, ids: Option<&[u64]>, path: &str, name: &str) {
     match move_photos(app, ids, path) {
diff --git a/crates/ui-egui/src/tests.rs b/crates/ui-egui/src/tests.rs
--- a/crates/ui-egui/src/tests.rs
+++ b/crates/ui-egui/src/tests.rs
@@ -75,6 +75,7 @@ mod switch_library;
 mod sync;
 mod tallies;
 mod temp_slider;
+mod text_prompt;
 mod titlebar;
 mod tool_overlay;
 mod unsaved;
diff --git a/crates/ui-egui/src/tests/text_prompt.rs b/crates/ui-egui/src/tests/text_prompt.rs
new file mode 100644
--- /dev/null
+++ b/crates/ui-egui/src/tests/text_prompt.rs
@@ -0,0 +1,111 @@
+//! A one-line prompt that the engine refuses stays open with its text and says why, so the name can
+//! be fixed; a folder made on disk says it was made.
+
+use std::path::PathBuf;
+use std::time::Duration;
+
+use serde_json::json;
+
+use crate::headless::Headless;
+use crate::state::Dialog;
+use crate::{LightcraftApp, Services};
+
+const T: Duration = Duration::from_secs(20);
+const SETTLE: Duration = Duration::from_secs(60);
+const CREATED: &str = "Created folder “{name}” in “{parent}”";
+
+/// A fresh `Shoot` folder holding `Taken` and `Other`, in a temporary folder of its own.
+fn shoot(tag: &str) -> PathBuf {
+    let root = std::env::temp_dir().join(format!("lc-text-prompt-{tag}-{}", std::process::id()));
+    let _ = std::fs::remove_dir_all(&root);
+    let shoot = root.join("Shoot");
+    for name in ["Taken", "Other"] {
+        std::fs::create_dir_all(shoot.join(name)).unwrap();
+    }
+    shoot
+}
+
+/// Remove the temporary folder `shoot` made, which holds `dir`.
+fn clean(dir: &std::path::Path) {
+    let _ = std::fs::remove_dir_all(dir.parent().unwrap());
+}
+
+fn app() -> Headless {
+    let session = lightcraft_engine::Session::new().with_fs();
+    let mut h = Headless::new(LightcraftApp::new(session, Services { png: None, ..Default::default() }), [1300.0, 900.0], 1.0);
+    h.settle(SETTLE);
+    h
+}
+
+fn prompt(command: &str, value: &str, params: serde_json::Value, key: &str) -> Dialog {
+    Dialog::TextPrompt { title: "Title".into(), hint: "Name".into(), value: value.into(), command: command.into(), params, key: key.into() }
+}
+
+/// Open `dialog`, press its OK button, and let the frame settle.
+fn confirm(h: &mut Headless, dialog: Dialog) {
+    h.app.ui.dialog = Some(dialog);
+    for _ in 0..4 {
+        h.step();
+    }
+    let r = h.request("ui.clickWidget", json!({"id": "button:dialogOk"}), T);
+    assert_eq!(r["ok"], true, "{r}");
+    h.settle(SETTLE);
+}
+
+fn toast(h: &Headless) -> String {
+    h.app.ui.toast.as_ref().map(|(t, _, _)| t.clone()).unwrap_or_default()
+}
+
+fn assert_stays_open(h: &Headless, value: &str, reason: &str) {
+    match &h.app.ui.dialog {
+        Some(Dialog::TextPrompt { value: kept, .. }) => assert_eq!(kept, value, "the typed text is kept"),
+        other => panic!("the prompt stays open: {other:?}"),
+    }
+    assert!(toast(h).contains(reason), "the reason is shown: {:?}", toast(h));
+}
+
+#[test]
+fn a_new_folder_whose_name_is_taken_keeps_the_prompt_open_and_says_why() {
+    let dir = shoot("create-taken");
+    let mut h = app();
+    confirm(&mut h, prompt("folder.create", "Taken", json!({"parent": dir.to_string_lossy()}), "name"));
+    assert_stays_open(&h, "Taken", "already exists");
+    clean(&dir);
+}
+
+#[test]
+fn a_rename_to_a_taken_name_keeps_the_prompt_open_and_says_why() {
+    let dir = shoot("rename-taken");
+    let mut h = app();
+    confirm(&mut h, prompt("folder.rename", "Taken", json!({"path": dir.join("Other").to_string_lossy()}), "name"));
+    assert_stays_open(&h, "Taken", "already exists");
+    assert!(dir.join("Other").is_dir(), "nothing was renamed");
+    clean(&dir);
+}
+
+#[test]
+fn a_new_folder_closes_the_prompt_and_says_where_it_is() {
+    let dir = shoot("create-ok");
+    let mut h = app();
+    confirm(&mut h, prompt("folder.create", " Selects ", json!({"parent": dir.to_string_lossy()}), "name"));
+    assert!(dir.join("Selects").is_dir(), "made on disk");
+    assert_eq!(h.app.ui.dialog, None);
+    let parent = lightcraft_catalog::folders::folder_label(&dir.to_string_lossy());
+    assert_eq!(toast(&h), CREATED.replace("{name}", "Selects").replace("{parent}", &parent));
+    clean(&dir);
+}
+
+#[test]
+fn the_created_folder_toast_comes_through_the_catalog() {
+    let dir = shoot("create-de");
+    let path = dir.join("Selects");
+    let parent = lightcraft_catalog::folders::folder_label(&dir.to_string_lossy());
+    let catalog: std::collections::BTreeMap<String, String> = serde_json::from_str(include_str!("../../locales/de-formats.json")).unwrap();
+    let want = catalog[CREATED].replace("{name}", "Selects").replace("{parent}", &parent);
+    crate::i18n::set_language(crate::i18n::Locale::De);
+    let text = crate::panels::left::created_text(&path.to_string_lossy(), &dir.to_string_lossy());
+    crate::i18n::set_language(crate::i18n::Locale::En);
+    assert_ne!(want, CREATED.replace("{name}", "Selects").replace("{parent}", &parent), "German has its own wording");
+    assert_eq!(text, want);
+    clean(&dir);
+}
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 (LR-BEHAV-DIALOGS: a one-line prompt that is refused stays open and says why, and a New Folder on Disk says it was made; 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
@@ -468,7 +468,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
 | LR-BEHAV-RENDER-FIDELITY | Rendering matches Lightroom | P1 | 🟡 | `crates/pipeline/src/lib.rs`, `crates/pipeline/src/tone.rs` | every slider exists and works, but the character of the result (tone curve shape, highlight recovery, texture / clarity / dehaze, noise reduction, sharpening, default look) is tuned by eye; there is no systematic side-by-side comparison against Lightroom on the same CC0 raws. Needs a fidelity suite: Lightroom reference renders kept only in the local `plan/` (never committed), compared per slider and preset with a perceptual metric. Tuning that changes how existing settings render ships as a new process version (LRC-DEV-PROCESS, `docs/process-versions.md`) |
 | LR-BEHAV-DRAGDROP | Drag and drop | P1 | ✅ | `crates/ui-egui/src/lib.rs`, `crates/ui-egui/src/panels/grid.rs` (`drag_feedback`), `crates/ui-egui/src/panels/left.rs` (`drop_target`, `album_drag_over`, `top_level_drop_target`, `drag_auto_scroll`) | files → app (a drop-target card while they hover, then the import review); grid photos → an album row (adds the selection, with a count badge while dragging); sidebar album / folder rows → a folder (moves it; its name follows the pointer); a drag of albums or grid photos near the top or bottom edge of the sidebar scrolls it (faster nearer the edge, only while the pointer is over the sidebar) |
 | LR-BEHAV-TOAST | Toast notifications | P1 | ✅ | `crates/ui-egui/src/panels.rs` | |
-| LR-BEHAV-DIALOGS | Dialogs fit the window | P1 | ✅ | `crates/ui-egui/src/dialogs.rs` (`dialog_body`, `list_height`), `crates/ui-egui/src/tests/dialog_fit.rs`, `crates/ui-egui/src/tests/dialogs.rs` (`a_click_outside_closes_the_dialog_when_settings_allow_it`) | a dialog taller than the window (Export on a 1366×768 screen, issue #781) never runs off it: its options scroll while the title bar and the Cancel / OK row stay on screen; lists that scroll on their own (What's New, All Metadata, shortcuts, smart-album rules, credits) get shorter first; dialogs that fit look as before; Import keeps its own resizable, scrolling window; Settings → Dialogs → Close a dialog by clicking outside it (off by default, so a stray click never throws away a dialog's choices): a click pressed and released on the dimmed backdrop closes the dialog like Esc and doesn't reach the panels below, while a drag that ends outside (a slider pulled past the edge) or a click that closes a dropdown keeps it; the import review never closes this way (`clicked_backdrop`) |
+| LR-BEHAV-DIALOGS | Dialogs fit the window | P1 | ✅ | `crates/ui-egui/src/dialogs.rs` (`dialog_body`, `list_height`), `crates/ui-egui/src/tests/dialog_fit.rs`, `crates/ui-egui/src/tests/dialogs.rs` (`a_click_outside_closes_the_dialog_when_settings_allow_it`) | a dialog taller than the window (Export on a 1366×768 screen, issue #781) never runs off it: its options scroll while the title bar and the Cancel / OK row stay on screen; lists that scroll on their own (What's New, All Metadata, shortcuts, smart-album rules, credits) get shorter first; dialogs that fit look as before; Import keeps its own resizable, scrolling window; Settings → Dialogs → Close a dialog by clicking outside it (off by default, so a stray click never throws away a dialog's choices): a click pressed and released on the dimmed backdrop closes the dialog like Esc and doesn't reach the panels below, while a drag that ends outside (a slider pulled past the edge) or a click that closes a dropdown keeps it; the import review never closes this way (`clicked_backdrop`); a one-line prompt (Rename Folder, New Folder on Disk, the preset and version names, New Library when its name can't be used, Auto-Tag from Tracklog) the engine refuses stays open with its text and shows the reason in a toast, so the name can be corrected, where it used to close without a word; a New Folder on Disk that works says so (“Created folder “Selects” in “2026/Shoot””, naming the parent by its last two folders as dialogs do) |
 | LR-BEHAV-SIDEBAR-COLLAPSE | Collapsible left-sidebar sections | P2 | ✅ | `crates/ui-egui/src/panels/left.rs` (`section`, `section_header`), `crates/ui-egui/src/sidebar.rs` (`SidebarLayout`), `crates/ui-egui/src/tests/panels.rs` | click the Albums, Local, By Date, Folders or Keywords header (or drive `ui.clickWidget` `sidebarSection:<albums\|local\|byDate\|folders\|keywords>`) to fold or unfold the section; a chevron before the title shows the state; the choice is kept across restarts (`sidebar` in the UI state; the `collapsedSidebar` list of older settings files is still read). the click itself is UI-only, like the By Date / Keywords disclosure triangles, and `cmd:view.sidebarSection` `{section, collapsed}` folds and unfolds for agents; photos dropped on a folded Albums section have no target |
 | LR-BEHAV-SIDEBAR-SECTIONS | Left-sidebar sections share one frame and one arrangement | P2 | ✅ | `crates/ui-egui/src/sidebar.rs` (`SidebarSection`, `SidebarLayout`), `crates/ui-egui/src/panels/left.rs` (`section`, `section_header`, `tree_toggle`), `crates/ui-egui/src/tests/panels.rs` | Albums, Local, By Date, Folders and Keywords are drawn by one `section` frame (the same gap above, header, fold and accessibility name) from one arrangement, `sidebar` in the UI state: a list of `{id, hidden, collapsed}` top to bottom, also settable with `ui.set`. Whatever is read, every section is in it exactly once (unknown and repeated entries are dropped, the rest follow in the usual order), so a damaged or newer settings file never loses the other settings. Rows that open (album folders, Local folders, dates, library folders, keywords) share `tree_toggle`: the same triangle, the same remembered open state, announced as Expand / Collapse. A section with nothing to list (Folders before anything is imported, Keywords before any is added) stays, open, with a one-line note in place of rows (`sidebarEmpty:<id>`) instead of disappearing. `ui.set` reads `sidebar` strictly (`SidebarLayout::parse`): an unknown or repeated section, or a flag that is not true / false, is refused and changes nothing; sections left out follow in the usual order, shown and open; the older `collapsedSidebar` list still folds and unfolds. A section may have one button at the end of its header, declared in one place (`header_button`: an icon, a tooltip, and either an action or a menu): the frame draws it at the visible edge in the header and its pinned copy, keeps its click from folding the section and leaves it room beside a folded section's count. Albums has + (`icon:albumNew`: Create Album / Smart Album / Folder…), Keywords has + (`icon:keywordNew`: Create Keyword Tag, for a keyword inside the default parent, not inside what the Keyword List has picked; once made, Keywords is shown and opened down to it). My Photos (All Photos, Recently Added, Picks, Missing Photos, Recently Deleted) is not a section: it stays on top |
 | LR-BEHAV-SIDEBAR-HIDE | Show and hide left-sidebar sections | P2 | ✅ | `cmd:view.sidebarSection`, `cmd:view.sidebarReset`, `crates/ui-egui/src/sidebar.rs`, `crates/ui-egui/src/panels/left.rs` (`sections_menu`), `crates/ui-egui/src/menus/menubar.rs`, `crates/ui-egui/src/tests/panels.rs` | View ▸ Sidebar Sections lists Albums, Local, By Date, Folders and Keywords in the sidebar's order, each checked while shown; unchecking one takes its header and rows off the sidebar, checking it puts it back where and how it was (still folded if it was). The same list opens with a right-click on any section header (with Hide This Section first; widgets `sidebarMenu:hide`, `sidebarMenu:section:<id>`, `sidebarMenu:reset`) and on the My Photos title (`sidebarTitle`), which is always there, so hidden sections can always come back. Reset Sidebar Sections (enabled once something changed) shows and opens every section in the usual order. `view.sidebarSection` `{section, show?, collapsed?}` flips shown / hidden when neither flag is given and refuses an unknown section or a flag that is not true / false. Hiding the section of what the grid shows (an album, a keyword filter) leaves the grid as it is; an album made while Albums is hidden or folded brings Albums back, open. Kept with the UI state (`sidebar`). My Photos itself can't be hidden |
@@ -959,3 +959,4 @@ Latin stays upright. Advanced Japanese composition remains open. Regression cove
 | 2026-10-23 | patch | LR-BEHAV-ACCESS: the name field of New Album, New Smart Album, Rename and the other one-field dialogs takes the keyboard focus once when the dialog opens instead of every frame, so Tab and Shift+Tab reach the check box, Cancel and OK; status unchanged (🟡) |
 | 2026-10-22 | minor | LR-CROP-AUTO: Auto straighten turns by at most 10° and only on at least 3 agreeing lines, and says when it finds nothing to level by; measured on 68 photos straightened by hand and 300 left as shot, unwanted turns of more than 1° fell from 79 to 19 of the 300. Downgraded ✅ → 🟡: it still leaves most tilted photos alone |
 | 2026-10-23 | patch | LRC-LIB-FILTERBAR: showing an album (`library.source`) while the filter holds an album drops the filter's album, as showing a library folder already dropped its folder filter; before, the old album stayed in the filter unseen (the filter bar has no album chip) and narrowed the next source such as All Photos; the row's note says so; status unchanged (✅) |
+| 2026-10-27 | patch | LR-BEHAV-DIALOGS: a one-line prompt the engine refuses (a name already taken, a bad time zone) stays open with the typed text and shows the reason, instead of closing silently; a New Folder on Disk that works shows “Created folder “…” in “…””; status unchanged (✅) |
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,13 @@
 # What's new in LightCraft
 
+## 2026-10-27
+
+### A refused name prompt stays open and says why
+- A one-line prompt (Rename Folder, New Folder on Disk, the preset and version names, New Library for a name it can't
+  use, Auto-Tag from Tracklog) that the app refuses, for example a folder name that is taken, now stays open with what
+  you typed and shows the reason, so you can change the name. Before, it closed without a word. A New Folder on Disk
+  that works now says so: “Created folder “Selects” in “2026/Shoot””. Cancel and Esc still close the prompt.
+
 ## 2026-10-24
 
 ### Relative-date filters and smart albums follow the clock
