monowind 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ascii.d.ts.map +1 -1
- package/dist/cdn.js +37 -25
- package/dist/cdn.js.map +1 -1
- package/dist/element.d.ts +5 -2
- package/dist/element.d.ts.map +1 -1
- package/dist/flex.d.ts +47 -0
- package/dist/flex.d.ts.map +1 -0
- package/dist/grid.d.ts +104 -0
- package/dist/grid.d.ts.map +1 -0
- package/dist/index.js +1893 -477
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +75 -24
- package/dist/layout.d.ts.map +1 -1
- package/dist/metrics.d.ts +10 -2
- package/dist/metrics.d.ts.map +1 -1
- package/dist/positioning.d.ts +10 -0
- package/dist/positioning.d.ts.map +1 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/style.d.ts +32 -2
- package/dist/style.d.ts.map +1 -1
- package/dist/tree.d.ts +19 -15
- package/dist/tree.d.ts.map +1 -1
- package/dist/types.d.ts +253 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/wrap.d.ts +62 -12
- package/dist/wrap.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/styles.css +137 -10
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#shadow","#decorations","#resizeObserver","#scheduleLayout","#mutationObserver","#suppressMutations","#isOwnedMutation","#cellMetrics","#onFontsLoaded","#layoutPending","#performLayout"],"sources":["../src/metrics.ts","../src/wrap.ts","../src/layout.ts","../src/borders.ts","../src/render.ts","../src/style.ts","../src/types.ts","../src/tree.ts","../src/element.ts","../src/ascii.ts"],"sourcesContent":["import type { CellMetrics } from \"./types.ts\";\n\n/** Round to nearest integer, ties away from zero (per specs/cell-model.md). */\nexport function roundHalfAwayFromZero(value: number): number {\n const rounded = value >= 0 ? Math.floor(value + 0.5) : -Math.floor(-value + 0.5);\n return rounded || 0; // normalize -0 → 0\n}\n\n/** Convert a computed px value to cells using the spacing scale (1 cell = 0.25rem). */\nexport function pxToCells(px: number, rootFontSizePx: number): number {\n if (rootFontSizePx <= 0) return 0;\n return roundHalfAwayFromZero(px / (0.25 * rootFontSizePx));\n}\n\n/** Convert a percentage of an integer container to whole cells, ties away from zero. */\nexport function percentToCells(percent: number, containerCells: number): number {\n return roundHalfAwayFromZero((containerCells * percent) / 100);\n}\n\n/** Measure the width of a monospace character and the line-box height. */\nexport function measureCellMetrics(host: HTMLElement): CellMetrics {\n const probe = document.createElement(\"span\");\n probe.setAttribute(\"aria-hidden\", \"true\");\n // `!important` overrides the companion stylesheet's `mono-wind *` rules\n // (white-space, overflow-wrap) that would otherwise wrap the probe to the\n // host's width and give us a bogus per-cell measurement.\n probe.style.cssText =\n \"position:absolute!important;visibility:hidden!important;pointer-events:none!important;\" +\n \"white-space:pre!important;overflow-wrap:normal!important;\" +\n \"top:0!important;left:0!important;padding:0!important;margin:0!important;border:0!important;\";\n probe.textContent = \"M\".repeat(100);\n host.appendChild(probe);\n const rect = probe.getBoundingClientRect();\n host.removeChild(probe);\n return { width: rect.width / 100, height: rect.height };\n}\n\nexport function getRootFontSizePx(): number {\n return parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n}\n","/**\n * Greedy word-wrap for monospace text.\n *\n * Words are runs of non-whitespace; whitespace runs collapse to single spaces\n * between fitting words. Browsers also treat a hyphen inside a word as a\n * break opportunity (break after `-`, no hyphen added) — except before a\n * digit, per UAX #14 (`2026-08` doesn't break) — so words are further split\n * into breakable segments. A segment longer than `width` breaks at cell\n * boundaries. `\\n` in the input is a HARD line break — the wrap restarts on\n * a new line (the source of these is `<br>` elements, converted to `\\n` by\n * the tree builder). A blank hard line still occupies one row.\n *\n * Matches how a browser wraps `white-space: normal; overflow-wrap: anywhere`\n * text in a fixed-width monospace container — we set that in styles.css so\n * the two agree.\n */\nexport function wrapLines(text: string, width: number): string[] {\n if (text.trim() === \"\") return [];\n return text.split(\"\\n\").flatMap((hardLine) => wrapHardLine(hardLine, width));\n}\n\n/** Number of rows `text` occupies at `width` (see wrapLines). */\nexport function wrapLineCount(text: string, width: number): number {\n return wrapLines(text, width).length;\n}\n\n/**\n * Split a word at its internal break opportunities: after each hyphen run,\n * unless the next character is a digit (UAX #14: no break between a hyphen\n * and a following number). `\"mx-auto\"` → `[\"mx-\", \"auto\"]`;\n * `\"2026-08\"` → `[\"2026-08\"]`. Also the unit of min-content width.\n */\nexport function breakableSegments(word: string): string[] {\n const segments: string[] = [];\n let start = 0;\n const hyphenRun = /-+/g;\n let match: RegExpExecArray | null;\n while ((match = hyphenRun.exec(word)) !== null) {\n const end = match.index + match[0].length;\n if (end < word.length && !/[0-9]/.test(word[end]!)) {\n segments.push(word.slice(start, end));\n start = end;\n }\n }\n segments.push(word.slice(start));\n return segments;\n}\n\nfunction wrapHardLine(text: string, width: number): string[] {\n // CSS \"document white space\" only: space, tab, CR, LF, FF. Notably NOT\n // NBSP (U+00A0) — JS `\\s` would match it, but the browser neither\n // collapses nor breaks at it, so it must stay inside its word.\n const words = text.split(/[ \\t\\r\\n\\f]+/).filter(Boolean);\n if (words.length === 0) return [\"\"];\n if (width <= 0) return [words.join(\" \")];\n\n const lines: string[] = [];\n let current = \"\";\n\n for (const word of words) {\n let joinsPrevious = false; // segments after the first attach with no space\n for (let segment of breakableSegments(word)) {\n const separator = !joinsPrevious && current !== \"\" ? 1 : 0;\n if (current !== \"\" && current.length + separator + segment.length <= width) {\n current += separator ? ` ${segment}` : segment;\n } else {\n if (current !== \"\") lines.push(current);\n // Break a too-long segment at cell boundaries; a chunk of exactly\n // `width` stays as the current line (matching browser overflow-wrap).\n while (segment.length > width) {\n lines.push(segment.slice(0, width));\n segment = segment.slice(width);\n }\n current = segment;\n }\n joinsPrevious = true;\n }\n }\n lines.push(current);\n return lines;\n}\n","import { percentToCells } from \"./metrics.ts\";\nimport { breakableSegments, wrapLineCount } from \"./wrap.ts\";\nimport type {\n CellLength,\n CellStyle,\n Insets,\n LayoutNode,\n NullableInsets,\n PerSide,\n Size,\n} from \"./types.ts\";\n\n/**\n * Layout entry point: mutates localRect on the root and each descendant.\n * Coordinates are parent-relative (root's rect is at 0,0).\n */\nexport function layoutRoot(root: LayoutNode, availableWidth: number): { height: number } {\n const cache: IntrinsicCache = { maxContent: new WeakMap(), minContent: new WeakMap() };\n layoutNode(root, availableWidth, undefined, 0, 0, \"fill\", cache);\n return { height: root.localRect.height };\n}\n\ntype SizingMode = \"fill\" | \"shrink\";\ninterface IntrinsicCache {\n maxContent: WeakMap<LayoutNode, number>;\n minContent: WeakMap<LayoutNode, number>;\n}\n\n/**\n * `forced` carries flex-assigned (\"used\") sizes from a parent flex pass —\n * they are authoritative and skip resolution/clamping entirely (the flex\n * loop already applied min/max). With sizes forced, `availableWidth` stays\n * the CONTAINING BLOCK's content width, which percent padding, margins,\n * and min/max resolve against — never the assigned size itself.\n */\nfunction layoutNode(\n node: LayoutNode,\n availableWidth: number,\n availableHeight: number | undefined,\n parentX: number,\n parentY: number,\n widthMode: SizingMode,\n cache: IntrinsicCache,\n forced?: { width?: number | undefined; height?: number | undefined },\n): void {\n const style = node.style;\n const forcedHeight = forced?.height;\n\n // Width is clamped to min/max BEFORE laying out content — wrapping and\n // child sizing must see the constrained width, not the raw resolved one.\n // (Height differs: max-height clamps the final rect after layout, since\n // content height is an output, and overflow handles the spill.)\n // Percent min/max (`max-w-full`) resolve against the available size; a\n // percent height limit with indefinite available height is ignored, per CSS.\n const minWidth = resolveLimit(style.minWidth, availableWidth) ?? 0;\n const maxWidth = resolveLimit(style.maxWidth, availableWidth);\n const minHeight = resolveLimit(style.minHeight, availableHeight) ?? 0;\n const maxHeight = resolveLimit(style.maxHeight, availableHeight);\n // Percent padding resolves against the containing block's width (CSS: all\n // four sides use the inline size) — `availableWidth` is that width here.\n // Stored on the node because the renderers need the resolved cells too.\n const padding: Insets = {\n top: resolveLength(style.padding.top, availableWidth),\n right: resolveLength(style.padding.right, availableWidth),\n bottom: resolveLength(style.padding.bottom, availableWidth),\n left: resolveLength(style.padding.left, availableWidth),\n };\n node.resolvedPadding = padding;\n const outerWidth =\n forced?.width ??\n clampSize(resolveWidth(style, availableWidth, widthMode, node, cache), minWidth, maxWidth);\n const outerHeightExplicit = resolveHeight(style, availableHeight);\n // A `forcedHeight` (set by a parent flex-column when grow/shrink assigned a\n // main-axis size) overrides both explicit `height` and `min-height` — the\n // flex algorithm's \"used main size\" is authoritative. Otherwise, `min-height`\n // is a lower bound so items-center / items-end see the enforced size, not\n // just the natural content size.\n const outerHeightFloor =\n forcedHeight ?? outerHeightExplicit ?? (minHeight > 0 ? minHeight : undefined);\n\n const inner = shrinkSize(\n outerWidth,\n outerHeightFloor ?? Number.POSITIVE_INFINITY,\n style.border,\n padding,\n );\n\n let contentHeight: number;\n if (node.children.length === 0) {\n // `white-space: nowrap` text never soft-wraps: its height is the\n // hard-line (`<br>`) count, regardless of width.\n contentHeight = node.text\n ? style.whiteSpace === \"nowrap\"\n ? node.text.split(\"\\n\").length\n : wrapLineCount(node.text, inner.width)\n : node.intrinsicHeight;\n } else if (style.display === \"flex\" && style.flexDirection === \"row\") {\n contentHeight = layoutFlexRow(node, inner.width, inner.height, style.border, padding, cache);\n } else if (style.display === \"flex\" && style.flexDirection === \"column\") {\n // Whether the main-axis (height) size is definite (explicit `height` or a\n // parent-assigned flex size) or only a `min-height` floor. A floor adds\n // distributable space for flex-grow but must never trigger flex-shrink —\n // min-height can only make the container taller, not compress content.\n const heightIsDefinite = forcedHeight !== undefined || outerHeightExplicit !== undefined;\n contentHeight = layoutFlexColumn(\n node,\n inner.width,\n inner.height,\n heightIsDefinite,\n style.border,\n padding,\n cache,\n );\n } else {\n contentHeight = layoutBlock(node, inner.width, style.border, padding, cache);\n }\n\n const naturalHeight =\n contentHeight + style.border.top + style.border.bottom + padding.top + padding.bottom;\n // Order matters: min-* is a floor, max-* is a ceiling; when both apply,\n // max wins per CSS (min-width < max-width is required, but if the author\n // sets an inconsistent pair CSS clamps to `max(min, min(max, value))`).\n // The pre-clamp height is the column flex algorithm's base size (CSS\n // distributes from UNclamped bases; min/max apply via its freeze loop).\n const unclampedHeight = forcedHeight ?? outerHeightExplicit ?? naturalHeight;\n node.unclampedHeight = unclampedHeight;\n const finalHeight = clampSize(unclampedHeight, minHeight, maxHeight);\n\n node.localRect = { x: parentX, y: parentY, width: outerWidth, height: finalHeight };\n}\n\nfunction clampSize(value: number, min: number, max: number | undefined): number {\n const clamped = max !== undefined ? Math.min(value, max) : value;\n return Math.max(min, clamped);\n}\n\n/** Resolve a spacing length to cells against its containing-block basis.\n * An indefinite basis (percent gap in an unbounded axis) resolves to 0. */\nfunction resolveLength(length: CellLength, basis: number | undefined): number {\n if (typeof length === \"number\") return length;\n return basis === undefined || !Number.isFinite(basis) ? 0 : percentToCells(length.percent, basis);\n}\n\n/** Resolve all four margin sides (preserving `auto` as null) against the\n * parent's content width — the CSS basis for every side. */\nfunction resolveMargin(margin: PerSide<CellLength | null>, basis: number): NullableInsets {\n const side = (v: CellLength | null) => (v === null ? null : resolveLength(v, basis));\n return {\n top: side(margin.top),\n right: side(margin.right),\n bottom: side(margin.bottom),\n left: side(margin.left),\n };\n}\n\n/** The cells of a CellLength for intrinsic sizing: percentages count as 0,\n * per CSS intrinsic-size contribution rules. */\nfunction intrinsicCells(length: CellLength): number {\n return typeof length === \"number\" ? length : 0;\n}\n\n/** Resolve a CellLength to cells: percent needs a definite available size.\n * `\"auto\"` resolves to none here (0 in block flow) — flex main-axis code\n * substitutes the item's content-based automatic minimum itself. */\nfunction resolveLimit(\n limit: CellLength | \"auto\" | undefined,\n available: number | undefined,\n): number | undefined {\n if (limit === undefined || limit === \"auto\") return undefined;\n if (typeof limit === \"number\") return limit;\n return available === undefined ? undefined : percentToCells(limit.percent, available);\n}\n\n/**\n * Lay out children in vertical block flow. Returns content height (rows used).\n *\n * - Vertical (main-axis) margins on adjacent siblings **collapse** — the\n * effective gap is `max(prev.bottom, curr.top)` for two positives, `min`\n * for two negatives, and the sum for mixed signs (standard CSS rule).\n * Parent–child collapsing is intentionally NOT implemented (see the cell-\n * model spec's Deviations section).\n * - Horizontal (cross-axis) margins position the child; `auto` on either\n * side centers or end-aligns as CSS does.\n */\nfunction layoutBlock(\n node: LayoutNode,\n innerWidth: number,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const originX = border.left + padding.left;\n const startY = border.top + padding.top;\n let y = startY;\n let previousMarginBottom: number | null = null;\n for (const child of node.children) {\n const childMargin = resolveMargin(child.style.margin, innerWidth);\n const marginTop = childMargin.top ?? 0;\n const marginBottom = childMargin.bottom ?? 0;\n const marginLeft = childMargin.left ?? 0;\n const marginRight = childMargin.right ?? 0;\n layoutNode(\n child,\n Math.max(0, innerWidth - marginLeft - marginRight),\n undefined,\n 0,\n 0,\n \"fill\",\n cache,\n );\n const crossAvailable = innerWidth - child.localRect.width;\n const bothAutoX = childMargin.left === null && childMargin.right === null;\n const oneAutoLeft = childMargin.left === null && childMargin.right !== null;\n const oneAutoRight = childMargin.right === null && childMargin.left !== null;\n let crossOffset: number;\n if (bothAutoX) crossOffset = Math.floor(crossAvailable / 2);\n else if (oneAutoLeft) crossOffset = crossAvailable - marginRight;\n else if (oneAutoRight) crossOffset = marginLeft;\n else crossOffset = marginLeft;\n\n // `y` tracks the position where the next child's top edge goes. Margins\n // are added JUST BEFORE placing each child, then only the child's height\n // afterwards — the child's own bottom margin waits until the next\n // sibling (or the end-of-container) so we can collapse them properly.\n y +=\n previousMarginBottom === null ? marginTop : collapseMargins(previousMarginBottom, marginTop);\n child.localRect = { ...child.localRect, x: originX + crossOffset, y };\n y += child.localRect.height;\n previousMarginBottom = marginBottom;\n }\n if (previousMarginBottom !== null) y += previousMarginBottom;\n return y - startY;\n}\n\n/**\n * CSS margin-collapsing rule for two adjacent block-flow margins:\n * - both positive → the larger absorbs the smaller.\n * - both negative → the more negative absorbs the less negative.\n * - mixed → they sum (positive shrunk by the negative).\n */\nfunction collapseMargins(a: number, b: number): number {\n if (a >= 0 && b >= 0) return Math.max(a, b);\n if (a <= 0 && b <= 0) return Math.min(a, b);\n return a + b;\n}\n\nfunction layoutFlexRow(\n node: LayoutNode,\n innerWidth: number,\n innerHeight: number,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const gapX = resolveLength(node.style.gapX, innerWidth);\n const gapY = resolveLength(node.style.gapY, innerHeight);\n const items = flexOrderedChildren(node).map((child) => {\n const margin = resolveMargin(child.style.margin, innerWidth);\n return {\n node: child,\n intrinsic: flexBaseOuterWidth(child, innerWidth, cache),\n grow: child.style.flexGrow,\n shrink: child.style.flexShrink,\n min: flexItemMinWidth(child, innerWidth, cache),\n max: resolveLimit(child.style.maxWidth, innerWidth),\n margin,\n marginLeft: margin.left,\n marginRight: margin.right,\n };\n });\n\n // Break into rows greedily. With gap, an item breaks when `used + gap +\n // fixedMargins + intrinsic` exceeds innerWidth. The first item on a row is\n // always placed even if it alone overflows, matching CSS.\n const rows: (typeof items)[] = [];\n if (node.style.flexWrap === \"wrap\") {\n let current: typeof items = [];\n let used = 0;\n for (const item of items) {\n // Placement uses the hypothetical size (base clamped by min/max).\n const hypothetical = Math.max(0, clampSize(item.intrinsic, item.min, item.max));\n const itemWidth = hypothetical + (item.marginLeft ?? 0) + (item.marginRight ?? 0);\n const next = current.length === 0 ? itemWidth : used + gapX + itemWidth;\n if (current.length > 0 && next > innerWidth) {\n rows.push(current);\n current = [];\n used = 0;\n }\n current.push(item);\n used = current.length === 1 ? itemWidth : used + gapX + itemWidth;\n }\n if (current.length > 0) rows.push(current);\n // wrap-reverse stacks the lines from the cross-end (bottom-up); items\n // within each line keep their main-axis order.\n if (node.style.wrapReverse) rows.reverse();\n } else {\n rows.push(items);\n }\n\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n let y = 0;\n let totalRowHeight = 0;\n\n for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n const row = rows[rowIndex]!;\n const totalGap = gapX * Math.max(0, row.length - 1);\n const fixedMarginTotal = row.reduce(\n (sum, item) => sum + (item.marginLeft ?? 0) + (item.marginRight ?? 0),\n 0,\n );\n const availableForItems = Math.max(0, innerWidth - totalGap - fixedMarginTotal);\n // Per CSS: if there's positive free space and any main-axis auto margin,\n // auto margins absorb the leftover BEFORE flex-grow. Detect that case and\n // keep items at their intrinsic size — the auto-margin loop below will\n // then distribute the leftover space itself.\n const rowHasAutoMainMargin = row.some(\n (item) => item.marginLeft === null || item.marginRight === null,\n );\n const totalRowIntrinsic = row.reduce((s, i) => s + i.intrinsic, 0);\n const skipGrowForAutoMargins = rowHasAutoMainMargin && totalRowIntrinsic <= availableForItems;\n const widths = skipGrowForAutoMargins\n ? row.map((i) => i.intrinsic)\n : resolveFlexMainAxis(row, availableForItems);\n for (let i = 0; i < row.length; i++) {\n layoutNode(row[i]!.node, innerWidth, undefined, 0, 0, \"fill\", cache, {\n width: widths[i]!,\n });\n }\n const maxChildHeight = row.reduce((h, item) => Math.max(h, item.node.localRect.height), 0);\n // For a nowrap single row, the row can stretch to the container's inner\n // height (from min-h or explicit height) so items-center / items-end\n // have the enforced size to align against. With wrap, each row's height\n // is just its tallest child.\n const rowHeight =\n rows.length === 1 && Number.isFinite(innerHeight)\n ? Math.max(innerHeight, maxChildHeight)\n : maxChildHeight;\n\n // Stretch phase: any item whose effective cross alignment is `stretch`\n // (no explicit height, no auto cross-axis margins) grows to fill the\n // row. Re-run layoutNode with `forcedHeight` so nested content that\n // depends on the parent's height sees the final size.\n for (let i = 0; i < row.length; i++) {\n const child = row[i]!.node;\n const effectiveAlign =\n child.style.alignSelf === \"auto\" ? node.style.alignItems : child.style.alignSelf;\n const itemMargin = row[i]!.margin;\n const hasCrossAutoMargin = itemMargin.top === null || itemMargin.bottom === null;\n // Treat `{kind: \"auto\"}` as no explicit height (Typed OM returns this\n // for elements that don't set a height; only `cells`/`percent` counts\n // as an author-set size that stretch should respect).\n const hasExplicitHeight =\n child.style.height !== undefined && child.style.height.kind !== \"auto\";\n if (\n effectiveAlign === \"stretch\" &&\n !hasCrossAutoMargin &&\n !hasExplicitHeight &&\n rowHeight > child.localRect.height\n ) {\n const marginTop = itemMargin.top ?? 0;\n const marginBottom = itemMargin.bottom ?? 0;\n // Per CSS, a stretched cross size is still clamped by the item's own\n // min/max-height (percent resolved against the container's inner\n // height when definite).\n const crossBasis = Number.isFinite(innerHeight) ? innerHeight : undefined;\n const stretchedHeight = clampSize(\n Math.max(0, rowHeight - marginTop - marginBottom),\n resolveLimit(child.style.minHeight, crossBasis) ?? 0,\n resolveLimit(child.style.maxHeight, crossBasis),\n );\n if (stretchedHeight === child.localRect.height) continue;\n layoutNode(child, innerWidth, undefined, 0, 0, \"fill\", cache, {\n width: widths[i]!,\n height: stretchedHeight,\n });\n }\n }\n const totalUsed = widths.reduce((s, w) => s + w, 0);\n const leftover = Math.max(0, availableForItems - totalUsed);\n\n // Auto margins on the main axis absorb leftover space (each gets an\n // equal share). If any exist, they override justify-content.\n const autoCount = row.reduce(\n (n, item) => n + (item.marginLeft === null ? 1 : 0) + (item.marginRight === null ? 1 : 0),\n 0,\n );\n const autoMarginBefore: number[] = Array.from({ length: row.length }, () => 0);\n const autoMarginAfter: number[] = Array.from({ length: row.length }, () => 0);\n let offsets: number[];\n if (autoCount > 0 && leftover > 0) {\n const shares = distributeInteger(\n Array.from({ length: autoCount }, () => 1),\n leftover,\n );\n let shareIndex = 0;\n for (let i = 0; i < row.length; i++) {\n if (row[i]!.marginLeft === null) autoMarginBefore[i] = shares[shareIndex++]!;\n if (row[i]!.marginRight === null) autoMarginAfter[i] = shares[shareIndex++]!;\n }\n offsets = mainAxisOffsets(\"start\", widths, 0);\n } else {\n offsets = mainAxisOffsets(effectiveJustify(node.style), widths, leftover);\n }\n\n let cumulativeExtraOffset = 0;\n for (let i = 0; i < row.length; i++) {\n const item = row[i]!;\n const child = item.node;\n const fixedLeft = item.marginLeft ?? 0;\n const fixedRight = item.marginRight ?? 0;\n cumulativeExtraOffset += autoMarginBefore[i]! + fixedLeft;\n child.localRect = {\n ...child.localRect,\n x: originX + offsets[i]! + i * gapX + cumulativeExtraOffset,\n y: originY + y + crossAxisOffset(child, node.style.alignItems, rowHeight, item.margin),\n };\n cumulativeExtraOffset += autoMarginAfter[i]! + fixedRight;\n }\n const rowSpacing = rowIndex < rows.length - 1 ? gapY : 0;\n y += rowHeight + rowSpacing;\n totalRowHeight += rowHeight + rowSpacing;\n }\n\n return Number.isFinite(innerHeight) ? Math.max(innerHeight, totalRowHeight) : totalRowHeight;\n}\n\nfunction layoutFlexColumn(\n node: LayoutNode,\n innerWidth: number,\n innerHeight: number,\n heightIsDefinite: boolean,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const gapY = resolveLength(node.style.gapY, innerHeight);\n\n const items = flexOrderedChildren(node).map((child) => {\n const margin = resolveMargin(child.style.margin, innerWidth);\n const marginLeft = margin.left ?? 0;\n const marginRight = margin.right ?? 0;\n const availableChildWidth = Math.max(0, innerWidth - marginLeft - marginRight);\n // Per-item cross-axis (width) stretch decision: parent's alignItems is\n // the default, but a child's own alignSelf wins if set. So an item with\n // `self-start` inside a stretch parent shrinks to intrinsic, not fills.\n const effectiveAlign =\n child.style.alignSelf === \"auto\" ? node.style.alignItems : child.style.alignSelf;\n const childStretch = effectiveAlign === \"stretch\";\n // First pass at intrinsic height along the main axis.\n layoutNode(\n child,\n availableChildWidth,\n undefined,\n 0,\n 0,\n childStretch ? \"fill\" : \"shrink\",\n cache,\n );\n const limitBasis = Number.isFinite(innerHeight) ? innerHeight : undefined;\n // Base main size per CSS flex-basis: an explicit basis (cells, or\n // percent against a definite container height) wins; otherwise the\n // first-pass height BEFORE min/max clamping — distribution starts from\n // raw bases, the freeze loop enforces the limits.\n const basis = child.style.flexBasis;\n const base =\n basis === undefined || basis.kind === \"auto\"\n ? child.unclampedHeight\n : basis.kind === \"cells\"\n ? basis.value\n : basis.kind === \"percent\" && limitBasis !== undefined\n ? percentToCells(basis.value, limitBasis)\n : child.unclampedHeight;\n // `min-height: auto` on a column item is the automatic minimum: its\n // content height (the first-pass laid-out height), unless overflow is\n // non-visible. Same rule as the row's min-content width.\n const autoMin =\n child.style.minHeight === \"auto\"\n ? child.style.overflow === \"visible\"\n ? child.localRect.height\n : 0\n : undefined;\n return {\n node: child,\n intrinsic: base,\n grow: child.style.flexGrow,\n shrink: child.style.flexShrink,\n min: autoMin ?? resolveLimit(child.style.minHeight, limitBasis) ?? 0,\n max: resolveLimit(child.style.maxHeight, limitBasis),\n margin,\n marginTop: margin.top,\n marginBottom: margin.bottom,\n marginLeft,\n marginRight,\n };\n });\n\n const totalGap = gapY * Math.max(0, items.length - 1);\n const fixedMarginTotal = items.reduce(\n (sum, item) => sum + (item.marginTop ?? 0) + (item.marginBottom ?? 0),\n 0,\n );\n const finiteInner = Number.isFinite(innerHeight);\n const totalIntrinsicHeight = items.reduce((s, i) => s + i.intrinsic, 0);\n const definiteAvailable = finiteInner\n ? Math.max(0, innerHeight - totalGap - fixedMarginTotal)\n : totalIntrinsicHeight;\n // A min-height-only container size is a floor, not a cap: it can hand\n // extra space to flex-grow, but content larger than the floor keeps its\n // intrinsic size (no flex-shrink) and the container grows to fit.\n const availableForItems = heightIsDefinite\n ? definiteAvailable\n : Math.max(definiteAvailable, totalIntrinsicHeight);\n\n // Same CSS rule as flex-row: auto margins on the main axis absorb positive\n // leftover before flex-grow gets to it.\n const columnHasAutoMainMargin = items.some(\n (item) => item.marginTop === null || item.marginBottom === null,\n );\n const skipGrowForAutoMargins =\n finiteInner && columnHasAutoMainMargin && totalIntrinsicHeight <= availableForItems;\n const finalHeights =\n finiteInner && !skipGrowForAutoMargins\n ? resolveFlexMainAxis(items, availableForItems)\n : items.map((i) => i.intrinsic);\n // If a child's main-axis size changed, re-run its layout with the new\n // height forced so any nested content that depends on the parent's height\n // (items-center/end in a nested flex, percent heights) sees the final size.\n for (let i = 0; i < items.length; i++) {\n if (finalHeights[i] !== items[i]!.intrinsic) {\n const item = items[i]!;\n const availableChildWidth = Math.max(0, innerWidth - item.marginLeft - item.marginRight);\n const effectiveAlign =\n item.node.style.alignSelf === \"auto\" ? node.style.alignItems : item.node.style.alignSelf;\n const childStretch = effectiveAlign === \"stretch\";\n layoutNode(\n item.node,\n availableChildWidth,\n finalHeights[i]!,\n 0,\n 0,\n childStretch ? \"fill\" : \"shrink\",\n cache,\n { height: finalHeights[i]! },\n );\n }\n }\n\n const totalUsed = finalHeights.reduce((s, h) => s + h, 0);\n const leftover = Math.max(0, availableForItems - totalUsed);\n\n const autoCount = items.reduce(\n (n, item) => n + (item.marginTop === null ? 1 : 0) + (item.marginBottom === null ? 1 : 0),\n 0,\n );\n const autoMarginBefore: number[] = Array.from({ length: items.length }, () => 0);\n const autoMarginAfter: number[] = Array.from({ length: items.length }, () => 0);\n let offsets: number[];\n if (autoCount > 0 && leftover > 0) {\n const shares = distributeInteger(\n Array.from({ length: autoCount }, () => 1),\n leftover,\n );\n let shareIndex = 0;\n for (let i = 0; i < items.length; i++) {\n if (items[i]!.marginTop === null) autoMarginBefore[i] = shares[shareIndex++]!;\n if (items[i]!.marginBottom === null) autoMarginAfter[i] = shares[shareIndex++]!;\n }\n offsets = mainAxisOffsets(\"start\", finalHeights, 0);\n } else {\n offsets = mainAxisOffsets(effectiveJustify(node.style), finalHeights, leftover);\n }\n\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n let cumulativeExtraOffset = 0;\n for (let i = 0; i < items.length; i++) {\n const item = items[i]!;\n const child = item.node;\n const fixedTop = item.marginTop ?? 0;\n const fixedBottom = item.marginBottom ?? 0;\n cumulativeExtraOffset += autoMarginBefore[i]! + fixedTop;\n child.localRect = {\n ...child.localRect,\n x: originX + crossAxisOffsetX(child, node.style.alignItems, innerWidth, item.margin),\n y: originY + offsets[i]! + i * gapY + cumulativeExtraOffset,\n };\n cumulativeExtraOffset += autoMarginAfter[i]! + fixedBottom;\n }\n\n const totalOccupied = totalUsed + totalGap + fixedMarginTotal;\n return finiteInner ? Math.max(innerHeight, totalOccupied) : totalOccupied;\n}\n\n/**\n * Compute a child's cross-axis (vertical) offset inside a flex row, honoring\n * align-self override, cross-axis auto margins, and fixed cross-axis margins.\n */\nfunction crossAxisOffset(\n child: LayoutNode,\n parentAlign: CellStyle[\"alignItems\"],\n rowHeight: number,\n m: NullableInsets,\n): number {\n const align = child.style.alignSelf === \"auto\" ? parentAlign : child.style.alignSelf;\n const marginTop = m.top ?? 0;\n const marginBottom = m.bottom ?? 0;\n const crossAvailable = rowHeight - child.localRect.height;\n const bothAuto = m.top === null && m.bottom === null;\n const oneAutoTop = m.top === null && m.bottom !== null;\n const oneAutoBottom = m.bottom === null && m.top !== null;\n if (bothAuto) return Math.floor(crossAvailable / 2);\n if (oneAutoTop) return crossAvailable - marginBottom;\n if (oneAutoBottom) return marginTop;\n return marginTop + alignCrossOffset(align, rowHeight, child.localRect.height);\n}\n\n/**\n * Symmetric helper for flex-column: cross axis is horizontal, so auto/fixed\n * margins on `left`/`right` participate.\n */\nfunction crossAxisOffsetX(\n child: LayoutNode,\n parentAlign: CellStyle[\"alignItems\"],\n containerWidth: number,\n m: NullableInsets,\n): number {\n const align = child.style.alignSelf === \"auto\" ? parentAlign : child.style.alignSelf;\n const marginLeft = m.left ?? 0;\n const marginRight = m.right ?? 0;\n const crossAvailable = containerWidth - child.localRect.width;\n const bothAuto = m.left === null && m.right === null;\n const oneAutoLeft = m.left === null && m.right !== null;\n const oneAutoRight = m.right === null && m.left !== null;\n if (bothAuto) return Math.floor(crossAvailable / 2);\n if (oneAutoLeft) return crossAvailable - marginRight;\n if (oneAutoRight) return marginLeft;\n return marginLeft + alignCrossOffset(align, containerWidth, child.localRect.width);\n}\n\n/**\n * Position each item along the main axis given its size and leftover space.\n * Returns the offset from container inner origin for each item.\n */\nfunction mainAxisOffsets(\n justify: CellStyle[\"justifyContent\"],\n sizes: number[],\n leftover: number,\n): number[] {\n const count = sizes.length;\n if (count === 0) return [];\n\n const offsets: number[] = [];\n let cursor = 0;\n\n if (justify === \"space-between\" && count > 1) {\n const gapBase = Math.floor(leftover / (count - 1));\n const extra = leftover - gapBase * (count - 1);\n for (let i = 0; i < count; i++) {\n offsets.push(cursor);\n cursor += sizes[i]! + gapBase + (i < extra ? 1 : 0);\n }\n return offsets;\n }\n\n // space-around: every item gets equal space on both sides, so the edge\n // gaps are half the inner ones (weights 1,2,…,2,1 over the n+1 gap\n // slots). space-evenly: all n+1 gaps equal. Integer-distributed with the\n // shared remainder rule, so the result is deterministic.\n if ((justify === \"space-around\" || justify === \"space-evenly\") && leftover > 0) {\n const weights = Array.from({ length: count + 1 }, (_, i) =>\n justify === \"space-evenly\" || i === 0 || i === count ? 1 : 2,\n );\n const gaps = distributeInteger(weights, leftover);\n for (let i = 0; i < count; i++) {\n cursor += gaps[i]!;\n offsets.push(cursor);\n cursor += sizes[i]!;\n }\n return offsets;\n }\n\n if (justify === \"center\") cursor = Math.floor(leftover / 2);\n else if (justify === \"end\") cursor = leftover;\n\n for (let i = 0; i < count; i++) {\n offsets.push(cursor);\n cursor += sizes[i]!;\n }\n return offsets;\n}\n\n/**\n * Resolve flex main-axis sizes per CSS Flexbox §9.7 (\"Resolving Flexible\n * Lengths\"), adapted to integers: distribute free space proportionally to\n * grow factors (or shrink weights = base × shrink), clamp each result to the\n * item's own min/max, FREEZE the items whose clamp fired, and redistribute\n * among the rest — repeating until nothing new violates. Without the\n * redistribution rounds, an item clamped up to `min-w-*` would keep space\n * its neighbors were already told they could use, and boxes would overlap.\n *\n * `min`/`max` are outer main sizes in cells, already resolved from percent.\n * When clamps bind, the returned sizes may sum to less or more than\n * `available` — that's CSS (`justify-content` sees the underfill; overflow\n * handles the excess).\n */\nexport function resolveFlexMainAxis(\n items: ReadonlyArray<{\n intrinsic: number;\n grow: number;\n shrink: number;\n min?: number | undefined;\n max?: number | undefined;\n }>,\n available: number,\n): number[] {\n const count = items.length;\n const clamp = (value: number, index: number) =>\n Math.max(0, clampSize(value, items[index]!.min ?? 0, items[index]!.max));\n const base = items.map((i) => i.intrinsic);\n // Grow vs shrink is decided from the HYPOTHETICAL sizes (clamped bases),\n // per CSS; distribution then starts from the raw bases.\n const hypotheticalTotal = base.reduce((s, b, i) => s + clamp(b, i), 0);\n const growing = available >= hypotheticalTotal;\n\n const sizes: number[] = Array.from({ length: count }, () => 0);\n const frozen: boolean[] = Array.from({ length: count }, () => false);\n // Pre-freeze inflexible items, and items whose base already violates in\n // the flex direction (max-violation when growing, min-violation when\n // shrinking), at their hypothetical size. A base merely BELOW its min\n // while growing stays flexible — it grows from the raw base and the\n // violation loop enforces the min afterwards.\n for (let i = 0; i < count; i++) {\n const hypothetical = clamp(base[i]!, i);\n const flexFactor = growing ? items[i]!.grow : items[i]!.shrink;\n if (\n flexFactor === 0 ||\n (growing && base[i]! > hypothetical) ||\n (!growing && base[i]! < hypothetical)\n ) {\n sizes[i] = hypothetical;\n frozen[i] = true;\n }\n }\n\n // Each round freezes at least one item, so this terminates within `count`\n // iterations.\n for (;;) {\n const unfrozen: number[] = [];\n for (let i = 0; i < count; i++) if (!frozen[i]) unfrozen.push(i);\n if (unfrozen.length === 0) break;\n\n const frozenTotal = sizes.reduce((s, v, i) => (frozen[i] ? s + v : s), 0);\n const unfrozenBaseTotal = unfrozen.reduce((s, i) => s + base[i]!, 0);\n const freeSpace = available - frozenTotal - unfrozenBaseTotal;\n const amount = growing ? Math.max(0, freeSpace) : Math.max(0, -freeSpace);\n\n const weights = unfrozen.map((i) => (growing ? items[i]!.grow : base[i]! * items[i]!.shrink));\n const shares = distributeInteger(weights, amount);\n const tentative = unfrozen.map((i, k) => base[i]! + (growing ? shares[k]! : -shares[k]!));\n const clamped = unfrozen.map((i, k) => clamp(tentative[k]!, i));\n const totalViolation = clamped.reduce((s, v, k) => s + (v - tentative[k]!), 0);\n\n if (totalViolation === 0) {\n for (let k = 0; k < unfrozen.length; k++) sizes[unfrozen[k]!] = clamped[k]!;\n break;\n }\n // Freeze only the violators on the dominant side (min violations when\n // the total is positive, max violations when negative) and go again.\n for (let k = 0; k < unfrozen.length; k++) {\n const violation = clamped[k]! - tentative[k]!;\n if (totalViolation > 0 ? violation > 0 : violation < 0) {\n sizes[unfrozen[k]!] = clamped[k]!;\n frozen[unfrozen[k]!] = true;\n }\n }\n }\n return sizes;\n}\n\n/**\n * Distribute `total` integer units across N slots proportionally to `weights`,\n * with the remainder (from flooring) given to the slots with the largest\n * fractional part — deterministic, document order for ties.\n */\nexport function distributeInteger(weights: number[], total: number): number[] {\n const sum = weights.reduce((s, w) => s + w, 0);\n if (sum === 0 || total <= 0) return weights.map(() => 0);\n const raw = weights.map((w) => (w / sum) * total);\n const floored = raw.map(Math.floor);\n let deficit = total - floored.reduce((s, v) => s + v, 0);\n if (deficit > 0) {\n const order = raw\n .map((v, i) => [i, v - Math.floor(v)] as const)\n .sort((a, b) => (b[1] === a[1] ? a[0] - b[0] : b[1] - a[1]));\n for (const [i] of order) {\n if (deficit <= 0) break;\n floored[i]! += 1;\n deficit -= 1;\n }\n }\n return floored;\n}\n\nfunction alignCrossOffset(\n align: CellStyle[\"alignItems\"],\n container: number,\n child: number,\n): number {\n if (align === \"center\") return Math.max(0, Math.floor((container - child) / 2));\n if (align === \"end\") return Math.max(0, container - child);\n return 0;\n}\n\nfunction resolveWidth(\n style: CellStyle,\n available: number,\n mode: SizingMode,\n node: LayoutNode,\n cache: IntrinsicCache,\n): number {\n const width = style.width;\n if (width !== undefined && width.kind !== \"auto\")\n return resolveSizeAgainst(width, available, node, cache);\n return mode === \"shrink\" ? Math.min(available, intrinsicOuterWidth(node, cache)) : available;\n}\n\nfunction resolveHeight(style: CellStyle, available: number | undefined): number | undefined {\n if (style.height?.kind === \"cells\") return style.height.value;\n if (style.height?.kind === \"percent\" && available != null)\n return percentToCells(style.height.value, available);\n return undefined;\n}\n\n/**\n * A flex-row item's base main size, per CSS `flex-basis`: an explicit basis\n * if set, else the item's explicit width (cells, percent, or an intrinsic\n * keyword), else its max-content size. Percentages resolve against the\n * container's content box (`innerWidth`). NOT clamped by min/max —\n * distribution starts from the raw base per CSS §9.7 (clamping happens via\n * the freeze/violation loop); pre-clamping would e.g. leave `flex-1`\n * columns unequal at their content minimums.\n */\nfunction flexBaseOuterWidth(child: LayoutNode, innerWidth: number, cache: IntrinsicCache): number {\n const basis = child.style.flexBasis;\n const width = child.style.width;\n if (basis !== undefined && basis.kind !== \"auto\") {\n return resolveSizeAgainst(basis, innerWidth, child, cache);\n }\n if (width !== undefined && width.kind !== \"auto\") {\n return resolveSizeAgainst(width, innerWidth, child, cache);\n }\n return intrinsicOuterWidth(child, cache);\n}\n\n/** Resolve a definite Size against an available extent (`auto` falls back\n * to max-content — callers handle the auto/fill distinction themselves). */\nfunction resolveSizeAgainst(\n size: Size,\n available: number,\n node: LayoutNode,\n cache: IntrinsicCache,\n): number {\n switch (size.kind) {\n case \"cells\":\n return size.value;\n case \"percent\":\n return percentToCells(size.value, available);\n case \"min-content\":\n return minContentOuterWidth(node, cache);\n case \"max-content\":\n return intrinsicOuterWidth(node, cache);\n case \"fit-content\":\n return Math.min(\n intrinsicOuterWidth(node, cache),\n Math.max(minContentOuterWidth(node, cache), available),\n );\n case \"auto\":\n return intrinsicOuterWidth(node, cache);\n }\n}\n\n/**\n * Flex item order: stable sort by CSS `order` (document order breaks\n * ties), then reversed for `row-reverse` / `column-reverse` — the main\n * axis runs backwards, so laying reversed children in a normal row with\n * flipped justify start/end is equivalent.\n */\nfunction flexOrderedChildren(node: LayoutNode): LayoutNode[] {\n const children = [...node.children].sort((a, b) => a.style.order - b.style.order);\n if (node.style.flexReverse) children.reverse();\n return children;\n}\n\nfunction effectiveJustify(style: CellStyle): CellStyle[\"justifyContent\"] {\n if (!style.flexReverse) return style.justifyContent;\n if (style.justifyContent === \"start\") return \"end\";\n if (style.justifyContent === \"end\") return \"start\";\n return style.justifyContent;\n}\n\n/**\n * A flex-row item's used minimum width. `min-width: auto` (the CSS default)\n * is the automatic minimum: the item's min-content size — which is why text\n * in a flex row stops shrinking at its longest segment instead of\n * disappearing. It only applies while overflow is visible: `overflow` set\n * to anything else (e.g. via `truncate`) or an explicit `min-w-*` opts out.\n */\nfunction flexItemMinWidth(child: LayoutNode, innerWidth: number, cache: IntrinsicCache): number {\n if (child.style.minWidth === \"auto\") {\n return child.style.overflow === \"visible\" ? minContentOuterWidth(child, cache) : 0;\n }\n return resolveLimit(child.style.minWidth, innerWidth) ?? 0;\n}\n\n/** Max-content intrinsic outer width (border + padding + unwrapped content). */\nfunction intrinsicOuterWidth(node: LayoutNode, cache: IntrinsicCache): number {\n const cached = cache.maxContent.get(node);\n if (cached !== undefined) return cached;\n const style = node.style;\n const inner = intrinsicInnerWidth(node, cache);\n const result =\n inner +\n style.border.left +\n style.border.right +\n intrinsicCells(style.padding.left) +\n intrinsicCells(style.padding.right);\n cache.maxContent.set(node, result);\n return result;\n}\n\nfunction intrinsicInnerWidth(node: LayoutNode, cache: IntrinsicCache): number {\n if (node.children.length === 0) return node.intrinsicWidth;\n if (node.style.display === \"flex\" && node.style.flexDirection === \"row\") {\n const gap = intrinsicCells(node.style.gapX) * Math.max(0, node.children.length - 1);\n return node.children.reduce((sum, c) => sum + intrinsicOuterWidth(c, cache), 0) + gap;\n }\n return node.children.reduce((max, c) => Math.max(max, intrinsicOuterWidth(c, cache)), 0);\n}\n\n/**\n * Min-content intrinsic outer width: the narrowest the box can get without\n * overflow. For a text leaf that's the longest unbreakable unit — a word\n * under normal wrapping, a whole hard line under `nowrap`. A nowrap flex\n * row sums its items (they sit side by side no matter what); wrapping rows\n * and block/column containers take the widest child.\n */\nfunction minContentOuterWidth(node: LayoutNode, cache: IntrinsicCache): number {\n const cached = cache.minContent.get(node);\n if (cached !== undefined) return cached;\n const style = node.style;\n const inner = minContentInnerWidth(node, cache);\n const result =\n inner +\n style.border.left +\n style.border.right +\n intrinsicCells(style.padding.left) +\n intrinsicCells(style.padding.right);\n cache.minContent.set(node, result);\n return result;\n}\n\nfunction minContentInnerWidth(node: LayoutNode, cache: IntrinsicCache): number {\n if (node.children.length === 0) {\n if (!node.text) return node.intrinsicWidth;\n if (node.style.whiteSpace === \"nowrap\") return node.intrinsicWidth;\n let longest = 0;\n for (const word of node.text.split(/[ \\t\\r\\n\\f]+/)) {\n for (const segment of breakableSegments(word)) {\n if (segment.length > longest) longest = segment.length;\n }\n }\n return longest;\n }\n if (\n node.style.display === \"flex\" &&\n node.style.flexDirection === \"row\" &&\n node.style.flexWrap === \"nowrap\"\n ) {\n const gap = intrinsicCells(node.style.gapX) * Math.max(0, node.children.length - 1);\n return node.children.reduce((sum, c) => sum + minContentOuterWidth(c, cache), 0) + gap;\n }\n return node.children.reduce((max, c) => Math.max(max, minContentOuterWidth(c, cache)), 0);\n}\n\nfunction shrinkSize(\n width: number,\n height: number,\n border: Insets,\n padding: Insets,\n): { width: number; height: number } {\n return {\n width: Math.max(0, width - border.left - border.right - padding.left - padding.right),\n height: Math.max(0, height - border.top - border.bottom - padding.top - padding.bottom),\n };\n}\n","import type { BorderStyle, CellStyle, PerSide, Rect } from \"./types.ts\";\n\n/** One run of identical border glyphs, in absolute cell coordinates. */\nexport interface BorderRun {\n glyph: string;\n x: number;\n y: number;\n length: number;\n color: string | undefined;\n}\n\ninterface Glyphs {\n h: string;\n v: string;\n tl: string;\n tr: string;\n bl: string;\n br: string;\n}\n\ninterface RingSides {\n top: boolean;\n right: boolean;\n bottom: boolean;\n left: boolean;\n}\n\n/**\n * Emit runs of border glyphs for the box's engine-allocated border cells.\n *\n * For multi-cell borders (`border-2`, `border-3`, …) the engine allocates N\n * cells per edge; we render them as N concentric rings. Styles and colors\n * are per-side (see paintRing); every ring repeats them.\n *\n * A single-cell-thin box (width < 2 or height < 2) has no interior; we draw\n * only vertical/horizontal runs and skip corners that would overlap.\n */\nexport function collectBorderRuns(style: CellStyle, box: Rect, out: BorderRun[]): void {\n const border = style.border;\n if (border.top === 0 && border.right === 0 && border.bottom === 0 && border.left === 0) return;\n const rings = Math.max(border.top, border.right, border.bottom, border.left);\n for (let ring = 0; ring < rings; ring++) {\n const sides = {\n top: ring < border.top,\n right: ring < border.right,\n bottom: ring < border.bottom,\n left: ring < border.left,\n };\n const ringRect = {\n x: box.x + (sides.left ? ring : 0),\n y: box.y + (sides.top ? ring : 0),\n width: box.width - (sides.left ? ring : 0) - (sides.right ? ring : 0),\n height: box.height - (sides.top ? ring : 0) - (sides.bottom ? ring : 0),\n };\n if (ringRect.width <= 0 || ringRect.height <= 0) continue;\n paintRing(out, style.borderStyle, style.borderColor, ringRect, sides);\n }\n}\n\n/**\n * Paint one ring, honoring per-side styles and colors. Each edge uses its\n * own style's glyphs. A corner where both adjacent edges share a style uses\n * that style's corner glyph; mixed-style corners fall back to the light\n * corners (Unicode has no mixed junction glyphs for most pairs — same\n * convention as dashed/dotted). Corner color comes from the horizontal\n * (top/bottom) edge.\n */\nfunction paintRing(\n out: BorderRun[],\n styles: PerSide<BorderStyle>,\n colors: PerSide<string | undefined>,\n rect: Rect,\n sides: RingSides,\n): void {\n const top = borderGlyphs(styles.top);\n const right = borderGlyphs(styles.right);\n const bottom = borderGlyphs(styles.bottom);\n const left = borderGlyphs(styles.left);\n const corner = (a: BorderStyle, b: BorderStyle, pick: (g: Glyphs) => string): string =>\n a === b ? pick(borderGlyphs(a)) : pick(borderGlyphs(\"solid\"));\n const { x, y, width, height } = rect;\n const hasCorners = width >= 2 && height >= 2;\n const interiorStartX = x + (sides.left ? 1 : 0);\n const interiorEndX = x + width - (sides.right ? 1 : 0);\n const interiorStartY = y + (sides.top ? 1 : 0);\n const interiorEndY = y + height - (sides.bottom ? 1 : 0);\n\n // Horizontal edges\n if (sides.top && interiorEndX > interiorStartX) {\n out.push({\n glyph: top.h,\n x: interiorStartX,\n y,\n length: interiorEndX - interiorStartX,\n color: colors.top,\n });\n }\n if (sides.bottom && height > (sides.top ? 1 : 0) && interiorEndX > interiorStartX) {\n out.push({\n glyph: bottom.h,\n x: interiorStartX,\n y: y + height - 1,\n length: interiorEndX - interiorStartX,\n color: colors.bottom,\n });\n }\n // Vertical edges\n if (sides.left) {\n for (let vy = interiorStartY; vy < interiorEndY; vy++)\n out.push({ glyph: left.v, x, y: vy, length: 1, color: colors.left });\n }\n if (sides.right && width > (sides.left ? 1 : 0)) {\n for (let vy = interiorStartY; vy < interiorEndY; vy++)\n out.push({ glyph: right.v, x: x + width - 1, y: vy, length: 1, color: colors.right });\n }\n // Corners (only when we have interior room to distinguish them)\n if (hasCorners) {\n if (sides.top && sides.left)\n out.push({\n glyph: corner(styles.top, styles.left, (g) => g.tl),\n x,\n y,\n length: 1,\n color: colors.top,\n });\n if (sides.top && sides.right)\n out.push({\n glyph: corner(styles.top, styles.right, (g) => g.tr),\n x: x + width - 1,\n y,\n length: 1,\n color: colors.top,\n });\n if (sides.bottom && sides.left)\n out.push({\n glyph: corner(styles.bottom, styles.left, (g) => g.bl),\n x,\n y: y + height - 1,\n length: 1,\n color: colors.bottom,\n });\n if (sides.bottom && sides.right)\n out.push({\n glyph: corner(styles.bottom, styles.right, (g) => g.br),\n x: x + width - 1,\n y: y + height - 1,\n length: 1,\n color: colors.bottom,\n });\n }\n}\n\nfunction borderGlyphs(style: BorderStyle): Glyphs {\n switch (style) {\n case \"double\":\n return { h: \"═\", v: \"║\", tl: \"╔\", tr: \"╗\", bl: \"╚\", br: \"╝\" };\n // Light double dash pair: two dashes per cell, cleaner than the triple\n // dash `┄`/`┆` which reads as dots in many fonts.\n case \"dashed\":\n return { h: \"╌\", v: \"╎\", tl: \"┌\", tr: \"┐\", bl: \"└\", br: \"┘\" };\n case \"dotted\":\n return { h: \"┄\", v: \"┊\", tl: \"┌\", tr: \"┐\", bl: \"└\", br: \"┘\" };\n default:\n return { h: \"─\", v: \"│\", tl: \"┌\", tr: \"┐\", bl: \"└\", br: \"┘\" };\n }\n}\n","import { collectBorderRuns } from \"./borders.ts\";\nimport type { BorderRun } from \"./borders.ts\";\nimport type { Insets, LayoutNode, Rect } from \"./types.ts\";\n\n/**\n * Write geometry custom properties on each source element and (re)paint the\n * decoration layer. Coordinates on LayoutNode are parent-relative; borders\n * are painted in absolute coordinates so we accumulate the parent origin as\n * we walk.\n */\nexport function render(root: LayoutNode, decorationLayer: HTMLElement): void {\n const borderRuns: BorderRun[] = [];\n walk(root, 0, 0, borderRuns, true);\n paintDecorations(decorationLayer, borderRuns);\n}\n\nfunction walk(\n node: LayoutNode,\n parentAbsX: number,\n parentAbsY: number,\n borderRuns: BorderRun[],\n isRoot: boolean,\n): void {\n const absX = parentAbsX + node.localRect.x;\n const absY = parentAbsY + node.localRect.y;\n\n if (!isRoot) {\n positionElement(\n node.source as HTMLElement,\n node.localRect,\n node.resolvedPadding,\n node.style.border,\n node.style.textAlignBlocked,\n node.style.overflow,\n node.style.whiteSpace,\n );\n }\n\n collectBorderRuns(\n node.style,\n { x: absX, y: absY, width: node.localRect.width, height: node.localRect.height },\n borderRuns,\n );\n\n for (const child of node.children) {\n walk(child, absX, absY, borderRuns, false);\n }\n}\n\nfunction positionElement(\n el: HTMLElement,\n rect: Rect,\n padding: Insets,\n border: Insets,\n textAlignBlocked: boolean,\n overflow: \"visible\" | \"clip\",\n whiteSpace: \"normal\" | \"nowrap\",\n): void {\n el.setAttribute(\"data-mw-laid-out\", \"\");\n if (whiteSpace === \"nowrap\") el.setAttribute(\"data-mw-nowrap\", \"\");\n else el.removeAttribute(\"data-mw-nowrap\");\n el.style.setProperty(\"--mw-x\", String(rect.x));\n el.style.setProperty(\"--mw-y\", String(rect.y));\n el.style.setProperty(\"--mw-w\", String(rect.width));\n el.style.setProperty(\"--mw-h\", String(rect.height));\n if (overflow === \"clip\") el.setAttribute(\"data-mw-clip\", \"\");\n else el.removeAttribute(\"data-mw-clip\");\n // The browser insets content by border + padding; the engine has already\n // allocated cells for both. We expose them separately so the companion CSS\n // reads naturally, and the CSS sums them into the actual `padding` (since\n // engine border is painted as glyphs, native border-width stays 0).\n el.style.setProperty(\"--mw-pt\", String(padding.top));\n el.style.setProperty(\"--mw-pr\", String(padding.right));\n el.style.setProperty(\"--mw-pb\", String(padding.bottom));\n el.style.setProperty(\"--mw-pl\", String(padding.left));\n el.style.setProperty(\"--mw-bt\", String(border.top));\n el.style.setProperty(\"--mw-br\", String(border.right));\n el.style.setProperty(\"--mw-bb\", String(border.bottom));\n el.style.setProperty(\"--mw-bl\", String(border.left));\n if (textAlignBlocked) el.setAttribute(\"data-mw-text-align-blocked\", \"\");\n else el.removeAttribute(\"data-mw-text-align-blocked\");\n}\n\nfunction paintDecorations(layer: HTMLElement, runs: BorderRun[]): void {\n layer.replaceChildren();\n for (const run of runs) {\n // One span PER CELL, not per run: box-drawing glyphs may come from a\n // fallback font with a different advance width than the measured cell\n // (e.g. Google Fonts subsets that omit box-drawing characters), so a\n // multi-glyph run would drift off the grid. Positioning every glyph\n // from the grid keeps borders aligned regardless of which font supplies\n // the glyph. Revisit as a perf optimization once we can detect that the\n // active font covers the glyphs (or when painting to canvas).\n for (let i = 0; i < run.length; i++) {\n const span = document.createElement(\"span\");\n span.setAttribute(\"aria-hidden\", \"true\");\n span.style.position = \"absolute\";\n span.style.left = `calc(${run.x + i} * var(--mw-cw))`;\n span.style.top = `calc(${run.y} * var(--mw-ch))`;\n span.style.font = \"inherit\";\n span.style.lineHeight = \"inherit\";\n span.style.whiteSpace = \"pre\";\n span.style.pointerEvents = \"none\";\n span.style.userSelect = \"none\";\n if (run.color) span.style.color = run.color;\n span.textContent = run.glyph;\n layer.appendChild(span);\n }\n }\n}\n","import { pxToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport type {\n AlignItems,\n BorderStyle,\n CellLength,\n CellStyle,\n Display,\n Insets,\n JustifyContent,\n PerSide,\n Size,\n} from \"./types.ts\";\n\n/**\n * Read the interpreted CellStyle for an element from its computed CSS.\n *\n * The host must have the `measuring` attribute set while this runs so the\n * engine's own geometry rules (from styles.css) don't feed their outputs back\n * into what we read.\n */\nexport function readCellStyle(el: Element, rootFontSizePx: number): CellStyle {\n const cs = getComputedStyle(el);\n const csm = supportsTypedOM(el) ? el.computedStyleMap() : null;\n const classAttr = el.getAttribute(\"class\") ?? \"\";\n const inlineStyle = (el as HTMLElement).style;\n\n const rawDisplay = cs.display;\n const display: Display =\n rawDisplay === \"flex\"\n ? \"flex\"\n : rawDisplay === \"grid\"\n ? \"grid\"\n : rawDisplay === \"none\"\n ? \"none\"\n : rawDisplay.startsWith(\"inline\")\n ? \"block\"\n : \"block\";\n\n return {\n display,\n flexDirection: cs.flexDirection.startsWith(\"column\") ? \"column\" : \"row\",\n flexReverse: cs.flexDirection.endsWith(\"-reverse\"),\n flexWrap: cs.flexWrap.startsWith(\"wrap\") ? \"wrap\" : \"nowrap\",\n wrapReverse: cs.flexWrap === \"wrap-reverse\",\n flexGrow: Number(cs.flexGrow) || 0,\n flexShrink: cs.flexShrink === \"\" ? 1 : Number(cs.flexShrink) || 0,\n // flex-basis keeps its computed form (percentages stay symbolic), so\n // plain getComputedStyle is reliable here — `flex-1` reads as \"0%\".\n flexBasis: readFlexBasis(cs.flexBasis, rootFontSizePx),\n order: Number(cs.order) || 0,\n justifyContent: mapJustify(cs.justifyContent),\n alignItems: mapAlign(cs.alignItems),\n alignSelf: mapAlignSelf(cs.alignSelf),\n width: readSize(csm, cs.width, \"width\", rootFontSizePx, classAttr, inlineStyle),\n height: readSize(csm, cs.height, \"height\", rootFontSizePx, classAttr, inlineStyle),\n minWidth: readLimit(cs.minWidth, rootFontSizePx) ?? \"auto\",\n minHeight: readLimit(cs.minHeight, rootFontSizePx) ?? \"auto\",\n maxWidth: readLimit(cs.maxWidth, rootFontSizePx),\n maxHeight: readLimit(cs.maxHeight, rootFontSizePx),\n padding: readPadding(cs, rootFontSizePx),\n margin: readMargin(cs, csm, classAttr, rootFontSizePx),\n gapX: readSpacing(cs.columnGap === \"normal\" ? \"0px\" : cs.columnGap, rootFontSizePx),\n gapY: readSpacing(cs.rowGap === \"normal\" ? \"0px\" : cs.rowGap, rootFontSizePx),\n border: readBorderInsets(cs),\n borderStyle: {\n top: mapBorderStyle(cs.borderTopStyle),\n right: mapBorderStyle(cs.borderRightStyle),\n bottom: mapBorderStyle(cs.borderBottomStyle),\n left: mapBorderStyle(cs.borderLeftStyle),\n },\n // Treat `hidden` and `clip` the same — both keep content inside the\n // box. Normalized to `clip` internally since that's the more precise\n // semantic for what we do (no scroll container, cheaper). Longhands\n // (`overflow-x`/`overflow-y`) are honored: setting just one axis to\n // hidden or clip still marks the element as clipping. `auto` and\n // `scroll` are left as \"visible\" here — real scrolling is deferred to\n // the scrolling milestone.\n overflow:\n isClipping(cs.overflow) || isClipping(cs.overflowX) || isClipping(cs.overflowY)\n ? \"clip\"\n : \"visible\",\n // `nowrap` and `pre` disable soft wrapping; `pre`'s whitespace\n // preservation is NOT honored (documented deviation — the tree builder\n // collapses whitespace). Readable via getComputedStyle because the\n // companion stylesheet's white-space lock is gated on `:not([measuring])`.\n whiteSpace: cs.whiteSpace === \"nowrap\" || cs.whiteSpace === \"pre\" ? \"nowrap\" : \"normal\",\n textOverflow: cs.textOverflow === \"ellipsis\" ? \"ellipsis\" : \"clip\",\n color: cs.color,\n backgroundColor: cs.backgroundColor === \"rgba(0, 0, 0, 0)\" ? undefined : cs.backgroundColor,\n borderColor: {\n top: cs.borderTopColor,\n right: cs.borderRightColor,\n bottom: cs.borderBottomColor,\n left: cs.borderLeftColor,\n },\n // Detect authored text-align via class + inline style rather than\n // getComputedStyle, since our own override would otherwise be echoed\n // back and cause oscillation. Inheritance is handled by CSS: forcing\n // `text-align: start` on the element that authors center/justify\n // cascades to its descendants automatically.\n textAlignBlocked: authoredTextAlignBlocked(classAttr, inlineStyle),\n };\n}\n\nfunction isClipping(value: string): boolean {\n return value === \"hidden\" || value === \"clip\";\n}\n\nfunction authoredTextAlignBlocked(classAttr: string, inlineStyle: CSSStyleDeclaration): boolean {\n if (/(?:^|[\\s:.[!])text-(?:center|justify)/.test(classAttr)) return true;\n const inline = inlineStyle.textAlign;\n return inline === \"center\" || inline === \"justify\";\n}\n\nfunction supportsTypedOM(\n el: Element,\n): el is Element & { computedStyleMap(): StylePropertyMapReadOnly } {\n return typeof (el as { computedStyleMap?: unknown }).computedStyleMap === \"function\";\n}\n\nfunction mapJustify(value: string): JustifyContent {\n switch (value) {\n case \"center\":\n return \"center\";\n case \"flex-end\":\n case \"end\":\n case \"right\":\n return \"end\";\n case \"space-between\":\n return \"space-between\";\n case \"space-around\":\n return \"space-around\";\n case \"space-evenly\":\n return \"space-evenly\";\n default:\n return \"start\";\n }\n}\n\nfunction mapAlign(value: string): AlignItems {\n switch (value) {\n case \"center\":\n return \"center\";\n case \"flex-end\":\n case \"end\":\n return \"end\";\n case \"stretch\":\n // CSS default for align-items on a flex container is \"normal\", which\n // behaves as \"stretch\" in flex/grid contexts.\n case \"normal\":\n case \"\":\n return \"stretch\";\n default:\n return \"start\";\n }\n}\n\nfunction mapAlignSelf(value: string): \"auto\" | AlignItems {\n if (value === \"auto\" || value === \"\" || value === \"normal\") return \"auto\";\n return mapAlign(value);\n}\n\n/**\n * Read margins, preserving `auto` as `null`.\n *\n * `getComputedStyle` returns *used* values for margins on flex items, which\n * means an authored `auto` has already been resolved to a pixel length by\n * the browser's own flex pass — we can't tell \"auto\" from a fixed number\n * anymore. Typed OM returns *computed* values, so \"auto\" survives; we use it\n * as the source of truth when available.\n *\n * On engines without Typed OM (Firefox pre-157), fall back to scanning the\n * class attribute for Tailwind auto-margin utilities. LTR only for now.\n */\nfunction readMargin(\n cs: CSSStyleDeclaration,\n csm: StylePropertyMapReadOnly | null,\n classAttr: string,\n rootFontSizePx: number,\n): PerSide<CellLength | null> {\n const readSide = (\n physical: string,\n logical: string,\n autoClassPattern: RegExp,\n ): CellLength | null => {\n if (csm) {\n const physicalValue = csm.get(physical)?.toString().trim();\n if (physicalValue === \"auto\") return null;\n const logicalValue = csm.get(logical)?.toString().trim();\n if (logicalValue === \"auto\") return null;\n // Percent margins must stay symbolic (getComputedStyle would hand\n // back a used px value resolved against the pre-grid natural layout).\n if (physicalValue?.endsWith(\"%\")) {\n const percent = parseFloat(physicalValue);\n if (Number.isFinite(percent) && percent !== 0) return { percent };\n }\n } else if (autoClassPattern.test(classAttr)) {\n return null;\n }\n const physicalValue = cs.getPropertyValue(physical);\n if (physicalValue === \"auto\") return null;\n const physicalCells = readSpacing(physicalValue, rootFontSizePx);\n if (physicalCells !== 0) return physicalCells;\n const logicalValue = cs.getPropertyValue(logical);\n if (logicalValue === \"auto\") return null;\n return readSpacing(logicalValue, rootFontSizePx);\n };\n return {\n top: readSide(\"margin-top\", \"margin-block-start\", /(?:^|[\\s:.[!])(?:m|my|mt)-auto\\b/),\n right: readSide(\"margin-right\", \"margin-inline-end\", /(?:^|[\\s:.[!])(?:m|mx|mr|me)-auto\\b/),\n bottom: readSide(\"margin-bottom\", \"margin-block-end\", /(?:^|[\\s:.[!])(?:m|my|mb)-auto\\b/),\n left: readSide(\"margin-left\", \"margin-inline-start\", /(?:^|[\\s:.[!])(?:m|mx|ml|ms)-auto\\b/),\n };\n}\n\nfunction mapBorderStyle(value: string): BorderStyle {\n switch (value) {\n case \"double\":\n return \"double\";\n case \"dashed\":\n return \"dashed\";\n case \"dotted\":\n return \"dotted\";\n default:\n return \"solid\";\n }\n}\n\n/**\n * Read a min/max constraint. Percentages must be kept symbolic (they resolve\n * against the parent's content box during layout) — naive px parsing would\n * read `\"100%\"` as 100px and produce a nonsense cell count.\n */\nfunction readLimit(value: string, rootFontSizePx: number): CellLength | undefined {\n if (!value || value === \"none\" || value === \"auto\") return undefined;\n if (value.endsWith(\"%\")) {\n const percent = parseFloat(value);\n return Number.isFinite(percent) ? { percent } : undefined;\n }\n const px = parseFloat(value);\n return Number.isFinite(px) ? pxToCells(px, rootFontSizePx) : undefined;\n}\n\n/**\n * Read a spacing length. Percentages stay symbolic — they resolve against\n * the containing block's width during layout (getComputedStyle would give\n * a used px value based on the pre-grid natural layout, which is wrong).\n */\nfunction readSpacing(value: string, rootFontSizePx: number): CellLength {\n if (!value || value === \"auto\" || value === \"none\") return 0;\n if (value.endsWith(\"%\")) {\n const percent = parseFloat(value);\n return Number.isFinite(percent) && percent !== 0 ? { percent } : 0;\n }\n const px = parseFloat(value);\n return Number.isFinite(px) ? pxToCells(px, rootFontSizePx) : 0;\n}\n\nfunction readSize(\n csm: StylePropertyMapReadOnly | null,\n fallback: string,\n key: \"width\" | \"height\",\n rootFontSizePx: number,\n classAttr: string,\n inlineStyle: CSSStyleDeclaration,\n): Size | undefined {\n if (csm) {\n const value = csm.get(key);\n if (value == null) return undefined;\n const s = value.toString().trim();\n if (s === \"auto\") return { kind: \"auto\" };\n const intrinsic = intrinsicSizeKeyword(s);\n if (intrinsic) return intrinsic;\n if (s.endsWith(\"%\")) return { kind: \"percent\", value: parseFloat(s) };\n if (s.endsWith(\"px\")) return { kind: \"cells\", value: pxToCells(parseFloat(s), rootFontSizePx) };\n if (s.endsWith(\"rem\"))\n return { kind: \"cells\", value: roundHalfAwayFromZero(parseFloat(s) / 0.25) };\n }\n // Fallback path (Firefox pre-157: no Typed OM). getComputedStyle returns\n // *used* values (always px) for box properties, so we can't distinguish\n // \"authored w-N\" from \"natural content width\". Look at what was authored:\n // inline styles first, then any Tailwind sizing utility in the class list.\n // If neither is present, treat as auto so intrinsic sizing kicks in.\n const inline = key === \"width\" ? inlineStyle.width : inlineStyle.height;\n if (inline) {\n if (inline === \"auto\") return { kind: \"auto\" };\n const intrinsic = intrinsicSizeKeyword(inline);\n if (intrinsic) return intrinsic;\n if (inline.endsWith(\"%\")) return { kind: \"percent\", value: parseFloat(inline) };\n const px = parseFloat(inline);\n if (Number.isFinite(px)) return { kind: \"cells\", value: pxToCells(px, rootFontSizePx) };\n }\n // Intrinsic-keyword utilities (`w-min`…) must be caught by class scan here:\n // getComputedStyle would hand back the browser's *used* px width, which is\n // measured content px — NOT on the spacing scale — and would convert to a\n // nonsense cell count.\n const axis = key === \"width\" ? \"w\" : \"h\";\n if (new RegExp(`(?:^|[\\\\s:.[!])${axis}-min\\\\b`).test(classAttr)) return { kind: \"min-content\" };\n if (new RegExp(`(?:^|[\\\\s:.[!])${axis}-max\\\\b`).test(classAttr)) return { kind: \"max-content\" };\n if (new RegExp(`(?:^|[\\\\s:.[!])${axis}-fit\\\\b`).test(classAttr)) return { kind: \"fit-content\" };\n if (!hasSizingUtility(classAttr, axis)) return { kind: \"auto\" };\n if (fallback === \"auto\") return { kind: \"auto\" };\n if (fallback.endsWith(\"%\")) return { kind: \"percent\", value: parseFloat(fallback) };\n const px = parseFloat(fallback);\n if (Number.isFinite(px)) return { kind: \"cells\", value: pxToCells(px, rootFontSizePx) };\n return undefined;\n}\n\n/**\n * CSS `flex-basis`. `auto` (and the unsupported `content`) → undefined, so\n * the layout falls back to the width-or-intrinsic base. `0%` (Tailwind\n * `flex-1`) must survive as an actual zero base.\n */\nfunction readFlexBasis(value: string, rootFontSizePx: number): Size | undefined {\n if (!value || value === \"auto\" || value === \"content\") return undefined;\n const keyword = intrinsicSizeKeyword(value);\n if (keyword) return keyword;\n if (value.endsWith(\"%\")) {\n const percent = parseFloat(value);\n return Number.isFinite(percent) ? { kind: \"percent\", value: percent } : undefined;\n }\n const px = parseFloat(value);\n return Number.isFinite(px) ? { kind: \"cells\", value: pxToCells(px, rootFontSizePx) } : undefined;\n}\n\nfunction intrinsicSizeKeyword(value: string): Size | undefined {\n if (value === \"min-content\") return { kind: \"min-content\" };\n if (value === \"max-content\") return { kind: \"max-content\" };\n if (value === \"fit-content\") return { kind: \"fit-content\" };\n return undefined;\n}\n\n/**\n * Detect whether an element has an authored `width` / `height` utility (not\n * `min-*` or `max-*`, which set separate properties). Handles variants\n * (`md:w-full`, `hover:w-0`) and arbitrary variant selectors (`[&_span]:w-2`).\n * Used only when Typed OM is unavailable.\n */\nfunction hasSizingUtility(classAttr: string, axis: \"w\" | \"h\"): boolean {\n const pattern = axis === \"w\" ? /(?:^|[\\s:.[!])w-/ : /(?:^|[\\s:.[!])h-/;\n return pattern.test(classAttr);\n}\n\nfunction readPadding(cs: CSSStyleDeclaration, rootFontSizePx: number): PerSide<CellLength> {\n return {\n top: readSpacing(cs.getPropertyValue(\"padding-top\"), rootFontSizePx),\n right: readSpacing(cs.getPropertyValue(\"padding-right\"), rootFontSizePx),\n bottom: readSpacing(cs.getPropertyValue(\"padding-bottom\"), rootFontSizePx),\n left: readSpacing(cs.getPropertyValue(\"padding-left\"), rootFontSizePx),\n };\n}\n\n/** Border widths use the 1px = 1 cell scale (not the spacing scale). */\nfunction readBorderInsets(cs: CSSStyleDeclaration): Insets {\n const readSide = (side: string, style: string) => {\n if (cs.getPropertyValue(style) === \"none\") return 0;\n return roundHalfAwayFromZero(parseFloat(cs.getPropertyValue(side)) || 0);\n };\n return {\n top: readSide(\"border-top-width\", \"border-top-style\"),\n right: readSide(\"border-right-width\", \"border-right-style\"),\n bottom: readSide(\"border-bottom-width\", \"border-bottom-style\"),\n left: readSide(\"border-left-width\", \"border-left-style\"),\n };\n}\n","export interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface Insets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** Insets where any side can be `null` to signal `auto` (used for margins). */\nexport interface NullableInsets {\n top: number | null;\n right: number | null;\n bottom: number | null;\n left: number | null;\n}\n\nexport type Size =\n | { kind: \"cells\"; value: number }\n | { kind: \"percent\"; value: number }\n | { kind: \"auto\" }\n /** Intrinsic sizing keywords (`w-min` / `w-max` / `w-fit`). Resolved\n * against content: min-content = longest unbreakable unit, max-content =\n * unwrapped size, fit-content = shrink-to-fit within the available space.\n * Only honored for `width`; on `height` they behave as `auto` (content\n * height already is the intrinsic height). */\n | { kind: \"min-content\" }\n | { kind: \"max-content\" }\n | { kind: \"fit-content\" };\n\nexport type Display = \"block\" | \"flex\" | \"grid\" | \"none\";\nexport type FlexDirection = \"row\" | \"column\";\nexport type FlexWrap = \"nowrap\" | \"wrap\";\nexport type JustifyContent =\n | \"start\"\n | \"center\"\n | \"end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\nexport type AlignItems = \"start\" | \"center\" | \"end\" | \"stretch\";\nexport type AlignSelf = \"auto\" | \"start\" | \"center\" | \"end\" | \"stretch\";\nexport type BorderStyle = \"solid\" | \"double\" | \"dashed\" | \"dotted\";\nexport type Overflow = \"visible\" | \"clip\";\nexport type WhiteSpace = \"normal\" | \"nowrap\";\n\n/** A length in whole cells, or a percentage kept symbolic until layout.\n * Percentages resolve against the CSS-appropriate basis at layout time:\n * the available extent for min/max (`max-w-full` = 100%), the containing\n * block's WIDTH for padding and margins (all four sides, per CSS), and the\n * container's own content box in the gap's axis for gaps. */\nexport type CellLength = number | { percent: number };\nexport type TextOverflow = \"clip\" | \"ellipsis\";\n\n/** One value per box edge (border style, border color, …). */\nexport interface PerSide<T> {\n top: T;\n right: T;\n bottom: T;\n left: T;\n}\n\nexport interface CellStyle {\n display: Display;\n flexDirection: FlexDirection;\n /** True for `row-reverse` / `column-reverse`: the main axis runs\n * backwards — items lay out in reverse order and `justify-content`\n * start/end swap meaning. */\n flexReverse: boolean;\n flexWrap: FlexWrap;\n /** True for `wrap-reverse`: lines stack from the cross-end (bottom-up). */\n wrapReverse: boolean;\n flexGrow: number;\n flexShrink: number;\n /** CSS `flex-basis`: the flex base size when not `auto`/undefined —\n * notably `0%` from Tailwind's `flex-1`, which makes grow distribute ALL\n * the space (equal columns) instead of just the extra. */\n flexBasis: Size | undefined;\n /** CSS `order` — flex items sort by it (stable, document order ties). */\n order: number;\n justifyContent: JustifyContent;\n alignItems: AlignItems;\n alignSelf: AlignSelf;\n width: Size | undefined;\n height: Size | undefined;\n /** `\"auto\"` is CSS `min-width/height: auto`: 0 in block flow, but a flex\n * item's automatic minimum (its min-content size, when overflow is\n * visible) on the flex main axis — the reason text in a flex row stops\n * shrinking instead of vanishing, and why `min-w-0` exists. */\n minWidth: CellLength | \"auto\";\n minHeight: CellLength | \"auto\";\n maxWidth: CellLength | undefined;\n maxHeight: CellLength | undefined;\n padding: PerSide<CellLength>;\n /** `null` = `auto`. Percentages resolve against the parent's content\n * width where the margin is consumed. */\n margin: PerSide<CellLength | null>;\n gapX: CellLength;\n gapY: CellLength;\n border: Insets;\n borderStyle: PerSide<BorderStyle>;\n borderColor: PerSide<string | undefined>;\n overflow: Overflow;\n /** `nowrap` disables soft wrapping (hard `<br>` breaks still apply). */\n whiteSpace: WhiteSpace;\n /** Paint-only: with `nowrap` + clipping, the browser draws the ellipsis.\n * The engine only needs it for the ASCII renderer's mirror of that. */\n textOverflow: TextOverflow;\n /**\n * Paint-only colors, reserved for the visual-system milestone. `color` will\n * feed decoration glyphs that visually belong to the text (control framing\n * like `[ Save ]`, cursors, selection carets); `backgroundColor` will feed\n * cell-level highlights (selection ranges, decoration backgrounds). Read\n * from the source element now so the future work has the data available.\n */\n color: string | undefined;\n backgroundColor: string | undefined;\n /** True when text-align is center/justify — forced back to `start` since\n * per-line centering can't be snapped to whole cells. See cell-model spec. */\n textAlignBlocked: boolean;\n}\n\nexport interface LayoutNode {\n source: Element;\n style: CellStyle;\n children: LayoutNode[];\n /** Raw text content of the element's direct text nodes (leaves only). Empty\n * for pure containers. May coexist with child element nodes when the\n * element has mixed text+element children. */\n text: string;\n intrinsicWidth: number;\n intrinsicHeight: number;\n localRect: Rect;\n /** Outer height before min/max clamping — written by layoutNode; the\n * column flex algorithm's base main size (CSS distributes from unclamped\n * bases; limits apply via its freeze loop). */\n unclampedHeight: number;\n /** Padding with percentages resolved to cells — written by layoutNode\n * (percent resolves against the containing block width, which only\n * layout knows); the renderers read this, never `style.padding`. */\n resolvedPadding: Insets;\n}\n\nexport interface CellMetrics {\n width: number;\n height: number;\n}\n\nexport function defaultCellStyle(): CellStyle {\n return {\n display: \"block\",\n flexDirection: \"row\",\n flexReverse: false,\n flexWrap: \"nowrap\",\n wrapReverse: false,\n flexGrow: 0,\n flexShrink: 0,\n flexBasis: undefined,\n order: 0,\n justifyContent: \"start\",\n alignItems: \"start\",\n alignSelf: \"auto\",\n width: undefined,\n height: undefined,\n minWidth: \"auto\",\n minHeight: \"auto\",\n maxWidth: undefined,\n maxHeight: undefined,\n padding: zeroInsets(),\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n gapX: 0,\n gapY: 0,\n border: zeroInsets(),\n borderStyle: { top: \"solid\", right: \"solid\", bottom: \"solid\", left: \"solid\" },\n overflow: \"visible\",\n whiteSpace: \"normal\",\n textOverflow: \"clip\",\n color: undefined,\n backgroundColor: undefined,\n borderColor: { top: undefined, right: undefined, bottom: undefined, left: undefined },\n textAlignBlocked: false,\n };\n}\n\nexport function zeroInsets(): Insets {\n return { top: 0, right: 0, bottom: 0, left: 0 };\n}\n","import { readCellStyle } from \"./style.ts\";\nimport { zeroInsets } from \"./types.ts\";\nimport type { LayoutNode } from \"./types.ts\";\n\n/**\n * Build a LayoutNode tree from an element subtree.\n *\n * Rules:\n * - Elements with computed `display: none` are skipped entirely.\n * - An element becomes a **leaf** if it has no element children, or if all\n * its element children have computed `display: inline`/`inline-*`/`contents`\n * (they're part of the inline text flow, not laid out separately). The\n * leaf's `text` is the element's combined `textContent`, so text nodes\n * interleaved with inline elements (`<div>hello <span>world</span></div>`)\n * participate in the wrap calculation and render correctly.\n * - Elements with at least one block-level element child become **containers**\n * and recurse. Direct text nodes on containers (uncommon in utility-first\n * markup) are not laid out — CSS creates anonymous inline boxes for them,\n * but our absolutely-positioned children escape that flow. This is\n * documented as a deviation in specs/cell-model.md.\n */\nexport function buildTree(root: Element, rootFontSizePx: number): LayoutNode | null {\n const style = readCellStyle(root, rootFontSizePx);\n if (style.display === \"none\") return null;\n\n const elementChildren = Array.from(root.children);\n const isInlineOnly = elementChildren.every(hasInlineDisplay);\n\n if (isInlineOnly) {\n // Per-hard-line trim: whitespace around a `<br>` is source formatting\n // (the browser collapses and strips it at line edges), not content.\n const text = extractLeafText(root)\n .split(\"\\n\")\n .map((line) => line.trim())\n .join(\"\\n\")\n .trim();\n const intrinsicWidth = longestLine(text);\n const intrinsicHeight = text.length > 0 ? countHardLines(text) : 0;\n return {\n source: root,\n style,\n children: [],\n text,\n intrinsicWidth,\n intrinsicHeight,\n localRect: { x: 0, y: 0, width: intrinsicWidth, height: intrinsicHeight },\n unclampedHeight: 0,\n resolvedPadding: zeroInsets(),\n };\n }\n\n const children: LayoutNode[] = [];\n for (const child of elementChildren) {\n const node = buildTree(child, rootFontSizePx);\n if (node) children.push(node);\n }\n return {\n source: root,\n style,\n children,\n text: \"\",\n intrinsicWidth: 0,\n intrinsicHeight: 0,\n localRect: { x: 0, y: 0, width: 0, height: 0 },\n unclampedHeight: 0,\n resolvedPadding: zeroInsets(),\n };\n}\n\n/**\n * HTML tags whose default display is inline. Checked BEFORE computed display\n * because a flex/grid parent \"blockifies\" its direct children (per CSS), so\n * `<br>`/`<span>`/etc. inside a `display: flex` element compute to \"block\".\n * For our purposes those are still semantically inline text-flow markers\n * and shouldn't force their parent into container mode.\n */\nconst INLINE_BY_DEFAULT_TAGS = new Set([\n \"A\",\n \"ABBR\",\n \"B\",\n \"BDI\",\n \"BDO\",\n \"BR\",\n \"CITE\",\n \"CODE\",\n \"DATA\",\n \"DFN\",\n \"EM\",\n \"I\",\n \"KBD\",\n \"MARK\",\n \"Q\",\n \"S\",\n \"SAMP\",\n \"SMALL\",\n \"SPAN\",\n \"STRONG\",\n \"SUB\",\n \"SUP\",\n \"TIME\",\n \"U\",\n \"VAR\",\n \"WBR\",\n]);\n\nfunction hasInlineDisplay(el: Element): boolean {\n if (INLINE_BY_DEFAULT_TAGS.has(el.tagName)) return true;\n const display = getComputedStyle(el).display;\n return display.startsWith(\"inline\") || display === \"contents\";\n}\n\n/**\n * Walk childNodes and produce the leaf's text — with `<br>` emitted as `\\n`\n * so the wrap calculation counts the line break the browser will honor.\n * Recurses into inline elements (`<span>`, `<a>`, `<b>`, …).\n *\n * Whitespace inside text nodes (including literal newlines from source\n * formatting) collapses to single spaces, exactly like the browser under\n * `white-space: normal` — ONLY `<br>` produces a hard `\\n`. Without this,\n * markup indentation would masquerade as hard line breaks and the engine\n * would allocate rows the browser never renders.\n */\nfunction extractLeafText(el: Element): string {\n const parts: string[] = [];\n for (const node of Array.from(el.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE) {\n // CSS collapsible white space only (space/tab/CR/LF/FF) — NOT `\\s`,\n // which would also eat NBSP (U+00A0); the browser preserves NBSP and\n // never breaks at it.\n parts.push((node.textContent ?? \"\").replace(/[ \\t\\r\\n\\f]+/g, \" \"));\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const child = node as Element;\n if (child.tagName === \"BR\") parts.push(\"\\n\");\n else parts.push(extractLeafText(child));\n }\n }\n return parts.join(\"\");\n}\n\nfunction longestLine(text: string): number {\n let max = 0;\n for (const line of text.split(\"\\n\")) if (line.length > max) max = line.length;\n return max;\n}\n\nfunction countHardLines(text: string): number {\n return text.split(\"\\n\").length;\n}\n","import { getRootFontSizePx, measureCellMetrics } from \"./metrics.ts\";\nimport { layoutRoot } from \"./layout.ts\";\nimport { render } from \"./render.ts\";\nimport { buildTree } from \"./tree.ts\";\nimport { defaultCellStyle } from \"./types.ts\";\nimport type { CellMetrics, LayoutNode } from \"./types.ts\";\n\nconst SHADOW_TEMPLATE = `\n<style>\n :host { display: block; position: relative; contain: layout style; }\n #viewport { position: relative; width: 100%; height: 100%; }\n #decorations { position: absolute; inset: 0; pointer-events: none; user-select: none; white-space: pre; }\n</style>\n<div id=\"viewport\">\n <div id=\"decorations\" aria-hidden=\"true\"></div>\n <slot></slot>\n</div>\n`;\n\nexport class MonoWindElement extends HTMLElement {\n #shadow: ShadowRoot;\n #decorations: HTMLElement;\n #resizeObserver: ResizeObserver | null = null;\n #mutationObserver: MutationObserver | null = null;\n #layoutPending = false;\n #suppressMutations = 0;\n #cellMetrics: CellMetrics | null = null;\n\n constructor() {\n super();\n this.#shadow = this.attachShadow({ mode: \"open\" });\n this.#shadow.innerHTML = SHADOW_TEMPLATE;\n this.#decorations = this.#shadow.getElementById(\"decorations\") as HTMLElement;\n }\n\n connectedCallback(): void {\n this.#resizeObserver = new ResizeObserver(() => this.#scheduleLayout());\n this.#resizeObserver.observe(this);\n\n this.#mutationObserver = new MutationObserver((records) => {\n if (this.#suppressMutations > 0) return;\n if (records.every(this.#isOwnedMutation)) return;\n // A class or style change on the host itself can shift font metrics\n // (font-size, font-family, letter-spacing). Invalidate the cache so\n // the next layout re-measures.\n if (records.some((r) => r.target === this && r.type === \"attributes\")) {\n this.#cellMetrics = null;\n }\n this.#scheduleLayout();\n });\n this.#mutationObserver.observe(this, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\"],\n });\n\n // Fonts can finish loading after our first layout (the first layout then\n // used fallback-font metrics), which would leave decorations positioned\n // with stale cell metrics. Two signals, both needed:\n // - `fonts.ready` — resolves when the initial font loads settle. WebKit\n // fires this reliably; keep it for the common first-load case.\n // - `loadingdone` — fires on every later font-load batch (lazily\n // triggered @font-face, dynamically added styles).\n // Re-measuring is cheap and layout runs at most once per frame.\n document.fonts?.ready.then(this.#onFontsLoaded).catch((err: unknown) => {\n console.warn(\"[monowind] document.fonts.ready failed:\", err);\n });\n document.fonts?.addEventListener(\"loadingdone\", this.#onFontsLoaded);\n\n this.#scheduleLayout();\n }\n\n disconnectedCallback(): void {\n this.#resizeObserver?.disconnect();\n this.#mutationObserver?.disconnect();\n this.#resizeObserver = null;\n this.#mutationObserver = null;\n document.fonts?.removeEventListener(\"loadingdone\", this.#onFontsLoaded);\n // Invalidate metrics — if the element is re-connected somewhere else,\n // the surrounding font/size may differ.\n this.#cellMetrics = null;\n }\n\n #onFontsLoaded = (): void => {\n this.#cellMetrics = null; // font may have changed dimensions\n this.#scheduleLayout();\n };\n\n #isOwnedMutation = (record: MutationRecord): boolean => {\n if (record.type !== \"attributes\") return false;\n const name = record.attributeName;\n if (name === \"data-mw-laid-out\") return true;\n if (name === \"data-mw-ready\") return true;\n if (name === \"data-mw-text-align-blocked\") return true;\n if (name === \"data-mw-clip\") return true;\n if (name === \"data-mw-nowrap\") return true;\n // Style attribute mutations are hard to filter precisely from the record\n // alone (we can't tell which property was set). Rely on the counter that\n // brackets our write phase — if we're inside it, treat as owned.\n if (name === \"style\") return this.#suppressMutations > 0;\n return false;\n };\n\n #scheduleLayout(): void {\n if (this.#layoutPending) return;\n this.#layoutPending = true;\n requestAnimationFrame(() => {\n this.#layoutPending = false;\n try {\n this.#performLayout();\n } catch (err) {\n console.error(\"[monowind] layout failed:\", err);\n }\n });\n }\n\n #performLayout(): void {\n // The write phase is bracketed by (a) incrementing #suppressMutations\n // and (b) setting the `measuring` attribute. Anything the engine writes\n // to the light DOM during this phase — geometry vars, data-mw-*\n // attributes, decoration DOM — is either filtered by the counter or\n // drained via takeRecords() at the end. The counter can slightly\n // over-filter (a third-party script mutating in the same task would\n // also be swallowed); that's an accepted trade-off for MVP.\n this.#suppressMutations++;\n this.setAttribute(\"measuring\", \"\");\n try {\n // (1) Cell metrics — cached; invalidated by disconnected callback\n // (implicit) and by document.fonts.ready.\n if (!this.#cellMetrics) {\n this.#cellMetrics = measureCellMetrics(this);\n this.style.setProperty(\"--mw-cw\", `${this.#cellMetrics.width}px`);\n this.style.setProperty(\"--mw-ch\", `${this.#cellMetrics.height}px`);\n }\n const metrics = this.#cellMetrics;\n\n // (2) Available cells from host's padding-box (clientWidth, not\n // getBoundingClientRect().width — the former excludes any user-set\n // border/padding on the host itself).\n const availableCols = Math.max(0, Math.floor(this.clientWidth / metrics.width));\n if (availableCols === 0) return;\n\n // (3) Build a tree from the light DOM. Root is a virtual container\n // over the light-DOM children so we can lay them out as a block.\n const rootFontSizePx = getRootFontSizePx();\n const childNodes: LayoutNode[] = [];\n for (const child of Array.from(this.children)) {\n const node = buildTree(child, rootFontSizePx);\n if (node) childNodes.push(node);\n }\n if (childNodes.length === 0) {\n this.#decorations.replaceChildren();\n this.setAttribute(\"data-mw-ready\", \"\");\n return;\n }\n const virtualRoot: LayoutNode = {\n source: this,\n style: defaultCellStyle(),\n children: childNodes,\n text: \"\",\n intrinsicWidth: 0,\n intrinsicHeight: 0,\n localRect: { x: 0, y: 0, width: 0, height: 0 },\n unclampedHeight: 0,\n resolvedPadding: { top: 0, right: 0, bottom: 0, left: 0 },\n };\n\n // (4) Compute integer layout.\n const { height } = layoutRoot(virtualRoot, availableCols);\n\n // (5) Write geometry + paint decorations. Do this before clearing the\n // measuring attribute so the browser only paints the final state.\n render(virtualRoot, this.#decorations);\n\n // (6) Size the host to match content rows (content-driven height).\n this.style.height = `${height * metrics.height}px`;\n\n // (7) Reveal the host now that layout is done — kills the FOUC where\n // the browser paints raw flex/block layout before the engine runs.\n this.setAttribute(\"data-mw-ready\", \"\");\n } finally {\n this.removeAttribute(\"measuring\");\n // Flush pending mutation records that our own writes caused before\n // re-enabling observation. Microtask ordering isn't strictly\n // guaranteed here (see note at top of #performLayout).\n queueMicrotask(() => {\n this.#mutationObserver?.takeRecords();\n this.#suppressMutations--;\n });\n }\n }\n}\n\n/** Register the <mono-wind> element (idempotent). */\nexport function defineMonoWind(): void {\n if (customElements.get(\"mono-wind\")) return;\n customElements.define(\"mono-wind\", MonoWindElement);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"mono-wind\": MonoWindElement;\n }\n}\n","import { collectBorderRuns } from \"./borders.ts\";\nimport type { BorderRun } from \"./borders.ts\";\nimport { wrapLines } from \"./wrap.ts\";\nimport type { LayoutNode } from \"./types.ts\";\n\n/**\n * Render a laid-out tree as plain-text ASCII art: borders as box-drawing\n * glyphs, leaf text word-wrapped inside its content box, everything else as\n * spaces.\n *\n * This is the engine's \"screenshot without a browser\": deterministic,\n * font-independent, and diffable — used for golden regression tests and as\n * a debugging/agent-inspection tool. It intentionally renders geometry the\n * way the browser would paint it (same border-run and word-wrap code), minus\n * colors and fonts.\n *\n * Content that overflows the root box is clipped at the grid edges.\n */\nexport function renderAscii(root: LayoutNode): string {\n const width = root.localRect.width;\n const height = root.localRect.height;\n if (width <= 0 || height <= 0) return \"\";\n\n const grid: string[][] = Array.from({ length: height }, () =>\n Array.from({ length: width }, () => \" \"),\n );\n const put = (x: number, y: number, glyph: string) => {\n if (x >= 0 && x < width && y >= 0 && y < height) grid[y]![x] = glyph;\n };\n\n walk(root, 0, 0, put);\n\n return grid.map((row) => row.join(\"\").trimEnd()).join(\"\\n\");\n}\n\ntype PutGlyph = (x: number, y: number, glyph: string) => void;\n\nfunction walk(node: LayoutNode, parentAbsX: number, parentAbsY: number, put: PutGlyph): void {\n const absX = parentAbsX + node.localRect.x;\n const absY = parentAbsY + node.localRect.y;\n const style = node.style;\n\n const borderRuns: BorderRun[] = [];\n collectBorderRuns(\n style,\n { x: absX, y: absY, width: node.localRect.width, height: node.localRect.height },\n borderRuns,\n );\n for (const run of borderRuns) {\n for (let i = 0; i < run.length; i++) put(run.x + i, run.y, run.glyph);\n }\n\n if (node.children.length === 0 && node.text) {\n const padding = node.resolvedPadding;\n const contentX = absX + style.border.left + padding.left;\n const contentY = absY + style.border.top + padding.top;\n const contentWidth =\n node.localRect.width - style.border.left - style.border.right - padding.left - padding.right;\n const lines =\n style.whiteSpace === \"nowrap\"\n ? node.text.split(\"\\n\").map((line) => truncateLine(line, contentWidth, style))\n : wrapLines(node.text, contentWidth);\n for (let row = 0; row < lines.length; row++) {\n const line = lines[row]!;\n for (let col = 0; col < line.length; col++) {\n put(contentX + col, contentY + row, line[col]!);\n }\n }\n }\n\n for (const child of node.children) {\n walk(child, absX, absY, put);\n }\n}\n\n/**\n * Mirror of what the browser paints for a nowrap line: a clipping box cuts\n * it at the content width, with `…` in the last visible cell when\n * `text-overflow: ellipsis` is set. A non-clipping nowrap line is left\n * intact — like the browser, it overflows (the grid edge clips it).\n */\nfunction truncateLine(line: string, contentWidth: number, style: LayoutNode[\"style\"]): string {\n if (style.overflow !== \"clip\" || line.length <= contentWidth) return line;\n if (contentWidth <= 0) return \"\";\n if (style.textOverflow === \"ellipsis\") return `${line.slice(0, contentWidth - 1)}…`;\n return line.slice(0, contentWidth);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/metrics.ts","../src/wrap.ts","../src/flex.ts","../src/types.ts","../src/grid.ts","../src/positioning.ts","../src/layout.ts","../src/borders.ts","../src/render.ts","../src/style.ts","../src/tree.ts","../src/element.ts","../src/ascii.ts"],"sourcesContent":["import type { CellMetrics } from \"./types.ts\";\n\n/** Round to nearest integer, ties away from zero (per specs/cell-model.md). */\nexport function roundHalfAwayFromZero(value: number): number {\n const rounded = value >= 0 ? Math.floor(value + 0.5) : -Math.floor(-value + 0.5);\n return rounded || 0; // normalize -0 → 0\n}\n\n/** Convert a computed px value to cells using the spacing scale (1 cell = 0.25rem). */\nexport function pxToCells(px: number, rootFontSizePx: number): number {\n if (rootFontSizePx <= 0) return 0;\n return roundHalfAwayFromZero(px / (0.25 * rootFontSizePx));\n}\n\n/** Convert a percentage of an integer container to whole cells, ties away from zero. */\nexport function percentToCells(percent: number, containerCells: number): number {\n return roundHalfAwayFromZero((containerCells * percent) / 100);\n}\n\n/** Measure the root's cell from the host's PERSISTENT shadow probe (100\n * \"M\"s inheriting the host's font): the advance of a monospace character\n * (with the root's own letter-spacing) and the line-box height. Root\n * leading/tracking thus size the grid; descendants' are quantized to it\n * (specs/cell-model.md). The probe must be long-lived: a throwaway node\n * created at measure time can transiently resolve the FALLBACK font even\n * after the real font has loaded (observed on CI Chromium), whereas a\n * persistent node is re-font-matched by the same machinery as real\n * content. */\nexport function measureCellMetrics(host: HTMLElement, probe: HTMLElement): CellMetrics {\n const rect = probe.getBoundingClientRect();\n const letterSpacing = parseFloat(getComputedStyle(host).letterSpacing) || 0;\n return { width: rect.width / 100, height: rect.height, letterSpacing };\n}\n\nexport function getRootFontSizePx(): number {\n return parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n}\n","/**\n * Greedy word-wrap for monospace text on the cell grid.\n *\n * Text is a string plus optional per-character `advances` (cells each\n * character occupies — 1 by default, `1 + tracking` for letter-spaced text;\n * see specs/cell-model.md). Words are runs of non-whitespace; whitespace\n * runs collapse to single spaces between fitting words. Browsers also treat\n * a hyphen inside a word as a break opportunity (break after `-`, no hyphen\n * added) — except before a digit, per UAX #14 (`2026-08` doesn't break) —\n * so words are further split into breakable segments. A segment wider than\n * `width` breaks at cell boundaries. `\\n` in the input is a HARD line break\n * — the wrap restarts on a new line (the source of these is `<br>`\n * elements, converted to `\\n` by the tree builder). A blank hard line still\n * occupies one row.\n *\n * Matches how a browser wraps `white-space: normal; overflow-wrap: anywhere`\n * text in a fixed-width monospace container — we set that in styles.css so\n * the two agree.\n */\n\n/** A wrapped line as an index range into the text (`end` exclusive). */\nexport interface LineSpan {\n start: number;\n end: number;\n}\n\n/**\n * Wrap options: per-character `advances` for tracked text (cells each\n * character occupies, `1 + tracking` of its innermost element), and the\n * leaf's own `tracking` — the trailing gap it absorbs at line ends (see\n * `lineAdvance`). Defaults: plain 1-cell characters, no tracking.\n */\nexport interface WrapOptions {\n advances?: number[] | undefined;\n tracking?: number;\n}\n\nexport function wrapLines(text: string, width: number, options: WrapOptions = {}): string[] {\n return wrapLineSpans(text, width, options).map((span) => text.slice(span.start, span.end));\n}\n\n/** Number of rows `text` occupies at `width` (see wrapLines). */\nexport function wrapLineCount(text: string, width: number, options: WrapOptions = {}): number {\n return wrapLineSpans(text, width, options).length;\n}\n\n/** Split at hard `\\n` breaks only (the `white-space: nowrap` line model). */\nexport function hardLineSpans(text: string): LineSpan[] {\n const spans: LineSpan[] = [];\n let start = 0;\n for (let i = 0; i <= text.length; i++) {\n if (i === text.length || text[i] === \"\\n\") {\n spans.push({ start, end: i });\n start = i + 1;\n }\n }\n return spans;\n}\n\nexport function wrapLineSpans(text: string, width: number, options: WrapOptions = {}): LineSpan[] {\n // Empty = nothing but collapsible white space. NOT `trim()`, which would\n // also eat NBSP — an NBSP-only leaf still renders a line in the browser.\n if (!/[^ \\t\\r\\n\\f]/.test(text)) return [];\n const spans: LineSpan[] = [];\n let lineStart = 0;\n for (let i = 0; i <= text.length; i++) {\n if (i === text.length || text[i] === \"\\n\") {\n spans.push(...wrapHardLine(text, lineStart, i, width, options));\n lineStart = i + 1;\n }\n }\n return spans;\n}\n\n/** Cells spanned by `text[start, end)`, every character's gap included. */\nexport function advanceOf(start: number, end: number, advances?: number[]): number {\n if (!advances) return end - start;\n let sum = 0;\n for (let i = start; i < end; i++) sum += advances[i] ?? 1;\n return sum;\n}\n\n/**\n * Cells `text[start, end)` occupies AS A LINE (specs/cell-model.md): up to\n * `tracking` (the leaf's own tracking) cells of the last character's gap\n * are trailing and don't count — the leaf's box reserves that room. A\n * tracked inline element's larger gap stays counted: browsers keep it at a\n * line end, and the engine doesn't cancel it (uniform across engines).\n */\nexport function lineAdvance(start: number, end: number, advances?: number[], tracking = 0): number {\n if (end <= start) return 0;\n return advanceOf(start, end, advances) - Math.min(tracking, trailingGap(end - 1, advances));\n}\n\nfunction trailingGap(index: number, advances?: number[]): number {\n return advances ? (advances[index] ?? 1) - 1 : 0;\n}\n\n/** Widest unbreakable unit (breakable segment) in the text — the\n * min-content width of a wrapping leaf. */\nexport function longestSegmentAdvance(text: string, options: WrapOptions = {}): number {\n const { advances, tracking = 0 } = options;\n let longest = 0;\n for (const word of wordRanges(text, 0, text.length)) {\n for (const segment of breakableSegmentRanges(text, word.start, word.end)) {\n longest = Math.max(longest, lineAdvance(segment.start, segment.end, advances, tracking));\n }\n }\n return longest;\n}\n\n/**\n * Split a word at its internal break opportunities: after each hyphen run,\n * unless the next character is a digit (UAX #14: no break between a hyphen\n * and a following number). `\"mx-auto\"` → `[\"mx-\", \"auto\"]`;\n * `\"2026-08\"` → `[\"2026-08\"]`.\n */\nexport function breakableSegments(word: string): string[] {\n return breakableSegmentRanges(word, 0, word.length).map((r) => word.slice(r.start, r.end));\n}\n\n/** U+FFFC marks an embedded atomic inline box (see LayoutNode.inlineBox):\n * unbreakable itself, but with break opportunities on BOTH sides, like\n * browsers give replaced elements. */\nexport const OBJECT_REPLACEMENT = \"\\uFFFC\";\n\n/** U+2060 (word joiner) marks ONE CELL of inline-element horizontal\n * padding in a run (specs/cell-model.md): pure blank space glued to its\n * neighbors — not collapsible white space, no break opportunity — so it\n * travels with the padded element's edge across wraps exactly like the\n * browser's `box-decoration-break: slice` padding. Multi-cell padding is\n * several 1-cell markers, keeping every gap/advance invariant intact.\n * (Escape form on purpose: the character is invisible.) */\nexport const INLINE_PAD = \"\\u2060\";\n\n/** Visit each object-replacement marker in a run, pairing its character\n * index with its ordinal (= index into the leaf's box list, which is in\n * run order). */\nexport function eachObjectMarker(\n text: ArrayLike<string>,\n visit: (charIndex: number, boxIndex: number) => void,\n): void {\n let boxIndex = 0;\n for (let i = 0; i < text.length; i++) {\n if (text[i] !== OBJECT_REPLACEMENT) continue;\n visit(i, boxIndex);\n boxIndex++;\n }\n}\n\nfunction breakableSegmentRanges(text: string, start: number, end: number): LineSpan[] {\n const segments: LineSpan[] = [];\n let segmentStart = start;\n for (let i = start; i < end; i++) {\n if (text[i] === OBJECT_REPLACEMENT) {\n if (i > segmentStart) segments.push({ start: segmentStart, end: i });\n segments.push({ start: i, end: i + 1 });\n segmentStart = i + 1;\n continue;\n }\n if (text[i] !== \"-\") continue;\n while (i + 1 < end && text[i + 1] === \"-\") i++;\n const next = i + 1;\n if (next < end && !/[0-9]/.test(text[next]!)) {\n segments.push({ start: segmentStart, end: next });\n segmentStart = next;\n }\n }\n segments.push({ start: segmentStart, end });\n return segments;\n}\n\n// CSS \"document white space\" only: space, tab, CR, LF, FF. Notably NOT NBSP\n// (U+00A0) — JS `\\s` would match it, but the browser neither collapses nor\n// breaks at it, so it must stay inside its word.\nconst COLLAPSIBLE = /[ \\t\\r\\n\\f]/;\n\nfunction wordRanges(text: string, start: number, end: number): LineSpan[] {\n const words: LineSpan[] = [];\n let i = start;\n while (i < end) {\n while (i < end && COLLAPSIBLE.test(text[i]!)) i++;\n if (i >= end) break;\n const wordStart = i;\n while (i < end && !COLLAPSIBLE.test(text[i]!)) i++;\n words.push({ start: wordStart, end: i });\n }\n return words;\n}\n\nfunction wrapHardLine(\n text: string,\n start: number,\n end: number,\n width: number,\n { advances, tracking = 0 }: WrapOptions,\n): LineSpan[] {\n const words = wordRanges(text, start, end);\n if (words.length === 0) return [{ start, end: start }];\n if (width <= 0) return [{ start: words[0]!.start, end: words[words.length - 1]!.end }];\n\n const lines: LineSpan[] = [];\n let current: LineSpan | null = null;\n // Advances accumulated over the current line, with words joined by ONE\n // space each regardless of the source whitespace run (collapsing).\n let advancesSum = 0;\n\n for (const word of words) {\n let joinsPrevious = false; // segments after the first attach with no space\n for (const segment of breakableSegmentRanges(text, word.start, word.end)) {\n let segStart = segment.start;\n const segEnd = segment.end;\n const separatorStart = current !== null && !joinsPrevious ? segStart - 1 : segStart;\n const candidate = advancesSum + advanceOf(separatorStart, segEnd, advances);\n const trailing = Math.min(tracking, trailingGap(segEnd - 1, advances));\n if (current !== null && candidate - trailing <= width) {\n current.end = segEnd;\n advancesSum = candidate;\n } else {\n if (current !== null) lines.push(current);\n // Break a too-wide segment at cell boundaries: a chunk of exactly\n // `width` stays as the current line (matching browser overflow-wrap).\n for (;;) {\n let fit = segStart;\n while (fit < segEnd && lineAdvance(segStart, fit + 1, advances, tracking) <= width) fit++;\n if (fit === segEnd || fit === segStart) break;\n lines.push({ start: segStart, end: fit });\n segStart = fit;\n }\n current = { start: segStart, end: segEnd };\n advancesSum = advanceOf(segStart, segEnd, advances);\n }\n joinsPrevious = true;\n }\n }\n if (current !== null) lines.push(current);\n return lines;\n}\n","import { percentToCells } from \"./metrics.ts\";\nimport {\n clampSize,\n intrinsicOuterWidth,\n isOutOfFlow,\n layoutNode,\n minContentOuterWidth,\n resolveLength,\n resolveLimit,\n resolveMargin,\n resolveSizeAgainst,\n} from \"./layout.ts\";\nimport type { IntrinsicCache } from \"./layout.ts\";\nimport type { CellStyle, Insets, LayoutNode, NullableInsets } from \"./types.ts\";\n\n/**\n * Flexbox (specs/flex.md): row and column algorithms, CSS §9.7 flexible\n * length resolution, and the shared distribution/alignment helpers. See\n * layout.ts for the deliberate import cycle between the layout modules.\n */\n\nexport function layoutFlexRow(\n node: LayoutNode,\n innerWidth: number,\n innerHeight: number,\n definiteInnerHeight: number | undefined,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const gapX = resolveLength(node.style.gapX, innerWidth);\n const gapY = resolveLength(node.style.gapY, innerHeight);\n const items = flexOrderedChildren(node).map((child) => {\n const margin = resolveMargin(child.style.margin, innerWidth);\n return {\n node: child,\n base: flexBaseOuterWidth(child, innerWidth, cache),\n grow: child.style.flexGrow,\n shrink: child.style.flexShrink,\n min: flexItemMinWidth(child, innerWidth, cache),\n max: resolveLimit(child.style.maxWidth, innerWidth),\n margin,\n };\n });\n\n // Break into rows greedily. With gap, an item breaks when `used + gap +\n // fixedMargins + base` exceeds innerWidth. The first item on a row is\n // always placed even if it alone overflows, matching CSS.\n const rows: (typeof items)[] = [];\n if (node.style.flexWrap === \"wrap\") {\n let current: typeof items = [];\n let used = 0;\n for (const item of items) {\n // Placement uses the hypothetical size (base clamped by min/max).\n const hypothetical = Math.max(0, clampSize(item.base, item.min, item.max));\n const itemWidth = hypothetical + (item.margin.left ?? 0) + (item.margin.right ?? 0);\n const next = current.length === 0 ? itemWidth : used + gapX + itemWidth;\n if (current.length > 0 && next > innerWidth) {\n rows.push(current);\n current = [];\n used = 0;\n }\n current.push(item);\n used = current.length === 1 ? itemWidth : used + gapX + itemWidth;\n }\n if (current.length > 0) rows.push(current);\n // wrap-reverse stacks the lines from the cross-end (bottom-up); items\n // within each line keep their main-axis order.\n if (node.style.wrapReverse) rows.reverse();\n } else {\n rows.push(items);\n }\n\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n\n // Phase A: resolve each line's item widths, lay the items out, and take\n // the line's natural height (tallest item).\n const lines = rows.map((row) => {\n const totalGap = gapX * Math.max(0, row.length - 1);\n const fixedMarginTotal = row.reduce(\n (sum, item) => sum + (item.margin.left ?? 0) + (item.margin.right ?? 0),\n 0,\n );\n const availableForItems = Math.max(0, innerWidth - totalGap - fixedMarginTotal);\n // Per CSS: if there's positive free space and any main-axis auto margin,\n // auto margins absorb the leftover BEFORE flex-grow. Detect that case and\n // keep items at their base size — the auto-margin loop below will\n // then distribute the leftover space itself.\n const rowHasAutoMainMargin = row.some(\n (item) => item.margin.left === null || item.margin.right === null,\n );\n const totalRowBase = row.reduce((s, i) => s + i.base, 0);\n const skipGrowForAutoMargins = rowHasAutoMainMargin && totalRowBase <= availableForItems;\n // When the distribution loop doesn't run, items take their HYPOTHETICAL\n // sizes (base clamped by min/max) — placement must agree with the sizes\n // the boxes actually get, not the raw bases.\n const widths = skipGrowForAutoMargins\n ? row.map((i) => Math.max(0, clampSize(i.base, i.min, i.max)))\n : resolveFlexMainAxis(row, availableForItems);\n for (let i = 0; i < row.length; i++) {\n layoutNode(row[i]!.node, innerWidth, definiteInnerHeight, 0, 0, \"fill\", cache, {\n width: widths[i]!,\n });\n }\n const height = row.reduce((h, item) => Math.max(h, item.node.localRect.height), 0);\n return { row, widths, availableForItems, height };\n });\n\n // Line heights and cross offsets (specs/flex.md step 9). A single nowrap\n // line stretches to a bounded inner height so items-center / items-end\n // have the enforced size to align against. A wrap-enabled (\"multi-line\",\n // per CSS — even with one line) container distributes bounded leftover\n // cross space per `align-content`: `stretch` grows the lines; the other\n // keywords offset them with the shared justify math.\n const rowHeights = lines.map((line) => line.height);\n const totalGapY = gapY * Math.max(0, lines.length - 1);\n let lineOffsets: number[];\n if (node.style.flexWrap === \"nowrap\") {\n if (Number.isFinite(innerHeight)) rowHeights[0] = Math.max(innerHeight, rowHeights[0] ?? 0);\n lineOffsets = [0];\n } else {\n const naturalTotal = rowHeights.reduce((s, h) => s + h, 0);\n const leftover = Number.isFinite(innerHeight)\n ? Math.max(0, innerHeight - naturalTotal - totalGapY)\n : 0;\n const alignContent = effectiveAlignContent(node.style);\n if (alignContent === \"stretch\" && leftover > 0) {\n const shares = distributeInteger(\n Array.from({ length: lines.length }, () => 1),\n leftover,\n );\n for (let i = 0; i < rowHeights.length; i++) rowHeights[i]! += shares[i]!;\n lineOffsets = mainAxisOffsets(\"start\", rowHeights, 0);\n } else {\n lineOffsets = mainAxisOffsets(\n alignContent === \"stretch\" ? \"start\" : alignContent,\n rowHeights,\n leftover,\n );\n }\n }\n\n // Phase B: per line, stretch items to the (possibly grown) line height\n // and place them.\n for (let rowIndex = 0; rowIndex < lines.length; rowIndex++) {\n const { row, widths, availableForItems } = lines[rowIndex]!;\n const rowHeight = rowHeights[rowIndex]!;\n const y = lineOffsets[rowIndex]! + rowIndex * gapY;\n\n // Stretch phase: any item whose effective cross alignment is `stretch`\n // (no explicit height, no auto cross-axis margins) grows to fill the\n // row. Re-run layoutNode with the height forced so nested content that\n // depends on the parent's height sees the final size.\n for (let i = 0; i < row.length; i++) {\n const child = row[i]!.node;\n const align = effectiveAlign(child, node);\n const itemMargin = row[i]!.margin;\n const hasCrossAutoMargin = itemMargin.top === null || itemMargin.bottom === null;\n // Treat `{kind: \"auto\"}` as no explicit height (Typed OM returns this\n // for elements that don't set a height; only `cells`/`percent` counts\n // as an author-set size that stretch should respect).\n const hasExplicitHeight =\n child.style.height !== undefined && child.style.height.kind !== \"auto\";\n if (\n align === \"stretch\" &&\n !hasCrossAutoMargin &&\n !hasExplicitHeight &&\n rowHeight > child.localRect.height\n ) {\n const marginTop = itemMargin.top ?? 0;\n const marginBottom = itemMargin.bottom ?? 0;\n // Per CSS, a stretched cross size is still clamped by the item's own\n // min/max-height (percent resolved against the container's inner\n // height when definite).\n const crossBasis = Number.isFinite(innerHeight) ? innerHeight : undefined;\n const stretchedHeight = clampSize(\n Math.max(0, rowHeight - marginTop - marginBottom),\n resolveLimit(child.style.minHeight, crossBasis) ?? 0,\n resolveLimit(child.style.maxHeight, crossBasis),\n );\n if (stretchedHeight === child.localRect.height) continue;\n layoutNode(child, innerWidth, definiteInnerHeight, 0, 0, \"fill\", cache, {\n width: widths[i]!,\n height: stretchedHeight,\n });\n }\n }\n const totalUsed = widths.reduce((s, w) => s + w, 0);\n const leftover = Math.max(0, availableForItems - totalUsed);\n\n // Auto margins on the main axis absorb leftover space (each gets an\n // equal share). If any exist, they override justify-content.\n const autoCount = row.reduce(\n (n, item) => n + (item.margin.left === null ? 1 : 0) + (item.margin.right === null ? 1 : 0),\n 0,\n );\n const autoMarginBefore: number[] = Array.from({ length: row.length }, () => 0);\n const autoMarginAfter: number[] = Array.from({ length: row.length }, () => 0);\n let offsets: number[];\n if (autoCount > 0 && leftover > 0) {\n const shares = distributeInteger(\n Array.from({ length: autoCount }, () => 1),\n leftover,\n );\n let shareIndex = 0;\n for (let i = 0; i < row.length; i++) {\n if (row[i]!.margin.left === null) autoMarginBefore[i] = shares[shareIndex++]!;\n if (row[i]!.margin.right === null) autoMarginAfter[i] = shares[shareIndex++]!;\n }\n offsets = mainAxisOffsets(\"start\", widths, 0);\n } else {\n offsets = mainAxisOffsets(effectiveJustify(node.style), widths, leftover);\n }\n\n let cumulativeExtraOffset = 0;\n for (let i = 0; i < row.length; i++) {\n const item = row[i]!;\n const child = item.node;\n const fixedLeft = item.margin.left ?? 0;\n const fixedRight = item.margin.right ?? 0;\n cumulativeExtraOffset += autoMarginBefore[i]! + fixedLeft;\n child.localRect = {\n ...child.localRect,\n x: originX + offsets[i]! + i * gapX + cumulativeExtraOffset,\n y: originY + y + crossAxisOffset(child, node.style.alignItems, rowHeight, item.margin),\n };\n cumulativeExtraOffset += autoMarginAfter[i]! + fixedRight;\n }\n }\n\n const totalOccupied = rowHeights.reduce((s, h) => s + h, 0) + totalGapY;\n const contentHeight = Number.isFinite(innerHeight)\n ? Math.max(innerHeight, totalOccupied)\n : totalOccupied;\n recordFlexStaticSlots(node, border, padding, innerWidth, contentHeight);\n return contentHeight;\n}\n\n/** Static slots for a flex container's out-of-flow children — the content\n * box plus alignment context, so the positioning pass can apply the CSS\n * \"as if it were the sole flex item\" rule once the box is sized. */\nfunction recordFlexStaticSlots(\n node: LayoutNode,\n border: Insets,\n padding: Insets,\n innerWidth: number,\n contentHeight: number,\n): void {\n for (const child of node.children) {\n if (!isOutOfFlow(child.style)) continue;\n child.staticSlot = {\n kind: \"flex\",\n direction: node.style.flexDirection,\n originX: border.left + padding.left,\n originY: border.top + padding.top,\n innerWidth,\n innerHeight: contentHeight,\n };\n }\n}\n\nexport function layoutFlexColumn(\n node: LayoutNode,\n innerWidth: number,\n innerHeight: number,\n heightIsDefinite: boolean,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const gapY = resolveLength(node.style.gapY, innerHeight);\n\n const items = flexOrderedChildren(node).map((child) => {\n const margin = resolveMargin(child.style.margin, innerWidth);\n const availableChildWidth = Math.max(0, innerWidth - (margin.left ?? 0) - (margin.right ?? 0));\n // Per-item cross-axis (width) stretch decision: parent's alignItems is\n // the default, but a child's own alignSelf wins if set. So an item with\n // `self-start` inside a stretch parent shrinks to intrinsic, not fills.\n const childStretch = effectiveAlign(child, node) === \"stretch\";\n // First pass at intrinsic height along the main axis. A definite\n // container height is the basis for the child's percent height.\n layoutNode(\n child,\n availableChildWidth,\n heightIsDefinite && Number.isFinite(innerHeight) ? innerHeight : undefined,\n 0,\n 0,\n childStretch ? \"fill\" : \"shrink\",\n cache,\n );\n const limitBasis = Number.isFinite(innerHeight) ? innerHeight : undefined;\n // Base main size per CSS flex-basis: an explicit basis (cells, or\n // percent against a definite container height) wins; otherwise the\n // first-pass height BEFORE min/max clamping — distribution starts from\n // raw bases, the freeze loop enforces the limits.\n const basis = child.style.flexBasis;\n const base =\n basis === undefined || basis.kind === \"auto\"\n ? child.unclampedHeight\n : basis.kind === \"cells\"\n ? basis.value\n : basis.kind === \"percent\" && limitBasis !== undefined\n ? percentToCells(basis.value, limitBasis)\n : child.unclampedHeight;\n // `min-height: auto` on a column item is the automatic minimum: its\n // content height (the first-pass laid-out height), unless overflow is\n // non-visible. Same rule as the row's min-content width.\n const autoMin =\n child.style.minHeight === \"auto\"\n ? child.style.overflow === \"visible\"\n ? child.localRect.height\n : 0\n : undefined;\n return {\n node: child,\n base,\n grow: child.style.flexGrow,\n shrink: child.style.flexShrink,\n min: autoMin ?? resolveLimit(child.style.minHeight, limitBasis) ?? 0,\n max: resolveLimit(child.style.maxHeight, limitBasis),\n margin,\n };\n });\n\n const totalGap = gapY * Math.max(0, items.length - 1);\n const fixedMarginTotal = items.reduce(\n (sum, item) => sum + (item.margin.top ?? 0) + (item.margin.bottom ?? 0),\n 0,\n );\n const finiteInner = Number.isFinite(innerHeight);\n const totalBaseHeight = items.reduce((s, i) => s + i.base, 0);\n const definiteAvailable = finiteInner\n ? Math.max(0, innerHeight - totalGap - fixedMarginTotal)\n : totalBaseHeight;\n // A min-height-only container size is a floor, not a cap: it can hand\n // extra space to flex-grow, but content larger than the floor keeps its\n // intrinsic size (no flex-shrink) and the container grows to fit.\n const availableForItems = heightIsDefinite\n ? definiteAvailable\n : Math.max(definiteAvailable, totalBaseHeight);\n\n // Same CSS rule as flex-row: auto margins on the main axis absorb positive\n // leftover before flex-grow gets to it.\n const columnHasAutoMainMargin = items.some(\n (item) => item.margin.top === null || item.margin.bottom === null,\n );\n const skipGrowForAutoMargins =\n finiteInner && columnHasAutoMainMargin && totalBaseHeight <= availableForItems;\n // Without distribution, items take their HYPOTHETICAL sizes (base clamped\n // by min/max) — stacking with raw bases would disagree with the heights\n // the boxes actually get (e.g. a min-h child would overlap its follower).\n const finalHeights =\n finiteInner && !skipGrowForAutoMargins\n ? resolveFlexMainAxis(items, availableForItems)\n : items.map((i) => Math.max(0, clampSize(i.base, i.min, i.max)));\n // If a child's main-axis size changed, re-run its layout with the new\n // height forced so any nested content that depends on the parent's height\n // (items-center/end in a nested flex, percent heights) sees the final size.\n for (let i = 0; i < items.length; i++) {\n if (finalHeights[i] !== items[i]!.node.localRect.height) {\n const item = items[i]!;\n const availableChildWidth = Math.max(\n 0,\n innerWidth - (item.margin.left ?? 0) - (item.margin.right ?? 0),\n );\n const childStretch = effectiveAlign(item.node, node) === \"stretch\";\n layoutNode(\n item.node,\n availableChildWidth,\n finalHeights[i]!,\n 0,\n 0,\n childStretch ? \"fill\" : \"shrink\",\n cache,\n { height: finalHeights[i]! },\n );\n }\n }\n\n const totalUsed = finalHeights.reduce((s, h) => s + h, 0);\n const leftover = Math.max(0, availableForItems - totalUsed);\n\n const autoCount = items.reduce(\n (n, item) => n + (item.margin.top === null ? 1 : 0) + (item.margin.bottom === null ? 1 : 0),\n 0,\n );\n const autoMarginBefore: number[] = Array.from({ length: items.length }, () => 0);\n const autoMarginAfter: number[] = Array.from({ length: items.length }, () => 0);\n let offsets: number[];\n if (autoCount > 0 && leftover > 0) {\n const shares = distributeInteger(\n Array.from({ length: autoCount }, () => 1),\n leftover,\n );\n let shareIndex = 0;\n for (let i = 0; i < items.length; i++) {\n if (items[i]!.margin.top === null) autoMarginBefore[i] = shares[shareIndex++]!;\n if (items[i]!.margin.bottom === null) autoMarginAfter[i] = shares[shareIndex++]!;\n }\n offsets = mainAxisOffsets(\"start\", finalHeights, 0);\n } else {\n offsets = mainAxisOffsets(effectiveJustify(node.style), finalHeights, leftover);\n }\n\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n let cumulativeExtraOffset = 0;\n for (let i = 0; i < items.length; i++) {\n const item = items[i]!;\n const child = item.node;\n const fixedTop = item.margin.top ?? 0;\n const fixedBottom = item.margin.bottom ?? 0;\n cumulativeExtraOffset += autoMarginBefore[i]! + fixedTop;\n child.localRect = {\n ...child.localRect,\n x: originX + crossAxisOffsetX(child, node.style.alignItems, innerWidth, item.margin),\n y: originY + offsets[i]! + i * gapY + cumulativeExtraOffset,\n };\n cumulativeExtraOffset += autoMarginAfter[i]! + fixedBottom;\n }\n\n const totalOccupied = totalUsed + totalGap + fixedMarginTotal;\n const contentHeight = finiteInner ? Math.max(innerHeight, totalOccupied) : totalOccupied;\n recordFlexStaticSlots(node, border, padding, innerWidth, contentHeight);\n return contentHeight;\n}\n\n/**\n * Compute a child's cross-axis (vertical) offset inside a flex row, honoring\n * align-self override, cross-axis auto margins, and fixed cross-axis margins.\n */\nfunction crossAxisOffset(\n child: LayoutNode,\n parentAlign: CellStyle[\"alignItems\"],\n rowHeight: number,\n m: NullableInsets,\n): number {\n const align = child.style.alignSelf === \"auto\" ? parentAlign : child.style.alignSelf;\n const marginTop = m.top ?? 0;\n const marginBottom = m.bottom ?? 0;\n const crossAvailable = rowHeight - child.localRect.height;\n const bothAuto = m.top === null && m.bottom === null;\n const oneAutoTop = m.top === null && m.bottom !== null;\n const oneAutoBottom = m.bottom === null && m.top !== null;\n if (bothAuto) return Math.floor(crossAvailable / 2);\n if (oneAutoTop) return crossAvailable - marginBottom;\n if (oneAutoBottom) return marginTop;\n return marginTop + alignCrossOffset(align, rowHeight, child.localRect.height);\n}\n\n/**\n * Symmetric helper for flex-column: cross axis is horizontal, so auto/fixed\n * margins on `left`/`right` participate.\n */\nfunction crossAxisOffsetX(\n child: LayoutNode,\n parentAlign: CellStyle[\"alignItems\"],\n containerWidth: number,\n m: NullableInsets,\n): number {\n const align = child.style.alignSelf === \"auto\" ? parentAlign : child.style.alignSelf;\n const marginLeft = m.left ?? 0;\n const marginRight = m.right ?? 0;\n const crossAvailable = containerWidth - child.localRect.width;\n const bothAuto = m.left === null && m.right === null;\n const oneAutoLeft = m.left === null && m.right !== null;\n const oneAutoRight = m.right === null && m.left !== null;\n if (bothAuto) return Math.floor(crossAvailable / 2);\n if (oneAutoLeft) return crossAvailable - marginRight;\n if (oneAutoRight) return marginLeft;\n return marginLeft + alignCrossOffset(align, containerWidth, child.localRect.width);\n}\n\n/**\n * Position each item along the main axis given its size and leftover space.\n * Returns the offset from container inner origin for each item.\n */\nexport function mainAxisOffsets(\n justify: CellStyle[\"justifyContent\"],\n sizes: number[],\n leftover: number,\n): number[] {\n const count = sizes.length;\n if (count === 0) return [];\n\n const offsets: number[] = [];\n let cursor = 0;\n\n if (justify === \"space-between\" && count > 1) {\n const gapBase = Math.floor(leftover / (count - 1));\n const extra = leftover - gapBase * (count - 1);\n for (let i = 0; i < count; i++) {\n offsets.push(cursor);\n cursor += sizes[i]! + gapBase + (i < extra ? 1 : 0);\n }\n return offsets;\n }\n\n // space-around: every item gets equal space on both sides, so the edge\n // gaps are half the inner ones (weights 1,2,…,2,1 over the n+1 gap\n // slots). space-evenly: all n+1 gaps equal. Integer-distributed with the\n // shared remainder rule, so the result is deterministic.\n if ((justify === \"space-around\" || justify === \"space-evenly\") && leftover > 0) {\n const weights = Array.from({ length: count + 1 }, (_, i) =>\n justify === \"space-evenly\" || i === 0 || i === count ? 1 : 2,\n );\n const gaps = distributeInteger(weights, leftover);\n for (let i = 0; i < count; i++) {\n cursor += gaps[i]!;\n offsets.push(cursor);\n cursor += sizes[i]!;\n }\n return offsets;\n }\n\n if (justify === \"center\") cursor = Math.floor(leftover / 2);\n else if (justify === \"end\") cursor = leftover;\n\n for (let i = 0; i < count; i++) {\n offsets.push(cursor);\n cursor += sizes[i]!;\n }\n return offsets;\n}\n\n/**\n * Resolve flex main-axis sizes per CSS Flexbox §9.7 (\"Resolving Flexible\n * Lengths\"), adapted to integers: distribute free space proportionally to\n * grow factors (or shrink weights = base × shrink), clamp each result to the\n * item's own min/max, FREEZE the items whose clamp fired, and redistribute\n * among the rest — repeating until nothing new violates. Without the\n * redistribution rounds, an item clamped up to `min-w-*` would keep space\n * its neighbors were already told they could use, and boxes would overlap.\n *\n * `min`/`max` are outer main sizes in cells, already resolved from percent.\n * When clamps bind, the returned sizes may sum to less or more than\n * `available` — that's CSS (`justify-content` sees the underfill; overflow\n * handles the excess).\n */\nexport function resolveFlexMainAxis(\n items: ReadonlyArray<{\n base: number;\n grow: number;\n shrink: number;\n min?: number | undefined;\n max?: number | undefined;\n }>,\n available: number,\n): number[] {\n const count = items.length;\n const clamp = (value: number, index: number) =>\n Math.max(0, clampSize(value, items[index]!.min ?? 0, items[index]!.max));\n const base = items.map((i) => i.base);\n // Grow vs shrink is decided from the HYPOTHETICAL sizes (clamped bases),\n // per CSS; distribution then starts from the raw bases.\n const hypotheticalTotal = base.reduce((s, b, i) => s + clamp(b, i), 0);\n const growing = available >= hypotheticalTotal;\n\n const sizes: number[] = Array.from({ length: count }, () => 0);\n const frozen: boolean[] = Array.from({ length: count }, () => false);\n // Pre-freeze inflexible items, and items whose base already violates in\n // the flex direction (max-violation when growing, min-violation when\n // shrinking), at their hypothetical size. A base merely BELOW its min\n // while growing stays flexible — it grows from the raw base and the\n // violation loop enforces the min afterwards.\n for (let i = 0; i < count; i++) {\n const hypothetical = clamp(base[i]!, i);\n const flexFactor = growing ? items[i]!.grow : items[i]!.shrink;\n if (\n flexFactor === 0 ||\n (growing && base[i]! > hypothetical) ||\n (!growing && base[i]! < hypothetical)\n ) {\n sizes[i] = hypothetical;\n frozen[i] = true;\n }\n }\n\n // Each round freezes at least one item, so this terminates within `count`\n // iterations.\n for (;;) {\n const unfrozen: number[] = [];\n for (let i = 0; i < count; i++) if (!frozen[i]) unfrozen.push(i);\n if (unfrozen.length === 0) break;\n\n const frozenTotal = sizes.reduce((s, v, i) => (frozen[i] ? s + v : s), 0);\n const unfrozenBaseTotal = unfrozen.reduce((s, i) => s + base[i]!, 0);\n const freeSpace = available - frozenTotal - unfrozenBaseTotal;\n const amount = growing ? Math.max(0, freeSpace) : Math.max(0, -freeSpace);\n\n const weights = unfrozen.map((i) => (growing ? items[i]!.grow : base[i]! * items[i]!.shrink));\n const shares = distributeInteger(weights, amount);\n const tentative = unfrozen.map((i, k) => base[i]! + (growing ? shares[k]! : -shares[k]!));\n const clamped = unfrozen.map((i, k) => clamp(tentative[k]!, i));\n const totalViolation = clamped.reduce((s, v, k) => s + (v - tentative[k]!), 0);\n\n if (totalViolation === 0) {\n for (let k = 0; k < unfrozen.length; k++) sizes[unfrozen[k]!] = clamped[k]!;\n break;\n }\n // Freeze only the violators on the dominant side (min violations when\n // the total is positive, max violations when negative) and go again.\n for (let k = 0; k < unfrozen.length; k++) {\n const violation = clamped[k]! - tentative[k]!;\n if (totalViolation > 0 ? violation > 0 : violation < 0) {\n sizes[unfrozen[k]!] = clamped[k]!;\n frozen[unfrozen[k]!] = true;\n }\n }\n }\n return sizes;\n}\n\n/**\n * Distribute `total` integer units across N slots proportionally to `weights`,\n * with the remainder (from flooring) given to the slots with the largest\n * fractional part — deterministic, document order for ties.\n */\nexport function distributeInteger(weights: number[], total: number): number[] {\n const sum = weights.reduce((s, w) => s + w, 0);\n if (sum === 0 || total <= 0) return weights.map(() => 0);\n const raw = weights.map((w) => (w / sum) * total);\n const floored = raw.map(Math.floor);\n let deficit = total - floored.reduce((s, v) => s + v, 0);\n if (deficit > 0) {\n const order = raw\n .map((v, i) => [i, v - Math.floor(v)] as const)\n .sort((a, b) => (b[1] === a[1] ? a[0] - b[0] : b[1] - a[1]));\n for (const [i] of order) {\n if (deficit <= 0) break;\n floored[i]! += 1;\n deficit -= 1;\n }\n }\n return floored;\n}\n\n/** A flex item's cross alignment: its own align-self, else the parent's\n * align-items. */\nexport function effectiveAlign(child: LayoutNode, parent: LayoutNode): CellStyle[\"alignItems\"] {\n return child.style.alignSelf === \"auto\"\n ? parent.style.alignItems\n : (child.style.alignSelf as CellStyle[\"alignItems\"]);\n}\n\nexport function alignCrossOffset(\n align: CellStyle[\"alignItems\"],\n container: number,\n child: number,\n): number {\n if (align === \"center\") return Math.max(0, Math.floor((container - child) / 2));\n if (align === \"end\") return Math.max(0, container - child);\n return 0;\n}\n\n/**\n * A flex-row item's base main size, per CSS `flex-basis`: an explicit basis\n * if set, else the item's explicit width (cells, percent, or an intrinsic\n * keyword), else its max-content size. Percentages resolve against the\n * container's content box (`innerWidth`). NOT clamped by min/max —\n * distribution starts from the raw base per CSS §9.7 (clamping happens via\n * the freeze/violation loop); pre-clamping would e.g. leave `flex-1`\n * columns unequal at their content minimums.\n */\nfunction flexBaseOuterWidth(child: LayoutNode, innerWidth: number, cache: IntrinsicCache): number {\n const basis = child.style.flexBasis;\n const width = child.style.width;\n if (basis !== undefined && basis.kind !== \"auto\") {\n return resolveSizeAgainst(basis, innerWidth, child, cache);\n }\n if (width !== undefined && width.kind !== \"auto\") {\n return resolveSizeAgainst(width, innerWidth, child, cache);\n }\n return intrinsicOuterWidth(child, cache);\n}\n\n/**\n * Flex item order: stable sort by CSS `order` (document order breaks\n * ties), then reversed for `row-reverse` / `column-reverse` — the main\n * axis runs backwards, so laying reversed children in a normal row with\n * flipped justify start/end is equivalent.\n */\nfunction flexOrderedChildren(node: LayoutNode): LayoutNode[] {\n const children = node.children\n .filter((c) => !isOutOfFlow(c.style))\n .sort((a, b) => a.style.order - b.style.order);\n if (node.style.flexReverse) children.reverse();\n return children;\n}\n\n/** wrap-reverse runs the cross axis backwards: start/end swap, the\n * symmetric values are unaffected (the line order is already reversed at\n * collection time). */\nfunction effectiveAlignContent(style: CellStyle): CellStyle[\"alignContent\"] {\n if (!style.wrapReverse) return style.alignContent;\n if (style.alignContent === \"start\") return \"end\";\n if (style.alignContent === \"end\") return \"start\";\n return style.alignContent;\n}\n\nexport function effectiveJustify(style: CellStyle): CellStyle[\"justifyContent\"] {\n // `stretch` (CSS `normal`/`stretch`) behaves as `start` in flex, per\n // css-align — normalize before the reverse flip so `row-reverse` still\n // packs from the main-start (right) edge under the default value.\n const justify = style.justifyContent === \"stretch\" ? \"start\" : style.justifyContent;\n if (!style.flexReverse) return justify;\n if (justify === \"start\") return \"end\";\n if (justify === \"end\") return \"start\";\n return justify;\n}\n\n/**\n * A flex-row item's used minimum width. `min-width: auto` (the CSS default)\n * is the automatic minimum: the item's min-content size — which is why text\n * in a flex row stops shrinking at its longest segment instead of\n * disappearing. It only applies while overflow is visible: `overflow` set\n * to anything else (e.g. via `truncate`) or an explicit `min-w-*` opts out.\n */\nfunction flexItemMinWidth(child: LayoutNode, innerWidth: number, cache: IntrinsicCache): number {\n if (child.style.minWidth === \"auto\") {\n return child.style.overflow === \"visible\" ? minContentOuterWidth(child, cache) : 0;\n }\n return resolveLimit(child.style.minWidth, innerWidth) ?? 0;\n}\n","export interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface Insets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** Insets where any side can be `null` to signal `auto` (used for margins). */\nexport interface NullableInsets {\n top: number | null;\n right: number | null;\n bottom: number | null;\n left: number | null;\n}\n\nexport type Size =\n | { kind: \"cells\"; value: number }\n | { kind: \"percent\"; value: number }\n | { kind: \"auto\" }\n /** Intrinsic sizing keywords (`w-min` / `w-max` / `w-fit`). Resolved\n * against content: min-content = longest unbreakable unit, max-content =\n * unwrapped size, fit-content = shrink-to-fit within the available space.\n * Only honored for `width`; on `height` they behave as `auto` (content\n * height already is the intrinsic height). */\n | { kind: \"min-content\" }\n | { kind: \"max-content\" }\n | { kind: \"fit-content\" };\n\nexport type Display = \"block\" | \"flex\" | \"grid\" | \"none\";\nexport type FlexDirection = \"row\" | \"column\";\nexport type FlexWrap = \"nowrap\" | \"wrap\";\nexport type JustifyContent =\n | \"start\"\n | \"center\"\n | \"end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\"\n /** CSS `normal` / `stretch`. In flex both behave as `start` (per\n * css-align); in grid they stretch auto-sized tracks over leftover space\n * (CSS Grid §11.8) and otherwise behave as `start`. */\n | \"stretch\";\nexport type AlignItems = \"start\" | \"center\" | \"end\" | \"stretch\";\n/** Multi-line cross distribution (`content-*`); `stretch` (the CSS\n * default `normal`) grows flex lines / grid tracks instead of offsetting\n * them. */\nexport type AlignContent = JustifyContent;\nexport type AlignSelf = \"auto\" | \"start\" | \"center\" | \"end\" | \"stretch\";\nexport type BorderStyle = \"solid\" | \"double\" | \"dashed\" | \"dotted\";\nexport type Overflow = \"visible\" | \"clip\";\nexport type Position = \"static\" | \"relative\" | \"absolute\" | \"fixed\" | \"sticky\";\n/** `nowrap` disables soft wrapping; `pre` additionally preserves the\n * source's spaces and newlines (specs/cell-model.md). Everything else\n * (`pre-wrap` included) behaves as `normal`. */\nexport type WhiteSpace = \"normal\" | \"nowrap\" | \"pre\";\n\n/** A length in whole cells, or a percentage kept symbolic until layout.\n * Percentages resolve against the CSS-appropriate basis at layout time:\n * the available extent for min/max (`max-w-full` = 100%), the containing\n * block's WIDTH for padding and margins (all four sides, per CSS), and the\n * container's own content box in the gap's axis for gaps. */\nexport type CellLength = number | { percent: number };\n\n/** A min/max constraint: a CellLength, or an intrinsic sizing keyword\n * (`max-w-max` = `max-width: max-content`, …). Keywords are honored on\n * width limits and behave as \"no constraint\" on height limits (content\n * height already is the intrinsic height). */\nexport type SizeLimit = CellLength | \"min-content\" | \"max-content\" | \"fit-content\";\nexport type TextOverflow = \"clip\" | \"ellipsis\";\n\n/** One bound of a grid track size (specs/grid.md). `fr` is only valid as a\n * max (the reader normalizes bare `<n>fr` to `minmax(auto, <n>fr)`, per\n * CSS); percent resolves against the container's content box in the\n * track's axis (indefinite axis → treated as `auto`). */\nexport type TrackBreadth =\n | { kind: \"cells\"; value: number }\n | { kind: \"percent\"; value: number }\n | { kind: \"fr\"; value: number }\n | { kind: \"auto\" }\n | { kind: \"min-content\" }\n | { kind: \"max-content\" }\n /** `min()` / `max()` over fixed breadths — the canonical responsive\n * auto-fill pattern `minmax(min(8rem, 100%), 1fr)`. Resolvable only\n * when every argument is (a percent argument needs a definite axis);\n * otherwise the whole function behaves as `auto`. `calc()` arithmetic\n * stays unsupported (specs/grid.md deviations). */\n | { kind: \"math\"; fn: \"min\" | \"max\"; args: TrackBreadth[] };\n\n/** A grid track as a normalized minmax pair — every track-size form reads\n * as one (`8rem` → minmax(cells, cells), `1fr` → minmax(auto, fr), …). */\nexport interface TrackSize {\n min: TrackBreadth;\n max: TrackBreadth;\n}\n\n/** A parsed `grid-template-columns` / `grid-template-rows`. Fixed repeats\n * are expanded at read time; an `auto-fill` / `auto-fit` repetition stays\n * symbolic (`autoRepeat`, spliced in at `tracks[autoRepeat.index]`) and\n * resolves its count at layout time against the definite axis size. */\nexport type GridTemplate =\n | { kind: \"none\" }\n | { kind: \"subgrid\" }\n | {\n kind: \"tracks\";\n tracks: TrackSize[];\n /** `[name …]` groups: `lineNames[i]` names line i (0 … tracks.length).\n * Absent when the template names no lines. */\n lineNames?: string[][];\n autoRepeat?: {\n index: number;\n tracks: TrackSize[];\n /** Names inside the repetition (tracks.length + 1 entries); the\n * edge groups merge with neighbors at every iteration boundary. */\n lineNames?: string[][];\n /** Names authored just before the `repeat()` — they attach to the\n * first repeated line once the count is known. */\n leadingNames?: string[];\n mode: \"auto-fill\" | \"auto-fit\";\n };\n };\n\n/** One side of a grid item's placement (`grid-column-start`, …): a line\n * number (negative counts from the explicit grid's end, per CSS), a span\n * (optionally counting only lines with a name), a named line (`foo`, or\n * `<n> foo` — `nth` absent for the bare form, whose area-edge lookup\n * comes first, specs/grid.md), or auto. */\nexport type GridLine =\n | { kind: \"auto\" }\n | { kind: \"line\"; value: number }\n | { kind: \"span\"; value: number; name?: string }\n | { kind: \"name\"; name: string; nth?: number };\n\n/** A named area from `grid-template-areas`, as 0-based line indices\n * (`colEnd` / `rowEnd` exclusive of the last cell's track). */\nexport interface GridArea {\n colStart: number;\n colEnd: number;\n rowStart: number;\n rowEnd: number;\n}\n\n/** `grid-template-areas`: the row/column count it defines and its\n * (rectangular) named areas. */\nexport interface GridAreas {\n columns: number;\n rows: number;\n areas: Map<string, GridArea>;\n}\n\nexport interface GridAutoFlow {\n direction: \"row\" | \"column\";\n dense: boolean;\n}\n\n/** Tracks a subgrid inherits from its parent grid in a subgridded axis\n * (specs/grid.md), projected into the subgrid's CONTENT-box coordinates:\n * the first and last tracks are shrunk by the subgrid's own margin,\n * border, and padding on that side, so its items still land on the\n * parent's lines. `gap` is the parent's gutter. */\nexport interface InheritedTracks {\n positions: number[];\n sizes: number[];\n gapBefore: number[];\n gap: number;\n}\n\n/** One value per box edge (border style, border color, …). */\nexport interface PerSide<T> {\n top: T;\n right: T;\n bottom: T;\n left: T;\n}\n\nexport interface CellStyle {\n display: Display;\n flexDirection: FlexDirection;\n /** True for `row-reverse` / `column-reverse`: the main axis runs\n * backwards — items lay out in reverse order and `justify-content`\n * start/end swap meaning. */\n flexReverse: boolean;\n flexWrap: FlexWrap;\n /** True for `wrap-reverse`: lines stack from the cross-end (bottom-up). */\n wrapReverse: boolean;\n flexGrow: number;\n flexShrink: number;\n /** CSS `flex-basis`: the flex base size when not `auto`/undefined —\n * notably `0%` from Tailwind's `flex-1`, which makes grow distribute ALL\n * the space (equal columns) instead of just the extra. */\n flexBasis: Size | undefined;\n /** CSS `order` — flex items sort by it (stable, document order ties). */\n order: number;\n justifyContent: JustifyContent;\n /** Flex: multi-line (wrap-enabled) containers only, per CSS. Grid: row\n * track distribution. */\n alignContent: AlignContent;\n alignItems: AlignItems;\n alignSelf: AlignSelf;\n /** Grid container inline-axis item alignment (`justify-items`); the CSS\n * default `normal` behaves as `stretch` in grid. */\n justifyItems: AlignItems;\n /** Grid item inline-axis self-alignment override (`justify-self`). */\n justifySelf: AlignSelf;\n /** Parsed track templates (specs/grid.md). `none` for non-grid elements. */\n gridTemplateColumns: GridTemplate;\n gridTemplateRows: GridTemplate;\n /** Sizes for implicit tracks (`grid-auto-columns` / `grid-auto-rows`),\n * cycled across the implicit tracks in each axis. Never empty — the CSS\n * initial value is a single `auto`. */\n gridAutoColumns: TrackSize[];\n gridAutoRows: TrackSize[];\n gridAutoFlow: GridAutoFlow;\n /** Parsed `grid-template-areas`; `null` for `none` or an invalid value\n * (per CSS the whole property then doesn't apply). */\n gridTemplateAreas: GridAreas | null;\n /** Grid item placement longhands. `auto` on non-grid-item elements. */\n gridColumnStart: GridLine;\n gridColumnEnd: GridLine;\n gridRowStart: GridLine;\n gridRowEnd: GridLine;\n width: Size | undefined;\n height: Size | undefined;\n /** `\"auto\"` is CSS `min-width/height: auto`: 0 in block flow, but a flex\n * item's automatic minimum (its min-content size, when overflow is\n * visible) on the flex main axis — the reason text in a flex row stops\n * shrinking instead of vanishing, and why `min-w-0` exists. */\n minWidth: SizeLimit | \"auto\";\n minHeight: SizeLimit | \"auto\";\n maxWidth: SizeLimit | undefined;\n maxHeight: SizeLimit | undefined;\n padding: PerSide<CellLength>;\n /** `null` = `auto`. Percentages resolve against the parent's content\n * width where the margin is consumed. */\n margin: PerSide<CellLength | null>;\n /** See specs/positioning.md: fixed behaves as absolute anchored to the\n * host; sticky behaves as relative until the scrolling milestone. */\n position: Position;\n /** `top/right/bottom/left`; `null` = `auto`. Percentages resolve against\n * the containing block (width for left/right, height for top/bottom). */\n insets: PerSide<CellLength | null>;\n gapX: CellLength;\n gapY: CellLength;\n border: Insets;\n borderStyle: PerSide<BorderStyle>;\n borderColor: PerSide<string | undefined>;\n overflow: Overflow;\n whiteSpace: WhiteSpace;\n /** CSS `tab-size` in cells — tab stops for preserved (`pre`) text,\n * expanded by the tree builder from each hard line's start. */\n tabSize: number;\n /** Empty rows between wrapped lines (`leading-*` re-quantized to the\n * grid: rows per line − 1). See specs/cell-model.md. */\n lineGap: number;\n /** Extra cells after every character (`tracking-*` re-quantized:\n * floor((letter-spacing − root letter-spacing) ÷ 0.025em)). */\n tracking: number;\n /** Paint-only: with `nowrap` + clipping, the browser draws the ellipsis.\n * The engine only needs it for the ASCII renderer's mirror of that. */\n textOverflow: TextOverflow;\n /**\n * Paint-only colors, reserved for the visual-system milestone. `color` will\n * feed decoration glyphs that visually belong to the text (control framing\n * like `[ Save ]`, cursors, selection carets); `backgroundColor` will feed\n * cell-level highlights (selection ranges, decoration backgrounds). Read\n * from the source element now so the future work has the data available.\n */\n color: string | undefined;\n backgroundColor: string | undefined;\n /** True when text-align is center/justify — forced back to `start` since\n * per-line centering can't be snapped to whole cells. See cell-model spec. */\n textAlignBlocked: boolean;\n}\n\nexport interface LayoutNode {\n source: Element;\n style: CellStyle;\n children: LayoutNode[];\n /** The leaf's text run (inline descendants included, `<br>` as `\\n`).\n * Empty for containers — their direct text nodes are not laid out. */\n text: string;\n intrinsicWidth: number;\n intrinsicHeight: number;\n localRect: Rect;\n /** Where an out-of-flow (absolute) box would have sat in normal flow —\n * its CSS \"static position\", parent-relative, recorded by the parent's\n * flow pass and consumed by the absolute-positioning pass for inset-less\n * axes. Flex parents record the container's content box plus alignment\n * so the \"as if sole flex item\" rule can apply once the box is sized. */\n staticSlot?:\n | { kind: \"block\"; x: number; y: number }\n | {\n kind: \"flex\";\n direction: FlexDirection;\n originX: number;\n originY: number;\n innerWidth: number;\n innerHeight: number;\n }\n /** Grid parents (specs/grid.md §10.1): `area` is the child's grid\n * area (its containing block when the grid container is positioned)\n * and `staticArea` the sole-item area for inset-less axes — both\n * parent-relative border-box rects. */\n | { kind: \"grid\"; area: Rect; staticArea: Rect };\n /** Per-character cell advances for tracked leaf text (`1 + tracking` of\n * the character's innermost element, specs/cell-model.md); absent when\n * every character is a plain 1-cell advance. */\n advances?: number[];\n /** Inline descendants of a leaf. The renderer writes each one's grid\n * tracking, its quantized horizontal padding (the run reserves the\n * cells as INLINE_PAD markers; the browser applies the same cells as\n * real padding via engine-owned vars), and — for the positioned ones —\n * its relative insets rewritten to whole cells (specs/positioning.md);\n * `null` insets = not positioned. */\n inlineElements?: {\n element: Element;\n tracking: number;\n padLeft: number;\n padRight: number;\n insets: PerSide<number | null> | null;\n }[];\n /** True on an atomic inline-level box (`inline-flex`/`inline-block`/\n * `inline-grid`) riding its parent leaf's text run as a single\n * unbreakable unit: the leaf's run holds an OBJECT REPLACEMENT\n * CHARACTER (U+FFFC) for it whose advance is the box's laid-out width.\n * The box stays IN FLOW in the browser (sized to whole cells by the\n * companion stylesheet) so the browser's own line layout places it —\n * engine and browser agree because both treat it as an atomic unit of\n * the same width (specs/cell-model.md). */\n inlineBox?: boolean;\n /** Set by a grid parent on a child whose template is `subgrid` in at\n * least one axis: the child's span in each axis (its explicit track\n * count there — placement clamps to it) and, once the parent has sized\n * that axis, the inherited tracks. Rows arrive in the parent's second\n * pass: the first pass lays the subgrid out provisionally (its own\n * items' heights feed the parent's row sizing). Absent on everything\n * else — a `subgrid` template then behaves as `none`, per CSS. */\n subgrid?:\n | {\n colSpan: number;\n rowSpan: number;\n cols?: InheritedTracks | undefined;\n rows?: InheritedTracks | undefined;\n }\n | undefined;\n /** True on a container whose direct text nodes were dropped (mixed\n * text + in-flow block children — cell-model deviation). The renderer\n * hides that text and warns instead of letting the browser paint it\n * unpositioned. */\n droppedText?: boolean;\n /** Outer height before min/max clamping — written by layoutNode; the\n * column flex algorithm's base main size (CSS distributes from unclamped\n * bases; limits apply via its freeze loop). */\n unclampedHeight: number;\n /** Padding with percentages resolved to cells — written by layoutNode\n * (percent resolves against the containing block width, which only\n * layout knows); the renderers read this, never `style.padding`. */\n resolvedPadding: Insets;\n}\n\n/** The root's cell, in px: width = glyph advance + the root's\n * letter-spacing, height = the root's line box (specs/cell-model.md).\n * `letterSpacing` is the root's, kept so descendant tracking can be read\n * relative to it. */\nexport interface CellMetrics {\n width: number;\n height: number;\n letterSpacing: number;\n}\n\nexport function defaultCellStyle(): CellStyle {\n return {\n display: \"block\",\n flexDirection: \"row\",\n flexReverse: false,\n flexWrap: \"nowrap\",\n wrapReverse: false,\n flexGrow: 0,\n flexShrink: 0,\n flexBasis: undefined,\n order: 0,\n // The CSS initial value `normal` reads as `stretch` (flex treats it\n // as `start`; grid stretches auto tracks).\n justifyContent: \"stretch\",\n alignContent: \"stretch\",\n alignItems: \"stretch\",\n alignSelf: \"auto\",\n justifyItems: \"stretch\",\n justifySelf: \"auto\",\n gridTemplateColumns: { kind: \"none\" },\n gridTemplateRows: { kind: \"none\" },\n gridAutoColumns: [autoTrack()],\n gridAutoRows: [autoTrack()],\n gridAutoFlow: { direction: \"row\", dense: false },\n gridTemplateAreas: null,\n gridColumnStart: { kind: \"auto\" },\n gridColumnEnd: { kind: \"auto\" },\n gridRowStart: { kind: \"auto\" },\n gridRowEnd: { kind: \"auto\" },\n width: undefined,\n height: undefined,\n minWidth: \"auto\",\n minHeight: \"auto\",\n maxWidth: undefined,\n maxHeight: undefined,\n padding: zeroInsets(),\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n position: \"static\",\n insets: { top: null, right: null, bottom: null, left: null },\n gapX: 0,\n gapY: 0,\n border: zeroInsets(),\n borderStyle: { top: \"solid\", right: \"solid\", bottom: \"solid\", left: \"solid\" },\n overflow: \"visible\",\n whiteSpace: \"normal\",\n tabSize: 8,\n lineGap: 0,\n tracking: 0,\n textOverflow: \"clip\",\n color: undefined,\n backgroundColor: undefined,\n borderColor: { top: undefined, right: undefined, bottom: undefined, left: undefined },\n textAlignBlocked: false,\n };\n}\n\nexport function zeroInsets(): Insets {\n return { top: 0, right: 0, bottom: 0, left: 0 };\n}\n\n/** The CSS initial implicit-track size: `minmax(auto, auto)`. */\nexport function autoTrack(): TrackSize {\n return { min: { kind: \"auto\" }, max: { kind: \"auto\" } };\n}\n","import { percentToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack } from \"./types.ts\";\nimport {\n clampSize,\n intrinsicOuterWidth,\n isOutOfFlow,\n layoutNode,\n minContentOuterWidth,\n resolveLength,\n resolveLimit,\n resolveMargin,\n resolveSizeAgainst,\n resolveWidthLimit,\n} from \"./layout.ts\";\nimport type { IntrinsicCache } from \"./layout.ts\";\nimport { alignCrossOffset, distributeInteger, effectiveAlign, mainAxisOffsets } from \"./flex.ts\";\nimport type {\n AlignItems,\n GridAutoFlow,\n GridLine,\n GridTemplate,\n InheritedTracks,\n Insets,\n JustifyContent,\n LayoutNode,\n NullableInsets,\n Rect,\n TrackBreadth,\n TrackSize,\n} from \"./types.ts\";\n\n/**\n * Grid layout (specs/grid.md): template resolution, CSS §8.5 auto-\n * placement, the §11 track sizing algorithm adapted to integer cells, and\n * item placement in areas. Shares the integer distribution and alignment\n * offset machinery with flex. See layout.ts for the deliberate import\n * cycle between the layout modules.\n */\n\nexport function layoutGrid(\n node: LayoutNode,\n innerWidth: number,\n innerHeight: number,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n // The column axis is always definite (width fills); the row axis uses\n // any bounded inner height — a `min-height` floor included, same as\n // flex lines — so rows stretch and align inside `min-h-*` containers.\n const rowAvailable = Number.isFinite(innerHeight) ? innerHeight : undefined;\n // A subgridded axis inherits the parent's tracks AND gutters\n // (specs/grid.md — an own gap on that axis is ignored, a documented\n // simplification). Rows may still be provisional (see LayoutNode.subgrid).\n const inheritedCols = node.subgrid?.cols;\n const inheritedRows = node.subgrid?.rows;\n const gapX = inheritedCols ? inheritedCols.gap : resolveLength(style.gapX, innerWidth);\n const gapY = inheritedRows ? inheritedRows.gap : resolveLength(style.gapY, rowAvailable);\n\n const structure = resolveGridStructure(\n node,\n innerWidth,\n rowAvailable,\n gapX,\n gapY,\n node.subgrid ? { col: node.subgrid.colSpan, row: node.subgrid.rowSpan } : undefined,\n );\n const { children, placed, colLines, rowLines, colTracks, rowTracks, colCollapsed, rowCollapsed } =\n structure;\n const margins = children.map((child) => resolveMargin(child.style.margin, innerWidth));\n const justifies = children.map((child) =>\n child.style.justifySelf === \"auto\" ? style.justifyItems : child.style.justifySelf,\n );\n\n // Whether each child subgrids its columns / rows, computed once and\n // shared by the sizing builders and both item passes.\n const subs = children.map(subgridAxes);\n\n // Column track sizing from the items' intrinsic width contributions\n // (outer sizes plus fixed margins, auto margins as 0; subgrid children\n // contribute their own items through the mapped tracks) — or the\n // parent's tracks when this axis is subgridded.\n const colSizing: SizingResult = inheritedCols\n ? sizingResultFromInherited(inheritedCols)\n : sizeTracks(\n colTracks,\n colCollapsed,\n columnSizingItems(structure, subs, margins, cache),\n innerWidth,\n gapX,\n style.justifyContent === \"stretch\",\n );\n const colPos = inheritedCols\n ? inheritedCols.positions\n : trackPositions(colSizing, innerWidth, style.justifyContent);\n\n // First item pass: resolve each item's width in its column area\n // (stretch by default; own min/max still clamp; explicit sizes and auto\n // margins opt out) and lay it out — heights emerge here. A subgrid is\n // always exactly its area in a subgridded axis, per CSS, and receives\n // the inherited tracks before its layout.\n const usedWidths: number[] = [];\n for (let i = 0; i < children.length; i++) {\n const child = children[i]!;\n const p = placed.items[i]!;\n const areaW = areaExtent(colPos, colSizing.sizes, p.col.start, p.col.span);\n const margin = margins[i]!;\n const availW = Math.max(0, areaW - fixedX(margin));\n const sub = subs[i]!;\n // A child that subgrids either axis carries a subgrid record — the\n // column half fills in now (rows follow after row sizing).\n if (sub.cols || sub.rows) {\n const cols = sub.cols\n ? inheritTracks(\n colPos,\n colSizing,\n gapX,\n p.col.start,\n p.col.span,\n subgridChrome(child, \"cols\", margin, areaW),\n )\n : undefined;\n child.subgrid = { colSpan: p.col.span, rowSpan: p.row.span, cols, rows: undefined };\n } else {\n child.subgrid = undefined;\n }\n const justify = justifies[i]!;\n const hasAutoX = margin.left === null || margin.right === null;\n const hasExplicitWidth = child.style.width !== undefined && child.style.width.kind !== \"auto\";\n if (sub.cols) {\n layoutNode(child, areaW, undefined, 0, 0, \"fill\", cache, { width: availW });\n } else if (justify === \"stretch\" && !hasAutoX && !hasExplicitWidth) {\n // The automatic minimum (`min-width: auto` = min-content while\n // overflow is visible) floors the stretched width, same as flex —\n // the item can overflow a `minmax(0, 1fr)` track narrower than its\n // content, matching CSS.\n const minW =\n child.style.minWidth === \"auto\"\n ? child.style.overflow === \"visible\"\n ? minContentOuterWidth(child, cache)\n : 0\n : (resolveLimit(child.style.minWidth, areaW) ?? 0);\n const maxW = resolveWidthLimit(child.style.maxWidth, areaW, child, cache);\n const stretched = clampSize(availW, minW, maxW);\n layoutNode(child, areaW, undefined, 0, 0, \"fill\", cache, { width: stretched });\n } else {\n layoutNode(child, availW, undefined, 0, 0, \"shrink\", cache);\n }\n usedWidths.push(child.localRect.width);\n }\n\n // Row track sizing from the laid-out heights (at final column widths,\n // the item's min- and max-content block contributions coincide) — or\n // the parent's tracks when this axis is subgridded.\n const rowSizing: SizingResult = inheritedRows\n ? sizingResultFromInherited(inheritedRows)\n : sizeTracks(\n rowTracks,\n rowCollapsed,\n rowSizingItems(structure, subs, margins),\n rowAvailable ?? \"max-content\",\n gapY,\n style.alignContent === \"stretch\",\n );\n const contentRows = totalExtent(rowSizing);\n const rowPos = inheritedRows\n ? inheritedRows.positions\n : trackPositions(rowSizing, rowAvailable ?? contentRows, style.alignContent);\n\n // Second item pass: block-axis stretch and final placement (a row\n // subgrid gets its inherited rows now and is laid out for real).\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n for (let i = 0; i < children.length; i++) {\n const child = children[i]!;\n const p = placed.items[i]!;\n const margin = margins[i]!;\n const areaW = areaExtent(colPos, colSizing.sizes, p.col.start, p.col.span);\n const areaH = areaExtent(rowPos, rowSizing.sizes, p.row.start, p.row.span);\n const availH = Math.max(0, areaH - fixedY(margin));\n const align = effectiveAlign(child, node);\n const hasAutoY = margin.top === null || margin.bottom === null;\n const hasExplicitHeight =\n child.style.height !== undefined && child.style.height.kind !== \"auto\";\n if (subs[i]!.rows) {\n child.subgrid!.rows = inheritTracks(\n rowPos,\n rowSizing,\n gapY,\n p.row.start,\n p.row.span,\n subgridChrome(child, \"rows\", margin, areaW),\n );\n layoutNode(child, areaW, areaH, 0, 0, \"fill\", cache, {\n width: usedWidths[i]!,\n height: availH,\n });\n } else if (align === \"stretch\" && !hasAutoY && !hasExplicitHeight) {\n // Same automatic minimum in the block axis: the laid-out content\n // height floors the stretch (a definite row smaller than the content\n // overflows instead of crushing it), unless overflow opts out.\n const minH =\n child.style.minHeight === \"auto\"\n ? child.style.overflow === \"visible\"\n ? child.localRect.height\n : 0\n : (resolveLimit(child.style.minHeight, areaH) ?? 0);\n const maxH = resolveLimit(child.style.maxHeight, areaH);\n const stretched = clampSize(availH, minH, maxH);\n if (stretched !== child.localRect.height) {\n layoutNode(child, areaW, areaH, 0, 0, \"fill\", cache, {\n width: usedWidths[i]!,\n height: stretched,\n });\n }\n } else if (child.style.height?.kind === \"percent\") {\n // A percent height resolves against the item's grid area, per the\n // cyclic-percentage rule: it contributed as `auto` to the row\n // sizing above, and resolves against the resulting area now.\n layoutNode(child, areaW, areaH, 0, 0, \"fill\", cache, { width: usedWidths[i]! });\n }\n child.localRect = {\n ...child.localRect,\n x:\n originX +\n colPos[p.col.start]! +\n areaAxisOffset(justifies[i]!, margin.left, margin.right, areaW, child.localRect.width),\n y:\n originY +\n rowPos[p.row.start]! +\n areaAxisOffset(align, margin.top, margin.bottom, areaH, child.localRect.height),\n };\n }\n\n const contentHeight = Number.isFinite(innerHeight)\n ? Math.max(innerHeight, contentRows)\n : contentRows;\n\n // Out-of-flow children (specs/grid.md §10.1): the child's grid area —\n // its containing block when this container is positioned — plus the\n // sole-item static area: the content box, or the padding box when this\n // container is itself absolutely positioned. Both parent-relative.\n const outOfFlow = node.children.filter((child) => isOutOfFlow(child.style));\n if (outOfFlow.length > 0) {\n const staticArea: Rect = isOutOfFlow(style)\n ? {\n x: border.left,\n y: border.top,\n width: padding.left + innerWidth + padding.right,\n height: padding.top + contentHeight + padding.bottom,\n }\n : { x: originX, y: originY, width: innerWidth, height: contentHeight };\n for (const child of outOfFlow) {\n const cols = absoluteAxisExtent(\n child.style.gridColumnStart,\n child.style.gridColumnEnd,\n colLines,\n placed.colOrigin,\n colPos,\n colSizing.sizes,\n -padding.left,\n innerWidth + padding.right,\n );\n const rows = absoluteAxisExtent(\n child.style.gridRowStart,\n child.style.gridRowEnd,\n rowLines,\n placed.rowOrigin,\n rowPos,\n rowSizing.sizes,\n -padding.top,\n contentHeight + padding.bottom,\n );\n child.staticSlot = {\n kind: \"grid\",\n area: {\n x: originX + cols.start,\n y: originY + rows.start,\n width: Math.max(0, cols.end - cols.start),\n height: Math.max(0, rows.end - rows.start),\n },\n staticArea,\n };\n }\n }\n\n return contentHeight;\n}\n\n/** Which axes of an in-flow grid child are `subgrid`. */\nfunction subgridAxes(child: LayoutNode): { cols: boolean; rows: boolean } {\n const isGrid = child.style.display === \"grid\";\n return {\n cols: isGrid && child.style.gridTemplateColumns.kind === \"subgrid\",\n rows: isGrid && child.style.gridTemplateRows.kind === \"subgrid\",\n };\n}\n\n/**\n * Project the parent's tracks `[start, start + span)` into a subgrid's\n * content-box coordinates: the subgrid's content box starts `chrome.start`\n * (margin + border + padding) inside the first track, so that track\n * loses those cells at its start and the last track loses `chrome.end`\n * at its end; interior lines keep their positions. All returned arrays\n * are fresh — later mutation of the parent's sizing can never leak into\n * the child's inherited tracks.\n */\nfunction inheritTracks(\n positions: number[],\n sizing: SizingResult,\n gap: number,\n start: number,\n span: number,\n chrome: { start: number; end: number },\n): InheritedTracks {\n const base = positions[start]! + chrome.start;\n const sizes = sizing.sizes.slice(start, start + span);\n sizes[0] = Math.max(0, sizes[0]! - chrome.start);\n sizes[span - 1] = Math.max(0, sizes[span - 1]! - chrome.end);\n return {\n positions: Array.from({ length: span }, (_, i) => (i === 0 ? 0 : positions[start + i]! - base)),\n sizes,\n gapBefore: Array.from({ length: span }, (_, i) => (i === 0 ? 0 : sizing.gapBefore[start + i]!)),\n gap,\n };\n}\n\n/** Adapt inherited tracks to the `SizingResult` shape the rest of\n * `layoutGrid` reads. The tracks are already sized (limits = sizes) —\n * downstream code never mutates a `SizingResult`, so the arrays can be\n * shared. */\nfunction sizingResultFromInherited(t: InheritedTracks): SizingResult {\n return { sizes: t.sizes, gapBefore: t.gapBefore, limits: t.sizes };\n}\n\n/** Column sizing contributions for a resolved grid: each item's\n * min-/max-content outer width plus fixed margins; a column-subgrid child\n * is replaced by its own items, mapped onto the parent's tracks. */\nfunction columnSizingItems(\n structure: GridStructure,\n subs: { cols: boolean; rows: boolean }[],\n margins: NullableInsets[],\n cache: IntrinsicCache,\n): SizingItem[] {\n const items: SizingItem[] = [];\n structure.children.forEach((child, i) => {\n const p = structure.placed.items[i]!;\n const margin = margins[i]!;\n if (subs[i]!.cols) {\n const chrome = subgridChrome(child, \"cols\", margin, 0);\n for (const item of subgridContributions(child, \"cols\", p, chrome, cache)) {\n items.push({ ...item, start: item.start + p.col.start });\n }\n return;\n }\n items.push({\n start: p.col.start,\n span: p.col.span,\n min: widthContribution(child, \"min\", cache) + fixedX(margin),\n max: widthContribution(child, \"max\", cache) + fixedX(margin),\n });\n });\n return items;\n}\n\n/** Row sizing contributions: each laid-out item's height plus fixed\n * margins (min = max at the final width); a row-subgrid child is\n * replaced by its own items, mapped onto the parent's tracks. */\nfunction rowSizingItems(\n structure: GridStructure,\n subs: { cols: boolean; rows: boolean }[],\n margins: NullableInsets[],\n): SizingItem[] {\n const items: SizingItem[] = [];\n structure.children.forEach((child, i) => {\n const p = structure.placed.items[i]!;\n const margin = margins[i]!;\n if (subs[i]!.rows) {\n const chrome = subgridChrome(child, \"rows\", margin, 0);\n for (const item of subgridContributions(child, \"rows\", p, chrome)) {\n items.push({ ...item, start: item.start + p.row.start });\n }\n return;\n }\n const height = child.localRect.height + fixedY(margin);\n items.push({ start: p.row.start, span: p.row.span, min: height, max: height });\n });\n return items;\n}\n\n/** A subgrid's own chrome on one axis — margin + border + padding on the\n * subgrid box itself — which its edge-track items must also cover (CSS\n * Grid 2 §3.1). `basis` resolves percent padding (per CSS, against the\n * containing-block WIDTH on all four sides); pass 0 during intrinsic\n * sizing so percent padding contributes 0, matching the intrinsic-size\n * rule for percent padding on any box. */\nfunction subgridChrome(\n child: LayoutNode,\n axis: \"cols\" | \"rows\",\n margin: NullableInsets,\n basis: number,\n): { start: number; end: number } {\n const { border, padding } = child.style;\n return axis === \"cols\"\n ? {\n start: (margin.left ?? 0) + border.left + resolveLength(padding.left, basis),\n end: (margin.right ?? 0) + border.right + resolveLength(padding.right, basis),\n }\n : {\n start: (margin.top ?? 0) + border.top + resolveLength(padding.top, basis),\n end: (margin.bottom ?? 0) + border.bottom + resolveLength(padding.bottom, basis),\n };\n}\n\n/**\n * A subgrid child's items as sizing contributions in the CHILD's own\n * track coordinates for the subgridded `axis` (the caller shifts them\n * onto the parent's tracks). Items in the subgrid's first/last track\n * also carry the subgrid's chrome on that side; nested subgrids compose\n * recursively. A subgrid without items still claims its chrome. `cache`\n * is needed for column (intrinsic) contributions only — rows use the\n * heights the provisional first pass laid out.\n *\n * `child.subgrid` is NOT written here — placement span is passed\n * explicitly to `resolveGridStructure`, keeping that field owned solely\n * by the parent's item passes.\n */\nfunction subgridContributions(\n child: LayoutNode,\n axis: \"cols\" | \"rows\",\n placement: { col: PlacedAxis; row: PlacedAxis },\n chrome: { start: number; end: number },\n cache?: IntrinsicCache,\n): SizingItem[] {\n const span = axis === \"cols\" ? placement.col.span : placement.row.span;\n const structure = resolveGridStructure(child, undefined, undefined, 0, 0, {\n col: placement.col.span,\n row: placement.row.span,\n });\n const items: SizingItem[] = [];\n structure.children.forEach((item, j) => {\n const q = structure.placed.items[j]!;\n const a = axis === \"cols\" ? q.col : q.row;\n const first = a.start === 0;\n const last = a.start + a.span === span;\n const extra = (first ? chrome.start : 0) + (last ? chrome.end : 0);\n const margin = resolveMargin(item.style.margin, 0);\n if (subgridAxes(item)[axis]) {\n const own = subgridChrome(item, axis, margin, 0);\n const nested = subgridContributions(\n item,\n axis,\n q,\n { start: own.start + (first ? chrome.start : 0), end: own.end + (last ? chrome.end : 0) },\n cache,\n );\n for (const c of nested) items.push({ ...c, start: c.start + a.start });\n return;\n }\n if (axis === \"cols\") {\n items.push({\n start: a.start,\n span: a.span,\n min: widthContribution(item, \"min\", cache!) + fixedX(margin) + extra,\n max: widthContribution(item, \"max\", cache!) + fixedX(margin) + extra,\n });\n } else {\n const height = item.localRect.height + fixedY(margin) + extra;\n items.push({ start: a.start, span: a.span, min: height, max: height });\n }\n });\n if (items.length === 0) {\n const total = chrome.start + chrome.end;\n items.push({ start: 0, span, min: total, max: total });\n }\n return items;\n}\n\n/**\n * One axis of an absolutely positioned grid child's area (CSS §10.1 with\n * §8.3 line resolution): definite lines map to track edges; `auto`, a\n * span against `auto`, and a line beyond the implicit grid resolve to the\n * container's padding edges (`edgeStart` / `edgeEnd`, content-relative).\n * Positions are content-relative track starts.\n */\nfunction absoluteAxisExtent(\n startLine: GridLine,\n endLine: GridLine,\n lines: AxisLines,\n origin: number,\n positions: number[],\n sizes: number[],\n edgeStart: number,\n edgeEnd: number,\n): { start: number; end: number } {\n let start = lineToIndex(startLine, \"start\", lines);\n let end = lineToIndex(endLine, \"end\", lines);\n if (start !== null && end !== null) {\n if (start > end) [start, end] = [end, start];\n else if (start === end) end = null;\n } else if (start !== null && endLine.kind === \"span\") {\n end = spanFrom(start, endLine, 1, lines);\n } else if (end !== null && startLine.kind === \"span\") {\n start = spanFrom(end, startLine, -1, lines);\n }\n // A grid line sits between two tracks with the gutter around it: as a\n // START line it is the following track's start edge, as an END line the\n // preceding track's end edge (an area never includes an outer gutter).\n const count = positions.length;\n const normalized = (line: number | null): number | undefined => {\n if (line === null) return undefined;\n const n = line - origin;\n return n < 0 || n > count || count === 0 ? undefined : n;\n };\n const startLineAt = (n: number): number =>\n n === count ? positions[count - 1]! + sizes[count - 1]! : positions[n]!;\n const endLineAt = (n: number): number =>\n n === 0 ? positions[0]! : positions[n - 1]! + sizes[n - 1]!;\n const s = normalized(start);\n const e = normalized(end);\n return {\n start: s === undefined ? edgeStart : startLineAt(s),\n end: e === undefined ? edgeEnd : endLineAt(e),\n };\n}\n\n/** The container's intrinsic content widths (specs/grid.md interaction\n * section): run placement and column sizing under a min-content\n * constraint — min-content = the track bases, max-content = the track\n * growth limits (fr tracks report their flex-fraction size), plus gaps.\n * One placement + sizing pass computes both, cached per node. */\nexport function gridIntrinsicInnerWidths(\n node: LayoutNode,\n cache: IntrinsicCache,\n): { min: number; max: number } {\n const cached = cache.gridIntrinsic.get(node);\n if (cached !== undefined) return cached;\n const style = node.style;\n const gapX = typeof style.gapX === \"number\" ? style.gapX : 0;\n const structure = resolveGridStructure(\n node,\n undefined,\n undefined,\n gapX,\n 0,\n node.subgrid ? { col: node.subgrid.colSpan, row: node.subgrid.rowSpan } : undefined,\n );\n const subs = structure.children.map(subgridAxes);\n const margins = structure.children.map((child) => resolveMargin(child.style.margin, 0));\n const sizing = sizeTracks(\n structure.colTracks,\n structure.colCollapsed,\n columnSizingItems(structure, subs, margins, cache),\n \"min-content\",\n gapX,\n false,\n );\n const gaps = sizing.gapBefore.reduce((s, g) => s + g, 0);\n const result = {\n min: sizing.sizes.reduce((s, v) => s + v, 0) + gaps,\n max: sizing.limits.reduce((s, v) => s + v, 0) + gaps,\n };\n cache.gridIntrinsic.set(node, result);\n return result;\n}\n\ninterface GridStructure {\n children: LayoutNode[];\n placed: PlacementResult;\n /** The explicit grid per axis — the basis for line resolution. */\n colLines: AxisLines;\n rowLines: AxisLines;\n colTracks: TrackSize[];\n rowTracks: TrackSize[];\n colCollapsed: boolean[];\n rowCollapsed: boolean[];\n}\n\n/** Everything upstream of track sizing: template resolution against the\n * axes' available sizes (a subgridded axis has exactly its span's worth\n * of placeholder tracks, and clamps placement to them — no implicit\n * tracks there, per CSS Grid 2), placement spec resolution, §8.5\n * auto-placement, the full per-axis track lists (implicit tracks\n * included), and auto-fit collapse flags. */\nfunction resolveGridStructure(\n node: LayoutNode,\n colAvailable: number | undefined,\n rowAvailable: number | undefined,\n gapX: number,\n gapY: number,\n subgridSpans?: { col: number; row: number },\n): GridStructure {\n const style = node.style;\n const children = gridOrderedChildren(node);\n const colSubgrid = style.gridTemplateColumns.kind === \"subgrid\" && subgridSpans !== undefined;\n const rowSubgrid = style.gridTemplateRows.kind === \"subgrid\" && subgridSpans !== undefined;\n const colTemplate = colSubgrid\n ? placeholderTemplate(subgridSpans.col)\n : resolveTemplate(style.gridTemplateColumns, colAvailable, gapX);\n const rowTemplate = rowSubgrid\n ? placeholderTemplate(subgridSpans.row)\n : resolveTemplate(style.gridTemplateRows, rowAvailable, gapY);\n // `grid-template-areas` (specs/grid.md): the explicit grid is the\n // larger of the template and the areas — extra tracks come from the\n // grid-auto-* lists — and every area names its edge lines\n // `<name>-start` / `<name>-end` in both axes. A subgridded axis keeps\n // its inherited track count.\n const areas = style.gridTemplateAreas;\n const colExplicit = [...colTemplate.tracks];\n const rowExplicit = [...rowTemplate.tracks];\n if (areas) {\n if (!colSubgrid) {\n extendExplicitTracks(\n colExplicit,\n colTemplate.lineNames,\n areas.columns,\n style.gridAutoColumns,\n );\n }\n if (!rowSubgrid) {\n extendExplicitTracks(rowExplicit, rowTemplate.lineNames, areas.rows, style.gridAutoRows);\n }\n for (const [name, area] of areas.areas) {\n colTemplate.lineNames[Math.min(area.colStart, colExplicit.length)]!.push(`${name}-start`);\n colTemplate.lineNames[Math.min(area.colEnd, colExplicit.length)]!.push(`${name}-end`);\n rowTemplate.lineNames[Math.min(area.rowStart, rowExplicit.length)]!.push(`${name}-start`);\n rowTemplate.lineNames[Math.min(area.rowEnd, rowExplicit.length)]!.push(`${name}-end`);\n }\n }\n const colLines: AxisLines = { explicitCount: colExplicit.length, names: colTemplate.lineNames };\n const rowLines: AxisLines = { explicitCount: rowExplicit.length, names: rowTemplate.lineNames };\n const specs = children.map((child) => ({\n col: resolveAxisPlacement(child.style.gridColumnStart, child.style.gridColumnEnd, colLines),\n row: resolveAxisPlacement(child.style.gridRowStart, child.style.gridRowEnd, rowLines),\n }));\n const placed = placeItems(specs, colExplicit.length, rowExplicit.length, style.gridAutoFlow);\n if (colSubgrid) clampToExplicit(placed, \"col\", colExplicit.length);\n if (rowSubgrid) clampToExplicit(placed, \"row\", rowExplicit.length);\n return {\n children,\n placed,\n colLines,\n rowLines,\n colTracks: buildAxisTracks(\n colExplicit,\n placed.colOrigin,\n placed.colCount,\n style.gridAutoColumns,\n ),\n rowTracks: buildAxisTracks(rowExplicit, placed.rowOrigin, placed.rowCount, style.gridAutoRows),\n colCollapsed: collapsedTracks(\n colTemplate,\n placed.colOrigin,\n placed.colCount,\n placed.items.map((p) => p.col),\n ),\n rowCollapsed: collapsedTracks(\n rowTemplate,\n placed.rowOrigin,\n placed.rowCount,\n placed.items.map((p) => p.row),\n ),\n };\n}\n\n/** A subgridded axis's stand-in template: `span` auto tracks. The\n * parent's inherited tracks replace them at sizing time; they only size\n * themselves during a row subgrid's provisional first pass. */\nfunction placeholderTemplate(span: number): ResolvedTemplate {\n return {\n tracks: Array.from({ length: span }, () => autoTrack()),\n lineNames: Array.from({ length: span + 1 }, () => []),\n };\n}\n\n/** Subgrids have no implicit tracks in a subgridded axis: any placement\n * outside the explicit `count` tracks is clamped onto the nearest edge\n * track(s), and the axis is normalized to exactly those tracks. */\nfunction clampToExplicit(placed: PlacementResult, axis: \"col\" | \"row\", count: number): void {\n const origin = axis === \"col\" ? placed.colOrigin : placed.rowOrigin;\n for (const item of placed.items) {\n const a = item[axis];\n const start = Math.min(Math.max(a.start + origin, 0), count - 1);\n const end = Math.min(Math.max(a.start + origin + a.span, start + 1), count);\n a.start = start;\n a.span = end - start;\n }\n if (axis === \"col\") {\n placed.colOrigin = 0;\n placed.colCount = count;\n } else {\n placed.rowOrigin = 0;\n placed.rowCount = count;\n }\n}\n\n/** Grid item order: stable sort by CSS `order` (document order ties) —\n * `order` participates in auto-placement, per CSS. */\nfunction gridOrderedChildren(node: LayoutNode): LayoutNode[] {\n return node.children\n .filter((child) => !isOutOfFlow(child.style) && !child.inlineBox)\n .sort((a, b) => a.style.order - b.style.order);\n}\n\nfunction fixedX(margin: NullableInsets): number {\n return (margin.left ?? 0) + (margin.right ?? 0);\n}\n\nfunction fixedY(margin: NullableInsets): number {\n return (margin.top ?? 0) + (margin.bottom ?? 0);\n}\n\n/** An item's outer width contribution to intrinsic track sizing: its\n * explicit width if fixed (percent behaves as auto, per intrinsic\n * contribution rules), else the min-/max-content outer width; clamped by\n * the item's own fixed min/max. */\nfunction widthContribution(child: LayoutNode, kind: \"min\" | \"max\", cache: IntrinsicCache): number {\n const style = child.style;\n let width: number | undefined;\n if (style.width !== undefined && style.width.kind !== \"auto\" && style.width.kind !== \"percent\") {\n width = resolveSizeAgainst(style.width, 0, child, cache);\n }\n if (width === undefined) {\n width = kind === \"min\" ? minContentOuterWidth(child, cache) : intrinsicOuterWidth(child, cache);\n }\n const min = typeof style.minWidth === \"number\" ? style.minWidth : 0;\n const max = typeof style.maxWidth === \"number\" ? style.maxWidth : undefined;\n return Math.max(0, clampSize(width, min, max));\n}\n\n// ---------------------------------------------------------------------------\n// Template resolution\n\ninterface ResolvedTemplate {\n tracks: TrackSize[];\n /** Names per line, tracks.length + 1 entries (fresh arrays — the\n * structure step adds area-implied names to them). */\n lineNames: string[][];\n /** The index range [start, end) of the tracks an `auto-fit` repetition\n * produced — those collapse to 0 when empty (gaps dropped too). */\n autoFit?: { start: number; end: number };\n}\n\n/**\n * Expand a template's auto-repeat against the axis's definite size:\n * `count = max(1, floor((available + gap) ÷ (iteration + gap·tracks)))`\n * with `iteration` the sum of the repeated tracks' fixed mins (their fixed\n * max when the min is intrinsic) — exact in integer cells. An indefinite\n * axis repeats once, per CSS. (`subgrid` never reaches here — the\n * structure step substitutes the inherited span; outside a grid parent\n * it behaves as `none`, per CSS.)\n */\nfunction resolveTemplate(\n template: GridTemplate,\n available: number | undefined,\n gap: number,\n): ResolvedTemplate {\n if (template.kind !== \"tracks\") return { tracks: [], lineNames: [[]] };\n const baseNames = (\n template.lineNames ?? Array.from({ length: template.tracks.length + 1 }, () => [])\n ).map((names) => [...names]);\n if (!template.autoRepeat) return { tracks: template.tracks, lineNames: baseNames };\n const { index, tracks: repetition, mode } = template.autoRepeat;\n let count = 1;\n if (available !== undefined) {\n const iteration = repetition.reduce((sum, track) => {\n const min = fixedBreadth(track.min, available) ?? fixedBreadth(track.max, available) ?? 1;\n return sum + Math.max(1, min);\n }, 0);\n count = Math.max(1, Math.floor((available + gap) / (iteration + gap * repetition.length)));\n }\n const repeated: TrackSize[] = [];\n for (let i = 0; i < count; i++) repeated.push(...repetition);\n const tracks = [...template.tracks.slice(0, index), ...repeated, ...template.tracks.slice(index)];\n // Line names: the repetition's edge groups merge with their neighbors\n // at every boundary (the names authored before the repeat land on the\n // first repeated line, the names after it on the line past the last).\n const repNames =\n template.autoRepeat.lineNames ?? Array.from({ length: repetition.length + 1 }, () => []);\n const lineNames: string[][] = baseNames.slice(0, index);\n let pending = [...(template.autoRepeat.leadingNames ?? [])];\n for (let i = 0; i < count; i++) {\n pending.push(...repNames[0]!);\n for (let j = 0; j < repetition.length; j++) {\n lineNames.push(pending);\n pending = [...repNames[j + 1]!];\n }\n }\n lineNames.push([...pending, ...baseNames[index]!]);\n lineNames.push(...baseNames.slice(index + 1));\n if (mode === \"auto-fit\") {\n return { tracks, lineNames, autoFit: { start: index, end: index + repeated.length } };\n }\n return { tracks, lineNames };\n}\n\n/** A fixed track breadth in cells, or undefined for intrinsic/fr (percent\n * is fixed only when the axis is definite, per CSS). A `min()`/`max()`\n * resolves when every argument does, else behaves as intrinsic. */\nfunction fixedBreadth(breadth: TrackBreadth, available: number | undefined): number | undefined {\n if (breadth.kind === \"cells\") return breadth.value;\n if (breadth.kind === \"percent\" && available !== undefined) {\n return percentToCells(breadth.value, available);\n }\n if (breadth.kind === \"math\") {\n const values: number[] = [];\n for (const arg of breadth.args) {\n const value = fixedBreadth(arg, available);\n if (value === undefined) return undefined;\n values.push(value);\n }\n return breadth.fn === \"min\" ? Math.min(...values) : Math.max(...values);\n }\n return undefined;\n}\n\n/** Grow an explicit track list to `count` tracks with the `grid-auto-*`\n * list (cycled), keeping `lineNames` at tracks + 1 entries — for tracks\n * that `grid-template-areas` defines beyond the template, per CSS §7.3. */\nfunction extendExplicitTracks(\n tracks: TrackSize[],\n lineNames: string[][],\n count: number,\n autoList: TrackSize[],\n): void {\n for (let i = tracks.length; i < count; i++) {\n tracks.push(autoList[(i - tracks.length) % autoList.length]!);\n lineNames.push([]);\n }\n}\n\n/** The full per-axis track list: explicit tracks at normalized indices\n * [−origin, −origin + explicit.length), implicit tracks on both sides\n * sized by the `grid-auto-*` list — cycled, taken from the list's end in\n * reverse for tracks before the explicit grid (positive modulo), per CSS. */\nfunction buildAxisTracks(\n explicit: TrackSize[],\n origin: number,\n count: number,\n autoList: TrackSize[],\n): TrackSize[] {\n const tracks: TrackSize[] = [];\n for (let i = 0; i < count; i++) {\n const original = i + origin;\n if (original >= 0 && original < explicit.length) {\n tracks.push(explicit[original]!);\n } else {\n const cycle = original < 0 ? original : original - explicit.length;\n tracks.push(autoList[((cycle % autoList.length) + autoList.length) % autoList.length]!);\n }\n }\n return tracks;\n}\n\n/** `auto-fit` collapse (CSS §7.2.3.2): a repeated track no placed item\n * spans is collapsed — sized 0 with its gaps dropped. */\nfunction collapsedTracks(\n template: ResolvedTemplate,\n origin: number,\n count: number,\n spans: { start: number; span: number }[],\n): boolean[] {\n const collapsed: boolean[] = Array.from({ length: count }, () => false);\n if (!template.autoFit) return collapsed;\n for (let original = template.autoFit.start; original < template.autoFit.end; original++) {\n const index = original - origin;\n if (index < 0 || index >= count) continue;\n const occupied = spans.some((s) => index >= s.start && index < s.start + s.span);\n if (!occupied) collapsed[index] = true;\n }\n return collapsed;\n}\n\n// ---------------------------------------------------------------------------\n// Placement (CSS §8.5)\n\ninterface AxisSpec {\n /** Normalized 0-based track index of the start line (explicit tracks\n * occupy [0, explicitCount)); may be negative (implicit tracks before\n * the explicit grid) or null for auto. */\n start: number | null;\n span: number;\n}\n\n/** The explicit grid of one axis for line resolution: its track count\n * and the names on each of its `explicitCount + 1` lines (template\n * `[name]` groups plus the `<area>-start` / `<area>-end` lines areas\n * imply). Line indices are 0-based; indices outside `0 … explicitCount`\n * are implicit lines. */\nexport interface AxisLines {\n explicitCount: number;\n names: string[][];\n}\n\n/**\n * A definite line (numeric or named) as a 0-based line index, or null\n * for `auto` and spans. Numbers are 1-based, negatives count from the\n * explicit grid's end. A bare name first matches the first line named\n * `<name>-start` / `<name>-end` for its side (the area edges), else it\n * means `1 <name>`; `<n> <name>` is the n-th line so named, walking into\n * the implicit grid when fewer exist (every implicit line is assumed to\n * carry every name, per CSS §8.3).\n */\nfunction lineToIndex(line: GridLine, side: \"start\" | \"end\", lines: AxisLines): number | null {\n if (line.kind === \"line\") {\n return line.value > 0 ? line.value - 1 : lines.explicitCount + 1 + line.value;\n }\n if (line.kind !== \"name\") return null;\n if (line.nth === undefined) {\n const edge = `${line.name}-${side}`;\n const index = lines.names.findIndex((names) => names.includes(edge));\n if (index !== -1) return index;\n }\n const nth = line.nth ?? 1;\n const count = lines.explicitCount;\n let seen = 0;\n if (nth > 0) {\n for (let i = 0; i <= count; i++) {\n if (lines.names[i]!.includes(line.name) && ++seen === nth) return i;\n }\n return count + (nth - seen);\n }\n for (let i = count; i >= 0; i--) {\n if (lines.names[i]!.includes(line.name) && ++seen === -nth) return i;\n }\n return -(-nth - seen);\n}\n\n/** The line a span reaches from a definite line: plain spans count every\n * line; a named span counts only lines carrying the name (all implicit\n * lines beyond the explicit grid count, per CSS). */\nfunction spanFrom(\n from: number,\n span: { value: number; name?: string },\n direction: 1 | -1,\n lines: AxisLines,\n): number {\n if (span.name === undefined) return from + direction * span.value;\n let remaining = span.value;\n let i = from;\n while (remaining > 0) {\n i += direction;\n const explicit = i >= 0 && i <= lines.explicitCount;\n if (!explicit || lines.names[i]!.includes(span.name)) remaining--;\n }\n return i;\n}\n\n/**\n * Resolve one axis of an item's placement from the two line longhands\n * (CSS §8.3). Both lines definite: start = the earlier line, span = the\n * distance (equal lines → the end line is discarded, span 1). One\n * definite line + a span → definite. Only spans (or nothing) →\n * indefinite with the requested span (a named span against `auto` is a\n * plain span — specs/grid.md deviation).\n */\nexport function resolveAxisPlacement(\n startLine: GridLine,\n endLine: GridLine,\n lines: AxisLines,\n): AxisSpec {\n const start = lineToIndex(startLine, \"start\", lines);\n const end = lineToIndex(endLine, \"end\", lines);\n if (start !== null && end !== null) {\n if (start === end) return { start, span: 1 };\n return { start: Math.min(start, end), span: Math.abs(end - start) };\n }\n if (start !== null) {\n const spanEnd = endLine.kind === \"span\" ? spanFrom(start, endLine, 1, lines) : start + 1;\n return { start, span: spanEnd - start };\n }\n if (end !== null) {\n const spanStart = startLine.kind === \"span\" ? spanFrom(end, startLine, -1, lines) : end - 1;\n return { start: spanStart, span: end - spanStart };\n }\n const span =\n startLine.kind === \"span\" ? startLine.value : endLine.kind === \"span\" ? endLine.value : 1;\n return { start: null, span };\n}\n\ninterface PlacedAxis {\n start: number;\n span: number;\n}\n\ninterface PlacementResult {\n items: { col: PlacedAxis; row: PlacedAxis }[];\n colOrigin: number;\n colCount: number;\n rowOrigin: number;\n rowCount: number;\n}\n\n/**\n * CSS §8.5 auto-placement. The flow's major axis grows (rows for `row`\n * flow); the minor axis has a bounded track count. Sparse (default): the\n * cursor only moves forward; `dense` restarts the scan from the grid's\n * start for every item. Items are expected in order-then-document order.\n */\nexport function placeItems(\n specs: { col: AxisSpec; row: AxisSpec }[],\n explicitCols: number,\n explicitRows: number,\n flow: GridAutoFlow,\n): PlacementResult {\n const rowFlow = flow.direction === \"row\";\n const major = specs.map((s) => (rowFlow ? s.row : s.col));\n const minor = specs.map((s) => (rowFlow ? s.col : s.row));\n const explicitMinor = rowFlow ? explicitCols : explicitRows;\n const explicitMajor = rowFlow ? explicitRows : explicitCols;\n\n // Minor-axis bounds (§8.5 step 3): the explicit count, grown by definite\n // placements (negative lines extend before the grid) and by the largest\n // span among the items to be auto-placed.\n let minorOrigin = 0;\n let minorEnd = Math.max(explicitMinor, 1);\n for (let i = 0; i < specs.length; i++) {\n const m = minor[i]!;\n if (m.start !== null) {\n minorOrigin = Math.min(minorOrigin, m.start);\n minorEnd = Math.max(minorEnd, m.start + m.span);\n }\n }\n for (let i = 0; i < specs.length; i++) {\n const m = minor[i]!;\n if (m.start === null) minorEnd = Math.max(minorEnd, minorOrigin + m.span);\n }\n let majorOrigin = 0;\n for (let i = 0; i < specs.length; i++) {\n const mj = major[i]!;\n if (mj.start !== null) majorOrigin = Math.min(majorOrigin, mj.start);\n }\n\n const occupied = new Set<string>();\n const fits = (mj: number, mn: number, mjSpan: number, mnSpan: number): boolean => {\n for (let a = mj; a < mj + mjSpan; a++) {\n for (let b = mn; b < mn + mnSpan; b++) if (occupied.has(`${a}:${b}`)) return false;\n }\n return true;\n };\n const mark = (mj: number, mn: number, mjSpan: number, mnSpan: number): void => {\n for (let a = mj; a < mj + mjSpan; a++) {\n for (let b = mn; b < mn + mnSpan; b++) occupied.add(`${a}:${b}`);\n }\n };\n\n const result: ({ major: number; minor: number } | null)[] = specs.map(() => null);\n\n // Step 1: fully definite items.\n for (let i = 0; i < specs.length; i++) {\n const mj = major[i]!;\n const mn = minor[i]!;\n if (mj.start === null || mn.start === null) continue;\n result[i] = { major: mj.start, minor: mn.start };\n mark(mj.start, mn.start, mj.span, mn.span);\n }\n\n // Step 2: items locked to a major-axis position. Sparse keeps a per-line\n // minor cursor so later items on the same line only move forward.\n const lineCursor = new Map<number, number>();\n for (let i = 0; i < specs.length; i++) {\n const mj = major[i]!;\n const mn = minor[i]!;\n if (mj.start === null || mn.start !== null) continue;\n const from = flow.dense\n ? minorOrigin\n : Math.max(minorOrigin, lineCursor.get(mj.start) ?? minorOrigin);\n let position = from;\n while (!fits(mj.start, position, mj.span, mn.span)) position++;\n result[i] = { major: mj.start, minor: position };\n mark(mj.start, position, mj.span, mn.span);\n if (!flow.dense) lineCursor.set(mj.start, position + mn.span);\n minorEnd = Math.max(minorEnd, position + mn.span);\n }\n\n // Steps 3–4: the auto-placement cursor.\n let curMajor = majorOrigin;\n let curMinor = minorOrigin;\n for (let i = 0; i < specs.length; i++) {\n if (result[i] !== null) continue;\n const mj = major[i]!;\n const mn = minor[i]!;\n if (flow.dense) {\n curMajor = majorOrigin;\n curMinor = minorOrigin;\n }\n if (mn.start !== null) {\n // Definite minor position: overflowing the cursor's minor position\n // wraps to the next major line, then the item slides down until it\n // fits.\n if (mn.start < curMinor) curMajor++;\n while (!fits(curMajor, mn.start, mj.span, mn.span)) curMajor++;\n result[i] = { major: curMajor, minor: mn.start };\n mark(curMajor, mn.start, mj.span, mn.span);\n curMinor = mn.start + mn.span;\n } else {\n let mjPos = curMajor;\n let mnPos = curMinor;\n for (;;) {\n if (mnPos + mn.span > minorEnd) {\n mjPos++;\n mnPos = minorOrigin;\n continue;\n }\n if (fits(mjPos, mnPos, mj.span, mn.span)) break;\n mnPos++;\n }\n result[i] = { major: mjPos, minor: mnPos };\n mark(mjPos, mnPos, mj.span, mn.span);\n curMajor = mjPos;\n curMinor = mnPos + mn.span;\n }\n }\n\n let majorEnd = Math.max(explicitMajor, majorOrigin);\n for (let i = 0; i < specs.length; i++) {\n majorEnd = Math.max(majorEnd, result[i]!.major + major[i]!.span);\n }\n\n const items = specs.map((_, i) => {\n const majorAxis = { start: result[i]!.major - majorOrigin, span: major[i]!.span };\n const minorAxis = { start: result[i]!.minor - minorOrigin, span: minor[i]!.span };\n return rowFlow ? { col: minorAxis, row: majorAxis } : { col: majorAxis, row: minorAxis };\n });\n const majorCount = majorEnd - majorOrigin;\n const minorCount = minorEnd - minorOrigin;\n return rowFlow\n ? {\n items,\n colOrigin: minorOrigin,\n colCount: minorCount,\n rowOrigin: majorOrigin,\n rowCount: majorCount,\n }\n : {\n items,\n colOrigin: majorOrigin,\n colCount: majorCount,\n rowOrigin: minorOrigin,\n rowCount: minorCount,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Track sizing (CSS §11, integer-adapted — specs/grid.md)\n\ninterface SizingItem {\n start: number;\n span: number;\n /** Min-content outer contribution (cells). */\n min: number;\n /** Max-content outer contribution (cells). */\n max: number;\n}\n\ninterface SizingResult {\n sizes: number[];\n /** Gap preceding each track (0 for the first and for collapsed tracks). */\n gapBefore: number[];\n /** Final growth limits (for the container's max-content size). */\n limits: number[];\n}\n\ninterface TrackState {\n base: number;\n /** Fixed or contribution-grown limit; null = infinite so far. */\n limit: number | null;\n /** Which contributions grow the base: intrinsic mins (auto /\n * min-content / max-content / unresolvable percent) take min-content\n * contributions (specs/grid.md step 2). */\n baseIntrinsic: boolean;\n /** How the limit grows: fixed never; fr via §11.7; intrinsic-min from\n * min-content contributions (max = min-content); intrinsic-max from\n * max-content contributions (max = auto / max-content). */\n limitKind: \"fixed\" | \"fr\" | \"intrinsic-min\" | \"intrinsic-max\";\n frFactor: number;\n collapsed: boolean;\n}\n\n/**\n * Size one axis's tracks. `space` is the definite inner size in the axis,\n * or the intrinsic sizing constraint when the axis is indefinite:\n * `\"max-content\"` for actual layout of an unbounded axis (rows of an\n * auto-height container), `\"min-content\"` for the container's min-content\n * measure. Steps: initialize from the minmax pairs; grow intrinsic\n * bases/limits from item contributions in ascending span order\n * (equal-weight integer distribution — specs/grid.md deviation); clamp\n * bases to fixed limits (the limit wins, emulating the spec's\n * limited-contribution rule). Definite: maximize bases up to limits\n * (§11.6), distribute the leftover to fr tracks floored at their bases\n * (§11.7), stretch auto-limited tracks over any remainder when the axis's\n * content-distribution is `stretch` (§11.8). Indefinite: fr tracks size\n * to the shared flex fraction (§11.7 with indefinite space), and under\n * the max-content constraint every track maximizes to its growth limit —\n * a fixed minmax max fills even without content, per CSS (§11.6's\n * infinite free space; all three browser engines agree).\n */\nexport function sizeTracks(\n trackSizes: TrackSize[],\n collapsed: boolean[],\n items: SizingItem[],\n space: number | \"min-content\" | \"max-content\",\n gap: number,\n stretchAuto: boolean,\n): SizingResult {\n const available = typeof space === \"number\" ? space : undefined;\n const tracks: TrackState[] = trackSizes.map((size, i) => {\n if (collapsed[i]) {\n return {\n base: 0,\n limit: 0,\n baseIntrinsic: false,\n limitKind: \"fixed\",\n frFactor: 0,\n collapsed: true,\n };\n }\n const fixedMin = fixedBreadth(size.min, available);\n const base = fixedMin ?? 0;\n const baseIntrinsic = fixedMin === undefined;\n const max = size.max;\n if (max.kind === \"fr\") {\n return {\n base,\n limit: null,\n baseIntrinsic,\n limitKind: \"fr\",\n frFactor: max.value,\n collapsed: false,\n };\n }\n const fixedMax = fixedBreadth(max, available);\n if (fixedMax !== undefined) {\n return {\n base,\n limit: fixedMax,\n baseIntrinsic,\n limitKind: \"fixed\",\n frFactor: 0,\n collapsed: false,\n };\n }\n return {\n base,\n limit: null,\n baseIntrinsic,\n limitKind: max.kind === \"min-content\" ? \"intrinsic-min\" : \"intrinsic-max\",\n frFactor: 0,\n collapsed: false,\n };\n });\n\n const gapBefore: number[] = tracks.map((t, i) => {\n if (i === 0 || t.collapsed) return 0;\n return tracks.slice(0, i).some((p) => !p.collapsed) ? gap : 0;\n });\n const internalGaps = (start: number, span: number): number => {\n let sum = 0;\n for (let i = start + 1; i < start + span; i++) sum += gapBefore[i]!;\n return sum;\n };\n const effectiveLimit = (t: TrackState): number =>\n t.collapsed ? 0 : t.limitKind === \"fixed\" ? t.limit! : Math.max(t.base, t.limit ?? t.base);\n\n // Step 2: intrinsic contributions, ascending span order. An item\n // spanning an fr track distributes only its MIN-content contribution,\n // and only to the fr tracks' bases (weighted by flex factor, per CSS\n // §11.5.1) — this is the automatic minimum that makes bare `1fr 1fr`\n // columns unequal under long content; max contributions are §11.7's\n // job. Everything else grows the intrinsic tracks it spans.\n const bySpan = [...items].sort((a, b) => a.span - b.span);\n for (const item of bySpan) {\n const spanned: TrackState[] = [];\n let crossesFr = false;\n for (let i = item.start; i < item.start + item.span; i++) {\n const t = tracks[i];\n if (t === undefined) continue;\n if (t.limitKind === \"fr\") crossesFr = true;\n spanned.push(t);\n }\n if (spanned.length === 0) continue;\n const gaps = internalGaps(item.start, item.span);\n if (crossesFr) {\n // Only fr tracks with an INTRINSIC min (`1fr` = minmax(auto, 1fr))\n // take the automatic minimum; `minmax(0, 1fr)` opts out and keeps\n // dividing evenly.\n const frReceivers = spanned.filter(\n (t) => t.limitKind === \"fr\" && t.baseIntrinsic && !t.collapsed,\n );\n if (frReceivers.length === 0) continue;\n const current = spanned.reduce((s, t) => s + t.base, 0) + gaps;\n const needed = item.min - current;\n if (needed > 0) {\n const factorSum = frReceivers.reduce((s, t) => s + t.frFactor, 0);\n const shares = distributeInteger(\n frReceivers.map((t) => (factorSum > 0 ? t.frFactor : 1)),\n needed,\n );\n frReceivers.forEach((t, k) => {\n t.base += shares[k]!;\n });\n }\n continue;\n }\n\n // Bases: grow the intrinsic-min tracks until the span covers the\n // item's min-content contribution.\n const baseReceivers = spanned.filter((t) => t.baseIntrinsic && !t.collapsed);\n if (baseReceivers.length > 0) {\n const current = spanned.reduce((s, t) => s + t.base, 0) + gaps;\n const needed = item.min - current;\n if (needed > 0) {\n const shares = distributeInteger(\n baseReceivers.map(() => 1),\n needed,\n );\n baseReceivers.forEach((t, k) => {\n t.base += shares[k]!;\n });\n }\n }\n // Limits: grow the intrinsic-limit tracks toward the corresponding\n // contribution (min-content maxes take the min contribution).\n for (const [kind, contribution] of [\n [\"intrinsic-min\", item.min],\n [\"intrinsic-max\", item.max],\n ] as const) {\n const receivers = spanned.filter((t) => t.limitKind === kind && !t.collapsed);\n if (receivers.length === 0) continue;\n const current = spanned.reduce((s, t) => s + effectiveLimit(t), 0) + gaps;\n const needed = contribution - current;\n if (needed > 0) {\n const shares = distributeInteger(\n receivers.map(() => 1),\n needed,\n );\n receivers.forEach((t, k) => {\n t.limit = effectiveLimit(t) + shares[k]!;\n });\n }\n }\n }\n\n // Step 3: clamp. A fixed limit wins over a larger base (mirroring\n // min/max-width, and emulating CSS's limited contributions); an\n // intrinsic limit is floored at its base.\n for (const t of tracks) {\n if (t.collapsed) continue;\n if (t.limitKind === \"fixed\") t.base = Math.min(t.base, t.limit!);\n else if (t.limitKind !== \"fr\") t.limit = Math.max(t.base, t.limit ?? t.base);\n }\n\n if (available === undefined) {\n // Indefinite axis. Flexible tracks size to the shared flex fraction\n // (§11.7 with indefinite space): the largest of each fr track's\n // base ÷ factor and, per item crossing fr tracks, its max-content\n // contribution left after the non-flexible spanned tracks, divided by\n // the crossed flex factors (floored at 1, per §11.7.1). Integer cells\n // via the shared rounding. This is why two `1fr` rows both take the\n // TALLEST item's height, matching browsers.\n const frTracks = tracks.filter((t) => t.limitKind === \"fr\" && !t.collapsed);\n if (frTracks.length > 0) {\n let fraction = 0;\n for (const t of frTracks) {\n if (t.frFactor > 0) fraction = Math.max(fraction, t.base / t.frFactor);\n }\n for (const item of items) {\n let factorSum = 0;\n let nonFlexible = internalGaps(item.start, item.span);\n for (let i = item.start; i < item.start + item.span; i++) {\n const t = tracks[i];\n if (t === undefined || t.collapsed) continue;\n if (t.limitKind === \"fr\") factorSum += t.frFactor;\n else nonFlexible += effectiveLimit(t);\n }\n if (factorSum <= 0) continue;\n fraction = Math.max(fraction, (item.max - nonFlexible) / Math.max(factorSum, 1));\n }\n for (const t of frTracks) {\n const size = Math.max(t.base, roundHalfAwayFromZero(t.frFactor * fraction));\n t.limit = size;\n if (space === \"max-content\") t.base = size;\n }\n }\n // Under the max-content constraint (§11.6 with infinite free space)\n // every other track maximizes to its growth limit.\n if (space === \"max-content\") {\n for (const t of tracks) {\n if (!t.collapsed && t.limitKind !== \"fr\") t.base = effectiveLimit(t);\n }\n }\n } else {\n const totalGaps = gapBefore.reduce((s, g) => s + g, 0);\n // §11.6 maximize: grow bases up to their growth limits with the free\n // space, equal shares, re-distributing what frozen tracks can't take.\n let free = available - totalGaps - tracks.reduce((s, t) => s + t.base, 0);\n for (;;) {\n if (free <= 0) break;\n const growable = tracks.filter(\n (t) => !t.collapsed && t.limitKind !== \"fr\" && t.base < effectiveLimit(t),\n );\n if (growable.length === 0) break;\n const shares = distributeInteger(\n growable.map(() => 1),\n free,\n );\n let grown = 0;\n growable.forEach((t, k) => {\n const grow = Math.min(shares[k]!, effectiveLimit(t) - t.base);\n t.base += grow;\n grown += grow;\n });\n free -= grown;\n if (grown === 0) break;\n }\n\n // §11.7 fr distribution: the space left after non-fr tracks, shared by\n // factor, each fr track floored at its base (the automatic minimum for\n // bare `<n>fr`; `minmax(0, 1fr)` has base 0 and divides evenly). A\n // factor sum below 1 only distributes that fraction of the space, per\n // CSS. Frozen-at-base tracks drop out and the rest re-distribute.\n const frTracks = tracks.filter((t) => t.limitKind === \"fr\");\n if (frTracks.length > 0) {\n const leftover = Math.max(\n 0,\n available - totalGaps - tracks.reduce((s, t) => s + (t.limitKind === \"fr\" ? 0 : t.base), 0),\n );\n let active = frTracks;\n let space = leftover;\n const factorSum = frTracks.reduce((s, t) => s + t.frFactor, 0);\n if (factorSum < 1) space = Math.floor(space * factorSum);\n for (;;) {\n const shares = distributeInteger(\n active.map((t) => t.frFactor),\n space,\n );\n const violators = active.filter((t, k) => shares[k]! < t.base);\n if (violators.length === 0) {\n active.forEach((t, k) => {\n t.base = Math.max(t.base, shares[k]!);\n });\n break;\n }\n for (const t of violators) space -= t.base;\n space = Math.max(0, space);\n active = active.filter((t) => !violators.includes(t));\n if (active.length === 0) break;\n }\n }\n\n // §11.8 stretch auto tracks: under `normal`/`stretch` content\n // distribution, leftover space grows the auto-limited tracks equally.\n if (stretchAuto) {\n const remaining = available - totalGaps - tracks.reduce((s, t) => s + t.base, 0);\n const autoTracks = tracks.filter((t) => !t.collapsed && t.limitKind === \"intrinsic-max\");\n if (remaining > 0 && autoTracks.length > 0) {\n const shares = distributeInteger(\n autoTracks.map(() => 1),\n remaining,\n );\n autoTracks.forEach((t, k) => {\n t.base += shares[k]!;\n });\n }\n }\n }\n\n return {\n sizes: tracks.map((t) => t.base),\n gapBefore,\n limits: tracks.map((t) => effectiveLimit(t)),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Geometry\n\n/** Track start positions relative to the content-box origin, including\n * the content-distribution offsets when the tracks underfill the axis\n * (`stretch` already consumed the space in sizing; it offsets as start). */\nfunction trackPositions(\n sizing: SizingResult,\n available: number,\n distribute: JustifyContent,\n): number[] {\n const { sizes, gapBefore } = sizing;\n const leftover = Math.max(0, available - totalExtent(sizing));\n const offsets = mainAxisOffsets(distribute === \"stretch\" ? \"start\" : distribute, sizes, leftover);\n const positions: number[] = [];\n let gapSum = 0;\n for (let i = 0; i < sizes.length; i++) {\n gapSum += gapBefore[i]!;\n positions.push(offsets[i]! + gapSum);\n }\n return positions;\n}\n\nfunction totalExtent(sizing: SizingResult): number {\n return sizing.sizes.reduce((s, v) => s + v, 0) + sizing.gapBefore.reduce((s, g) => s + g, 0);\n}\n\n/** The extent of a track span, internal gaps included. */\nfunction areaExtent(positions: number[], sizes: number[], start: number, span: number): number {\n const last = start + span - 1;\n if (positions[start] === undefined || positions[last] === undefined) return 0;\n return positions[last]! + sizes[last]! - positions[start]!;\n}\n\n/** An item's offset inside its grid area along one axis: auto margins win\n * over alignment (both → centered, one → pushed to the other side), then\n * the fixed leading margin plus the alignment offset (`stretch` behaves\n * as `start` — the stretch already happened in sizing). */\nfunction areaAxisOffset(\n align: AlignItems,\n before: number | null,\n after: number | null,\n area: number,\n size: number,\n): number {\n const fixedBefore = before ?? 0;\n const fixedAfter = after ?? 0;\n const slack = area - size;\n if (before === null && after === null) return Math.floor(slack / 2);\n if (before === null) return slack - fixedAfter;\n if (after === null) return fixedBefore;\n return fixedBefore + alignCrossOffset(align, area, size + fixedBefore + fixedAfter);\n}\n","import {\n clampSize,\n intrinsicOuterWidth,\n isPositioned,\n layoutNode,\n minContentOuterWidth,\n resolveLength,\n resolveLimit,\n resolveMargin,\n resolveSizeAgainst,\n resolveWidthLimit,\n} from \"./layout.ts\";\nimport type { IntrinsicCache } from \"./layout.ts\";\nimport { alignCrossOffset, effectiveAlign, effectiveJustify, mainAxisOffsets } from \"./flex.ts\";\nimport type { CellLength, CellStyle, LayoutNode, Rect } from \"./types.ts\";\n\n/**\n * Positioning pass (specs/positioning.md): after flow layout, place\n * out-of-flow (absolute/fixed) boxes against their containing blocks and\n * apply relative offsets. Runs top-down so ancestor rects are final\n * first. See layout.ts for the deliberate import cycle between the layout\n * modules.\n */\n\ntype Effective = \"static\" | \"relative\" | \"absolute\";\n\n/** sticky behaves as relative (no scrolling yet); fixed as absolute. */\nfunction effectivePosition(style: CellStyle): Effective {\n if (style.position === \"absolute\" || style.position === \"fixed\") return \"absolute\";\n if (style.position === \"relative\" || style.position === \"sticky\") return \"relative\";\n return \"static\";\n}\n\ninterface Frame {\n node: LayoutNode;\n absX: number;\n absY: number;\n}\n\nexport function walkPositioned(\n node: LayoutNode,\n absX: number,\n absY: number,\n ancestors: Frame[],\n cache: IntrinsicCache,\n): void {\n for (const child of node.children) {\n const effective = effectivePosition(child.style);\n if (effective === \"relative\") {\n // Pure visual offset; percent insets resolve against the parent's\n // content box. `top` wins over `bottom`, `left` over `right` (LTR).\n const contentW =\n node.localRect.width -\n node.style.border.left -\n node.style.border.right -\n node.resolvedPadding.left -\n node.resolvedPadding.right;\n const contentH =\n node.localRect.height -\n node.style.border.top -\n node.style.border.bottom -\n node.resolvedPadding.top -\n node.resolvedPadding.bottom;\n child.localRect.x += relativeOffset(\n child.style.insets.left,\n child.style.insets.right,\n contentW,\n );\n child.localRect.y += relativeOffset(\n child.style.insets.top,\n child.style.insets.bottom,\n contentH,\n );\n } else if (effective === \"absolute\") {\n placeAbsolute(child, node, absX, absY, ancestors, cache);\n }\n walkPositioned(\n child,\n absX + child.localRect.x,\n absY + child.localRect.y,\n [\n ...ancestors,\n { node: child, absX: absX + child.localRect.x, absY: absY + child.localRect.y },\n ],\n cache,\n );\n }\n}\n\nfunction relativeOffset(start: CellLength | null, end: CellLength | null, basis: number): number {\n if (start !== null) return resolveLength(start, basis);\n if (end !== null) return -resolveLength(end, basis);\n return 0;\n}\n\n/** The containing block's padding box, in absolute cells: the nearest\n * positioned ancestor, or the host for `fixed` / when none exists. */\nfunction containingBlock(ancestors: Frame[], fixed: boolean): Rect {\n if (!fixed) {\n for (let i = ancestors.length - 1; i > 0; i--) {\n const frame = ancestors[i]!;\n if (!isPositioned(frame.node.style)) continue;\n const b = frame.node.style.border;\n return {\n x: frame.absX + b.left,\n y: frame.absY + b.top,\n width: Math.max(0, frame.node.localRect.width - b.left - b.right),\n height: Math.max(0, frame.node.localRect.height - b.top - b.bottom),\n };\n }\n }\n const host = ancestors[0]!;\n return {\n x: host.absX,\n y: host.absY,\n width: host.node.localRect.width,\n height: host.node.localRect.height,\n };\n}\n\nfunction placeAbsolute(\n child: LayoutNode,\n parent: LayoutNode,\n parentAbsX: number,\n parentAbsY: number,\n ancestors: Frame[],\n cache: IntrinsicCache,\n): void {\n const style = child.style;\n const fixed = style.position === \"fixed\";\n const slot = child.staticSlot;\n // A positioned GRID parent's absolute child is contained by its grid\n // area (specs/grid.md §10.1), not the parent's padding box.\n const cb: Rect =\n slot?.kind === \"grid\" && !fixed && isPositioned(parent.style)\n ? {\n x: parentAbsX + slot.area.x,\n y: parentAbsY + slot.area.y,\n width: slot.area.width,\n height: slot.area.height,\n }\n : containingBlock(ancestors, fixed);\n const left = style.insets.left === null ? null : resolveLength(style.insets.left, cb.width);\n const right = style.insets.right === null ? null : resolveLength(style.insets.right, cb.width);\n const top = style.insets.top === null ? null : resolveLength(style.insets.top, cb.height);\n const bottom =\n style.insets.bottom === null ? null : resolveLength(style.insets.bottom, cb.height);\n const margin = resolveMargin(style.margin, cb.width);\n const marginLeft = margin.left ?? 0;\n const marginRight = margin.right ?? 0;\n const marginTop = margin.top ?? 0;\n const marginBottom = margin.bottom ?? 0;\n\n // Used width, per CSS in priority order: an explicit width resolves\n // against the CONTAINING BLOCK (percent included); opposing insets with\n // an auto width stretch the box between them; otherwise shrink-to-fit\n // (fit-content) within the space the insets and margins leave. All\n // clamped by the element's min/max against the containing block.\n const widthAuto = style.width === undefined || style.width.kind === \"auto\";\n const heightAuto = style.height === undefined || style.height.kind === \"auto\";\n const minW = resolveWidthLimit(style.minWidth, cb.width, child, cache) ?? 0;\n const maxW = resolveWidthLimit(style.maxWidth, cb.width, child, cache);\n const forced: { width?: number; height?: number } = {};\n if (!widthAuto) {\n forced.width = clampSize(resolveSizeAgainst(style.width!, cb.width, child, cache), minW, maxW);\n } else if (left !== null && right !== null) {\n forced.width = clampSize(\n Math.max(0, cb.width - left - right - marginLeft - marginRight),\n minW,\n maxW,\n );\n } else {\n const available = Math.max(0, cb.width - (left ?? 0) - (right ?? 0) - marginLeft - marginRight);\n forced.width = clampSize(\n Math.min(\n intrinsicOuterWidth(child, cache),\n Math.max(minContentOuterWidth(child, cache), available),\n ),\n minW,\n maxW,\n );\n }\n if (top !== null && bottom !== null && heightAuto) {\n forced.height = clampSize(\n Math.max(0, cb.height - top - bottom - marginTop - marginBottom),\n resolveLimit(style.minHeight, cb.height) ?? 0,\n resolveLimit(style.maxHeight, cb.height),\n );\n }\n layoutNode(child, cb.width, cb.height, 0, 0, \"shrink\", cache, forced);\n const width = child.localRect.width;\n const height = child.localRect.height;\n\n // Horizontal placement. Both insets + auto margins center (`inset-0\n // m-auto` idiom); a single auto margin absorbs the slack on its side.\n let x: number;\n if (left !== null && right !== null) {\n const slack = Math.max(0, cb.width - left - right - width - marginLeft - marginRight);\n const bothAuto = margin.left === null && margin.right === null;\n x =\n cb.x +\n left +\n marginLeft +\n (bothAuto ? Math.floor(slack / 2) : margin.left === null ? slack : 0);\n } else if (left !== null) {\n x = cb.x + left + marginLeft;\n } else if (right !== null) {\n x = cb.x + cb.width - right - width - marginRight;\n } else {\n x = staticPositionX(child, parent, parentAbsX, width);\n }\n let y: number;\n if (top !== null && bottom !== null) {\n const slack = Math.max(0, cb.height - top - bottom - height - marginTop - marginBottom);\n const bothAuto = margin.top === null && margin.bottom === null;\n y =\n cb.y + top + marginTop + (bothAuto ? Math.floor(slack / 2) : margin.top === null ? slack : 0);\n } else if (top !== null) {\n y = cb.y + top + marginTop;\n } else if (bottom !== null) {\n y = cb.y + cb.height - bottom - height - marginBottom;\n } else {\n y = staticPositionY(child, parent, parentAbsY, height);\n }\n\n child.localRect = { ...child.localRect, x: x - parentAbsX, y: y - parentAbsY };\n}\n\n/** The sole-item static position along the main axis is exactly where a\n * single in-flow item would land — reuse the canonical justify math, which\n * already encodes the CSS content-distribution fallbacks. */\nfunction soleItemMainOffset(\n justify: CellStyle[\"justifyContent\"],\n inner: number,\n size: number,\n): number {\n return mainAxisOffsets(justify, [size], Math.max(0, inner - size))[0]!;\n}\n\n/** Cross alignment for the sole-item rule; stretch behaves as start. */\nfunction soleItemCrossOffset(\n child: LayoutNode,\n parent: LayoutNode,\n inner: number,\n size: number,\n): number {\n return alignCrossOffset(effectiveAlign(child, parent), inner, size);\n}\n\n/** The hypothetical sole-item box includes the element's fixed margins\n * (auto margins count as 0 in the static position, per CSS §10.1). */\nfunction flexStaticOffset(\n child: LayoutNode,\n parent: LayoutNode,\n slot: { direction: \"row\" | \"column\"; innerWidth: number; innerHeight: number },\n axis: \"x\" | \"y\",\n size: number,\n): number {\n const margin = resolveMargin(child.style.margin, slot.innerWidth);\n const [before, after, inner, isMain] =\n axis === \"x\"\n ? ([margin.left ?? 0, margin.right ?? 0, slot.innerWidth, slot.direction === \"row\"] as const)\n : ([\n margin.top ?? 0,\n margin.bottom ?? 0,\n slot.innerHeight,\n slot.direction === \"column\",\n ] as const);\n const outer = size + before + after;\n const offset = isMain\n ? soleItemMainOffset(effectiveJustify(parent.style), inner, outer)\n : soleItemCrossOffset(child, parent, inner, outer);\n return offset + before;\n}\n\n/** The grid static position (specs/grid.md §10.1): the sole item of the\n * recorded static area, self-aligned (`justify-self` / `align-self`,\n * stretch behaving as start) with its fixed margins in the box. */\nfunction gridStaticOffset(\n child: LayoutNode,\n parent: LayoutNode,\n area: Rect,\n axis: \"x\" | \"y\",\n size: number,\n): number {\n const margin = resolveMargin(child.style.margin, area.width);\n const justify =\n child.style.justifySelf === \"auto\"\n ? parent.style.justifyItems\n : (child.style.justifySelf as CellStyle[\"alignItems\"]);\n const [before, after, inner, align] =\n axis === \"x\"\n ? ([margin.left ?? 0, margin.right ?? 0, area.width, justify] as const)\n : ([\n margin.top ?? 0,\n margin.bottom ?? 0,\n area.height,\n effectiveAlign(child, parent),\n ] as const);\n return alignCrossOffset(align, inner, size + before + after) + before;\n}\n\nfunction staticPositionX(\n child: LayoutNode,\n parent: LayoutNode,\n parentAbsX: number,\n width: number,\n): number {\n const slot = child.staticSlot;\n if (slot === undefined) return parentAbsX;\n if (slot.kind === \"block\") return parentAbsX + slot.x;\n if (slot.kind === \"grid\") {\n return (\n parentAbsX + slot.staticArea.x + gridStaticOffset(child, parent, slot.staticArea, \"x\", width)\n );\n }\n return parentAbsX + slot.originX + flexStaticOffset(child, parent, slot, \"x\", width);\n}\n\nfunction staticPositionY(\n child: LayoutNode,\n parent: LayoutNode,\n parentAbsY: number,\n height: number,\n): number {\n const slot = child.staticSlot;\n if (slot === undefined) return parentAbsY;\n if (slot.kind === \"block\") return parentAbsY + slot.y;\n if (slot.kind === \"grid\") {\n return (\n parentAbsY + slot.staticArea.y + gridStaticOffset(child, parent, slot.staticArea, \"y\", height)\n );\n }\n return parentAbsY + slot.originY + flexStaticOffset(child, parent, slot, \"y\", height);\n}\n","import { percentToCells } from \"./metrics.ts\";\nimport {\n advanceOf,\n eachObjectMarker,\n hardLineSpans,\n lineAdvance,\n longestSegmentAdvance,\n OBJECT_REPLACEMENT,\n wrapLineSpans,\n} from \"./wrap.ts\";\nimport type { LineSpan } from \"./wrap.ts\";\nimport {\n alignCrossOffset,\n effectiveJustify,\n layoutFlexColumn,\n layoutFlexRow,\n mainAxisOffsets,\n} from \"./flex.ts\";\nimport { gridIntrinsicInnerWidths, layoutGrid } from \"./grid.ts\";\nimport { walkPositioned } from \"./positioning.ts\";\nimport type {\n CellLength,\n CellStyle,\n Insets,\n LayoutNode,\n NullableInsets,\n PerSide,\n Size,\n SizeLimit,\n} from \"./types.ts\";\n\n/**\n * Core layout: the per-node sizing pipeline, block flow, and the shared\n * sizing/intrinsic machinery. Flex lives in flex.ts, the positioning pass\n * in positioning.ts, each mirroring its spec file. The modules are\n * mutually recursive (children lay out through layoutNode), so the import\n * cycle between them is deliberate — safe because they contain only\n * hoisted function declarations with no top-level cross-module execution.\n */\n\n/**\n * Layout entry point: mutates localRect on the root and each descendant.\n * Coordinates are parent-relative (root's rect is at 0,0).\n */\nexport function layoutRoot(root: LayoutNode, availableWidth: number): { height: number } {\n const cache = makeIntrinsicCache();\n layoutNode(root, availableWidth, undefined, 0, 0, \"fill\", cache);\n // Positioning pass (specs/positioning.md): out-of-flow boxes were skipped\n // by flow layout; place them against their containing blocks, and apply\n // relative offsets. Runs top-down so ancestor rects are final first.\n walkPositioned(root, 0, 0, [{ node: root, absX: 0, absY: 0 }], cache);\n return { height: root.localRect.height };\n}\n\n/** absolute / fixed boxes are out of normal flow. */\nexport function isOutOfFlow(style: CellStyle): boolean {\n return style.position === \"absolute\" || style.position === \"fixed\";\n}\n\n/** A containing block for absolute descendants, per CSS. */\nexport function isPositioned(style: CellStyle): boolean {\n return style.position !== \"static\";\n}\n\nexport type SizingMode = \"fill\" | \"shrink\";\n\nexport interface IntrinsicCache {\n maxContent: WeakMap<LayoutNode, number>;\n minContent: WeakMap<LayoutNode, number>;\n /** Grid containers compute both intrinsic widths in one placement +\n * sizing pass — cached here so the min and max lookups share it. */\n gridIntrinsic: WeakMap<LayoutNode, { min: number; max: number }>;\n}\n\nexport function makeIntrinsicCache(): IntrinsicCache {\n return { maxContent: new WeakMap(), minContent: new WeakMap(), gridIntrinsic: new WeakMap() };\n}\n\n/**\n * `forced` carries flex-assigned (\"used\") sizes from a parent flex pass —\n * they are authoritative and skip resolution/clamping entirely (the flex\n * loop already applied min/max). With sizes forced, `availableWidth` stays\n * the CONTAINING BLOCK's content width, which percent padding, margins,\n * and min/max resolve against — never the assigned size itself.\n */\nexport function layoutNode(\n node: LayoutNode,\n availableWidth: number,\n availableHeight: number | undefined,\n parentX: number,\n parentY: number,\n widthMode: SizingMode,\n cache: IntrinsicCache,\n forced?: { width?: number | undefined; height?: number | undefined },\n): void {\n const style = node.style;\n const forcedHeight = forced?.height;\n\n // Width is clamped to min/max BEFORE laying out content — wrapping and\n // child sizing must see the constrained width, not the raw resolved one.\n // (Height differs: max-height clamps the final rect after layout, since\n // content height is an output, and overflow handles the spill.)\n // Percent min/max (`max-w-full`) resolve against the available size; a\n // percent height limit with indefinite available height is ignored, per CSS.\n const minWidth = resolveWidthLimit(style.minWidth, availableWidth, node, cache) ?? 0;\n const maxWidth = resolveWidthLimit(style.maxWidth, availableWidth, node, cache);\n const minHeight = resolveLimit(style.minHeight, availableHeight) ?? 0;\n const maxHeight = resolveLimit(style.maxHeight, availableHeight);\n // Percent padding resolves against the containing block's width (CSS: all\n // four sides use the inline size) — `availableWidth` is that width here.\n // Stored on the node because the renderers need the resolved cells too.\n const padding: Insets = {\n top: resolveLength(style.padding.top, availableWidth),\n right: resolveLength(style.padding.right, availableWidth),\n bottom: resolveLength(style.padding.bottom, availableWidth),\n left: resolveLength(style.padding.left, availableWidth),\n };\n node.resolvedPadding = padding;\n const outerWidth =\n forced?.width ??\n clampSize(resolveWidth(style, availableWidth, widthMode, node, cache), minWidth, maxWidth);\n const outerHeightExplicit = resolveHeight(style, availableHeight);\n // A `forcedHeight` (set by a parent flex-column when grow/shrink assigned a\n // main-axis size) overrides both explicit `height` and `min-height` — the\n // flex algorithm's \"used main size\" is authoritative. Otherwise, `min-height`\n // is a lower bound so items-center / items-end see the enforced size, not\n // just the natural content size.\n const outerHeightFloor =\n forcedHeight ?? outerHeightExplicit ?? (minHeight > 0 ? minHeight : undefined);\n\n const inner = shrinkSize(\n outerWidth,\n outerHeightFloor ?? Number.POSITIVE_INFINITY,\n style.border,\n padding,\n );\n\n // Whether the height is definite (explicit `height` or a parent-assigned\n // flex size) rather than only a `min-height` floor. Column flex: a floor\n // adds grow space but never triggers shrink. Everywhere: only a DEFINITE\n // content height is the basis for children's percent heights, per CSS.\n const heightIsDefinite = forcedHeight !== undefined || outerHeightExplicit !== undefined;\n const definiteInnerHeight =\n heightIsDefinite && Number.isFinite(inner.height) ? inner.height : undefined;\n\n let contentHeight: number;\n if (laysOutAsTextLeaf(node)) {\n // A text leaf (possibly carrying out-of-flow children), or an empty\n // box. `white-space: nowrap` text never soft-wraps: its height is the\n // hard-line (`<br>`) count, regardless of width. `leading-*` adds\n // `lineGap` empty rows BETWEEN lines only (specs/cell-model.md).\n if (node.text) {\n // Atomic inline boxes first: lay each out (shrink-to-fit; height =\n // its own content) and resolve its U+FFFC marker's advance to the\n // laid-out width, so the wrap below treats it as an unbreakable\n // unit of exactly that many cells.\n const boxes = node.children.filter((child) => child.inlineBox);\n eachObjectMarker(node.text, (charIndex, boxIndex) => {\n const box = boxes[boxIndex]!;\n layoutNode(box, inner.width, undefined, 0, 0, \"shrink\", cache);\n node.advances![charIndex] = Math.max(1, box.localRect.width);\n });\n const geometry = leafLineGeometry(node, inner.width);\n contentHeight = geometry.totalRows;\n // Content alignment of the anonymous text item, quantized to whole\n // cells (specs/cell-model.md): a flex/grid element whose content is\n // bare text centers/ends it by folding the leftover into the\n // engine-owned padding. The browser's own (fractional, off-grid)\n // anonymous-item alignment is reset in styles.css; padding places\n // the text instead, so browser, ASCII, and decorations agree.\n // Symmetry of the wrap is preserved: the padded content box is\n // exactly the widest line, and greedy wrap breaks identically there\n // (every line fits, and every overflow still overflows).\n alignLeafText(node, geometry, inner.width, inner.height, padding);\n // Place each box at its marker's wrapped (line, column) — the\n // browser's own line layout puts the in-flow box in the same spot\n // because both models reserve exactly the same cells for it, and a\n // taller box grows its LINE (per CSS; the box is vertical-align:\n // top, so its top sits on the line's first row like the text).\n if (boxes.length > 0) {\n const lineOfChar = (charIndex: number) =>\n geometry.spans.findIndex((span) => charIndex >= span.start && charIndex < span.end);\n eachObjectMarker(node.text, (charIndex, boxIndex) => {\n const line = lineOfChar(charIndex);\n if (line === -1) return; // e.g. width 0 edge; box stays at origin\n const span = geometry.spans[line]!;\n boxes[boxIndex]!.localRect = {\n ...boxes[boxIndex]!.localRect,\n x: style.border.left + padding.left + advanceOf(span.start, charIndex, node.advances),\n y: style.border.top + padding.top + geometry.lineY[line]!,\n };\n });\n }\n } else {\n contentHeight = node.intrinsicHeight;\n }\n // Out-of-flow children of a leaf: static position = the content-box\n // origin plus their margins (specs/positioning.md — CSS's hypothetical\n // inline position is approximated by the run's origin).\n for (const child of node.children) {\n if (child.inlineBox) continue;\n const margin = resolveMargin(child.style.margin, inner.width);\n child.staticSlot = {\n kind: \"block\",\n x: style.border.left + padding.left + (margin.left ?? 0),\n y: style.border.top + padding.top + (margin.top ?? 0),\n };\n }\n } else if (style.display === \"flex\" && style.flexDirection === \"row\") {\n contentHeight = layoutFlexRow(\n node,\n inner.width,\n inner.height,\n definiteInnerHeight,\n style.border,\n padding,\n cache,\n );\n } else if (style.display === \"flex\" && style.flexDirection === \"column\") {\n contentHeight = layoutFlexColumn(\n node,\n inner.width,\n inner.height,\n heightIsDefinite,\n style.border,\n padding,\n cache,\n );\n } else if (style.display === \"grid\") {\n contentHeight = layoutGrid(node, inner.width, inner.height, style.border, padding, cache);\n } else {\n contentHeight = layoutBlock(\n node,\n inner.width,\n definiteInnerHeight,\n style.border,\n padding,\n cache,\n );\n }\n\n const naturalHeight =\n contentHeight + style.border.top + style.border.bottom + padding.top + padding.bottom;\n // Order matters: min-* is a floor, max-* is a ceiling; when both apply,\n // max wins per CSS (min-width < max-width is required, but if the author\n // sets an inconsistent pair CSS clamps to `max(min, min(max, value))`).\n // The pre-clamp height is the column flex algorithm's base size (CSS\n // distributes from UNclamped bases; min/max apply via its freeze loop).\n const unclampedHeight = forcedHeight ?? outerHeightExplicit ?? naturalHeight;\n node.unclampedHeight = unclampedHeight;\n const finalHeight = clampSize(unclampedHeight, minHeight, maxHeight);\n\n node.localRect = { x: parentX, y: parentY, width: outerWidth, height: finalHeight };\n}\n\n/**\n * True when the node lays out as a TEXT LEAF: no in-flow block children\n * (atomic inline boxes ride the text run and out-of-flow boxes hang off\n * it, so neither counts), and either text to wrap or nothing at all. The\n * one exception: a TEXTLESS flex or grid container keeps its own path —\n * flex so its out-of-flow children get the sole-flex-item static\n * position, grid so explicit tracks still size an empty container. A\n * flex/grid element WITH text is still a leaf — its text lays out as a\n * single anonymous item that must size the box (for grid this skips\n * placing the anonymous item into the track grid; specs/grid.md\n * deviation).\n */\nfunction laysOutAsTextLeaf(node: LayoutNode): boolean {\n const hasInFlowChildren = node.children.some(\n (child) => !isOutOfFlow(child.style) && !child.inlineBox,\n );\n if (hasInFlowChildren) return false;\n return node.text !== \"\" || (node.style.display !== \"flex\" && node.style.display !== \"grid\");\n}\n\nexport function clampSize(value: number, min: number, max: number | undefined): number {\n const clamped = max !== undefined ? Math.min(value, max) : value;\n return Math.max(min, clamped);\n}\n\n/**\n * Quantized content alignment for a flex/grid text leaf: fold the leftover\n * space around the anonymous text item into the engine-owned padding so the\n * text lands on whole cells. Flex rows justify horizontally and align\n * vertically; columns swap; grid uses item alignment (justify-items /\n * align-items — the anonymous item's single implicit track fills the box).\n * The padded content box becomes exactly the widest line, which preserves\n * the wrap: every line still fits, and greedy breaks are unchanged.\n * Mutates `padding` (=== node.resolvedPadding), which the renderers and\n * this leaf's box/slot placement below all read.\n */\nfunction alignLeafText(\n node: LayoutNode,\n geometry: { spans: LineSpan[]; totalRows: number },\n innerWidth: number,\n innerHeight: number,\n padding: Insets,\n): void {\n const style = node.style;\n if (style.display !== \"flex\" && style.display !== \"grid\") return;\n if (geometry.spans.length === 0) return;\n const isColumn = style.display === \"flex\" && style.flexDirection === \"column\";\n\n const itemWidth = geometry.spans.reduce(\n (max, span) => Math.max(max, lineAdvance(span.start, span.end, node.advances, style.tracking)),\n 0,\n );\n const leftoverX = Math.max(0, innerWidth - itemWidth);\n if (leftoverX > 0) {\n const tx =\n style.display === \"grid\"\n ? alignCrossOffset(style.justifyItems, innerWidth, itemWidth)\n : isColumn\n ? alignCrossOffset(style.alignItems, innerWidth, itemWidth)\n : mainAxisOffsets(effectiveJustify(style), [itemWidth], leftoverX)[0]!;\n if (tx > 0) {\n padding.left += tx;\n padding.right += leftoverX - tx;\n }\n }\n\n // Vertical offsets only exist inside a bounded box (explicit height,\n // min-height floor, or a flex/grid-assigned size).\n if (Number.isFinite(innerHeight)) {\n const leftoverY = Math.max(0, innerHeight - geometry.totalRows);\n if (leftoverY > 0) {\n const ty =\n style.display === \"grid\" || !isColumn\n ? alignCrossOffset(style.alignItems, innerHeight, geometry.totalRows)\n : mainAxisOffsets(effectiveJustify(style), [geometry.totalRows], leftoverY)[0]!;\n if (ty > 0) {\n padding.top += ty;\n padding.bottom += leftoverY - ty;\n }\n }\n }\n}\n\n/**\n * A text leaf's wrapped lines with their vertical geometry. Lines are one\n * row tall unless an atomic inline box on the line is taller — the line\n * grows to the tallest box (per CSS line-box growth), and later lines\n * shift down. `lineGap` rows separate lines as usual. Requires the leaf's\n * inline boxes to be laid out already (their rect heights are read here);\n * marker advances must be resolved.\n */\nexport function leafLineGeometry(\n node: LayoutNode,\n contentWidth: number,\n): { spans: LineSpan[]; lineY: number[]; totalRows: number } {\n const spans =\n node.style.whiteSpace !== \"normal\"\n ? hardLineSpans(node.text)\n : wrapLineSpans(node.text, contentWidth, {\n advances: node.advances,\n tracking: node.style.tracking,\n });\n const boxes = node.children.filter((child) => child.inlineBox);\n const lineY: number[] = [];\n let y = 0;\n let boxIndex = 0;\n for (let s = 0; s < spans.length; s++) {\n lineY.push(y);\n const span = spans[s]!;\n let height = 1;\n for (let i = span.start; i < span.end; i++) {\n if (node.text[i] !== OBJECT_REPLACEMENT) continue;\n height = Math.max(height, boxes[boxIndex]!.localRect.height);\n boxIndex++;\n }\n y += height + (s < spans.length - 1 ? node.style.lineGap : 0);\n }\n return { spans, lineY, totalRows: y };\n}\n\n/** Resolve a spacing length to cells against its containing-block basis.\n * An indefinite basis (percent gap in an unbounded axis) resolves to 0. */\nexport function resolveLength(length: CellLength, basis: number | undefined): number {\n if (typeof length === \"number\") return length;\n return basis === undefined || !Number.isFinite(basis) ? 0 : percentToCells(length.percent, basis);\n}\n\n/** Resolve all four margin sides (preserving `auto` as null) against the\n * parent's content width — the CSS basis for every side. */\nexport function resolveMargin(margin: PerSide<CellLength | null>, basis: number): NullableInsets {\n const side = (v: CellLength | null) => (v === null ? null : resolveLength(v, basis));\n return {\n top: side(margin.top),\n right: side(margin.right),\n bottom: side(margin.bottom),\n left: side(margin.left),\n };\n}\n\n/** The cells of a CellLength for intrinsic sizing: percentages count as 0,\n * per CSS intrinsic-size contribution rules. */\nfunction intrinsicCells(length: CellLength): number {\n return typeof length === \"number\" ? length : 0;\n}\n\n/** Resolve a height limit to cells: percent needs a definite available\n * size; intrinsic keywords behave as \"no constraint\" on heights. `\"auto\"`\n * resolves to none here (0 in block flow) — flex main-axis code\n * substitutes the item's content-based automatic minimum itself. */\nexport function resolveLimit(\n limit: SizeLimit | \"auto\" | undefined,\n available: number | undefined,\n): number | undefined {\n if (limit === undefined || typeof limit === \"string\") return undefined;\n if (typeof limit === \"number\") return limit;\n return available === undefined ? undefined : percentToCells(limit.percent, available);\n}\n\n/** Resolve a WIDTH limit to cells — like resolveLimit, but intrinsic\n * keywords (`max-w-max` = max-content, …) resolve against the node's\n * content. */\nexport function resolveWidthLimit(\n limit: SizeLimit | \"auto\" | undefined,\n available: number,\n node: LayoutNode,\n cache: IntrinsicCache,\n): number | undefined {\n if (limit === \"min-content\" || limit === \"max-content\" || limit === \"fit-content\") {\n return resolveSizeAgainst({ kind: limit }, available, node, cache);\n }\n return resolveLimit(limit, available);\n}\n\n/**\n * Lay out children in vertical block flow. Returns content height (rows used).\n *\n * - Vertical (main-axis) margins on adjacent siblings **collapse** — the\n * effective gap is `max(prev.bottom, curr.top)` for two positives, `min`\n * for two negatives, and the sum for mixed signs (standard CSS rule).\n * Parent–child collapsing is intentionally NOT implemented (see the cell-\n * model spec's Deviations section).\n * - Horizontal (cross-axis) margins position the child; `auto` on either\n * side centers or end-aligns as CSS does.\n */\nfunction layoutBlock(\n node: LayoutNode,\n innerWidth: number,\n definiteInnerHeight: number | undefined,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const originX = border.left + padding.left;\n const startY = border.top + padding.top;\n let y = startY;\n let previousMarginBottom: number | null = null;\n for (const child of node.children) {\n const childMargin = resolveMargin(child.style.margin, innerWidth);\n const marginTop = childMargin.top ?? 0;\n const marginBottom = childMargin.bottom ?? 0;\n const marginLeft = childMargin.left ?? 0;\n const marginRight = childMargin.right ?? 0;\n if (isOutOfFlow(child.style)) {\n // Record the CSS static position (where the box would have started in\n // flow) without consuming space or disturbing margin collapsing.\n child.staticSlot = {\n kind: \"block\",\n x: originX + marginLeft,\n y:\n y +\n (previousMarginBottom === null\n ? marginTop\n : collapseMargins(previousMarginBottom, marginTop)),\n };\n continue;\n }\n layoutNode(\n child,\n Math.max(0, innerWidth - marginLeft - marginRight),\n definiteInnerHeight,\n 0,\n 0,\n \"fill\",\n cache,\n );\n const crossAvailable = innerWidth - child.localRect.width;\n const bothAutoX = childMargin.left === null && childMargin.right === null;\n const oneAutoLeft = childMargin.left === null && childMargin.right !== null;\n const oneAutoRight = childMargin.right === null && childMargin.left !== null;\n let crossOffset: number;\n if (bothAutoX) crossOffset = Math.floor(crossAvailable / 2);\n else if (oneAutoLeft) crossOffset = crossAvailable - marginRight;\n else if (oneAutoRight) crossOffset = marginLeft;\n else crossOffset = marginLeft;\n\n // `y` tracks the position where the next child's top edge goes. Margins\n // are added JUST BEFORE placing each child, then only the child's height\n // afterwards — the child's own bottom margin waits until the next\n // sibling (or the end-of-container) so we can collapse them properly.\n y +=\n previousMarginBottom === null ? marginTop : collapseMargins(previousMarginBottom, marginTop);\n child.localRect = { ...child.localRect, x: originX + crossOffset, y };\n y += child.localRect.height;\n previousMarginBottom = marginBottom;\n }\n if (previousMarginBottom !== null) y += previousMarginBottom;\n return y - startY;\n}\n\n/**\n * CSS margin-collapsing rule for two adjacent block-flow margins:\n * - both positive → the larger absorbs the smaller.\n * - both negative → the more negative absorbs the less negative.\n * - mixed → they sum (positive shrunk by the negative).\n */\nfunction collapseMargins(a: number, b: number): number {\n if (a >= 0 && b >= 0) return Math.max(a, b);\n if (a <= 0 && b <= 0) return Math.min(a, b);\n return a + b;\n}\n\nfunction resolveWidth(\n style: CellStyle,\n available: number,\n mode: SizingMode,\n node: LayoutNode,\n cache: IntrinsicCache,\n): number {\n const width = style.width;\n if (width !== undefined && width.kind !== \"auto\")\n return resolveSizeAgainst(width, available, node, cache);\n return mode === \"shrink\" ? Math.min(available, intrinsicOuterWidth(node, cache)) : available;\n}\n\nfunction resolveHeight(style: CellStyle, available: number | undefined): number | undefined {\n if (style.height?.kind === \"cells\") return style.height.value;\n if (style.height?.kind === \"percent\" && available != null)\n return percentToCells(style.height.value, available);\n return undefined;\n}\n\n/** Resolve a definite Size against an available extent (`auto` falls back\n * to max-content — callers handle the auto/fill distinction themselves). */\nexport function resolveSizeAgainst(\n size: Size,\n available: number,\n node: LayoutNode,\n cache: IntrinsicCache,\n): number {\n switch (size.kind) {\n case \"cells\":\n return size.value;\n case \"percent\":\n return percentToCells(size.value, available);\n case \"min-content\":\n return minContentOuterWidth(node, cache);\n case \"max-content\":\n return intrinsicOuterWidth(node, cache);\n case \"fit-content\":\n return Math.min(\n intrinsicOuterWidth(node, cache),\n Math.max(minContentOuterWidth(node, cache), available),\n );\n case \"auto\":\n return intrinsicOuterWidth(node, cache);\n }\n}\n\n/** Max-content intrinsic outer width (border + padding + unwrapped content). */\nexport function intrinsicOuterWidth(node: LayoutNode, cache: IntrinsicCache): number {\n const cached = cache.maxContent.get(node);\n if (cached !== undefined) return cached;\n const style = node.style;\n const inner = intrinsicInnerWidth(node, cache);\n const result =\n inner +\n style.border.left +\n style.border.right +\n intrinsicCells(style.padding.left) +\n intrinsicCells(style.padding.right);\n cache.maxContent.set(node, result);\n return result;\n}\n\nfunction intrinsicInnerWidth(node: LayoutNode, cache: IntrinsicCache): number {\n const inFlow = node.children.filter((c) => !isOutOfFlow(c.style) && !c.inlineBox);\n if (inFlow.length === 0) return node.intrinsicWidth;\n if (node.style.display === \"grid\") return gridIntrinsicInnerWidths(node, cache).max;\n if (node.style.display === \"flex\" && node.style.flexDirection === \"row\") {\n const gap = intrinsicCells(node.style.gapX) * Math.max(0, inFlow.length - 1);\n return inFlow.reduce((sum, c) => sum + intrinsicOuterWidth(c, cache), 0) + gap;\n }\n return inFlow.reduce((max, c) => Math.max(max, intrinsicOuterWidth(c, cache)), 0);\n}\n\n/**\n * Min-content intrinsic outer width: the narrowest the box can get without\n * overflow. For a text leaf that's the longest unbreakable unit — a word\n * under normal wrapping, a whole hard line under `nowrap`. A nowrap flex\n * row sums its items (they sit side by side no matter what); wrapping rows\n * and block/column containers take the widest child.\n */\nexport function minContentOuterWidth(node: LayoutNode, cache: IntrinsicCache): number {\n const cached = cache.minContent.get(node);\n if (cached !== undefined) return cached;\n const style = node.style;\n const inner = minContentInnerWidth(node, cache);\n const result =\n inner +\n style.border.left +\n style.border.right +\n intrinsicCells(style.padding.left) +\n intrinsicCells(style.padding.right);\n cache.minContent.set(node, result);\n return result;\n}\n\nfunction minContentInnerWidth(node: LayoutNode, cache: IntrinsicCache): number {\n const inFlow = node.children.filter((c) => !isOutOfFlow(c.style) && !c.inlineBox);\n if (inFlow.length === 0) {\n if (!node.text || node.style.whiteSpace !== \"normal\") return node.intrinsicWidth;\n return longestSegmentAdvance(node.text, {\n advances: node.advances,\n tracking: node.style.tracking,\n });\n }\n if (node.style.display === \"grid\") return gridIntrinsicInnerWidths(node, cache).min;\n if (\n node.style.display === \"flex\" &&\n node.style.flexDirection === \"row\" &&\n node.style.flexWrap === \"nowrap\"\n ) {\n const gap = intrinsicCells(node.style.gapX) * Math.max(0, inFlow.length - 1);\n return inFlow.reduce((sum, c) => sum + minContentOuterWidth(c, cache), 0) + gap;\n }\n return inFlow.reduce((max, c) => Math.max(max, minContentOuterWidth(c, cache)), 0);\n}\n\nfunction shrinkSize(\n width: number,\n height: number,\n border: Insets,\n padding: Insets,\n): { width: number; height: number } {\n return {\n width: Math.max(0, width - border.left - border.right - padding.left - padding.right),\n height: Math.max(0, height - border.top - border.bottom - padding.top - padding.bottom),\n };\n}\n","import type { BorderStyle, CellStyle, PerSide, Rect } from \"./types.ts\";\n\n/** One run of identical border glyphs, in absolute cell coordinates. */\nexport interface BorderRun {\n glyph: string;\n x: number;\n y: number;\n length: number;\n color: string | undefined;\n}\n\ninterface Glyphs {\n h: string;\n v: string;\n tl: string;\n tr: string;\n bl: string;\n br: string;\n}\n\ninterface RingSides {\n top: boolean;\n right: boolean;\n bottom: boolean;\n left: boolean;\n}\n\n/**\n * Emit runs of border glyphs for the box's engine-allocated border cells.\n *\n * For multi-cell borders (`border-2`, `border-3`, …) the engine allocates N\n * cells per edge; we render them as N concentric rings. Styles and colors\n * are per-side (see paintRing); every ring repeats them.\n *\n * A single-cell-thin box (width < 2 or height < 2) has no interior; we draw\n * only vertical/horizontal runs and skip corners that would overlap.\n */\nexport function collectBorderRuns(style: CellStyle, box: Rect, out: BorderRun[]): void {\n const border = style.border;\n if (border.top === 0 && border.right === 0 && border.bottom === 0 && border.left === 0) return;\n const rings = Math.max(border.top, border.right, border.bottom, border.left);\n for (let ring = 0; ring < rings; ring++) {\n const sides = {\n top: ring < border.top,\n right: ring < border.right,\n bottom: ring < border.bottom,\n left: ring < border.left,\n };\n const ringRect = {\n x: box.x + (sides.left ? ring : 0),\n y: box.y + (sides.top ? ring : 0),\n width: box.width - (sides.left ? ring : 0) - (sides.right ? ring : 0),\n height: box.height - (sides.top ? ring : 0) - (sides.bottom ? ring : 0),\n };\n if (ringRect.width <= 0 || ringRect.height <= 0) continue;\n paintRing(out, style.borderStyle, style.borderColor, ringRect, sides);\n }\n}\n\n/**\n * Paint one ring, honoring per-side styles and colors. Each edge uses its\n * own style's glyphs. A corner where both adjacent edges share a style uses\n * that style's corner glyph; mixed-style corners fall back to the light\n * corners (Unicode has no mixed junction glyphs for most pairs — same\n * convention as dashed/dotted). Corner color comes from the horizontal\n * (top/bottom) edge.\n */\nfunction paintRing(\n out: BorderRun[],\n styles: PerSide<BorderStyle>,\n colors: PerSide<string | undefined>,\n rect: Rect,\n sides: RingSides,\n): void {\n const top = borderGlyphs(styles.top);\n const right = borderGlyphs(styles.right);\n const bottom = borderGlyphs(styles.bottom);\n const left = borderGlyphs(styles.left);\n const corner = (a: BorderStyle, b: BorderStyle, pick: (g: Glyphs) => string): string =>\n a === b ? pick(borderGlyphs(a)) : pick(borderGlyphs(\"solid\"));\n const { x, y, width, height } = rect;\n const hasCorners = width >= 2 && height >= 2;\n const interiorStartX = x + (sides.left ? 1 : 0);\n const interiorEndX = x + width - (sides.right ? 1 : 0);\n const interiorStartY = y + (sides.top ? 1 : 0);\n const interiorEndY = y + height - (sides.bottom ? 1 : 0);\n\n // Horizontal edges\n if (sides.top && interiorEndX > interiorStartX) {\n out.push({\n glyph: top.h,\n x: interiorStartX,\n y,\n length: interiorEndX - interiorStartX,\n color: colors.top,\n });\n }\n if (sides.bottom && height > (sides.top ? 1 : 0) && interiorEndX > interiorStartX) {\n out.push({\n glyph: bottom.h,\n x: interiorStartX,\n y: y + height - 1,\n length: interiorEndX - interiorStartX,\n color: colors.bottom,\n });\n }\n // Vertical edges\n if (sides.left) {\n for (let vy = interiorStartY; vy < interiorEndY; vy++)\n out.push({ glyph: left.v, x, y: vy, length: 1, color: colors.left });\n }\n if (sides.right && width > (sides.left ? 1 : 0)) {\n for (let vy = interiorStartY; vy < interiorEndY; vy++)\n out.push({ glyph: right.v, x: x + width - 1, y: vy, length: 1, color: colors.right });\n }\n // Corners (only when we have interior room to distinguish them)\n if (hasCorners) {\n if (sides.top && sides.left)\n out.push({\n glyph: corner(styles.top, styles.left, (g) => g.tl),\n x,\n y,\n length: 1,\n color: colors.top,\n });\n if (sides.top && sides.right)\n out.push({\n glyph: corner(styles.top, styles.right, (g) => g.tr),\n x: x + width - 1,\n y,\n length: 1,\n color: colors.top,\n });\n if (sides.bottom && sides.left)\n out.push({\n glyph: corner(styles.bottom, styles.left, (g) => g.bl),\n x,\n y: y + height - 1,\n length: 1,\n color: colors.bottom,\n });\n if (sides.bottom && sides.right)\n out.push({\n glyph: corner(styles.bottom, styles.right, (g) => g.br),\n x: x + width - 1,\n y: y + height - 1,\n length: 1,\n color: colors.bottom,\n });\n }\n}\n\nfunction borderGlyphs(style: BorderStyle): Glyphs {\n switch (style) {\n case \"double\":\n return { h: \"═\", v: \"║\", tl: \"╔\", tr: \"╗\", bl: \"╚\", br: \"╝\" };\n // Light double dash pair: two dashes per cell, cleaner than the triple\n // dash `┄`/`┆` which reads as dots in many fonts.\n case \"dashed\":\n return { h: \"╌\", v: \"╎\", tl: \"┌\", tr: \"┐\", bl: \"└\", br: \"┘\" };\n case \"dotted\":\n return { h: \"┄\", v: \"┊\", tl: \"┌\", tr: \"┐\", bl: \"└\", br: \"┘\" };\n default:\n return { h: \"─\", v: \"│\", tl: \"┌\", tr: \"┐\", bl: \"└\", br: \"┘\" };\n }\n}\n","import { collectBorderRuns } from \"./borders.ts\";\nimport type { BorderRun } from \"./borders.ts\";\nimport type { LayoutNode, PerSide } from \"./types.ts\";\n\n/**\n * Write geometry custom properties on each source element and (re)paint the\n * decoration layer. Coordinates on LayoutNode are parent-relative; borders\n * are painted in absolute coordinates so we accumulate the parent origin as\n * we walk.\n */\nexport function render(root: LayoutNode, decorationLayer: HTMLElement): void {\n const borderRuns: BorderRun[] = [];\n const inlineInsetElements = new Set<Element>();\n walk(root, 0, 0, borderRuns, true, inlineInsetElements);\n paintDecorations(decorationLayer, borderRuns);\n // Clear engine-written inset vars from inline elements that no longer\n // carry authored relative insets.\n for (const el of Array.from(root.source.querySelectorAll(\"[data-mw-inline-inset]\"))) {\n if (!inlineInsetElements.has(el)) {\n el.removeAttribute(\"data-mw-inline-inset\");\n const style = (el as HTMLElement).style;\n for (const prop of [\"--mw-it\", \"--mw-ir\", \"--mw-ib\", \"--mw-il\"]) style.removeProperty(prop);\n }\n }\n}\n\nfunction walk(\n node: LayoutNode,\n parentAbsX: number,\n parentAbsY: number,\n borderRuns: BorderRun[],\n isRoot: boolean,\n inlineInsetElements: Set<Element>,\n): void {\n const absX = parentAbsX + node.localRect.x;\n const absY = parentAbsY + node.localRect.y;\n\n if (node.inlineElements) {\n for (const { element, tracking, padLeft, padRight, insets } of node.inlineElements) {\n const el = element as HTMLElement;\n el.style.setProperty(\"--mw-ls\", String(tracking));\n // Quantized horizontal padding (specs/cell-model.md): the companion\n // stylesheet applies these cells as the element's real padding —\n // its typography lock zeroes any authored value, so browser padding\n // always equals the cells the run reserved.\n if (padLeft > 0) el.style.setProperty(\"--mw-ipl\", String(padLeft));\n else el.style.removeProperty(\"--mw-ipl\");\n if (padRight > 0) el.style.setProperty(\"--mw-ipr\", String(padRight));\n else el.style.removeProperty(\"--mw-ipr\");\n if (insets) {\n inlineInsetElements.add(element);\n applyInlineInsets(el, insets);\n }\n }\n }\n\n if (!isRoot) positionElement(node);\n\n collectBorderRuns(\n node.style,\n { x: absX, y: absY, width: node.localRect.width, height: node.localRect.height },\n borderRuns,\n );\n\n for (const child of node.children) {\n walk(child, absX, absY, borderRuns, false, inlineInsetElements);\n }\n}\n\n/**\n * Rewrite an inline element's authored relative insets to whole-cell\n * offsets (specs/positioning.md). The values go into engine-owned custom\n * properties consumed by a `:not([measuring])`-gated companion rule —\n * writing `top` etc. directly would be read back as the authored value on\n * the next measure pass and compound (a feedback loop). Sides the author\n * left `auto` get no var: the companion declaration is then invalid at\n * computed-value time and the inset falls back to `auto`.\n */\nfunction applyInlineInsets(el: HTMLElement, insets: PerSide<number | null>): void {\n el.setAttribute(\"data-mw-inline-inset\", \"\");\n const write = (prop: string, cells: number | null) => {\n if (cells === null) el.style.removeProperty(prop);\n else el.style.setProperty(prop, String(cells));\n };\n write(\"--mw-it\", insets.top);\n write(\"--mw-ir\", insets.right);\n write(\"--mw-ib\", insets.bottom);\n write(\"--mw-il\", insets.left);\n}\n\nfunction positionElement(node: LayoutNode): void {\n const el = node.source as HTMLElement;\n const rect = node.localRect;\n const padding = node.resolvedPadding;\n const { border, textAlignBlocked, overflow, whiteSpace, tracking, lineGap } = node.style;\n // Atomic inline boxes stay IN FLOW (the browser's line layout places\n // them); everything else is engine-positioned. Same geometry vars, a\n // different companion rule (see styles.css).\n el.setAttribute(node.inlineBox ? \"data-mw-inline-box\" : \"data-mw-laid-out\", \"\");\n el.removeAttribute(node.inlineBox ? \"data-mw-laid-out\" : \"data-mw-inline-box\");\n // Grid typography (specs/cell-model.md): extra cells per character, rows\n // per wrapped line, and the half-leading cancellation shift.\n el.style.setProperty(\"--mw-ls\", String(tracking));\n el.style.setProperty(\"--mw-lh\", String(lineGap + 1));\n el.style.setProperty(\"--mw-lhs\", String(-lineGap / 2));\n if (whiteSpace !== \"normal\") el.setAttribute(\"data-mw-nowrap\", \"\");\n else el.removeAttribute(\"data-mw-nowrap\");\n // `white-space: pre` leaves also keep their preserved spaces\n // browser-side (the tree builder kept them in the run) — see styles.css.\n if (whiteSpace === \"pre\") el.setAttribute(\"data-mw-pre\", \"\");\n else el.removeAttribute(\"data-mw-pre\");\n el.style.setProperty(\"--mw-x\", String(rect.x));\n el.style.setProperty(\"--mw-y\", String(rect.y));\n el.style.setProperty(\"--mw-w\", String(rect.width));\n el.style.setProperty(\"--mw-h\", String(rect.height));\n if (overflow === \"clip\") el.setAttribute(\"data-mw-clip\", \"\");\n else el.removeAttribute(\"data-mw-clip\");\n // The browser insets content by border + padding; the engine has already\n // allocated cells for both. We expose them separately so the companion CSS\n // reads naturally, and the CSS sums them into the actual `padding` (since\n // engine border is painted as glyphs, native border-width stays 0).\n el.style.setProperty(\"--mw-pt\", String(padding.top));\n el.style.setProperty(\"--mw-pr\", String(padding.right));\n el.style.setProperty(\"--mw-pb\", String(padding.bottom));\n el.style.setProperty(\"--mw-pl\", String(padding.left));\n el.style.setProperty(\"--mw-bt\", String(border.top));\n el.style.setProperty(\"--mw-br\", String(border.right));\n el.style.setProperty(\"--mw-bb\", String(border.bottom));\n el.style.setProperty(\"--mw-bl\", String(border.left));\n if (textAlignBlocked) el.setAttribute(\"data-mw-text-align-blocked\", \"\");\n else el.removeAttribute(\"data-mw-text-align-blocked\");\n // Un-laid-out direct text (mixed with block children) would otherwise\n // paint unpositioned over the children — hide it (see styles.css).\n if (node.droppedText) el.setAttribute(\"data-mw-dropped-text\", \"\");\n else el.removeAttribute(\"data-mw-dropped-text\");\n}\n\nfunction paintDecorations(layer: HTMLElement, runs: BorderRun[]): void {\n layer.replaceChildren();\n for (const run of runs) {\n // One span PER CELL, not per run: box-drawing glyphs may come from a\n // fallback font with a different advance width than the measured cell\n // (e.g. Google Fonts subsets that omit box-drawing characters), so a\n // multi-glyph run would drift off the grid. Positioning every glyph\n // from the grid keeps borders aligned regardless of which font supplies\n // the glyph. Revisit as a perf optimization once we can detect that the\n // active font covers the glyphs (or when painting to canvas).\n for (let i = 0; i < run.length; i++) {\n const span = document.createElement(\"span\");\n span.setAttribute(\"aria-hidden\", \"true\");\n span.style.position = \"absolute\";\n span.style.left = `calc(${run.x + i} * var(--mw-cw))`;\n span.style.top = `calc(${run.y} * var(--mw-ch))`;\n span.style.font = \"inherit\";\n span.style.lineHeight = \"inherit\";\n span.style.whiteSpace = \"pre\";\n span.style.pointerEvents = \"none\";\n span.style.userSelect = \"none\";\n if (run.color) span.style.color = run.color;\n span.textContent = run.glyph;\n layer.appendChild(span);\n }\n }\n}\n","import { pxToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack } from \"./types.ts\";\nimport type {\n AlignItems,\n BorderStyle,\n CellLength,\n CellMetrics,\n CellStyle,\n Display,\n GridArea,\n GridAreas,\n GridAutoFlow,\n GridLine,\n GridTemplate,\n Insets,\n JustifyContent,\n PerSide,\n Position,\n Size,\n SizeLimit,\n TrackBreadth,\n TrackSize,\n} from \"./types.ts\";\n\n/**\n * Read the interpreted CellStyle for an element from its computed CSS.\n *\n * The host must have the `measuring` attribute set while this runs so the\n * engine's own geometry rules (from styles.css) don't feed their outputs back\n * into what we read.\n *\n * `metrics` (the host's measured cell) is the basis for leading and\n * tracking; absent in headless tests, where the cell height defaults to\n * the font size and the root letter-spacing to 0.\n */\nexport function readCellStyle(\n el: Element,\n rootFontSizePx: number,\n metrics?: CellMetrics,\n): CellStyle {\n const cs = getComputedStyle(el);\n const fontSizePx = parseFloat(cs.fontSize) || rootFontSizePx;\n const csm = supportsTypedOM(el) ? el.computedStyleMap() : null;\n const classAttr = el.getAttribute(\"class\") ?? \"\";\n const inlineStyle = (el as HTMLElement).style;\n\n // Atomic inline-level boxes lay their CONTENT out like their block-level\n // counterparts (the tree builder blockifies the box itself onto its own\n // row — cell-model deviation).\n const rawDisplay = cs.display;\n const display: Display =\n rawDisplay === \"flex\" || rawDisplay === \"inline-flex\"\n ? \"flex\"\n : rawDisplay === \"grid\" || rawDisplay === \"inline-grid\"\n ? \"grid\"\n : rawDisplay === \"none\"\n ? \"none\"\n : \"block\";\n\n // Grid templates: `getComputedStyle` on a live grid container returns\n // the USED track list (expanded, in px) — fr factors, repeat(), and\n // minmax() are gone. Typed OM returns the COMPUTED value with the\n // authored structure intact (verified in Chromium and WebKit), so it's\n // the primary source, as for margins and insets. Without Typed OM\n // (Firefox pre-157), a `data-mw-degrid` attribute (measuring-gated\n // `display: block` rule in styles.css) blockifies the element for the\n // read, which makes getComputedStyle hand back the computed value too.\n // The attribute is not in the engine's MutationObserver filter, so the\n // write doesn't re-trigger layout.\n let gridTemplateColumns: GridTemplate = { kind: \"none\" };\n let gridTemplateRows: GridTemplate = { kind: \"none\" };\n let gridAutoColumns: TrackSize[] = [autoTrack()];\n let gridAutoRows: TrackSize[] = [autoTrack()];\n let gridAutoFlow: GridAutoFlow = { direction: \"row\", dense: false };\n let gridTemplateAreas: GridAreas | null = null;\n if (display === \"grid\") {\n if (csm) {\n gridTemplateColumns = parseTrackTemplate(\n csm.get(\"grid-template-columns\")?.toString() ?? \"\",\n rootFontSizePx,\n );\n gridTemplateRows = parseTrackTemplate(\n csm.get(\"grid-template-rows\")?.toString() ?? \"\",\n rootFontSizePx,\n );\n } else {\n el.setAttribute(\"data-mw-degrid\", \"\");\n try {\n gridTemplateColumns = parseTrackTemplate(\n cs.getPropertyValue(\"grid-template-columns\"),\n rootFontSizePx,\n );\n gridTemplateRows = parseTrackTemplate(\n cs.getPropertyValue(\"grid-template-rows\"),\n rootFontSizePx,\n );\n } finally {\n el.removeAttribute(\"data-mw-degrid\");\n }\n }\n // No used-value trap for these: their computed values keep the\n // authored form on grid containers too.\n gridAutoColumns = parseAutoTracks(cs.getPropertyValue(\"grid-auto-columns\"), rootFontSizePx);\n gridAutoRows = parseAutoTracks(cs.getPropertyValue(\"grid-auto-rows\"), rootFontSizePx);\n gridAutoFlow = parseGridAutoFlow(cs.getPropertyValue(\"grid-auto-flow\"));\n gridTemplateAreas = parseGridTemplateAreas(cs.getPropertyValue(\"grid-template-areas\"));\n }\n\n return {\n display,\n flexDirection: cs.flexDirection.startsWith(\"column\") ? \"column\" : \"row\",\n flexReverse: cs.flexDirection.endsWith(\"-reverse\"),\n flexWrap: cs.flexWrap.startsWith(\"wrap\") ? \"wrap\" : \"nowrap\",\n wrapReverse: cs.flexWrap === \"wrap-reverse\",\n flexGrow: Number(cs.flexGrow) || 0,\n flexShrink: cs.flexShrink === \"\" ? 1 : Number(cs.flexShrink) || 0,\n // flex-basis keeps its computed form (percentages stay symbolic), so\n // plain getComputedStyle is reliable here — `flex-1` reads as \"0%\".\n flexBasis: readFlexBasis(cs.flexBasis, rootFontSizePx),\n order: Number(cs.order) || 0,\n justifyContent: mapJustify(cs.justifyContent),\n alignContent: mapJustify(cs.alignContent),\n alignItems: mapAlign(cs.alignItems),\n alignSelf: mapAlignSelf(cs.alignSelf),\n justifyItems: mapAlign(cs.justifyItems),\n justifySelf: mapAlignSelf(cs.justifySelf),\n gridTemplateColumns,\n gridTemplateRows,\n gridAutoColumns,\n gridAutoRows,\n gridAutoFlow,\n gridTemplateAreas,\n // Placement longhands have no used-value trap (computed = as\n // specified) and cost four cheap reads, so they're read on every\n // element — items don't know their parent's display here.\n gridColumnStart: parseGridLine(cs.getPropertyValue(\"grid-column-start\")),\n gridColumnEnd: parseGridLine(cs.getPropertyValue(\"grid-column-end\")),\n gridRowStart: parseGridLine(cs.getPropertyValue(\"grid-row-start\")),\n gridRowEnd: parseGridLine(cs.getPropertyValue(\"grid-row-end\")),\n width: readSize(csm, cs.width, \"width\", rootFontSizePx, classAttr, inlineStyle),\n height: readSize(csm, cs.height, \"height\", rootFontSizePx, classAttr, inlineStyle),\n minWidth: readLimit(cs.minWidth, rootFontSizePx) ?? \"auto\",\n minHeight: readLimit(cs.minHeight, rootFontSizePx) ?? \"auto\",\n maxWidth: readLimit(cs.maxWidth, rootFontSizePx),\n maxHeight: readLimit(cs.maxHeight, rootFontSizePx),\n padding: readPadding(cs, rootFontSizePx),\n margin: readMargin(cs, csm, classAttr, rootFontSizePx),\n position: readPosition(cs.position),\n insets: readInsets(cs, csm, classAttr, inlineStyle, rootFontSizePx),\n gapX: readSpacing(cs.columnGap === \"normal\" ? \"0px\" : cs.columnGap, rootFontSizePx),\n gapY: readSpacing(cs.rowGap === \"normal\" ? \"0px\" : cs.rowGap, rootFontSizePx),\n border: readBorderInsets(cs),\n borderStyle: {\n top: mapBorderStyle(cs.borderTopStyle),\n right: mapBorderStyle(cs.borderRightStyle),\n bottom: mapBorderStyle(cs.borderBottomStyle),\n left: mapBorderStyle(cs.borderLeftStyle),\n },\n // Treat `hidden` and `clip` the same — both keep content inside the\n // box. Normalized to `clip` internally since that's the more precise\n // semantic for what we do (no scroll container, cheaper). Longhands\n // (`overflow-x`/`overflow-y`) are honored: setting just one axis to\n // hidden or clip still marks the element as clipping. `auto` and\n // `scroll` are left as \"visible\" here — real scrolling is deferred to\n // the scrolling milestone.\n overflow:\n isClipping(cs.overflow) || isClipping(cs.overflowX) || isClipping(cs.overflowY)\n ? \"clip\"\n : \"visible\",\n // `nowrap` and `pre` disable soft wrapping; `pre` additionally makes\n // the tree builder preserve the source's spaces and newlines\n // (specs/cell-model.md). Readable via getComputedStyle because the\n // companion stylesheet's white-space lock is gated on `:not([measuring])`.\n whiteSpace: cs.whiteSpace === \"pre\" ? \"pre\" : cs.whiteSpace === \"nowrap\" ? \"nowrap\" : \"normal\",\n tabSize: Math.max(1, Math.floor(parseFloat(cs.tabSize)) || 8),\n // Both readable because the companion stylesheet's typography rewrite\n // is gated on `:not([measuring])`.\n lineGap: lineGapRows(cs.lineHeight, metrics?.height ?? fontSizePx),\n tracking: trackingCells(cs.letterSpacing, fontSizePx, metrics?.letterSpacing ?? 0),\n textOverflow: cs.textOverflow === \"ellipsis\" ? \"ellipsis\" : \"clip\",\n color: cs.color,\n backgroundColor: cs.backgroundColor === \"rgba(0, 0, 0, 0)\" ? undefined : cs.backgroundColor,\n borderColor: {\n top: cs.borderTopColor,\n right: cs.borderRightColor,\n bottom: cs.borderBottomColor,\n left: cs.borderLeftColor,\n },\n // Detect authored text-align via class + inline style rather than\n // getComputedStyle, since our own override would otherwise be echoed\n // back and cause oscillation. Inheritance is handled by CSS: forcing\n // `text-align: start` on the element that authors center/justify\n // cascades to its descendants automatically.\n textAlignBlocked: authoredTextAlignBlocked(classAttr, inlineStyle),\n };\n}\n\nfunction isClipping(value: string): boolean {\n return value === \"hidden\" || value === \"clip\";\n}\n\nfunction authoredTextAlignBlocked(classAttr: string, inlineStyle: CSSStyleDeclaration): boolean {\n if (/(?:^|[\\s:.[!])text-(?:center|justify)/.test(classAttr)) return true;\n const inline = inlineStyle.textAlign;\n return inline === \"center\" || inline === \"justify\";\n}\n\nfunction supportsTypedOM(\n el: Element,\n): el is Element & { computedStyleMap(): StylePropertyMapReadOnly } {\n return typeof (el as { computedStyleMap?: unknown }).computedStyleMap === \"function\";\n}\n\n/** `normal` (the initial value) and `stretch` both read as `stretch`: flex\n * treats it as `start` (per css-align), grid stretches auto tracks. */\nfunction mapJustify(value: string): JustifyContent {\n switch (value) {\n case \"center\":\n return \"center\";\n case \"flex-end\":\n case \"end\":\n case \"right\":\n return \"end\";\n case \"space-between\":\n return \"space-between\";\n case \"space-around\":\n return \"space-around\";\n case \"space-evenly\":\n return \"space-evenly\";\n case \"normal\":\n case \"stretch\":\n case \"\":\n return \"stretch\";\n default:\n return \"start\";\n }\n}\n\nfunction mapAlign(value: string): AlignItems {\n switch (value) {\n case \"center\":\n return \"center\";\n case \"flex-end\":\n case \"end\":\n return \"end\";\n case \"stretch\":\n // CSS default for align-items on a flex container is \"normal\", which\n // behaves as \"stretch\" in flex/grid contexts.\n case \"normal\":\n case \"\":\n return \"stretch\";\n default:\n return \"start\";\n }\n}\n\nfunction mapAlignSelf(value: string): \"auto\" | AlignItems {\n if (value === \"auto\" || value === \"\" || value === \"normal\") return \"auto\";\n return mapAlign(value);\n}\n\n/**\n * Read margins, preserving `auto` as `null`.\n *\n * `getComputedStyle` returns *used* values for margins on flex items, which\n * means an authored `auto` has already been resolved to a pixel length by\n * the browser's own flex pass — we can't tell \"auto\" from a fixed number\n * anymore. Typed OM returns *computed* values, so \"auto\" survives; we use it\n * as the source of truth when available.\n *\n * On engines without Typed OM (Firefox pre-157), fall back to scanning the\n * class attribute for Tailwind auto-margin utilities. LTR only for now.\n */\nfunction readMargin(\n cs: CSSStyleDeclaration,\n csm: StylePropertyMapReadOnly | null,\n classAttr: string,\n rootFontSizePx: number,\n): PerSide<CellLength | null> {\n const readSide = (\n physical: string,\n logical: string,\n autoClassPattern: RegExp,\n ): CellLength | null => {\n if (csm) {\n const physicalValue = csm.get(physical)?.toString().trim();\n if (physicalValue === \"auto\") return null;\n const logicalValue = csm.get(logical)?.toString().trim();\n if (logicalValue === \"auto\") return null;\n // Percent margins must stay symbolic (getComputedStyle would hand\n // back a used px value resolved against the pre-grid natural layout).\n if (physicalValue?.endsWith(\"%\")) {\n const percent = parseFloat(physicalValue);\n if (Number.isFinite(percent) && percent !== 0) return { percent };\n }\n } else if (autoClassPattern.test(classAttr)) {\n return null;\n }\n const physicalValue = cs.getPropertyValue(physical);\n if (physicalValue === \"auto\") return null;\n const physicalCells = readSpacing(physicalValue, rootFontSizePx);\n if (physicalCells !== 0) return physicalCells;\n const logicalValue = cs.getPropertyValue(logical);\n if (logicalValue === \"auto\") return null;\n return readSpacing(logicalValue, rootFontSizePx);\n };\n return {\n top: readSide(\"margin-top\", \"margin-block-start\", /(?:^|[\\s:.[!])(?:m|my|mt)-auto\\b/),\n right: readSide(\"margin-right\", \"margin-inline-end\", /(?:^|[\\s:.[!])(?:m|mx|mr|me)-auto\\b/),\n bottom: readSide(\"margin-bottom\", \"margin-block-end\", /(?:^|[\\s:.[!])(?:m|my|mb)-auto\\b/),\n left: readSide(\"margin-left\", \"margin-inline-start\", /(?:^|[\\s:.[!])(?:m|mx|ml|ms)-auto\\b/),\n };\n}\n\n/** Extra cells after each character: floor((letter-spacing − root\n * letter-spacing) ÷ 0.025em), never negative (specs/cell-model.md). The\n * root's own letter-spacing is part of the cell, so only the excess over\n * it (inherited by default) counts. */\nexport function trackingCells(\n letterSpacing: string,\n fontSizePx: number,\n rootLetterSpacingPx: number,\n): number {\n const px =\n (letterSpacing === \"normal\" ? 0 : parseFloat(letterSpacing) || 0) - rootLetterSpacingPx;\n if (px <= 0) return 0;\n return Math.floor(px / (0.025 * fontSizePx) + 1e-6);\n}\n\n/** Empty rows between wrapped lines: floor(line-height ÷ cell height) − 1,\n * never negative. Computed line-height is always px (or `normal`). */\nfunction lineGapRows(lineHeight: string, cellHeightPx: number): number {\n if (!lineHeight || lineHeight === \"normal\" || cellHeightPx <= 0) return 0;\n const px = parseFloat(lineHeight);\n if (!Number.isFinite(px)) return 0;\n return Math.max(0, Math.floor(px / cellHeightPx + 1e-6) - 1);\n}\n\nfunction readPosition(value: string): Position {\n switch (value) {\n case \"relative\":\n case \"absolute\":\n case \"fixed\":\n case \"sticky\":\n return value;\n default:\n return \"static\";\n }\n}\n\n/**\n * Read insets, preserving `auto` as `null`.\n *\n * Same trap as margins: on POSITIONED elements, `getComputedStyle` returns\n * *used* values for top/right/bottom/left — an `auto` side comes back as a\n * resolved distance, indistinguishable from an authored inset (which would\n * e.g. wrongly trigger the absolute stretch branch). Typed OM returns\n * *computed* values, so `auto` survives. The no-Typed-OM fallback trusts a\n * side only when an inline style or a Tailwind inset utility for it is\n * authored (then the used value equals the authored one). LTR only.\n */\nfunction readInsets(\n cs: CSSStyleDeclaration,\n csm: StylePropertyMapReadOnly | null,\n classAttr: string,\n inlineStyle: CSSStyleDeclaration,\n rootFontSizePx: number,\n): PerSide<CellLength | null> {\n const side = (\n prop: \"top\" | \"right\" | \"bottom\" | \"left\",\n utilityPattern: RegExp,\n ): CellLength | null => {\n if (csm) {\n const value = csm.get(prop)?.toString().trim();\n if (!value || value === \"auto\") return null;\n return readSpacing(value, rootFontSizePx);\n }\n const inline = inlineStyle[prop];\n if (inline) return inline === \"auto\" ? null : readSpacing(inline, rootFontSizePx);\n if (!utilityPattern.test(classAttr)) return null;\n const value = cs.getPropertyValue(prop);\n return !value || value === \"auto\" ? null : readSpacing(value, rootFontSizePx);\n };\n return {\n top: side(\"top\", /(?:^|[\\s:.[!])-?(?:top|inset|inset-y)-/),\n right: side(\"right\", /(?:^|[\\s:.[!])-?(?:right|end|inset|inset-x)-/),\n bottom: side(\"bottom\", /(?:^|[\\s:.[!])-?(?:bottom|inset|inset-y)-/),\n left: side(\"left\", /(?:^|[\\s:.[!])-?(?:left|start|inset|inset-x)-/),\n };\n}\n\nfunction mapBorderStyle(value: string): BorderStyle {\n switch (value) {\n case \"double\":\n return \"double\";\n case \"dashed\":\n return \"dashed\";\n case \"dotted\":\n return \"dotted\";\n default:\n return \"solid\";\n }\n}\n\n/**\n * Read a min/max constraint. Percentages must be kept symbolic (they resolve\n * against the parent's content box during layout) — naive px parsing would\n * read `\"100%\"` as 100px and produce a nonsense cell count.\n */\nfunction readLimit(value: string, rootFontSizePx: number): SizeLimit | undefined {\n if (!value || value === \"none\" || value === \"auto\") return undefined;\n if (value === \"min-content\" || value === \"max-content\" || value === \"fit-content\") return value;\n if (value.endsWith(\"%\")) {\n const percent = parseFloat(value);\n return Number.isFinite(percent) ? { percent } : undefined;\n }\n const px = parseFloat(value);\n return Number.isFinite(px) ? pxToCells(px, rootFontSizePx) : undefined;\n}\n\n/**\n * Read a spacing length. Percentages stay symbolic — they resolve against\n * the containing block's width during layout (getComputedStyle would give\n * a used px value based on the pre-grid natural layout, which is wrong).\n */\nfunction readSpacing(value: string, rootFontSizePx: number): CellLength {\n if (!value || value === \"auto\" || value === \"none\") return 0;\n if (value.endsWith(\"%\")) {\n const percent = parseFloat(value);\n return Number.isFinite(percent) && percent !== 0 ? { percent } : 0;\n }\n const px = parseFloat(value);\n return Number.isFinite(px) ? pxToCells(px, rootFontSizePx) : 0;\n}\n\nfunction readSize(\n csm: StylePropertyMapReadOnly | null,\n fallback: string,\n key: \"width\" | \"height\",\n rootFontSizePx: number,\n classAttr: string,\n inlineStyle: CSSStyleDeclaration,\n): Size | undefined {\n if (csm) {\n const value = csm.get(key);\n if (value == null) return undefined;\n const s = value.toString().trim();\n if (s === \"auto\") return { kind: \"auto\" };\n const intrinsic = intrinsicSizeKeyword(s);\n if (intrinsic) return intrinsic;\n if (s.endsWith(\"%\")) return { kind: \"percent\", value: parseFloat(s) };\n if (s.endsWith(\"px\")) return { kind: \"cells\", value: pxToCells(parseFloat(s), rootFontSizePx) };\n if (s.endsWith(\"rem\"))\n return { kind: \"cells\", value: roundHalfAwayFromZero(parseFloat(s) / 0.25) };\n }\n // Fallback path (Firefox pre-157: no Typed OM). getComputedStyle returns\n // *used* values (always px) for box properties, so we can't distinguish\n // \"authored w-N\" from \"natural content width\". Look at what was authored:\n // inline styles first, then any Tailwind sizing utility in the class list.\n // If neither is present, treat as auto so intrinsic sizing kicks in.\n const inline = key === \"width\" ? inlineStyle.width : inlineStyle.height;\n if (inline) {\n if (inline === \"auto\") return { kind: \"auto\" };\n const intrinsic = intrinsicSizeKeyword(inline);\n if (intrinsic) return intrinsic;\n if (inline.endsWith(\"%\")) return { kind: \"percent\", value: parseFloat(inline) };\n const px = parseFloat(inline);\n if (Number.isFinite(px)) return { kind: \"cells\", value: pxToCells(px, rootFontSizePx) };\n }\n // Intrinsic-keyword utilities (`w-min`…) must be caught by class scan here:\n // getComputedStyle would hand back the browser's *used* px width, which is\n // measured content px — NOT on the spacing scale — and would convert to a\n // nonsense cell count.\n const axis = key === \"width\" ? \"w\" : \"h\";\n if (new RegExp(`(?:^|[\\\\s:.[!])${axis}-min\\\\b`).test(classAttr)) return { kind: \"min-content\" };\n if (new RegExp(`(?:^|[\\\\s:.[!])${axis}-max\\\\b`).test(classAttr)) return { kind: \"max-content\" };\n if (new RegExp(`(?:^|[\\\\s:.[!])${axis}-fit\\\\b`).test(classAttr)) return { kind: \"fit-content\" };\n if (!hasSizingUtility(classAttr, axis)) return { kind: \"auto\" };\n if (fallback === \"auto\") return { kind: \"auto\" };\n if (fallback.endsWith(\"%\")) return { kind: \"percent\", value: parseFloat(fallback) };\n const px = parseFloat(fallback);\n if (Number.isFinite(px)) return { kind: \"cells\", value: pxToCells(px, rootFontSizePx) };\n return undefined;\n}\n\n/**\n * CSS `flex-basis`. `auto` (and the unsupported `content`) → undefined, so\n * the layout falls back to the width-or-intrinsic base. `0%` (Tailwind\n * `flex-1`) must survive as an actual zero base.\n */\nfunction readFlexBasis(value: string, rootFontSizePx: number): Size | undefined {\n if (!value || value === \"auto\" || value === \"content\") return undefined;\n const keyword = intrinsicSizeKeyword(value);\n if (keyword) return keyword;\n if (value.endsWith(\"%\")) {\n const percent = parseFloat(value);\n return Number.isFinite(percent) ? { kind: \"percent\", value: percent } : undefined;\n }\n const px = parseFloat(value);\n return Number.isFinite(px) ? { kind: \"cells\", value: pxToCells(px, rootFontSizePx) } : undefined;\n}\n\nfunction intrinsicSizeKeyword(value: string): Size | undefined {\n if (value === \"min-content\") return { kind: \"min-content\" };\n if (value === \"max-content\") return { kind: \"max-content\" };\n if (value === \"fit-content\") return { kind: \"fit-content\" };\n return undefined;\n}\n\n/**\n * Parse a computed `grid-template-columns` / `grid-template-rows` value\n * (specs/grid.md). Expected on a NON-grid element (see the degrid read in\n * readCellStyle), so the authored structure survives: lengths are computed\n * to px, but `fr`, `minmax()`, and `repeat()` keep their form. Fixed\n * repeats expand here; `auto-fill` / `auto-fit` stay symbolic for layout.\n * Line names would appear in `[bracket]` groups — deferred, dropped.\n */\nexport function parseTrackTemplate(value: string, rootFontSizePx: number): GridTemplate {\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"none\") return { kind: \"none\" };\n if (trimmed === \"subgrid\" || trimmed.startsWith(\"subgrid \")) return { kind: \"subgrid\" };\n const tracks: TrackSize[] = [];\n const lineNames: string[][] = [];\n // Names collected for the line BEFORE the next track (or the trailing\n // line); a `repeat()`'s edge groups merge into it, per CSS.\n let pending: string[] = [];\n const pushTrack = (track: TrackSize) => {\n lineNames.push(pending);\n pending = [];\n tracks.push(track);\n };\n let autoRepeat: NonNullable<Extract<GridTemplate, { kind: \"tracks\" }>[\"autoRepeat\"]> | undefined;\n for (const token of splitTopLevel(trimmed)) {\n const names = parseLineNames(token);\n if (names) {\n pending.push(...names);\n continue;\n }\n const repeat = token.match(/^repeat\\(\\s*([^,]+?)\\s*,(.*)\\)$/s);\n if (repeat) {\n const inner = parseTrackList(repeat[2]!.trim(), rootFontSizePx);\n if (inner.tracks.length === 0) continue;\n const count = repeat[1]!;\n if (count === \"auto-fill\" || count === \"auto-fit\") {\n // Per CSS only one auto-repeat is allowed; a second is ignored.\n if (!autoRepeat) {\n autoRepeat = { index: tracks.length, tracks: inner.tracks, mode: count };\n if (inner.lineNames.some((n) => n.length > 0)) autoRepeat.lineNames = inner.lineNames;\n if (pending.length > 0) autoRepeat.leadingNames = pending;\n pending = [];\n }\n continue;\n }\n const n = Math.max(0, Math.floor(Number(count) || 0));\n for (let i = 0; i < n; i++) {\n pending.push(...inner.lineNames[0]!);\n for (let j = 0; j < inner.tracks.length; j++) {\n pushTrack(inner.tracks[j]!);\n pending.push(...inner.lineNames[j + 1]!);\n }\n }\n continue;\n }\n pushTrack(parseTrackSize(token, rootFontSizePx));\n }\n lineNames.push(pending);\n if (tracks.length === 0 && !autoRepeat) return { kind: \"none\" };\n const template: Extract<GridTemplate, { kind: \"tracks\" }> = { kind: \"tracks\", tracks };\n if (lineNames.some((n) => n.length > 0)) template.lineNames = lineNames;\n if (autoRepeat) template.autoRepeat = autoRepeat;\n return template;\n}\n\n/** A plain track list (no `repeat()`): tracks plus the line names around\n * them — `lineNames` has one entry per line, tracks.length + 1. */\nfunction parseTrackList(\n value: string,\n rootFontSizePx: number,\n): { tracks: TrackSize[]; lineNames: string[][] } {\n const tracks: TrackSize[] = [];\n const lineNames: string[][] = [];\n let pending: string[] = [];\n for (const token of splitTopLevel(value)) {\n const names = parseLineNames(token);\n if (names) {\n pending.push(...names);\n continue;\n }\n lineNames.push(pending);\n pending = [];\n tracks.push(parseTrackSize(token, rootFontSizePx));\n }\n lineNames.push(pending);\n return { tracks, lineNames };\n}\n\n/** `[name other-name]` → the names; null for any other token. */\nfunction parseLineNames(token: string): string[] | null {\n const group = token.match(/^\\[(.*)\\]$/s);\n if (!group) return null;\n return group[1]!.split(/\\s+/).filter((name) => name !== \"\");\n}\n\n/**\n * Parse `grid-template-areas` (specs/grid.md): one quoted string per row,\n * whitespace-separated cell tokens, `.` (any run of dots) for an empty\n * cell. Per CSS the whole value is invalid — and reads as `none` — when\n * rows have different lengths or a name's cells don't form one\n * filled-in rectangle.\n */\nexport function parseGridTemplateAreas(value: string): GridAreas | null {\n const rows: string[][] = [];\n for (const match of value.matchAll(/\"([^\"]*)\"|'([^']*)'/g)) {\n const cells = (match[1] ?? match[2] ?? \"\")\n .trim()\n .split(/\\s+/)\n .filter((c) => c !== \"\");\n if (cells.length === 0) return null;\n rows.push(cells);\n }\n if (rows.length === 0) return null;\n const columns = rows[0]!.length;\n if (rows.some((row) => row.length !== columns)) return null;\n const areas = new Map<string, GridArea>();\n rows.forEach((row, r) => {\n row.forEach((cell, c) => {\n if (/^\\.+$/.test(cell)) return;\n const area = areas.get(cell);\n if (!area) areas.set(cell, { colStart: c, colEnd: c + 1, rowStart: r, rowEnd: r + 1 });\n else {\n area.colStart = Math.min(area.colStart, c);\n area.colEnd = Math.max(area.colEnd, c + 1);\n area.rowStart = Math.min(area.rowStart, r);\n area.rowEnd = Math.max(area.rowEnd, r + 1);\n }\n });\n });\n // Rectangular check: every cell inside a name's bounding box carries it.\n for (const [name, area] of areas) {\n for (let r = area.rowStart; r < area.rowEnd; r++) {\n for (let c = area.colStart; c < area.colEnd; c++) {\n if (rows[r]![c] !== name) return null;\n }\n }\n }\n return { columns, rows: rows.length, areas };\n}\n\n/** Parse `grid-auto-columns` / `grid-auto-rows`: a track-size list, cycled\n * across implicit tracks. Falls back to a single `auto`. */\nfunction parseAutoTracks(value: string, rootFontSizePx: number): TrackSize[] {\n const tracks = splitTopLevel(value.trim())\n .filter((t) => t !== \"\" && !t.startsWith(\"[\"))\n .map((t) => parseTrackSize(t, rootFontSizePx));\n return tracks.length > 0 ? tracks : [autoTrack()];\n}\n\n/** Normalize one track size to a minmax pair: `<n>fr` → minmax(auto, fr)\n * per CSS; a fixed/intrinsic breadth b → minmax(b, b). `fit-content()` is\n * deferred (specs/grid.md deviations) and reads as `auto`. */\nfunction parseTrackSize(token: string, rootFontSizePx: number): TrackSize {\n const minmax = token.match(/^minmax\\((.*)\\)$/s);\n if (minmax) {\n // Depth-aware argument split — a nested function (`minmax(min(8rem,\n // 100%), 1fr)`) has commas of its own.\n const args = splitTopLevelCommas(minmax[1]!).map((arg) => arg.trim());\n if (args.length === 2) {\n return {\n min: parseTrackBreadth(args[0]!, rootFontSizePx),\n max: parseTrackBreadth(args[1]!, rootFontSizePx),\n };\n }\n return { min: { kind: \"auto\" }, max: { kind: \"auto\" } };\n }\n const breadth = parseTrackBreadth(token, rootFontSizePx);\n if (breadth.kind === \"fr\") return { min: { kind: \"auto\" }, max: breadth };\n return { min: breadth, max: breadth };\n}\n\nfunction parseTrackBreadth(token: string, rootFontSizePx: number): TrackBreadth {\n if (token === \"auto\" || token.startsWith(\"fit-content\")) return { kind: \"auto\" };\n if (token === \"min-content\") return { kind: \"min-content\" };\n if (token === \"max-content\") return { kind: \"max-content\" };\n // min()/max() over fixed breadths stay symbolic (percent arguments\n // resolve against the axis at layout time). Anything unresolvable —\n // calc() arithmetic included — degrades to `auto` (specs/grid.md\n // deviations).\n const math = token.match(/^(min|max)\\((.*)\\)$/s);\n if (math) {\n const args = splitTopLevelCommas(math[2]!).map((arg) =>\n parseTrackBreadth(arg.trim(), rootFontSizePx),\n );\n const fixed = args.every(\n (a) => a.kind === \"cells\" || a.kind === \"percent\" || a.kind === \"math\",\n );\n if (args.length > 0 && fixed) {\n return { kind: \"math\", fn: math[1] as \"min\" | \"max\", args };\n }\n return { kind: \"auto\" };\n }\n if (token.endsWith(\"fr\")) {\n const value = parseFloat(token);\n return Number.isFinite(value) && value >= 0 ? { kind: \"fr\", value } : { kind: \"auto\" };\n }\n if (token.endsWith(\"%\")) {\n const percent = parseFloat(token);\n return Number.isFinite(percent) ? { kind: \"percent\", value: percent } : { kind: \"auto\" };\n }\n const px = parseFloat(token);\n if (!Number.isFinite(px)) return { kind: \"auto\" };\n const cells = token.endsWith(\"rem\")\n ? roundHalfAwayFromZero(px / 0.25)\n : pxToCells(px, rootFontSizePx);\n return { kind: \"cells\", value: cells };\n}\n\n/** Split a CSS function's arguments on top-level commas (nested parens\n * stay intact). */\nfunction splitTopLevelCommas(value: string): string[] {\n const args: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < value.length; i++) {\n const ch = value[i]!;\n if (ch === \"(\") depth++;\n else if (ch === \")\") depth--;\n else if (ch === \",\" && depth === 0) {\n args.push(value.slice(start, i));\n start = i + 1;\n }\n }\n args.push(value.slice(start));\n return args.filter((a) => a.trim() !== \"\");\n}\n\n/** Split a CSS value list on top-level whitespace (nested parens and\n * brackets stay intact). */\nfunction splitTopLevel(value: string): string[] {\n const tokens: string[] = [];\n let depth = 0;\n let start = -1;\n for (let i = 0; i < value.length; i++) {\n const ch = value[i]!;\n if (ch === \"(\" || ch === \"[\") depth++;\n else if (ch === \")\" || ch === \"]\") depth--;\n if (/\\s/.test(ch) && depth === 0) {\n if (start !== -1) tokens.push(value.slice(start, i));\n start = -1;\n } else if (start === -1) {\n start = i;\n }\n }\n if (start !== -1) tokens.push(value.slice(start));\n return tokens;\n}\n\n/** Parse a `grid-column-start`-family longhand: `auto`, an integer line\n * (possibly negative), `span <n>`, or the named forms — `foo`, `<n> foo`,\n * `span foo`, `span <n> foo` (specs/grid.md \"Named lines and areas\"). */\nexport function parseGridLine(value: string): GridLine {\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"auto\") return { kind: \"auto\" };\n // `span`, an integer, and a custom-ident, in any order (browsers\n // serialize `span 2 foo`; the grammar allows every order).\n let span = false;\n let integer: number | undefined;\n let name: string | undefined;\n for (const token of trimmed.split(/\\s+/)) {\n if (token === \"span\") span = true;\n else if (/^-?\\d+$/.test(token)) integer = Number(token);\n else name = token;\n }\n if (span) {\n const count = integer ?? 1;\n if (count < 1) return { kind: \"auto\" };\n return name === undefined\n ? { kind: \"span\", value: count }\n : { kind: \"span\", value: count, name };\n }\n if (name !== undefined) {\n if (integer === 0) return { kind: \"auto\" };\n return integer === undefined ? { kind: \"name\", name } : { kind: \"name\", name, nth: integer };\n }\n if (integer !== undefined && integer !== 0) return { kind: \"line\", value: integer };\n return { kind: \"auto\" };\n}\n\nfunction parseGridAutoFlow(value: string): GridAutoFlow {\n return {\n direction: value.includes(\"column\") ? \"column\" : \"row\",\n dense: value.includes(\"dense\"),\n };\n}\n\n/**\n * Detect whether an element has an authored `width` / `height` utility (not\n * `min-*` or `max-*`, which set separate properties). Handles variants\n * (`md:w-full`, `hover:w-0`) and arbitrary variant selectors (`[&_span]:w-2`).\n * Used only when Typed OM is unavailable.\n */\nfunction hasSizingUtility(classAttr: string, axis: \"w\" | \"h\"): boolean {\n const pattern = axis === \"w\" ? /(?:^|[\\s:.[!])w-/ : /(?:^|[\\s:.[!])h-/;\n return pattern.test(classAttr);\n}\n\nfunction readPadding(cs: CSSStyleDeclaration, rootFontSizePx: number): PerSide<CellLength> {\n return {\n top: readSpacing(cs.getPropertyValue(\"padding-top\"), rootFontSizePx),\n right: readSpacing(cs.getPropertyValue(\"padding-right\"), rootFontSizePx),\n bottom: readSpacing(cs.getPropertyValue(\"padding-bottom\"), rootFontSizePx),\n left: readSpacing(cs.getPropertyValue(\"padding-left\"), rootFontSizePx),\n };\n}\n\n/** Border widths use the 1px = 1 cell scale (not the spacing scale). */\nfunction readBorderInsets(cs: CSSStyleDeclaration): Insets {\n const readSide = (side: string, style: string) => {\n if (cs.getPropertyValue(style) === \"none\") return 0;\n return roundHalfAwayFromZero(parseFloat(cs.getPropertyValue(side)) || 0);\n };\n return {\n top: readSide(\"border-top-width\", \"border-top-style\"),\n right: readSide(\"border-right-width\", \"border-right-style\"),\n bottom: readSide(\"border-bottom-width\", \"border-bottom-style\"),\n left: readSide(\"border-left-width\", \"border-left-style\"),\n };\n}\n","import { intrinsicOuterWidth, makeIntrinsicCache } from \"./layout.ts\";\nimport { pxToCells } from \"./metrics.ts\";\nimport { readCellStyle, trackingCells } from \"./style.ts\";\nimport { zeroInsets } from \"./types.ts\";\nimport { eachObjectMarker, INLINE_PAD, lineAdvance, OBJECT_REPLACEMENT } from \"./wrap.ts\";\nimport type { CellMetrics, LayoutNode, PerSide } from \"./types.ts\";\n\n/**\n * Build a LayoutNode tree from an element subtree.\n *\n * Rules (specs/cell-model.md \"Inline detection\"):\n * - Elements with computed `display: none` are skipped entirely (their\n * text never joins a run).\n * - An element is a **leaf** when it has no IN-FLOW block-level element\n * children: in-flow inline children (computed `inline`/`inline-*`/\n * `contents`) are part of the text run, and out-of-flow children\n * (absolute/fixed — blockified per CSS) hang off the leaf as layout\n * nodes for the positioning pass. The leaf's `text` is its combined\n * in-flow text, so text nodes interleaved with inline elements\n * (`<div>hello <span>world</span></div>`) participate in the wrap\n * calculation and render correctly.\n * - Elements with at least one in-flow block-level element child become\n * **containers** and recurse. Direct text nodes on containers (uncommon\n * in utility-first markup) are not laid out — a documented deviation.\n *\n * `cellMetrics` (measured by the host) is the basis for leading and\n * tracking; absent in headless tests (see readCellStyle).\n */\nexport function buildTree(\n root: Element,\n rootFontSizePx: number,\n cellMetrics?: CellMetrics,\n): LayoutNode | null {\n const style = readCellStyle(root, rootFontSizePx, cellMetrics);\n if (style.display === \"none\") return null;\n\n const elementChildren = Array.from(root.children);\n const roles = elementChildren.map(childRole);\n\n if (!roles.includes(\"block\")) {\n // Leaf: in-flow inline content forms the text run (atomic inline\n // boxes ride it as U+FFFC markers); out-of-flow children become\n // layout nodes for the positioning pass.\n const run = extractLeafRun(root, style.tracking, {\n rootFontSizePx,\n rootLetterSpacingPx: cellMetrics?.letterSpacing ?? 0,\n cellMetrics,\n preserve: style.whiteSpace === \"pre\",\n tabSize: style.tabSize,\n });\n const text = run.chars.join(\"\");\n // Intrinsic advances for the box markers use the boxes' max-content\n // widths; layout overwrites them with the laid-out widths per pass.\n if (run.boxes.length > 0) {\n const cache = makeIntrinsicCache();\n eachObjectMarker(run.chars, (charIndex, boxIndex) => {\n run.advances[charIndex] = Math.max(1, intrinsicOuterWidth(run.boxes[boxIndex]!, cache));\n });\n }\n const intrinsicWidth = longestLineAdvance(text, run.advances, style.tracking);\n const intrinsicHeight = text.length > 0 ? countHardLines(text) : 0;\n const children: LayoutNode[] = [...run.boxes];\n for (let i = 0; i < elementChildren.length; i++) {\n if (roles[i] !== \"out-of-flow\") continue;\n const child = buildTree(elementChildren[i]!, rootFontSizePx, cellMetrics);\n if (child) children.push(child);\n }\n const node: LayoutNode = {\n source: root,\n style,\n children,\n text,\n intrinsicWidth,\n intrinsicHeight,\n localRect: { x: 0, y: 0, width: intrinsicWidth, height: intrinsicHeight },\n unclampedHeight: 0,\n resolvedPadding: zeroInsets(),\n };\n if (run.advances.some((a) => a !== 1) || run.boxes.length > 0) node.advances = run.advances;\n if (run.inlineElements.length > 0) node.inlineElements = run.inlineElements;\n return node;\n }\n\n const children: LayoutNode[] = [];\n for (let i = 0; i < elementChildren.length; i++) {\n if (roles[i] === \"none\") continue;\n const node = buildTree(elementChildren[i]!, rootFontSizePx, cellMetrics);\n if (node) children.push(node);\n }\n const container: LayoutNode = {\n source: root,\n style,\n children,\n text: \"\",\n intrinsicWidth: 0,\n intrinsicHeight: 0,\n localRect: { x: 0, y: 0, width: 0, height: 0 },\n unclampedHeight: 0,\n resolvedPadding: zeroInsets(),\n };\n flagDroppedText(root, container);\n return container;\n}\n\n/**\n * HTML tags whose default display is inline — a FALLBACK for environments\n * whose getComputedStyle returns \"\" for un-styled elements (happy-dom in\n * the headless tests). Real browsers always resolve a computed display,\n * so there this list is never consulted: computed display decides, and\n * CSS blockification (flex/grid children, absolute positioning) is\n * honored (specs/cell-model.md \"Inline detection\").\n */\nconst FALLBACK_INLINE_TAGS = new Set([\n \"A\",\n \"ABBR\",\n \"B\",\n \"BDI\",\n \"BDO\",\n \"BR\",\n \"CITE\",\n \"CODE\",\n \"DATA\",\n \"DFN\",\n \"EM\",\n \"I\",\n \"KBD\",\n \"MARK\",\n \"Q\",\n \"S\",\n \"SAMP\",\n \"SMALL\",\n \"SPAN\",\n \"STRONG\",\n \"SUB\",\n \"SUP\",\n \"TIME\",\n \"U\",\n \"VAR\",\n \"WBR\",\n]);\n\n/** Resolve a computed display, falling back per tag for environments\n * that return \"\" (happy-dom). */\nfunction resolvedDisplay(el: Element, display: string): string {\n return display || (FALLBACK_INLINE_TAGS.has(el.tagName) ? \"inline\" : \"block\");\n}\n\n/** True for content that flows WITH the surrounding text (computed\n * `inline` or `contents`). */\nfunction isRunInline(el: Element, display: string): boolean {\n const resolved = resolvedDisplay(el, display);\n return resolved === \"inline\" || resolved === \"contents\";\n}\n\n/** Atomic inline-level boxes (`inline-flex`/`inline-block`/`inline-grid`)\n * ride the line as single unbreakable units with their own internal\n * layout (specs/cell-model.md). */\nfunction isAtomicInline(el: Element, display: string): boolean {\n const resolved = resolvedDisplay(el, display);\n return resolved.startsWith(\"inline\") && resolved !== \"inline\";\n}\n\n/** Classify a direct child: skipped, out-of-flow box, text-run content\n * (plain inline AND atomic inline boxes), or in-flow block (which forces\n * container mode). */\nfunction childRole(el: Element): \"none\" | \"out-of-flow\" | \"inline\" | \"block\" {\n const cs = getComputedStyle(el);\n if (cs.display === \"none\") return \"none\";\n if (cs.position === \"absolute\" || cs.position === \"fixed\") return \"out-of-flow\";\n if (isRunInline(el, cs.display) || isAtomicInline(el, cs.display)) return \"inline\";\n return \"block\";\n}\n\ninterface LeafRun {\n chars: string[];\n /** Cells each character occupies: `1 + tracking` of its innermost element. */\n advances: number[];\n inlineElements: NonNullable<LayoutNode[\"inlineElements\"]>;\n /** Atomic inline boxes, in run order — each corresponds to one U+FFFC\n * marker in `chars` (layout resolves the marker's advance to the box's\n * laid-out width). */\n boxes: LayoutNode[];\n}\n\ninterface RunContext {\n rootFontSizePx: number;\n rootLetterSpacingPx: number;\n cellMetrics: CellMetrics | undefined;\n /** Leaf-level `white-space: pre`: keep the source's spaces and newlines\n * (tabs expand to `tabSize` stops from each hard line's start) instead\n * of collapsing. Applies to the whole run — a `white-space` override on\n * an inline descendant is not honored (specs/cell-model.md). */\n preserve: boolean;\n tabSize: number;\n}\n\n/**\n * Walk a leaf's childNodes and produce its text run — with `<br>` emitted as\n * `\\n` so the wrap calculation counts the line break the browser will honor\n * — plus per-character advances and the inline elements the renderer must\n * write grid typography (and rewritten relative insets) onto.\n *\n * Whitespace inside text nodes (including literal newlines from source\n * formatting) collapses to single spaces, exactly like the browser under\n * `white-space: normal` — ONLY `<br>` produces a hard `\\n`. Whitespace\n * around a hard break is stripped (the browser strips it at line edges too).\n * CSS collapsible white space only (space/tab/CR/LF/FF) — NOT `\\s`, which\n * would also eat NBSP (U+00A0); the browser preserves NBSP and never breaks\n * at it. A `white-space: pre` leaf skips all of that: spaces and newlines\n * survive as authored and tabs expand to tab stops (see RunContext).\n */\nfunction extractLeafRun(el: Element, tracking: number, ctx: RunContext): LeafRun {\n const run: LeafRun = { chars: [], advances: [], inlineElements: [], boxes: [] };\n collectRun(el, tracking, ctx, run);\n if (ctx.preserve) {\n // Browsers give a final newline in `pre` content no line box of its\n // own — drop exactly one (the HTML parser already ate the one right\n // after the opening tag).\n if (run.chars[run.chars.length - 1] === \"\\n\") {\n run.chars.pop();\n run.advances.pop();\n }\n return run;\n }\n return normalizeRun(run);\n}\n\nfunction collectRun(el: Element, tracking: number, ctx: RunContext, run: LeafRun): void {\n // Cells since the current hard line began — the tab-stop basis.\n const column = (): number => {\n let cells = 0;\n for (let i = run.chars.length - 1; i >= 0 && run.chars[i] !== \"\\n\"; i--) {\n cells += run.advances[i]!;\n }\n return cells;\n };\n for (const node of Array.from(el.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE) {\n if (ctx.preserve) {\n // `white-space: pre`: spaces and newlines survive as authored;\n // tabs expand to the next `tabSize` stop (spaces are pushed\n // untracked — tab stops are grid columns, not glyphs).\n for (const ch of (node.textContent ?? \"\").replace(/\\r\\n?/g, \"\\n\")) {\n if (ch === \"\\n\") {\n run.chars.push(\"\\n\");\n run.advances.push(0);\n } else if (ch === \"\\t\") {\n const target = (Math.floor(column() / ctx.tabSize) + 1) * ctx.tabSize;\n for (let cells = column(); cells < target; cells++) {\n run.chars.push(\" \");\n run.advances.push(1);\n }\n } else {\n run.chars.push(ch);\n run.advances.push(1 + tracking);\n }\n }\n } else {\n for (const ch of (node.textContent ?? \"\").replace(/[ \\t\\r\\n\\f]+/g, \" \")) {\n run.chars.push(ch);\n run.advances.push(1 + tracking);\n }\n }\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const child = node as Element;\n if (child.tagName === \"BR\") {\n run.chars.push(\"\\n\");\n run.advances.push(0);\n continue;\n }\n // Reads happen during the measure pass, so authored values are visible.\n const cs = getComputedStyle(child);\n // Skipped or out-of-flow content never joins the run (a hidden\n // span's text must not render; an absolute span leaves the flow).\n if (cs.display === \"none\" || cs.position === \"absolute\" || cs.position === \"fixed\") continue;\n // An atomic inline box rides the run as ONE unbreakable unit: a\n // U+FFFC marker whose advance layout resolves to the box's width.\n if (isAtomicInline(child, cs.display)) {\n const box = buildTree(child, ctx.rootFontSizePx, ctx.cellMetrics);\n if (box) {\n box.inlineBox = true;\n run.chars.push(OBJECT_REPLACEMENT);\n run.advances.push(1);\n run.boxes.push(box);\n }\n continue;\n }\n // A BLOCK-level element nested inside the run can't be laid out\n // from here — skip its subtree and warn, mirroring dropped text.\n if (!isRunInline(child, cs.display)) {\n warnSkippedRunContent(child);\n continue;\n }\n const childTracking = trackingCells(\n cs.letterSpacing,\n parseFloat(cs.fontSize) || ctx.rootFontSizePx,\n ctx.rootLetterSpacingPx,\n );\n // Horizontal padding on an inline element (`px-1` badges), quantized\n // to cells: the run reserves the cells as 1-cell INLINE_PAD markers\n // glued to the element's edges, and the renderer writes the same\n // cells back as real padding (percent padding is unsupported and\n // reads as 0; vertical inline padding never moves layout, per CSS,\n // and passes through untouched).\n const padLeft = inlinePadCells(cs.paddingLeft, ctx.rootFontSizePx);\n const padRight = inlinePadCells(cs.paddingRight, ctx.rootFontSizePx);\n run.inlineElements.push({\n element: child,\n tracking: childTracking,\n padLeft,\n padRight,\n insets: cs.position === \"static\" ? null : inlineInsets(cs, ctx.rootFontSizePx),\n });\n for (let i = 0; i < padLeft; i++) {\n run.chars.push(INLINE_PAD);\n run.advances.push(1);\n }\n collectRun(child, childTracking, ctx, run);\n for (let i = 0; i < padRight; i++) {\n run.chars.push(INLINE_PAD);\n run.advances.push(1);\n }\n }\n }\n}\n\n/** Quantize an inline element's horizontal padding to cells. Computed\n * padding is px in every browser; a percent that survives (pre-Typed-OM\n * quirk) is unsupported on inline elements and reads as 0. */\nfunction inlinePadCells(value: string, rootFontSizePx: number): number {\n if (!value || value.endsWith(\"%\")) return 0;\n const px = parseFloat(value);\n return Number.isFinite(px) ? Math.max(0, pxToCells(px, rootFontSizePx)) : 0;\n}\n\n/** Authored relative insets of an inline (relative/sticky) element,\n * rewritten to whole cells by the renderer (specs/positioning.md).\n * Percent insets on inline elements are unsupported (`null`), a\n * documented deviation. (Absolute/fixed inline elements never reach\n * here — they leave the run as out-of-flow boxes.) */\nfunction inlineInsets(cs: CSSStyleDeclaration, rootFontSizePx: number): PerSide<number | null> {\n const side = (value: string): number | null => {\n if (!value || value === \"auto\" || value.endsWith(\"%\")) return null;\n const px = parseFloat(value);\n return Number.isFinite(px) ? pxToCells(px, rootFontSizePx) : null;\n };\n return { top: side(cs.top), right: side(cs.right), bottom: side(cs.bottom), left: side(cs.left) };\n}\n\n/** Collapse consecutive spaces (also across inline-element boundaries), trim\n * spaces at hard-line edges, and drop leading/trailing blank lines — keeping\n * chars and advances in lockstep. */\nfunction normalizeRun(run: LeafRun): LeafRun {\n const chars: string[] = [];\n const advances: number[] = [];\n const lineStart = () => {\n let i = chars.length;\n while (i > 0 && chars[i - 1] !== \"\\n\") i--;\n return i;\n };\n const trimLineEnd = () => {\n while (chars.length > lineStart() && chars[chars.length - 1] === \" \") {\n chars.pop();\n advances.pop();\n }\n };\n for (let i = 0; i < run.chars.length; i++) {\n const ch = run.chars[i]!;\n if (ch === \" \") {\n // Skip spaces at a line start and after another space. Collapsing\n // looks THROUGH inline-padding markers: white-space processing is\n // character-based, so padding between two spaces doesn't stop them\n // collapsing (and a space preceded only by padding still counts as\n // line-start, both per CSS).\n let previous = chars.length - 1;\n while (previous >= 0 && chars[previous] === INLINE_PAD) previous--;\n const atLineStart = previous < 0 || chars[previous] === \"\\n\";\n if (atLineStart || chars[previous] === \" \") continue;\n } else if (ch === \"\\n\") {\n trimLineEnd();\n }\n chars.push(ch);\n advances.push(run.advances[i]!);\n }\n trimLineEnd();\n // Drop leading/trailing blank hard lines (source formatting), like trim().\n while (chars[0] === \"\\n\") {\n chars.shift();\n advances.shift();\n }\n while (chars[chars.length - 1] === \"\\n\") {\n chars.pop();\n advances.pop();\n }\n return { chars, advances, inlineElements: run.inlineElements, boxes: run.boxes };\n}\n\nfunction longestLineAdvance(text: string, advances: number[], tracking: number): number {\n let max = 0;\n let lineStart = 0;\n for (let i = 0; i <= text.length; i++) {\n if (i === text.length || text[i] === \"\\n\") {\n max = Math.max(max, lineAdvance(lineStart, i, advances, tracking));\n lineStart = i + 1;\n }\n }\n return max;\n}\n\nfunction countHardLines(text: string): number {\n return text.split(\"\\n\").length;\n}\n\nconst warnedDroppedText = new WeakSet<Element>();\n\nconst warnedSkippedRunContent = new WeakSet<Element>();\n\nfunction warnSkippedRunContent(el: Element): void {\n if (warnedSkippedRunContent.has(el)) return;\n warnedSkippedRunContent.add(el);\n console.warn(\n \"[monowind] A block-level element nested inside a text run can't be laid out and was \" +\n \"skipped. Give it its own place in the layout instead.\",\n el,\n );\n}\n\n/** Mixed direct text + in-flow block children: the text can't be laid out\n * (no element to position — cell-model deviation). Hide it (via the\n * renderer) and tell the author how to fix their markup, once. */\nfunction flagDroppedText(el: Element, node: LayoutNode): void {\n const hasText = Array.from(el.childNodes).some(\n (child) => child.nodeType === Node.TEXT_NODE && /[^ \\t\\r\\n\\f]/.test(child.textContent ?? \"\"),\n );\n if (!hasText) return;\n node.droppedText = true;\n if (warnedDroppedText.has(el)) return;\n warnedDroppedText.add(el);\n console.warn(\n \"[monowind] Direct text next to block-level children can't be laid out and was hidden. \" +\n \"Wrap each text segment in its own element (e.g. a <div>).\",\n el,\n );\n}\n","import { getRootFontSizePx, measureCellMetrics } from \"./metrics.ts\";\nimport { layoutRoot } from \"./layout.ts\";\nimport { render } from \"./render.ts\";\nimport { buildTree } from \"./tree.ts\";\nimport { defaultCellStyle, zeroInsets } from \"./types.ts\";\nimport type { CellMetrics, LayoutNode } from \"./types.ts\";\n\nconst SHADOW_TEMPLATE = `\n<style>\n :host { display: block; position: relative; contain: layout style; }\n #viewport { position: relative; width: 100%; height: 100%; }\n /* When the host hides its own dropped direct text (visibility, see\n * styles.css), the decoration layer must not sink with it. Scoped to\n * that state so an authored 'invisible' on the host stays intact. */\n :host([data-mw-dropped-text]) #viewport { visibility: visible; }\n #decorations { position: absolute; inset: 0; pointer-events: none; user-select: none; white-space: pre; }\n</style>\n<div id=\"viewport\">\n <div id=\"decorations\" aria-hidden=\"true\"></div>\n <slot></slot>\n</div>\n`;\n\n// Import-safe outside the browser (SSR, Node scripts using renderAscii):\n// `HTMLElement` doesn't exist there, and a bare `extends HTMLElement` throws\n// at IMPORT time. Substitute an inert base — the class is only instantiated\n// by the browser after defineMonoWind(), which no-ops without a DOM.\nconst HTMLElementBase = (\n typeof HTMLElement === \"undefined\" ? class {} : HTMLElement\n) as typeof HTMLElement;\n\nexport class MonoWindElement extends HTMLElementBase {\n #shadow: ShadowRoot;\n #decorations: HTMLElement;\n #probe: HTMLElement;\n #resizeObserver: ResizeObserver | null = null;\n #mutationObserver: MutationObserver | null = null;\n #layoutPending = false;\n #cellMetrics: CellMetrics | null = null;\n\n constructor() {\n super();\n this.#shadow = this.attachShadow({ mode: \"open\" });\n this.#shadow.innerHTML = SHADOW_TEMPLATE;\n this.#decorations = this.#shadow.getElementById(\"decorations\") as HTMLElement;\n // Cell-metrics probe (see measureCellMetrics): persistent, hidden but\n // measurable, inheriting the host's font/line-height/letter-spacing.\n // It lives in the LIGHT DOM so it is font-matched in exactly the same\n // context as the content it stands in for (shadow-tree font matching\n // has its own quirks on some Chromium builds). Measurement happens\n // under the `measuring` attribute, so the companion stylesheet's\n // typography locks are off; the inline `!important`s guard the\n // box/wrap properties that must hold regardless.\n this.#probe = document.createElement(\"span\");\n this.#probe.setAttribute(\"aria-hidden\", \"true\");\n this.#probe.setAttribute(\"data-mw-probe\", \"\");\n this.#probe.style.cssText =\n \"position:absolute!important;top:0!important;left:0!important;\" +\n \"visibility:hidden!important;pointer-events:none!important;user-select:none!important;\" +\n \"white-space:pre!important;overflow-wrap:normal!important;\" +\n \"padding:0!important;margin:0!important;border:0!important;\";\n this.#probe.textContent = \"M\".repeat(100);\n }\n\n connectedCallback(): void {\n // Before the observers connect, so its insertion isn't observed.\n if (this.#probe.parentNode !== this) this.appendChild(this.#probe);\n\n this.#resizeObserver = new ResizeObserver(() => this.#scheduleLayout());\n this.#resizeObserver.observe(this);\n\n // Any surviving record is a user mutation: everything the engine\n // writes happens synchronously inside #performLayout and is drained\n // there before observation resumes.\n this.#mutationObserver = new MutationObserver(() => this.#scheduleLayout());\n this.#mutationObserver.observe(this, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\"],\n });\n\n // Fonts can finish loading after our first layout (the first layout then\n // used fallback-font metrics), which would leave decorations positioned\n // with stale cell metrics. Two signals, both needed:\n // - `fonts.ready` — resolves when the initial font loads settle. WebKit\n // fires this reliably; keep it for the common first-load case.\n // - `loadingdone` — fires on every later font-load batch (lazily\n // triggered @font-face, dynamically added styles).\n // Re-measuring is cheap and layout runs at most once per frame.\n document.fonts?.ready.then(this.#onFontsLoaded).catch((err: unknown) => {\n console.warn(\"[monowind] document.fonts.ready failed:\", err);\n });\n document.fonts?.addEventListener(\"loadingdone\", this.#onFontsLoaded);\n\n this.#scheduleLayout();\n }\n\n disconnectedCallback(): void {\n this.#resizeObserver?.disconnect();\n this.#mutationObserver?.disconnect();\n this.#resizeObserver = null;\n this.#mutationObserver = null;\n document.fonts?.removeEventListener(\"loadingdone\", this.#onFontsLoaded);\n }\n\n #onFontsLoaded = (): void => {\n // Defer a frame: rAF callbacks run BEFORE the style recalc that\n // applies a freshly loaded font, so an immediate layout could measure\n // the PRE-swap fallback metrics when the event and the swap land in\n // the same frame (seen consistently on slow CI runners). One frame\n // later the swap has rendered; #scheduleLayout adds its own rAF.\n requestAnimationFrame(() => this.#scheduleLayout());\n };\n\n #scheduleLayout(): void {\n if (this.#layoutPending) return;\n this.#layoutPending = true;\n requestAnimationFrame(() => {\n this.#layoutPending = false;\n try {\n this.#performLayout();\n } catch (err) {\n console.error(\"[monowind] layout failed:\", err);\n }\n });\n }\n\n #performLayout(): void {\n // The write phase is bracketed by the `measuring` attribute (gates the\n // companion stylesheet so reads see authored values). Everything the\n // engine writes to the light DOM — geometry vars, data-mw-* attributes\n // — happens synchronously in here, so the synchronous takeRecords() in\n // `finally` drains exactly our own mutation records. Observation\n // resumes the moment #performLayout returns: a user mutation in the\n // same task (right after a layout) is seen normally.\n this.setAttribute(\"measuring\", \"\");\n try {\n // (1) Cell metrics — measured EVERY layout from the persistent\n // probe (one getBoundingClientRect on a hidden node; layout is\n // already being forced). No cache to go stale: fonts settling out of\n // order with our rAFs once left a fallback-font measurement cached\n // with nothing to invalidate it. The vars are only rewritten when\n // the values change.\n const metrics = measureCellMetrics(this, this.#probe);\n const previous = this.#cellMetrics;\n if (\n previous === null ||\n previous.width !== metrics.width ||\n previous.height !== metrics.height ||\n previous.letterSpacing !== metrics.letterSpacing\n ) {\n this.style.setProperty(\"--mw-cw\", `${metrics.width}px`);\n this.style.setProperty(\"--mw-ch\", `${metrics.height}px`);\n this.style.setProperty(\"--mw-rls\", `${metrics.letterSpacing}px`);\n }\n this.#cellMetrics = metrics;\n\n // (2) Available cells from the host's CONTENT box — authored padding\n // on the host stays outside the grid (the shadow #viewport, which\n // laid-out children position against, already sits inside it).\n // clientWidth excludes the border; subtract the padding ourselves.\n const cs = getComputedStyle(this);\n const padX = (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);\n const availableCols = Math.max(0, Math.floor((this.clientWidth - padX) / metrics.width));\n if (availableCols === 0) return;\n\n // (3) Build a tree from the light DOM. Root is a virtual container\n // over the light-DOM children so we can lay them out as a block.\n const rootFontSizePx = getRootFontSizePx();\n const childNodes: LayoutNode[] = [];\n for (const child of Array.from(this.children)) {\n if (child === this.#probe) continue;\n const node = buildTree(child, rootFontSizePx, metrics);\n if (node) childNodes.push(node);\n }\n // The host is a container like any other: direct text on it can't\n // be laid out — hide it and warn (cell-model deviation), same as\n // tree.ts does for nested containers.\n const hostText = Array.from(this.childNodes).some(\n (child) =>\n child.nodeType === Node.TEXT_NODE && /[^ \\t\\r\\n\\f]/.test(child.textContent ?? \"\"),\n );\n if (hostText) {\n if (!this.hasAttribute(\"data-mw-dropped-text\")) {\n console.warn(\n \"[monowind] Direct text inside <mono-wind> can't be laid out and was hidden. \" +\n \"Wrap each text segment in its own element (e.g. a <div>).\",\n this,\n );\n }\n this.setAttribute(\"data-mw-dropped-text\", \"\");\n } else {\n this.removeAttribute(\"data-mw-dropped-text\");\n }\n if (childNodes.length === 0) {\n this.#decorations.replaceChildren();\n this.setAttribute(\"data-mw-ready\", \"\");\n return;\n }\n const virtualRoot: LayoutNode = {\n source: this,\n style: defaultCellStyle(),\n children: childNodes,\n text: \"\",\n intrinsicWidth: 0,\n intrinsicHeight: 0,\n localRect: { x: 0, y: 0, width: 0, height: 0 },\n unclampedHeight: 0,\n resolvedPadding: zeroInsets(),\n };\n\n // (4) Compute integer layout.\n const { height } = layoutRoot(virtualRoot, availableCols);\n\n // (5) Write geometry + paint decorations. Do this before clearing the\n // measuring attribute so the browser only paints the final state.\n render(virtualRoot, this.#decorations);\n\n // (6) Size the host to match content rows (content-driven height).\n // Under border-box (Tailwind's preflight default) the height must\n // also cover the host's own padding and border.\n const chrome =\n cs.boxSizing === \"border-box\"\n ? (parseFloat(cs.paddingTop) || 0) +\n (parseFloat(cs.paddingBottom) || 0) +\n (parseFloat(cs.borderTopWidth) || 0) +\n (parseFloat(cs.borderBottomWidth) || 0)\n : 0;\n this.style.height = `${height * metrics.height + chrome}px`;\n\n // (7) Reveal the host now that layout is done — kills the FOUC where\n // the browser paints raw flex/block layout before the engine runs.\n this.setAttribute(\"data-mw-ready\", \"\");\n } finally {\n this.removeAttribute(\"measuring\");\n // Drain the records our own writes queued (takeRecords is\n // synchronous). Deferring this to a microtask would open a window\n // where a USER mutation gets dropped with the engine's own.\n this.#mutationObserver?.takeRecords();\n }\n }\n}\n\n/** Register the <mono-wind> element (idempotent; no-op without a DOM, so\n * calling it from code that also runs server-side is safe). */\nexport function defineMonoWind(): void {\n if (typeof customElements === \"undefined\") return;\n if (customElements.get(\"mono-wind\")) return;\n customElements.define(\"mono-wind\", MonoWindElement);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"mono-wind\": MonoWindElement;\n }\n}\n","import { collectBorderRuns } from \"./borders.ts\";\nimport type { BorderRun } from \"./borders.ts\";\nimport { leafLineGeometry } from \"./layout.ts\";\nimport { advanceOf, INLINE_PAD, lineAdvance, OBJECT_REPLACEMENT } from \"./wrap.ts\";\nimport type { LineSpan } from \"./wrap.ts\";\nimport type { LayoutNode } from \"./types.ts\";\n\n/**\n * Render a laid-out tree as plain-text ASCII art: borders as box-drawing\n * glyphs, leaf text word-wrapped inside its content box, everything else as\n * spaces.\n *\n * This is the engine's \"screenshot without a browser\": deterministic,\n * font-independent, and diffable — used for golden regression tests and as\n * a debugging/agent-inspection tool. It intentionally renders geometry the\n * way the browser would paint it (same border-run and word-wrap code), minus\n * colors and fonts.\n *\n * Content that overflows the root box is clipped at the grid edges.\n */\nexport function renderAscii(root: LayoutNode): string {\n const width = root.localRect.width;\n const height = root.localRect.height;\n if (width <= 0 || height <= 0) return \"\";\n\n const grid: string[][] = Array.from({ length: height }, () =>\n Array.from({ length: width }, () => \" \"),\n );\n const put = (x: number, y: number, glyph: string) => {\n if (x >= 0 && x < width && y >= 0 && y < height) grid[y]![x] = glyph;\n };\n\n walk(root, 0, 0, put);\n\n return grid.map((row) => row.join(\"\").trimEnd()).join(\"\\n\");\n}\n\ntype PutGlyph = (x: number, y: number, glyph: string) => void;\n\nfunction walk(node: LayoutNode, parentAbsX: number, parentAbsY: number, put: PutGlyph): void {\n const absX = parentAbsX + node.localRect.x;\n const absY = parentAbsY + node.localRect.y;\n const style = node.style;\n\n const borderRuns: BorderRun[] = [];\n collectBorderRuns(\n style,\n { x: absX, y: absY, width: node.localRect.width, height: node.localRect.height },\n borderRuns,\n );\n for (const run of borderRuns) {\n for (let i = 0; i < run.length; i++) put(run.x + i, run.y, run.glyph);\n }\n\n const hasInFlowChildren = node.children.some(\n (child) =>\n !child.inlineBox && child.style.position !== \"absolute\" && child.style.position !== \"fixed\",\n );\n if (!hasInFlowChildren && node.text) {\n const padding = node.resolvedPadding;\n const contentX = absX + style.border.left + padding.left;\n const contentY = absY + style.border.top + padding.top;\n const contentWidth =\n node.localRect.width - style.border.left - style.border.right - padding.left - padding.right;\n const { spans, lineY } = leafLineGeometry(node, contentWidth);\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i]!;\n const row = contentY + lineY[i]!;\n const truncated =\n style.whiteSpace !== \"normal\" && style.overflow === \"clip\"\n ? truncateSpan(node.text, span, contentWidth, node.advances, style)\n : { end: span.end, ellipsis: false };\n // Each character advances by its own cell count (tracking gaps).\n let x = contentX;\n for (let k = span.start; k < truncated.end; k++) {\n // U+FFFC marks an embedded inline box (its cells are drawn by the\n // box's own walk); INLINE_PAD marks a blank inline-padding cell —\n // neither is a glyph.\n if (node.text[k] !== OBJECT_REPLACEMENT && node.text[k] !== INLINE_PAD) {\n put(x, row, node.text[k]!);\n }\n x += advanceOf(k, k + 1, node.advances);\n }\n if (truncated.ellipsis) put(x, row, \"…\");\n }\n }\n\n for (const child of node.children) {\n walk(child, absX, absY, put);\n }\n}\n\n/**\n * Mirror of what the browser paints for a clipped nowrap line: cut at the\n * content width, with `…` in the last visible cell when `text-overflow:\n * ellipsis` is set (the ellipsis reserves one cell).\n */\nfunction truncateSpan(\n text: string,\n span: LineSpan,\n contentWidth: number,\n advances: number[] | undefined,\n style: LayoutNode[\"style\"],\n): { end: number; ellipsis: boolean } {\n const { textOverflow, tracking } = style;\n if (lineAdvance(span.start, span.end, advances, tracking) <= contentWidth) {\n return { end: span.end, ellipsis: false };\n }\n const limit = textOverflow === \"ellipsis\" ? contentWidth - 1 : contentWidth;\n let end = span.start;\n while (end < span.end && lineAdvance(span.start, end + 1, advances, tracking) <= limit) end++;\n return { end, ellipsis: textOverflow === \"ellipsis\" && contentWidth > 0 };\n}\n"],"mappings":"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"}
|