diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md
index 9afb1f35..92af4f15 100644
--- a/ATTRIBUTION.md
+++ b/ATTRIBUTION.md
@@ -4,7 +4,7 @@
Every asset PrintCraft includes, bundles or uses to build its published material, with its author, source and licence. The policy is in [AGENTS.md](AGENTS.md) §1. The machine-readable list, with SHA-256 hashes, is [ATTRIBUTION.toml](ATTRIBUTION.toml). Licence texts are kept beside the assets and summarised in [NOTICE](NOTICE).
-## In this repository (215)
+## In this repository (217)
| Asset | Title | Author | Licence | Source | Used for |
|---|---|---|---|---|---|
@@ -12,6 +12,8 @@ Every asset PrintCraft includes, bundles or uses to build its published material
| `assets/icons/align-left.svg` | Lucide icon "align-left" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/align-left.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
| `assets/icons/align-center.svg` | Lucide icon "align-center" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/align-center.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
| `assets/icons/align-right.svg` | Lucide icon "align-right" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/align-right.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
+| `assets/icons/columns-3.svg` | Lucide icon "columns-3" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/columns-3.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
+| `assets/icons/rows-3.svg` | Lucide icon "rows-3" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/rows-3.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
| `assets/icons/app-window.svg` | Lucide icon "app-window" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/app-window.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
| `assets/icons/arrow-left-right.svg` | Lucide icon "arrow-left-right" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/arrow-left-right.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
| `assets/icons/arrow-up-down.svg` | Lucide icon "arrow-up-down" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/arrow-up-down.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
diff --git a/ATTRIBUTION.toml b/ATTRIBUTION.toml
index f87e63af..058fba17 100644
--- a/ATTRIBUTION.toml
+++ b/ATTRIBUTION.toml
@@ -52,6 +52,28 @@ kind = "icon"
usage = "UI icon, embedded via crates/ui-egui/src/icon_data.rs"
sha256 = "70ef15bcaa5721820aef032ad1e65370fb2667fd2e2d63eb24fbf3c2f57346cc"
+[[asset]]
+path = "assets/icons/columns-3.svg"
+title = "Lucide icon \"columns-3\""
+author = "Lucide Contributors (portions Cole Bemis, Feather)"
+source = "https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/columns-3.svg)"
+licence = "ISC"
+licence_file = "assets/icons/LICENSE-lucide.txt"
+kind = "icon"
+usage = "UI icon, embedded via crates/ui-egui/src/icon_data.rs"
+sha256 = "54f7a2f2c3ffe9c0f13189e85571192651aaafe1eea0726de97701f67921aafb"
+
+[[asset]]
+path = "assets/icons/rows-3.svg"
+title = "Lucide icon \"rows-3\""
+author = "Lucide Contributors (portions Cole Bemis, Feather)"
+source = "https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/rows-3.svg)"
+licence = "ISC"
+licence_file = "assets/icons/LICENSE-lucide.txt"
+kind = "icon"
+usage = "UI icon, embedded via crates/ui-egui/src/icon_data.rs"
+sha256 = "401a4ceb06a88210638e3264e05f2a5281acad42df5c96363160db75f7fd105a"
+
[[asset]]
path = "assets/icons/app-window.svg"
title = "Lucide icon \"app-window\""
diff --git a/assets/icons/columns-3.svg b/assets/icons/columns-3.svg
new file mode 100644
index 00000000..fad45b61
--- /dev/null
+++ b/assets/icons/columns-3.svg
@@ -0,0 +1,17 @@
+
+
diff --git a/assets/icons/rows-3.svg b/assets/icons/rows-3.svg
new file mode 100644
index 00000000..48276e11
--- /dev/null
+++ b/assets/icons/rows-3.svg
@@ -0,0 +1,17 @@
+
+
diff --git a/crates/automation/src/forms.rs b/crates/automation/src/forms.rs
index 92d7261a..0c8e5e77 100644
--- a/crates/automation/src/forms.rs
+++ b/crates/automation/src/forms.rs
@@ -41,6 +41,52 @@ fn format_arg(v: &Value) -> Result {
})
}
+/// `{"border": "#FF0000" | "none", "fill": …, "width": 1-3, "style": "solid"|…, "text_color": …,
+/// "font": "helvetica"|"times"|"courier"}`, changing only what is given.
+fn look_arg(v: &Value, mut l: printcraft_engine::FieldLook) -> Result {
+ use printcraft_engine::{BorderStyle, FieldFont};
+ let o = v.as_object().ok_or_else(|| bad("appearance must be an object"))?;
+ let colour = |k: &str| -> Result