monowind 0.1.2 → 0.1.4
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/borders.d.ts +49 -9
- package/dist/borders.d.ts.map +1 -1
- package/dist/cdn.d.ts +2 -1
- package/dist/cdn.d.ts.map +1 -1
- package/dist/cdn.js +37 -26
- package/dist/cdn.js.map +1 -1
- package/dist/element.d.ts +8 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/flex.d.ts.map +1 -1
- package/dist/grid.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1802 -860
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +9 -0
- package/dist/layout.d.ts.map +1 -1
- package/dist/plain-text.d.ts +31 -0
- package/dist/plain-text.d.ts.map +1 -0
- package/dist/style.d.ts.map +1 -1
- package/dist/table.d.ts +82 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/tree.d.ts.map +1 -1
- package/dist/types.d.ts +99 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/warn.d.ts +2 -0
- package/dist/warn.d.ts.map +1 -0
- package/dist/wrap.d.ts +7 -6
- package/dist/wrap.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/styles.css +40 -2
- package/dist/ascii.d.ts +0 -16
- package/dist/ascii.d.ts.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/borders.ts","../src/metrics.ts","../src/wrap.ts","../src/flex.ts","../src/types.ts","../src/grid.ts","../src/warn.ts","../src/table.ts","../src/positioning.ts","../src/layout.ts","../src/plain-text.ts","../src/render.ts","../src/style.ts","../src/tree.ts","../src/element.ts"],"sourcesContent":["import type {\n BorderRun,\n BorderStyle,\n CellStyle,\n GapRule,\n Insets,\n LayoutNode,\n PerSide,\n Rect,\n} from \"./types.ts\";\n\nexport type { BorderRun } from \"./types.ts\";\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\n/** Where CSS applies `z-index`: positioned elements and flex/grid\n * items; inert on static block-flow children. */\nexport function zIndexApplies(child: LayoutNode, parent: LayoutNode): boolean {\n return (\n child.style.position !== \"static\" ||\n parent.style.display === \"flex\" ||\n parent.style.display === \"grid\"\n );\n}\n\nfunction effectiveZIndex(child: LayoutNode, parent: LayoutNode): number {\n return zIndexApplies(child, parent) ? (child.style.zIndex ?? 0) : 0;\n}\n\n/** Children in paint order: stable-sorted by effective z-index,\n * document order breaking ties — mirrored by both renderers so\n * decorations and plain text agree with browser stacking at overlaps (a\n * simplified model: no stacking contexts, negative z still paints over\n * the parent's own glyphs). */\nexport function paintOrderedChildren(node: LayoutNode): LayoutNode[] {\n return [...node.children].sort((a, b) => effectiveZIndex(a, node) - effectiveZIndex(b, node));\n}\n\n/** A style's straight line glyph, for lattice segments. */\nexport function lineGlyph(style: BorderStyle, axis: \"h\" | \"v\"): string {\n const glyphs = borderGlyphs(style);\n return axis === \"h\" ? glyphs.h : glyphs.v;\n}\n\n/** Junction glyph for a lattice intersection, from which of the four\n * arms exist. `double` has a full junction set; dashed/dotted (and mixed\n * styles, decided by the caller) use the light set — the corner\n * convention (specs/cell-model.md). Stubs (≤1 arm) fall back to plain\n * line glyphs. */\nexport function junctionGlyph(\n style: BorderStyle,\n up: boolean,\n down: boolean,\n left: boolean,\n right: boolean,\n): string {\n const set = style === \"double\" ? DOUBLE_JUNCTIONS : LIGHT_JUNCTIONS;\n return set[(up ? 8 : 0) | (down ? 4 : 0) | (left ? 2 : 0) | (right ? 1 : 0)]!;\n}\n\n// Indexed by the up/down/left/right bitmask (8/4/2/1).\nconst LIGHT_JUNCTIONS = [\n \" \",\n \"─\",\n \"─\",\n \"─\", // no vertical arm\n \"│\",\n \"┌\",\n \"┐\",\n \"┬\",\n \"│\",\n \"└\",\n \"┘\",\n \"┴\",\n \"│\",\n \"├\",\n \"┤\",\n \"┼\",\n];\nconst DOUBLE_JUNCTIONS = [\n \" \",\n \"═\",\n \"═\",\n \"═\",\n \"║\",\n \"╔\",\n \"╗\",\n \"╦\",\n \"║\",\n \"╚\",\n \"╝\",\n \"╩\",\n \"║\",\n \"╠\",\n \"╣\",\n \"╬\",\n];\n\n/** Rings are junction special cases: lines are two collinear arms,\n * corners two perpendicular ones. Only dashed/dotted lines need their own\n * glyphs (`╌`/`╎` — the double dash pair reads cleaner than the triple\n * dash, which looks like dots in many fonts; `┄`/`┊` for dotted). Their\n * corners fall back to light via the junction set, as before. */\nfunction borderGlyphs(style: BorderStyle): Glyphs {\n const j = (up: boolean, down: boolean, left: boolean, right: boolean) =>\n junctionGlyph(style, up, down, left, right);\n const base: Glyphs = {\n h: j(false, false, true, true),\n v: j(true, true, false, false),\n tl: j(false, true, false, true),\n tr: j(false, true, true, false),\n bl: j(true, false, false, true),\n br: j(true, false, true, false),\n };\n if (style === \"dashed\") return { ...base, h: \"╌\", v: \"╎\" };\n if (style === \"dotted\") return { ...base, h: \"┄\", v: \"┊\" };\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Gap decorations (specs/gap-decorations.md)\n\n/** One gap band a rule may occupy: `bandStart`/`bandSize` across the\n * band's axis (x for a vertical rule), `start`/`end` along it. All in\n * content-box cells. */\nexport interface RuleSegment {\n bandStart: number;\n bandSize: number;\n start: number;\n end: number;\n}\n\nexport interface GapRuleContext {\n ruleX: GapRule | null;\n ruleY: GapRule | null;\n /** Column-gap bands (vertical lines) and row-gap bands (horizontal). */\n vertical: RuleSegment[];\n horizontal: RuleSegment[];\n contentWidth: number;\n contentHeight: number;\n border: Insets;\n borderStyle: PerSide<BorderStyle>;\n borderColor: PerSide<string | undefined>;\n padding: Insets;\n}\n\n/**\n * Paint gap rules as node-local glyph runs: each rule centers in its\n * band (floor on the leading side), crossings get junction glyphs from\n * their arms, and a rule that reaches the content edge through zero\n * padding tees into the container's innermost border ring. Mixed styles\n * fall back to the light set; all-double crossings use the double set.\n */\nexport function collectGapRuleRuns(ctx: GapRuleContext): BorderRun[] {\n const out: BorderRun[] = [];\n const originX = ctx.border.left + ctx.padding.left;\n const originY = ctx.border.top + ctx.padding.top;\n const placed = (rule: GapRule, seg: RuleSegment) => ({\n line: seg.bandStart + Math.floor((seg.bandSize - rule.width) / 2),\n start: seg.start,\n end: seg.end,\n });\n const vLines = ctx.ruleX ? ctx.vertical.map((seg) => placed(ctx.ruleX!, seg)) : [];\n const hLines = ctx.ruleY ? ctx.horizontal.map((seg) => placed(ctx.ruleY!, seg)) : [];\n const vWidth = ctx.ruleX?.width ?? 0;\n const hWidth = ctx.ruleY?.width ?? 0;\n /** Does a vertical rule cover column `x` at row `y`? */\n const verticalArm = (x: number, y: number): boolean =>\n vLines.some((l) => x >= l.line && x < l.line + vWidth && y >= l.start && y < l.end);\n /** Is row `y` inside a horizontal line? (Those cells belong to the\n * horizontal pass, which paints the junctions — no double glyphs.) */\n const insideHorizontal = (y: number): boolean =>\n hLines.some((l) => y >= l.line && y < l.line + hWidth);\n\n if (ctx.ruleX) {\n const glyph = lineGlyph(ctx.ruleX.style, \"v\");\n for (const line of vLines) {\n for (let t = 0; t < vWidth; t++)\n for (let y = line.start; y < line.end; y++) {\n if (insideHorizontal(y)) continue;\n out.push({\n glyph,\n x: originX + line.line + t,\n y: originY + y,\n length: 1,\n color: ctx.ruleX.color,\n });\n }\n collectRuleBorderTees(ctx, out, \"x\", line.line, line.start, line.end);\n }\n }\n if (ctx.ruleY) {\n const allDouble = ctx.ruleY.style === \"double\" && ctx.ruleX?.style === \"double\";\n for (const line of hLines) {\n for (let t = 0; t < hWidth; t++) {\n const y = line.line + t;\n for (let x = line.start; x < line.end; x++) {\n const through = verticalArm(x, y);\n const up = through || verticalArm(x, y - 1);\n const down = through || verticalArm(x, y + 1);\n out.push({\n glyph:\n up || down\n ? junctionGlyph(\n allDouble ? \"double\" : \"solid\",\n up,\n down,\n x > line.start,\n x < line.end - 1,\n )\n : lineGlyph(ctx.ruleY.style, \"h\"),\n x: originX + x,\n y: originY + y,\n length: 1,\n color: ctx.ruleY.color,\n });\n }\n }\n collectRuleBorderTees(ctx, out, \"y\", line.line, line.start, line.end);\n }\n }\n return out;\n}\n\n/** Tee a full-extent rule into the container's own innermost border\n * ring (only through ZERO padding — otherwise they don't touch). */\nfunction collectRuleBorderTees(\n ctx: GapRuleContext,\n out: BorderRun[],\n axis: \"x\" | \"y\",\n line: number,\n start: number,\n end: number,\n): void {\n const rule = axis === \"x\" ? ctx.ruleX! : ctx.ruleY!;\n const originX = ctx.border.left + ctx.padding.left;\n const originY = ctx.border.top + ctx.padding.top;\n const nodeWidth = originX + ctx.contentWidth + ctx.padding.right + ctx.border.right;\n const nodeHeight = originY + ctx.contentHeight + ctx.padding.bottom + ctx.border.bottom;\n const tee = (\n x: number,\n y: number,\n borderSide: BorderStyle,\n color: string | undefined,\n up: boolean,\n down: boolean,\n left: boolean,\n right: boolean,\n ) => {\n const style = rule.style === \"double\" && borderSide === \"double\" ? \"double\" : \"solid\";\n out.push({ glyph: junctionGlyph(style, up, down, left, right), x, y, length: 1, color });\n };\n if (axis === \"x\") {\n for (let t = 0; t < rule.width; t++) {\n const x = originX + line + t;\n if (start <= 0 && ctx.padding.top === 0 && ctx.border.top > 0)\n tee(\n x,\n ctx.border.top - 1,\n ctx.borderStyle.top,\n ctx.borderColor.top,\n false,\n true,\n true,\n true,\n );\n if (end >= ctx.contentHeight && ctx.padding.bottom === 0 && ctx.border.bottom > 0)\n tee(\n x,\n nodeHeight - ctx.border.bottom,\n ctx.borderStyle.bottom,\n ctx.borderColor.bottom,\n true,\n false,\n true,\n true,\n );\n }\n } else {\n for (let t = 0; t < rule.width; t++) {\n const y = originY + line + t;\n if (start <= 0 && ctx.padding.left === 0 && ctx.border.left > 0)\n tee(\n ctx.border.left - 1,\n y,\n ctx.borderStyle.left,\n ctx.borderColor.left,\n true,\n true,\n false,\n true,\n );\n if (end >= ctx.contentWidth && ctx.padding.right === 0 && ctx.border.right > 0)\n tee(\n nodeWidth - ctx.border.right,\n y,\n ctx.borderStyle.right,\n ctx.borderColor.right,\n true,\n true,\n true,\n false,\n );\n }\n }\n}\n","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\n * hyphen added) — except a word-INITIAL hyphen run (UAX #14 LB20a;\n * `-top-1` wraps `-top-` │ `1`, probed in Chromium/WebKit; Firefox's\n * own model differs and is a documented divergence) — so words are\n * 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 * except a word-initial run (UAX #14 LB20a). `\"mx-auto\"` →\n * `[\"mx-\", \"auto\"]`; `\"-top-1\"` → `[\"-top-\", \"1\"]`.\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 // Word-initial runs aren't break opportunities (see file header).\n const wordInitial = i === start;\n while (i + 1 < end && text[i + 1] === \"-\") i++;\n const next = i + 1;\n if (!wordInitial && next < end) {\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 { collectGapRuleRuns } from \"./borders.ts\";\nimport type { RuleSegment } from \"./borders.ts\";\nimport {\n clampSize,\n intrinsicOuterWidth,\n isOutOfFlow,\n layoutNode,\n minContentOuterWidth,\n resolveGap,\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 = resolveGap(node.style, \"x\", innerWidth);\n const gapY = resolveGap(node.style, \"y\", 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\n // Gap rules (specs/gap-decorations.md): vertical bands between the\n // items of each line (visual order — the space between adjacent\n // rects, whatever justify/margins/reverse produced it), horizontal\n // bands between lines, full content width.\n if (node.style.ruleX || node.style.ruleY) {\n const vertical: RuleSegment[] = [];\n const horizontal: RuleSegment[] = [];\n for (let r = 0; r < lines.length; r++) {\n const top = lineOffsets[r]! + r * gapY;\n const rects = lines[r]!.row.map((item) => item.node.localRect).sort((a, b) => a.x - b.x);\n for (let i = 1; i < rects.length; i++) {\n const bandStart = rects[i - 1]!.x + rects[i - 1]!.width - originX;\n const bandSize = rects[i]!.x - originX - bandStart;\n if (bandSize > 0)\n vertical.push({ bandStart, bandSize, start: top, end: top + rowHeights[r]! });\n }\n if (r > 0) {\n const prevBottom = lineOffsets[r - 1]! + (r - 1) * gapY + rowHeights[r - 1]!;\n if (top > prevBottom)\n horizontal.push({\n bandStart: prevBottom,\n bandSize: top - prevBottom,\n start: 0,\n end: innerWidth,\n });\n }\n }\n node.decorationRuns = collectGapRuleRuns({\n ruleX: node.style.ruleX,\n ruleY: node.style.ruleY,\n vertical,\n horizontal,\n contentWidth: innerWidth,\n contentHeight,\n border,\n borderStyle: node.style.borderStyle,\n borderColor: node.style.borderColor,\n padding,\n });\n }\n\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 = resolveGap(node.style, \"y\", 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\n // Gap rules: horizontal bands between stacked items, full content\n // width (the single column's cross extent).\n if (node.style.ruleY && items.length > 1) {\n const horizontal: RuleSegment[] = [];\n const rects = items\n .map((item) => item.node.localRect)\n .slice()\n .sort((a, b) => a.y - b.y);\n for (let i = 1; i < rects.length; i++) {\n const bandStart = rects[i - 1]!.y + rects[i - 1]!.height - originY;\n const bandSize = rects[i]!.y - originY - bandStart;\n if (bandSize > 0) horizontal.push({ bandStart, bandSize, start: 0, end: innerWidth });\n }\n node.decorationRuns = collectGapRuleRuns({\n ruleX: null,\n ruleY: node.style.ruleY,\n vertical: [],\n horizontal,\n contentWidth: innerWidth,\n contentHeight,\n border,\n borderStyle: node.style.borderStyle,\n borderColor: node.style.borderColor,\n padding,\n });\n }\n\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\" | \"table\" | \"none\";\n/** Table-internal role from the computed display (specs/table.md).\n * `\"none\"` on everything that isn't table-internal. Cells and captions\n * keep `display: \"block\"` — they ARE block containers; the table\n * container finds them by role. */\nexport type TableRole =\n | \"none\"\n | \"header-group\"\n | \"row-group\"\n | \"footer-group\"\n | \"row\"\n | \"cell\"\n | \"caption\"\n | \"column\"\n | \"column-group\";\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 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\n/** A gap-decoration rule (specs/gap-decorations.md), from the rule-*\n * utilities' `--mw-rule-*` mirrors. `color` is always concrete:\n * currentColor resolves to the container's computed color at read time,\n * like border colors. */\nexport interface GapRule {\n width: number;\n style: BorderStyle;\n color: string | undefined;\n}\n\n/** A collapsed table participant's authored border, moved out of\n * `CellStyle.border` at read time (`border-collapse` inherits, so every\n * internal element knows): geometry and painting then treat the element\n * as borderless, and the table's lattice consumes this instead\n * (specs/table.md). */\nexport interface LatticeBorder {\n width: Insets;\n style: PerSide<BorderStyle>;\n color: PerSide<string | undefined>;\n /** `border-style: hidden` (`border-hidden`): suppresses the shared\n * segment outright, beating any neighbor — its computed width is 0, so\n * the flag must ride separately (CSS 2.1 §17.6.2.1). */\n hidden: PerSide<boolean>;\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 plain-text 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 /** Paint-only text styling, passed through to the browser and\n * mirrored per-segment by the plain-text mode's spans. */\n fontWeight: string;\n fontStyle: string;\n textDecorationLine: string;\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 /** Computed text-align, normalized LTR (`right`/`end` → `end`, all else\n * `start`). On-grid: line offsets are whole cells. Browser paints its\n * own alignment; `renderPlainText` mirrors it per line. */\n textAlign: \"start\" | \"end\";\n tableRole: TableRole;\n tableLayout: \"auto\" | \"fixed\";\n /** True for `border-collapse: collapse` (Tailwind preflight's default\n * on `<table>`): cell borders merge into the shared lattice. */\n borderCollapse: boolean;\n /** `border-spacing`, quantized per axis; separate borders only. */\n borderSpacingX: number;\n borderSpacingY: number;\n captionSide: \"top\" | \"bottom\";\n /** Computed `vertical-align` normalized (the companion's baseline\n * lock is measuring-gated, so the read sees the authored/UA value).\n * Consumed by table cells (`td`/`th` default to the UA's `middle`;\n * `baseline` behaves as `start`) and by atomic inline boxes, where\n * only `end` (bottom) acts — it drops the line's text to the box's\n * last row (specs/cell-model.md). */\n verticalAlign: \"start\" | \"center\" | \"end\";\n /** Authored `z-index` (`null` = auto). Browser stacking is native;\n * the renderers walk children in this order (stable, document-order\n * ties) so decorations and plain text agree with it at overlaps. */\n zIndex: number | null;\n /** Set on collapsed-table participants; null everywhere else. */\n latticeBorder: LatticeBorder | null;\n /** Gap rules on flex/grid containers (specs/gap-decorations.md);\n * null when unauthored. The used gap in a ruled axis floors at the\n * rule width (deviation: rules take layout space — ink needs cells). */\n ruleX: GapRule | null;\n ruleY: GapRule | null;\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 /** Paint-only text styling for the plain-text mode (the browser\n * renders the real element). */\n color: string | undefined;\n fontWeight: string;\n fontStyle: string;\n textDecorationLine: string;\n }[];\n /** Per-character index into `inlineElements` (-1 = direct leaf text);\n * present only when the run contains inline elements. Plain-text\n * rendering maps colors, font styling, and relative inset shifts from\n * it. */\n charInline?: number[];\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 /** Engine-generated glyph runs in this node's local coordinates\n * (offset by its absolute position at paint time). Today: a collapsed\n * table's border lattice; future producers (css-gaps rules,\n * specs/gap-decorations.md) plug in here with no renderer changes. */\n decorationRuns?: BorderRun[];\n /** True on a node the table pass removed from rendering: misparented\n * table content (no anonymous boxes — specs/table.md) and `<col>`/\n * `<colgroup>` boxes (width carriers, never rendered). */\n tableHidden?: 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 /** Content-derived outer height, before explicit-height/min-height\n * flooring — written by layoutNode. Table cells align their content\n * against this: an explicit cell height tallens the box (and floors\n * the row), but `vertical-align` centers the CONTENT, per CSS. */\n naturalContentHeight?: 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 fontWeight: \"400\",\n fontStyle: \"normal\",\n textDecorationLine: \"none\",\n borderColor: { top: undefined, right: undefined, bottom: undefined, left: undefined },\n textAlignBlocked: false,\n textAlign: \"start\",\n tableRole: \"none\",\n tableLayout: \"auto\",\n borderCollapse: false,\n borderSpacingX: 0,\n borderSpacingY: 0,\n captionSide: \"top\",\n verticalAlign: \"start\",\n zIndex: null,\n latticeBorder: null,\n ruleX: null,\n ruleY: null,\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 { collectGapRuleRuns } from \"./borders.ts\";\nimport type { RuleSegment } from \"./borders.ts\";\nimport { percentToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack } from \"./types.ts\";\nimport {\n clampSize,\n intrinsicOuterWidth,\n isOutOfFlow,\n layoutNode,\n minContentOuterWidth,\n resolveGap,\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 : resolveGap(style, \"x\", innerWidth);\n const gapY = inheritedRows ? inheritedRows.gap : resolveGap(style, \"y\", 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 // Gap rules (specs/gap-decorations.md): gutter bands between adjacent\n // tracks (collapsed auto-fit gutters have no width and drop out),\n // spanning the grid's extent in the other axis. Rules paint through\n // spanning items — `rule-break` is unsupported (spec deviation).\n if (style.ruleX || style.ruleY) {\n const gridBands = (positions: number[], sizes: number[]): RuleSegment[] => {\n const bands: RuleSegment[] = [];\n for (let i = 1; i < positions.length; i++) {\n const bandStart = positions[i - 1]! + sizes[i - 1]!;\n const bandSize = positions[i]! - bandStart;\n if (bandSize > 0) bands.push({ bandStart, bandSize, start: 0, end: 0 });\n }\n return bands;\n };\n const extent = (positions: number[], sizes: number[]): [number, number] =>\n positions.length === 0\n ? [0, 0]\n : [positions[0]!, positions[positions.length - 1]! + sizes[sizes.length - 1]!];\n const [rowStart, rowEnd] = extent(rowPos, rowSizing.sizes);\n const [colStart, colEnd] = extent(colPos, colSizing.sizes);\n const vertical = gridBands(colPos, colSizing.sizes).map((band) => ({\n ...band,\n start: rowStart,\n end: rowEnd,\n }));\n const horizontal = gridBands(rowPos, rowSizing.sizes).map((band) => ({\n ...band,\n start: colStart,\n end: colEnd,\n }));\n node.decorationRuns = collectGapRuleRuns({\n ruleX: style.ruleX,\n ruleY: style.ruleY,\n vertical,\n horizontal,\n contentWidth: innerWidth,\n contentHeight,\n border,\n borderStyle: style.borderStyle,\n borderColor: style.borderColor,\n padding,\n });\n }\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 = Math.max(typeof style.gapX === \"number\" ? style.gapX : 0, style.ruleX?.width ?? 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","/** One-time developer warnings for silent deviations (cell-model,\n * table specs): each element warns once per distinct message, however\n * many layout passes run. */\nconst warned = new WeakMap<Element, Set<string>>();\n\nexport function warnOnce(el: Element, message: string): void {\n let messages = warned.get(el);\n if (!messages) warned.set(el, (messages = new Set()));\n if (messages.has(message)) return;\n messages.add(message);\n console.warn(`[monowind] ${message}`, el);\n}\n","import { junctionGlyph, lineGlyph } from \"./borders.ts\";\nimport { percentToCells } from \"./metrics.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport { distributeInteger } from \"./flex.ts\";\nimport {\n clampSize,\n intrinsicOuterWidth,\n isOutOfFlow,\n layoutNode,\n minContentOuterWidth,\n resolveLength,\n resolveSizeAgainst,\n} from \"./layout.ts\";\nimport type { IntrinsicCache } from \"./layout.ts\";\nimport type { BorderRun, BorderStyle, Insets, LatticeBorder, LayoutNode } from \"./types.ts\";\n\n/**\n * Table layout (specs/table.md): CSS 2.1 §17 adapted to integer cells.\n * Structure comes from `tableRole`s (computed display), spans from the\n * HTML attributes, column sizing from the §17.5.2.2 algorithms with the\n * shared integer distribution, and collapsed borders become a shared\n * box-drawing lattice painted with junction glyphs.\n */\n\ninterface PlacedCell {\n node: LayoutNode;\n /** The row LayoutNode the cell lives under (its rect parent). */\n rowNode: LayoutNode;\n row: number;\n col: number;\n rowSpan: number;\n colSpan: number;\n}\n\ninterface TableStructure {\n caption: LayoutNode | null;\n /** Rows in render order: header-group rows, body rows, footer-group rows. */\n rows: LayoutNode[];\n /** Per row: its group container node (null for rows directly in the table). */\n rowGroups: (LayoutNode | null)[];\n /** Per row: the exclusive end row index of its row group (`rowspan=\"0\"`\n * extends to it, and row spans clamp to it). */\n groupEnds: number[];\n cells: PlacedCell[];\n columnCount: number;\n /** Fixed width from `<col>` elements, per column. */\n colFixed: (number | undefined)[];\n /** Percent width from `<col>` elements, per column. */\n colPercent: (number | undefined)[];\n /** `<col>`/`<colgroup>` boxes and misparented content — never rendered. */\n hidden: LayoutNode[];\n}\n\n// ---------------------------------------------------------------------------\n// Structure\n\nfunction markHidden(structure: TableStructure, node: LayoutNode): void {\n structure.hidden.push(node);\n if (node.style.tableRole === \"column\" || node.style.tableRole === \"column-group\") return;\n warnOnce(\n node.source,\n \"Table content outside the expected structure (rows in tables, cells in rows) \" +\n \"can't be laid out and was hidden — no anonymous table boxes (specs/table.md).\",\n );\n}\n\n/** HTML `colspan`/`rowspan`, clamped per the HTML spec. `rowspan` 0 means\n * \"to the end of the row group\" and resolves during placement. */\nfunction spanAttribute(el: Element, name: \"colspan\" | \"rowspan\"): number {\n const raw = Number.parseInt(el.getAttribute(name) ?? \"\", 10);\n if (Number.isNaN(raw)) return 1;\n if (name === \"colspan\") return Math.min(1000, Math.max(1, raw));\n return Math.min(65534, Math.max(0, raw));\n}\n\nfunction readColumns(structure: TableStructure, node: LayoutNode, cache: IntrinsicCache): void {\n const expand = (col: LayoutNode, count: number) => {\n const width = col.style.width;\n const fixed =\n width && width.kind !== \"auto\" && width.kind !== \"percent\"\n ? resolveSizeAgainst(width, 0, col, cache)\n : undefined;\n const percent = width && width.kind === \"percent\" ? width.value : undefined;\n for (let i = 0; i < count; i++) {\n structure.colFixed.push(fixed);\n structure.colPercent.push(percent);\n }\n };\n if (node.style.tableRole === \"column\") {\n expand(node, spanCount(node.source));\n return;\n }\n const cols = node.children.filter((child) => child.style.tableRole === \"column\");\n if (cols.length === 0) expand(node, spanCount(node.source));\n else for (const col of cols) expand(col, spanCount(col.source));\n for (const child of node.children)\n if (child.style.tableRole !== \"column\") markHidden(structure, child);\n}\n\n/** `<col span>` / `<colgroup span>`, clamped per HTML (1–1000). */\nfunction spanCount(el: Element): number {\n const raw = Number.parseInt(el.getAttribute(\"span\") ?? \"\", 10);\n return Number.isNaN(raw) ? 1 : Math.min(1000, Math.max(1, raw));\n}\n\nfunction resolveTableStructure(node: LayoutNode, cache: IntrinsicCache): TableStructure {\n const structure: TableStructure = {\n caption: null,\n rows: [],\n rowGroups: [],\n groupEnds: [],\n cells: [],\n columnCount: 0,\n colFixed: [],\n colPercent: [],\n hidden: [],\n };\n\n // Row groups render header-first and footer-last regardless of DOM\n // order, per HTML; consecutive direct rows form one implicit group.\n const headerRows: { row: LayoutNode; group: LayoutNode }[] = [];\n const bodyRows: { row: LayoutNode; group: LayoutNode | null }[] = [];\n const footerRows: { row: LayoutNode; group: LayoutNode }[] = [];\n for (const child of node.children) {\n if (isOutOfFlow(child.style)) continue;\n const role = child.style.tableRole;\n if (role === \"row\") {\n bodyRows.push({ row: child, group: null });\n } else if (role === \"header-group\" || role === \"row-group\" || role === \"footer-group\") {\n const bucket =\n role === \"header-group\" ? headerRows : role === \"footer-group\" ? footerRows : bodyRows;\n for (const rowChild of child.children) {\n if (isOutOfFlow(rowChild.style)) continue;\n if (rowChild.style.tableRole === \"row\") bucket.push({ row: rowChild, group: child });\n else markHidden(structure, rowChild);\n }\n } else if (role === \"caption\") {\n if (structure.caption === null) structure.caption = child;\n else markHidden(structure, child);\n } else if (role === \"column\" || role === \"column-group\") {\n readColumns(structure, child, cache);\n structure.hidden.push(child);\n } else {\n markHidden(structure, child);\n }\n }\n\n // Group boundaries: each explicit group is one; direct body rows merge\n // with their neighbors into implicit groups per contiguous run.\n const ordered = [...headerRows, ...bodyRows, ...footerRows];\n let groupStart = 0;\n for (let r = 0; r < ordered.length; r++) {\n structure.rows.push(ordered[r]!.row);\n structure.rowGroups.push(ordered[r]!.group);\n const nextGroup = ordered[r + 1]?.group;\n const sameGroup =\n r + 1 < ordered.length &&\n (ordered[r]!.group === nextGroup || (ordered[r]!.group === null && nextGroup === null));\n if (!sameGroup) {\n for (let g = groupStart; g <= r; g++) structure.groupEnds.push(r + 1);\n groupStart = r + 1;\n }\n }\n\n placeCells(structure);\n return structure;\n}\n\n/** The grid auto-placement cursor specialized to tables: rows are\n * definite, cells fill left-to-right skipping slots blocked by earlier\n * spans, never dense (specs/table.md). */\nfunction placeCells(structure: TableStructure): void {\n // blockedUntil[c] = exclusive row index until which column c is occupied.\n const blockedUntil: number[] = [];\n for (let r = 0; r < structure.rows.length; r++) {\n const rowNode = structure.rows[r]!;\n let c = 0;\n for (const child of rowNode.children) {\n if (isOutOfFlow(child.style)) continue;\n if (child.style.tableRole !== \"cell\") {\n markHidden(structure, child);\n continue;\n }\n while ((blockedUntil[c] ?? 0) > r) c++;\n const colSpan = spanAttribute(child.source, \"colspan\");\n const rawRowSpan = spanAttribute(child.source, \"rowspan\");\n const groupEnd = structure.groupEnds[r]!;\n const rowSpan = Math.max(\n 1,\n Math.min(rawRowSpan === 0 ? groupEnd - r : rawRowSpan, groupEnd - r),\n );\n for (let i = c; i < c + colSpan; i++)\n blockedUntil[i] = Math.max(blockedUntil[i] ?? 0, r + rowSpan);\n structure.cells.push({ node: child, rowNode, row: r, col: c, rowSpan, colSpan });\n c += colSpan;\n }\n }\n structure.columnCount = Math.max(blockedUntil.length, structure.colFixed.length);\n}\n\n// ---------------------------------------------------------------------------\n// Column sizing (specs/table.md, CSS 2.1 §17.5.2.2 integer-adapted)\n\ninterface ColumnBounds {\n min: number[];\n max: number[];\n /** Highest percent authored on the column's cells or its `<col>`. */\n percent: (number | undefined)[];\n}\n\n/** A cell's intrinsic contribution. A fixed width replaces the max\n * contribution (floored at the content min — the width can't shrink a\n * column below its content, per CSS 2.1); the min stays content-derived.\n * Cell margins are ignored, per CSS (internal table boxes have none). */\nfunction cellContribution(cell: LayoutNode, kind: \"min\" | \"max\", cache: IntrinsicCache): number {\n const style = cell.style;\n const contentMin = minContentOuterWidth(cell, cache);\n let width: number;\n if (kind === \"min\") {\n width = contentMin;\n } else {\n const fixed =\n style.width !== undefined && style.width.kind !== \"auto\" && style.width.kind !== \"percent\"\n ? resolveSizeAgainst(style.width, 0, cell, cache)\n : undefined;\n width = fixed !== undefined ? Math.max(contentMin, fixed) : intrinsicOuterWidth(cell, 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\nfunction cellPercent(cell: LayoutNode): number | undefined {\n const width = cell.style.width;\n return width && width.kind === \"percent\" ? width.value : undefined;\n}\n\nfunction autoColumnBounds(\n structure: TableStructure,\n chrome: TableChrome,\n cache: IntrinsicCache,\n): ColumnBounds {\n const count = structure.columnCount;\n const min = Array.from({ length: count }, () => 0);\n const max = Array.from({ length: count }, () => 0);\n const percent = Array.from({ length: count }, (): number | undefined => undefined);\n for (let c = 0; c < count; c++) {\n if (structure.colFixed[c] !== undefined) max[c] = structure.colFixed[c]!;\n percent[c] = structure.colPercent[c];\n }\n\n const spanning: PlacedCell[] = [];\n for (const cell of structure.cells) {\n if (cell.colSpan > 1) {\n spanning.push(cell);\n continue;\n }\n min[cell.col] = Math.max(min[cell.col]!, cellContribution(cell.node, \"min\", cache));\n max[cell.col] = Math.max(max[cell.col]!, cellContribution(cell.node, \"max\", cache));\n const p = cellPercent(cell.node);\n if (p !== undefined) percent[cell.col] = Math.max(percent[cell.col] ?? 0, p);\n }\n\n // Spanning cells: ascending span, excess over what the spanned columns\n // already provide distributed proportionally to their max widths\n // (equal shares when all zero). Percent on spanning cells is ignored.\n spanning.sort((a, b) => a.colSpan - b.colSpan);\n for (const cell of spanning) {\n const c0 = cell.col;\n const c1 = cell.col + cell.colSpan;\n const interior = chromeBetweenColumns(chrome, c0, c1);\n const weights = max.slice(c0, c1);\n for (const kind of [\"min\", \"max\"] as const) {\n const target = kind === \"min\" ? min : max;\n const provided = target.slice(c0, c1).reduce((a, b) => a + b, 0) + interior;\n const excess = cellContribution(cell.node, kind, cache) - provided;\n if (excess <= 0) continue;\n const shares = distributeInteger(\n weights.some((w) => w > 0) ? weights : weights.map(() => 1),\n excess,\n );\n for (let c = c0; c < c1; c++) target[c]! += shares[c - c0]!;\n }\n }\n\n for (let c = 0; c < count; c++) max[c] = Math.max(max[c]!, min[c]!);\n return { min, max, percent };\n}\n\n/** Distribute the definite column space (specs/table.md steps 4–5):\n * percent columns pin to their resolved shares (floored at min, scaled\n * so non-percent columns keep their mins); the rest grow min → max, then\n * share anything beyond proportionally to their maxes. */\nfunction distributeColumns(bounds: ColumnBounds, columnSpace: number): number[] {\n const count = bounds.min.length;\n const widths = bounds.min.slice();\n const percentIndices: number[] = [];\n const autoIndices: number[] = [];\n for (let c = 0; c < count; c++)\n (bounds.percent[c] !== undefined ? percentIndices : autoIndices).push(c);\n\n if (percentIndices.length > 0) {\n const totalPercent = percentIndices.reduce((sum, c) => sum + bounds.percent[c]!, 0);\n const scale = Math.max(100, totalPercent);\n for (const c of percentIndices) {\n const raw = Math.round((columnSpace * bounds.percent[c]!) / scale);\n widths[c] = Math.max(bounds.min[c]!, raw);\n }\n // Cap so every non-percent column keeps its min (the used-width floor\n // guarantees all-mins fits); shrink proportionally to target − min.\n const autoMins = autoIndices.reduce((sum, c) => sum + bounds.min[c]!, 0);\n const percentTotal = percentIndices.reduce((sum, c) => sum + widths[c]!, 0);\n const over = percentTotal - (columnSpace - autoMins);\n if (over > 0) {\n const reducible = percentIndices.map((c) => widths[c]! - bounds.min[c]!);\n const cuts = distributeInteger(\n reducible,\n Math.min(\n over,\n reducible.reduce((a, b) => a + b, 0),\n ),\n );\n percentIndices.forEach((c, i) => (widths[c]! -= cuts[i]!));\n }\n }\n\n let remaining = columnSpace - widths.reduce((a, b) => a + b, 0);\n if (remaining > 0 && autoIndices.length > 0) {\n const room = autoIndices.map((c) => bounds.max[c]! - bounds.min[c]!);\n const growable = room.reduce((a, b) => a + b, 0);\n const grow = distributeInteger(room, Math.min(remaining, growable));\n autoIndices.forEach((c, i) => (widths[c]! += grow[i]!));\n remaining -= Math.min(remaining, growable);\n }\n if (remaining > 0) {\n // Beyond every max: proportional to the maxes (equal when all zero);\n // percent columns join only when there is nothing else.\n const targets = autoIndices.length > 0 ? autoIndices : percentIndices;\n if (targets.length > 0) {\n const weights = targets.map((c) => bounds.max[c]!);\n const extra = distributeInteger(\n weights.some((w) => w > 0) ? weights : weights.map(() => 1),\n remaining,\n );\n targets.forEach((c, i) => (widths[c]! += extra[i]!));\n }\n }\n return widths;\n}\n\n/** `table-layout: fixed`: `<col>`s, then the first row's cells (spanning\n * cells split equally); still-unsized columns share the rest equally.\n * Content is never measured. */\nfunction fixedLayoutColumns(\n structure: TableStructure,\n columnSpace: number,\n cache: IntrinsicCache,\n): number[] {\n const count = structure.columnCount;\n const widths = Array.from({ length: count }, (): number | undefined => undefined);\n for (let c = 0; c < count; c++) {\n if (structure.colFixed[c] !== undefined) widths[c] = structure.colFixed[c];\n else if (structure.colPercent[c] !== undefined)\n widths[c] = Math.max(0, Math.round((columnSpace * structure.colPercent[c]!) / 100));\n }\n for (const cell of structure.cells) {\n if (cell.row !== 0) continue;\n const style = cell.node.style;\n let cellWidth: number | undefined;\n if (style.width && style.width.kind === \"percent\")\n cellWidth = Math.max(0, Math.round((columnSpace * style.width.value) / 100));\n else if (style.width && style.width.kind !== \"auto\")\n cellWidth = resolveSizeAgainst(style.width, 0, cell.node, cache);\n if (cellWidth === undefined) continue;\n const share = distributeInteger(\n Array.from({ length: cell.colSpan }, () => 1),\n cellWidth,\n );\n for (let i = 0; i < cell.colSpan; i++) {\n const c = cell.col + i;\n if (widths[c] === undefined) widths[c] = share[i];\n }\n }\n const sized = widths.reduce<number>((sum, w) => sum + (w ?? 0), 0);\n const unsized = widths.filter((w) => w === undefined).length;\n if (unsized > 0) {\n const shares = distributeInteger(\n Array.from({ length: unsized }, () => 1),\n Math.max(0, columnSpace - sized),\n );\n let i = 0;\n for (let c = 0; c < count; c++) if (widths[c] === undefined) widths[c] = shares[i++];\n }\n return widths.map((w) => w ?? 0);\n}\n\n// ---------------------------------------------------------------------------\n// Border lattice (collapsed) and spacing (separate) geometry\n\ninterface LatticeSegment {\n width: number;\n style: BorderStyle;\n color: string | undefined;\n}\n\ninterface TableChrome {\n collapsed: boolean;\n /** Collapsed: per-line widths (columnCount + 1 / rowCount + 1); the\n * separate model keeps them zero and uses the spacings. */\n vLines: number[];\n hLines: number[];\n spacingX: number;\n spacingY: number;\n /** Collapsed only: winner per vertical segment [line][row] and\n * horizontal segment [line][column]; null = no border there (spanned\n * through, or nothing authored). */\n vSegments: (LatticeSegment | null)[][];\n hSegments: (LatticeSegment | null)[][];\n}\n\ntype Side = \"top\" | \"right\" | \"bottom\" | \"left\";\n\nconst STYLE_RANK: Record<BorderStyle, number> = { double: 3, solid: 2, dashed: 1, dotted: 0 };\n\n/** CSS 2.1 §17.6.2.1, simplified: wider wins, then style rank, then the\n * candidate order (callers pass cell > row > row group > table). */\nfunction resolveSegment(\n candidates: { border: LatticeBorder | null; side: Side }[],\n): LatticeSegment | null {\n for (const { border, side } of candidates) if (border?.hidden[side]) return null; // hidden beats everything\n let winner: LatticeSegment | null = null;\n for (const { border, side } of candidates) {\n if (!border) continue;\n const width = border.width[side];\n if (width <= 0) continue;\n const style = border.style[side];\n if (\n winner === null ||\n width > winner.width ||\n (width === winner.width && STYLE_RANK[style] > STYLE_RANK[winner.style])\n ) {\n winner = { width, style, color: border.color[side] };\n }\n }\n return winner;\n}\n\nfunction resolveChrome(node: LayoutNode, structure: TableStructure): TableChrome {\n const C = structure.columnCount;\n const R = structure.rows.length;\n const collapsed = node.style.borderCollapse;\n const chrome: TableChrome = {\n collapsed,\n vLines: Array.from({ length: C + 1 }, () => 0),\n hLines: Array.from({ length: R + 1 }, () => 0),\n spacingX: collapsed ? 0 : node.style.borderSpacingX,\n spacingY: collapsed ? 0 : node.style.borderSpacingY,\n vSegments: [],\n hSegments: [],\n };\n if (!collapsed || C === 0 || R === 0) return chrome;\n\n // Occupancy map for adjacency lookups.\n const cellAt: (PlacedCell | undefined)[][] = Array.from({ length: R }, () =>\n Array.from({ length: C }, (): PlacedCell | undefined => undefined),\n );\n for (const cell of structure.cells)\n for (let r = cell.row; r < cell.row + cell.rowSpan; r++)\n for (let c = cell.col; c < cell.col + cell.colSpan; c++) cellAt[r]![c] = cell;\n\n const table = node.style.latticeBorder;\n for (let i = 0; i <= C; i++) {\n const segments: (LatticeSegment | null)[] = [];\n for (let r = 0; r < R; r++) {\n const left = i > 0 ? cellAt[r]![i - 1] : undefined;\n const right = i < C ? cellAt[r]![i] : undefined;\n if (left !== undefined && left === right) {\n segments.push(null); // spanned through\n continue;\n }\n const candidates: { border: LatticeBorder | null; side: Side }[] = [];\n if (left && left.col + left.colSpan === i)\n candidates.push({ border: left.node.style.latticeBorder, side: \"right\" });\n if (right && right.col === i)\n candidates.push({ border: right.node.style.latticeBorder, side: \"left\" });\n // Row/group left/right borders compete at the table's edge lines.\n const edge: Side | null = i === 0 ? \"left\" : i === C ? \"right\" : null;\n if (edge) {\n candidates.push({ border: structure.rows[r]!.style.latticeBorder, side: edge });\n const group = structure.rowGroups[r];\n if (group) candidates.push({ border: group.style.latticeBorder, side: edge });\n candidates.push({ border: table, side: edge });\n }\n segments.push(resolveSegment(candidates));\n }\n chrome.vSegments.push(segments);\n chrome.vLines[i] = segments.reduce((w, s) => Math.max(w, s?.width ?? 0), 0);\n }\n for (let j = 0; j <= R; j++) {\n const segments: (LatticeSegment | null)[] = [];\n for (let c = 0; c < C; c++) {\n const above = j > 0 ? cellAt[j - 1]![c] : undefined;\n const below = j < R ? cellAt[j]![c] : undefined;\n if (above !== undefined && above === below) {\n segments.push(null);\n continue;\n }\n const candidates: { border: LatticeBorder | null; side: Side }[] = [];\n if (above && above.row + above.rowSpan === j)\n candidates.push({ border: above.node.style.latticeBorder, side: \"bottom\" });\n if (below && below.row === j)\n candidates.push({ border: below.node.style.latticeBorder, side: \"top\" });\n if (j > 0)\n candidates.push({ border: structure.rows[j - 1]!.style.latticeBorder, side: \"bottom\" });\n if (j < R) candidates.push({ border: structure.rows[j]!.style.latticeBorder, side: \"top\" });\n const groupAbove = j > 0 ? structure.rowGroups[j - 1] : null;\n const groupBelow = j < R ? structure.rowGroups[j] : null;\n if (groupAbove && groupAbove !== groupBelow)\n candidates.push({ border: groupAbove.style.latticeBorder, side: \"bottom\" });\n if (groupBelow && groupBelow !== groupAbove)\n candidates.push({ border: groupBelow.style.latticeBorder, side: \"top\" });\n if (j === 0) candidates.push({ border: table, side: \"top\" });\n if (j === R) candidates.push({ border: table, side: \"bottom\" });\n segments.push(resolveSegment(candidates));\n }\n chrome.hSegments.push(segments);\n chrome.hLines[j] = segments.reduce((w, s) => Math.max(w, s?.width ?? 0), 0);\n }\n return chrome;\n}\n\nfunction innerChromeX(chrome: TableChrome, columnCount: number): number {\n return chrome.collapsed\n ? chrome.vLines.reduce((a, b) => a + b, 0)\n : (columnCount + 1) * chrome.spacingX;\n}\n\n/** Chrome between columns [c0, c1): interior lattice lines or spacing. */\nfunction chromeBetweenColumns(chrome: TableChrome, c0: number, c1: number): number {\n if (!chrome.collapsed) return chrome.spacingX * (c1 - c0 - 1);\n let sum = 0;\n for (let i = c0 + 1; i < c1; i++) sum += chrome.vLines[i]!;\n return sum;\n}\n\nfunction chromeBetweenRows(chrome: TableChrome, r0: number, r1: number): number {\n if (!chrome.collapsed) return chrome.spacingY * (r1 - r0 - 1);\n let sum = 0;\n for (let j = r0 + 1; j < r1; j++) sum += chrome.hLines[j]!;\n return sum;\n}\n\n// ---------------------------------------------------------------------------\n// Cached per-node table data (structure + chrome + column bounds)\n\nexport interface TableData {\n structure: TableStructure;\n chrome: TableChrome;\n bounds: ColumnBounds;\n chromeX: number;\n}\n\nfunction tableData(node: LayoutNode, cache: IntrinsicCache): TableData {\n const cached = cache.tableData.get(node);\n if (cached) return cached;\n const structure = resolveTableStructure(node, cache);\n const chrome = resolveChrome(node, structure);\n const bounds = autoColumnBounds(structure, chrome, cache);\n const data: TableData = {\n structure,\n chrome,\n bounds,\n chromeX: innerChromeX(chrome, structure.columnCount),\n };\n cache.tableData.set(node, data);\n return data;\n}\n\n/** Content-box intrinsic widths: column bounds plus lattice/spacing\n * chrome, floored by the caption. Percents behave as auto here (the\n * indefinite-axis rule); inflation applies only against a definite\n * available width, in `tableUsedOuterWidth`. */\nexport function tableIntrinsicInnerWidths(\n node: LayoutNode,\n cache: IntrinsicCache,\n): { min: number; max: number } {\n const { structure, bounds, chromeX } = tableData(node, cache);\n let min = bounds.min.reduce((a, b) => a + b, 0) + chromeX;\n let max = bounds.max.reduce((a, b) => a + b, 0) + chromeX;\n if (structure.caption) {\n min = Math.max(min, minContentOuterWidth(structure.caption, cache));\n max = Math.max(max, intrinsicOuterWidth(structure.caption, cache));\n }\n return { min, max };\n}\n\n/** Used outer width of an auto-width table (specs/table.md step 3):\n * shrink-to-fit with percent inflation, floored at the min sum, capped\n * at the available width. Fixed layout always fills. */\nexport function tableUsedOuterWidth(\n node: LayoutNode,\n availableWidth: number,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n const { bounds, chromeX } = tableData(node, cache);\n const { min, max } = tableIntrinsicInnerWidths(node, cache);\n const outerChromeX =\n style.border.left +\n style.border.right +\n resolveLength(style.padding.left, availableWidth) +\n resolveLength(style.padding.right, availableWidth);\n\n // Percent inflation (css-tables-3 style, probed): each percent column\n // demands max ÷ p, the rest demand sum ÷ (1 − Σp); Σp ≥ 100% demands\n // everything. All in column space; chrome comes back after.\n let demand = bounds.max.reduce((a, b) => a + b, 0);\n let sumPercent = 0;\n let nonPercentMax = 0;\n for (let c = 0; c < bounds.max.length; c++) {\n const p = bounds.percent[c];\n if (p === undefined) nonPercentMax += bounds.max[c]!;\n else sumPercent += p;\n }\n if (sumPercent >= 100) {\n demand = Number.POSITIVE_INFINITY;\n } else if (sumPercent > 0) {\n for (let c = 0; c < bounds.max.length; c++) {\n const p = bounds.percent[c];\n if (p !== undefined && p > 0)\n demand = Math.max(demand, Math.ceil((bounds.max[c]! * 100) / p));\n }\n demand = Math.max(demand, Math.ceil((nonPercentMax * 100) / (100 - sumPercent)));\n }\n // `max` (not just the column demand) so the caption's own max-content\n // participates in shrink-to-fit.\n const target = Math.max(demand + chromeX, max) + outerChromeX;\n return Math.max(min + outerChromeX, Math.min(target, availableWidth));\n}\n\n// ---------------------------------------------------------------------------\n// Layout\n\nexport function layoutTable(\n node: LayoutNode,\n innerWidth: number,\n definiteInnerHeight: number | undefined,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const { structure, chrome, bounds } = tableData(node, cache);\n const C = structure.columnCount;\n const R = structure.rows.length;\n const contentLeft = border.left + padding.left;\n const contentTop = border.top + padding.top;\n\n for (const hiddenNode of structure.hidden) {\n hiddenNode.tableHidden = true;\n hiddenNode.localRect = { x: 0, y: 0, width: 0, height: 0 };\n hiddenNode.resolvedPadding = { top: 0, right: 0, bottom: 0, left: 0 };\n hiddenNode.unclampedHeight = 0;\n }\n\n const columnSpace = Math.max(0, innerWidth - innerChromeX(chrome, C));\n // Fixed layout applies only with an authored width; a width-auto fixed\n // table uses the auto algorithm, like every browser (CSS 2.1 §17.5.2).\n const style = node.style;\n const usesFixedLayout =\n style.tableLayout === \"fixed\" && style.width !== undefined && style.width.kind !== \"auto\";\n const widths = usesFixedLayout\n ? fixedLayoutColumns(structure, columnSpace, cache)\n : distributeColumns(bounds, columnSpace);\n\n // Column x positions and grid width, table-content-relative.\n const colX: number[] = [];\n let x = 0;\n for (let c = 0; c < C; c++) {\n x += chrome.collapsed ? chrome.vLines[c]! : chrome.spacingX;\n colX.push(x);\n x += widths[c]!;\n }\n const gridWidth = x + (chrome.collapsed ? (chrome.vLines[C] ?? 0) : chrome.spacingX);\n\n // Caption first: a top caption shifts the grid down.\n let captionHeight = 0;\n if (structure.caption) {\n layoutNode(structure.caption, innerWidth, undefined, contentLeft, contentTop, \"fill\", cache);\n captionHeight = structure.caption.localRect.height;\n }\n\n // Cell natural heights at their final span widths. Percent heights in\n // the subtree contribute nothing here (they'd be circular).\n const naturalHeights = new Map<PlacedCell, number>();\n const spanWidths = new Map<PlacedCell, number>();\n for (const cell of structure.cells) {\n const c1 = cell.col + cell.colSpan;\n const spanW =\n widths.slice(cell.col, c1).reduce((a, b) => a + b, 0) +\n chromeBetweenColumns(chrome, cell.col, c1);\n spanWidths.set(cell, spanW);\n layoutNode(cell.node, spanW, undefined, 0, 0, \"fill\", cache, { width: spanW });\n naturalHeights.set(cell, cell.node.localRect.height);\n }\n\n // Row heights: fixed (and, against a definite table height, percent —\n // probed: all engines pin such rows and give the leftover to the\n // others) row heights floor, single-span cells raise, spanning cells\n // distribute ascending-span (equal shares), extra definite height\n // spreads equally over the non-percent rows (specs/table.md).\n const chromeY = chrome.collapsed\n ? chrome.hLines.reduce((a, b) => a + b, 0)\n : (R + 1) * chrome.spacingY;\n const rowBasis =\n definiteInnerHeight === undefined\n ? undefined\n : Math.max(0, definiteInnerHeight - captionHeight - chromeY);\n const percentFloor = (size: LayoutNode[\"style\"][\"height\"]): number =>\n size !== undefined && size.kind === \"percent\" && rowBasis !== undefined\n ? percentToCells(size.value, rowBasis)\n : 0;\n const rowHeights = Array.from({ length: R }, () => 0);\n const percentRows = Array.from({ length: R }, () => false);\n for (let r = 0; r < R; r++) {\n const h = structure.rows[r]!.style.height;\n if (h !== undefined && h.kind === \"cells\") rowHeights[r] = h.value;\n const floor = percentFloor(h);\n if (floor > 0) {\n rowHeights[r] = Math.max(rowHeights[r]!, floor);\n percentRows[r] = true;\n }\n }\n for (const cell of structure.cells)\n if (cell.rowSpan === 1) {\n const floor = percentFloor(cell.node.style.height);\n if (floor > 0) percentRows[cell.row] = true;\n rowHeights[cell.row] = Math.max(rowHeights[cell.row]!, naturalHeights.get(cell)!, floor);\n }\n const rowSpanning = structure.cells\n .filter((cell) => cell.rowSpan > 1)\n .sort((a, b) => a.rowSpan - b.rowSpan);\n for (const cell of rowSpanning) {\n const r1 = cell.row + cell.rowSpan;\n const provided =\n rowHeights.slice(cell.row, r1).reduce((a, b) => a + b, 0) +\n chromeBetweenRows(chrome, cell.row, r1);\n const excess = naturalHeights.get(cell)! - provided;\n if (excess <= 0) continue;\n const shares = distributeInteger(\n Array.from({ length: cell.rowSpan }, () => 1),\n excess,\n );\n for (let r = cell.row; r < r1; r++) rowHeights[r]! += shares[r - cell.row]!;\n }\n if (definiteInnerHeight !== undefined && R > 0) {\n const extra =\n definiteInnerHeight - captionHeight - chromeY - rowHeights.reduce((a, b) => a + b, 0);\n if (extra > 0) {\n // Percent rows are pinned at their share; the rest split the\n // leftover (equally — deviation 5).\n const receivers: number[] = [];\n for (let r = 0; r < R; r++) if (!percentRows[r]) receivers.push(r);\n const targets = receivers.length > 0 ? receivers : Array.from({ length: R }, (_, r) => r);\n const shares = distributeInteger(\n targets.map(() => 1),\n extra,\n );\n targets.forEach((r, i) => (rowHeights[r]! += shares[i]!));\n }\n }\n\n // Row y positions, table-content-relative.\n const gridTop = structure.caption && node.style.captionSide === \"top\" ? captionHeight : 0;\n const rowY: number[] = [];\n let y = gridTop;\n for (let r = 0; r < R; r++) {\n y += chrome.collapsed ? chrome.hLines[r]! : chrome.spacingY;\n rowY.push(y);\n y += rowHeights[r]!;\n }\n const gridBottom =\n R > 0 ? y + (chrome.collapsed ? (chrome.hLines[R] ?? 0) : chrome.spacingY) : gridTop;\n\n // Rects, parent-relative down the tree: table → group → row → cell.\n // Rows and groups never went through layoutNode; give them the fields\n // the renderers expect (padding on internal boxes is ignored, per CSS).\n const groupTops = new Map<LayoutNode, number>();\n for (let r = 0; r < R; r++) {\n const group = structure.rowGroups[r];\n if (group && !groupTops.has(group)) groupTops.set(group, rowY[r]!);\n }\n for (const [group, top] of groupTops) {\n let bottom = top;\n for (let r = 0; r < R; r++)\n if (structure.rowGroups[r] === group) bottom = rowY[r]! + rowHeights[r]!;\n group.localRect = {\n x: contentLeft,\n y: contentTop + top,\n width: gridWidth,\n height: bottom - top,\n };\n group.resolvedPadding = { top: 0, right: 0, bottom: 0, left: 0 };\n group.unclampedHeight = bottom - top;\n }\n for (let r = 0; r < R; r++) {\n const rowNode = structure.rows[r]!;\n const group = structure.rowGroups[r];\n const groupTop = group ? groupTops.get(group)! : undefined;\n rowNode.localRect = {\n x: groupTop === undefined ? contentLeft : 0,\n y: groupTop === undefined ? contentTop + rowY[r]! : rowY[r]! - groupTop,\n width: gridWidth,\n height: rowHeights[r]!,\n };\n rowNode.resolvedPadding = { top: 0, right: 0, bottom: 0, left: 0 };\n rowNode.unclampedHeight = rowHeights[r]!;\n }\n for (const cell of structure.cells) {\n const r1 = cell.row + cell.rowSpan;\n const areaH =\n rowHeights.slice(cell.row, r1).reduce((a, b) => a + b, 0) +\n chromeBetweenRows(chrome, cell.row, r1);\n // A cell with percent-height children re-lays-out at the final area\n // height so they resolve against it — the browsers' legacy second\n // pass. Deeper percents chain through their parents' then-definite\n // heights; alignment then sees whatever height the content reached.\n const hasPercentHeightChild = cell.node.children.some(\n (child) => !isOutOfFlow(child.style) && child.style.height?.kind === \"percent\",\n );\n if (hasPercentHeightChild && areaH !== naturalHeights.get(cell)) {\n layoutNode(cell.node, spanWidths.get(cell)!, areaH, 0, 0, \"fill\", cache, {\n width: spanWidths.get(cell)!,\n height: areaH,\n });\n }\n // Align the CONTENT, not the box: an explicit cell height tallens\n // the natural box, but vertical-align still centers within it.\n alignCellContent(\n cell.node,\n areaH - (cell.node.naturalContentHeight ?? cell.node.localRect.height),\n );\n cell.node.localRect = {\n x: colX[cell.col]!,\n y: 0,\n width: cell.node.localRect.width,\n height: areaH,\n };\n }\n\n // Static slots for the table's own out-of-flow children: content origin\n // (sole-item semantics are a grid/flex concept; block-like here).\n for (const child of node.children)\n if (isOutOfFlow(child.style))\n child.staticSlot = { kind: \"block\", x: contentLeft, y: contentTop };\n\n if (structure.caption && node.style.captionSide === \"bottom\")\n structure.caption.localRect.y = contentTop + gridBottom;\n\n if (chrome.collapsed && C > 0 && R > 0)\n node.decorationRuns = buildLatticeRuns(\n chrome,\n structure,\n widths,\n rowHeights,\n colX,\n rowY,\n contentLeft,\n contentTop,\n );\n\n // A top caption is already inside gridBottom (via gridTop).\n return node.style.captionSide === \"bottom\" ? gridBottom + captionHeight : gridBottom;\n}\n\n/** Fold the cell's leftover block-axis space into its content per\n * `vertical-align`: leaves take it as engine-owned padding (the\n * alignLeafText pattern); containers shift their children. */\nfunction alignCellContent(cell: LayoutNode, delta: number): void {\n if (delta <= 0) return;\n const align = cell.style.verticalAlign;\n const offset = align === \"center\" ? Math.floor(delta / 2) : align === \"end\" ? delta : 0;\n const hasInFlow = cell.children.some((c) => !isOutOfFlow(c.style) && !c.inlineBox);\n if (!hasInFlow) {\n // The FULL delta lands in padding even at offset 0 (top alignment):\n // the renderers then account for every row of the stretched box.\n cell.resolvedPadding.top += offset;\n cell.resolvedPadding.bottom += delta - offset;\n return;\n }\n if (offset <= 0) return;\n for (const child of cell.children) {\n if (child.inlineBox) continue;\n if (isOutOfFlow(child.style)) {\n if (child.staticSlot?.kind === \"block\") child.staticSlot.y += offset;\n } else {\n child.localRect.y += offset;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Lattice painting\n\nfunction buildLatticeRuns(\n chrome: TableChrome,\n structure: TableStructure,\n widths: number[],\n rowHeights: number[],\n colX: number[],\n rowY: number[],\n contentLeft: number,\n contentTop: number,\n): BorderRun[] {\n const C = structure.columnCount;\n const R = structure.rows.length;\n const out: BorderRun[] = [];\n const lineX = (i: number) =>\n i < C ? colX[i]! - chrome.vLines[i]! : colX[C - 1]! + widths[C - 1]!;\n const lineY = (j: number) =>\n j < R ? rowY[j]! - chrome.hLines[j]! : rowY[R - 1]! + rowHeights[R - 1]!;\n\n // Straight vertical segments.\n for (let i = 0; i <= C; i++) {\n const segments = chrome.vSegments[i]!;\n for (let r = 0; r < R; r++) {\n const seg = segments[r];\n if (!seg) continue;\n // A segment narrower than its line paints from the line's start\n // (CSS centers collapsed borders; sub-cell centering can't).\n const glyph = lineGlyph(seg.style, \"v\");\n for (let t = 0; t < seg.width; t++)\n for (let yy = rowY[r]!; yy < rowY[r]! + rowHeights[r]!; yy++)\n out.push({\n glyph,\n x: contentLeft + lineX(i) + t,\n y: contentTop + yy,\n length: 1,\n color: seg.color,\n });\n }\n }\n // Straight horizontal segments.\n for (let j = 0; j <= R; j++) {\n const segments = chrome.hSegments[j]!;\n for (let c = 0; c < C; c++) {\n const seg = segments[c];\n if (!seg) continue;\n const glyph = lineGlyph(seg.style, \"h\");\n for (let t = 0; t < seg.width; t++)\n out.push({\n glyph,\n x: contentLeft + colX[c]!,\n y: contentTop + lineY(j) + t,\n length: widths[c]!,\n color: seg.color,\n });\n }\n }\n // Junction blocks where a vertical and a horizontal line cross.\n for (let i = 0; i <= C; i++) {\n if (chrome.vLines[i]! <= 0) continue;\n for (let j = 0; j <= R; j++) {\n if (chrome.hLines[j]! <= 0) continue;\n const up = j > 0 ? chrome.vSegments[i]![j - 1] : null;\n const down = j < R ? chrome.vSegments[i]![j] : null;\n const left = i > 0 ? chrome.hSegments[j]![i - 1] : null;\n const right = i < C ? chrome.hSegments[j]![i] : null;\n const arms = [up, down, left, right].filter((s): s is LatticeSegment => s !== null);\n if (arms.length === 0) continue;\n // Junction style: double only when every arm is double (the corner\n // convention); color from the dominant arm.\n const style: BorderStyle = arms.every((s) => s.style === \"double\") ? \"double\" : \"solid\";\n const dominant = arms.reduce((a, b) =>\n b.width > a.width || (b.width === a.width && STYLE_RANK[b.style] > STYLE_RANK[a.style])\n ? b\n : a,\n );\n const glyph = junctionGlyph(style, up !== null, down !== null, left !== null, right !== null);\n // Thick lines fill the whole crossing block with the junction glyph.\n for (let t = 0; t < chrome.vLines[i]!; t++)\n for (let u = 0; u < chrome.hLines[j]!; u++)\n out.push({\n glyph,\n x: contentLeft + lineX(i) + t,\n y: contentTop + lineY(j) + u,\n length: 1,\n color: dominant.color,\n });\n }\n }\n return out;\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 { layoutTable, tableIntrinsicInnerWidths, tableUsedOuterWidth } from \"./table.ts\";\nimport type { TableData } from \"./table.ts\";\nimport { walkPositioned } from \"./positioning.ts\";\nimport { warnOnce } from \"./warn.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 /** Table structure + chrome + column bounds, shared by the intrinsic,\n * width-resolution, and layout passes. */\n tableData: WeakMap<LayoutNode, TableData>;\n}\n\nexport function makeIntrinsicCache(): IntrinsicCache {\n return {\n maxContent: new WeakMap(),\n minContent: new WeakMap(),\n gridIntrinsic: new WeakMap(),\n tableData: new WeakMap(),\n };\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 // Fresh per layout: only the pass that runs (table lattice, flex/grid\n // gap rules) repopulates it.\n delete node.decorationRuns;\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, plain text, 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 if (style.display === \"table\") {\n contentHeight = layoutTable(\n node,\n inner.width,\n definiteInnerHeight,\n style.border,\n padding,\n cache,\n );\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 node.naturalContentHeight = naturalHeight;\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[]; textY: 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 const textY: 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 // `vertical-align: bottom` on an atomic box drops the line's TEXT to\n // the box's last row (grid-exact in every engine, probed); the\n // largest such box wins. top/middle/baseline behave as top\n // (cell-model deviation — middle and baseline are off-grid).\n let textOffset = 0;\n for (let i = span.start; i < span.end; i++) {\n if (node.text[i] !== OBJECT_REPLACEMENT) continue;\n const box = boxes[boxIndex]!;\n height = Math.max(height, box.localRect.height);\n if (box.style.verticalAlign === \"end\")\n textOffset = Math.max(textOffset, box.localRect.height - 1);\n else if (box.style.verticalAlign === \"center\")\n warnOnce(\n box.source,\n \"vertical-align: middle on an inline box can't land on whole rows and \" +\n \"behaves as top. Use align-top or align-bottom.\",\n );\n boxIndex++;\n }\n textY.push(y + Math.min(textOffset, height - 1));\n y += height + (s < spans.length - 1 ? node.style.lineGap : 0);\n }\n return { spans, lineY, textY, totalRows: y };\n}\n\n/** The used gap in an axis: the resolved gap floored at the axis's rule\n * width (specs/gap-decorations.md deviation 1 — rules take layout\n * space, so `rule` alone behaves as `gap-1 rule`). */\nexport function resolveGap(style: CellStyle, axis: \"x\" | \"y\", basis: number | undefined): number {\n const gap = resolveLength(axis === \"x\" ? style.gapX : style.gapY, basis);\n const rule = axis === \"x\" ? style.ruleX : style.ruleY;\n return Math.max(gap, rule?.width ?? 0);\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 (style.display === \"table\") {\n // Tables shrink-to-fit even in block flow, floored at their min sum\n // (specs/table.md step 3); fixed layout fills, percents inflate. A\n // table degraded to a text leaf (no rows) shrink-to-fits on its\n // plain intrinsics.\n const hasStructure = node.children.some(\n (child) => !isOutOfFlow(child.style) && !child.inlineBox,\n );\n if (!hasStructure) {\n if (width !== undefined && width.kind !== \"auto\")\n return resolveSizeAgainst(width, available, node, cache);\n return Math.min(available, intrinsicOuterWidth(node, cache));\n }\n if (width !== undefined && width.kind !== \"auto\") {\n const resolved = resolveSizeAgainst(width, available, node, cache);\n return Math.max(resolved, tableMinOuterWidth(node, available, cache));\n }\n return tableUsedOuterWidth(node, available, cache);\n }\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 tableMinOuterWidth(node: LayoutNode, available: number, cache: IntrinsicCache): number {\n const style = node.style;\n return (\n tableIntrinsicInnerWidths(node, cache).min +\n style.border.left +\n style.border.right +\n resolveLength(style.padding.left, available) +\n resolveLength(style.padding.right, available)\n );\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 === \"table\") return tableIntrinsicInnerWidths(node, cache).max;\n if (node.style.display === \"flex\" && node.style.flexDirection === \"row\") {\n const gap =\n Math.max(intrinsicCells(node.style.gapX), node.style.ruleX?.width ?? 0) *\n 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 (node.style.display === \"table\") return tableIntrinsicInnerWidths(node, cache).min;\n if (\n node.style.display === \"flex\" &&\n node.style.flexDirection === \"row\" &&\n node.style.flexWrap === \"nowrap\"\n ) {\n const gap =\n Math.max(intrinsicCells(node.style.gapX), node.style.ruleX?.width ?? 0) *\n 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 { collectBorderRuns, paintOrderedChildren } 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\", though the border\n * glyphs are Unicode box drawing): leaf text word-wrapped inside its\n * content box, everything else as 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 renderPlainText(root: LayoutNode): string {\n return renderGrids(root)\n .grid.map((row) => row.join(\"\").trimEnd())\n .join(\"\\n\");\n}\n\n/** Paint-through styling for one cell; every field optional so spans\n * only carry what differs from the host's inherited text style. */\nexport interface CellPaint {\n color?: string;\n fontWeight?: string;\n fontStyle?: string;\n textDecorationLine?: string;\n}\n\n/** One row of same-styled text runs. Joining every segment's text\n * reproduces the `renderPlainText` row — the plain-text mode builds\n * spans from these, so a copy still yields the pure text. */\nexport interface PlainTextSegment extends CellPaint {\n text: string;\n}\n\nexport function renderPlainTextSegments(root: LayoutNode): PlainTextSegment[][] {\n const { grid, paints } = renderGrids(root);\n return grid.map((row, y) => {\n const trimmed = row.join(\"\").trimEnd();\n const segments: PlainTextSegment[] = [];\n for (let x = 0; x < trimmed.length; x++) {\n // Painted spaces keep their bundle: underline/line-through must\n // span an inline run's inner spaces (filler cells carry none).\n const paint = paints[y]![x];\n const last = segments[segments.length - 1];\n if (last && samePaint(last, paint)) last.text += trimmed[x]!;\n else segments.push({ text: trimmed[x]!, ...paint });\n }\n return segments;\n });\n}\n\nfunction samePaint(a: CellPaint, b: CellPaint | undefined): boolean {\n return (\n a.color === b?.color &&\n a.fontWeight === b?.fontWeight &&\n a.fontStyle === b?.fontStyle &&\n a.textDecorationLine === b?.textDecorationLine\n );\n}\n\nfunction renderGrids(root: LayoutNode): { grid: string[][]; paints: (CellPaint | undefined)[][] } {\n const width = Math.max(0, root.localRect.width);\n const height = Math.max(0, root.localRect.height);\n const grid: string[][] = Array.from({ length: height }, () =>\n Array.from({ length: width }, () => \" \"),\n );\n const paints: (CellPaint | undefined)[][] = Array.from({ length: height }, () =>\n Array.from({ length: width }, (): CellPaint | undefined => undefined),\n );\n walk(root, 0, 0, (x, y, glyph, paint) => {\n if (x >= 0 && x < width && y >= 0 && y < height) {\n grid[y]![x] = glyph;\n paints[y]![x] = paint;\n }\n });\n return { grid, paints };\n}\n\n/** Non-default text styling only, so unstyled runs stay bare. */\nfunction textPaint(source: {\n color: string | undefined;\n fontWeight: string;\n fontStyle: string;\n textDecorationLine: string;\n}): CellPaint {\n const paint: CellPaint = {};\n if (source.color) paint.color = source.color;\n if (source.fontWeight !== \"400\" && source.fontWeight !== \"normal\" && source.fontWeight !== \"\")\n paint.fontWeight = source.fontWeight;\n if (source.fontStyle !== \"normal\" && source.fontStyle !== \"\") paint.fontStyle = source.fontStyle;\n if (source.textDecorationLine !== \"none\" && source.textDecorationLine !== \"\")\n paint.textDecorationLine = source.textDecorationLine;\n return paint;\n}\n\ntype PutGlyph = (x: number, y: number, glyph: string, paint: CellPaint | undefined) => void;\n\nfunction walk(node: LayoutNode, parentAbsX: number, parentAbsY: number, put: PutGlyph): void {\n if (node.tableHidden) return;\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 const paint = run.color === undefined ? undefined : { color: run.color };\n for (let i = 0; i < run.length; i++) put(run.x + i, run.y, run.glyph, paint);\n }\n if (node.decorationRuns) {\n for (const run of node.decorationRuns) {\n const paint = run.color === undefined ? undefined : { color: run.color };\n for (let i = 0; i < run.length; i++) put(absX + run.x + i, absY + run.y, run.glyph, paint);\n }\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, textY } = leafLineGeometry(node, contentWidth);\n const leafPaint = textPaint(style);\n const inlinePaints = node.inlineElements?.map((entry) => textPaint(entry));\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i]!;\n const row = contentY + textY[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 // `text-align: end` offsets each line to the content box's right\n // edge (whole cells; a line at or over the width stays at start,\n // matching the truncation path).\n const lineWidth = lineAdvance(span.start, span.end, node.advances, style.tracking);\n let x = contentX + (style.textAlign === \"end\" ? Math.max(0, contentWidth - lineWidth) : 0);\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 const inlineIndex = node.charInline?.[k] ?? -1;\n const entry = inlineIndex >= 0 ? node.inlineElements![inlineIndex] : undefined;\n // Inline relative shifts, whole cells (specs/positioning.md):\n // the over-constrained sides resolve like CSS (top/left win).\n const insets = entry?.insets;\n const dx = insets ? (insets.left ?? (insets.right !== null ? -insets.right : 0)) : 0;\n const dy = insets ? (insets.top ?? (insets.bottom !== null ? -insets.bottom : 0)) : 0;\n put(x + dx, row + dy, node.text[k]!, entry ? inlinePaints![inlineIndex] : leafPaint);\n }\n x += advanceOf(k, k + 1, node.advances);\n }\n if (truncated.ellipsis) put(x, row, \"…\", leafPaint);\n }\n }\n\n for (const child of paintOrderedChildren(node)) {\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","import { collectBorderRuns, paintOrderedChildren, zIndexApplies } 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 // A hidden table box (misparented content, <col>) hides its whole\n // subtree browser-side; nothing to paint or recurse into.\n if (node.tableHidden) return;\n\n collectBorderRuns(\n node.style,\n { x: absX, y: absY, width: node.localRect.width, height: node.localRect.height },\n borderRuns,\n );\n if (node.decorationRuns) {\n for (const run of node.decorationRuns)\n borderRuns.push({ ...run, x: absX + run.x, y: absY + run.y });\n }\n\n for (const child of paintOrderedChildren(node)) {\n // Absolutization would otherwise activate z-index on static block\n // children too (CSS keeps it inert there): the companion reads\n // `--mw-z`, written only where CSS applies it.\n const el = child.source as HTMLElement;\n if (child.style.zIndex !== null && zIndexApplies(child, node) && !child.inlineBox)\n el.style.setProperty(\"--mw-z\", String(child.style.zIndex));\n else el.style.removeProperty(\"--mw-z\");\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 // Bottom-aligned atomic boxes keep their browser alignment (grid-exact,\n // probed); everything else is pinned top by the companion rule.\n if (node.inlineBox && node.style.verticalAlign === \"end\") el.setAttribute(\"data-mw-vbottom\", \"\");\n else el.removeAttribute(\"data-mw-vbottom\");\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 if (node.tableHidden) el.setAttribute(\"data-mw-table-hidden\", \"\");\n else el.removeAttribute(\"data-mw-table-hidden\");\n}\n\nfunction paintDecorations(layer: HTMLElement, runs: BorderRun[]): void {\n layer.replaceChildren();\n // Later runs win per cell (junction tees over border edges, lattice\n // crossings) — the same overwrite semantics as renderPlainText's grid;\n // overlapping glyph spans would BOTH paint (visible under mismatched\n // ink, e.g. `╦` over `═`).\n const cells = new Map<string, { x: number; y: number; glyph: string; color?: string }>();\n for (const run of runs)\n for (let i = 0; i < run.length; i++) {\n const x = run.x + i;\n const cell: { x: number; y: number; glyph: string; color?: string } = {\n x,\n y: run.y,\n glyph: run.glyph,\n };\n if (run.color) cell.color = run.color;\n cells.set(`${x},${run.y}`, cell);\n }\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 (const cell of cells.values()) {\n const span = document.createElement(\"span\");\n span.setAttribute(\"aria-hidden\", \"true\");\n span.style.position = \"absolute\";\n span.style.left = `calc(${cell.x} * var(--mw-cw))`;\n span.style.top = `calc(${cell.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 (cell.color) span.style.color = cell.color;\n span.textContent = cell.glyph;\n layer.appendChild(span);\n }\n}\n","import { pxToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack, zeroInsets } from \"./types.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport type {\n AlignItems,\n BorderStyle,\n CellLength,\n CellMetrics,\n CellStyle,\n Display,\n GapRule,\n GridArea,\n GridAreas,\n GridAutoFlow,\n GridLine,\n GridTemplate,\n Insets,\n JustifyContent,\n PerSide,\n Position,\n Size,\n SizeLimit,\n TableRole,\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 warnAuthoredFontSize(el, classAttr, inlineStyle);\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 || TABLE_DISPLAY_FALLBACK[el.tagName] || \"\";\n const tableRole: TableRole = TABLE_ROLES[rawDisplay] ?? \"none\";\n const display: Display =\n rawDisplay === \"flex\" || rawDisplay === \"inline-flex\"\n ? \"flex\"\n : rawDisplay === \"grid\" || rawDisplay === \"inline-grid\"\n ? \"grid\"\n : rawDisplay === \"table\" || rawDisplay === \"inline-table\"\n ? \"table\"\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 let tableLayout: \"auto\" | \"fixed\" = \"auto\";\n let borderCollapse = false;\n let borderSpacingX = 0;\n let borderSpacingY = 0;\n if (display === \"table\") {\n tableLayout = cs.tableLayout === \"fixed\" ? \"fixed\" : \"auto\";\n borderCollapse = cs.borderCollapse === \"collapse\";\n if (!borderCollapse) {\n // Computed form is \"Xpx\" or \"Xpx Ypx\" (horizontal first, per CSS).\n const parts = cs.borderSpacing.split(\" \");\n borderSpacingX = pxToCells(parseFloat(parts[0] ?? \"\") || 0, rootFontSizePx);\n borderSpacingY = pxToCells(parseFloat(parts[1] ?? parts[0] ?? \"\") || 0, rootFontSizePx);\n }\n }\n\n const style: CellStyle = {\n display,\n tableRole,\n tableLayout,\n borderCollapse,\n borderSpacingX,\n borderSpacingY,\n captionSide: cs.captionSide === \"bottom\" ? \"bottom\" : \"top\",\n // Cells and atomic-inline candidates; the rest never consume it.\n verticalAlign:\n tableRole === \"cell\" || rawDisplay.startsWith(\"inline-\")\n ? readVerticalAlign(el, cs)\n : \"start\",\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, inlineStyle, 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 fontWeight: cs.fontWeight,\n fontStyle: cs.fontStyle,\n textDecorationLine: cs.textDecorationLine,\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 // The forced-start rule is measuring-gated, so the computed value is\n // the authored one (no echo); the legacy `align` attribute surfaces\n // as `-webkit-center`/`-moz-center`. Inherited centering blocks each\n // descendant individually — same net effect as CSS inheritance.\n textAlignBlocked: authoredTextAlignBlocked(el, cs),\n textAlign: cs.textAlign === \"right\" || cs.textAlign === \"end\" ? \"end\" : \"start\",\n zIndex: cs.zIndex === \"auto\" || cs.zIndex === \"\" ? null : Number(cs.zIndex) || 0,\n latticeBorder: null,\n ruleX: display === \"flex\" || display === \"grid\" ? readGapRule(cs, \"x\") : null,\n ruleY: display === \"flex\" || display === \"grid\" ? readGapRule(cs, \"y\") : null,\n };\n applyBorderCollapse(style, cs);\n return style;\n}\n\n/** Collapsed-table participants surrender their borders to the lattice\n * (`border-collapse` inherits, so each element knows on its own); the\n * table also drops its padding, per CSS 2.1 (specs/table.md). */\nfunction applyBorderCollapse(style: CellStyle, cs: CSSStyleDeclaration): void {\n if (cs.borderCollapse !== \"collapse\") return;\n const participates =\n style.display === \"table\" ||\n style.tableRole === \"cell\" ||\n style.tableRole === \"row\" ||\n style.tableRole === \"row-group\" ||\n style.tableRole === \"header-group\" ||\n style.tableRole === \"footer-group\";\n if (!participates) return;\n style.latticeBorder = {\n width: style.border,\n style: style.borderStyle,\n color: style.borderColor,\n hidden: {\n top: cs.borderTopStyle === \"hidden\",\n right: cs.borderRightStyle === \"hidden\",\n bottom: cs.borderBottomStyle === \"hidden\",\n left: cs.borderLeftStyle === \"hidden\",\n },\n };\n style.border = zeroInsets();\n if (style.display === \"table\") style.padding = zeroInsets();\n}\n\nfunction isClipping(value: string): boolean {\n return value === \"hidden\" || value === \"clip\";\n}\n\n/** Tag → display fallback for environments whose getComputedStyle\n * returns \"\" for UA-styled table elements (happy-dom); real browsers\n * always resolve a computed display. */\nconst TABLE_DISPLAY_FALLBACK: Record<string, string> = {\n TABLE: \"table\",\n THEAD: \"table-header-group\",\n TBODY: \"table-row-group\",\n TFOOT: \"table-footer-group\",\n TR: \"table-row\",\n TD: \"table-cell\",\n TH: \"table-cell\",\n CAPTION: \"table-caption\",\n COL: \"table-column\",\n COLGROUP: \"table-column-group\",\n};\n\nconst TABLE_ROLES: Record<string, TableRole> = {\n \"table-header-group\": \"header-group\",\n \"table-row-group\": \"row-group\",\n \"table-footer-group\": \"footer-group\",\n \"table-row\": \"row\",\n \"table-cell\": \"cell\",\n \"table-caption\": \"caption\",\n \"table-column\": \"column\",\n \"table-column-group\": \"column-group\",\n};\n\n/** Cell block-axis alignment, from the COMPUTED `vertical-align` — the\n * companion's baseline lock is measuring-gated, so the read sees the\n * authored/UA value from any authoring (classes, plain CSS, hints).\n * Only top/middle/bottom apply to cells (CSS 2.1); everything else\n * behaves as baseline, which behaves as `start`. Fallbacks are for\n * environments without presentational hints or UA table styles\n * (happy-dom): the `valign` attribute, then the tag's UA `middle`. */\nfunction readVerticalAlign(el: Element, cs: CSSStyleDeclaration): \"start\" | \"center\" | \"end\" {\n const value =\n cs.verticalAlign ||\n el.getAttribute(\"valign\")?.toLowerCase() ||\n (el.tagName === \"TD\" || el.tagName === \"TH\" ? \"middle\" : \"baseline\");\n if (value === \"top\") return \"start\";\n if (value === \"middle\") return \"center\";\n if (value === \"bottom\") return \"end\";\n return \"start\";\n}\n\n/** Font sizes are locked to the root (cell-model deviation 3); the lock is\n * silent, so surface it once. Detected via class + inline style — the\n * companion stylesheet's `font-size: inherit` hides it from computed style. */\nfunction warnAuthoredFontSize(\n el: Element,\n classAttr: string,\n inlineStyle: CSSStyleDeclaration,\n): void {\n const authored =\n /(?:^|[\\s:.[!])text-(?:xs|sm|base|lg|[2-9]?xl)(?![\\w-])/.test(classAttr) ||\n /(?:^|[\\s:.[!])text-\\[(?:(?:length|size):|[\\d.])/.test(classAttr) ||\n inlineStyle.fontSize !== \"\";\n if (!authored) return;\n warnOnce(\n el,\n \"font-size inside <mono-wind> is ignored — all text shares the host's cell \" +\n \"size. Size the <mono-wind> element itself instead.\",\n );\n}\n\n/** Gap rules from the `--mw-rule-*` mirrors (specs/gap-decorations.md);\n * registered `inherits: false`, so a container only sees its own.\n * Widths use the border scale (1px = 1 cell), like the utilities. */\nfunction readGapRule(cs: CSSStyleDeclaration, axis: \"x\" | \"y\"): GapRule | null {\n const width = roundHalfAwayFromZero(\n parseFloat(cs.getPropertyValue(`--mw-rule-${axis}-width`)) || 0,\n );\n if (width <= 0) return null;\n const color = cs.getPropertyValue(`--mw-rule-${axis}-color`).trim();\n return {\n width,\n style: mapBorderStyle(cs.getPropertyValue(`--mw-rule-${axis}-style`).trim()),\n // Default currentColor, resolved on the CONTAINER (like computed\n // border colors) — decoration spans would otherwise inherit the\n // host's color, not the container's.\n color: color && color !== \"currentcolor\" && color !== \"currentColor\" ? color : cs.color,\n };\n}\n\nfunction authoredTextAlignBlocked(el: Element, cs: CSSStyleDeclaration): boolean {\n if (/center|justify/.test(cs.textAlign)) return true;\n // Hint fallback for environments that don't map `align` (happy-dom).\n const attr = el.getAttribute(\"align\")?.toLowerCase();\n return attr === \"center\" || attr === \"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 inlineStyle: CSSStyleDeclaration,\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 (\n autoClassPattern.test(classAttr) ||\n inlineStyle.getPropertyValue(physical) === \"auto\"\n ) {\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 // Percent utilities must be caught here too: their used px depends on\n // the (pre-neutralization) native layout — badly wrong inside tables.\n const fraction = new RegExp(`(?:^|[\\\\s:.[!])${axis}-(\\\\d+)/(\\\\d+)(?![\\\\w./])`).exec(classAttr);\n if (fraction)\n return { kind: \"percent\", value: (100 * Number(fraction[1])) / Number(fraction[2]) };\n if (new RegExp(`(?:^|[\\\\s:.[!])${axis}-full(?![\\\\w-])`).test(classAttr))\n return { kind: \"percent\", value: 100 };\n const arbitraryPercent = new RegExp(`(?:^|[\\\\s:.[!])${axis}-\\\\[(\\\\d+(?:\\\\.\\\\d+)?)%\\\\]`).exec(\n classAttr,\n );\n if (arbitraryPercent) return { kind: \"percent\", value: Number(arbitraryPercent[1]) };\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 { warnOnce } from \"./warn.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) {\n node.inlineElements = run.inlineElements;\n node.charInline = run.chars.map((_, i) => run.inlineIndex[i] ?? -1);\n }\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 /** Per character: index into `inlineElements` (-1 = direct leaf text). */\n inlineIndex: 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: [], inlineIndex: [], 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 run.inlineIndex.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 color: cs.color,\n fontWeight: cs.fontWeight,\n fontStyle: cs.fontStyle,\n textDecorationLine: cs.textDecorationLine,\n });\n const inlineIndex = run.inlineElements.length - 1;\n for (let i = 0; i < padLeft; i++) {\n run.chars.push(INLINE_PAD);\n run.advances.push(1);\n }\n const start = run.chars.length;\n collectRun(child, childTracking, ctx, run);\n // Chars the recursion added belong to this element unless a deeper\n // one claimed them first.\n for (let i = start; i < run.chars.length; i++)\n if (run.inlineIndex[i] === undefined) run.inlineIndex[i] = inlineIndex;\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 inlineIndex: 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 inlineIndex.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 inlineIndex.push(run.inlineIndex[i] ?? -1);\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 inlineIndex.shift();\n }\n while (chars[chars.length - 1] === \"\\n\") {\n chars.pop();\n advances.pop();\n inlineIndex.pop();\n }\n return { chars, advances, inlineIndex, 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\nfunction warnSkippedRunContent(el: Element): void {\n warnOnce(\n el,\n \"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 );\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 warnOnce(\n el,\n \"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 );\n}\n","import { renderPlainText, renderPlainTextSegments } from \"./plain-text.ts\";\nimport { 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 /* Plain-text mode (the plain-text attribute): a selectable text mirror of the\n * whole render replaces the layered output — the slotted content keeps\n * driving layout invisibly underneath (and stays inert), decorations\n * hide, and one selection copies the art, whitespace included. */\n #plain-text { display: none; position: absolute; inset: 0; margin: 0; font: inherit; line-height: inherit; letter-spacing: inherit; white-space: pre; }\n :host([plain-text]) #plain-text { display: block; }\n :host([plain-text]) #decorations { display: none; }\n :host([plain-text]) slot { visibility: hidden; }\n</style>\n<div id=\"viewport\">\n <div id=\"decorations\" aria-hidden=\"true\"></div>\n <pre id=\"plain-text\"></pre>\n <slot></slot>\n</div>\n`;\n\n// Import-safe outside the browser (SSR, Node scripts using renderPlainText):\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 static observedAttributes = [\"plain-text\"];\n\n #shadow: ShadowRoot;\n #decorations: HTMLElement;\n #plainText: HTMLElement;\n #probe: HTMLElement;\n #resizeObserver: ResizeObserver | null = null;\n #mutationObserver: MutationObserver | null = null;\n #layoutPending = false;\n #cellMetrics: CellMetrics | null = null;\n #lastLayout: LayoutNode | 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 this.#plainText = this.#shadow.getElementById(\"plain-text\") 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 // colspan/rowspan/span are layout inputs too (specs/table.md).\n attributeFilter: [\"class\", \"style\", \"colspan\", \"rowspan\", \"span\"],\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 attributeChangedCallback(): void {\n this.#scheduleLayout();\n }\n\n /** The current render as plain text — the same deterministic mirror\n * the golden tests diff (borders as box-drawing glyphs, text on its\n * grid rows, interior whitespace real, row ends trimmed). Flushes a\n * pending layout so the snapshot is current; empty before the first\n * layout or when the host has no laid-out content. */\n toPlainText(): string {\n // The already-queued rAF will re-run the layout; that's idempotent.\n if (this.#layoutPending) this.#performLayout();\n return this.#lastLayout ? renderPlainText(this.#lastLayout) : \"\";\n }\n\n /** Colored spans, one per same-colored run — the copied text is still\n * exactly `renderPlainText` (spans don't affect the clipboard). */\n #renderPlainTextMirror(root: LayoutNode): void {\n if (!this.hasAttribute(\"plain-text\")) {\n this.#plainText.textContent = \"\";\n return;\n }\n const rows = renderPlainTextSegments(root);\n const fragment = document.createDocumentFragment();\n rows.forEach((segments, index) => {\n if (index > 0) fragment.appendChild(document.createTextNode(\"\\n\"));\n for (const segment of segments) {\n const styled =\n segment.color !== undefined ||\n segment.fontWeight !== undefined ||\n segment.fontStyle !== undefined ||\n segment.textDecorationLine !== undefined;\n if (!styled) {\n fragment.appendChild(document.createTextNode(segment.text));\n continue;\n }\n const span = document.createElement(\"span\");\n if (segment.color !== undefined) span.style.color = segment.color;\n if (segment.fontWeight !== undefined) span.style.fontWeight = segment.fontWeight;\n if (segment.fontStyle !== undefined) span.style.fontStyle = segment.fontStyle;\n if (segment.textDecorationLine !== undefined)\n span.style.textDecoration = segment.textDecorationLine;\n span.textContent = segment.text;\n fragment.appendChild(span);\n }\n });\n this.#plainText.replaceChildren(fragment);\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.#plainText.textContent = \"\";\n this.#lastLayout = null;\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 this.#lastLayout = virtualRoot;\n this.#renderPlainTextMirror(virtualRoot);\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"],"mappings":"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"}
|