- a_faces_seam_stays_within_half_its_width_of_the_face checks Rotate
(Classic)'s branches too: No Shading keeps its paint, a gradient keeps
the gradient, and Diffuse shades its plane darker at some view.
- classic_revolves_seams_are_round checks each seam's reach as well as
its join, and covers a gradient.
- The Wireframe edge takes seam_stroke (the same stroke it built by hand).
- Docs: which seams went from miter to round and which already were;
the white-light difference from the 2026-10-17 comparison is expected,
not measured; the 3D area rows record the change; the performance note
says its measurement predates the Classic Rotate and Revolve paths.
- Under a perspective, the shared 400,000-element limit of a 3D effect's graphics now counts
what each path draws once mapped: a straight side stays one element, and only curves count
as their 8 pieces. Two copies of a 30,000-sided polygon now both draw. The symbol check
counts the same way, and without a perspective it counts each curve once.
- The Materials tab's handles on the artboard are hidden while a geometry effect (such as
Transform) comes after the 3D effect of a selected object, since that effect draws the
graphics away from the handles.
- A press on the canvas while its context menu is open only closes the menu, and no longer
grabs a graphic's handle.
- A symbol instance inside a graphic's art shows its changes to a dynamic symbol, and a symbol
with 9-slice guides is placed through them, as the canvas draws the instance. Paths that
cross a guide are cut at it.
Pin craft-ui to c4b8405d, which adds a top edge and the canvas-side top
corner to icon-strip flyouts and saves the moved top per group. Accept
its new MoveFlyoutTop docking action, and restore the saved top when a
group returns to its place. A docking regression checks the cursors, an
upward top-edge and free-corner drag with the bottom and icon-column edge
fixed, and the top after reopening and in a saved layout.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Codex <codex@openai.com>
Each 3D facet is stroked with a narrow seam of its own paint (0.05 to
0.75 pt; Revolve's is always 0.75 pt) so neighboring facets meet without
an antialiasing hairline. In Extrude & Bevel, Inflate and Rotate under a
white light, and in every face of the 3D (Classic) effects (Extrude &
Bevel, Rotate and Revolve (Classic); shaded, No Shading, gradient and
pattern alike), that seam kept the default Miter Join with its limit
of 10. Revolve's seams and the colored-light seams
were already round. A facet seen almost edge-on is a sharp sliver, and
its mitered seam reached up to ten times its half-width past the facet's
tip: thorns of up to 3.75 pt past the solid, along the tops of type seen
tilted and at every edge-on bevel facet.
#2706 (multiple lights) deliberately kept white-light seam joins as they
were, so that legacy white-light output stayed byte-identical to main
(its comment "Preserve existing white-light paints, alpha composition and
seam joins exactly", and four PNGs compared byte for byte). That kept
the thorns too. This change reverses that one part on purpose: the
paints and alpha composition stay exactly as #2706 left them; only the
join changes.
- Outputs change, the document model doesn't. Exports draw the new
joins (SVG writes stroke-linejoin="round", PDF and .ai draw round
joins), and Expand Appearance writes round seams into the document.
But nothing a document stores selects the join, and the format is
unchanged, so there is no version gate: an old file drawn now simply
has no thorns.
- Round joins. Projected facets rarely have right-angle corners (a
square seen at an angle is a parallelogram with acute corners, and an
exact 90° corner sits at a √2 limit), and round is what the seams of
colored lights and Revolve already draw. The cost: where a facet has
no neighbor (Rotate's plane, every silhouette corner) its convex
corners are drawn rounded by up to 0.375 pt instead of sharp.
Alternatives weighed and not taken: a Miter Join with a limit near √2
at every seam, the composed clip included, which would bevel slivers
but chamfer most projected corners as well; and seaming only the edges
facets share, or clipping facets to their union as solid_surface
does, which would keep every outer corner sharp but means a new
geometry pass for every 3D effect. Round is the smallest change that
matches the seams already drawn.
- A seam no longer reaches past its facet by more than half its width,
so the art's visual bounds shrink by up to 3.375 pt where a thorn
stood (10 × 0.375 less the 0.375 a round seam still reaches).
White-light output is no longer byte-identical to #2706's comparison;
docs/3d-lighting-performance.md says so.
Every seam stroke is made by lighting::seam_stroke. The colored clip in
composed_art already outlined its seam with round joins and is
unchanged. Tests: every seam of Extrude & Bevel, Extrude & Bevel (Classic, each
branch), Rotate (Classic), Inflate and Rotate, under white and colored
light, has round joins and reaches no more than half its width past its
face, at views that make a sliver; Revolve (Classic)'s seams are round
on each surface; a mitered seam fails them, and so does the legacy
white-light Inflate test, which now expects Round.
The Brushes rows name each type as the New Brush dialog does (Art Brush,
Scatter Brush) and say "missing from the Brushes panel" for a brush the
panel does not hold. The panel now shows these values through the
catalogs, so a localized interface no longer shows them in English.
document.info and the saved report keep them in English. Every catalog
gets a row for "missing from the Brushes panel"; the type names already
had rows.
View > Proof Setup > Working CMYK simulates the working CMYK space of
Color Settings in Proof Colors and Separations Preview, also in a
document assigned another CMYK profile. The active context keeps the
working context beside the assigned profiles, and the proof table cache
key includes the working settings, so a change of the working CMYK space
shows in the next proof.
With automation read roots in force, document.json returned each entry of
svg_scripts unchanged, so a JavaScript file linked from outside the read
roots kept its full path in the reply. The reply copy now names such a
file by its file name alone. An entry given as a URL is kept, and the
stored document is not changed.
- object.expand.info reports no gradient or fill to expand for a
gradient that repeats in more runs across its box than are written,
matching object.expand, which leaves it a gradient. For a path that a
painting live effect draws, it measures each piece the effect returns.
- CSS writes a repeating gradient's stop positions, and a repeating
radial gradient's radius, with enough decimals that their rounding
adds up to at most a hundredth of a period across the box (at least
four for positions and three for the radius).
- docs/mcp.md says that sharp steps and swatch-linked stops are the last
to be left out rather than always kept, and that the CSS conic limit
counts stops before midpoints and Perceptual curves add more.
A stroke at an opacity of 0 draws nothing, so its brush is no longer
listed in the Brushes category, brushNames or brushes. Pattern Objects,
Gradient Objects and Spot Color Objects likewise leave out fills and
strokes at an opacity of 0, and Objects no longer counts objects whose
only such paint is at opacity 0.
A reply hid a hidden library's absolute path wherever it appeared, also
inside another loaded library's id when the match began after the id's
start. With `/libs/Kit.gpl` hidden, the readable id
`loaded//project/libs/Kit.gpl` came back as `loaded//projectKit.gpl`,
and a request that used it failed.
Each whole readable id in a reply (with or without `loaded/`, or in a
`file:` URL with no host or `localhost`) is now found first, and a
hidden id or path that lies inside it stays. The same path after a
drive or in a URL with another host is still hidden.