* UI: the application bar uses craft-window's title bar
DesignCraft's title-bar code moved to craft-libs as craft_window::title_bar.
The application bar calls it instead of its own copy, and the macOS shell
takes sync_movable from it. Differences: a drag on an in-window panel lying
over the bar no longer moves the window, full screen ignores the bar's drag
and double-click, and floating panels in their own windows keep their own
movable flag.
* UI: craft-window from craft-libs main
* UI: the application bar ignores the title bar's response
Found while testing crates/geom/src/units.rs:~147 (Unit::ruler_ticks, the `while major * zoom < 50.0` loop)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/mcp/src/server.rs:62-64 (Server::serve)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A duplicated text frame holding an anchored placed PDF leaves two placements sharing one ItemId, so the raw update count exceeded the variant count and a correct export failed. The guard now checks that every mapped id was reached. Replaces the mismatch test with a duplicated-frame export regression.
* Styles: renaming a style keeps its Export Tagging
Renaming a paragraph or character style, or moving it into a style
group, moves its Export Tagging to the new name. Deleting a style drops
its tagging and leaves the replacement's own tagging unchanged.
* Styles: a paragraph style can't be renamed onto another style's name
* Styles: a refused rename says the name is taken and shows the General section
Renaming a paragraph or character style onto a name another style has
now says so ("a paragraph style named `Body` already exists"); empty
or bracketed names keep the generic message. The Paragraph Style Options
dialog switches to General, where the name field is, when the rename is
refused. Paragraph style names are trimmed like character style names,
and a renamed style never picks up an export tag left under its new name.
* Styles: the rename test's stale tagging takes the Split Document field
* ROADMAP: date the style rename line 2026-10-24
* Search: Delete Workspace is left out of Quick Apply and command search
It needs a saved workspace's name, which a search entry can't supply,
so choosing it there failed. The application bar's workspace menu lists
the saved workspaces to delete.
* Search: leave out the interface commands that fail or reset a setting there
Quick Apply and the application bar's search ran their entries without
parameters. Commands that need a workspace, a command and shortcut, a
menu item, a panel, a window edge, an app page, a recent file, or a
swatch or color group failed when chosen there. Interface Color Theme
and UI Scaling switched to the dark theme and 100%, Workspace switched
to Essentials, and Reset Shortcuts cleared every custom shortcut without
asking. Search leaves all of them out; each stays in the menu, panel or
dialog that gives it the value.
* Search: the flattener preset, Screen Mode, Zoom To and the Task Bar pin stay out of Quick Apply
The report asks for a placement the export walk reaches whose asset is still a PDF, so it cannot
name a choice anchored inside a table cell or a note. The paragraph now says that rather than
leaving the scope to the sentence above.
The placed-PDF doc said every placement counts. Both exports and the PDF/A-2b rasterisation pass
walk document and parent spreads, groups and objects anchored in a story; a placement anchored
inside a table cell's or a footnote's text is not reached yet, so the doc now says what happens
to it instead of claiming it is carried. Gap 19 states the same boundary in one line.
The parent-page regression covers a placement a page inherits. The other placement the export
walks reach is an object anchored in a story: the IDML copy gets a variant that shows every
layer, an external-only copy is refused, and PDF/A-2b rasterises it and warns. The nested-story
regression that used to cover this case also asserted placements anchored inside a table cell and
a footnote, which this pass does not reach; this one keeps the anchored case alone.
Both exports walk Document::placed_items: document and parent spreads, groups, and the objects
anchored in a story. That is the walk the parent-page and anchored fix introduced. The
nested-story traversal (table cells, notes, endnotes), Document::update_placed_items and the
fail-closed refusals that went with it are not part of it: that is the traversal change on its
own, not the placements this pass carries. update_items keeps its reach, so the two exports clear
the choice where the placement actually is again.
A choice anchored inside a table cell's or a note's text therefore stays on the document and is
not carried into the embedded IDML copy, as on main; the refusal that turned that silent
difference into an export error goes with the traversal it guarded, since asking the walk's own
predicate it could never fire. The stale-field half keeps: has_applicable_pdf_layer_overrides
still asks for a graphic whose asset is a PDF, so relinking a placed PDF to an image no longer
makes the package report name a choice that does not exist.
Tests: the nested-placement regression and the relink integration test of the removed refusal
go; the parent-page regression, the stale-field predicate test and the format 4 cell-only reader
test stay. The comments no longer claim every placement counts.
Graphic gained an optional layer_options field, so the test-only literals in the PDF
crate and in the engine's optional-content support need it. No behaviour changes.
The workspace file guard scans test modules too when they are declared `pub(crate) mod` (it only
skips a plain `mod`), so a temp file written inside pdflayers.rs' tests failed
no_crate_touches_the_file_system_outside_the_checked_readers. The unit test now builds the state a
relink leaves behind - layer fields on an item whose asset is an image - and asserts the refusal
predicate ignores it while all three exports run. The user path (a real links.relink to a PNG) moves
to tests/pdf_optional_content.rs, where the guard exempts fixtures written by test files.
a_missing_link_shown_by_its_preview_is_still_reported builds its link
under std::env::temp_dir(). On macOS and Linux that returns TMPDIR as
set, so a relative TMPDIR gave a relative link, which document_path
refuses in a document without a path, and the test failed with
"(the path is not valid)". The test now passes the temporary folder
through std::path::absolute first. The preflight code is unchanged.
Comment-only: the refusal in both exports cannot fire while the walk and the predicate cover the
same placements, so the comments now say it is a tripwire for a future nesting construct and ask
nobody to narrow the walk to match it.