# Logical layout `internal/layout.Layout(root, Options{Width, Height, TextEngine})` accepts a transient tree of `Node{ID, Kind, Style, Children, Content, ImageSize, Measure, ScrollX, ScrollY}`. Styles are borrowed immutable `*css.Style` values from `css.Engine.Compute` (normally compiled with `css.UA()`). A nil style receives minimal block defaults; use computed CSS for complete visual defaults. IDs are supplied by the frame-tree adapter and should be unique. Input must be acyclic, with depth at most 256; no renderer resources or parent pointers are retained. The caller owns the decoded images: use `internal/image.Decode` for bounded PNG/JPEG bytes or `internal/image.Size` for existing Go images, then put the intrinsic size on the node. Byte input must itself be bounded by the reader before decoding. `Kind` differentiates image/text intrinsic measurement, Stack overlay, and Scroll clipping. Flex is selected by the computed `display:flex`, with row/column UA defaults overridable by author CSS. Block children flow vertically; Stack children share the origin, paint in input order, and hit-test in reverse order. Flex supports row/column, wrap, grow/shrink/basis, row/column gaps, align-self/items and justify-content. CSS `px` is logical; computed `em`/`rem` have already become `px`; `%` dimensions use the containing content box and padding/margins use containing width. Auto width fills the containing width except images; auto height fits the children. Oversized/negative/nonfinite geometry is clamped to bounded logical coordinates. CSS `display:none` drops a subtree. Overflow hidden/auto/scroll emits a content clip per axis, leaving visible axes unbounded; only scroll/auto (or Scroll kind) consumes offsets, clamped to the measured content extent. The caller supplies offset; there is no scroll event policy here. `Output.Tree` is JSON-safe geometry and measured content extent. `Output.Display` contains ordered JSON-safe commands (`shadow`, `rect`, `border`, `outline`, `clip-push`, `text`, `image`, `clip-pop`). Glyph rune-cluster offsets and shaped glyph positions are copied to text commands. Each display-list `Run` also borrows its shaped `*text.Face` for in-process rasterization and carries serializable `FaceID` and `Size` (the logical font size used for shaping). `Face` is omitted from JSON; decoding JSON alone cannot reconstruct a face, so a renderer consuming serialized commands must resolve `FaceID` to a matching font before rasterizing. The original `text.Line` values remain on tree nodes for in-process use and are omitted from JSON. Image commands reference node IDs; the renderer adapter resolves their pixels. `Hit` applies ancestor clips and reverse child order. Pointer capture, focus and tab ordering are separate runtime responsibilities. `Physical` independently rounds logical rectangle edges using a fractional Wayland scale at the renderer boundary; do not use physical coordinates for hit tests. JSON snapshots under `internal/layout/testdata` validate tree and list structure, not rendered pixels. `Options.Arena` supplies reusable storage for the tree and display list. An `Output` is valid until its arena is passed to `Layout` again; the runtime alternates two arenas so the committed layout stays readable while the next frame is laid out. The superseded layout, including its images and text, stays reachable until the next build reuses its arena. Without an arena, `Layout` returns a detached `Output`. Known bounds: layout does not implement CSS margin collapse, absolute positioning, baseline alignment, `align-content`, or CSS transforms. Shadow and border commands carry geometry/style data for the renderer; decoration rasterization is not owned here. Text requires a provided `text.Engine` or a synchronous measure callback. Computed line-height repositions shaped baselines, text-align offsets runs within each content line, and letter-spacing is applied to shaped clusters before the text engine wraps (via the additive `text.Request.LetterSpacing` option). A synchronous callback's result must be immutable for the duration of layout; do not share a mutable shaping engine across goroutines.