monowind 0.2.6 → 0.2.7
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/README.md +12 -0
- package/dist/cdn.js +65 -43
- package/dist/cdn.js.map +1 -1
- package/dist/element.d.ts.map +1 -1
- package/dist/focus.d.ts +39 -0
- package/dist/focus.d.ts.map +1 -0
- package/dist/index.js +1428 -1201
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/paint.d.ts.map +1 -1
- package/dist/plain-text.d.ts +14 -4
- package/dist/plain-text.d.ts.map +1 -1
- package/dist/pointer.d.ts +6 -1
- package/dist/pointer.d.ts.map +1 -1
- package/dist/selection.d.ts +11 -0
- package/dist/selection.d.ts.map +1 -1
- package/dist/style.d.ts +9 -1
- package/dist/style.d.ts.map +1 -1
- package/dist/tree.d.ts +7 -0
- package/dist/tree.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/styles.css +23 -9
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/animate.ts","../src/glyphs.ts","../src/warn.ts","../src/leaf.ts","../src/borders.ts","../src/metrics.ts","../src/wrap.ts","../src/flex.ts","../src/types.ts","../src/grid.ts","../src/multicol.ts","../src/table.ts","../src/positioning.ts","../src/layout.ts","../src/plain-text.ts","../src/pointer.ts","../src/selection.ts","../src/paint.ts","../src/render.ts","../src/style.ts","../src/tree.ts","../src/element.ts"],"sourcesContent":["/**\n * Engine-synthesized transitions for lock-owned properties\n * (specs/cell-model.md \"Animation\"). `background-color` has no native\n * timeline to sample — the companion locks the light DOM's bg\n * transparent so it can't cover the grid, so the authored value only\n * exists in measuring snapshots. When a read sees the value change on\n * an element whose authored `transition` covers background-color, the\n * engine runs the fade itself: same duration, delay, and easing,\n * interpolating in OKLAB (CSS's interpolation space for non-legacy\n * pairs; legacy rgb pairs interpolate in sRGB, per css-color-4).\n *\n * Two-phase because of the measuring override: reads happen under\n * `[measuring]`, where the companion forces `transition-property` to\n * the sampled set — so the CHANGE is recorded during the read\n * (`trackBackground`), and the authored config is resolved at the end\n * of the layout pass (`resolvePendingTransitions`), after the settling\n * flush restores the authored `transition-property` list.\n */\n\ninterface Rgba {\n r: number; // 0..1, sRGB\n g: number;\n b: number;\n a: number;\n legacy: boolean; // rgb()/transparent — pairs of these lerp in sRGB\n}\n\ninterface SynthesizedTransition {\n from: Rgba;\n to: Rgba;\n toValue: string;\n start: number; // performance.now() + delay\n duration: number;\n easing: (t: number) => number;\n}\n\nconst lastBackground = new WeakMap<Element, string>();\nconst pending: { el: Element; from: string; to: string }[] = [];\n// A Map, not a WeakMap: hasSynthesizedTransitions must sweep entries\n// whose element left the tree (or whose fade expired unsampled, e.g.\n// hidden mid-fade) — otherwise a stray entry would pin the sampling\n// loop to its 30s safety valve. The sweep bounds the strong refs.\nconst active = new Map<Element, SynthesizedTransition>();\n\n/**\n * Called from the style reader with the freshly read background-color\n * (empty string when unset). Returns the value layout should USE: the\n * in-flight interpolation when a synthesized transition is running,\n * the previous value when a change was just detected on an element\n * that MIGHT transition (the fade or a corrective repaint follows next\n * frame — see resolvePendingTransitions), or the value itself. The\n * might-transition check reads `transition-duration`, which the\n * measuring override does NOT mask — an element with no transition at\n * all must paint its new background THIS pass, never a stale one.\n */\nexport function trackBackground(el: Element, value: string, cs: CSSStyleDeclaration): string {\n const previous = lastBackground.get(el);\n lastBackground.set(el, value);\n const running = active.get(el);\n if (running) {\n if (value !== running.toValue) {\n // Retargeted mid-flight: restart from the current interpolated\n // color on the next resolve.\n const from = sampleColor(running);\n active.delete(el);\n pending.push({ el, from, to: value });\n return from;\n }\n const sampled = sampleColor(running);\n if (sampled === running.toValue) active.delete(el);\n return sampled;\n }\n if (\n previous !== undefined &&\n previous !== value &&\n cs.transitionDuration.split(\",\").some((duration) => parseFloat(duration) > 0)\n ) {\n pending.push({ el, from: previous, to: value });\n return previous;\n }\n return value;\n}\n\n/** Arm this host's pending fades — call with `[measuring]` and\n * `[settling]` OFF (and every lock snap-back already committed under\n * the mask), so the authored `transition-property` list is readable\n * and the reads here start nothing. Changes whose config doesn't cover\n * background-color snap: they were painted STALE this pass\n * (trackBackground returned the previous value), so the caller must\n * schedule one corrective relayout whenever this returns true. Other\n * hosts' pends stay queued for their own layouts. */\nexport function resolvePendingTransitions(host: Element): boolean {\n let hadPending = false;\n for (let i = pending.length - 1; i >= 0; i--) {\n const { el, from, to } = pending[i]!;\n // A disconnected element's pend is dead no matter whose it was —\n // drop it here so a torn-down host can't grow the queue forever.\n if (!el.isConnected) {\n pending.splice(i, 1);\n continue;\n }\n if (!host.contains(el)) continue;\n pending.splice(i, 1);\n hadPending = true;\n const config = transitionConfigFor(getComputedStyle(el), \"background-color\");\n const fromColor = parseColor(from);\n const toColor = parseColor(to);\n if (!config || !fromColor || !toColor) continue;\n active.set(el, {\n from: fromColor,\n to: toColor,\n toValue: to,\n start: performance.now() + config.delay,\n duration: config.duration,\n easing: config.easing,\n });\n }\n return hadPending;\n}\n\nexport function hasSynthesizedTransitions(): boolean {\n // Sweep entries no read will ever finish: gone elements, and expired\n // fades on elements no longer laid out (a raw read equals toValue by\n // now, so dropping them changes nothing a future read would paint).\n const now = performance.now();\n for (const [el, transition] of active) {\n if (!el.isConnected || now >= transition.start + transition.duration) active.delete(el);\n }\n return active.size > 0;\n}\n\nfunction sampleColor(transition: SynthesizedTransition): string {\n const t = (performance.now() - transition.start) / transition.duration;\n if (t >= 1) return transition.toValue;\n const eased = t <= 0 ? 0 : transition.easing(t);\n return serialize(mix(transition.from, transition.to, eased));\n}\n\n/* === Transition config ================================================ */\n\nconst KEYWORD_EASINGS: Record<string, [number, number, number, number]> = {\n ease: [0.25, 0.1, 0.25, 1],\n \"ease-in\": [0.42, 0, 1, 1],\n \"ease-out\": [0, 0, 0.58, 1],\n \"ease-in-out\": [0.42, 0, 0.58, 1],\n};\n\nfunction transitionConfigFor(\n cs: CSSStyleDeclaration,\n property: string,\n): { duration: number; delay: number; easing: (t: number) => number } | null {\n const properties = cs.transitionProperty.split(\",\").map((p) => p.trim());\n // Per css-transitions, the LAST matching entry wins; shorter value\n // lists repeat to the property list's length.\n let index = -1;\n for (let i = 0; i < properties.length; i++) {\n if (properties[i] === property || properties[i] === \"all\") index = i;\n }\n if (index < 0) return null;\n const nth = (list: string): string => {\n const values = list.split(\",\").map((v) => v.trim());\n return values[index % values.length] ?? \"\";\n };\n const duration = parseSeconds(nth(cs.transitionDuration));\n if (duration <= 0) return null;\n return {\n duration: duration * 1000,\n delay: parseSeconds(nth(cs.transitionDelay)) * 1000,\n easing: parseEasing(nth(cs.transitionTimingFunction)),\n };\n}\n\nfunction parseSeconds(value: string): number {\n const parsed = parseFloat(value);\n if (!Number.isFinite(parsed)) return 0;\n return value.endsWith(\"ms\") ? parsed / 1000 : parsed;\n}\n\nfunction parseEasing(value: string): (t: number) => number {\n if (value === \"linear\") return (t) => t;\n const keyword = KEYWORD_EASINGS[value];\n if (keyword) return cubicBezier(...keyword);\n const bezier = value.match(/^cubic-bezier\\(([^)]+)\\)$/);\n if (bezier) {\n const [x1, y1, x2, y2] = bezier[1]!.split(\",\").map((n) => parseFloat(n));\n if ([x1, y1, x2, y2].every((n) => Number.isFinite(n))) {\n return cubicBezier(x1!, y1!, x2!, y2!);\n }\n }\n // steps() and anything unrecognized: linear is the closest snap-free\n // stand-in.\n return (t) => t;\n}\n\n/** Standard cubic-bezier easing: solve x(u) = t for u by bisection,\n * return y(u). Whole-cell output makes sub-ms precision pointless. */\nfunction cubicBezier(x1: number, y1: number, x2: number, y2: number): (t: number) => number {\n const coord = (a: number, b: number, u: number): number =>\n 3 * a * u * (1 - u) * (1 - u) + 3 * b * u * u * (1 - u) + u * u * u;\n return (t) => {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (coord(x1, x2, mid) < t) lo = mid;\n else hi = mid;\n }\n return coord(y1, y2, (lo + hi) / 2);\n };\n}\n\n/* === Color math ======================================================= */\n\nfunction parseColor(value: string): Rgba | null {\n if (value === \"\" || value === \"transparent\") return { r: 0, g: 0, b: 0, a: 0, legacy: true };\n let match = value.match(/^rgba?\\(([^)]+)\\)$/);\n if (match) {\n const parts = match[1]!.split(/[\\s,/]+/).map((n) => parseFloat(n));\n if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;\n return {\n r: parts[0]! / 255,\n g: parts[1]! / 255,\n b: parts[2]! / 255,\n a: parts[3] ?? 1,\n legacy: true,\n };\n }\n match = value.match(/^color\\(srgb ([^)]+)\\)$/);\n if (match) {\n const parts = match[1]!.split(/[\\s/]+/).map((n) => parseFloat(n));\n if (parts.length < 3 || parts.slice(0, 3).some((n) => !Number.isFinite(n))) return null;\n return { r: parts[0]!, g: parts[1]!, b: parts[2]!, a: parts[3] ?? 1, legacy: false };\n }\n match = value.match(/^okl(ch|ab)\\(([^)]+)\\)$/);\n if (match) {\n const polar = match[1] === \"ch\";\n const parts = match[2]!\n .replaceAll(\"none\", \"0\")\n .split(/[\\s/]+/)\n .map((n) => parseFloat(n));\n if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;\n const [l, c1, c2] = parts as [number, number, number];\n const a = polar ? c1 * Math.cos((c2 * Math.PI) / 180) : c1;\n const b = polar ? c1 * Math.sin((c2 * Math.PI) / 180) : c2;\n return { ...oklabToSrgb(l, a, b), a: parts[3] ?? 1, legacy: false };\n }\n return null;\n}\n\nfunction mix(from: Rgba, to: Rgba, t: number): Rgba {\n // Premultiplied-alpha interpolation (a transparent endpoint keeps the\n // other's chromaticity), in OKLAB unless both endpoints are legacy\n // sRGB (css-color-4 interpolation rules).\n const a = from.a + (to.a - from.a) * t;\n const lerp = (x: number, y: number): number => {\n const premixed = x * from.a + (y * to.a - x * from.a) * t;\n return a === 0 ? 0 : premixed / a;\n };\n if (from.legacy && to.legacy) {\n return { r: lerp(from.r, to.r), g: lerp(from.g, to.g), b: lerp(from.b, to.b), a, legacy: true };\n }\n const f = srgbToOklab(from.r, from.g, from.b);\n const o = srgbToOklab(to.r, to.g, to.b);\n const rgb = oklabToSrgb(lerp(f.l, o.l), lerp(f.a, o.a), lerp(f.b, o.b));\n return { ...rgb, a, legacy: false };\n}\n\nfunction serialize(color: Rgba): string {\n const channel = (c: number): number => Math.round(Math.min(1, Math.max(0, c)) * 255);\n const alpha = Math.round(Math.min(1, Math.max(0, color.a)) * 1000) / 1000;\n return `rgba(${channel(color.r)}, ${channel(color.g)}, ${channel(color.b)}, ${alpha})`;\n}\n\nfunction linearize(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\nfunction delinearize(c: number): number {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;\n}\n\nfunction srgbToOklab(r: number, g: number, b: number): { l: number; a: number; b: number } {\n const lr = linearize(r);\n const lg = linearize(g);\n const lb = linearize(b);\n const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n return {\n l: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n };\n}\n\nfunction oklabToSrgb(l: number, a: number, b: number): { r: number; g: number; b: number } {\n const l3 = Math.pow(l + 0.3963377774 * a + 0.2158037573 * b, 3);\n const m3 = Math.pow(l - 0.1055613458 * a - 0.0638541728 * b, 3);\n const s3 = Math.pow(l - 0.0894841775 * a - 1.291485548 * b, 3);\n return {\n r: delinearize(4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3),\n g: delinearize(-1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3),\n b: delinearize(-0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3),\n };\n}\n","import type { BorderStyle } from \"./types.ts\";\n\n/**\n * Border glyph sets (specs/theming.md): the rendering vocabulary\n * border STYLES resolve through — what the themed \"hardware\" can\n * draw. Orthogonal to styles: authors keep writing `border-double`;\n * the active set decides its glyphs (`╔═╗`, `+=+`, or a single-line\n * downgrade). Selected per decoration OWNER via the inherited\n * `--mw-border-glyphs` custom property; the property carries only a\n * NAME — tables live here. Fallback is PER GLYPH: a set may override\n * only corners and inherit everything else from the defaults.\n */\n\n/** One style's glyph overrides, by role. Roles cover the engine's\n * full junction vocabulary (lines, four corners, four tees, cross);\n * every field optional. */\nexport interface GlyphTable {\n h?: string;\n v?: string;\n tl?: string;\n tr?: string;\n bl?: string;\n br?: string;\n /** `┴` — arms up, left, right. */\n teeUp?: string;\n /** `┬` — arms down, left, right. */\n teeDown?: string;\n /** `┤` — arms up, down, left. */\n teeLeft?: string;\n /** `├` — arms up, down, right. */\n teeRight?: string;\n /** `┼` — all four arms. */\n cross?: string;\n /** Scrollbar gutter ink (specs/scrolling.md); defaults `░` / `█`. */\n scrollTrack?: string;\n scrollThumb?: string;\n}\n\nexport type BorderGlyphSet = Partial<Record<BorderStyle, GlyphTable>>;\n\nconst sets = new Map<string, BorderGlyphSet>();\nconst listeners = new Set<() => void>();\n\n/** Register (or last-wins replace, with a warning) a glyph set.\n * Connected hosts relayout — the shared post-hoc-registration idiom. */\nexport function registerBorderGlyphs(name: string, set: BorderGlyphSet): void {\n const key = name.toLowerCase().trim();\n if (sets.has(key)) {\n console.warn(`[monowind] registerBorderGlyphs: replacing \"${key}\" (last registration wins).`);\n }\n sets.set(key, set);\n for (const listener of listeners) listener();\n}\n\n/** Resolve a `--mw-border-glyphs` value to a set — once per\n * decoration owner, then passed into the glyph primitives. Unknown or\n * empty names (headless environments read \"\") mean the built-in\n * defaults. */\nexport function glyphSetFor(name: string | null | undefined): BorderGlyphSet | undefined {\n if (!name) return undefined;\n return sets.get(name.toLowerCase().trim());\n}\n\n/** Host subscription to registrations; returns the unsubscriber. */\nexport function onGlyphRegistryChange(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\n/** The role a junction bitmask (up 8 / down 4 / left 2 / right 1)\n * plays — stubs (≤1 arm per axis alone) read as plain lines. */\nexport function junctionRole(mask: number): keyof GlyphTable | null {\n switch (mask) {\n case 1:\n case 2:\n case 3:\n return \"h\";\n case 4:\n case 8:\n case 12:\n return \"v\";\n case 5:\n return \"tl\";\n case 6:\n return \"tr\";\n case 9:\n return \"bl\";\n case 10:\n return \"br\";\n case 7:\n return \"teeDown\";\n case 11:\n return \"teeUp\";\n case 13:\n return \"teeRight\";\n case 14:\n return \"teeLeft\";\n case 15:\n return \"cross\";\n default:\n return null; // mask 0: no arms\n }\n}\n\n/* === Junction tables ================================================== */\n\n// Indexed by the up/down/left/right bitmask (8/4/2/1).\nexport const LIGHT_JUNCTIONS = [\n \" \",\n \"─\",\n \"─\",\n \"─\", // no vertical arm\n \"│\",\n \"┌\",\n \"┐\",\n \"┬\",\n \"│\",\n \"└\",\n \"┘\",\n \"┴\",\n \"│\",\n \"├\",\n \"┤\",\n \"┼\",\n];\nexport const DOUBLE_JUNCTIONS = [\n \" \",\n \"═\",\n \"═\",\n \"═\",\n \"║\",\n \"╔\",\n \"╗\",\n \"╦\",\n \"║\",\n \"╚\",\n \"╝\",\n \"╩\",\n \"║\",\n \"╠\",\n \"╣\",\n \"╬\",\n];\n\n/** A full role table read off a junction table — first mask wins per\n * role, so every role resolves to its canonical glyph. */\nfunction tableFrom(junctions: readonly string[]): GlyphTable {\n const table: GlyphTable = {};\n for (let mask = 1; mask < 16; mask++) {\n const role = junctionRole(mask);\n if (role && !(role in table)) table[role] = junctions[mask]!;\n }\n return table;\n}\n\n/** Every role drawn with one glyph, for sets with no junction geometry. */\nconst uniformTable = (glyph: string): GlyphTable =>\n tableFrom(Array.from({ length: 16 }, () => glyph));\n\n/* === Built-in sets ==================================================== */\n\n// `default` needs no table — an unresolved set falls through to the\n// engine's built-in glyphs everywhere.\nregisterBorderGlyphs(\"default\", {});\n\n// PETSCII/C64 flavor: solid corners become arcs; everything else keeps\n// the defaults (dashed/dotted corners stay square — the arc glyphs\n// exist only in the light-solid weight).\nregisterBorderGlyphs(\"rounded\", {\n solid: { tl: \"╭\", tr: \"╮\", bl: \"╰\", br: \"╯\" },\n});\n\n// Teletype: 7-bit ASCII only. `double` keeps emphasis via `=`.\nconst asciiTable: GlyphTable = { ...uniformTable(\"+\"), h: \"-\", v: \"|\" };\nregisterBorderGlyphs(\"ascii\", {\n solid: { ...asciiTable, scrollTrack: \"|\", scrollThumb: \"#\" },\n double: { ...asciiTable, h: \"=\" },\n dashed: asciiTable,\n dotted: { ...asciiTable, h: \".\", v: \":\" },\n});\n\nconst lightTable = tableFrom(LIGHT_JUNCTIONS);\n\n// DEC/VT-style terminals drew one line style only: double, dashed,\n// and dotted all downgrade to solid light lines.\nregisterBorderGlyphs(\"single\", {\n double: lightTable,\n dashed: lightTable,\n dotted: lightTable,\n});\n\n// CP437 hardware: double survives, but the dashed/dotted line glyphs\n// don't exist in the codepage (bitmap fonts lack them — a fallback\n// font would break the grid), so they downgrade to solid.\nregisterBorderGlyphs(\"cp437\", { dashed: lightTable, dotted: lightTable });\n\n/** Gutter ink through the owner's set — solid-table roles, defaults\n * `░` / `█` (specs/scrolling.md). */\nexport function scrollGlyphs(set: BorderGlyphSet | undefined): { track: string; thumb: string } {\n return {\n track: set?.solid?.scrollTrack ?? \"\\u2591\",\n thumb: set?.solid?.scrollThumb ?? \"\\u2588\",\n };\n}\n\n// BBS/ANSI-art flavor: CP437 blocks, styles mapped to shade density.\nregisterBorderGlyphs(\"blocks\", {\n solid: uniformTable(\"█\"),\n double: uniformTable(\"█\"),\n dashed: uniformTable(\"▒\"),\n dotted: uniformTable(\"░\"),\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}`, warnSubject(el));\n}\n\n/** The element for a warning: the reference itself in a browser (an\n * inspectable link in DevTools), a one-line description under Node\n * (tests), whose console would print the whole object graph. */\nexport function warnSubject(el: Element): Element | string {\n const node = (globalThis as { process?: { versions?: { node?: string } } }).process?.versions\n ?.node;\n if (!node) return el;\n const id = el.id ? `#${el.id}` : \"\";\n const classes = el.classList.length ? `.${Array.from(el.classList).join(\".\")}` : \"\";\n return `<${el.tagName.toLowerCase()}${id}${classes}>`;\n}\n","import { warnOnce } from \"./warn.ts\";\n\n/**\n * Public leaf-renderer API (specs/leaf-renderers.md): a custom element\n * registers as a GRID LEAF and supplies its own cell content instead\n * of laid-out children — the generalization of what the tree builder\n * special-cases for form controls. `@monowind/ascii` is the first\n * consumer.\n *\n * Stability contract: this surface is public — every future change is\n * ADDITIVE (new optional fields/parameters), per the spec's evolution\n * policy.\n */\n\n/** Per-cell styling for a run — an extensible subset of what the grid\n * paints. Color values are CSS `<color>` strings, vars welcome\n * (`var(--mw-ansi-red)`); they resolve at paint time against the\n * host, so themes restyle content with no re-render. */\nexport interface LeafPaint {\n color?: string;\n backgroundColor?: string;\n fontWeight?: string;\n fontStyle?: string;\n textDecorationLine?: string;\n}\n\n/** One painted span of a content line: cells `[start, end)` of\n * `lines[line]`. */\nexport interface LeafRun {\n line: number;\n start: number;\n end: number;\n paint: LeafPaint;\n}\n\n/** What a renderer returns: preformatted content lines (the leaf's\n * intrinsic width is the longest line, height the line count —\n * white-space styling does not apply to renderer content) plus\n * optional paint runs. */\nexport interface LeafContent {\n lines: string[];\n runs?: LeafRun[];\n}\n\nexport interface LeafRegistration {\n /** Custom-element tag name (must contain a hyphen — built-ins are\n * never claimable). Stored lowercased. */\n tag: string;\n /** SYNCHRONOUS and DOM-read-only; called each layout pass (caching\n * is the renderer's own business). Asynchrony (font loading, …)\n * lives outside: finish the work, then `invalidateLeaves()`. Must\n * also run under happy-dom/Node — `renderPlainText` traverses the\n * same tree. */\n render: (el: Element) => LeafContent;\n /** Attributes whose changes re-render this leaf (merged into the\n * host's mutation-observer filter; `class`/`style` and character\n * data are always observed). */\n observedAttributes?: string[];\n /** The node whose contents a semantic gesture ON the leaf selects\n * (specs/semantic-selection.md) — a shadow transcript that sits\n * under the art, say. Absent: the leaf's light contents. */\n selectionTarget?: (el: Element) => Node | null;\n}\n\nconst leaves = new Map<string, LeafRegistration>();\nconst listeners = new Set<() => void>();\n\n/** Register (or last-wins replace, with a warning) a leaf renderer.\n * Connected hosts relayout, so registration after first paint is\n * safe — the post-hoc-registration idiom every monowind registry\n * shares. */\nexport function registerLeafRenderer(registration: LeafRegistration): void {\n const tag = registration.tag.toLowerCase();\n if (!tag.includes(\"-\")) {\n console.warn(\n `[monowind] registerLeafRenderer: \"${registration.tag}\" is not a custom-element tag name (needs a hyphen); ignored.`,\n );\n return;\n }\n if (leaves.has(tag)) {\n console.warn(\n `[monowind] registerLeafRenderer: replacing existing renderer for <${tag}> (last registration wins).`,\n );\n }\n leaves.set(tag, { ...registration, tag });\n notify();\n}\n\n/** Relayout every connected host — the invalidation hook for leaf\n * content whose inputs changed outside the DOM (a font finished\n * registering, …). Coalesced per frame by the hosts themselves. */\nexport function invalidateLeaves(): void {\n notify();\n}\n\nexport function leafRendererFor(tagName: string): LeafRegistration | undefined {\n return leaves.get(tagName.toLowerCase());\n}\n\n/** The union of every registration's observed attributes — the host\n * extends its MutationObserver filter with these. */\nexport function leafObservedAttributes(): string[] {\n const all = new Set<string>();\n for (const leaf of leaves.values()) {\n for (const attribute of leaf.observedAttributes ?? []) all.add(attribute.toLowerCase());\n }\n return [...all];\n}\n\n/** Host subscription to registry changes (registration or\n * invalidation); returns the unsubscriber. Internal to the engine. */\nexport function onLeafRegistryChange(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\n/** Run a renderer with the spec's error contract: a throw must never\n * break layout — warn once per element and render nothing this pass. */\nexport function renderLeafContent(leaf: LeafRegistration, el: Element): LeafContent | null {\n try {\n return leaf.render(el);\n } catch (err) {\n warnOnce(el, `<${leaf.tag}> renderer threw; rendering nothing. ${String(err)}`);\n return null;\n }\n}\n\nfunction notify(): void {\n for (const listener of listeners) listener();\n}\n","import { DOUBLE_JUNCTIONS, LIGHT_JUNCTIONS, glyphSetFor, junctionRole } from \"./glyphs.ts\";\nimport type { BorderGlyphSet } from \"./glyphs.ts\";\nimport type {\n RuleBreak,\n RuleVisibilityItems,\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(\n out,\n style.borderStyle,\n style.borderColor,\n ringRect,\n sides,\n glyphSetFor(style.glyphSet),\n );\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 set?: BorderGlyphSet,\n): void {\n const top = borderGlyphs(styles.top, set);\n const right = borderGlyphs(styles.right, set);\n const bottom = borderGlyphs(styles.bottom, set);\n const left = borderGlyphs(styles.left, set);\n const corner = (a: BorderStyle, b: BorderStyle, pick: (g: Glyphs) => string): string =>\n a === b ? pick(borderGlyphs(a, set)) : pick(borderGlyphs(\"solid\", set));\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/** Whether the child paints in the positioned step (Appendix E step\n * 8+): positioned elements, and flex/grid items with an explicit\n * z-index (z-index applies there per CSS, but `auto` items paint as\n * normal flow, steps 4-7 — source order only decides among them,\n * never over a positioned sibling). */\nexport function paintsInPositionedStep(child: LayoutNode, parent: LayoutNode): boolean {\n return (\n child.style.position !== \"static\" ||\n ((parent.style.display === \"flex\" || parent.style.display === \"grid\") &&\n child.style.zIndex !== null)\n );\n}\n\n/** Children in paint order (CSS 2.1 Appendix E, no floats and sibling\n * stacking only): negative z-index (asc), then non-positioned block,\n * then non-positioned inline, then positioned with z-index >= 0 or\n * auto (asc, auto counts as 0). Stable within a bucket, so DOM order\n * breaks ties. Bucketed instead of full-sorted so the common case\n * (single bucket, no z-index) is allocation-free. */\nexport function paintOrderedChildren(node: LayoutNode): LayoutNode[] {\n if (node.children.length <= 1) return node.children;\n let negatives: LayoutNode[] | null = null;\n let blocks: LayoutNode[] | null = null;\n let inlines: LayoutNode[] | null = null;\n let positioned: LayoutNode[] | null = null;\n for (const child of node.children) {\n if (paintsInPositionedStep(child, node)) {\n if ((child.style.zIndex ?? 0) < 0) (negatives ??= []).push(child);\n else (positioned ??= []).push(child);\n } else if (child.inlineBox) (inlines ??= []).push(child);\n else (blocks ??= []).push(child);\n }\n if (negatives && negatives.length > 1) {\n negatives.sort((a, b) => (a.style.zIndex ?? 0) - (b.style.zIndex ?? 0));\n }\n if (positioned && positioned.length > 1) {\n positioned.sort((a, b) => (a.style.zIndex ?? 0) - (b.style.zIndex ?? 0));\n }\n if (!negatives && blocks && !inlines && !positioned) return blocks;\n if (!negatives && !blocks && inlines && !positioned) return inlines;\n if (!negatives && !blocks && !inlines && positioned) return positioned;\n return [...(negatives ?? []), ...(blocks ?? []), ...(inlines ?? []), ...(positioned ?? [])];\n}\n\n/** A style's straight line glyph, for lattice segments. */\nexport function lineGlyph(style: BorderStyle, axis: \"h\" | \"v\", set?: BorderGlyphSet): string {\n const glyphs = borderGlyphs(style, set);\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. An active glyph SET (specs/theming.md) overrides PER\n * GLYPH by junction role. */\nexport function junctionGlyph(\n style: BorderStyle,\n up: boolean,\n down: boolean,\n left: boolean,\n right: boolean,\n set?: BorderGlyphSet,\n): string {\n const mask = (up ? 8 : 0) | (down ? 4 : 0) | (left ? 2 : 0) | (right ? 1 : 0);\n if (set) {\n const role = junctionRole(mask);\n const override = role && set[style]?.[role];\n if (override) return override;\n }\n const table = style === \"double\" ? DOUBLE_JUNCTIONS : LIGHT_JUNCTIONS;\n return table[mask]!;\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, set?: BorderGlyphSet): Glyphs {\n const j = (up: boolean, down: boolean, left: boolean, right: boolean) =>\n junctionGlyph(style, up, down, left, right, set);\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 { h: \"╌\", v: \"╎\", ...withoutLines(base), ...setLines(set, style) };\n if (style === \"dotted\") return { h: \"┄\", v: \"┊\", ...withoutLines(base), ...setLines(set, style) };\n return base;\n}\n\nfunction withoutLines(glyphs: Glyphs): Omit<Glyphs, \"h\" | \"v\"> {\n const { h: _h, v: _v, ...rest } = glyphs;\n return rest;\n}\n\nfunction setLines(set: BorderGlyphSet | undefined, style: BorderStyle): Partial<Glyphs> {\n const table = set?.[style];\n const lines: Partial<Glyphs> = {};\n if (table?.h) lines.h = table.h;\n if (table?.v) lines.v = table.v;\n return lines;\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. A `half` endpoint is an overlap-join extension\n * tip: its ink reaches only the end cell's centerline, so meeting\n * rules connect there (`┘`) instead of crossing past each other. */\nexport interface RuleSegment {\n bandStart: number;\n bandSize: number;\n start: number;\n end: number;\n startHalf?: boolean;\n endHalf?: boolean;\n}\n\n/** One cross-axis strip of a gap band: the cells beside a crossing\n * track, `[start, end)` along the band, with what borders it. */\nexport interface GapStrip {\n start: number;\n end: number;\n /** An item spans ACROSS the gap here — the gap doesn't exist. */\n spanned: boolean;\n /** The cells on either side of the gap hold items. */\n beforeOccupied: boolean;\n afterOccupied: boolean;\n}\n\nexport interface GapSegment {\n start: number;\n end: number;\n startHalf?: boolean;\n endHalf?: boolean;\n}\n\n/**\n * Split one gap band into painted segments (specs/gap-decorations.md\n * \"Segments\", probed in Chromium 151): track strips kept per spanning\n * occupancy and rule-visibility-items, crossing-gap strips joined per\n * rule-break, contiguous runs merged, endpoints retracted by the inset.\n */\nexport function ruleBandSegments(\n strips: GapStrip[],\n ruleBreak: RuleBreak,\n visibility: RuleVisibilityItems,\n inset: number | \"overlap-join\",\n): GapSegment[] {\n const covered = strips.map((strip) => {\n if (strip.spanned) return false;\n if (visibility === \"between\") return strip.beforeOccupied && strip.afterOccupied;\n if (visibility === \"around\") return strip.beforeOccupied || strip.afterOccupied;\n return true; // all — and grid's normal\n });\n const pieces: { start: number; end: number; covered: boolean }[] = [];\n for (let i = 0; i < strips.length; i++) {\n pieces.push({ start: strips[i]!.start, end: strips[i]!.end, covered: covered[i]! });\n if (i + 1 < strips.length) {\n const joined =\n ruleBreak === \"intersection\"\n ? false\n : ruleBreak === \"none\"\n ? covered[i]! || covered[i + 1]!\n : covered[i]! && covered[i + 1]!;\n pieces.push({ start: strips[i]!.end, end: strips[i + 1]!.start, covered: joined });\n }\n }\n const segments: GapSegment[] = [];\n for (const piece of pieces) {\n if (!piece.covered) continue;\n const last = segments[segments.length - 1];\n if (last && last.end === piece.start) last.end = piece.end;\n else segments.push({ start: piece.start, end: piece.end });\n }\n if (inset === \"overlap-join\") {\n // Junction endpoints extend into the crossing gap to its centerline\n // (half the gap plus half the crossing rule, probed — Chromium\n // extends whether or not a crossing rule paints there); segments\n // that run through a crossing don't end at its boundary, so the\n // lookups miss them. Cap endpoints stay put, per the spec.\n const startExtension = new Map<number, number>();\n const endExtension = new Map<number, number>();\n for (let i = 0; i + 1 < strips.length; i++) {\n const crossingStart = strips[i]!.end;\n const width = strips[i + 1]!.start - crossingStart;\n if (width <= 0) continue;\n endExtension.set(crossingStart, crossingStart + Math.ceil(width / 2));\n startExtension.set(strips[i + 1]!.start, crossingStart + Math.floor(width / 2));\n }\n return segments.map((segment) => {\n const start = startExtension.get(segment.start);\n const end = endExtension.get(segment.end);\n return {\n start: start ?? segment.start,\n end: end ?? segment.end,\n startHalf: start !== undefined,\n endHalf: end !== undefined,\n };\n });\n }\n return segments\n .map((segment) => ({ start: segment.start + inset, end: segment.end - inset }))\n .filter((segment) => segment.end > segment.start);\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 /** The owning container's resolved glyph set (specs/theming.md). */\n glyphs?: BorderGlyphSet | undefined;\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 startHalf: seg.startHalf === true,\n endHalf: seg.endHalf === true,\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 /** Junction arms come from INK AT CELL BOUNDARIES over the union of\n * segments: a segment through boundary `b`, or full-ending exactly\n * there — a `half` overlap-join tip stops at its cell's centerline\n * and contributes no arm past it (elbows over crosses). */\n const inkAtBoundary = (lines: typeof vLines, width: number, across: number, b: number): boolean =>\n lines.some(\n (l) =>\n across >= l.line &&\n across < l.line + width &&\n ((l.start < b && l.end > b) ||\n (l.end === b && !l.endHalf) ||\n (l.start === b && !l.startHalf)),\n );\n /** Is the cell inside a horizontal segment? (Those cells belong to\n * the horizontal pass, which paints the junctions — no double glyphs.) */\n const insideHorizontal = (x: number, y: number): boolean =>\n hLines.some((l) => y >= l.line && y < l.line + hWidth && x >= l.start && x < l.end);\n\n if (ctx.ruleX) {\n const glyph = lineGlyph(ctx.ruleX.style, \"v\", ctx.glyphs);\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(line.line + t, 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 up = inkAtBoundary(vLines, vWidth, x, y);\n const down = inkAtBoundary(vLines, vWidth, x, y + 1);\n out.push({\n glyph:\n up || down\n ? junctionGlyph(\n allDouble ? \"double\" : \"solid\",\n up,\n down,\n inkAtBoundary(hLines, hWidth, y, x),\n inkAtBoundary(hLines, hWidth, y, x + 1),\n ctx.glyphs,\n )\n : lineGlyph(ctx.ruleY.style, \"h\", ctx.glyphs),\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({\n glyph: junctionGlyph(style, up, down, left, right, ctx.glyphs),\n x,\n y,\n length: 1,\n color,\n });\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 // Glyph ink vs line box: a Range rect spans the font's ascent + descent,\n // which some fonts draw TALLER than their `normal` line box. WebKit\n // fragments columns at ink bottoms, so multicol needs the overhang.\n const range = probe.ownerDocument.createRange();\n range.selectNodeContents(probe);\n const inkOverhang = Math.max(0, range.getBoundingClientRect().height - rect.height);\n return { width: rect.width / 100, height: rect.height, letterSpacing, inkOverhang };\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 /** `text-indent` in cells: reduces the first hard line's usable width\n * (the paint layer offsets that line's x by the same amount). Per CSS,\n * subsequent hard lines (`<br>`-separated) don't re-indent. */\n firstLineIndent?: number | undefined;\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/** A final `\\n` produces no last line box (probed, all engines: `a<br>`\n * is one line, `a<br><br>` two, `<br>` alone one) — drop the empty span\n * it would otherwise create. */\nfunction dropFinalBreakSpan(spans: LineSpan[], text: string): LineSpan[] {\n if (text.endsWith(\"\\n\")) spans.pop();\n return spans;\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 dropFinalBreakSpan(spans, text);\n}\n\nexport function wrapLineSpans(text: string, width: number, options: WrapOptions = {}): LineSpan[] {\n // Empty = nothing but collapsible white space — but a `\\n` is a hard\n // break (a `<br>`), never collapsible. NOT `trim()`, which would also\n // eat NBSP — an NBSP-only leaf still renders a line in the browser.\n if (!/[^ \\t\\r\\f]/.test(text)) return [];\n const spans: LineSpan[] = [];\n let lineStart = 0;\n let indent = options.firstLineIndent ?? 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, indent));\n indent = 0; // Only the very first hard line gets the indent.\n lineStart = i + 1;\n }\n }\n return dropFinalBreakSpan(spans, text);\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 firstLineIndent = 0,\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 // Only the first line box (before the first `lines.push`) is charged\n // the text-indent — subsequent lines get the full width back.\n let lineIndent = Math.max(0, firstLineIndent);\n const availableWidth = () => width - lineIndent;\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 <= availableWidth()) {\n current.end = segEnd;\n advancesSum = candidate;\n } else {\n if (current !== null) {\n lines.push(current);\n lineIndent = 0;\n }\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 (\n fit < segEnd &&\n lineAdvance(segStart, fit + 1, advances, tracking) <= availableWidth()\n )\n fit++;\n if (fit === segEnd || fit === segStart) break;\n lines.push({ start: segStart, end: fit });\n lineIndent = 0;\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 { glyphSetFor } from \"./glyphs.ts\";\nimport { collectGapRuleRuns, ruleBandSegments } from \"./borders.ts\";\nimport type { GapSegment, GapStrip, 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\ninterface FlexLine {\n row: { node: LayoutNode }[];\n}\n\n/** Column-gap x-ranges of one line: the space between adjacent item\n * rects in visual order (whatever gap, justify, and margins produced). */\nfunction lineGapRanges(line: FlexLine, originX: number): { start: number; end: number }[] {\n const rects = line.row.map((item) => item.node.localRect).sort((a, b) => a.x - b.x);\n const ranges: { start: number; end: number }[] = [];\n for (let i = 1; i < rects.length; i++) {\n const start = rects[i - 1]!.x + rects[i - 1]!.width - originX;\n const end = rects[i]!.x - originX;\n if (end > start) ranges.push({ start, end });\n }\n return ranges;\n}\n\n/** Segments of the row-gap band above line `r`: under `rule-break:\n * intersection` the band breaks at the union of the two adjacent lines'\n * column gaps (probed in Chromium — a T from either side counts);\n * otherwise one full-width segment. */\nfunction rowBandSegments(\n node: LayoutNode,\n lines: FlexLine[],\n r: number,\n originX: number,\n innerWidth: number,\n): GapSegment[] {\n if (node.style.ruleBreak !== \"intersection\") return [{ start: 0, end: innerWidth }];\n const crossings = [lines[r - 1]!, lines[r]!]\n .flatMap((line) => lineGapRanges(line, originX))\n .sort((a, b) => a.start - b.start);\n // Item strips (the complement of the merged crossings) feed the shared\n // segmenter; every strip is plain occupied track.\n const occupiedStrip = (start: number, end: number): GapStrip => ({\n start,\n end,\n spanned: false,\n beforeOccupied: true,\n afterOccupied: true,\n });\n const strips: GapStrip[] = [];\n let cursor = 0;\n for (const crossing of crossings) {\n if (crossing.start > cursor) strips.push(occupiedStrip(cursor, crossing.start));\n cursor = Math.max(cursor, crossing.end);\n }\n if (cursor < innerWidth) strips.push(occupiedStrip(cursor, innerWidth));\n return ruleBandSegments(\n strips,\n \"intersection\",\n \"all\",\n node.style.ruleInset === \"overlap-join\" ? \"overlap-join\" : 0,\n );\n}\n\nexport function insetSegments(\n segments: RuleSegment[],\n inset: number | \"overlap-join\",\n): RuleSegment[] {\n if (typeof inset !== \"number\" || inset <= 0) return segments;\n return segments\n .map((segment) => ({ ...segment, start: segment.start + inset, end: segment.end - inset }))\n .filter((segment) => segment.end > segment.start);\n}\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's cross size IS a definite inner height (css-flexbox §9.4.8 —\n // stretched items shrink to it, content overflowing), and stretches to\n // a min-height floor so items-center / items-end have the enforced size\n // to align against. A wrap-enabled (\"multi-line\", per CSS — even with\n // one line) container distributes bounded leftover cross space per\n // `align-content`: `stretch` grows the lines; the other keywords offset\n // 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 (definiteInnerHeight !== undefined) rowHeights[0] = definiteInnerHeight;\n else if (Number.isFinite(innerHeight))\n 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) takes the row's\n // height — grown or shrunk (`min-height: auto` is 0 in the cross\n // axis; content overflows). Re-run layoutNode with the height forced\n // so nested content that depends on the parent's height sees it.\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 for (const gap of lineGapRanges(lines[r]!, originX)) {\n vertical.push({\n bandStart: gap.start,\n bandSize: gap.end - gap.start,\n start: top,\n end: top + rowHeights[r]!,\n });\n }\n if (r > 0) {\n const prevBottom = lineOffsets[r - 1]! + (r - 1) * gapY + rowHeights[r - 1]!;\n if (top > prevBottom) {\n for (const segment of rowBandSegments(node, lines, r, originX, innerWidth)) {\n horizontal.push({ bandStart: prevBottom, bandSize: top - prevBottom, ...segment });\n }\n }\n }\n }\n // `normal` behaves as `none` in flex and visibility-items is\n // grid/multicol-only (css-gaps), so beyond intersection breaks the\n // bands only honor rule-inset (specs/gap-decorations.md \"Segments\").\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(node.style.glyphSet),\n ruleX: node.style.ruleX,\n ruleY: node.style.ruleY,\n vertical: insetSegments(vertical, node.style.ruleInset),\n horizontal: insetSegments(horizontal, node.style.ruleInset),\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.y === \"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), retracted by rule-inset.\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 glyphs: glyphSetFor(node.style.glyphSet),\n ruleX: null,\n ruleY: node.style.ruleY,\n vertical: [],\n horizontal: insetSegments(horizontal, node.style.ruleInset),\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.x === \"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\" | \"multicol\" | \"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\";\n/** Per-axis overflow state. `hidden` reads as `\"clip\"` (no scroll\n * container, cheaper — the precise semantic for what the engine\n * does); `auto` and `scroll` are both scroll containers\n * (`scrollsAxis`), differing only in the gutter — `scroll` reserves\n * it always, `auto` only once content overflows. */\nexport type OverflowAxis = \"visible\" | \"clip\" | \"auto\" | \"scroll\";\n\nexport function scrollsAxis(axis: OverflowAxis): boolean {\n return axis === \"auto\" || axis === \"scroll\";\n}\nexport interface Overflow {\n x: OverflowAxis;\n y: OverflowAxis;\n}\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. */\n/** One run of a leaf's character → source map (see `LayoutNode.charSource`). */\nexport interface CharSourceRun {\n index: number;\n length: number;\n node: Text;\n offset: number;\n}\n\nexport interface InheritedTracks {\n positions: number[];\n sizes: number[];\n gapBefore: number[];\n gap: number;\n}\n\n/** A leaf's atomic inline boxes in MARKER order — the order of its\n * U+FFFC characters, which is document order (`children` is built in\n * document order). Every marker ↔ box pairing (layout widths and line\n * placement, copy splicing, boundary points inside a box) reads it here\n * and nowhere else. */\nexport function inlineBoxesOf(node: LayoutNode): LayoutNode[] {\n return node.children.filter((child) => child.inlineBox);\n}\n\n/** The gutter band each axis's bar occupies when reserved\n * (specs/scrolling.md): the bar's thickness plus the perpendicular\n * inset that moves it inward — the rightmost columns for y, the\n * bottom rows for x. */\nexport function scrollGutterBands(style: CellStyle): { right: number; bottom: number } {\n return {\n right: style.scrollbarSize.y + style.scrollbarInset.x,\n bottom: style.scrollbarSize.x + style.scrollbarInset.y,\n };\n}\n\n/** The gutters an explicit `scroll` axis reserves unconditionally\n * (specs/scrolling.md). Folded into padding wherever padding cells\n * are derived, so content-box math, intrinsic sizes, and the native\n * overlay (--mw-p*) agree. `auto` axes reserve only on overflow, in\n * layoutNode's second pass — never here. */\nexport function scrollGutter(style: CellStyle): { right: number; bottom: number } {\n if (style.scrollbarWidth === \"none\") return { right: 0, bottom: 0 };\n const bands = scrollGutterBands(style);\n return {\n right: style.overflow.y === \"scroll\" ? bands.right : 0,\n bottom: style.overflow.x === \"scroll\" ? bands.bottom : 0,\n };\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/** Where rule segments break at gap intersections (css-gaps-1\n * rule-break; specs/gap-decorations.md \"Segments\"). */\nexport type RuleBreak = \"none\" | \"normal\" | \"intersection\";\n\n/** Which segments paint next to empty grid areas (css-gaps-1\n * rule-visibility-items; `normal` acts as `all` in grid). */\nexport type RuleVisibilityItems = \"normal\" | \"all\" | \"around\" | \"between\";\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 /** `scrollbar-width: none` suppresses the gutter and bar entirely;\n * `thin` and `auto` both defer to `scrollbarSize`\n * (specs/scrolling.md). */\n scrollbarWidth: \"auto\" | \"none\";\n /** Bar thickness in cells per axis — `x` the horizontal bar's\n * height, `y` the vertical bar's width (`--mw-scrollbar-size-x/y`,\n * the scrollbar-*, scrollbar-x-*, scrollbar-y-* utilities; default\n * 1). */\n scrollbarSize: { x: number; y: number };\n /** Cells kept clear around the bars for the author's arrow buttons\n * (`--mw-scrollbar-inset-x/y`, the scrollbar-inset-* utilities;\n * default 0; specs/scrolling.md). */\n scrollbarInset: { x: number; y: number };\n /** `scrollbar-color` thumb/track ink; `null` = currentColor pair. */\n scrollbarColor: { thumb: string; track: string } | null;\n /** Per-axis `overscroll-behavior`: whether a boundary gesture may\n * CHAIN to an ancestor scroller (the grid-mode wheel router's\n * gesture-start decision; the native path honors it natively). */\n overscroll: { x: boolean; y: boolean };\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 /** `bg-clear` marker (`--mw-bg-clear: 1`): occlude ancestor decoration\n * glyphs under this element's border box WITHOUT painting a bg color.\n * `backgroundColor` stays undefined; the renderer fills with plain\n * spaces instead of colored spaces. */\n backgroundClear: boolean;\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 `justify` — forced back to `start` (its\n * extra per-line word spacing is fractional). See cell-model spec. */\n textAlignBlocked: boolean;\n /** Computed text-align, normalized LTR. `end` offsets each line by\n * W − line, `center` by floor((W − line) / 2) — whole cells, painted\n * by the grid (the browser's own fractional centering only touches\n * the invisible light-DOM copy). */\n textAlign: \"start\" | \"center\" | \"end\";\n /** First-line indent in cells (per CSS: applies once to the first\n * formatted line of the block; `<br>` doesn't re-indent). Charged\n * against the wrap width of the first line and offsets that line's\n * paint x. Percentages resolve to 0 (unsupported). */\n textIndent: number;\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 /** Effective element opacity input (0..1). Ancestors MULTIPLY down\n * the paint walk (CSS opacity nests, it doesn't inherit); the product\n * rides on every emitted grid span, which composites against the\n * page — translucency blends with what's behind the host, never with\n * covered cells (deviation; front paint wins a cell as always). */\n opacity: number;\n /** The border glyph SET name from `--mw-border-glyphs` (`null` =\n * default) — the theming vocabulary borders/lattices/rules resolve\n * through (specs/theming.md); resolved on the decoration's owner. */\n glyphSet: string | null;\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 ruleBreak: RuleBreak;\n /** Cells retracted from every rule-segment endpoint (rule-inset,\n * quantized like border widths) — or `overlap-join`, which instead\n * extends junction endpoints into the crossing gap so meeting rules\n * connect. */\n ruleInset: number | \"overlap-join\";\n ruleVisibilityItems: RuleVisibilityItems;\n /** Multicol container inputs (specs/multicol.md): authored\n * column-count / column-width (cells), null = auto. A container is\n * multicol (display \"multicol\") when either is set on a block. */\n columnCount: number | null;\n columnWidth: number | null;\n columnFill: \"auto\" | \"balance\";\n /** column-span: all on a child — closes the column row, spans the\n * container's full content width (specs/multicol.md \"Spanners\"). */\n columnSpan: boolean;\n /** Forced column breaks (`break-before/after-column`). */\n breakBeforeColumn: boolean;\n breakAfterColumn: boolean;\n /** `break-inside: avoid` / `avoid-column` — a paragraph-flow child\n * fragments as one unbreakable unit (specs/multicol.md). */\n breakInsideAvoid: boolean;\n}\n\nexport interface LayoutNode {\n source: Element;\n style: CellStyle;\n /** In document order (tree.ts): paint-order ties resolve later-wins,\n * and a leaf's atomic inline boxes are in marker order — see\n * `inlineBoxesOf`, the one place that pairing is read. */\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 styling mirrored into the grid (the browser's own\n * ink is transparent-locked). `backgroundColor` fills the run's\n * cells — how a focus-inverted inline link shows its highlight. */\n color: string | undefined;\n backgroundColor: 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 /** Where each character of `text` came from, as runs of consecutive\n * characters (specs/semantic-selection.md): `text[index + k]` is\n * `node.data[offset + k]` for `k < length`. Characters with no source\n * position (`<br>` newlines, inline-box and padding markers) fall\n * between runs; renderer leaves have no map. */\n charSource?: CharSourceRun[];\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 /** A text leaf's ink extent in content cells (widest line, rows) —\n * written by the leaf pass; scrollable-overflow accounting reads it\n * instead of re-wrapping. */\n textExtent?: { width: number; rows: number };\n /** Scroll geometry (specs/scrolling.md), written by layoutNode on\n * containers with a scroll axis: content extent and the derived\n * max offset, both in cells. Absent elsewhere. */\n scrollRange?: { sizeX: number; sizeY: number; maxX: number; maxY: number };\n /** Current scroll offset in cells (paint-time input, written by the\n * element from native scrollTop/scrollLeft; absent = 0/0). */\n scroll?: { x: number; y: number };\n /** The gutter cells this container actually reserved — `scroll`\n * axes always, `auto` axes only when content overflows (the layout\n * second pass). Paint, hit-testing, and thumb drags read THIS, not\n * the style. */\n scrollGutterCells?: { right: number; bottom: 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 /** Fragmented line map of a multicol text leaf (specs/multicol.md):\n * text wrapped at the column width, each line assigned a column and\n * column-local rows. Written by layout; the plain-text renderer reads\n * it back so both place lines identically. A paragraph-flow container\n * carries a spanless one for its rules, height fold, and native\n * column vars; its children carry their own line maps in\n * container-content coordinates. */\n multicolGeometry?: MulticolLeafGeometry;\n /** Paragraph-flow multicol child (specs/multicol.md \"Fragmenting\n * text-leaf children\"): stays IN FLOW in the browser inside the\n * container's native columns so the browser fragments it itself.\n * Carries the engine-resolved margins the companion re-applies\n * quantized. */\n multicolFlow?: NullableInsets;\n /** In-flow multicol SPANNER (specs/multicol.md): a normally laid-out\n * box that stays in the native flow with `column-span: all`, its\n * geometry forced like a laid-out element's. Carries the quantized\n * native margins (`left` = the engine's cross offset). */\n multicolFlowSpan?: NullableInsets;\n}\n\n/** A multicol text leaf's per-line fragmentation. `lineY`/`textY` are\n * COLUMN-local rows; `lineX` is the line's column's content-relative x.\n * Leaf columns are all `columnWidth` wide (the division remainder is\n * folded into the engine-owned right padding so the browser's equal\n * fractional columns land on the same whole cells). */\nexport interface MulticolLeafGeometry {\n spans: { start: number; end: number }[];\n lineY: number[];\n textY: number[];\n lineX: number[];\n totalRows: number;\n columnCount: number;\n columnWidth: number;\n gap: number;\n /** Columns holding at least one line — overflow columns included. */\n columnsUsed: number;\n /** Spanner-split flow: one rule extent per SEGMENT (content-relative\n * rows and its occupied columns); absent = one full-height segment. */\n ruleSegments?: { start: number; end: number; columns: number }[];\n /** Spanner-split flow relies on the NATIVE balancer per segment (the\n * companion keeps `column-fill: balance` and the natural height)\n * instead of the fill-to-computed-height reconstruction. */\n nativeBalance?: boolean;\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 /** How far a glyph's ink extends past the cell's line box, in px\n * (some fonts' ascent + descent exceed their `normal` line box).\n * WebKit breaks columns at ink bottoms, so multicol leaves get this\n * much extra native column height (see styles.css). */\n inkOverhang?: 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: { x: \"visible\", y: \"visible\" },\n scrollbarWidth: \"auto\",\n scrollbarSize: { x: 1, y: 1 },\n scrollbarInset: { x: 0, y: 0 },\n overscroll: { x: true, y: true },\n scrollbarColor: null,\n whiteSpace: \"normal\",\n tabSize: 8,\n lineGap: 0,\n tracking: 0,\n textOverflow: \"clip\",\n color: undefined,\n backgroundColor: undefined,\n backgroundClear: false,\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 textIndent: 0,\n tableRole: \"none\",\n tableLayout: \"auto\",\n borderCollapse: false,\n borderSpacingX: 0,\n borderSpacingY: 0,\n captionSide: \"top\",\n verticalAlign: \"start\",\n glyphSet: null,\n opacity: 1,\n zIndex: null,\n latticeBorder: null,\n ruleX: null,\n ruleY: null,\n ruleBreak: \"normal\",\n ruleInset: 0,\n ruleVisibilityItems: \"normal\",\n columnCount: null,\n columnWidth: null,\n columnFill: \"balance\",\n columnSpan: false,\n breakBeforeColumn: false,\n breakAfterColumn: false,\n breakInsideAvoid: 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 { collectGapRuleRuns, ruleBandSegments } from \"./borders.ts\";\nimport { glyphSetFor } from \"./glyphs.ts\";\nimport type { GapStrip } from \"./borders.ts\";\nimport type { RuleSegment } from \"./borders.ts\";\nimport { percentToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack } from \"./types.ts\";\nimport {\n clampSize,\n isOutOfFlow,\n layoutNode,\n minContentOuterWidth,\n resolveGap,\n resolveLength,\n resolveLimit,\n resolveMargin,\n resolveWidthLimit,\n widthContribution,\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.x === \"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 // an item's max-content block contribution IS its laid-out height; its\n // minimum is the automatic minimum) — or the parent's tracks when this\n // 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.y === \"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 // segmented per placement occupancy, rule-break, rule-visibility-items,\n // and rule-inset (see the spec's \"Segments\" section).\n if (style.ruleX || style.ruleY) {\n const colCount = colSizing.sizes.length;\n const rowCount = rowSizing.sizes.length;\n // occupied[c][r]: a cell holds (part of) an item. crossesCol[g][r]:\n // an item spans across column-gap g (between columns g and g+1)\n // at row r — the gap doesn't exist there; crossesRow likewise.\n const occupied = Array.from({ length: colCount }, () =>\n Array.from({ length: rowCount }, () => false),\n );\n const crossesCol = Array.from({ length: Math.max(0, colCount - 1) }, () =>\n Array.from({ length: rowCount }, () => false),\n );\n const crossesRow = Array.from({ length: Math.max(0, rowCount - 1) }, () =>\n Array.from({ length: colCount }, () => false),\n );\n for (const p of placed.items) {\n for (let c = p.col.start; c < p.col.start + p.col.span && c < colCount; c++) {\n for (let r = p.row.start; r < p.row.start + p.row.span && r < rowCount; r++) {\n occupied[c]![r] = true;\n if (c + 1 < p.col.start + p.col.span && c < colCount - 1) crossesCol[c]![r] = true;\n if (r + 1 < p.row.start + p.row.span && r < rowCount - 1) crossesRow[r]![c] = true;\n }\n }\n }\n const strips = (\n gap: number,\n positions: number[],\n sizes: number[],\n crosses: boolean[][],\n before: (t: number) => boolean,\n after: (t: number) => boolean,\n ): GapStrip[] =>\n positions.map((position, t) => ({\n start: position,\n end: position + sizes[t]!,\n spanned: crosses[gap]?.[t] ?? false,\n beforeOccupied: before(t),\n afterOccupied: after(t),\n }));\n const bandSegments = (\n positions: number[],\n sizes: number[],\n stripsFor: (gap: number) => GapStrip[],\n ): 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) continue;\n for (const segment of ruleBandSegments(\n stripsFor(i - 1),\n style.ruleBreak,\n style.ruleVisibilityItems,\n style.ruleInset,\n )) {\n bands.push({ bandStart, bandSize, ...segment });\n }\n }\n return bands;\n };\n const vertical = bandSegments(colPos, colSizing.sizes, (gap) =>\n strips(\n gap,\n rowPos,\n rowSizing.sizes,\n crossesCol,\n (r) => occupied[gap]?.[r] ?? false,\n (r) => occupied[gap + 1]?.[r] ?? false,\n ),\n );\n const horizontal = bandSegments(rowPos, rowSizing.sizes, (gap) =>\n strips(\n gap,\n colPos,\n colSizing.sizes,\n crossesRow,\n (c) => occupied[c]?.[gap] ?? false,\n (c) => occupied[c]?.[gap + 1] ?? false,\n ),\n );\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(style.glyphSet),\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 // The minimum contribution is the automatic minimum (CSS §11.5.1 /\n // css-sizing): the content height while overflow is visible, 0 for\n // a scroll container — so `fr` rows can shrink one against a cap.\n const min =\n child.style.minHeight === \"auto\" && child.style.overflow.y !== \"visible\"\n ? fixedY(margin)\n : height;\n items.push({ start: p.row.start, span: p.row.span, min, 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// ---------------------------------------------------------------------------\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 { collectGapRuleRuns } from \"./borders.ts\";\nimport { glyphSetFor } from \"./glyphs.ts\";\nimport type { RuleSegment } from \"./borders.ts\";\nimport { insetSegments } from \"./flex.ts\";\nimport {\n blockCrossOffset,\n collapseMargins,\n isOutOfFlow,\n layoutNode,\n leafLineMetrics,\n leafLineSpans,\n resolveGap,\n resolveMargin,\n} from \"./layout.ts\";\nimport type { IntrinsicCache } from \"./layout.ts\";\nimport { wrapLineSpans } from \"./wrap.ts\";\nimport type {\n CellStyle,\n Insets,\n LayoutNode,\n MulticolLeafGeometry,\n NullableInsets,\n} from \"./types.ts\";\n\n/**\n * Multi-column layout (specs/multicol.md): css-multicol §3.4 column\n * resolution in cells, sequential/balanced fill, spanners, and column\n * rules through the gap-decoration pipeline. Direct-text leaves fragment\n * at line granularity; element children distribute atomically. Part of\n * the deliberate layout-module import cycle (see layout.ts).\n */\n\n/** Used column count per css-multicol §3.4, from the computed\n * `column-count`/`column-width` pair. */\nfunction usedColumnCount(style: CellStyle, available: number, gap: number): number {\n const fit =\n style.columnWidth !== null\n ? Math.max(1, Math.floor((available + gap) / (style.columnWidth + gap)))\n : null;\n if (style.columnCount !== null && fit !== null)\n return Math.max(1, Math.min(style.columnCount, fit));\n if (fit !== null) return fit;\n return Math.max(1, style.columnCount ?? 1);\n}\n\n/** Column tracks for an element-children container: base width\n * `floor((available − (count − 1) × gap) / count)` with the remainder\n * distributed one cell per column left to right. */\nexport function resolveColumnTracks(style: CellStyle, available: number, gap: number): number[] {\n const count = usedColumnCount(style, available, gap);\n const base = Math.max(1, Math.floor((available - (count - 1) * gap) / count));\n const leftover = Math.max(0, available - (count * base + (count - 1) * gap));\n return Array.from({ length: count }, (_, i) => base + (i < leftover ? 1 : 0));\n}\n\n/** Max-content inner width: `count × content + (count − 1) × gap` when\n * `column-count` drives the count (probed: all three engines agree);\n * with only `column-width`, the content's own max-content floored at\n * one `W`-wide column (Chromium/WebKit; Firefox clamps to `W` — a\n * documented divergence, specs/multicol.md). */\nexport function multicolIntrinsicInnerWidth(style: CellStyle, contentMax: number): number {\n const gap = Math.max(typeof style.gapX === \"number\" ? style.gapX : 0, style.ruleX?.width ?? 0);\n if (style.columnCount !== null) {\n return style.columnCount * contentMax + (style.columnCount - 1) * gap;\n }\n return Math.max(style.columnWidth ?? 1, contentMax);\n}\n\n/** The column-height restriction (css-multicol §7): the smaller of the\n * definite height and the max-height, either alone, or none. */\nexport function restrictingHeight(\n definite: number | undefined,\n max: number | undefined,\n): number | undefined {\n if (definite === undefined) return max;\n if (max === undefined) return definite;\n return Math.min(definite, max);\n}\n\n/** Smallest `height` in `[lo, hi]` accepted by `fits` (monotonic). */\nfunction minimalHeight(lo: number, hi: number, fits: (height: number) => boolean): number {\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (fits(mid)) hi = mid;\n else lo = mid + 1;\n }\n return lo;\n}\n\n/** Column geometry for a TEXT LEAF: all columns equal at the base width,\n * the remainder reported so layout can fold it into the engine-owned\n * right padding — the browser's equal fractional columns then start on\n * the same whole cells as the engine's. */\nexport function resolveLeafColumns(\n style: CellStyle,\n available: number,\n gap: number,\n): { count: number; width: number; leftover: number } {\n const count = usedColumnCount(style, available, gap);\n const width = Math.max(1, Math.floor((available - (count - 1) * gap) / count));\n const leftover = Math.max(0, available - (count * width + (count - 1) * gap));\n return { count, width, leftover };\n}\n\n/** Whether a rule paints in a gap given which side columns hold content:\n * CSS paints rules only between two columns that both have content\n * (`normal`/`between`); `around` needs either side, `all` always paints\n * (specs/gap-decorations.md item visibility). */\nfunction ruleVisible(\n mode: CellStyle[\"ruleVisibilityItems\"],\n before: boolean,\n after: boolean,\n): boolean {\n if (mode === \"all\") return true;\n if (mode === \"around\") return before || after;\n return before && after;\n}\n\n/**\n * Fragment a multicol text leaf into columns (specs/multicol.md \"Direct\n * text\"): wrap at the column width, then fill columns sequentially into\n * the fill height — every line box spans its own leading (`height +\n * lineGap` rows, the browser's line-box model), and a line never splits\n * across columns. `balance` packs into the minimal height that needs at\n * most `count` columns (clamped to a definite height); `auto` with a\n * definite height fills each column to it, overflow columns catching\n * the rest.\n */\nexport function multicolLeafGeometry(\n node: LayoutNode,\n columns: { count: number; width: number },\n gap: number,\n definiteHeight: number | undefined,\n): MulticolLeafGeometry {\n // Tracked text wraps at `width − tracking`: the browser fits a line\n // into its column COUNTING the phantom trailing letter-spacing gap\n // (probed in all three engines — the single-column carve-out has no\n // per-column equivalent, so the fit rule tightens instead).\n const spans = leafLineSpans(node, Math.max(1, columns.width - node.style.tracking));\n const { heights, textOffsets } = leafLineMetrics(node, spans);\n const lineGap = node.style.lineGap;\n const units = lineUnits(heights.map((h) => h + lineGap));\n\n let height: number;\n if (node.style.columnFill === \"auto\" && definiteHeight !== undefined) {\n height = Math.max(1, definiteHeight);\n } else {\n const balanced = minimalHeight(\n units.reduce((max, unit) => Math.max(max, unit.rows - lineGap), 1),\n Math.max(1, units.reduce((sum, unit) => sum + unit.rows, 0) - lineGap),\n (limit) => fillLineColumns(units, lineGap, limit).columns <= columns.count,\n );\n height =\n definiteHeight !== undefined ? Math.max(1, Math.min(balanced, definiteHeight)) : balanced;\n }\n\n const filled = fillLineColumns(units, lineGap, height);\n return {\n spans,\n lineY: filled.top,\n textY: filled.top.map((top, s) => top + textOffsets[s]!),\n lineX: filled.column.map((c) => c * (columns.width + gap)),\n totalRows: filled.maxUsed,\n columnCount: columns.count,\n columnWidth: columns.width,\n gap,\n columnsUsed: spans.length > 0 ? filled.columns : 0,\n };\n}\n\n/** One unit of a column fill: its rows (line box heights + trailing\n * leading), the collapsed margin rows before it (0 within a child),\n * whether a forced break precedes it, and its line count — an\n * unbreakable `break-inside: avoid` child contributes ONE unit\n * carrying all its lines. */\ninterface FillUnit {\n rows: number;\n pre: number;\n /** Glued trailing rows (a paragraph gap as padding-bottom): counted\n * with the unit at break checks, never trimmed or spilled. */\n post: number;\n forced: boolean;\n lines: number;\n}\n\n/** How `pre` rows behave at a column break (specs/multicol.md):\n * - \"truncate\": a break swallows the margin it lands in (CSS\n * Fragmentation §5.2) — the spanless forced-height reconstruction,\n * where the native gaps ARE margins.\n * - \"glue\": the spanner path, where the companion rewrites each gap as\n * padding-bottom on the PRECEDING paragraph (`post` rows) —\n * Chromium/Firefox keep a trailing padding monolithic with its last\n * line (probed pixel-exact), so the gap sits invisibly at a column\n * bottom and the next paragraph starts flush at the column top, the\n * CSS-truncation look. WebKit instead slice-spills padding across\n * breaks AND adds further in-engine divergences (fractional balance\n * heights, post-spanner segment misplacement), so\n * `detectGluedPreBreak` gates it back to the zero-margin constraint —\n * see the layoutMulticol dispatch. */\ntype PreBreakMode = \"truncate\" | \"glue\";\n\n/** Greedy sequential fill of line units into columns at `limit`:\n * LINE-major columns and top rows. Heights are TIGHT — a column of L\n * lines occupies `Σ(h + lineGap) − lineGap` rows, its last line's\n * trailing leading trimmed like a single-column leaf's (the companion\n * re-extends the native box by `lineGap` so the browser still counts\n * full line boxes). `pre` rows follow `mode` at breaks (see\n * PreBreakMode); the very first margin stays — a multicol container is\n * an independent formatting context, so it never parent-collapses. A\n * multi-line unit too tall for ANY column breaks to a fresh column and\n * then splits greedily (probed: Chromium/Firefox; WebKit instead\n * abandons `avoid` — documented divergence). Drives the balance\n * searches, the final maps, and the public `multicolLines` predictor. */\nfunction fillLineColumns(\n units: FillUnit[],\n lineGap: number,\n limit: number,\n mode: PreBreakMode = \"truncate\",\n): { columns: number; maxUsed: number; column: number[]; top: number[] } {\n let column = 0;\n let used = 0;\n let maxUsed = 0;\n const columnOf: number[] = [];\n const top: number[] = [];\n for (let i = 0; i < units.length; i++) {\n const unit = units[i]!;\n let lead = mode === \"glue\" || i === 0 || used > 0 ? unit.pre : 0;\n // A glued trailing pad is monolithic with its unit: the break check\n // counts it, and it never spills to the next column (probed).\n if (used > 0 && (unit.forced || used + lead + unit.rows + unit.post - lineGap > limit)) {\n if (mode === \"truncate\") lead = 0;\n column += 1;\n used = 0;\n }\n const lineRows = unit.rows / unit.lines;\n if (unit.lines > 1 && unit.rows - lineGap > limit) {\n // Too tall to keep whole: split greedily from the (fresh) column.\n for (let line = 0; line < unit.lines; line++) {\n if (used > 0 && used + lead + lineRows - lineGap > limit) {\n if (mode === \"truncate\") lead = 0;\n column += 1;\n used = 0;\n }\n columnOf.push(column);\n top.push(used + lead);\n used += lead + lineRows;\n lead = 0;\n maxUsed = Math.max(maxUsed, used - lineGap);\n }\n used += unit.post;\n if (unit.post > 0) maxUsed = Math.max(maxUsed, used);\n continue;\n }\n for (let line = 0; line < unit.lines; line++) {\n columnOf.push(column);\n top.push(used + lead + line * lineRows);\n }\n used += lead + unit.rows + unit.post;\n // A column ending in a bare line trims its trailing leading (tight\n // model); a glued pad sits below the FULL line box, untrimmed.\n maxUsed = Math.max(maxUsed, used - (unit.post > 0 ? 0 : lineGap));\n }\n return { columns: column + 1, maxUsed, column: columnOf, top };\n}\n\n/** Margin-less, break-less line units from per-line row heights. */\nfunction lineUnits(rows: number[]): FillUnit[] {\n return rows.map((r) => ({ rows: r, pre: 0, post: 0, forced: false, lines: 1 }));\n}\n\n/** Whether the running browser GLUES a trailing padding to its last\n * line at a column break — measured once from a hidden fixture\n * replaying the probes' distinguishing case: a 3-line paragraph with\n * one row of padding-bottom, then a 2-line one, balanced into 2\n * columns. Glue (Chromium/Firefox) keeps the pad in column 0 and the\n * second paragraph starts flush atop column 1; WebKit slice-spills the\n * pad into column 1, pushing the paragraph a row down. An environment\n * that doesn't lay the fixture out (unit tests) measures nothing and\n * counts as glued. */\nlet detectedGluedPreBreak: boolean | null = null;\nfunction detectGluedPreBreak(): boolean {\n if (detectedGluedPreBreak !== null) return detectedGluedPreBreak;\n // The fixture carries its own fixed geometry (the behavior it probes\n // is font-independent): `row` px per line, one row of padding-bottom,\n // 2 columns of 10 characters.\n const row = 20;\n const fixture = document.createElement(\"div\");\n fixture.style.cssText =\n \"position:absolute;left:-9999px;visibility:hidden;columns:2;column-gap:0;\" +\n `column-fill:balance;width:200px;font:10px/${row}px monospace;orphans:1;widows:1`;\n fixture.innerHTML =\n `<div style=\"margin:0;padding:0 0 ${row}px 0\">aaaaaa aaaaaa aaaaaa</div>` +\n '<div style=\"margin:0\"><span>bbbbbb</span> bbbbbb</div>';\n document.body.appendChild(fixture);\n const fixtureTop = fixture.getBoundingClientRect().top;\n const probe = fixture.querySelector(\"span\")!.getBoundingClientRect();\n fixture.remove();\n // Glued: the second paragraph starts at the column top (offset 0);\n // sliced: the spilled pad pushes it a full row down. Split the\n // difference for sub-pixel robustness.\n detectedGluedPreBreak = !(probe.width > 0 && probe.top - fixtureTop >= row / 2);\n return detectedGluedPreBreak;\n}\n\n/**\n * Predict a multicol TEXT LEAF's fragmentation — the multicol analogue\n * of `wrapLines`, sharing the engine's wrap and fill code so a\n * prediction can never drift from the layout. Returns each line with\n * its column and its TIGHT top row within the column. `restrictingHeight`\n * (the content-box height in rows, e.g. read from a rendered element)\n * reproduces any final layout — sequential fill into the final height\n * IS the layout, whatever fill mode produced it; without it, lines\n * balance into `columnCount` columns.\n */\nexport function multicolLines(\n text: string,\n options: {\n columnWidth: number;\n columnCount: number;\n tracking?: number;\n lineGap?: number;\n restrictingHeight?: number;\n /** `text-indent` charged to the first line (cells). */\n firstLineIndent?: number;\n },\n): { text: string; column: number; top: number }[] {\n const { columnWidth, columnCount, tracking = 0, lineGap = 0, restrictingHeight } = options;\n const advances = tracking > 0 ? Array.from(text, () => 1 + tracking) : undefined;\n const spans = wrapLineSpans(text, Math.max(1, columnWidth - tracking), {\n advances,\n tracking,\n firstLineIndent: options.firstLineIndent,\n });\n const units = lineUnits(spans.map(() => 1 + lineGap));\n const height =\n restrictingHeight ??\n minimalHeight(1, Math.max(1, spans.length * (1 + lineGap) - lineGap), (limit) => {\n return fillLineColumns(units, lineGap, limit).columns <= columnCount;\n });\n const filled = fillLineColumns(units, lineGap, height);\n return spans.map((span, i) => ({\n text: text.slice(span.start, span.end),\n column: filled.column[i]!,\n top: filled.top[i]!,\n }));\n}\n\n/** Column rules for a multicol leaf or paragraph-flow container: one\n * band per gap per SEGMENT (a spanless geometry paints one full-height\n * segment), visibility per the side columns' occupancy. */\nexport function multicolLeafRuleRuns(\n node: LayoutNode,\n geometry: MulticolLeafGeometry,\n border: Insets,\n padding: Insets,\n): void {\n const style = node.style;\n if (!style.ruleX) return;\n const contentWidth =\n geometry.columnCount * geometry.columnWidth + (geometry.columnCount - 1) * geometry.gap;\n const extents = geometry.ruleSegments ?? [\n { start: 0, end: geometry.totalRows, columns: geometry.columnsUsed },\n ];\n const vertical: RuleSegment[] = [];\n for (const extent of extents) {\n const occupied = Math.min(extent.columns, geometry.columnCount);\n for (let g = 0; g < geometry.columnCount - 1; g++) {\n if (!ruleVisible(style.ruleVisibilityItems, g < occupied, g + 1 < occupied)) continue;\n vertical.push({\n bandStart: (g + 1) * geometry.columnWidth + g * geometry.gap,\n bandSize: geometry.gap,\n start: extent.start,\n end: extent.end,\n });\n }\n }\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(style.glyphSet),\n ruleX: style.ruleX,\n ruleY: null,\n vertical: insetSegments(vertical, style.ruleInset),\n horizontal: [],\n contentWidth,\n contentHeight: geometry.totalRows,\n border,\n borderStyle: style.borderStyle,\n borderColor: style.borderColor,\n padding,\n });\n}\n\ninterface MulticolUnit {\n node: LayoutNode;\n margin: NullableInsets;\n breakBefore: boolean;\n}\n\n/** A chrome-less text-leaf child, eligible to fragment at line\n * granularity in a paragraph-flow container (specs/multicol.md\n * \"Fragmenting text-leaf children\"): static block, childless text, no\n * border/padding/background/sizing/span, normal white-space, and the\n * container's own line gap (the native box shares the container's\n * inherited line-height and trailing-leading extension). */\nfunction isFragmentableLeaf(child: LayoutNode, container: CellStyle): boolean {\n const style = child.style;\n const insets = style.padding;\n return (\n child.text !== \"\" &&\n child.children.length === 0 &&\n style.display === \"block\" &&\n style.position === \"static\" &&\n !style.columnSpan &&\n style.whiteSpace === \"normal\" &&\n style.lineGap === container.lineGap &&\n style.border.top === 0 &&\n style.border.right === 0 &&\n style.border.bottom === 0 &&\n style.border.left === 0 &&\n insets.top === 0 &&\n insets.right === 0 &&\n insets.bottom === 0 &&\n insets.left === 0 &&\n style.backgroundColor === undefined &&\n !style.backgroundClear &&\n style.overflow.x === \"visible\" &&\n style.overflow.y === \"visible\" &&\n (style.width === undefined || style.width.kind === \"auto\") &&\n (style.height === undefined || style.height.kind === \"auto\") &&\n (style.minWidth === \"auto\" || style.minWidth === 0 || style.minWidth === undefined) &&\n (style.minHeight === \"auto\" || style.minHeight === 0 || style.minHeight === undefined) &&\n style.maxWidth === undefined &&\n style.maxHeight === undefined\n );\n}\n\n/**\n * Paragraph flow (specs/multicol.md \"Fragmenting text-leaf children\"):\n * every in-flow child is a chrome-less text leaf, so children fragment\n * at line granularity like the container's own direct text. One unit\n * stream drives the fill — each child's wrapped lines as full line\n * boxes, collapsed margins between children, a break truncating any\n * margin it lands in, the column end trimming the trailing leading\n * (tight model). Children keep their per-line maps\n * (`multicolGeometry`, container-content coordinates) and stay IN FLOW\n * in the browser (`multicolFlow`); the container gets a spanless\n * geometry for its rules, height fold, and native column vars.\n * Returns content height (rows used).\n */\nfunction layoutMulticolFlow(\n node: LayoutNode,\n inFlow: LayoutNode[],\n innerWidth: number,\n restriction: number | undefined,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n const gap = resolveGap(style, \"x\", innerWidth);\n const columns = resolveLeafColumns(style, innerWidth, gap);\n padding.right += columns.leftover;\n const lineGap = style.lineGap;\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n const contentWidth = innerWidth - columns.leftover;\n\n // Split the flow into segments at in-flow spanners.\n const segments: LayoutNode[][] = [[]];\n const spannerAfter: (LayoutNode | undefined)[] = [];\n for (const child of inFlow) {\n if (child.style.columnSpan) {\n spannerAfter[segments.length - 1] = child;\n segments.push([]);\n } else {\n segments[segments.length - 1]!.push(child);\n }\n }\n const hasSpanners = segments.length > 1;\n // With spanners the native balancer is trusted, and the companion\n // rewrites inter-paragraph gaps as padding-bottom on the preceding\n // paragraph (margins derail it — see the spec), glued to its last\n // line. No detection needed HERE: the dispatch gate keeps non-glue\n // (WebKit) spanner flow margin-less, and with every gap 0 the two\n // modes are identical. Spanless flow keeps real native margins under\n // a forced height, where breaks truncate them.\n const preBreakMode: PreBreakMode = hasSpanners ? \"glue\" : \"truncate\";\n\n const ruleSegments: { start: number; end: number; columns: number }[] = [];\n let segTop = 0;\n let columnsUsed = 0;\n for (let seg = 0; seg < segments.length; seg++) {\n const paragraphs = segments[seg]!;\n // A segment's last bottom margin: the companion zeroes native\n // paragraph bottoms, so it survives by transfer into the following\n // spanner's top margin — a SUM, per css-multicol §6.1 (spanner\n // margins never collapse with column content).\n let trailingBottom = 0;\n if (paragraphs.length > 0) {\n const children = paragraphs.map((child) => ({\n node: child,\n spans: leafLineSpans(child, Math.max(1, columns.width - child.style.tracking)),\n margin: resolveMargin(child.style.margin, columns.width),\n pre: 0,\n post: 0,\n }));\n const units: FillUnit[] = [];\n let prevBottom: number | null = null;\n let prevChild: (typeof children)[number] | null = null;\n let pendingBreak = false;\n for (const child of children) {\n const { node, spans, margin } = child;\n const gap =\n prevBottom === null ? (margin.top ?? 0) : collapseMargins(prevBottom, margin.top ?? 0);\n // Glue mode rides each inter-paragraph gap as the PRECEDING\n // child's padding-bottom (its last unit's glued `post`); the\n // segment-leading gap, which no break can precede, stays the\n // first child's own padding-top. Truncate mode keeps every gap\n // as the following child's margin (`pre`).\n let pre = gap;\n if (preBreakMode === \"glue\" && prevChild !== null) {\n pre = 0;\n prevChild.post = gap;\n units[units.length - 1]!.post = gap;\n } else {\n child.pre = gap;\n }\n const forced = pendingBreak || node.style.breakBeforeColumn;\n if (node.style.breakInsideAvoid && spans.length > 0) {\n // The whole child is one unbreakable unit (probed: engines\n // keep it whole, or split from a fresh column when too tall).\n units.push({\n rows: spans.length * (1 + lineGap),\n pre,\n post: 0,\n forced,\n lines: spans.length,\n });\n } else {\n for (let s = 0; s < spans.length; s++) {\n units.push({\n rows: 1 + lineGap,\n pre: s > 0 ? 0 : pre,\n post: 0,\n forced: s === 0 && forced,\n lines: 1,\n });\n }\n }\n if (spans.length > 0) {\n prevBottom = margin.bottom ?? 0;\n prevChild = child;\n }\n pendingBreak = node.style.breakAfterColumn;\n }\n trailingBottom = prevBottom ?? 0;\n\n let height: number;\n if (style.columnFill === \"auto\" && restriction !== undefined) {\n height = Math.max(1, restriction);\n } else {\n const balanced = minimalHeight(\n 1,\n Math.max(\n 1,\n fillLineColumns(units, lineGap, Number.POSITIVE_INFINITY, preBreakMode).maxUsed,\n ),\n (limit) => fillLineColumns(units, lineGap, limit, preBreakMode).columns <= columns.count,\n );\n height =\n restriction !== undefined ? Math.max(1, Math.min(balanced, restriction)) : balanced;\n }\n const filled = fillLineColumns(units, lineGap, height, preBreakMode);\n\n for (let c = 0, line = 0; c < children.length; c++) {\n const { node: child, spans, margin, pre, post } = children[c]!;\n const lineY: number[] = [];\n const lineX: number[] = [];\n for (let s = 0; s < spans.length; s++, line++) {\n lineY.push(segTop + filled.top[line]!);\n lineX.push(filled.column[line]! * (columns.width + gap));\n }\n delete child.decorationRuns;\n child.multicolGeometry = {\n spans,\n lineY,\n textY: lineY,\n lineX,\n totalRows: segTop + filled.maxUsed,\n columnCount: columns.count,\n columnWidth: columns.width,\n gap,\n columnsUsed: filled.columns,\n };\n // Spanner containers: the companion reinterprets the vertical\n // gaps as padding (engine-collapsed, so native sibling\n // collapsing can't disagree) — the segment-leading gap as this\n // child's padding-top, each inter-paragraph gap as the\n // PRECEDING child's padding-bottom — see the\n // [data-mw-multicol-balance] child rule.\n child.multicolFlow = hasSpanners\n ? { top: pre, right: margin.right, bottom: post, left: margin.left }\n : margin;\n child.localRect = { x: originX, y: originY, width: contentWidth, height: filled.maxUsed };\n child.resolvedPadding = { top: 0, right: 0, bottom: 0, left: 0 };\n }\n if (units.length > 0) {\n ruleSegments.push({ start: segTop, end: segTop + filled.maxUsed, columns: filled.columns });\n columnsUsed = Math.max(columnsUsed, filled.columns);\n // The browser stacks a non-final segment's columns as FULL line\n // boxes — its trailing leading stays before the spanner.\n segTop += filled.maxUsed + (seg < segments.length - 1 ? lineGap : 0);\n }\n }\n const spanner = spannerAfter[seg];\n if (spanner) {\n // In-flow spanner (css-multicol §6.1, probed): the columns' full\n // extent (the folded content width, so it aligns with the tracks),\n // margins never collapsing with column content, the native\n // balancer handling the segments around it.\n const margin = resolveMargin(spanner.style.margin, contentWidth);\n const marginX = (margin.left ?? 0) + (margin.right ?? 0);\n layoutNode(spanner, Math.max(0, contentWidth - marginX), undefined, 0, 0, \"fill\", cache);\n const cross = blockCrossOffset(margin, contentWidth, spanner.localRect.width);\n const marginTop = (margin.top ?? 0) + trailingBottom;\n segTop += marginTop;\n spanner.localRect = { ...spanner.localRect, x: originX + cross, y: originY + segTop };\n spanner.multicolFlowSpan = {\n top: marginTop,\n right: 0,\n bottom: margin.bottom ?? 0,\n left: cross,\n };\n segTop += spanner.localRect.height + (margin.bottom ?? 0);\n }\n }\n const totalRows = segTop;\n\n for (const child of node.children) {\n if (!isOutOfFlow(child.style)) continue;\n const margin = resolveMargin(child.style.margin, innerWidth);\n child.staticSlot = {\n kind: \"block\",\n x: originX + (margin.left ?? 0),\n y: originY + (margin.top ?? 0),\n };\n }\n // Spanless container geometry: drives the column rules and the\n // vertical-slack fold in layoutNode, and the native column vars.\n node.multicolGeometry = {\n spans: [],\n lineY: [],\n textY: [],\n lineX: [],\n totalRows,\n columnCount: columns.count,\n columnWidth: columns.width,\n gap,\n columnsUsed,\n ...(hasSpanners ? { ruleSegments, nativeBalance: true } : {}),\n };\n return totalRows;\n}\n\n/**\n * Lay out a multicol container's element children (specs/multicol.md\n * \"Element children\"): children are atomic (never split across columns),\n * measured at the column width, and packed sequentially — a new column\n * when the next child would exceed the fill height or at a forced break.\n * Adjacent margins collapse within a column; a margin at a column break\n * truncates at the column top. `column-span: all` children split the\n * flow into stacked segments that each balance independently. Returns\n * content height (rows used).\n */\nexport function layoutMulticol(\n node: LayoutNode,\n innerWidth: number,\n definiteInnerHeight: number | undefined,\n maxInnerHeight: number | undefined,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n // Only a definite height makes `column-fill: auto` pad segments (and\n // rules) to the full fill; max-height merely restricts.\n const restriction = restrictingHeight(definiteInnerHeight, maxInnerHeight);\n // Paragraph flow: every in-flow child a chrome-less text leaf (or a\n // spanner) → text fragments at line granularity instead of\n // distributing atomically. With spanners the native balancer handles\n // the segments, which the probes pin down for unrestricted heights\n // and `column-fill: balance`; paragraph margins ride along as\n // companion-written padding glued to the preceding paragraph. Both\n // require a browser whose balancer the engine can predict. WebKit\n // slice-spills padding at breaks (so margins there fall back to\n // atomic) and balances segments in INK-HEIGHT sub-pixels — the\n // fractional height corrupts the ORIGIN of whatever segment follows,\n // flipping its distribution (probed live) — so WebKit flow also\n // requires all paragraphs in ONE segment (spanners only at the\n // edges), whose origin is engine-quantized boxes alone.\n const inFlow = node.children.filter((child) => !isOutOfFlow(child.style));\n const paragraphs = inFlow.filter((child) => !child.style.columnSpan);\n const paragraphSegments = inFlow.reduce(\n (count, child, i) =>\n !child.style.columnSpan && (i === 0 || inFlow[i - 1]!.style.columnSpan) ? count + 1 : count,\n 0,\n );\n if (\n paragraphs.length > 0 &&\n paragraphs.every((child) => isFragmentableLeaf(child, style)) &&\n (paragraphs.length === inFlow.length ||\n (style.columnFill === \"balance\" &&\n restriction === undefined &&\n (detectGluedPreBreak() ||\n (paragraphSegments <= 1 &&\n paragraphs.every(\n (child) =>\n (child.style.margin.top === 0 || child.style.margin.top === null) &&\n (child.style.margin.bottom === 0 || child.style.margin.bottom === null),\n )))))\n ) {\n return layoutMulticolFlow(node, inFlow, innerWidth, restriction, border, padding, cache);\n }\n const gap = resolveGap(style, \"x\", innerWidth);\n const widths = resolveColumnTracks(style, innerWidth, gap);\n const count = widths.length;\n const xOffsets: number[] = [];\n {\n let x = 0;\n for (const w of widths) {\n xOffsets.push(x);\n x += w + gap;\n }\n }\n // Overflow columns (css-multicol §7.2) continue past the last track at\n // its width.\n const columnX = (c: number): number =>\n c < count ? xOffsets[c]! : xOffsets[count - 1]! + (c - count + 1) * (widths[count - 1]! + gap);\n const columnWidthAt = (c: number): number => widths[Math.min(c, count - 1)]!;\n // Children measure at the NARROWEST track so a remainder column never\n // overflows its fill height; placement re-lays out at the real width.\n const measureWidth = widths[count - 1]!;\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n\n const vertical: RuleSegment[] = [];\n let y = 0;\n let segment: MulticolUnit[] = [];\n let pendingSlots: { child: LayoutNode; margin: NullableInsets; index: number }[] = [];\n let pendingBreak = false;\n\n /** Greedy sequential pack of the segment at `limit`; `place` also\n * writes child rects and resolves out-of-flow static slots at their\n * column-flow positions. Returns columns used and the tallest column. */\n const pack = (limit: number, place: boolean): { columns: number; maxUsed: number } => {\n let c = 0;\n let used = 0;\n let prevBottom: number | null = null;\n let maxUsed = 0;\n // Static position of an out-of-flow child between two units: the\n // current column-flow position, its own top margin collapsing like a\n // sibling's (specs/positioning.md).\n const resolveSlots = (index: number): void => {\n if (!place) return;\n for (const pending of pendingSlots) {\n if (pending.index !== index) continue;\n const lead =\n prevBottom === null\n ? (pending.margin.top ?? 0)\n : collapseMargins(prevBottom, pending.margin.top ?? 0);\n pending.child.staticSlot = {\n kind: \"block\",\n x: originX + columnX(c) + (pending.margin.left ?? 0),\n y: originY + y + used + lead,\n };\n }\n };\n for (let i = 0; i < segment.length; i++) {\n const unit = segment[i]!;\n resolveSlots(i);\n let joint =\n prevBottom === null\n ? i === 0\n ? (unit.margin.top ?? 0)\n : 0\n : collapseMargins(prevBottom, unit.margin.top ?? 0);\n const height = unit.node.localRect.height;\n if (prevBottom !== null && (unit.breakBefore || used + joint + height > limit)) {\n c += 1;\n used = 0;\n prevBottom = null;\n joint = 0;\n }\n if (place) {\n const child = unit.node;\n const colWidth = columnWidthAt(c);\n if (colWidth !== measureWidth) {\n const marginX = (unit.margin.left ?? 0) + (unit.margin.right ?? 0);\n layoutNode(\n child,\n Math.max(0, colWidth - marginX),\n definiteInnerHeight,\n 0,\n 0,\n \"fill\",\n cache,\n );\n }\n child.localRect = {\n ...child.localRect,\n x: originX + columnX(c) + blockCrossOffset(unit.margin, colWidth, child.localRect.width),\n y: originY + y + used + joint,\n };\n }\n used += joint + unit.node.localRect.height;\n maxUsed = Math.max(maxUsed, used);\n prevBottom = unit.margin.bottom ?? 0;\n }\n resolveSlots(segment.length);\n return { columns: c + 1, maxUsed };\n };\n\n const flushSegment = (): void => {\n if (segment.length === 0) {\n // Out-of-flow children in an empty segment sit at its start.\n for (const pending of pendingSlots) {\n pending.child.staticSlot = {\n kind: \"block\",\n x: originX + (pending.margin.left ?? 0),\n y: originY + y + (pending.margin.top ?? 0),\n };\n }\n pendingSlots = [];\n return;\n }\n const availableH = restriction === undefined ? undefined : Math.max(1, restriction - y);\n const fillsToHeight = style.columnFill === \"auto\" && availableH !== undefined;\n let height: number;\n if (fillsToHeight) {\n height = availableH!;\n } else {\n // Minimal height needing at most `count` columns; forced breaks and\n // margin collapsing are inside `pack`, so the search runs on it.\n const balanced = minimalHeight(1, pack(Number.POSITIVE_INFINITY, false).maxUsed, (limit) => {\n return pack(limit, false).columns <= count;\n });\n height = availableH !== undefined ? Math.min(balanced, availableH) : balanced;\n }\n const packed = pack(height, true);\n // A DEFINITE-height sequential fill keeps its column boxes (and\n // rules) at the full fill height; balanced and max-height-restricted\n // segments are exactly as tall as their tallest column. A lone child\n // taller than the fill height still grows the segment (monolithic\n // overflow).\n const segmentRows =\n fillsToHeight && definiteInnerHeight !== undefined\n ? Math.max(packed.maxUsed, height)\n : packed.maxUsed;\n if (style.ruleX) {\n for (let g = 0; g < count - 1; g++) {\n const columnsFilled = Math.min(packed.columns, count);\n if (!ruleVisible(style.ruleVisibilityItems, g < columnsFilled, g + 1 < columnsFilled))\n continue;\n vertical.push({\n bandStart: xOffsets[g]! + widths[g]!,\n bandSize: gap,\n start: y,\n end: y + segmentRows,\n });\n }\n }\n y += segmentRows;\n segment = [];\n pendingSlots = [];\n };\n\n for (const child of node.children) {\n if (isOutOfFlow(child.style)) {\n // Deferred: the placement pack resolves the static slot at the\n // column-flow position the box would have occupied.\n pendingSlots.push({\n child,\n margin: resolveMargin(child.style.margin, innerWidth),\n index: segment.length,\n });\n continue;\n }\n if (child.style.columnSpan) {\n // Spanner (css-multicol §6.1): full content width, stacked between\n // segments; its margins don't collapse with column content\n // (specs/multicol.md deviation 5).\n flushSegment();\n pendingBreak = false;\n const margin = resolveMargin(child.style.margin, innerWidth);\n const marginX = (margin.left ?? 0) + (margin.right ?? 0);\n layoutNode(\n child,\n Math.max(0, innerWidth - marginX),\n definiteInnerHeight,\n 0,\n 0,\n \"fill\",\n cache,\n );\n y += margin.top ?? 0;\n child.localRect = {\n ...child.localRect,\n x: originX + blockCrossOffset(margin, innerWidth, child.localRect.width),\n y: originY + y,\n };\n y += child.localRect.height + (margin.bottom ?? 0);\n continue;\n }\n const columnMargin = resolveMargin(child.style.margin, measureWidth);\n const marginX = (columnMargin.left ?? 0) + (columnMargin.right ?? 0);\n layoutNode(\n child,\n Math.max(0, measureWidth - marginX),\n definiteInnerHeight,\n 0,\n 0,\n \"fill\",\n cache,\n );\n segment.push({\n node: child,\n margin: columnMargin,\n breakBefore: pendingBreak || child.style.breakBeforeColumn,\n });\n pendingBreak = child.style.breakAfterColumn;\n }\n flushSegment();\n\n if (style.ruleX && vertical.length > 0) {\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(style.glyphSet),\n ruleX: style.ruleX,\n ruleY: null,\n vertical: insetSegments(vertical, style.ruleInset),\n horizontal: [],\n contentWidth: innerWidth,\n contentHeight: y,\n border,\n borderStyle: style.borderStyle,\n borderColor: style.borderColor,\n padding,\n });\n }\n return y;\n}\n","import { junctionGlyph, lineGlyph } from \"./borders.ts\";\nimport { scrollGutter } from \"./types.ts\";\nimport { glyphSetFor } from \"./glyphs.ts\";\nimport type { BorderGlyphSet } from \"./glyphs.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 scrollGutter(style).right;\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 glyphSetFor(node.style.glyphSet),\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 set?: BorderGlyphSet,\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\", set);\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\", set);\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(\n style,\n up !== null,\n down !== null,\n left !== null,\n right !== null,\n set,\n );\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 {\n layoutMulticol,\n multicolIntrinsicInnerWidth,\n multicolLeafGeometry,\n multicolLeafRuleRuns,\n resolveLeafColumns,\n restrictingHeight,\n} from \"./multicol.ts\";\nimport { layoutTable, tableIntrinsicInnerWidths, tableUsedOuterWidth } from \"./table.ts\";\nimport type { TableData } from \"./table.ts\";\nimport { walkPositioned } from \"./positioning.ts\";\nimport { inlineBoxesOf, scrollGutter, scrollGutterBands, scrollsAxis } from \"./types.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport type {\n CellLength,\n CellStyle,\n Insets,\n LayoutNode,\n MulticolLeafGeometry,\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 // The host keeps its in-flow height; the grid covers the INK — visible\n // overflow paints past the host like CSS paints it past any box\n // (specs/cell-model.md \"Overflow\").\n const height = root.localRect.height;\n const ink = contentExtent(root);\n root.localRect.width = Math.max(root.localRect.width, ink.x);\n root.localRect.height = Math.max(height, ink.y);\n return { 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?: {\n width?: number | undefined;\n height?: number | undefined;\n /** Second-pass auto-gutter reservation (see the scrollRange block):\n * an overflowing `auto` axis re-lays out once WITH its gutter and\n * keeps it regardless of the new extent — no oscillation. */\n gutter?: { right: boolean; bottom: boolean };\n },\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, multicol) repopulates them.\n delete node.decorationRuns;\n delete node.multicolGeometry;\n delete node.multicolFlow;\n delete node.multicolFlowSpan;\n delete node.textExtent;\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 gutter = scrollGutter(style);\n const bands = scrollGutterBands(style);\n if (forced?.gutter?.right) gutter.right = bands.right;\n if (forced?.gutter?.bottom) gutter.bottom = bands.bottom;\n const padding: Insets = {\n top: resolveLength(style.padding.top, availableWidth),\n right: resolveLength(style.padding.right, availableWidth) + gutter.right,\n bottom: resolveLength(style.padding.bottom, availableWidth) + gutter.bottom,\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\n // `height` and `max-height` both RESTRICT multicol column heights\n // (css-multicol §7), unlike other displays where max-height only clamps\n // the final rect and overflow spills.\n const maxInnerHeight =\n maxHeight === undefined\n ? undefined\n : Math.max(\n 0,\n maxHeight - style.border.top - style.border.bottom - padding.top - padding.bottom,\n );\n\n // Content layout against an inner height and whether it is definite.\n // Flex and grid containers size their content against a definite\n // height, and a `max-height` on an indefinite one caps the USED size,\n // not just the box (css-flexbox §9.2 / §9.4, css-grid §11.1): content\n // past the cap re-flexes against it — a scroll-container item\n // (automatic minimum 0) shrinks and scrolls.\n const isLeaf = laysOutAsTextLeaf(node);\n const layoutContent = (innerHeight: number, definite: boolean): number => {\n const definiteInner = definite && Number.isFinite(innerHeight) ? innerHeight : undefined;\n if (isLeaf) {\n return layoutTextLeaf(\n node,\n inner.width,\n innerHeight,\n definiteInner,\n maxInnerHeight,\n padding,\n cache,\n );\n }\n if (style.display === \"flex\" && style.flexDirection === \"row\") {\n return layoutFlexRow(\n node,\n inner.width,\n innerHeight,\n definiteInner,\n style.border,\n padding,\n cache,\n );\n }\n if (style.display === \"flex\") {\n return layoutFlexColumn(\n node,\n inner.width,\n innerHeight,\n definite,\n style.border,\n padding,\n cache,\n );\n }\n if (style.display === \"grid\") {\n return layoutGrid(node, inner.width, innerHeight, style.border, padding, cache);\n }\n if (style.display === \"table\") {\n return layoutTable(node, inner.width, definiteInner, style.border, padding, cache);\n }\n if (style.display === \"multicol\") {\n return layoutMulticol(\n node,\n inner.width,\n definiteInner,\n maxInnerHeight,\n style.border,\n padding,\n cache,\n );\n }\n return layoutBlock(node, inner.width, definiteInner, style.border, padding, cache);\n };\n let contentHeight = layoutContent(inner.height, heightIsDefinite);\n const capsUsedHeight = !isLeaf && (style.display === \"flex\" || style.display === \"grid\");\n if (capsUsedHeight && !heightIsDefinite && maxHeight !== undefined) {\n // The USED size: max clamps, and a larger min wins over it (CSS).\n const chromeY = style.border.top + style.border.bottom + padding.top + padding.bottom;\n const usedInner = clampSize(contentHeight + chromeY, minHeight, maxHeight) - chromeY;\n if (usedInner < contentHeight) contentHeight = layoutContent(Math.max(0, usedInner), true);\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 // Multicol browser agreement (leaf and paragraph-flow container,\n // specs/multicol.md): fold the FINAL box's vertical slack into the\n // engine-owned bottom padding so the browser's column box is exactly\n // as tall as the engine's fill (its sequential fill then breaks on\n // the same lines), and only then paint the column rules — the fold\n // decides whether they tee into the bottom border.\n // The cast defeats stale narrowing from the `delete` above (the leaf\n // pass re-populates the property behind a call TS doesn't track).\n const multicolGeometry = node.multicolGeometry as MulticolLeafGeometry | undefined;\n if (multicolGeometry) {\n const finalContentHeight =\n finalHeight - style.border.top - style.border.bottom - padding.top - padding.bottom;\n if (finalContentHeight > multicolGeometry.totalRows)\n padding.bottom += finalContentHeight - multicolGeometry.totalRows;\n multicolLeafRuleRuns(node, multicolGeometry, style.border, padding);\n }\n\n node.localRect = { x: parentX, y: parentY, width: outerWidth, height: finalHeight };\n\n // Scroll geometry (specs/scrolling.md): content extent and max\n // offset, from the ENGINE's layout — never native scrollHeight.\n if (scrollsAxis(style.overflow.x) || scrollsAxis(style.overflow.y)) {\n const extent = contentExtent(node);\n const sizeX = Math.max(0, extent.x - style.border.left - padding.left);\n const sizeY = Math.max(0, extent.y - style.border.top - padding.top);\n const contentW = Math.max(\n 0,\n outerWidth - style.border.left - style.border.right - padding.left - padding.right,\n );\n const contentH = Math.max(\n 0,\n finalHeight - style.border.top - style.border.bottom - padding.top - padding.bottom,\n );\n node.scrollRange = {\n sizeX,\n sizeY,\n maxX: scrollsAxis(style.overflow.x) ? Math.max(0, sizeX - contentW) : 0,\n maxY: scrollsAxis(style.overflow.y) ? Math.max(0, sizeY - contentH) : 0,\n };\n // CSS parity for `auto`: reserve the gutter only when content\n // actually overflows, and keep it even if the narrower re-layout no\n // longer overflows (browsers' own anti-oscillation rule). One axis's\n // gutter can push the OTHER axis into overflow, so the pass repeats\n // while a newly overflowing axis lacks its gutter — gutters only\n // accrue, so at most one more pass.\n if (style.scrollbarWidth !== \"none\") {\n const have = forced?.gutter ?? { right: false, bottom: false };\n const needY = have.right || (style.overflow.y === \"auto\" && node.scrollRange.maxY > 0);\n const needX = have.bottom || (style.overflow.x === \"auto\" && node.scrollRange.maxX > 0);\n if (needY !== have.right || needX !== have.bottom) {\n layoutNode(node, availableWidth, availableHeight, parentX, parentY, widthMode, cache, {\n ...forced,\n gutter: { right: needY, bottom: needX },\n });\n return;\n }\n }\n node.scrollGutterCells = { right: gutter.right, bottom: gutter.bottom };\n } else {\n delete node.scrollRange;\n delete node.scrollGutterCells;\n }\n}\n\n/**\n * Layout for a TEXT LEAF (possibly carrying out-of-flow children), or an\n * empty box. `white-space: nowrap` text never soft-wraps: its height is\n * the hard-line (`<br>`) count, regardless of width. `leading-*` adds\n * `lineGap` empty rows BETWEEN lines only (specs/cell-model.md). Returns\n * content height (rows used); mutates `padding` (=== resolvedPadding)\n * for quantized content alignment and multicol column folding.\n */\nfunction layoutTextLeaf(\n node: LayoutNode,\n innerWidth: number,\n innerHeight: number,\n definiteInnerHeight: number | undefined,\n maxInnerHeight: number | undefined,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n let contentHeight: number;\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 = inlineBoxesOf(node);\n eachObjectMarker(node.text, (charIndex, boxIndex) => {\n const box = boxes[boxIndex]!;\n layoutNode(box, innerWidth, undefined, 0, 0, \"shrink\", cache);\n node.advances![charIndex] = Math.max(1, box.localRect.width);\n });\n let geometry: { spans: LineSpan[]; lineY: number[]; textY: number[]; totalRows: number };\n let lineX: number[] | undefined;\n if (style.display === \"multicol\") {\n // Direct-text multicol leaf (specs/multicol.md): fragment the\n // wrapped lines into columns, the fill restricted by a definite\n // height or max-height (css-multicol §7). The division remainder\n // folds into the engine-owned right padding so the browser's\n // equal fractional columns start on the engine's whole cells;\n // vertical slack folds after the final height clamp (layoutNode).\n const gap = resolveGap(style, \"x\", innerWidth);\n const columns = resolveLeafColumns(style, innerWidth, gap);\n padding.right += columns.leftover;\n const multicol = multicolLeafGeometry(\n node,\n columns,\n gap,\n restrictingHeight(definiteInnerHeight, maxInnerHeight),\n );\n node.multicolGeometry = multicol;\n geometry = multicol;\n lineX = multicol.lineX;\n } else {\n geometry = leafLineGeometry(node, innerWidth);\n }\n contentHeight = geometry.totalRows;\n node.textExtent = {\n width: geometry.spans.reduce(\n (max, span) =>\n Math.max(max, lineAdvance(span.start, span.end, node.advances, style.tracking)),\n 0,\n ),\n rows: geometry.totalRows,\n };\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, innerWidth, innerHeight, 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:\n style.border.left +\n padding.left +\n (lineX?.[line] ?? 0) +\n 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, innerWidth);\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 return contentHeight;\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/** A single-column text leaf's wrapped lines with their vertical\n * geometry: `lineGap` rows between lines, per-line heights and text\n * drops from leafLineMetrics (multicol leaves fragment through\n * multicolLeafGeometry instead). Marker advances must be resolved. */\nexport function leafLineGeometry(\n node: LayoutNode,\n contentWidth: number,\n): { spans: LineSpan[]; lineY: number[]; textY: number[]; totalRows: number } {\n const spans = leafLineSpans(node, contentWidth);\n const { heights, textOffsets } = leafLineMetrics(node, spans);\n const lineY: number[] = [];\n const textY: number[] = [];\n let y = 0;\n for (let s = 0; s < spans.length; s++) {\n lineY.push(y);\n textY.push(y + textOffsets[s]!);\n y += heights[s]! + (s < spans.length - 1 ? node.style.lineGap : 0);\n }\n return { spans, lineY, textY, totalRows: y };\n}\n\n/** A leaf's line spans: hard `<br>` lines under nowrap/pre, greedy\n * word-wrap at the content width otherwise. */\nexport function leafLineSpans(node: LayoutNode, contentWidth: number): LineSpan[] {\n return node.style.whiteSpace !== \"normal\"\n ? hardLineSpans(node.text)\n : wrapLineSpans(node.text, contentWidth, {\n advances: node.advances,\n tracking: node.style.tracking,\n firstLineIndent: node.style.textIndent,\n });\n}\n\n/**\n * Per-line height and text drop for a leaf's wrapped lines. 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). `vertical-align:\n * bottom` on a box drops the line's TEXT to the box's last row\n * (grid-exact in every engine, probed); the largest such box wins.\n * top/middle/baseline behave as top (cell-model deviation — middle and\n * baseline are off-grid). Requires the leaf's inline boxes to be laid\n * out already (their rect heights are read here).\n */\nexport function leafLineMetrics(\n node: LayoutNode,\n spans: LineSpan[],\n): { heights: number[]; textOffsets: number[] } {\n const boxes = inlineBoxesOf(node);\n const heights: number[] = [];\n const textOffsets: number[] = [];\n let boxIndex = 0;\n for (const span of spans) {\n let height = 1;\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 heights.push(height);\n textOffsets.push(Math.min(textOffset, height - 1));\n }\n return { heights, textOffsets };\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 crossOffset = blockCrossOffset(childMargin, innerWidth, child.localRect.width);\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/** Horizontal placement of a box inside its block-flow slot: `auto`\n * margins center or end-align, fixed margins offset (CSS block flow;\n * multicol columns use the same rule). */\nexport function blockCrossOffset(\n margin: NullableInsets,\n slotWidth: number,\n boxWidth: number,\n): number {\n const available = slotWidth - boxWidth;\n if (margin.left === null && margin.right === null) return Math.floor(available / 2);\n if (margin.left === null) return available - (margin.right ?? 0);\n return margin.left;\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 */\nexport function 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\n/** How far a box's content reaches past its border-box origin, in\n * cells: children's own scrollable extents plus its text's extent —\n * CSS scrollable overflow counts descendants' overflow unless a box\n * clips it (`scrollableExtent`). */\nfunction contentExtent(node: LayoutNode): { x: number; y: number } {\n let x = 0;\n let y = 0;\n for (const child of node.children) {\n if (child.style.position === \"fixed\") continue;\n const extent = scrollableExtent(child);\n x = Math.max(x, child.localRect.x + extent.x);\n y = Math.max(y, child.localRect.y + extent.y);\n }\n if (node.textExtent) {\n const { border } = node.style;\n const padding = node.resolvedPadding;\n x = Math.max(x, border.left + padding.left + node.textExtent.width);\n y = Math.max(y, border.top + padding.top + node.textExtent.rows);\n }\n return { x, y };\n}\n\n/** A box's contribution to its parent's scrollable overflow: its own\n * box, grown by its content's overflow on each axis it leaves\n * visible. */\nfunction scrollableExtent(node: LayoutNode): { x: number; y: number } {\n const { width, height } = node.localRect;\n const clipsX = node.style.overflow.x !== \"visible\";\n const clipsY = node.style.overflow.y !== \"visible\";\n if (clipsX && clipsY) return { x: width, y: height };\n const content = contentExtent(node);\n return {\n x: clipsX ? width : Math.max(width, content.x),\n y: clipsY ? height : Math.max(height, content.y),\n };\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 scrollGutter(style).right\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 scrollGutter(style).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) {\n if (node.style.display === \"multicol\")\n return multicolIntrinsicInnerWidth(node.style, node.intrinsicWidth);\n return node.intrinsicWidth;\n }\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 + widthContribution(c, \"max\", cache), 0) + gap;\n }\n const widest = inFlow.reduce((max, c) => Math.max(max, widthContribution(c, \"max\", cache)), 0);\n if (node.style.display === \"multicol\") return multicolIntrinsicInnerWidth(node.style, widest);\n return widest;\n}\n\n/** A child's outer width contribution to its parent's intrinsic size: its\n * explicit width if fixed (percent behaves as auto, per intrinsic\n * contribution rules), else its min-/max-content outer width; clamped by\n * its own fixed min/max. */\nexport function widthContribution(\n child: LayoutNode,\n kind: \"min\" | \"max\",\n cache: IntrinsicCache,\n): 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 * 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 scrollGutter(style).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 + widthContribution(c, \"min\", cache), 0) + gap;\n }\n return inFlow.reduce((max, c) => Math.max(max, widthContribution(c, \"min\", 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 { glyphSetFor, scrollGlyphs } from \"./glyphs.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 * The grid covers the layout's ink extent (layoutRoot grows the root\n * to it); ink above or left of the origin has no cells and is dropped.\n */\nexport function renderPlainText(root: LayoutNode): string {\n return renderGrids(root)\n .grid.map((row) => row.join(\"\").trimEnd())\n .join(\"\\n\");\n}\n\n/** Per-cell paint; every field optional so spans only carry what\n * differs from the host's inherited text style. `color` paints the\n * glyph, `backgroundColor` fills the cell (the light DOM's own bg is\n * neutralized in styles.css so the grid owns backgrounds outright). */\nexport interface CellPaint {\n color?: string;\n /** `string | undefined` (not just optional): a bg-clear fill merges\n * an EXPLICIT undefined over the cell to erase the bg beneath. */\n backgroundColor?: string | undefined;\n fontWeight?: string;\n fontStyle?: string;\n textDecorationLine?: string;\n /** Effective opacity (ancestor product, baked by the walk) as a CSS\n * value — the span composites against the page, so translucency\n * blends with what's behind the HOST, never with covered cells.\n * `\"0\"` still paints: the glyphs stay selectable in grid mode. */\n opacity?: string;\n}\n\n/** One row of same-paint runs. Joining every segment's text reproduces\n * the `renderPlainText` row, so a copy from the DOM adapter (paint.ts)\n * still yields the pure text. */\nexport interface CellSegment extends CellPaint {\n text: string;\n}\n\n/** Row-major cell segments. Each row is `rowSegments(grid[y],\n * paints[y])` — the DOM adapter (paint.ts) uses this, and tests\n * assert paint fields against it. */\nexport function renderCellSegments(root: LayoutNode): CellSegment[][] {\n const { grid, paints } = renderGrids(root);\n return grid.map((row, y) => rowSegments(row, paints[y]!));\n}\n\n/** One rendered row → its same-paint runs. Trims the blank tail so it\n * doesn't emit useless spans — but a trailing space with a painted\n * BACKGROUND is visible ink (a borderless focus-invert fill is nothing\n * but spaces) and must stay. Painted spaces INSIDE a run stay too\n * (underline spans an inline run's inner spaces). */\nfunction rowSegments(row: string[], paints: (CellPaint | undefined)[]): CellSegment[] {\n let end = row.length;\n while (end > 0 && row[end - 1] === \" \" && paints[end - 1]?.backgroundColor === undefined) end--;\n const segments: CellSegment[] = [];\n for (let x = 0; x < end; x++) {\n const paint = paints[x];\n const last = segments[segments.length - 1];\n if (last && samePaint(last, paint)) last.text += row[x]!;\n else segments.push({ text: row[x]!, ...paint });\n }\n return segments;\n}\n\nexport function samePaint(a: CellPaint, b: CellPaint | undefined): boolean {\n return (\n a.color === b?.color &&\n a.backgroundColor === b?.backgroundColor &&\n a.fontWeight === b?.fontWeight &&\n a.fontStyle === b?.fontStyle &&\n a.textDecorationLine === b?.textDecorationLine &&\n a.opacity === b?.opacity\n );\n}\n\n/** Apply a `CellPaint` to a `CSSStyleDeclaration`. Kept in this file\n * alongside samePaint / textPaint so the paint schema has one home. */\nexport function applyCellPaint(paint: CellPaint, style: CSSStyleDeclaration): void {\n if (paint.color !== undefined) style.color = paint.color;\n if (paint.backgroundColor !== undefined) style.backgroundColor = paint.backgroundColor;\n if (paint.fontWeight !== undefined) style.fontWeight = paint.fontWeight;\n if (paint.fontStyle !== undefined) style.fontStyle = paint.fontStyle;\n if (paint.textDecorationLine !== undefined) style.textDecoration = paint.textDecorationLine;\n if (paint.opacity !== undefined) style.opacity = paint.opacity;\n}\n\n/** True when a segment carries no paint — the DOM adapter emits a bare\n * text node for these instead of an empty <span>. */\nexport function isBarePaint(paint: CellPaint): boolean {\n return (\n paint.color === undefined &&\n paint.backgroundColor === undefined &&\n paint.fontWeight === undefined &&\n paint.fontStyle === undefined &&\n paint.textDecorationLine === undefined &&\n paint.opacity === undefined\n );\n}\n\nfunction renderGrids(root: LayoutNode): {\n grid: string[][];\n paints: (CellPaint | undefined)[][];\n} {\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 // Merge paints per field: a later glyph over an earlier fill\n // keeps the fill's fields (bg-fill's backgroundColor survives\n // when text paints its color on top). Same-field overlaps still\n // last-wins.\n const existing = paints[y]![x];\n paints[y]![x] = existing ? { ...existing, ...paint } : paint;\n }\n });\n return { grid, paints };\n}\n\n/** Non-default text styling only, so unstyled runs stay bare.\n * `backgroundColor` rides along for INLINE elements (a leaf's own bg\n * paints via the border-box fill instead). */\nfunction textPaint(source: {\n color: string | undefined;\n backgroundColor?: 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.backgroundColor) paint.backgroundColor = source.backgroundColor;\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(\n node: LayoutNode,\n parentAbsX: number,\n parentAbsY: number,\n put: PutGlyph,\n alpha = 1,\n): 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 // Effective opacity (specs/cell-model.md \"Opacity\"): ancestors\n // multiply (CSS nests, it doesn't inherit) and the value rides on\n // every paint this node produces — including an opacity of 0, whose\n // glyphs must stay in the grid for select=\"grid\" selection.\n const alphaPaint = (paint: CellPaint | undefined): CellPaint | undefined =>\n alpha >= 1 ? paint : { ...paint, opacity: String(Math.round(alpha * 1000) / 1000) };\n\n // Fill the border-box with painted spaces so this element's bg\n // wipes ancestor decoration glyphs at these cells; own borders /\n // text / decoration paint after and layer on top. `bg-clear` runs\n // the same fill without a visible color.\n if (style.backgroundColor !== undefined || style.backgroundClear) {\n // bg-clear fills with an EXPLICIT undefined so the merge in put()\n // strips the cell's painted background too — the wipe covers\n // ancestor backgrounds, not just their glyphs.\n const fillPaint: CellPaint | undefined =\n style.backgroundColor !== undefined\n ? alphaPaint({ backgroundColor: style.backgroundColor })\n : { backgroundColor: undefined };\n for (let dy = 0; dy < node.localRect.height; dy++) {\n for (let dx = 0; dx < node.localRect.width; dx++) {\n put(absX + dx, absY + dy, \" \", fillPaint);\n }\n }\n }\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 = alphaPaint(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 = alphaPaint(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 // Overflow (specs/scrolling.md): a clipping/scrolling axis culls the\n // node's CONTENT ink (text and children — own decorations paint\n // unclipped) at the PADDING box, per CSS: padding cells sit blank at\n // the scroll extremes but content flows through them mid-scroll. A\n // reserved gutter cell stays excluded (the bar owns it). Nested\n // containers compose: the wrapped put chains to the parent's.\n const gutter = node.scrollGutterCells;\n const clipsX = style.overflow.x !== \"visible\";\n const clipsY = style.overflow.y !== \"visible\";\n const scrolledX = absX - (node.scroll?.x ?? 0);\n const scrolledY = absY - (node.scroll?.y ?? 0);\n let contentPut = put;\n if (clipsX || clipsY) {\n const x0 = absX + style.border.left;\n const y0 = absY + style.border.top;\n const x1 = absX + node.localRect.width - style.border.right - (gutter?.right ?? 0);\n const y1 = absY + node.localRect.height - style.border.bottom - (gutter?.bottom ?? 0);\n contentPut = (x, y, glyph, paint) => {\n if (clipsX && (x < x0 || x >= x1)) return;\n if (clipsY && (y < y0 || y >= y1)) return;\n put(x, y, 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 leafPaint = alphaPaint(textPaint(style));\n const inlinePaints = node.inlineElements?.map((entry) => alphaPaint(textPaint(entry)));\n forEachLeafCell(\n node,\n scrolledX,\n scrolledY,\n (k, x, y) => {\n const inlineIndex = node.charInline?.[k] ?? -1;\n const entry = inlineIndex >= 0 ? node.inlineElements![inlineIndex] : undefined;\n // INLINE_PAD marks a blank inline-padding cell: no glyph, but\n // its element's background still fills it.\n if (node.text[k] === INLINE_PAD) {\n if (entry?.backgroundColor) {\n contentPut(x, y, \" \", alphaPaint({ backgroundColor: entry.backgroundColor }));\n }\n } else {\n contentPut(x, y, node.text[k]!, entry ? inlinePaints![inlineIndex] : leafPaint);\n }\n },\n (x, y) => contentPut(x, y, \"…\", leafPaint),\n );\n }\n\n for (const child of paintOrderedChildren(node)) {\n walk(child, scrolledX, scrolledY, contentPut, alpha * child.style.opacity);\n }\n\n // Scrollbars last, over content (specs/scrolling.md): every\n // reserved gutter paints track + thumb (full-length when nothing\n // overflows — the `scroll` case; an `auto` gutter exists only with\n // overflow). The shared corner cell of two bars stays blank.\n const range = node.scrollRange;\n if (range && gutter && (gutter.right > 0 || gutter.bottom > 0)) {\n const { track, thumb } = scrollGlyphs(glyphSetFor(style.glyphSet));\n // `scrollbar-color: auto` means the container's own color (its\n // currentColor, like borders) — not the inherited grid default.\n const barPaint = (color: string | undefined): CellPaint | undefined =>\n alphaPaint(color ? { color } : undefined);\n const trackPaint = barPaint(style.scrollbarColor?.track ?? style.color);\n const thumbPaint = barPaint(style.scrollbarColor?.thumb ?? style.color);\n const bars = scrollbarGeometry(node, absX, absY);\n if (bars.y) {\n const { col, row, thick, len } = bars.y;\n const { at, len: thumbLen } = thumbSpan(len, range.sizeY, range.maxY, node.scroll?.y ?? 0);\n for (let dx = 0; dx < thick; dx++) {\n for (let i = 0; i < len; i++) {\n const isThumb = i >= at && i < at + thumbLen;\n put(col + dx, row + i, isThumb ? thumb : track, isThumb ? thumbPaint : trackPaint);\n }\n }\n }\n if (bars.x) {\n const { col, row, thick, len } = bars.x;\n const { at, len: thumbLen } = thumbSpan(len, range.sizeX, range.maxX, node.scroll?.x ?? 0);\n for (let dy = 0; dy < thick; dy++) {\n for (let i = 0; i < len; i++) {\n const isThumb = i >= at && i < at + thumbLen;\n put(col + i, row + dy, isThumb ? thumb : track, isThumb ? thumbPaint : trackPaint);\n }\n }\n }\n }\n}\n\n/** The cells a leaf's text occupies: the per-line placement — line\n * geometry (a multicol leaf's stored fragmentation, else recomputed),\n * first-line indent, alignment, truncation, inline relative shifts,\n * per-character advances — in ONE place, so mapping a cell back to a\n * character (charIndexAtCell) cannot drift from the paint. `absX/absY`\n * is the leaf's border-box origin with its own scroll applied; U+FFFC\n * markers are skipped (their boxes paint themselves). */\nfunction forEachLeafCell(\n node: LayoutNode,\n absX: number,\n absY: number,\n onChar: (index: number, x: number, y: number, advance: number) => void,\n onEllipsis?: (x: number, y: number) => void,\n): void {\n const style = node.style;\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 multicol = node.multicolGeometry;\n const { spans, textY } = multicol ?? leafLineGeometry(node, contentWidth);\n // Alignment and truncation act within one column of a multicol leaf,\n // against the tracked wrap width — the browser's own alignment\n // includes the trailing letter-spacing gap, so the engine ends lines\n // at `width − tracking` to sit under it.\n const alignWidth = multicol ? Math.max(1, multicol.columnWidth - style.tracking) : contentWidth;\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i]!;\n const row = contentY + textY[i]!;\n // First-line indent reduces the usable width and shifts the origin\n // (per CSS, `<br>` doesn't re-indent, so only spans[0] is charged).\n const indent = i === 0 ? style.textIndent : 0;\n const truncated =\n style.whiteSpace !== \"normal\" && style.overflow.x === \"clip\"\n ? truncateSpan(node.text, span, alignWidth - indent, node.advances, style)\n : { end: span.end, ellipsis: false };\n // `text-align: end` offsets each line to the content box's right\n // edge; `center` to floor((W − line) / 2). Whole cells; a line at\n // or over the width stays at start, matching truncation.\n const lineWidth = lineAdvance(span.start, span.end, node.advances, style.tracking);\n const leftover = Math.max(0, alignWidth - indent - lineWidth);\n const alignOffset =\n style.textAlign === \"end\"\n ? leftover\n : style.textAlign === \"center\"\n ? Math.floor(leftover / 2)\n : 0;\n let x = contentX + (multicol?.lineX[i] ?? 0) + alignOffset + indent;\n for (let k = span.start; k < truncated.end; k++) {\n const advance = advanceOf(k, k + 1, node.advances);\n if (node.text[k] !== OBJECT_REPLACEMENT) {\n // Inline relative shifts, whole cells (specs/positioning.md):\n // the over-constrained sides resolve like CSS (top/left win).\n const insets = node.inlineElements?.[node.charInline?.[k] ?? -1]?.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 onChar(k, x + dx, row + dy, advance);\n }\n x += advance;\n }\n if (truncated.ellipsis) onEllipsis?.(x, row);\n }\n}\n\n/** Whether a cell lies on one of a fragmented leaf's line boxes — the\n * hit test for paragraph-flow multicol children, whose `localRect` is\n * the shared container box (specs/multicol.md): each line covers its\n * column's width and the rows down to the next line in that column\n * (its own line box when it is the column's last). */\nexport function leafLineCovers(\n node: LayoutNode,\n absX: number,\n absY: number,\n col: number,\n row: number,\n): boolean {\n const geometry = node.multicolGeometry;\n if (!geometry) return false;\n const style = node.style;\n const padding = node.resolvedPadding;\n const x = col - (absX + style.border.left + padding.left);\n const y = row - (absY + style.border.top + padding.top);\n const { lineX, lineY } = geometry;\n for (let i = 0; i < lineY.length; i++) {\n if (x < lineX[i]! || x >= lineX[i]! + geometry.columnWidth) continue;\n const next = i + 1 < lineY.length && lineX[i + 1] === lineX[i] ? lineY[i + 1]! : undefined;\n const bottom = next ?? lineY[i]! + 1 + style.lineGap;\n if (y >= lineY[i]! && y < bottom) return true;\n }\n return false;\n}\n\n/** The index into `node.text` of the character painted at a cell, or\n * null for a blank cell (specs/semantic-selection.md). `absX/absY` is\n * the leaf's painted border-box origin as hitStack reports it. */\nexport function charIndexAtCell(\n node: LayoutNode,\n absX: number,\n absY: number,\n col: number,\n row: number,\n): number | null {\n let found: number | null = null;\n forEachLeafCell(\n node,\n absX - (node.scroll?.x ?? 0),\n absY - (node.scroll?.y ?? 0),\n (k, x, y, advance) => {\n if (found === null && y === row && col >= x && col < x + advance) found = k;\n },\n );\n return found;\n}\n\n/** Where a container's bars paint, in absolute cells from its\n * border-box origin (specs/scrolling.md): each bar sits at the inner\n * edge of its reserved band (`scrollbar-inset` moves it inward, the\n * freed cells stay blank), `thick` cells across; its track starts\n * inset from its own edge and ends against the other axis's band, or\n * inset from the far edge when there is none. Shared with thumb\n * dragging (element.ts). */\nexport function scrollbarGeometry(\n node: LayoutNode,\n absX: number,\n absY: number,\n): { y?: Scrollbar; x?: Scrollbar } {\n const gutter = node.scrollGutterCells;\n if (!gutter) return {};\n const { border, scrollbarSize: size, scrollbarInset: inset } = node.style;\n const innerTop = absY + border.top;\n const innerLeft = absX + border.left;\n const innerBottom = absY + node.localRect.height - border.bottom;\n const innerRight = absX + node.localRect.width - border.right;\n // A track ends against the other axis's band when there is one (the\n // corner cell between the bars stays blank), else inset from the edge.\n const bottomEnd = gutter.bottom > 0 ? innerBottom - gutter.bottom : innerBottom - inset.y;\n const rightEnd = gutter.right > 0 ? innerRight - gutter.right : innerRight - inset.x;\n const bars: { y?: Scrollbar; x?: Scrollbar } = {};\n if (gutter.right > 0) {\n bars.y = {\n col: innerRight - gutter.right,\n row: innerTop + inset.y,\n thick: Math.min(size.y, gutter.right),\n len: Math.max(0, bottomEnd - innerTop - inset.y),\n };\n }\n if (gutter.bottom > 0) {\n bars.x = {\n col: innerLeft + inset.x,\n row: innerBottom - gutter.bottom,\n thick: Math.min(size.x, gutter.bottom),\n len: Math.max(0, rightEnd - innerLeft - inset.x),\n };\n }\n return bars;\n}\n\n/** One bar: the cell its track starts at, its thickness across, and\n * its length along its axis. */\nexport interface Scrollbar {\n col: number;\n row: number;\n thick: number;\n len: number;\n}\n\n/** Thumb geometry on a bar `trackLen` cells long: proportional to the\n * visible fraction, but shrunk until every scroll offset gets its own\n * thumb position (`trackLen − max` cells at most, one at least) — so a\n * scrollable bar always shows track, and each step moves the thumb\n * while the track has room. Shared with thumb dragging (element.ts). */\nexport function thumbSpan(\n trackLen: number,\n size: number,\n max: number,\n offset: number,\n): { at: number; len: number } {\n const frac = size > 0 ? Math.min(1, trackLen / size) : 1;\n let len = Math.max(1, Math.round(frac * trackLen));\n if (max > 0) len = Math.max(1, Math.min(len, trackLen - max));\n const at = max > 0 ? Math.round((Math.min(offset, max) / max) * (trackLen - len)) : 0;\n return { at, len };\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 { paintOrderedChildren } from \"./borders.ts\";\nimport { leafLineCovers } from \"./plain-text.ts\";\nimport type { LayoutNode } from \"./types.ts\";\n\n/**\n * Cell hit-testing for the synthesized pointer states\n * (specs/cell-model.md \"Pointer states\"): under select=\"grid\" the\n * light DOM is pointer-events: none, so :hover/:active can never\n * match — the engine derives them from the pointer's cell instead,\n * leaving every event on the grid (selection stays intact).\n */\n\nexport interface HitEntry {\n node: LayoutNode;\n /** The node's PAINTED border-box origin, in absolute cells\n * (ancestor scroll offsets applied). */\n x: number;\n y: number;\n}\n\n/** The nodes under a cell with their painted origins, outermost\n * first: the innermost node whose border-box covers the cell, plus\n * its ancestors — native :hover marks the whole chain, so the\n * synthesized attribute does too. Overlapping siblings resolve to the\n * TOPMOST in paint order (z-index, document-order ties), matching\n * what the grid shows at that cell. */\nexport function hitStack(root: LayoutNode, col: number, row: number): HitEntry[] {\n const stack: HitEntry[] = [];\n let node = root;\n let x = root.localRect.x;\n let y = root.localRect.y;\n for (;;) {\n let hit: LayoutNode | null = null;\n for (const child of paintOrderedChildren(node)) {\n if (child.tableHidden) continue;\n const cx = x + child.localRect.x;\n const cy = y + child.localRect.y;\n // A paragraph-flow multicol child shares the container's box with\n // its siblings; its ink is where its line fragments are.\n const inside = child.multicolFlow\n ? leafLineCovers(child, cx, cy, col, row)\n : col >= cx &&\n col < cx + child.localRect.width &&\n row >= cy &&\n row < cy + child.localRect.height;\n if (inside) hit = child;\n }\n if (!hit) return stack;\n stack.push({ node: hit, x: x + hit.localRect.x, y: y + hit.localRect.y });\n // Descend with the hit's scroll applied: its children paint (and\n // therefore hit) shifted by the offset (specs/scrolling.md).\n x += hit.localRect.x - (hit.scroll?.x ?? 0);\n y += hit.localRect.y - (hit.scroll?.y ?? 0);\n node = hit;\n }\n}\n\n/** The hit stack's elements — what the synthesized states mark. */\nexport function hitChain(root: LayoutNode, col: number, row: number): Element[] {\n return hitStack(root, col, row).map((entry) => entry.node.source);\n}\n","import { inlineBoxesOf } from \"./types.ts\";\nimport type { LayoutNode } from \"./types.ts\";\nimport { INLINE_PAD, OBJECT_REPLACEMENT } from \"./wrap.ts\";\n\n/**\n * Character ↔ DOM position mapping over a leaf's `charSource` runs\n * (specs/semantic-selection.md): word boundaries map forward to\n * `setBaseAndExtent` points, and a Range's boundary points map\n * backward to slices of the leaf's layout text.\n */\n\n/** Negative when point `a` precedes point `b` in DOM order, 0 when equal. */\nexport function comparePoints(aNode: Node, aOffset: number, bNode: Node, bOffset: number): number {\n const document = aNode.ownerDocument!;\n const a = document.createRange();\n a.setStart(aNode, aOffset);\n a.collapse(true);\n const b = document.createRange();\n b.setStart(bNode, bOffset);\n b.collapse(true);\n return a.compareBoundaryPoints(a.START_TO_START, b);\n}\n\n/** The index into `leaf.text` of the character at or after a DOM\n * boundary point: a point inside a collapsed whitespace run is that\n * run's space, a point past a node's mapped characters is the next\n * mapped index (or `text.length`), and a point inside an atomic inline\n * box's subtree is the box's U+FFFC marker. */\nexport function charIndexAt(leaf: LayoutNode, container: Node, offset: number): number {\n const boxes = inlineBoxesOf(leaf);\n const boxIndex = boxes.findIndex((box) => box.source.contains(container));\n if (boxIndex >= 0) {\n let marker = -1;\n for (let i = 0; i <= boxIndex; i++) marker = leaf.text.indexOf(OBJECT_REPLACEMENT, marker + 1);\n if (marker >= 0) return marker;\n }\n const runs = leaf.charSource ?? [];\n // Runs are in DOM order: the last one starting at or before the point.\n let low = 0;\n let high = runs.length;\n while (low < high) {\n const mid = (low + high) >> 1;\n const run = runs[mid]!;\n if (comparePoints(run.node, run.offset, container, offset) <= 0) low = mid + 1;\n else high = mid;\n }\n if (low === 0) return 0;\n const run = runs[low - 1]!;\n if (container === run.node && offset < run.offset + run.length) {\n return run.index + (offset - run.offset);\n }\n return run.index + run.length;\n}\n\n/** The DOM position of `leaf.text[index]` (or of the end of the run\n * ending there); null for a character with no source position. */\nexport function positionOf(leaf: LayoutNode, index: number): { node: Text; offset: number } | null {\n const runs = leaf.charSource ?? [];\n let low = 0;\n let high = runs.length;\n while (low < high) {\n const mid = (low + high) >> 1;\n if (runs[mid]!.index <= index) low = mid + 1;\n else high = mid;\n }\n const run = runs[low - 1];\n if (!run) return null;\n const delta = index - run.index;\n return delta <= run.length ? { node: run.node, offset: run.offset + delta } : null;\n}\n\n/* === Selection location ============================================= */\n\nexport interface BoundaryPoints {\n startContainer: Node;\n startOffset: number;\n endContainer: Node;\n endOffset: number;\n}\n\n/** The document Selection's first range as seen through `shadowRoot`\n * (`getComposedRanges` on Firefox/WebKit and standards-path Chromium;\n * `ShadowRoot.getSelection()` as the legacy Chromium fallback —\n * verified 2026-09-01). A selection inside some OTHER shadow root (a\n * custom leaf's transcript) comes back retargeted onto that root's\n * host, which is exactly the light-tree range around the leaf. Any API\n * surprise reads as no selection, never an error. */\nexport function selectionRangeThrough(shadowRoot: ShadowRoot): BoundaryPoints | null {\n try {\n const selection = shadowRoot.ownerDocument.getSelection();\n if (!selection) return null;\n if (selection.getComposedRanges) {\n const ranges = selection.getComposedRanges({ shadowRoots: [shadowRoot] });\n return ranges[0] ?? null;\n }\n const shadowSelection = (\n shadowRoot as { getSelection?: () => Selection | null }\n ).getSelection?.();\n if (!shadowSelection || shadowSelection.rangeCount === 0) return null;\n return shadowSelection.getRangeAt(0);\n } catch {\n return null;\n }\n}\n\n/** Where a selection lives relative to a host: in its shadow `grid`,\n * in its light DOM (both points, the host's own child list included),\n * or anywhere else — including straddling the two. */\nexport type SelectionKind = \"grid\" | \"light\" | \"outside\";\n\nexport function classifySelection(\n host: Element,\n grid: Element,\n range: BoundaryPoints,\n): SelectionKind {\n const { startContainer: start, endContainer: end } = range;\n if (grid.contains(start) && grid.contains(end)) return \"grid\";\n if (host.contains(start) && host.contains(end)) return \"light\";\n return \"outside\";\n}\n\n/* === Copy serialization ============================================== */\n\n/** A required line break count (collapses with neighbors, dropped at\n * the ends) or literal text (a leaf's slice, a table's tab or row\n * newline) — the HTML `innerText` rendered-text items. */\ntype TextItem = { text: string } | { breaks: number };\n\n/** `text/plain` for a light-DOM selection (specs/semantic-selection.md\n * \"Copy serialization\"): every node the range intersects, in tree\n * order, laid out by the `innerText` rules — a `<p>` surrounded by a\n * blank line, any other block-level box by one line break, table cells\n * separated by tabs and rows by newlines — over each leaf's layout\n * text. The browsers' own serializers lose block breaks for the\n * engine's out-of-flow boxes; this restores what they would have\n * produced in flow. */\nexport function serializeSelection(root: LayoutNode, points: BoundaryPoints): string {\n const range = root.source.ownerDocument!.createRange();\n range.setStart(points.startContainer, points.startOffset);\n range.setEnd(points.endContainer, points.endOffset);\n const items: TextItem[] = [];\n collectItems(root, range, items);\n return assemble(items);\n}\n\nfunction collectItems(node: LayoutNode, range: Range, items: TextItem[]): void {\n if (node.tableHidden || !range.intersectsNode(node.source)) return;\n const breaks = requiredBreaks(node);\n if (breaks) items.push({ breaks });\n if (node.style.tableRole === \"row\") {\n collectRow(node, range, items);\n } else if (node.style.display === \"table\") {\n const rows = tableRows(node);\n for (const child of node.children) {\n if (child.style.tableRole === \"row\" || isRowGroup(child)) continue;\n collectItems(child, range, items); // captions\n }\n // Separators only between rows the range reaches, like the\n // browsers' own partial-table copies.\n let emitted = false;\n for (const row of rows) {\n if (!range.intersectsNode(row.source)) continue;\n if (emitted) items.push({ text: \"\\n\" });\n collectItems(row, range, items);\n emitted = true;\n }\n } else {\n if (isTextLeaf(node)) items.push({ text: leafSlice(node, range) });\n for (const child of node.children) {\n if (!child.inlineBox) collectItems(child, range, items);\n }\n }\n if (breaks) items.push({ breaks });\n}\n\nfunction collectRow(row: LayoutNode, range: Range, items: TextItem[]): void {\n let emitted = false;\n for (const cell of row.children) {\n if (cell.style.tableRole !== \"cell\" || cell.tableHidden) continue;\n if (!range.intersectsNode(cell.source)) continue;\n if (emitted) items.push({ text: \"\\t\" });\n collectItems(cell, range, items);\n emitted = true;\n }\n}\n\nfunction isRowGroup(node: LayoutNode): boolean {\n const role = node.style.tableRole;\n return role === \"header-group\" || role === \"row-group\" || role === \"footer-group\";\n}\n\nfunction tableRows(table: LayoutNode): LayoutNode[] {\n const rows: LayoutNode[] = [];\n for (const child of table.children) {\n if (child.style.tableRole === \"row\") rows.push(child);\n else if (isRowGroup(child)) {\n for (const row of child.children) if (row.style.tableRole === \"row\") rows.push(row);\n }\n }\n return rows;\n}\n\n/** `innerText`: a `<p>` gets two required breaks, any other block-level\n * box (a caption included) one; inline boxes and table internals none. */\nfunction requiredBreaks(node: LayoutNode): number {\n if (node.inlineBox) return 0;\n const role = node.style.tableRole;\n if (role === \"row\" || role === \"cell\" || isRowGroup(node)) return 0;\n if (role === \"column\" || role === \"column-group\") return 0;\n return node.source.tagName === \"P\" ? 2 : 1;\n}\n\n/** A node whose text is painted: text and no in-flow children (the\n * paint walk's own test); renderer leaves included. */\nexport function isTextLeaf(node: LayoutNode): boolean {\n if (node.text.length === 0) return false;\n return !node.children.some(\n (child) =>\n !child.inlineBox && child.style.position !== \"absolute\" && child.style.position !== \"fixed\",\n );\n}\n\n/** The part of a leaf's layout text the range covers — all of it for a\n * renderer leaf (its text has no source positions) — with inline\n * boxes spliced in for their U+FFFC markers and padding markers\n * dropped. A final newline (a trailing `<br>`, which the wrap layer\n * drops) goes too. */\nfunction leafSlice(leaf: LayoutNode, range: Range): string {\n const { text } = leaf;\n let start = 0;\n let end = text.length;\n if (leaf.charSource) {\n if (leaf.source.contains(range.startContainer)) {\n start = charIndexAt(leaf, range.startContainer, range.startOffset);\n }\n if (leaf.source.contains(range.endContainer)) {\n end = charIndexAt(leaf, range.endContainer, range.endOffset);\n }\n }\n let slice = text.slice(start, end);\n if (end === text.length && slice.endsWith(\"\\n\")) slice = slice.slice(0, -1);\n const boxes = inlineBoxesOf(leaf);\n let boxIndex = text.slice(0, start).split(OBJECT_REPLACEMENT).length - 1;\n slice = slice.replaceAll(OBJECT_REPLACEMENT, () => {\n const box = boxes[boxIndex++];\n if (!box || !range.intersectsNode(box.source)) return \"\";\n const items: TextItem[] = [];\n collectItems(box, range, items);\n return assemble(items);\n });\n return slice.replaceAll(INLINE_PAD, \"\");\n}\n\n/** Required breaks collapse to the largest of a run and vanish at\n * either end; text items concatenate. */\nfunction assemble(items: TextItem[]): string {\n let out = \"\";\n let pending = 0;\n for (const item of items) {\n if (\"breaks\" in item) {\n pending = Math.max(pending, item.breaks);\n continue;\n }\n if (item.text.length === 0) continue;\n if (out.length > 0 && pending > 0) out += \"\\n\".repeat(pending);\n pending = 0;\n out += item.text;\n }\n return out;\n}\n\n/* === Words ============================================================ */\n\nconst segmenters = new Map<string, Intl.Segmenter | null>();\n\n/** The word containing `leaf.text[index]` — the `Intl.Segmenter`\n * segment (word-like or not) within the run of text between markers\n * and newlines, in the element's language. null off a character, at a\n * marker, or without a Segmenter. */\nexport function wordAt(leaf: LayoutNode, index: number): { start: number; end: number } | null {\n const { text } = leaf;\n if (index < 0 || index >= text.length || isWordBoundary(text[index]!)) return null;\n let start = index;\n while (start > 0 && !isWordBoundary(text[start - 1]!)) start--;\n let end = index;\n while (end < text.length && !isWordBoundary(text[end]!)) end++;\n const segmenter = segmenterFor(leaf.source.closest?.(\"[lang]\")?.getAttribute(\"lang\") ?? \"\");\n if (!segmenter) return null;\n for (const segment of segmenter.segment(text.slice(start, end))) {\n const from = start + segment.index;\n const to = from + segment.segment.length;\n if (index >= from && index < to) return { start: from, end: to };\n }\n return null;\n}\n\nfunction isWordBoundary(ch: string): boolean {\n return ch === \"\\n\" || ch === OBJECT_REPLACEMENT || ch === INLINE_PAD;\n}\n\n/** One Segmenter per language, cached (construction is not free and\n * word extension asks per pointermove); an invalid tag falls back to\n * the default locale. */\nfunction segmenterFor(lang: string): Intl.Segmenter | null {\n let segmenter = segmenters.get(lang);\n if (segmenter === undefined) {\n segmenter = createSegmenter(lang) ?? createSegmenter(\"\");\n segmenters.set(lang, segmenter);\n }\n return segmenter;\n}\n\nfunction createSegmenter(lang: string): Intl.Segmenter | null {\n if (typeof Intl.Segmenter !== \"function\") return null;\n try {\n return new Intl.Segmenter(lang || undefined, { granularity: \"word\" });\n } catch {\n return null;\n }\n}\n","import { applyCellPaint, isBarePaint, renderCellSegments, samePaint } from \"./plain-text.ts\";\nimport type { CellSegment } from \"./plain-text.ts\";\nimport { selectionRangeThrough } from \"./selection.ts\";\nimport type { LayoutNode } from \"./types.ts\";\n\n/**\n * Paint the laid-out tree into the shadow's `#grid` (a `<pre>`): each\n * text line is a cell row, same-paint runs coalesce into spans.\n *\n * Node identity is preserved wherever possible (specs/cell-model.md\n * \"Selection\"): an unchanged paint skips the write entirely, and a\n * paint whose STRUCTURE (segment texts and span/bare split) matches\n * the last one only patches span styles in place — no node churn, so\n * live Selections (and an in-flight drag's anchor, which no engine\n * lets us restore) survive animation frames untouched. A structural\n * change rebuilds the nodes: the selection is captured as flat\n * character offsets before the swap and restored after, and while a\n * primary press is down with a selection anchor in the grid the\n * rebuild is HELD for release instead (element.ts) — even restored\n * nodes collapse Chromium's drag.\n */\nconst lastPaintSignature = new WeakMap<HTMLElement, string>();\ninterface PaintedRows {\n nodes: (Text | HTMLElement)[][];\n segments: CellSegment[][];\n}\nconst lastPaint = new WeakMap<HTMLElement, PaintedRows>();\n\n/** True when a Selection boundary (a collapsed press anchor counts —\n * the drag it starts must survive) lies inside the grid. */\nfunction hasSelectionInside(target: HTMLElement): boolean {\n return captureSelection(target, true) !== null;\n}\n\n/** Returns false when the paint was HELD: the caller asked to defer\n * structural rebuilds (a primary press is down) and a selection\n * anchor is in the grid — repeat the paint on release. */\nexport function paintGrid(root: LayoutNode, target: HTMLElement, holdStructural = false): boolean {\n const rows = renderCellSegments(root);\n const signature = signatureOf(rows);\n if (lastPaintSignature.get(target) === signature) return true;\n\n // Style-only pass: same texts in the same span/bare segmentation —\n // patch the spans whose paint actually changed and leave every\n // node's identity alone.\n const previous = lastPaint.get(target);\n if (previous && structureMatches(target, previous.nodes, rows)) {\n lastPaintSignature.set(target, signature);\n for (let y = 0; y < rows.length; y++) {\n for (let i = 0; i < rows[y]!.length; i++) {\n const segment = rows[y]![i]!;\n if (isBarePaint(segment) || samePaint(segment, previous.segments[y]![i])) continue;\n const span = previous.nodes[y]![i]! as HTMLElement;\n span.style.cssText = \"\";\n applyCellPaint(segment, span.style);\n }\n }\n previous.segments = rows;\n return true;\n }\n\n if (holdStructural && hasSelectionInside(target)) return false;\n lastPaintSignature.set(target, signature);\n const fragment = document.createDocumentFragment();\n const nodes: (Text | HTMLElement)[][] = [];\n for (let y = 0; y < rows.length; y++) {\n if (y > 0) fragment.appendChild(document.createTextNode(\"\\n\"));\n const rowNodes: (Text | HTMLElement)[] = [];\n for (const segment of rows[y]!) {\n if (isBarePaint(segment)) {\n const text = document.createTextNode(segment.text);\n rowNodes.push(text);\n fragment.appendChild(text);\n continue;\n }\n const span = document.createElement(\"span\");\n applyCellPaint(segment, span.style);\n span.textContent = segment.text;\n rowNodes.push(span);\n fragment.appendChild(span);\n }\n nodes.push(rowNodes);\n }\n lastPaint.set(target, { nodes, segments: rows });\n const saved = captureSelection(target, false);\n target.replaceChildren(fragment);\n if (saved) restoreSelection(target, saved);\n return true;\n}\n\nfunction structureMatches(\n target: HTMLElement,\n previous: (Text | HTMLElement)[][],\n rows: CellSegment[][],\n): boolean {\n if (previous.length !== rows.length) return false;\n for (let y = 0; y < rows.length; y++) {\n const prevRow = previous[y]!;\n const row = rows[y]!;\n if (prevRow.length !== row.length) return false;\n for (let i = 0; i < row.length; i++) {\n const node = prevRow[i]!;\n const bare = isBarePaint(row[i]!);\n if (bare !== (node.nodeType === Node.TEXT_NODE)) return false;\n if (node.textContent !== row[i]!.text) return false;\n // Something else may have cleared the grid (the empty-content\n // path replaceChildren's it) — stale detached nodes can't be\n // patched.\n if (node.parentNode !== target) return false;\n }\n }\n return true;\n}\n\n/* === Selection preservation ========================================== */\n\ninterface SavedSelection {\n start: number; // flat character offsets into the grid's textContent\n end: number;\n backward: boolean;\n}\n\n/** Anything unexpected degrades to the old behavior (selection lost),\n * never an error. */\nfunction captureSelection(target: HTMLElement, allowCollapsed: boolean): SavedSelection | null {\n try {\n const selection = target.ownerDocument.getSelection();\n if (!selection) return null;\n const shadowRoot = target.getRootNode();\n if (!(shadowRoot instanceof ShadowRoot)) return null;\n const range = selectionRangeThrough(shadowRoot);\n if (!range) return null;\n const start = flatOffset(target, range.startContainer, range.startOffset);\n const end = flatOffset(target, range.endContainer, range.endOffset);\n if (start === null || end === null) return null;\n if (start === end && !allowCollapsed) return null;\n // `direction` is unsupported in some engines; forward is the safe\n // default (a restored backward drag then extends from its focus\n // end — visible only if the user keeps dragging).\n const direction = (selection as { direction?: string }).direction;\n return { start, end, backward: direction === \"backward\" };\n } catch {\n return null;\n }\n}\n\nfunction restoreSelection(target: HTMLElement, saved: SavedSelection): void {\n try {\n const start = nodeAtOffset(target, saved.start);\n const end = nodeAtOffset(target, saved.end);\n if (!start || !end) return;\n // Chromium: restore through the shadow root's own selection — the\n // document-level restore leaves a live drag's internal anchor on\n // the detached nodes and the next mousemove collapses it.\n const shadowRoot = target.getRootNode() as { getSelection?: () => Selection | null };\n const selection = shadowRoot.getSelection?.() ?? target.ownerDocument.getSelection();\n if (saved.backward) {\n selection?.setBaseAndExtent(end[0], end[1], start[0], start[1]);\n } else {\n selection?.setBaseAndExtent(start[0], start[1], end[0], end[1]);\n }\n } catch {\n // Leave whatever the browser collapsed the selection to.\n }\n}\n\n/** Boundary point → offset into the grid's flat text; null when the\n * point is outside the grid (the selection reaches past it — restoring\n * only our half would corrupt it). A Range does the flattening: its\n * string is exactly the text between the grid's start and the point. */\nfunction flatOffset(target: HTMLElement, container: Node, offset: number): number | null {\n if (!target.contains(container)) return null;\n const range = target.ownerDocument.createRange();\n range.selectNodeContents(target);\n range.setEnd(container, offset);\n return range.toString().length;\n}\n\nexport function nodeAtOffset(target: HTMLElement, offset: number): [Text, number] | null {\n let remaining = offset;\n let last: [Text, number] | null = null;\n for (const text of textNodesOf(target)) {\n if (remaining <= text.data.length) return [text, remaining];\n remaining -= text.data.length;\n last = [text, text.data.length];\n }\n // Offset past the new content (the grid shrank): clamp to the end.\n return last;\n}\n\nfunction* textNodesOf(target: HTMLElement): Generator<Text> {\n const walker = target.ownerDocument.createTreeWalker(target, NodeFilter.SHOW_TEXT);\n let node = walker.nextNode();\n while (node) {\n yield node as Text;\n node = walker.nextNode();\n }\n}\n\nfunction signatureOf(rows: CellSegment[][]): string {\n const parts: string[] = [];\n for (const row of rows) {\n for (const s of row) {\n parts.push(\n s.text,\n s.color ?? \"\",\n s.backgroundColor ?? \"\",\n s.fontWeight ?? \"\",\n s.fontStyle ?? \"\",\n s.textDecorationLine ?? \"\",\n s.opacity ?? \"\",\n );\n }\n parts.push(\"\\n\");\n }\n return parts.join(\"\\x1f\");\n}\n","import { paintOrderedChildren, paintsInPositionedStep } from \"./borders.ts\";\nimport { leafLineSpans } from \"./layout.ts\";\nimport type { LayoutNode, PerSide } from \"./types.ts\";\nimport { lineAdvance } from \"./wrap.ts\";\n\n/**\n * Write geometry custom properties, quantized inline padding, and z-index\n * markers on each source element in the light DOM. Coordinates on\n * LayoutNode are parent-relative; the companion stylesheet turns them\n * into px via the measured cell size. No painting: decoration and text\n * glyphs land in the shadow grid via `paint.ts`.\n *\n * Every write is change-checked: a relayout that computes the same\n * result mutates nothing. Chrome dismisses an open <select> popup on\n * style mutations near it, and the dynamic-state listeners relayout on\n * the very events that open one (focusin/pointerover) — idempotent\n * writes keep the popup up.\n */\nexport function render(root: LayoutNode): void {\n const inlineInsetElements = new Set<Element>();\n walk(root, true, inlineInsetElements);\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\n/** setProperty, skipped when the value is already there. */\nfunction setVar(el: HTMLElement, prop: string, value: string): void {\n if (el.style.getPropertyValue(prop) !== value) el.style.setProperty(prop, value);\n}\n\n/** removeProperty, skipped when the property isn't set. */\nfunction clearVar(el: HTMLElement, prop: string): void {\n if (el.style.getPropertyValue(prop) !== \"\") el.style.removeProperty(prop);\n}\n\n/** Boolean attribute toggle, skipped when already in the target state. */\nfunction setFlag(el: Element, name: string, on: boolean): void {\n if (el.hasAttribute(name) === on) return;\n if (on) el.setAttribute(name, \"\");\n else el.removeAttribute(name);\n}\n\nfunction walk(node: LayoutNode, isRoot: boolean, inlineInsetElements: Set<Element>): void {\n if (node.inlineElements) {\n for (const { element, tracking, padLeft, padRight, insets } of node.inlineElements) {\n const el = element as HTMLElement;\n setVar(el, \"--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) setVar(el, \"--mw-ipl\", String(padLeft));\n else clearVar(el, \"--mw-ipl\");\n if (padRight > 0) setVar(el, \"--mw-ipr\", String(padRight));\n else clearVar(el, \"--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 recurse into.\n if (node.tableHidden) return;\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 && paintsInPositionedStep(child, node) && !child.inlineBox)\n setVar(el, \"--mw-z\", String(child.style.zIndex));\n else clearVar(el, \"--mw-z\");\n walk(child, 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 setFlag(el, \"data-mw-inline-inset\", true);\n const write = (prop: string, cells: number | null) => {\n if (cells === null) clearVar(el, prop);\n else setVar(el, 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\n/** Centered text: the grid paints `floor(leftover / 2)` whole cells,\n * the browser centers the native copy fractionally — half a cell apart\n * on odd-leftover lines (specs/cell-model.md \"Text alignment\"). When\n * EVERY line shares the odd-parity drift (a single-line heading, most\n * commonly), the companion nudges the native copy half a cell left so\n * selection sits on the glyphs. CHILDLESS text leaves only: the nudge\n * would also shift an embedded atomic box's visible native ink and an\n * absolutized child's selectable text, and an inline box's own\n * form-control ink keeps browser centering per the spec. The leftover\n * math mirrors the paint's alignOffset (plain-text.ts). */\nfunction needsCenterNudge(node: LayoutNode): boolean {\n const style = node.style;\n if (style.textAlign !== \"center\" || !node.text) return false;\n if (node.inlineBox || node.children.length > 0) return false;\n const multicol = node.multicolGeometry;\n const padding = node.resolvedPadding;\n const contentWidth =\n node.localRect.width - style.border.left - style.border.right - padding.left - padding.right;\n const alignWidth = multicol ? Math.max(1, multicol.columnWidth - style.tracking) : contentWidth;\n const spans = multicol?.spans ?? leafLineSpans(node, contentWidth);\n if (spans.length === 0) return false;\n return spans.every((span, i) => {\n const indent = i === 0 ? style.textIndent : 0;\n const leftover =\n alignWidth - indent - lineAdvance(span.start, span.end, node.advances, style.tracking);\n return leftover > 0 && leftover % 2 === 1;\n });\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 and paragraph-flow multicol children stay IN\n // FLOW (the browser's own line layout / column fragmentation places\n // them); everything else is engine-positioned. Same geometry vars, a\n // different companion rule each (see styles.css).\n const flow = node.multicolFlow;\n const flowSpan = node.multicolFlowSpan;\n setFlag(el, \"data-mw-laid-out\", !node.inlineBox && !flow && !flowSpan);\n setFlag(el, \"data-mw-inline-box\", Boolean(node.inlineBox));\n setFlag(el, \"data-mw-multicol-flow\", Boolean(flow));\n setFlag(el, \"data-mw-multicol-flow-span\", Boolean(flowSpan));\n const flowMargins = flow ?? flowSpan;\n if (flowMargins) {\n setVar(el, \"--mw-mt\", String(flowMargins.top ?? 0));\n setVar(el, \"--mw-mr\", String(flowMargins.right ?? 0));\n setVar(el, \"--mw-mb\", String(flowMargins.bottom ?? 0));\n setVar(el, \"--mw-ml\", String(flowMargins.left ?? 0));\n } else {\n clearVar(el, \"--mw-mt\");\n clearVar(el, \"--mw-mr\");\n clearVar(el, \"--mw-mb\");\n clearVar(el, \"--mw-ml\");\n }\n // Bottom-aligned atomic boxes keep their browser alignment (grid-exact,\n // probed); everything else is pinned top by the companion rule.\n setFlag(el, \"data-mw-vbottom\", Boolean(node.inlineBox) && node.style.verticalAlign === \"end\");\n // Grid typography (specs/cell-model.md): extra cells per character, rows\n // per wrapped line, and the half-leading cancellation shift.\n setVar(el, \"--mw-ls\", String(tracking));\n setVar(el, \"--mw-lh\", String(lineGap + 1));\n setVar(el, \"--mw-lhs\", String(-lineGap / 2));\n setFlag(el, \"data-mw-nowrap\", whiteSpace !== \"normal\");\n // A multicol TEXT LEAF or paragraph-flow container keeps native\n // columns, driven by the engine's used values so the browser\n // fragments on the same lines (specs/multicol.md \"Browser\n // agreement\"); a spanner-split flow additionally trusts the NATIVE\n // balancer per segment (probed exact). Atomic element-children\n // containers get no flag: their light DOM has nothing in flow.\n // Flow CHILDREN carry a geometry too (their line maps) but must never\n // get native columns themselves — only the container fragments.\n const multicol = flow || flowSpan ? undefined : node.multicolGeometry;\n setFlag(el, \"data-mw-multicol\", Boolean(multicol));\n setFlag(el, \"data-mw-multicol-balance\", Boolean(multicol?.nativeBalance));\n if (multicol) {\n setVar(el, \"--mw-colc\", String(multicol.columnCount));\n setVar(el, \"--mw-colg\", String(multicol.gap));\n } else {\n clearVar(el, \"--mw-colc\");\n clearVar(el, \"--mw-colg\");\n }\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 setFlag(el, \"data-mw-pre\", whiteSpace === \"pre\");\n setVar(el, \"--mw-x\", String(rect.x));\n setVar(el, \"--mw-y\", String(rect.y));\n setVar(el, \"--mw-w\", String(rect.width));\n setVar(el, \"--mw-h\", String(rect.height));\n setFlag(el, \"data-mw-clip\", overflow.x === \"clip\" || overflow.y === \"clip\");\n setFlag(el, \"data-mw-scroll\", node.scrollRange !== undefined);\n if (node.scrollRange) {\n // Native range == engine range by construction: a 1px ::after\n // spacer (companion CSS) ends at exactly max + box cells, so\n // scrollHeight - clientHeight lands on the engine's max in every\n // engine (browsers disagree about end padding in the scrollable\n // overflow area). An axis with no range parks the spacer in the\n // first cell — a box outside the padding box (at -1px) is dropped\n // from the overflow area on BOTH axes.\n const { maxX, maxY } = node.scrollRange;\n setVar(el, \"--mw-se-x\", String(maxX > 0 ? maxX + node.localRect.width : 1));\n setVar(el, \"--mw-se-y\", String(maxY > 0 ? maxY + node.localRect.height : 1));\n } else {\n clearVar(el, \"--mw-se-x\");\n clearVar(el, \"--mw-se-y\");\n }\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 setVar(el, \"--mw-pt\", String(padding.top));\n setVar(el, \"--mw-pr\", String(padding.right));\n setVar(el, \"--mw-pb\", String(padding.bottom));\n setVar(el, \"--mw-pl\", String(padding.left));\n setVar(el, \"--mw-bt\", String(border.top));\n setVar(el, \"--mw-br\", String(border.right));\n setVar(el, \"--mw-bb\", String(border.bottom));\n setVar(el, \"--mw-bl\", String(border.left));\n // Native text-indent is authored in px; overwrite it in cells so the\n // browser's own line (the selectable, transparent-locked text under\n // the grid) sits under the glyphs the engine painted. Always set —\n // custom properties inherit, so an unset var on an `indent-0` child\n // would resolve to an indented ancestor's value.\n setVar(el, \"--mw-ti\", String(node.style.textIndent));\n setFlag(el, \"data-mw-text-align-blocked\", textAlignBlocked);\n setFlag(el, \"data-mw-center-nudge\", needsCenterNudge(node));\n // Un-laid-out direct text (mixed with block children) would otherwise\n // paint unpositioned over the children — hide it (see styles.css).\n setFlag(el, \"data-mw-dropped-text\", Boolean(node.droppedText));\n setFlag(el, \"data-mw-table-hidden\", Boolean(node.tableHidden));\n}\n","import { trackBackground } from \"./animate.ts\";\nimport { pxToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack, zeroInsets } from \"./types.ts\";\nimport { leafRendererFor } from \"./leaf.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport type {\n AlignItems,\n Overflow,\n OverflowAxis,\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 // A min/max limit: an authored calc() or viewport length first (their\n // units carry intent the computed px has lost), then the computed px.\n const limit = (property: string, resolved: string, prefix: string): SizeLimit | undefined =>\n authoredCalcCells(\n csm,\n property,\n resolved,\n classAttr,\n prefix,\n inlineStyle,\n metrics,\n rootFontSizePx,\n ) ??\n viewportLimit(\n csm,\n property,\n resolved,\n classAttr,\n prefix,\n inlineStyle,\n metrics,\n rootFontSizePx,\n ) ??\n readLimit(resolved, rootFontSizePx);\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 // Multicol: a block with an authored column-count or column-width\n // (specs/multicol.md). Computed values are specified values (probed\n // — no used-value trap).\n const columnCount =\n cs.columnCount && cs.columnCount !== \"auto\"\n ? Math.max(1, Math.floor(Number(cs.columnCount) || 1))\n : null;\n const columnWidthPx =\n cs.columnWidth && cs.columnWidth !== \"auto\" ? parseFloat(cs.columnWidth) : NaN;\n const columnWidth = Number.isFinite(columnWidthPx)\n ? Math.max(1, pxToCells(columnWidthPx, rootFontSizePx))\n : null;\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\" || isZeroClipped(el, cs)\n ? \"none\"\n : columnCount !== null || columnWidth !== null\n ? \"multicol\"\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, metrics),\n height: readSize(csm, cs.height, \"height\", rootFontSizePx, classAttr, inlineStyle, metrics),\n minWidth: limit(\"min-width\", cs.minWidth, \"min-w\") ?? \"auto\",\n minHeight: limit(\"min-height\", cs.minHeight, \"min-h\") ?? \"auto\",\n maxWidth: limit(\"max-width\", cs.maxWidth, \"max-w\"),\n maxHeight: limit(\"max-height\", cs.maxHeight, \"max-h\"),\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 // `column-gap: normal` is 0 in flex/grid but 1em in multicol, per\n // CSS (specs/multicol.md \"Reading\"). Headless DOMs report unset as\n // an empty string — same initial value.\n gapX: readSpacing(\n cs.columnGap === \"normal\" || cs.columnGap === \"\"\n ? display === \"multicol\"\n ? `${fontSizePx}px`\n : \"0px\"\n : cs.columnGap,\n rootFontSizePx,\n ),\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 overflow: readOverflow(cs),\n scrollbarWidth: readScrollbarWidth(el, cs),\n scrollbarColor: readScrollbarColor(cs.scrollbarColor),\n overscroll: {\n x: (cs.overscrollBehaviorX || \"auto\") === \"auto\",\n y: (cs.overscrollBehaviorY || \"auto\") === \"auto\",\n },\n scrollbarSize: {\n x: readCells(cs.getPropertyValue(\"--mw-scrollbar-size-x\")),\n y: readCells(cs.getPropertyValue(\"--mw-scrollbar-size-y\")),\n },\n scrollbarInset: {\n x: readCells(cs.getPropertyValue(\"--mw-scrollbar-inset-x\"), 0),\n y: readCells(cs.getPropertyValue(\"--mw-scrollbar-inset-y\"), 0),\n },\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, 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: readAnimatedBackground(el, cs.backgroundColor, cs),\n backgroundClear: cs.getPropertyValue(\"--mw-bg-clear\").trim() === \"1\",\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: readTextAlign(el, cs),\n textIndent: readTextIndent(cs, rootFontSizePx),\n opacity: readOpacity(cs.opacity),\n glyphSet: cs.getPropertyValue(\"--mw-border-glyphs\").trim() || null,\n zIndex: cs.zIndex === \"auto\" || cs.zIndex === \"\" ? null : Number(cs.zIndex) || 0,\n latticeBorder: null,\n ruleX:\n display === \"flex\" || display === \"grid\" || display === \"multicol\"\n ? readGapRule(cs, \"x\")\n : null,\n ruleY: display === \"flex\" || display === \"grid\" ? readGapRule(cs, \"y\") : null,\n ruleBreak: readKeyword(cs, \"--mw-rule-break\", [\"none\", \"intersection\"] as const, \"normal\"),\n ruleInset:\n cs.getPropertyValue(\"--mw-rule-inset\").trim() === \"overlap-join\"\n ? \"overlap-join\"\n : Math.max(\n 0,\n roundHalfAwayFromZero(parseFloat(cs.getPropertyValue(\"--mw-rule-inset\")) || 0),\n ),\n ruleVisibilityItems: readKeyword(\n cs,\n \"--mw-rule-visibility-items\",\n [\"all\", \"around\", \"between\"] as const,\n \"normal\",\n ),\n columnCount,\n columnWidth,\n columnFill: cs.columnFill === \"auto\" ? \"auto\" : \"balance\",\n columnSpan: cs.columnSpan === \"all\",\n breakBeforeColumn: cs.breakBefore === \"column\",\n breakAfterColumn: cs.breakAfter === \"column\",\n breakInsideAvoid: cs.breakInside === \"avoid\" || cs.breakInside === \"avoid-column\",\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\n/** True for a computed `background-color` that shouldn't trigger the\n * bg-occludes-decorations fill. Real browsers resolve transparent to\n * `rgba(0, 0, 0, 0)`; the empty-string and `currentcolor` branches\n * cover happy-dom (test env), which leaves some computed values\n * unresolved. */\nexport function isTransparentColor(value: string): boolean {\n if (!value) return true;\n const normalized = value.trim().toLowerCase();\n return (\n normalized === \"\" ||\n normalized === \"transparent\" ||\n normalized === \"rgba(0, 0, 0, 0)\" ||\n normalized === \"currentcolor\"\n );\n}\n\n/** Background-color read, routed through the synthesized-transition\n * tracker (animate.ts): a mid-fade read returns the interpolated color\n * — including near-transparent frames of a fade to/from unset, which\n * must paint rather than read as \"no background\". */\nfunction readAnimatedBackground(\n el: Element,\n raw: string,\n cs: CSSStyleDeclaration,\n): string | undefined {\n const tracked = trackBackground(el, isTransparentColor(raw) ? \"\" : raw, cs);\n return tracked === \"\" ? undefined : tracked;\n}\n\nfunction isClipping(value: string): boolean {\n return value === \"hidden\" || value === \"clip\";\n}\n\n/** Authored `scrollbar-width`, cached from the first CLEAN read: once\n * the element carries data-mw-scroll our own hiding lock sets it to\n * none, and Firefox never re-resolves the computed value when the\n * lock's [measuring] gate flips — so the pre-lock value is the truth\n * (authored changes after the first layout won't re-read there;\n * documented deviation). */\nconst scrollbarWidthCache = new WeakMap<Element, \"auto\" | \"none\">();\nlet scrollbarWidthReadable: boolean | null = null;\n\n/** Environments with forced overlay scrollbars (headless Firefox\n * among them) compute `scrollbar-width: none` on EVERY element — a\n * pristine probe reading `none` means reads carry no authored signal,\n * so the engine ignores the property there instead of hiding every\n * bar. */\nfunction scrollbarWidthReadsTrustworthy(doc: Document): boolean {\n if (scrollbarWidthReadable !== null) return scrollbarWidthReadable;\n if (!doc.body) return true; // decide later, on a real read\n const probe = doc.createElement(\"div\");\n probe.style.cssText = \"position: absolute; width: 0; height: 0; overflow: auto\";\n doc.body.appendChild(probe);\n scrollbarWidthReadable = getComputedStyle(probe).scrollbarWidth !== \"none\";\n probe.remove();\n return scrollbarWidthReadable;\n}\n\nfunction readScrollbarWidth(el: Element, cs: CSSStyleDeclaration): \"auto\" | \"none\" {\n if (!scrollbarWidthReadsTrustworthy(el.ownerDocument)) return \"auto\";\n if (el.hasAttribute(\"data-mw-scroll\")) {\n const cached = scrollbarWidthCache.get(el);\n if (cached !== undefined) return cached;\n }\n const value: \"auto\" | \"none\" = cs.scrollbarWidth === \"none\" ? \"none\" : \"auto\";\n scrollbarWidthCache.set(el, value);\n return value;\n}\n\n/** `scrollbar-color: <thumb> <track>` — two computed colors, split at\n * the top parenthesis level (rgb()/color() carry inner spaces). */\nfunction readScrollbarColor(value: string): { thumb: string; track: string } | null {\n const v = (value ?? \"\").trim();\n if (!v || v === \"auto\") return null;\n let depth = 0;\n for (let i = 0; i < v.length; i++) {\n const ch = v[i]!;\n if (ch === \"(\") depth++;\n else if (ch === \")\") depth--;\n else if (ch === \" \" && depth === 0) {\n return { thumb: v.slice(0, i), track: v.slice(i + 1).trim() };\n }\n }\n return null;\n}\n\n/** A `<integer>` custom property in cells, floored at `min`. */\nfunction readCells(value: string, min = 1): number {\n return Math.max(min, Math.floor(Number(value) || min));\n}\n\nfunction overflowAxis(value: string): OverflowAxis {\n if (isClipping(value)) return \"clip\";\n if (value === \"auto\" || value === \"scroll\") return value;\n return \"visible\";\n}\n\n/** Per-axis overflow (specs/scrolling.md). Longhands read first (the\n * shorthand sets both in real browsers; happy-dom may leave them \"\",\n * hence the fallback), then the CSS coercion: one non-visible axis\n * forces the other's `visible` to compute `auto`. */\nfunction readOverflow(cs: CSSStyleDeclaration): Overflow {\n let x = overflowAxis(cs.overflowX || cs.overflow);\n let y = overflowAxis(cs.overflowY || cs.overflow);\n if (x !== \"visible\" && y === \"visible\") y = \"auto\";\n if (y !== \"visible\" && x === \"visible\") x = \"auto\";\n return { x, y };\n}\n\n/** The screen-reader-only pattern (Tailwind `sr-only` and friends): an\n * absolutely positioned box whose ink can't show — a zero `clip` rect,\n * or a clipped ≤1px box. Treated as display:none by the ENGINE only:\n * the light-DOM element keeps its authored styles, so assistive tech\n * still reads it. */\nfunction isZeroClipped(el: Element, cs: CSSStyleDeclaration): boolean {\n if (cs.position !== \"absolute\" && cs.position !== \"fixed\") return false;\n const clip = cs.clip.replace(/\\s/g, \"\");\n if (clip === \"rect(0px,0px,0px,0px)\" || clip === \"rect(0,0,0,0)\") return true;\n // The clipped-box half reads the browser's NATURAL size, which for a\n // renderer leaf is meaningless (its size comes from the renderer's\n // lines; its light content is invisible) — a fresh absolute leaf\n // with overflow-clip and no padding measures 0x0 and would be\n // dropped before it ever renders, staying 0x0 forever.\n if (leafRendererFor(el.tagName)) return false;\n return (\n (isClipping(cs.overflow) || isClipping(cs.overflowX)) &&\n parseFloat(cs.width) <= 1 &&\n parseFloat(cs.height) <= 1\n );\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 readKeyword<T extends string, D extends string>(\n cs: CSSStyleDeclaration,\n property: string,\n values: readonly T[],\n fallback: D,\n): T | D {\n const value = cs.getPropertyValue(property).trim() as T;\n return values.includes(value) ? value : fallback;\n}\n\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\n/** Only `justify` is blocked (its per-line extra word spacing is\n * fractional and off-grid). `center` is engine-quantized: the grid\n * paints each line at floor((W − line) / 2); the browser's own\n * (fractional) centering only touches the invisible light-DOM copy. */\nfunction authoredTextAlignBlocked(el: Element, cs: CSSStyleDeclaration): boolean {\n if (cs.textAlign === \"justify\") return true;\n // Hint fallback for environments that don't map `align` (happy-dom).\n return el.getAttribute(\"align\")?.toLowerCase() === \"justify\";\n}\n\nfunction readTextAlign(el: Element, cs: CSSStyleDeclaration): \"start\" | \"center\" | \"end\" {\n const value = cs.textAlign || el.getAttribute(\"align\")?.toLowerCase() || \"\";\n if (value === \"right\" || value === \"end\") return \"end\";\n // -webkit-center / -moz-center: the legacy `align` attribute's\n // computed form in real browsers.\n if (value === \"center\" || value.endsWith(\"-center\")) return \"center\";\n return \"start\";\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 ÷ font-size) − 1,\n * never negative. Computed line-height is always px (or `normal`); the\n * divisor is FONT-SIZE, not cell-height, so unitless ratios keep their\n * CSS meaning (`leading-loose` = 2 → 2 rows per line, 1 gap) even when\n * cell-height ≠ 1em (default `line-height: normal` on the root makes\n * the cell ~1.15em). */\nfunction lineGapRows(lineHeight: string, fontSizePx: number): number {\n if (!lineHeight || lineHeight === \"normal\" || fontSizePx <= 0) return 0;\n const px = parseFloat(lineHeight);\n if (!Number.isFinite(px)) return 0;\n return Math.max(0, Math.floor(px / fontSizePx + 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\n/** Computed `opacity`, clamped to [0, 1]; a non-numeric read is opaque. */\nfunction readOpacity(value: string): number {\n const parsed = parseFloat(value);\n return Number.isFinite(parsed) ? Math.min(1, Math.max(0, parsed)) : 1;\n}\n\n/** `text-indent` in cells. Percentages come through as `Npx` after\n * `getComputedStyle` only when a definite width is around, and even then\n * they'd need per-line resolution; treat them as 0. */\nfunction readTextIndent(cs: CSSStyleDeclaration, rootFontSizePx: number): number {\n const value = cs.textIndent;\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\nfunction readSize(\n csm: StylePropertyMapReadOnly | null,\n fallback: string,\n key: \"width\" | \"height\",\n rootFontSizePx: number,\n classAttr: string,\n inlineStyle: CSSStyleDeclaration,\n metrics: CellMetrics | undefined,\n): Size | undefined {\n // Viewport-relative lengths (h-screen, style=\"height: 100dvh\", …)\n // express PHYSICAL screen intent, so they convert via the measured\n // cell size, not the spacing scale (specs/cell-model.md\n // \"Viewport-relative lengths\"). The inline style attribute keeps the\n // authored unit verbatim — and inline beats classes, per cascade.\n const inlineViewport = viewportLengthPx(key === \"width\" ? inlineStyle.width : inlineStyle.height);\n if (inlineViewport !== null) {\n return { kind: \"cells\", value: physicalCells(inlineViewport, key, metrics, rootFontSizePx) };\n }\n const calc = authoredCalcCells(\n csm,\n key,\n fallback,\n classAttr,\n key === \"width\" ? \"w\" : \"h\",\n inlineStyle,\n metrics,\n rootFontSizePx,\n );\n if (calc !== undefined) return { kind: \"cells\", value: calc };\n // Class scan, every engine: computed values (Typed OM included)\n // resolve viewport units to plain px, indistinguishable from\n // spacing-scale lengths.\n const viewportPx = viewportUtilityPx(classAttr, key === \"width\" ? \"w\" : \"h\");\n if (viewportPx !== null) {\n // Confirm the utility is ACTIVE against the resolved value — an\n // inactive variant (md:h-screen below md) or an overriding inline\n // style resolves elsewhere and must win. When it agrees, prefer\n // the RESOLVED px: it also carries sv/lv/dv bases the innerWidth/\n // Height estimate can't know. No resolved value at all (headless\n // test env, stylesheet not loaded yet) trusts the scan.\n const resolved = parseFloat(csm ? String(csm.get(key) ?? \"\") : fallback);\n const agrees = Number.isFinite(resolved) && Math.abs(resolved - viewportPx) <= viewportPx * 0.3;\n if (agrees || !Number.isFinite(resolved)) {\n const px = agrees ? resolved : viewportPx;\n return { kind: \"cells\", value: physicalCells(px, key, metrics, rootFontSizePx) };\n }\n }\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 // Authored viewport units that survive to the computed string\n // (engine-dependent; arbitrary values like h-[50vh]).\n const authoredViewport = viewportLengthPx(s);\n if (authoredViewport !== null) {\n return {\n kind: \"cells\",\n value: physicalCells(authoredViewport, key, metrics, rootFontSizePx),\n };\n }\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 // Numeric spacing-scale utility (`h-7`, `w-0.5`, …): map the class\n // directly to cells. Match the Tailwind spacing scale (N * 0.25rem\n // = N cells) so we don't have to trust `cs.height` — same result\n // for most elements, but critical for <td>/<th> in Firefox where\n // `cs.height` returns the USED height from the table layout\n // (including rowspan effects), not the authored value.\n const numeric = new RegExp(`(?:^|[\\\\s:.[!])${axis}-(\\\\d+(?:\\\\.\\\\d+)?)(?![\\\\w-/])`).exec(\n classAttr,\n );\n if (numeric) return { kind: \"cells\", value: roundHalfAwayFromZero(Number(numeric[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/** Parse an authored viewport-relative length (\"100dvh\", \"50vw\", …)\n * into px against the current viewport. null for anything else. */\nfunction viewportLengthPx(value: string): number | null {\n const match = /^(-?[\\d.]+)((?:[dsl]?v)(?:h|w|min|max)|vi|vb)$/.exec(value.trim());\n if (!match || typeof window === \"undefined\") return null;\n const amount = parseFloat(match[1]!);\n if (!Number.isFinite(amount)) return null;\n const unit = match[2]!;\n const height = window.innerHeight;\n const width = window.innerWidth;\n const basis = unit.endsWith(\"h\")\n ? height\n : unit.endsWith(\"min\")\n ? Math.min(width, height)\n : unit.endsWith(\"max\")\n ? Math.max(width, height)\n : unit === \"vb\"\n ? height\n : width; // vw / vi\n return (amount / 100) * basis;\n}\n\n/** Tailwind viewport utilities (`h-screen`, `min-h-dvh`, `h-[95dvh]`,\n * …) → px. Scanned in EVERY engine (computed values resolve viewport\n * units to plain px); callers active-check the result. `prefix` is\n * the utility stem (\"h\", \"w\", \"min-h\", …). */\nfunction viewportUtilityPx(classAttr: string, prefix: string): number | null {\n if (typeof window === \"undefined\") return null;\n const named = new RegExp(`(?:^|[\\\\s:.[!])${prefix}-(screen|[dsl]v[hw])(?![\\\\w-])`).exec(\n classAttr,\n );\n if (named) {\n const name = named[1]!;\n // h-screen = 100vh, w-screen = 100vw; explicit units name their axis.\n if (name === \"screen\") return prefix.includes(\"h\") ? window.innerHeight : window.innerWidth;\n return name.endsWith(\"h\") ? window.innerHeight : window.innerWidth;\n }\n // Arbitrary viewport values: h-[95dvh], min-h-[50vh], …\n const arbitrary = new RegExp(\n `(?:^|[\\\\s:.[!])${prefix}-\\\\[(-?[\\\\d.]+(?:[dsl]?v(?:h|w|min|max)|vi|vb))\\\\]`,\n ).exec(classAttr);\n return arbitrary ? viewportLengthPx(arbitrary[1]!) : null;\n}\n\n/** Convert PHYSICAL px to cells on the given axis using the measured\n * cell size — viewport-relative lengths mean real screen distance, not\n * the spacing scale. Headless fallback: the spacing scale. */\nfunction physicalCells(\n px: number,\n key: \"width\" | \"height\",\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): number {\n const cellPx = key === \"width\" ? metrics?.width : metrics?.height;\n if (cellPx && cellPx > 0) return Math.max(0, Math.floor(px / cellPx));\n return pxToCells(px, rootFontSizePx);\n}\n\n/** An authored `calc()` length, evaluated PER TERM into cells\n * (specs/cell-model.md \"Mixed-unit calc()\"): viewport units through the\n * measured cell like `h-screen`, `rem` and `--spacing(N)` on the\n * spacing scale, `px` on the same scale — so `calc(100vh -\n * --spacing(2))` is \"the rows that fit, minus two\", which the single\n * computed px can no longer say. Sourced from the inline style or the\n * arbitrary-value utility (`max-h-[calc(…)]`, `_` for spaces), and\n * active-checked against the computed px like viewport utilities. A\n * term the evaluator does not model (%, em, var()) leaves the value to\n * the computed px. undefined = no authored calc. */\nfunction authoredCalcCells(\n csm: StylePropertyMapReadOnly | null,\n property: string,\n resolvedValue: string,\n classAttr: string,\n utilityPrefix: string,\n inlineStyle: CSSStyleDeclaration,\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): number | undefined {\n const key = property.endsWith(\"width\") ? \"width\" : \"height\";\n const inline = inlineStyle.getPropertyValue(property).trim();\n const fromInline = inline.startsWith(\"calc(\");\n // Six reads per element: the substring test spares the regex almost always.\n if (!fromInline && !classAttr.includes(\"-[calc(\")) return undefined;\n const utility = new RegExp(`(?:^|[\\\\s:.[!])${utilityPrefix}-\\\\[(calc\\\\([^\\\\]]*\\\\))\\\\]`).exec(\n classAttr,\n );\n const authored = fromInline ? inline : utility?.[1]?.replaceAll(\"_\", \" \");\n if (!authored) return undefined;\n const value = evaluateCalc(authored, key, metrics, rootFontSizePx);\n if (!value || value.unitless) return undefined;\n const cells = Math.max(0, roundHalfAwayFromZero(value.cells));\n // The inline style wins by cascade; a class needs the active-check: an\n // inactive variant or an overriding declaration resolves elsewhere — to\n // other px, or to a keyword (`none`, `auto`). No resolved value at all\n // (headless, stylesheet not loaded) trusts the class.\n if (fromInline) return cells;\n const resolvedText = (csm ? String(csm.get(property) ?? \"\") : resolvedValue).trim();\n const resolved = parseFloat(resolvedText);\n const agrees = Number.isFinite(resolved)\n ? Math.abs(resolved - value.px) <= Math.abs(value.px) * 0.3\n : resolvedText === \"\";\n return agrees ? cells : undefined;\n}\n\n/** A calc term carried two ways: the engine's cells (per-unit\n * semantics) and the px the browser computes (for the active-check). */\ninterface CalcValue {\n cells: number;\n px: number;\n unitless: boolean;\n}\n\n/** Recursive-descent evaluation of `calc()` arithmetic over lengths.\n * null for anything outside the modeled units. */\nfunction evaluateCalc(\n source: string,\n key: \"width\" | \"height\",\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): CalcValue | null {\n const tokens = source.match(/--spacing\\(\\s*-?[\\d.]+\\s*\\)|calc|[\\d.]+[a-z%]*|[()+\\-*/]/g);\n if (!tokens || tokens.join(\"\").replace(/\\s+/g, \"\") !== source.replace(/\\s+/g, \"\")) return null;\n let i = 0;\n const peek = (): string | undefined => tokens[i];\n const next = (): string | undefined => tokens[i++];\n const length = (cells: number, px: number): CalcValue => ({ cells, px, unitless: false });\n const term = (token: string): CalcValue | null => {\n const spacing = /^--spacing\\(\\s*(-?[\\d.]+)\\s*\\)$/.exec(token);\n if (spacing) {\n const n = parseFloat(spacing[1]!);\n return length(n, (n * rootFontSizePx) / 4);\n }\n const match = /^([\\d.]+)([a-z%]*)$/.exec(token);\n if (!match) return null;\n const amount = parseFloat(match[1]!);\n const unit = match[2]!;\n if (!Number.isFinite(amount)) return null;\n if (unit === \"\") return { cells: amount, px: amount, unitless: true };\n if (unit === \"px\") return length(amount / (rootFontSizePx / 4), amount);\n if (unit === \"rem\") return length(amount * 4, amount * rootFontSizePx);\n const viewport = viewportLengthPx(token);\n if (viewport === null) return null;\n return length(physicalCells(viewport, key, metrics, rootFontSizePx), viewport);\n };\n const combine = (op: string, a: CalcValue, b: CalcValue): CalcValue | null => {\n if (op === \"+\" || op === \"-\") {\n if (a.unitless !== b.unitless) return null;\n const sign = op === \"+\" ? 1 : -1;\n return { cells: a.cells + sign * b.cells, px: a.px + sign * b.px, unitless: a.unitless };\n }\n if (op === \"*\") {\n if (!a.unitless && !b.unitless) return null;\n const [n, v] = a.unitless ? [a, b] : [b, a];\n return { cells: v.cells * n.cells, px: v.px * n.px, unitless: v.unitless && n.unitless };\n }\n if (!b.unitless || b.px === 0) return null;\n return { cells: a.cells / b.cells, px: a.px / b.px, unitless: a.unitless };\n };\n const factor = (): CalcValue | null => {\n const token = next();\n if (token === undefined) return null;\n if (token === \"-\") {\n const value = factor();\n return value && { cells: -value.cells, px: -value.px, unitless: value.unitless };\n }\n if (token === \"calc\") return next() === \"(\" ? group() : null;\n if (token === \"(\") return group();\n return term(token);\n };\n const group = (): CalcValue | null => {\n const value = sum();\n return next() === \")\" ? value : null;\n };\n const product = (): CalcValue | null => {\n let value = factor();\n while (value && (peek() === \"*\" || peek() === \"/\")) {\n const op = next()!;\n const rhs = factor();\n value = rhs ? combine(op, value, rhs) : null;\n }\n return value;\n };\n const sum = (): CalcValue | null => {\n let value = product();\n while (value && (peek() === \"+\" || peek() === \"-\")) {\n const op = next()!;\n const rhs = product();\n value = rhs ? combine(op, value, rhs) : null;\n }\n return value;\n };\n const result = sum();\n return i === tokens.length ? result : null;\n}\n\n/** Viewport-relative min/max limit, when one is authored. Class scan\n * (`min-h-screen`, `min-h-[95dvh]`, …) — computed values resolve\n * viewport units to plain px in every engine, so the class list is the\n * only reliable signal — active-checked against the resolved value,\n * same rules as readSize's viewport branch. undefined = not\n * viewport-relative (caller falls through to the normal readLimit). */\nfunction viewportLimit(\n csm: StylePropertyMapReadOnly | null,\n property: string,\n resolvedValue: string,\n classAttr: string,\n utilityPrefix: string,\n inlineStyle: CSSStyleDeclaration,\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): number | undefined {\n const key = property.endsWith(\"width\") ? \"width\" : \"height\";\n // An authored viewport string — inline style (kept verbatim in the\n // style attribute) or a computed value that survives resolution —\n // is proof in itself: no active-check needed (or possible: parsing\n // it as px would misread \"100dvh\" as 100).\n const authoredPx =\n viewportLengthPx(inlineStyle.getPropertyValue(property)) ??\n viewportLengthPx(csm?.get(property)?.toString().trim() ?? \"\");\n if (authoredPx !== null) return physicalCells(authoredPx, key, metrics, rootFontSizePx);\n // Class scan needs the active-check, same rules as readSize's\n // viewport branch.\n const scanned = viewportUtilityPx(classAttr, utilityPrefix);\n if (scanned === null) return undefined;\n const resolvedText = (csm ? String(csm.get(property) ?? \"\") : resolvedValue).trim();\n const resolved = parseFloat(resolvedText);\n const agrees = Number.isFinite(resolved) && Math.abs(resolved - scanned) <= scanned * 0.3;\n // A keyword (`none`, `auto`) is a resolved value too: the utility lost.\n if (!agrees && resolvedText !== \"\") return undefined;\n return physicalCells(agrees ? resolved : scanned, key, metrics, rootFontSizePx);\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 { leafRendererFor, renderLeafContent } from \"./leaf.ts\";\nimport type { LeafRegistration } from \"./leaf.ts\";\nimport { pxToCells } from \"./metrics.ts\";\nimport { isTransparentColor, readCellStyle, trackingCells } from \"./style.ts\";\nimport { zeroInsets } from \"./types.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport {\n eachObjectMarker,\n hardLineSpans,\n INLINE_PAD,\n lineAdvance,\n OBJECT_REPLACEMENT,\n wrapLineCount,\n} from \"./wrap.ts\";\nimport type { CellMetrics, CharSourceRun, LayoutNode, PerSide } from \"./types.ts\";\n\n/** Per-textarea content width in cells, captured by the host BEFORE\n * the measuring attribute goes on — the engine's width rule is off\n * during measuring, so `textarea.clientWidth` read then would reflect\n * the browser-default width instead of our engine-assigned one (which\n * may itself be constrained by max-width / flex parent). */\nexport type TextareaWidths = Map<HTMLTextAreaElement, number>;\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 textareaWidths?: TextareaWidths,\n): LayoutNode | null {\n const style = readCellStyle(root, rootFontSizePx, cellMetrics);\n if (style.display === \"none\") return null;\n\n // Registered leaf renderers (specs/leaf-renderers.md) supply their\n // own grid content; children are skipped entirely. The light DOM\n // stays untouched — it keeps the a11y tree and select=\"text\"\n // semantics while the grid shows the rendered content.\n const leaf = leafRendererFor(root.tagName);\n if (leaf) return buildRendererLeaf(root, style, leaf);\n\n const elementChildren = Array.from(root.children);\n const roles = elementChildren.map(childRole);\n\n // Form controls are always leaves — descending into a <select>'s\n // <option>s would leak that text into the grid.\n const tag = root.tagName;\n const formControl = isFormControlTag(tag);\n\n if (!roles.includes(\"block\") || formControl) {\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 textareaWidths,\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 // Form controls with no explicit width would otherwise be 0 cells\n // wide (their leaf is empty; the value renders natively). Intrinsic\n // widths mirror the native ones: input's size attribute, textarea's\n // cols, and a select's option labels — the longest by default, the\n // SELECTED one under `field-sizing: content`, like the browser.\n let intrinsicWidth = longestLineAdvance(text, run.advances, style.tracking);\n if (formControl && intrinsicWidth === 0) {\n // Number(): happy-dom (tests) returns these attributes as strings.\n if (tag === \"INPUT\") intrinsicWidth = Number((root as HTMLInputElement).size) || 20;\n else if (tag === \"TEXTAREA\")\n intrinsicWidth = Number((root as HTMLTextAreaElement).cols) || 20;\n else {\n const select = root as HTMLSelectElement;\n // .label ?? .textContent: happy-dom (tests) lacks option.label.\n const labelOf = (option: HTMLOptionElement | undefined) =>\n option?.label || option?.textContent || \"\";\n const labels =\n getComputedStyle(root).getPropertyValue(\"field-sizing\") === \"content\"\n ? [labelOf(select.selectedOptions[0])]\n : Array.from(select.options, labelOf);\n intrinsicWidth = Math.max(1, ...labels.map((label) => label.trim().length));\n }\n }\n // Form controls always reserve at least one content row (native\n // shows a caret-height field even empty). CSS `min-height` can't\n // do it — it floors the outer box, which the border already\n // exceeds.\n const contentHeight = text.length > 0 ? countHardLines(text) : 0;\n let intrinsicHeight: number;\n if (tag === \"TEXTAREA\") {\n const textarea = root as HTMLTextAreaElement;\n const value = textarea.value ?? \"\";\n // Row count = wrap the value against the textarea's current\n // content-area width in cells (captured by the host pre-\n // measuring so it reflects the engine-assigned width, not the\n // browser default that applies while measuring is on). Pure\n // and monotonic, so the box grows AND shrinks as the width\n // changes — max-w-full under viewport resize, flex reflow,\n // typing that wraps. Fallback for the first-ever layout (no\n // snapshot yet): hard-line count only.\n const contentCells = textareaWidths?.get(textarea);\n // Unlike `<br>` (whose trailing break is dropped, per CSS),\n // a textarea SHOWS the empty line after a trailing `\\n` — that\n // extra visible row is where the caret sits after Enter.\n const trailingLine = value.endsWith(\"\\n\") ? 1 : 0;\n const wrappedLines =\n contentCells !== undefined && contentCells > 0\n ? wrapLineCount(value, contentCells) + trailingLine\n : value === \"\"\n ? 0\n : value.split(/\\r\\n?|\\n/).length;\n const rowsFloor =\n getComputedStyle(root).getPropertyValue(\"field-sizing\") === \"content\"\n ? 1\n : Number(textarea.rows) || 2;\n const lines = Math.max(rowsFloor, wrappedLines);\n // Leading: N lines occupy N + (N − 1) × gap rows, same as any\n // laid-out leaf (specs/cell-model.md \"Line height on the grid\").\n intrinsicHeight = lines + Math.max(0, lines - 1) * style.lineGap;\n } else if (formControl) {\n intrinsicHeight = Math.max(1, contentHeight);\n } else {\n intrinsicHeight = contentHeight;\n }\n // `children` in DOCUMENT order: paint-order ties (same z-index)\n // resolve as CSS would — later DOM wins — and the atomic inline\n // boxes come out in U+FFFC marker order (inlineBoxesOf). Direct\n // boxes interleave with out-of-flow siblings by construction; a\n // box nested in an inline ancestor is sorted into place.\n const directBoxes = new Map<Element, LayoutNode>();\n const nestedBoxes: LayoutNode[] = [];\n for (const box of run.boxes) {\n if (box.source.parentElement === root) directBoxes.set(box.source, box);\n else nestedBoxes.push(box);\n }\n const children: LayoutNode[] = [];\n for (let i = 0; i < elementChildren.length; i++) {\n const el = elementChildren[i]!;\n const box = directBoxes.get(el);\n if (box) children.push(box);\n else if (roles[i] === \"out-of-flow\") {\n const child = buildTree(el, rootFontSizePx, cellMetrics, textareaWidths);\n if (child) children.push(child);\n }\n }\n if (nestedBoxes.length > 0) {\n children.push(...nestedBoxes);\n children.sort((a, b) =>\n a.source.compareDocumentPosition(b.source) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1,\n );\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 const charSource = charSourceRuns(run);\n if (charSource.length > 0) node.charSource = charSource;\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, textareaWidths);\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/** A registered leaf renderer's node (specs/leaf-renderers.md): the\n * renderer's lines become the leaf's preformatted text (white-space\n * styling does not apply — the lines ARE the content), and its paint\n * runs ride the existing inline-run machinery as paint-only entries\n * with neutral geometry, so the painters need no new path. */\nfunction buildRendererLeaf(\n root: Element,\n style: ReturnType<typeof readCellStyle>,\n leaf: LeafRegistration,\n): LayoutNode {\n const content = renderLeafContent(leaf, root);\n const lines = content?.lines ?? [];\n const text = lines.join(\"\\n\");\n style.whiteSpace = \"pre\";\n // Replaced-element sizing (like <img>): auto width means intrinsic,\n // not stretch — and it must live HERE, not in companion CSS, because\n // Gecko's computed styles never surface intrinsic keywords (only the\n // class scan would see a `w-max`, and a stylesheet rule has neither).\n if (style.width === undefined || style.width.kind === \"auto\") {\n style.width = { kind: \"max-content\" };\n }\n // One cell per UTF-16 unit — consistent with the run mapping below\n // (astral glyph art is out of scope; fonts are BMP in practice) —\n // plus tracking, applied uniformly so the art stretches coherently\n // (columns stay aligned across rows, like letter-spacing on a pre).\n const advances = Array.from({ length: text.length }, () => 1 + style.tracking);\n const intrinsicWidth = longestLineAdvance(text, advances, style.tracking);\n const intrinsicHeight = lines.length;\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 (style.tracking > 0) node.advances = advances;\n const runs = content?.runs ?? [];\n if (runs.length > 0 && text.length > 0) {\n // Line start offsets into the joined text (newlines included).\n const lineStart: number[] = [0];\n for (const line of lines) lineStart.push(lineStart[lineStart.length - 1]! + line.length + 1);\n const charInline = Array.from({ length: text.length }, () => -1);\n node.inlineElements = runs.map((run) => ({\n element: root,\n tracking: 0,\n padLeft: 0,\n padRight: 0,\n insets: null,\n color: run.paint.color,\n backgroundColor: run.paint.backgroundColor,\n fontWeight: run.paint.fontWeight ?? \"\",\n fontStyle: run.paint.fontStyle ?? \"\",\n textDecorationLine: run.paint.textDecorationLine ?? \"\",\n }));\n runs.forEach((run, index) => {\n const line = lines[run.line];\n if (line === undefined) return;\n const from = Math.max(0, run.start);\n const to = Math.min(line.length, run.end);\n for (let col = from; col < to; col++) charInline[lineStart[run.line]! + col] = index;\n });\n node.charInline = charInline;\n }\n return node;\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 // Registered leaf renderers are always block participants — an\n // unstyled custom element computes to `inline`, which would fold\n // its semantic text into the parent's run instead of rendering.\n if (leafRendererFor(el.tagName)) return \"block\";\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: the source Text node and offset (`null`/-1 for\n * `<br>` newlines and markers). Compacted into `charSource` runs. */\n sourceNode: (Text | null)[];\n sourceOffset: 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 textareaWidths: TextareaWidths | 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 = {\n chars: [],\n advances: [],\n sourceNode: [],\n sourceOffset: [],\n inlineIndex: [],\n inlineElements: [],\n boxes: [],\n };\n collectRun(el, tracking, ctx, run);\n if (ctx.preserve) {\n // A final newline gets no line box of its own — the wrap layer's\n // dropFinalBreakSpan rule (the HTML parser already ate the one right\n // after the opening tag).\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 // Form controls render their value / caret / selection natively —\n // leave the leaf empty so the grid doesn't double-render, and skip\n // descending into their internals (e.g. <select>'s <option>s).\n if (isFormControlTag(el.tagName)) return;\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 const text = node.textContent ?? \"\";\n let offset = 0;\n for (const ch of text) {\n const at = offset;\n offset += ch.length;\n if (ch === \"\\r\") {\n if (text[offset] === \"\\n\") continue; // CRLF: the LF carries the break\n pushChar(run, \"\\n\", 0, node as Text, at);\n } else if (ch === \"\\n\") {\n pushChar(run, \"\\n\", 0, node as Text, at);\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 pushChar(run, \" \", 1, node as Text, at);\n }\n } else {\n pushChar(run, ch, 1 + tracking, node as Text, at);\n }\n }\n } else {\n // Collapsible white space (space/tab/CR/LF/FF) folds to one\n // space that keeps the first collapsed character's offset.\n let offset = 0;\n let inSpace = false;\n for (const ch of node.textContent ?? \"\") {\n const collapsible =\n ch === \" \" || ch === \"\\t\" || ch === \"\\r\" || ch === \"\\n\" || ch === \"\\f\";\n if (!collapsible) pushChar(run, ch, 1 + tracking, node as Text, offset);\n else if (!inSpace) pushChar(run, \" \", 1 + tracking, node as Text, offset);\n inSpace = collapsible;\n offset += ch.length;\n }\n }\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const child = node as Element;\n if (child.tagName === \"BR\") {\n pushChar(run, \"\\n\", 0, null, -1);\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, ctx.textareaWidths);\n if (box) {\n box.inlineBox = true;\n pushChar(run, OBJECT_REPLACEMENT, 1, null, -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 backgroundColor: isTransparentColor(cs.backgroundColor) ? undefined : cs.backgroundColor,\n fontWeight: cs.fontWeight,\n fontStyle: cs.fontStyle,\n textDecorationLine: cs.textDecorationLine,\n });\n const inlineIndex = run.inlineElements.length - 1;\n // Pad cells belong to the element too (its bg must fill them).\n for (let i = 0; i < padLeft; i++) {\n run.inlineIndex[run.chars.length] = inlineIndex;\n pushChar(run, INLINE_PAD, 1, null, -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.inlineIndex[run.chars.length] = inlineIndex;\n pushChar(run, INLINE_PAD, 1, null, -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 sourceNode: (Text | null)[] = [];\n const sourceOffset: 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 sourceNode.pop();\n sourceOffset.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 sourceNode.push(run.sourceNode[i] ?? null);\n sourceOffset.push(run.sourceOffset[i] ?? -1);\n inlineIndex.push(run.inlineIndex[i] ?? -1);\n }\n trimLineEnd();\n // Edge `\\n`s stay: every leading <br> creates a line box and all but\n // the final trailing one do (probed, all engines) — the wrap layer\n // drops exactly that last one (dropFinalBreakSpan).\n return {\n chars,\n advances,\n sourceNode,\n sourceOffset,\n inlineIndex,\n inlineElements: run.inlineElements,\n boxes: run.boxes,\n };\n}\n\nfunction pushChar(run: LeafRun, ch: string, advance: number, source: Text | null, offset: number) {\n run.chars.push(ch);\n run.advances.push(advance);\n run.sourceNode.push(source);\n run.sourceOffset.push(offset);\n}\n\n/** Compact the per-character source map into runs (`LayoutNode.charSource`):\n * a run grows while the next character continues the same Text node at\n * the next offset. */\nfunction charSourceRuns(run: LeafRun): CharSourceRun[] {\n const runs: CharSourceRun[] = [];\n let index = 0;\n for (let i = 0; i < run.chars.length; i++) {\n const ch = run.chars[i]!;\n const node = run.sourceNode[i];\n const offset = run.sourceOffset[i]!;\n const last = runs[runs.length - 1];\n if (node) {\n if (last && last.node === node && last.offset + last.length === offset)\n last.length += ch.length;\n else runs.push({ index, length: ch.length, node, offset });\n }\n index += ch.length;\n }\n return runs;\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 hardLineSpans(text).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/** True if `el` has any direct text child that isn't just whitespace. */\nexport function hasDirectText(el: Element): boolean {\n return Array.from(el.childNodes).some(\n (child) => child.nodeType === Node.TEXT_NODE && /[^ \\t\\r\\n\\f]/.test(child.textContent ?? \"\"),\n );\n}\n\n/** Author-facing warning when direct text can't be laid out alongside\n * block children — shared by the nested-container path here and the\n * host-level path in element.ts. */\nexport const DIRECT_TEXT_DROPPED =\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/** True for tags whose value/caret/selection are handled by the browser\n * natively — the tree builder treats them as empty leaves. */\nexport function isFormControlTag(tag: string): boolean {\n return tag === \"INPUT\" || tag === \"SELECT\" || tag === \"TEXTAREA\";\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 if (!hasDirectText(el)) return;\n node.droppedText = true;\n warnOnce(el, DIRECT_TEXT_DROPPED);\n}\n","import { hasSynthesizedTransitions, resolvePendingTransitions } from \"./animate.ts\";\nimport { onGlyphRegistryChange } from \"./glyphs.ts\";\nimport { leafObservedAttributes, leafRendererFor, onLeafRegistryChange } from \"./leaf.ts\";\nimport { hitChain, hitStack } from \"./pointer.ts\";\nimport { charIndexAtCell, renderPlainText, scrollbarGeometry, thumbSpan } from \"./plain-text.ts\";\nimport {\n classifySelection,\n comparePoints,\n isTextLeaf,\n positionOf,\n selectionRangeThrough,\n serializeSelection,\n wordAt,\n} from \"./selection.ts\";\nimport type { BoundaryPoints } from \"./selection.ts\";\nimport { nodeAtOffset, paintGrid } from \"./paint.ts\";\nimport { getRootFontSizePx, measureCellMetrics } from \"./metrics.ts\";\nimport { layoutRoot } from \"./layout.ts\";\nimport { render } from \"./render.ts\";\nimport { buildTree, DIRECT_TEXT_DROPPED, hasDirectText } from \"./tree.ts\";\nimport type { TextareaWidths } from \"./tree.ts\";\nimport { defaultCellStyle, zeroInsets } from \"./types.ts\";\nimport { warnSubject } from \"./warn.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%; background: inherit; }\n /* When the host hides its own dropped direct text (visibility, see\n * styles.css), the render layer must not sink with it. Scoped to that\n * state so an authored 'invisible' on the host stays intact. */\n :host([data-mw-dropped-text]) #viewport { visibility: visible; }\n /* The unified grid: one <pre> with same-paint-run spans, cell-precise\n * (one monospace character = one cell). In select=\"grid\" (the\n * default, reflected onto the attribute — see DEFAULT_SELECT) the\n * grid catches drags for native selection of the ASCII; interactive\n * elements opt back into pointer-events via styles.css so clicks\n * still work. In select=\"text\" the grid is inert to events and drag\n * selects the light DOM natively. */\n /* Sized by the engine's ink extent (element.ts), not the host box:\n * visible overflow paints past the host (specs/cell-model.md\n * \"Overflow\"), and the host's background follows it there — the\n * host is the canvas, as the root element's background covers a\n * document's overflow — inherited through #viewport, the shadow\n * parent. (A translucent host background paints repeatedly inside\n * the box.) */\n #grid { position: absolute; top: 0; left: 0; margin: 0; background: inherit; font: inherit; line-height: inherit; letter-spacing: inherit; white-space: pre; pointer-events: none; user-select: none; -webkit-user-select: none; }\n :host([select=\"grid\"]) #grid { pointer-events: auto; user-select: text; -webkit-user-select: text; }\n :host([select=\"grid\"]) slot { pointer-events: none; user-select: none; -webkit-user-select: none; }\n /* A live semantic selection (specs/semantic-selection.md) lifts the\n * lock so the element selection copies; pointer events stay off. */\n :host([select=\"grid\"][data-mw-semantic-selection]) slot { user-select: text; -webkit-user-select: text; }\n /* Selection invert — mirror of the canonical rule in styles.css\n * (which explains the field choices); update together. */\n ::selection { color: var(--mw-bg, canvas); text-shadow: 0 0 0 var(--mw-bg, canvas); background: var(--mw-fg, canvastext); }\n</style>\n<div id=\"viewport\">\n <pre id=\"grid\" aria-hidden=\"true\"></pre>\n <slot></slot>\n</div>\n`;\n\n/** The `select` attribute's default, reflected onto the attribute when\n * it is absent or unrecognized so every stylesheet keys on an explicit\n * value — the single place the default lives. */\nconst DEFAULT_SELECT = \"grid\";\n\n/** Set on the host while an element selection made by a semantic\n * gesture is live (specs/semantic-selection.md): the shadow stylesheet\n * lifts the grid-mode user-select lock under it. */\nconst SEMANTIC_SELECTION = \"data-mw-semantic-selection\";\n\ninterface Point {\n node: Node;\n offset: number;\n}\n\n/** A selectable unit — a word's or paragraph's DOM range. */\ninterface SelectionUnit {\n start: Point;\n end: Point;\n}\n\ninterface SemanticGesture {\n unit: \"word\" | \"paragraph\";\n anchor: SelectionUnit;\n}\n\n/** Light elements that legitimately receive pointer events in grid\n * mode — the styles.css opt-in list. Any other light target got the\n * event by a browser quirk (Firefox hit-tests a multicol spanner's\n * anonymous wrapper as its container despite pointer-events: none)\n * and is handled as a grid event at the same coordinates. */\nconst INTERACTIVE = \"a, button, input, select, textarea, label, [tabindex], [role='button']\";\n\nconst DYNAMIC_RELAYOUT_EVENTS = [\n \"pointerover\",\n \"pointerleave\",\n // `:active` styles (`active:opacity-50`) need a repaint on both edges\n // of a press — pointer and keyboard (Space/Enter activation).\n \"pointerdown\",\n \"pointerup\",\n \"pointercancel\",\n \"keydown\",\n \"keyup\",\n \"focusin\",\n \"focusout\",\n \"input\",\n \"change\",\n] as const;\n\n/** Transition properties the engine SAMPLES per animation frame (the\n * grid repaints with true mid-fade values): computed `color` stays live\n * under the text-fill lock, and nothing locks border colors or opacity.\n * Lock-owned properties (backgrounds, decoration color, geometry) are\n * snapped by the measuring/settling `transition-property` allow-list\n * instead — keep the two in sync (styles.css \"Lock toggles must\n * never…\"). */\nconst SAMPLED_TRANSITION = /^(color|opacity|border-(top|right|bottom|left)-color|border-color)$/;\n\n/** Safety valve for the sampling loop: a transition whose end/cancel\n * event never arrives (subtree torn down mid-fade) must not pin a rAF\n * loop forever. */\nconst SAMPLING_VALVE_MS = 30_000;\n\n/* Wheel-gesture model (specs/scrolling.md \"Gesture latching\"). */\n/** Ticks further apart than this begin a new gesture — and settle. */\nconst WHEEL_QUIESCE_MS = 200;\n/** Pointer jitter that still counts as stationary. */\nconst WHEEL_POINTER_SLOP_PX = 3;\n/** An undecided first tick this small is eaten, not latched. */\nconst WHEEL_LEAD_IN_PX = 4;\n/** Non-increasing ticks that confirm momentum. */\nconst INERTIA_TICKS = 8;\n/** Settle only once scrolling has gone QUIET after `scrollend`: a held\n * key fires scrollend after every step's animation, and an immediate\n * (instant) settle would cut the next step's animation short. */\nconst SETTLE_QUIESCE_MS = 100;\n/** Settle debounce where `scrollend` is missing (older Safari). */\nconst SETTLE_FALLBACK_MS = 160;\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 = [\"select\"];\n\n // Stylesheets can apply after a host's first layout (vite dev\n // injection, the CDN's in-browser Tailwind compile, HMR) — a pure\n // <head> mutation no per-host observer sees, which would otherwise\n // leave UA-styled geometry until an unrelated trigger. One shared\n // watcher relayouts every connected host on any head change (rare, and\n // relayout coalesces per frame); a still-loading <link> applies its CSS\n // at load time, so those get a one-shot listener too.\n static #headHosts = new Set<MonoWindElement>();\n static #headWatcher: MutationObserver | null = null;\n\n static #onHeadStylesChanged = (): void => {\n for (const host of MonoWindElement.#headHosts) host.#scheduleLayout();\n };\n\n static #watchLoadingLink(node: Node): void {\n if (node instanceof HTMLLinkElement && node.rel === \"stylesheet\" && !node.sheet) {\n node.addEventListener(\"load\", MonoWindElement.#onHeadStylesChanged, { once: true });\n }\n }\n\n static #watchHead(host: MonoWindElement): void {\n MonoWindElement.#headHosts.add(host);\n if (MonoWindElement.#headWatcher) return;\n // Stylesheets already in flight when the first host connects apply\n // without any head mutation — catch their loads too.\n for (const link of document.querySelectorAll(\"link[rel=stylesheet]\")) {\n MonoWindElement.#watchLoadingLink(link);\n }\n const watcher = new MutationObserver((records) => {\n for (const record of records) {\n for (const node of record.addedNodes) MonoWindElement.#watchLoadingLink(node);\n }\n MonoWindElement.#onHeadStylesChanged();\n });\n watcher.observe(document.head, { childList: true, subtree: true, characterData: true });\n MonoWindElement.#headWatcher = watcher;\n }\n\n static #unwatchHead(host: MonoWindElement): void {\n MonoWindElement.#headHosts.delete(host);\n if (MonoWindElement.#headHosts.size === 0) {\n MonoWindElement.#headWatcher?.disconnect();\n MonoWindElement.#headWatcher = null;\n }\n }\n\n #shadow: ShadowRoot;\n #grid: 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 #unsubscribeLeafRegistry: (() => void) | null = null;\n #unsubscribeGlyphRegistry: (() => void) | null = null;\n #paintPending = false;\n /** Scroll containers of the LAST layout (specs/scrolling.md). */\n #scrollNodes: LayoutNode[] = [];\n #settleTimers = new Map<Element, ReturnType<typeof setTimeout>>();\n /** Last routed-wheel activity per scroll container: each scrollBy is a separate\n * PROGRAMMATIC scroll, so the browser fires scrollend between wheel\n * ticks — mid-gesture settles would keep snapping small deltas back\n * (the \"resistance\"). Recent activity suppresses them; the wheel\n * quiesce timer settles instead. */\n #routedWheelAt = new WeakMap<Element, number>();\n /** What the current wheel gesture is LATCHED to — a scroll container, or the\n * page (`el: null`): chaining is a gesture-START decision (native\n * scroll-chaining semantics), so mid-gesture boundary hits stay on\n * the scroll container and a scroll container sliding under the pointer never captures a\n * page gesture. `mag`/`decayed` track the delta trend (see\n * #onWheel). */\n #wheelLatch: WheelLatch | null = null;\n #thumbDrag: ThumbDrag | null = null;\n /** The last primary pointerdown's type: a `mousedown` counts as a\n * semantic gesture only after a mouse or pen (a tap's compatibility\n * mousedown follows a touch pointerdown). */\n #lastPointerType = \"\";\n #semanticGesture: SemanticGesture | null = null;\n /** An engine-driven grid drag, anchored at a flat text offset: the\n * fallback when a plain mousedown lands on a phantom light target\n * (see INTERACTIVE), where no native selection can start. */\n #gridDrag: { anchor: number } | null = null;\n /** A primary press that landed on the grid: the first pointermove with\n * the button down marks the host `data-mw-dragging`, which drops\n * interactive light elements' pointer events so a native drag sweeps\n * through their cells instead of stalling at their edge. */\n #pressOnGrid = false;\n /** Native scrollers outside the host (ancestors with scrollable\n * overflow, then the page), collected per layout so a wheel tick\n * never reads computed styles (see #outsideCanScroll). */\n #outerScrollers: Element[] = [];\n\n /** (Re-)observe the light DOM; re-run when the leaf registry adds\n * observed attributes to the filter. `observe` on the same target\n * replaces the previous options in place. */\n #observeLightDom(): void {\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 // leaf renderers declare theirs at registration.\n attributeFilter: [\n \"class\",\n \"style\",\n \"colspan\",\n \"rowspan\",\n \"span\",\n ...leafObservedAttributes(),\n ],\n });\n }\n\n constructor() {\n super();\n this.#shadow = this.attachShadow({ mode: \"open\" });\n this.#shadow.innerHTML = SHADOW_TEMPLATE;\n this.#grid = this.#shadow.getElementById(\"grid\") 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 // attributeChangedCallback only fires on changes; an absent\n // attribute reflects its default here.\n if (!this.hasAttribute(\"select\")) this.setAttribute(\"select\", DEFAULT_SELECT);\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 this.#observeSurroundings();\n // The probe too: a freshly inserted probe can transiently font-match\n // the FALLBACK at first layout even when the real font is already\n // loaded (WebKit; no fonts event ever follows). The swap changes the\n // probe's size, so observing it is the missing re-measure signal.\n // (The probe is absolutely positioned, hence blockified — inline\n // boxes would be unobservable.)\n this.#resizeObserver.observe(this.#probe);\n // Viewport-relative lengths (h-screen, h-[95dvh], …) read\n // window.innerWidth/Height at layout time; a window resize that\n // doesn't change the HOST's size (height-only, typically) would\n // otherwise never retrigger them.\n window.addEventListener(\"resize\", this.#onWindowResize);\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.#observeLightDom();\n // Leaf renderers (specs/leaf-renderers.md): a registration or\n // invalidation after this host's first layout must repaint it, and\n // new observed attributes must join the filter.\n this.#unsubscribeLeafRegistry = onLeafRegistryChange(() => {\n this.#observeLightDom();\n this.#scheduleLayout();\n });\n this.#unsubscribeGlyphRegistry = onGlyphRegistryChange(() => this.#scheduleLayout());\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 // Pseudo-classes (:hover/:focus-visible/:active) and form-control\n // value changes flip computed styles without any MutationObserver\n // signal. Delegated events on the host schedule a relayout; the\n // rAF debouncer collapses hover storms into at most one per frame.\n for (const evt of DYNAMIC_RELAYOUT_EVENTS) {\n this.addEventListener(evt, this.#scheduleDynamicRelayout);\n }\n\n // Animation sampling (specs/cell-model.md \"Animation\"): a running\n // transition of a sampled property re-lays-out every frame, so the\n // grid repaints with the browser's own interpolated values.\n this.addEventListener(\"transitionrun\", this.#onTransitionRun);\n this.addEventListener(\"transitionend\", this.#onTransitionDone);\n this.addEventListener(\"transitioncancel\", this.#onTransitionDone);\n\n // Synthesized pointer states (specs/cell-model.md \"Pointer\n // states\"): under select=\"grid\" the light DOM is pointer-events:\n // none, so :hover/:active can't match — the engine hit-tests the\n // pointer's cell and marks the chain with data-mw-hover /\n // data-mw-active (utilities.css retargets the Tailwind variants).\n this.addEventListener(\"pointermove\", this.#onPointerMove);\n this.addEventListener(\"pointerleave\", this.#onPointerLeave);\n this.addEventListener(\"pointerdown\", this.#onPointerDown);\n // Scroll events don't bubble — capture catches every light-DOM\n // container's scroll (specs/scrolling.md).\n this.addEventListener(\"scroll\", this.#onScroll, { capture: true, passive: true });\n this.addEventListener(\"scrollend\", this.#onScrollEnd, { capture: true });\n this.addEventListener(\"wheel\", this.#onWheel, { passive: false });\n // A selection in the light DOM copies as the engine's plain text\n // (specs/semantic-selection.md): the browsers' serializers lose\n // block breaks for the out-of-flow boxes the render uses.\n this.addEventListener(\"copy\", this.#onCopy);\n // Multi-click gestures (specs/semantic-selection.md): the click\n // count rides mousedown (PointerEvent.detail is 0).\n this.addEventListener(\"mousedown\", this.#onMouseDown);\n document.addEventListener(\"selectionchange\", this.#onSelectionChange);\n // Release on the window: a selection drag routinely ends outside\n // the host, and the press state must thaw wherever it ends.\n window.addEventListener(\"pointerup\", this.#onPointerUp);\n window.addEventListener(\"pointercancel\", this.#onPointerUp);\n // Content scrolling under a stationary pointer moves cells beneath\n // it — native :hover re-evaluates there, so the synthesis must\n // too. Capture catches nested scrollers (scroll doesn't bubble).\n document.addEventListener(\"scroll\", this.#onAnyScroll, { capture: true, passive: true });\n\n MonoWindElement.#watchHead(this);\n this.#scheduleLayout();\n }\n\n disconnectedCallback(): void {\n window.removeEventListener(\"resize\", this.#onWindowResize);\n this.#resizeObserver?.disconnect();\n this.#mutationObserver?.disconnect();\n this.#resizeObserver = null;\n this.#mutationObserver = null;\n this.#unsubscribeLeafRegistry?.();\n this.#unsubscribeLeafRegistry = null;\n this.#unsubscribeGlyphRegistry?.();\n this.#unsubscribeGlyphRegistry = null;\n document.fonts?.removeEventListener(\"loadingdone\", this.#onFontsLoaded);\n for (const evt of DYNAMIC_RELAYOUT_EVENTS) {\n this.removeEventListener(evt, this.#scheduleDynamicRelayout);\n }\n this.removeEventListener(\"transitionrun\", this.#onTransitionRun);\n this.removeEventListener(\"transitionend\", this.#onTransitionDone);\n this.removeEventListener(\"transitioncancel\", this.#onTransitionDone);\n this.#activeTransitions = 0;\n this.removeEventListener(\"pointermove\", this.#onPointerMove);\n this.removeEventListener(\"pointerleave\", this.#onPointerLeave);\n this.removeEventListener(\"pointerdown\", this.#onPointerDown);\n this.removeEventListener(\"scroll\", this.#onScroll, { capture: true });\n this.removeEventListener(\"scrollend\", this.#onScrollEnd, { capture: true });\n this.removeEventListener(\"wheel\", this.#onWheel);\n this.removeEventListener(\"copy\", this.#onCopy);\n this.removeEventListener(\"mousedown\", this.#onMouseDown);\n document.removeEventListener(\"selectionchange\", this.#onSelectionChange);\n for (const timer of this.#settleTimers.values()) clearTimeout(timer);\n this.#settleTimers.clear();\n this.#thumbDrag = null;\n this.#wheelLatch = null;\n window.removeEventListener(\"pointerup\", this.#onPointerUp);\n window.removeEventListener(\"pointercancel\", this.#onPointerUp);\n document.removeEventListener(\"scroll\", this.#onAnyScroll, { capture: true });\n this.#hoverClient = null;\n this.#pressTarget = null;\n this.#pressing = false;\n this.#paintHeld = false;\n this.#updatePointerStates();\n MonoWindElement.#unwatchHead(this);\n }\n\n /* === Synthesized pointer states ==================================== */\n\n #hovered = new Set<Element>();\n #pressed = new Set<Element>();\n #pressTarget: Element | null = null;\n #pressing = false;\n #paintHeld = false;\n #hoverClient: { x: number; y: number } | null = null;\n #hoverCol = NaN;\n #hoverRow = NaN;\n #gridOrigin: { left: number; top: number } | null = null;\n static #hoverCapable = typeof matchMedia === \"undefined\" ? null : matchMedia(\"(hover: hover)\");\n\n /** Paint-only pass (specs/scrolling.md): reruns paintGrid from the\n * last layout with current scroll offsets — no measuring, no\n * layout. Scroll events coalesce into one frame. */\n #schedulePaint(): void {\n // A queued layout repaints (and re-syncs offsets) itself.\n if (this.#paintPending || this.#layoutPending) return;\n this.#paintPending = true;\n // rAF, with a timeout backstop: headless/backgrounded Firefox can\n // throttle rAF into never firing, freezing scroll mirroring.\n let done = false;\n const run = (): void => {\n if (done) return;\n done = true;\n this.#paintPending = false;\n const metrics = this.#cellMetrics;\n if (!this.isConnected || !this.#lastLayout || !metrics) return;\n this.#syncScrollOffsets(metrics);\n this.#paintHeld = !paintGrid(this.#lastLayout, this.#grid, this.#holdsNativeDrag());\n // The cells under a stationary pointer changed with the scroll.\n this.#updatePointerStates();\n };\n requestAnimationFrame(run);\n setTimeout(run, 50);\n }\n\n /** Per-container offsets for the paint: from the pre-mask snapshot during\n * a layout pass (native reads are clamped inside the mask; pins\n * resolve to the NEW max), from the live position on a scroll\n * repaint. */\n #syncScrollOffsets(metrics: CellMetrics, snapshot?: ScrollSnapshot): void {\n for (const node of this.#scrollNodes) {\n const el = node.source as HTMLElement;\n const { maxX, maxY } = node.scrollRange!;\n const entry = snapshot?.get(el);\n node.scroll = entry\n ? {\n x: entry.pinX ? maxX : Math.min(entry.x, maxX),\n y: entry.pinY ? maxY : Math.min(entry.y, maxY),\n }\n : this.#quantize(node, metrics);\n }\n }\n\n /** A container's native position in cells (see scrollCells), ties\n * broken away from the last painted offset. */\n #quantize(node: LayoutNode, metrics: CellMetrics): { x: number; y: number } {\n const el = node.source as HTMLElement;\n const { maxX, maxY } = node.scrollRange!;\n const base = node.scroll ?? { x: 0, y: 0 };\n return {\n x: scrollCells(el, \"x\", metrics.width, maxX, base.x),\n y: scrollCells(el, \"y\", metrics.height, maxY, base.y),\n };\n }\n\n /** Snapshot of every scroll container's native position, taken BEFORE the\n * measuring mask goes on: the mask collapses container geometry (the\n * range spacer is off) and browsers clamp native positions during\n * that reflow — Chromium eagerly, Firefox lazily — so any read inside\n * the pass is wrong. Bottom-stick rides along: a scroll container settled at a\n * real end (pre-layout max > 0) re-pins to the NEW max. */\n #captureScrollState(): ScrollSnapshot {\n const snapshot: ScrollSnapshot = new Map();\n const metrics = this.#cellMetrics;\n if (!metrics) return snapshot;\n for (const node of this.#scrollNodes) {\n const el = node.source as HTMLElement;\n const { maxX, maxY } = node.scrollRange!;\n const { x, y } = this.#quantize(node, metrics);\n snapshot.set(el, {\n top: el.scrollTop,\n left: el.scrollLeft,\n x,\n y,\n pinX: maxX > 0 && x >= maxX,\n pinY: maxY > 0 && y >= maxY,\n });\n }\n return snapshot;\n }\n\n /** Write the snapshot back after the unmask (pins to the native\n * ceiling — the new max). Firefox and WebKit hold post-reflow scroll\n * clamping in a lazy state where a write that looks like the\n * pre-clamp value coalesces with the pending clamp into \"no\n * change\" — no scroll event, and the container desyncs. Reading\n * FIRST commits the clamp, so the write is a real change (same-value\n * writes are no-ops). */\n #restoreScrollPositions(snapshot: ScrollSnapshot): void {\n for (const node of this.#scrollNodes) {\n const el = node.source as HTMLElement;\n const entry = snapshot.get(el);\n if (!entry) continue;\n void el.scrollTop;\n void el.scrollLeft;\n el.scrollTop = entry.pinY ? el.scrollHeight : entry.top;\n el.scrollLeft = entry.pinX ? el.scrollWidth : entry.left;\n }\n }\n\n /** Arm (or re-arm) a pane's settle for after `delay` of quiet. */\n #settleAfter(el: HTMLElement, delay: number): void {\n clearTimeout(this.#settleTimers.get(el));\n this.#settleTimers.set(\n el,\n setTimeout(() => this.#settle(el), delay),\n );\n }\n\n #onScroll = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof HTMLElement) || target === this) return;\n if (!target.hasAttribute(\"data-mw-scroll\")) return;\n this.#schedulePaint();\n // Routed wheel ticks keep their own quiesce timer (#onWheel).\n if (Date.now() - (this.#routedWheelAt.get(target) ?? 0) < WHEEL_QUIESCE_MS) return;\n // Still scrolling: a pending settle waits; without scrollend\n // (older Safari) the pause after the last event settles instead.\n clearTimeout(this.#settleTimers.get(target));\n if (!(\"onscrollend\" in window)) this.#settleAfter(target, SETTLE_FALLBACK_MS);\n };\n\n #onScrollEnd = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof HTMLElement) || target === this) return;\n if (!target.hasAttribute(\"data-mw-scroll\")) return;\n // Mid-gesture scrollends: routed wheel ticks and thumb drags\n // settle on quiesce/release instead (see #routedWheelAt).\n if (Date.now() - (this.#routedWheelAt.get(target) ?? 0) < WHEEL_QUIESCE_MS) return;\n this.#settleAfter(target, SETTLE_QUIESCE_MS);\n };\n\n /** Snap the native position to the cell the grid already SHOWS\n * (the same quantization as the paint) — never a different cell,\n * or the grid would visibly jump after the gesture. Idempotent: its\n * own scroll event changes no cell. The max cell settles on the\n * native CEILING, not the multiple: leftover native room would\n * latch the next text-mode gesture to an invisible scroll instead\n * of chaining. */\n #settle(el: HTMLElement): void {\n if (this.#thumbDrag?.el === el) return; // release settles\n // Repaint unconditionally: scroll events can coalesce away under\n // load (observed in Firefox), and the settle is the gesture's\n // reliable terminal signal — a current grid makes this a no-op.\n this.#schedulePaint();\n const metrics = this.#cellMetrics;\n const node = this.#scrollNodes.find((candidate) => candidate.source === el);\n if (!metrics || !node) return;\n const range = node.scrollRange!;\n // The painted cell: the settle lands where the grid already is.\n const cells = node.scroll ?? this.#quantize(node, metrics);\n const top =\n cells.y === range.maxY ? el.scrollHeight - el.clientHeight : cells.y * metrics.height;\n const left = cells.x === range.maxX ? el.scrollWidth - el.clientWidth : cells.x * metrics.width;\n if (Math.abs(el.scrollTop - top) > 0.5 || Math.abs(el.scrollLeft - left) > 0.5) {\n el.scrollTo({ top, left, behavior: \"instant\" });\n }\n }\n\n /** Grid-mode wheel routing (specs/scrolling.md): the light DOM is\n * pointer-inert, so the engine hit-tests the cell and scrolls the\n * nearest consuming container — chaining OUTWARD per axis, since\n * programmatic scrollBy never chains natively. preventDefault only\n * for ticks a scroll container owns, so page scrolling survives. */\n #onWheel = (event: Event): void => {\n if (this.getAttribute(\"select\") !== \"grid\") return;\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n if (!layout || !metrics || this.#scrollNodes.length === 0) return;\n const e = event as WheelEvent;\n const scale = e.deltaMode === 1 ? metrics.height : e.deltaMode === 2 ? this.clientHeight : 1;\n const dx = e.deltaX * scale;\n const dy = e.deltaY * scale;\n // Chromium marks every tick after an uncanceled first one in a\n // native scroll sequence non-cancelable: the page owns that\n // gesture — unless nothing outside the host can scroll that way,\n // where routing is the only thing the tick can usefully do.\n if (!e.cancelable && this.#outsideCanScroll(dx, dy)) return;\n const { col, row } = this.#cellAt(e.clientX, e.clientY, metrics);\n const now = Date.now();\n const mag = Math.abs(dx) + Math.abs(dy);\n // Zero-delta ticks mark gesture phases (Safari's, and Chromium's\n // momentum cancel when a finger lands mid-inertia): a boundary.\n // Canceled, so a sequence they open stays cancelable.\n if (mag === 0) {\n this.#wheelLatch = null;\n e.preventDefault();\n return;\n }\n // Native room decides (the native ceiling IS the engine's max);\n // an axis without engine range never consumes.\n const canMove = (node: LayoutNode): boolean => {\n const range = node.scrollRange!;\n const el = node.source as HTMLElement;\n if (dy !== 0 && range.maxY > 0) {\n if (\n (dy > 0 && el.scrollTop < el.scrollHeight - el.clientHeight - 0.5) ||\n (dy < 0 && el.scrollTop > 0.5)\n )\n return true;\n }\n if (dx !== 0 && range.maxX > 0) {\n if (\n (dx > 0 && el.scrollLeft < el.scrollWidth - el.clientWidth - 0.5) ||\n (dx < 0 && el.scrollLeft > 0.5)\n )\n return true;\n }\n return false;\n };\n // Gesture boundaries without native phase info: a gesture ends\n // when ticks quiesce or the delta RISES after confirmed inertia —\n // momentum never rises (it often repeats a delta: 3, 3, 2, 2, 1…),\n // finger ticks wobble — so a scroll container at its end hands a new push to\n // the page instead of blocking until the inertia dies. Confirmed\n // inertia STICKS: a new push usually starts below the momentum it\n // interrupts, and only its second tick rises. Momentum follows the\n // pointer (its ticks land wherever the cursor went), so after a\n // move a same-axis tick that continues the decay is still the old\n // gesture; any rise or a new dominant axis is the new one.\n const latch = this.#wheelLatch;\n const axis = Math.abs(dx) >= Math.abs(dy) ? \"x\" : \"y\";\n const rise = latch !== null && mag > latch.mag * 1.25 + 1;\n const moved =\n latch !== null &&\n (Math.abs(e.clientX - latch.x) > WHEEL_POINTER_SLOP_PX ||\n Math.abs(e.clientY - latch.y) > WHEEL_POINTER_SLOP_PX);\n const inertia = latch !== null && latch.decayed >= INERTIA_TICKS;\n const held =\n latch !== null &&\n now - latch.at < WHEEL_QUIESCE_MS &&\n axis === latch.axis &&\n (moved ? mag <= latch.mag : !(inertia && rise));\n let target: LayoutNode | null = null;\n if (held) {\n const smooth = mag <= latch.mag && mag >= latch.mag * 0.5;\n latch.decayed = smooth ? latch.decayed + 1 : inertia ? latch.decayed : 0;\n latch.mag = mag;\n latch.at = now;\n if (!latch.el) return; // the page's gesture\n target = this.#scrollNodes.find((node) => node.source === latch.el) ?? null;\n }\n if (!target) {\n const stack = hitStack(layout, col, row);\n for (let i = stack.length - 1; i >= 0; i--) {\n const node = stack[i]!.node;\n if (!node.scrollRange) continue;\n if (canMove(node)) {\n target = node;\n break;\n }\n // At its boundary already: chain outward only if this scroll container's\n // overscroll-behavior allows it on the gesture's axis.\n const overscroll = node.style.overscroll;\n if ((dy !== 0 && !overscroll.y) || (dx !== 0 && !overscroll.x)) {\n target = node; // contain/none: the gesture stays here, inert\n break;\n }\n }\n // A swipe's first tick often carries only a tiny cross-axis\n // delta; over a scroll container that cannot consume it, it decides nothing\n // yet: eaten (keeping the sequence cancelable), unlatched — the\n // next, decisive tick picks the scroll container.\n if (!target && mag < WHEEL_LEAD_IN_PX) {\n e.preventDefault();\n return;\n }\n this.#wheelLatch = {\n el: target ? (target.source as HTMLElement) : null,\n x: e.clientX,\n y: e.clientY,\n axis,\n at: now,\n mag,\n decayed: 0,\n };\n }\n if (!target) return; // the page's gesture\n e.preventDefault();\n if (!canMove(target)) return; // latched at the boundary: consume, no chain\n const el = target.source as HTMLElement;\n const range = target.scrollRange!;\n const apply: ScrollToOptions = { behavior: \"instant\" };\n if (dy !== 0 && range.maxY > 0) apply.top = dy;\n if (dx !== 0 && range.maxX > 0) apply.left = dx;\n el.scrollBy(apply);\n // One gesture, not N programmatic scrolls: suppress the per-tick\n // scrollend settles and settle after quiesce.\n this.#routedWheelAt.set(el, now);\n this.#settleAfter(el, WHEEL_QUIESCE_MS);\n };\n\n /** Whether a native scroller outside the host has room in the\n * delta's direction (offset reads only — the list is per layout). */\n #outsideCanScroll(dx: number, dy: number): boolean {\n return this.#outerScrollers.some(\n (el) =>\n (dy > 0 && el.scrollTop < el.scrollHeight - el.clientHeight - 0.5) ||\n (dy < 0 && el.scrollTop > 0.5) ||\n (dx > 0 && el.scrollLeft < el.scrollWidth - el.clientWidth - 0.5) ||\n (dx < 0 && el.scrollLeft > 0.5),\n );\n }\n\n /** The host's width is capped to whole cells (styles.css), so a\n * growing slot no longer resizes the host: observe the parent (a\n * growing container) and the siblings (a flex or grid slot that\n * grows because a sibling shrank). Re-run per layout — observe() is\n * idempotent, and new siblings join. */\n #observeSurroundings(): void {\n const parent = this.parentElement;\n if (!parent || !this.#resizeObserver) return;\n this.#resizeObserver.observe(parent);\n for (const sibling of parent.children) {\n if (sibling !== this) this.#resizeObserver.observe(sibling);\n }\n }\n\n /** The grid cell under a client point. The origin is cached until\n * the next layout or page scroll invalidates it. */\n #cellAt(clientX: number, clientY: number, metrics: CellMetrics): { col: number; row: number } {\n if (!this.#gridOrigin) {\n const rect = this.#grid.getBoundingClientRect();\n this.#gridOrigin = { left: rect.left, top: rect.top };\n }\n return {\n col: Math.floor((clientX - this.#gridOrigin.left) / metrics.width),\n row: Math.floor((clientY - this.#gridOrigin.top) / metrics.height),\n };\n }\n\n /** A pointerdown on a visible gutter bar begins a thumb drag —\n * engine-routed in BOTH modes (the gutter is grid ink; there is no\n * native scrollbar). Proportional: the draggable track maps onto\n * the scroll range. */\n #gutterDragAt(clientX: number, clientY: number): ThumbDrag | null {\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n if (!layout || !metrics || this.#scrollNodes.length === 0) return null;\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n const stack = hitStack(layout, col, row);\n for (let i = stack.length - 1; i >= 0; i--) {\n const { node, x, y } = stack[i]!;\n const range = node.scrollRange;\n if (!range) continue;\n const el = node.source as HTMLElement;\n const { y: yBar, x: xBar } = scrollbarGeometry(node, x, y);\n if (\n yBar &&\n range.maxY > 0 &&\n col >= yBar.col &&\n col < yBar.col + yBar.thick &&\n row >= yBar.row &&\n row < yBar.row + yBar.len\n ) {\n const thumbLen = thumbSpan(yBar.len, range.sizeY, range.maxY, 0).len;\n const draggablePx = Math.max(1, (yBar.len - thumbLen) * metrics.height);\n return {\n el,\n axis: \"y\",\n startClient: clientY,\n startPx: el.scrollTop,\n factor: (range.maxY * metrics.height) / draggablePx,\n };\n }\n if (\n xBar &&\n range.maxX > 0 &&\n row >= xBar.row &&\n row < xBar.row + xBar.thick &&\n col >= xBar.col &&\n col < xBar.col + xBar.len\n ) {\n const thumbLen = thumbSpan(xBar.len, range.sizeX, range.maxX, 0).len;\n const draggablePx = Math.max(1, (xBar.len - thumbLen) * metrics.width);\n return {\n el,\n axis: \"x\",\n startClient: clientX,\n startPx: el.scrollLeft,\n factor: (range.maxX * metrics.width) / draggablePx,\n };\n }\n }\n return null;\n }\n\n #onPointerMove = (event: Event): void => {\n if (isTouchInProgress(event)) return; // see #scheduleDynamicRelayout\n const { clientX, clientY } = event as PointerEvent;\n const drag = this.#thumbDrag;\n if (drag) {\n const delta = (drag.axis === \"y\" ? clientY : clientX) - drag.startClient;\n const target = drag.startPx + delta * drag.factor;\n if (drag.axis === \"y\") drag.el.scrollTop = target;\n else drag.el.scrollLeft = target;\n return;\n }\n const held = ((event as PointerEvent).buttons & 1) !== 0;\n if (held && this.#semanticGesture)\n this.#extendSemantic(this.#semanticGesture, clientX, clientY);\n if (held && this.#gridDrag) this.#extendGridDrag(this.#gridDrag, clientX, clientY);\n if (held && this.#pressOnGrid && !this.hasAttribute(\"data-mw-dragging\")) {\n this.setAttribute(\"data-mw-dragging\", \"\");\n }\n this.#hoverClient = { x: clientX, y: clientY };\n // High-frequency path: skip the update while the pointer stays in\n // the same cell (state can only change with the cell — relayouts\n // and scrolls have their own refresh calls).\n const metrics = this.#cellMetrics;\n if (metrics) {\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n if (col === this.#hoverCol && row === this.#hoverRow) return;\n }\n this.#updatePointerStates();\n };\n\n #onCopy = (event: Event): void => {\n const { clipboardData } = event as ClipboardEvent;\n const layout = this.#lastLayout;\n const range = this.#elementSelection();\n if (!clipboardData || !layout || !range) return;\n clipboardData.setData(\"text/plain\", serializeSelection(layout, range));\n event.preventDefault();\n };\n\n /** Double- and triple-click on the grid select the element's word or\n * paragraph (specs/semantic-selection.md); a plain click ends a\n * semantic selection's lift synchronously, ahead of selectionchange. */\n #onMouseDown = (event: Event): void => {\n const e = event as MouseEvent;\n if (e.button !== 0 || this.getAttribute(\"select\") !== \"grid\") return;\n const onGrid = e.composedPath().includes(this.#grid);\n if (!onGrid && !this.#isPhantomTarget(e.target)) return;\n const finePointer = this.#lastPointerType === \"mouse\" || this.#lastPointerType === \"pen\";\n if (e.detail <= 1) {\n if (e.detail !== 1) return;\n this.removeAttribute(SEMANTIC_SELECTION);\n // A press that blurs a control inside the host repaints the focus\n // invert — a structural rebuild a native drag anchor would not\n // survive (paintGrid holds those until release). Take such a\n // press over, like a phantom one: blur now, drag through the\n // engine.\n const focused = this.#focusedInside();\n if (finePointer && (!onGrid || focused)) {\n focused?.blur();\n this.#startGridDrag(e);\n }\n return;\n }\n if (!finePointer) return;\n const unit = e.detail === 2 ? \"word\" : \"paragraph\";\n const selection = document.getSelection();\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n if (!selection || !layout || !metrics) return;\n const { col, row } = this.#cellAt(e.clientX, e.clientY, metrics);\n const target = this.#unitAt(col, row, unit);\n if (!target) {\n // No word or paragraph under the cell (a gap, a border, a blank):\n // the browser's own gesture on the grid — a run of glyphs, or the\n // grid line on a triple-click.\n this.removeAttribute(SEMANTIC_SELECTION);\n this.#semanticGesture = null;\n return;\n }\n // Ours from here: no native word/whole-grid selection, no native\n // drag. A canceled mousedown moves no focus, so move it as the\n // click would have (a focused control would otherwise keep the\n // copy command).\n e.preventDefault();\n this.#focusedInside()?.blur();\n this.#liftLock(target);\n // Shift extends the existing element selection from its anchor.\n const anchor: SelectionUnit =\n e.shiftKey && selection.anchorNode && this.#elementSelection()\n ? pointUnit({ node: selection.anchorNode, offset: selection.anchorOffset })\n : target;\n this.#selectThrough(selection, anchor, target);\n this.#semanticGesture = { unit, anchor };\n };\n\n /** The focused element, when it is inside the host. */\n #focusedInside(): HTMLElement | null {\n const active = document.activeElement;\n return active instanceof HTMLElement && active !== document.body && this.contains(active)\n ? active\n : null;\n }\n\n /** Structural repaints are held while a NATIVE drag may be in flight\n * (its browser-internal anchor would not survive a rebuild); an\n * engine-driven grid drag re-derives its points from flat offsets and\n * needs no hold. */\n #holdsNativeDrag(): boolean {\n return this.#pressing && !this.#gridDrag;\n }\n\n /** A non-interactive light element inside the host: never a legitimate\n * pointer target in grid mode, so an event there is a grid event. */\n #isPhantomTarget(target: EventTarget | null): boolean {\n return (\n target instanceof Element &&\n target !== this &&\n this.contains(target) &&\n !target.matches(INTERACTIVE)\n );\n }\n\n /** The grid's flat text offset for a cell (rows are trailing-trimmed\n * in the <pre>, so a blank tail clamps to the row's end). */\n #gridOffsetAt(col: number, row: number): number {\n const rows = this.#grid.textContent!.split(\"\\n\");\n const y = Math.max(0, Math.min(row, rows.length - 1));\n let offset = 0;\n for (let i = 0; i < y; i++) offset += rows[i]!.length + 1;\n return offset + Math.max(0, Math.min(col, rows[y]?.length ?? 0));\n }\n\n /** The grid text position under a client point: its flat offset and\n * the text node holding it. */\n #gridPointAt(clientX: number, clientY: number): { offset: number; at: [Text, number] } | null {\n const metrics = this.#cellMetrics;\n if (!metrics) return null;\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n const offset = this.#gridOffsetAt(col, row);\n const at = nodeAtOffset(this.#grid, offset);\n return at && { offset, at };\n }\n\n #startGridDrag(e: MouseEvent): void {\n const point = this.#gridPointAt(e.clientX, e.clientY);\n if (!point) return;\n e.preventDefault();\n document.getSelection()?.setBaseAndExtent(...point.at, ...point.at);\n this.#gridDrag = { anchor: point.offset };\n }\n\n #extendGridDrag(drag: { anchor: number }, clientX: number, clientY: number): void {\n const base = nodeAtOffset(this.#grid, drag.anchor);\n const point = this.#gridPointAt(clientX, clientY);\n if (base && point) document.getSelection()?.setBaseAndExtent(...base, ...point.at);\n }\n\n /** Drag extension: the anchor unit through the unit under the pointer,\n * in DOM order (base at the anchor's far edge, so the browser's\n * selection direction matches the drag). */\n #extendSemantic(gesture: SemanticGesture, clientX: number, clientY: number): void {\n const metrics = this.#cellMetrics;\n const selection = document.getSelection();\n if (!metrics || !selection) return;\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n const current = this.#unitAt(col, row, gesture.unit);\n if (current) this.#selectThrough(selection, gesture.anchor, current);\n }\n\n /** Select from the anchor unit through `unit`: the anchor's far edge\n * becomes the base, so the browser's selection direction matches the\n * gesture. Points inside a custom leaf's shadow cannot pair with\n * light-tree points, so each side is expressed at light-tree edges\n * unless both are the same shadow unit. */\n #selectThrough(selection: Selection, anchor: SelectionUnit, unit: SelectionUnit): void {\n if (sameUnit(anchor, unit)) {\n selectBetween(selection, unit.start, unit.end);\n return;\n }\n const from = this.#lightEdges(anchor);\n const to = this.#lightEdges(unit);\n const forward =\n comparePoints(from.start.node, from.start.offset, to.start.node, to.start.offset) <= 0;\n if (forward) selectBetween(selection, from.start, to.end);\n else selectBetween(selection, from.end, to.start);\n }\n\n /** The word or paragraph under a cell — null unless a CHARACTER of a\n * text leaf is painted there (padding, borders, gaps, and blank tails\n * are the browser's). The innermost hit text leaf; its\n * selectionTarget's contents for a custom leaf; a Segmenter word\n * mapped to DOM positions for the word gesture (falling back to the\n * paragraph where the text has no positions). */\n #unitAt(col: number, row: number, unit: \"word\" | \"paragraph\"): SelectionUnit | null {\n const layout = this.#lastLayout;\n if (!layout) return null;\n const stack = hitStack(layout, col, row);\n for (let i = stack.length - 1; i >= 0; i--) {\n const { node, x, y } = stack[i]!;\n if (!isTextLeaf(node)) continue;\n const index = charIndexAtCell(node, x, y, col, row);\n if (index === null) return null;\n const target = leafRendererFor(node.source.tagName)?.selectionTarget?.(node.source);\n if (unit === \"word\" && !target) {\n const word = wordAt(node, index);\n const start = word && positionOf(node, word.start);\n const end = word && positionOf(node, word.end);\n if (start && end) return { start, end };\n }\n const container = target ?? node.source;\n return {\n start: { node: container, offset: 0 },\n end: { node: container, offset: container.childNodes.length },\n };\n }\n return null;\n }\n\n /** A unit inside a custom leaf's shadow, as the light-tree range\n * around its host; a light unit unchanged. The edges sit at the\n * neighbors' content ends rather than on the parent: a point on this\n * host itself comes back from Firefox's getComposedRanges re-expressed\n * inside the shadow slot, which would read as outside the light DOM. */\n #lightEdges(unit: SelectionUnit): SelectionUnit {\n const root = unit.start.node.getRootNode();\n if (!(root instanceof ShadowRoot) || root === this.#grid.getRootNode()) return unit;\n const host = root.host;\n const parent = host.parentNode;\n if (!parent) return unit;\n const index = Array.prototype.indexOf.call(parent.childNodes, host);\n const before = host.previousSibling;\n const after = host.nextSibling;\n return {\n start: isPlainNode(before)\n ? {\n node: before,\n offset: before instanceof Text ? before.length : before.childNodes.length,\n }\n : { node: parent, offset: index },\n end: isPlainNode(after) ? { node: after, offset: 0 } : { node: parent, offset: index + 1 },\n };\n }\n\n /** Lift the grid-mode lock before the range is set — a forced style\n * resolution on the unit's element, so the range only ever lands in\n * selectable content. */\n #liftLock(unit: SelectionUnit): void {\n this.setAttribute(SEMANTIC_SELECTION, \"\");\n const node = unit.start.node;\n const element = node instanceof Element ? node : node.parentElement;\n if (element) void getComputedStyle(element).userSelect;\n }\n\n /** The document selection when it is a non-collapsed range in this\n * host's light DOM (a custom leaf's shadow selection reads as the\n * light range around its host); null otherwise. */\n #elementSelection(): BoundaryPoints | null {\n const range = selectionRangeThrough(this.#grid.getRootNode() as ShadowRoot);\n if (!range || classifySelection(this, this.#grid, range) !== \"light\") return null;\n const collapsed =\n range.startContainer === range.endContainer && range.startOffset === range.endOffset;\n return collapsed ? null : range;\n }\n\n /** The lift ends once the selection left the light DOM or collapsed. */\n #onSelectionChange = (): void => {\n if (!this.hasAttribute(SEMANTIC_SELECTION)) return;\n if (!this.#elementSelection()) this.removeAttribute(SEMANTIC_SELECTION);\n };\n\n #onPointerLeave = (): void => {\n this.#hoverClient = null;\n this.#updatePointerStates();\n };\n\n #onPointerDown = (event: Event): void => {\n const e = event as PointerEvent;\n if (!e.isPrimary || e.button !== 0) return;\n this.#lastPointerType = e.pointerType;\n // A finger pans natively (styles.css \"Touch panning\") and must not\n // relayout before release (see #scheduleDynamicRelayout): no thumb\n // drag, no synthesized press.\n if (isTouchInProgress(e)) return;\n const drag = this.#gutterDragAt(e.clientX, e.clientY);\n if (drag) {\n this.#thumbDrag = drag;\n e.preventDefault();\n // Keep tracking past the host's edge, like a native thumb\n // (synthetic events have no pointer to capture).\n if (e.isTrusted) this.setPointerCapture(e.pointerId);\n return;\n }\n this.#hoverClient = { x: e.clientX, y: e.clientY };\n this.#pressing = true;\n this.#pressOnGrid = e.composedPath().includes(this.#grid);\n this.#updatePointerStates(true);\n };\n\n #onPointerUp = (event: Event): void => {\n if (!(event as PointerEvent).isPrimary) return;\n this.#semanticGesture = null;\n this.#gridDrag = null;\n this.#pressOnGrid = false;\n this.removeAttribute(\"data-mw-dragging\");\n if (this.#thumbDrag) {\n this.#settle(this.#thumbDrag.el);\n this.#thumbDrag = null;\n return;\n }\n if (!this.#pressing && !this.#pressTarget) return;\n this.#pressing = false;\n this.#pressTarget = null;\n this.#updatePointerStates();\n if (this.#paintHeld) this.#scheduleLayout();\n };\n\n #onAnyScroll = (event: Event): void => {\n if (!this.#hoverClient) return;\n // Container scrolls are #onScroll's: hover refreshes in the paint frame\n // AFTER the offsets sync (a per-event refresh here would read\n // stale offsets), and a container's scroll never moves the grid itself.\n const target = event.target;\n if (target instanceof HTMLElement && target.hasAttribute(\"data-mw-scroll\")) return;\n this.#gridOrigin = null;\n this.#updatePointerStates();\n };\n\n /** Recompute both synthesized chains from the stored pointer\n * position and diff them onto the DOM; a change schedules a repaint.\n * `claimPress` (pointerdown only) makes the fresh chain's innermost\n * element the press target before the active chain derives from\n * it. */\n #updatePointerStates(claimPress = false): void {\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n let chain: Element[] = [];\n if (\n this.#hoverClient &&\n layout &&\n metrics &&\n this.isConnected &&\n this.getAttribute(\"select\") === \"grid\" &&\n (this.#pressing || MonoWindElement.#hoverCapable?.matches)\n ) {\n const { col, row } = this.#cellAt(this.#hoverClient.x, this.#hoverClient.y, metrics);\n this.#hoverCol = col;\n this.#hoverRow = row;\n chain = hitChain(layout, col, row);\n } else {\n this.#hoverCol = NaN;\n this.#hoverRow = NaN;\n }\n const innermost = chain.at(-1) ?? null;\n if (claimPress) this.#pressTarget = innermost;\n // Hover applies only on hover-capable pointers; the press chain\n // exists regardless (touch has :active). Like native :active, the\n // pressed element and its ancestors stay marked while the pointer\n // is over the pressed element, drop when it leaves, return when it\n // re-enters. (Mid-drag hover changes track normally — the paint\n // hold keeps their restyles off the grid until release.)\n const hover = MonoWindElement.#hoverCapable?.matches ? chain : [];\n const pressIndex = this.#pressTarget ? chain.indexOf(this.#pressTarget) : -1;\n const press = pressIndex >= 0 ? chain.slice(0, pressIndex + 1) : [];\n let changed = this.#applyChain(\"data-mw-hover\", this.#hovered, hover);\n changed = this.#applyChain(\"data-mw-active\", this.#pressed, press) || changed;\n // Mirror the hovered cursor onto the grid (the real hit target) —\n // `cursor-pointer` on a click-wired element is invisible otherwise.\n const cursor = innermost ? getComputedStyle(innermost).cursor : \"\";\n this.#grid.style.cursor = cursor === \"auto\" ? \"\" : cursor;\n if (changed && this.isConnected) this.#scheduleLayout();\n }\n\n #applyChain(attribute: string, previous: Set<Element>, next: Element[]): boolean {\n let changed = false;\n const nextSet = new Set(next);\n for (const el of previous) {\n if (!nextSet.has(el)) {\n el.removeAttribute(attribute);\n changed = true;\n }\n }\n for (const el of nextSet) {\n if (!previous.has(el)) {\n el.setAttribute(attribute, \"\");\n changed = true;\n }\n }\n previous.clear();\n for (const el of nextSet) previous.add(el);\n return changed;\n }\n\n #activeTransitions = 0;\n #samplingLoopRunning = false;\n #lastTransitionRun = 0;\n\n #onTransitionRun = (event: Event): void => {\n if (!SAMPLED_TRANSITION.test((event as TransitionEvent).propertyName)) return;\n this.#activeTransitions++;\n this.#lastTransitionRun = performance.now();\n this.#startSamplingLoop();\n };\n\n #onTransitionDone = (event: Event): void => {\n if (!SAMPLED_TRANSITION.test((event as TransitionEvent).propertyName)) return;\n this.#activeTransitions = Math.max(0, this.#activeTransitions - 1);\n };\n\n #startSamplingLoop(): void {\n if (this.#samplingLoopRunning) return;\n this.#samplingLoopRunning = true;\n const tick = (): void => {\n if (\n !this.isConnected ||\n (this.#activeTransitions === 0 && !hasSynthesizedTransitions()) ||\n performance.now() - this.#lastTransitionRun > SAMPLING_VALVE_MS\n ) {\n this.#samplingLoopRunning = false;\n this.#activeTransitions = 0;\n // One final settle pass so the grid lands exactly on the\n // transitions' target values.\n this.#scheduleLayout();\n return;\n }\n this.#performLayoutSafely();\n requestAnimationFrame(tick);\n };\n requestAnimationFrame(tick);\n }\n\n #scheduleDynamicRelayout = (event: Event): void => {\n // A touch must not relayout before it is released: iOS decides\n // which scroller owns a pan in the first frames, and a relayout\n // reflows the light DOM under the finger, which abandons the pan\n // to the page. Touch has no hover to reflect, and the release\n // relayout picks up the tap's outcome.\n if (isTouchInProgress(event)) return;\n // Focus moving onto or off a <select>: relayout NOW, while still\n // inside the event dispatch — the click's default action opens the\n // picker right after, and once it's open relayouts are held (see\n // #openSelectPicker). Deferring here would freeze the grid with\n // the PREVIOUS focus-invert while native text colors update,\n // leaving the old select white-on-white.\n if (\n (event.type === \"focusin\" || event.type === \"focusout\") &&\n event.target instanceof HTMLSelectElement\n ) {\n this.#performLayoutSafely();\n return;\n }\n this.#scheduleLayout();\n };\n\n attributeChangedCallback(name: string, _previous: string | null, next: string | null): void {\n if (name === \"select\" && next !== \"text\" && next !== \"grid\") {\n if (next !== null) {\n console.warn(\n `[monowind] Ignoring unrecognized select=\"${next}\". Expected \"grid\" (default) or \"text\".`,\n warnSubject(this),\n );\n }\n // Reflect the default so the attribute is the single source of\n // truth — every selector keys on an explicit value, and no CSS\n // has to know what an absent attribute means.\n this.setAttribute(\"select\", DEFAULT_SELECT);\n return;\n }\n // select=\"text\" hands pointer events back to the light DOM — the\n // synthesized chains must not double up with the native states.\n if (name === \"select\") this.#updatePointerStates();\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 #onWindowResize = (): void => {\n this.#scheduleLayout();\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 /** True while a focused in-host <select> has its picker open. A\n * relayout then would churn styles and make Chrome dismiss the\n * picker instantly (`:open` on <select> is Chromium-only for now;\n * browsers without it don't dismiss and fall through). */\n #openSelectPicker(): boolean {\n const active = document.activeElement;\n if (!(active instanceof HTMLSelectElement) || !this.contains(active)) return false;\n try {\n return active.matches(\":open\");\n } catch {\n return false;\n }\n }\n\n #performLayoutSafely(): void {\n try {\n this.#performLayout();\n } catch (err) {\n console.error(\"[monowind] layout failed:\", err);\n }\n }\n\n #scheduleLayout(): void {\n if (this.#layoutPending) return;\n this.#layoutPending = true;\n requestAnimationFrame(() => {\n this.#layoutPending = false;\n // Hold the relayout while a select picker is up — re-arm so it\n // runs the frame after the picker closes (change or dismiss).\n if (this.#openSelectPicker()) {\n this.#scheduleLayout();\n return;\n }\n this.#performLayoutSafely();\n });\n }\n\n #performLayout(): void {\n // A queued frame can outlive the host's removal (story/app teardown,\n // SPA navigation): computed styles on a detached tree read as empty\n // strings, which would misclassify every element and misfire author\n // warnings. Reconnection schedules a fresh layout.\n if (!this.isConnected) return;\n // Container positions are read before the mask and written back after\n // it (specs/scrolling.md); bottom-stick resolves in between.\n const scrollState = this.#captureScrollState();\n // Snapshot each textarea's content-area width in cells BEFORE the\n // measuring attribute goes on. Inside measuring the engine's width\n // rule is off — the textarea reverts to its browser-default width\n // and any read would be wrong. The tree builder wraps the value\n // against this width to compute the row count.\n const textareaWidths: TextareaWidths = new Map();\n const cellWidth = getComputedStyle(this).getPropertyValue(\"--mw-cw\").trim();\n const cellWidthPx = parseFloat(cellWidth);\n if (Number.isFinite(cellWidthPx) && cellWidthPx > 0) {\n for (const ta of this.querySelectorAll<HTMLTextAreaElement>(\"textarea\")) {\n const style = getComputedStyle(ta);\n const contentPx =\n ta.clientWidth -\n (parseFloat(style.paddingLeft) || 0) -\n (parseFloat(style.paddingRight) || 0);\n // `round` (not `floor`) so subpixel remainders don't chop one\n // cell off the width — the browser rarely wraps a character\n // that fits within half a cell of the edge.\n textareaWidths.set(ta, Math.max(0, Math.round(contentPx / cellWidthPx)));\n }\n }\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. A host innerHTML swap wipes the probe (a\n // detached node measures 0×0, and 0-px cells blow the layout up) —\n // re-adopt it here; the childList record drains with the engine's\n // own writes below.\n if (this.#probe.parentNode !== this) this.appendChild(this.#probe);\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 previous.inkOverhang !== metrics.inkOverhang\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 this.style.setProperty(\"--mw-ink\", `${metrics.inkOverhang ?? 0}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, textareaWidths);\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 if (hasDirectText(this)) {\n if (!this.hasAttribute(\"data-mw-dropped-text\")) {\n console.warn(`[monowind] ${DIRECT_TEXT_DROPPED}`, warnSubject(this));\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.#grid.replaceChildren();\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 to light DOM + paint the shadow grid. Do this\n // before clearing the measuring attribute so the browser only\n // paints the final state.\n render(virtualRoot);\n this.#scrollNodes = collectScrollContainers(virtualRoot);\n this.#syncScrollOffsets(metrics, scrollState);\n // Style-only paints patch nodes in place (drag anchors survive);\n // a STRUCTURAL rebuild while a primary press holds a selection\n // anchor in the grid is deferred to release — a drag in flight\n // re-derives from the browser's internal anchor, which the\n // rebuild would destroy (Chromium collapses even across a\n // capture-and-restore).\n this.#paintHeld = !paintGrid(virtualRoot, this.#grid, this.#holdsNativeDrag());\n this.#lastLayout = virtualRoot;\n // The grid box is the ink extent in engine cells: a glyph a\n // fallback font draws wider still overhangs as ink, but the box\n // (and the background it inherits) never grows from it.\n const gridWidth = `${virtualRoot.localRect.width * metrics.width}px`;\n const gridHeight = `${virtualRoot.localRect.height * metrics.height}px`;\n if (this.#grid.style.width !== gridWidth) this.#grid.style.width = gridWidth;\n if (this.#grid.style.height !== gridHeight) this.#grid.style.height = gridHeight;\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 const hostHeight = `${height * metrics.height + chrome}px`;\n if (this.style.height !== hostHeight) this.style.height = hostHeight;\n // Cap the width to the columns laid out (specs/cell-model.md \"Host\n // sizing\"); the companion applies it outside measuring.\n const chromeX =\n cs.boxSizing === \"border-box\"\n ? padX + (parseFloat(cs.borderLeftWidth) || 0) + (parseFloat(cs.borderRightWidth) || 0)\n : 0;\n const hostWidth = `${availableCols * metrics.width + chromeX}px`;\n if (this.style.getPropertyValue(\"--mw-host-w\") !== hostWidth)\n this.style.setProperty(\"--mw-host-w\", hostWidth);\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 if (!this.hasAttribute(\"data-mw-ready\")) this.setAttribute(\"data-mw-ready\", \"\");\n } finally {\n // The measured real values are about to snap back to the locks —\n // a delta that must never start a native fade (transitions beat\n // `!important`, and a native background fade paints the light-DOM\n // element's box ON TOP of the grid). [settling] holds the\n // transition-property mask up while the snap-back COMMITS: the\n // forced flush consumes every lock delta under the mask, so the\n // unmasked commits that follow (this frame's end included) see no\n // delta and the authored lists stay fully respected.\n this.setAttribute(\"settling\", \"\");\n this.removeAttribute(\"measuring\");\n void getComputedStyle(this).transitionProperty;\n this.removeAttribute(\"settling\");\n // Restore native container positions AFTER the unmask — the browser\n // re-clamps them when the mask lifts (Firefox lazily), so any\n // earlier write gets wiped. The grid already painted from the\n // same snapshot; a changed native position fires its scroll\n // event into a same-cell repaint.\n this.#restoreScrollPositions(scrollState);\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 // Synthesized transitions (animate.ts): background changes the\n // read detected arm HERE, outside the masks, where the authored\n // `transition-property` list is readable — then the sampling loop\n // drives the fade. A pending change that did NOT arm was painted\n // stale this pass; one more relayout paints its target.\n if (resolvePendingTransitions(this)) {\n if (hasSynthesizedTransitions()) {\n this.#lastTransitionRun = performance.now();\n this.#startSamplingLoop();\n } else {\n this.#scheduleLayout();\n }\n }\n // Surroundings, outside the mask so the reads are authored values:\n // the resize signals a capped host needs, and the native scrollers\n // a page-owned wheel sequence may still have room in.\n this.#observeSurroundings();\n this.#outerScrollers = [];\n const scrolling = document.scrollingElement ?? document.documentElement;\n for (let el = this.parentElement; el; el = el.parentElement) {\n if (el === scrolling || /auto|scroll/.test(getComputedStyle(el).overflow)) {\n this.#outerScrollers.push(el);\n }\n }\n // The layout may have moved content under a stationary pointer —\n // re-derive the synthesized pointer states (cheap when nothing\n // changed; a chain change coalesces into the next frame).\n this.#gridOrigin = null;\n if (this.#hoverClient) this.#updatePointerStates();\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\n/** Pre-layout native container positions, by element (specs/scrolling.md):\n * px, the cells they meant under the OLD range, and end pins. */\ntype ScrollSnapshot = Map<\n HTMLElement,\n { top: number; left: number; x: number; y: number; pinX: boolean; pinY: boolean }\n>;\n\ninterface WheelLatch {\n /** The latched scroll container; null = the page. */\n el: HTMLElement | null;\n x: number;\n y: number;\n /** The gesture's dominant axis at its start. */\n axis: \"x\" | \"y\";\n at: number;\n /** Last tick's |delta| and how many ticks it has decayed smoothly\n * (sticky once INERTIA_TICKS confirm momentum). */\n mag: number;\n decayed: number;\n}\n\n/** An in-flight scrollbar-thumb drag (specs/scrolling.md). */\ninterface ThumbDrag {\n el: HTMLElement;\n axis: \"x\" | \"y\";\n startClient: number;\n startPx: number;\n factor: number;\n}\n\n/** A container's native position on one axis, in cells (see\n * quantizeScroll). */\nfunction scrollCells(\n el: HTMLElement,\n axis: \"x\" | \"y\",\n cellSize: number,\n max: number,\n base: number,\n): number {\n const px = axis === \"y\" ? el.scrollTop : el.scrollLeft;\n const ceiling =\n axis === \"y\" ? el.scrollHeight - el.clientHeight : el.scrollWidth - el.clientWidth;\n return quantizeScroll(px, ceiling, cellSize, max, base);\n}\n\n/** Native scroll position → whole-cell offset within the engine's\n * range (specs/scrolling.md). Within half a cell of `base` (the last\n * painted offset) the shown cell stays — a wobble never flips it;\n * beyond that, the NEAREST cell, ties away from `base`, so a keyboard\n * step of two and a half cells moves three in either direction. At\n * the native `ceiling` the container IS at max: the spacer ends at the\n * engine's edge, but scrollHeight and clientHeight round\n * independently, so the ceiling can sit a pixel either side of the\n * multiple. (A container still at 0 never reads as \"at max\", whatever\n * its ceiling — the spacer may not have applied yet.) */\nexport function quantizeScroll(\n px: number,\n ceiling: number,\n cellSize: number,\n max: number,\n base: number,\n): number {\n if (max > 0 && px > 0 && px >= ceiling - 1) return max;\n const delta = px / cellSize - base;\n const cells =\n Math.abs(delta) <= 0.5 ? base : base + Math.sign(delta) * Math.round(Math.abs(delta));\n return Math.min(Math.max(0, cells), max);\n}\n\n/** A touch pointer that has not been lifted — the phase in which the\n * engine must not reflow anything (see #scheduleDynamicRelayout).\n * `pointercancel` counts as in progress: iOS fires it the moment it\n * takes the pan, and a relayout there kills the gesture. */\nfunction isTouchInProgress(event: Event): boolean {\n return (\n event instanceof PointerEvent && event.pointerType === \"touch\" && event.type !== \"pointerup\"\n );\n}\n\n/** A light node that can hold a boundary point of its own: anything\n * but another shadow host. */\nfunction isPlainNode(node: Node | null): node is Node {\n return node !== null && !(node instanceof Element && node.shadowRoot);\n}\n\n/** A collapsed unit — an existing selection's anchor, for Shift. */\nfunction pointUnit(point: Point): SelectionUnit {\n return { start: point, end: point };\n}\n\nfunction selectBetween(selection: Selection, base: Point, extent: Point): void {\n selection.setBaseAndExtent(base.node, base.offset, extent.node, extent.offset);\n}\n\nfunction sameUnit(a: SelectionUnit, b: SelectionUnit): boolean {\n return (\n a.start.node === b.start.node &&\n a.start.offset === b.start.offset &&\n a.end.node === b.end.node &&\n a.end.offset === b.end.offset\n );\n}\n\nfunction collectScrollContainers(root: LayoutNode): LayoutNode[] {\n const out: LayoutNode[] = [];\n const visit = (node: LayoutNode): void => {\n if (node.scrollRange) out.push(node);\n for (const child of node.children) visit(child);\n };\n visit(root);\n return out;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/animate.ts","../src/glyphs.ts","../src/warn.ts","../src/leaf.ts","../src/borders.ts","../src/metrics.ts","../src/wrap.ts","../src/flex.ts","../src/types.ts","../src/grid.ts","../src/multicol.ts","../src/table.ts","../src/positioning.ts","../src/layout.ts","../src/plain-text.ts","../src/pointer.ts","../src/focus.ts","../src/selection.ts","../src/paint.ts","../src/render.ts","../src/style.ts","../src/tree.ts","../src/element.ts"],"sourcesContent":["/**\n * Engine-synthesized transitions for lock-owned properties\n * (specs/cell-model.md \"Animation\"). `background-color` has no native\n * timeline to sample — the companion locks the light DOM's bg\n * transparent so it can't cover the grid, so the authored value only\n * exists in measuring snapshots. When a read sees the value change on\n * an element whose authored `transition` covers background-color, the\n * engine runs the fade itself: same duration, delay, and easing,\n * interpolating in OKLAB (CSS's interpolation space for non-legacy\n * pairs; legacy rgb pairs interpolate in sRGB, per css-color-4).\n *\n * Two-phase because of the measuring override: reads happen under\n * `[measuring]`, where the companion forces `transition-property` to\n * the sampled set — so the CHANGE is recorded during the read\n * (`trackBackground`), and the authored config is resolved at the end\n * of the layout pass (`resolvePendingTransitions`), after the settling\n * flush restores the authored `transition-property` list.\n */\n\ninterface Rgba {\n r: number; // 0..1, sRGB\n g: number;\n b: number;\n a: number;\n legacy: boolean; // rgb()/transparent — pairs of these lerp in sRGB\n}\n\ninterface SynthesizedTransition {\n from: Rgba;\n to: Rgba;\n toValue: string;\n start: number; // performance.now() + delay\n duration: number;\n easing: (t: number) => number;\n}\n\nconst lastBackground = new WeakMap<Element, string>();\nconst pending: { el: Element; from: string; to: string }[] = [];\n// A Map, not a WeakMap: hasSynthesizedTransitions must sweep entries\n// whose element left the tree (or whose fade expired unsampled, e.g.\n// hidden mid-fade) — otherwise a stray entry would pin the sampling\n// loop to its 30s safety valve. The sweep bounds the strong refs.\nconst active = new Map<Element, SynthesizedTransition>();\n\n/**\n * Called from the style reader with the freshly read background-color\n * (empty string when unset). Returns the value layout should USE: the\n * in-flight interpolation when a synthesized transition is running,\n * the previous value when a change was just detected on an element\n * that MIGHT transition (the fade or a corrective repaint follows next\n * frame — see resolvePendingTransitions), or the value itself. The\n * might-transition check reads `transition-duration`, which the\n * measuring override does NOT mask — an element with no transition at\n * all must paint its new background THIS pass, never a stale one.\n */\nexport function trackBackground(el: Element, value: string, cs: CSSStyleDeclaration): string {\n const previous = lastBackground.get(el);\n lastBackground.set(el, value);\n const running = active.get(el);\n if (running) {\n if (value !== running.toValue) {\n // Retargeted mid-flight: restart from the current interpolated\n // color on the next resolve.\n const from = sampleColor(running);\n active.delete(el);\n pending.push({ el, from, to: value });\n return from;\n }\n const sampled = sampleColor(running);\n if (sampled === running.toValue) active.delete(el);\n return sampled;\n }\n if (\n previous !== undefined &&\n previous !== value &&\n cs.transitionDuration.split(\",\").some((duration) => parseFloat(duration) > 0)\n ) {\n pending.push({ el, from: previous, to: value });\n return previous;\n }\n return value;\n}\n\n/** Arm this host's pending fades — call with `[measuring]` and\n * `[settling]` OFF (and every lock snap-back already committed under\n * the mask), so the authored `transition-property` list is readable\n * and the reads here start nothing. Changes whose config doesn't cover\n * background-color snap: they were painted STALE this pass\n * (trackBackground returned the previous value), so the caller must\n * schedule one corrective relayout whenever this returns true. Other\n * hosts' pends stay queued for their own layouts. */\nexport function resolvePendingTransitions(host: Element): boolean {\n let hadPending = false;\n for (let i = pending.length - 1; i >= 0; i--) {\n const { el, from, to } = pending[i]!;\n // A disconnected element's pend is dead no matter whose it was —\n // drop it here so a torn-down host can't grow the queue forever.\n if (!el.isConnected) {\n pending.splice(i, 1);\n continue;\n }\n if (!host.contains(el)) continue;\n pending.splice(i, 1);\n hadPending = true;\n const config = transitionConfigFor(getComputedStyle(el), \"background-color\");\n const fromColor = parseColor(from);\n const toColor = parseColor(to);\n if (!config || !fromColor || !toColor) continue;\n active.set(el, {\n from: fromColor,\n to: toColor,\n toValue: to,\n start: performance.now() + config.delay,\n duration: config.duration,\n easing: config.easing,\n });\n }\n return hadPending;\n}\n\nexport function hasSynthesizedTransitions(): boolean {\n // Sweep entries no read will ever finish: gone elements, and expired\n // fades on elements no longer laid out (a raw read equals toValue by\n // now, so dropping them changes nothing a future read would paint).\n const now = performance.now();\n for (const [el, transition] of active) {\n if (!el.isConnected || now >= transition.start + transition.duration) active.delete(el);\n }\n return active.size > 0;\n}\n\nfunction sampleColor(transition: SynthesizedTransition): string {\n const t = (performance.now() - transition.start) / transition.duration;\n if (t >= 1) return transition.toValue;\n const eased = t <= 0 ? 0 : transition.easing(t);\n return serialize(mix(transition.from, transition.to, eased));\n}\n\n/* === Transition config ================================================ */\n\nconst KEYWORD_EASINGS: Record<string, [number, number, number, number]> = {\n ease: [0.25, 0.1, 0.25, 1],\n \"ease-in\": [0.42, 0, 1, 1],\n \"ease-out\": [0, 0, 0.58, 1],\n \"ease-in-out\": [0.42, 0, 0.58, 1],\n};\n\nfunction transitionConfigFor(\n cs: CSSStyleDeclaration,\n property: string,\n): { duration: number; delay: number; easing: (t: number) => number } | null {\n const properties = cs.transitionProperty.split(\",\").map((p) => p.trim());\n // Per css-transitions, the LAST matching entry wins; shorter value\n // lists repeat to the property list's length.\n let index = -1;\n for (let i = 0; i < properties.length; i++) {\n if (properties[i] === property || properties[i] === \"all\") index = i;\n }\n if (index < 0) return null;\n const nth = (list: string): string => {\n const values = list.split(\",\").map((v) => v.trim());\n return values[index % values.length] ?? \"\";\n };\n const duration = parseSeconds(nth(cs.transitionDuration));\n if (duration <= 0) return null;\n return {\n duration: duration * 1000,\n delay: parseSeconds(nth(cs.transitionDelay)) * 1000,\n easing: parseEasing(nth(cs.transitionTimingFunction)),\n };\n}\n\nfunction parseSeconds(value: string): number {\n const parsed = parseFloat(value);\n if (!Number.isFinite(parsed)) return 0;\n return value.endsWith(\"ms\") ? parsed / 1000 : parsed;\n}\n\nfunction parseEasing(value: string): (t: number) => number {\n if (value === \"linear\") return (t) => t;\n const keyword = KEYWORD_EASINGS[value];\n if (keyword) return cubicBezier(...keyword);\n const bezier = value.match(/^cubic-bezier\\(([^)]+)\\)$/);\n if (bezier) {\n const [x1, y1, x2, y2] = bezier[1]!.split(\",\").map((n) => parseFloat(n));\n if ([x1, y1, x2, y2].every((n) => Number.isFinite(n))) {\n return cubicBezier(x1!, y1!, x2!, y2!);\n }\n }\n // steps() and anything unrecognized: linear is the closest snap-free\n // stand-in.\n return (t) => t;\n}\n\n/** Standard cubic-bezier easing: solve x(u) = t for u by bisection,\n * return y(u). Whole-cell output makes sub-ms precision pointless. */\nfunction cubicBezier(x1: number, y1: number, x2: number, y2: number): (t: number) => number {\n const coord = (a: number, b: number, u: number): number =>\n 3 * a * u * (1 - u) * (1 - u) + 3 * b * u * u * (1 - u) + u * u * u;\n return (t) => {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (coord(x1, x2, mid) < t) lo = mid;\n else hi = mid;\n }\n return coord(y1, y2, (lo + hi) / 2);\n };\n}\n\n/* === Color math ======================================================= */\n\nfunction parseColor(value: string): Rgba | null {\n if (value === \"\" || value === \"transparent\") return { r: 0, g: 0, b: 0, a: 0, legacy: true };\n let match = value.match(/^rgba?\\(([^)]+)\\)$/);\n if (match) {\n const parts = match[1]!.split(/[\\s,/]+/).map((n) => parseFloat(n));\n if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;\n return {\n r: parts[0]! / 255,\n g: parts[1]! / 255,\n b: parts[2]! / 255,\n a: parts[3] ?? 1,\n legacy: true,\n };\n }\n match = value.match(/^color\\(srgb ([^)]+)\\)$/);\n if (match) {\n const parts = match[1]!.split(/[\\s/]+/).map((n) => parseFloat(n));\n if (parts.length < 3 || parts.slice(0, 3).some((n) => !Number.isFinite(n))) return null;\n return { r: parts[0]!, g: parts[1]!, b: parts[2]!, a: parts[3] ?? 1, legacy: false };\n }\n match = value.match(/^okl(ch|ab)\\(([^)]+)\\)$/);\n if (match) {\n const polar = match[1] === \"ch\";\n const parts = match[2]!\n .replaceAll(\"none\", \"0\")\n .split(/[\\s/]+/)\n .map((n) => parseFloat(n));\n if (parts.length < 3 || parts.some((n) => !Number.isFinite(n))) return null;\n const [l, c1, c2] = parts as [number, number, number];\n const a = polar ? c1 * Math.cos((c2 * Math.PI) / 180) : c1;\n const b = polar ? c1 * Math.sin((c2 * Math.PI) / 180) : c2;\n return { ...oklabToSrgb(l, a, b), a: parts[3] ?? 1, legacy: false };\n }\n return null;\n}\n\nfunction mix(from: Rgba, to: Rgba, t: number): Rgba {\n // Premultiplied-alpha interpolation (a transparent endpoint keeps the\n // other's chromaticity), in OKLAB unless both endpoints are legacy\n // sRGB (css-color-4 interpolation rules).\n const a = from.a + (to.a - from.a) * t;\n const lerp = (x: number, y: number): number => {\n const premixed = x * from.a + (y * to.a - x * from.a) * t;\n return a === 0 ? 0 : premixed / a;\n };\n if (from.legacy && to.legacy) {\n return { r: lerp(from.r, to.r), g: lerp(from.g, to.g), b: lerp(from.b, to.b), a, legacy: true };\n }\n const f = srgbToOklab(from.r, from.g, from.b);\n const o = srgbToOklab(to.r, to.g, to.b);\n const rgb = oklabToSrgb(lerp(f.l, o.l), lerp(f.a, o.a), lerp(f.b, o.b));\n return { ...rgb, a, legacy: false };\n}\n\nfunction serialize(color: Rgba): string {\n const channel = (c: number): number => Math.round(Math.min(1, Math.max(0, c)) * 255);\n const alpha = Math.round(Math.min(1, Math.max(0, color.a)) * 1000) / 1000;\n return `rgba(${channel(color.r)}, ${channel(color.g)}, ${channel(color.b)}, ${alpha})`;\n}\n\nfunction linearize(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\nfunction delinearize(c: number): number {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;\n}\n\nfunction srgbToOklab(r: number, g: number, b: number): { l: number; a: number; b: number } {\n const lr = linearize(r);\n const lg = linearize(g);\n const lb = linearize(b);\n const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n return {\n l: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n };\n}\n\nfunction oklabToSrgb(l: number, a: number, b: number): { r: number; g: number; b: number } {\n const l3 = Math.pow(l + 0.3963377774 * a + 0.2158037573 * b, 3);\n const m3 = Math.pow(l - 0.1055613458 * a - 0.0638541728 * b, 3);\n const s3 = Math.pow(l - 0.0894841775 * a - 1.291485548 * b, 3);\n return {\n r: delinearize(4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3),\n g: delinearize(-1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3),\n b: delinearize(-0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3),\n };\n}\n","import type { BorderStyle } from \"./types.ts\";\n\n/**\n * Border glyph sets (specs/theming.md): the rendering vocabulary\n * border STYLES resolve through — what the themed \"hardware\" can\n * draw. Orthogonal to styles: authors keep writing `border-double`;\n * the active set decides its glyphs (`╔═╗`, `+=+`, or a single-line\n * downgrade). Selected per decoration OWNER via the inherited\n * `--mw-border-glyphs` custom property; the property carries only a\n * NAME — tables live here. Fallback is PER GLYPH: a set may override\n * only corners and inherit everything else from the defaults.\n */\n\n/** One style's glyph overrides, by role. Roles cover the engine's\n * full junction vocabulary (lines, four corners, four tees, cross);\n * every field optional. */\nexport interface GlyphTable {\n h?: string;\n v?: string;\n tl?: string;\n tr?: string;\n bl?: string;\n br?: string;\n /** `┴` — arms up, left, right. */\n teeUp?: string;\n /** `┬` — arms down, left, right. */\n teeDown?: string;\n /** `┤` — arms up, down, left. */\n teeLeft?: string;\n /** `├` — arms up, down, right. */\n teeRight?: string;\n /** `┼` — all four arms. */\n cross?: string;\n /** Scrollbar gutter ink (specs/scrolling.md); defaults `░` / `█`. */\n scrollTrack?: string;\n scrollThumb?: string;\n}\n\nexport type BorderGlyphSet = Partial<Record<BorderStyle, GlyphTable>>;\n\nconst sets = new Map<string, BorderGlyphSet>();\nconst listeners = new Set<() => void>();\n\n/** Register (or last-wins replace, with a warning) a glyph set.\n * Connected hosts relayout — the shared post-hoc-registration idiom. */\nexport function registerBorderGlyphs(name: string, set: BorderGlyphSet): void {\n const key = name.toLowerCase().trim();\n if (sets.has(key)) {\n console.warn(`[monowind] registerBorderGlyphs: replacing \"${key}\" (last registration wins).`);\n }\n sets.set(key, set);\n for (const listener of listeners) listener();\n}\n\n/** Resolve a `--mw-border-glyphs` value to a set — once per\n * decoration owner, then passed into the glyph primitives. Unknown or\n * empty names (headless environments read \"\") mean the built-in\n * defaults. */\nexport function glyphSetFor(name: string | null | undefined): BorderGlyphSet | undefined {\n if (!name) return undefined;\n return sets.get(name.toLowerCase().trim());\n}\n\n/** Host subscription to registrations; returns the unsubscriber. */\nexport function onGlyphRegistryChange(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\n/** The role a junction bitmask (up 8 / down 4 / left 2 / right 1)\n * plays — stubs (≤1 arm per axis alone) read as plain lines. */\nexport function junctionRole(mask: number): keyof GlyphTable | null {\n switch (mask) {\n case 1:\n case 2:\n case 3:\n return \"h\";\n case 4:\n case 8:\n case 12:\n return \"v\";\n case 5:\n return \"tl\";\n case 6:\n return \"tr\";\n case 9:\n return \"bl\";\n case 10:\n return \"br\";\n case 7:\n return \"teeDown\";\n case 11:\n return \"teeUp\";\n case 13:\n return \"teeRight\";\n case 14:\n return \"teeLeft\";\n case 15:\n return \"cross\";\n default:\n return null; // mask 0: no arms\n }\n}\n\n/* === Junction tables ================================================== */\n\n// Indexed by the up/down/left/right bitmask (8/4/2/1).\nexport const LIGHT_JUNCTIONS = [\n \" \",\n \"─\",\n \"─\",\n \"─\", // no vertical arm\n \"│\",\n \"┌\",\n \"┐\",\n \"┬\",\n \"│\",\n \"└\",\n \"┘\",\n \"┴\",\n \"│\",\n \"├\",\n \"┤\",\n \"┼\",\n];\nexport const DOUBLE_JUNCTIONS = [\n \" \",\n \"═\",\n \"═\",\n \"═\",\n \"║\",\n \"╔\",\n \"╗\",\n \"╦\",\n \"║\",\n \"╚\",\n \"╝\",\n \"╩\",\n \"║\",\n \"╠\",\n \"╣\",\n \"╬\",\n];\n\n/** A full role table read off a junction table — first mask wins per\n * role, so every role resolves to its canonical glyph. */\nfunction tableFrom(junctions: readonly string[]): GlyphTable {\n const table: GlyphTable = {};\n for (let mask = 1; mask < 16; mask++) {\n const role = junctionRole(mask);\n if (role && !(role in table)) table[role] = junctions[mask]!;\n }\n return table;\n}\n\n/** Every role drawn with one glyph, for sets with no junction geometry. */\nconst uniformTable = (glyph: string): GlyphTable =>\n tableFrom(Array.from({ length: 16 }, () => glyph));\n\n/* === Built-in sets ==================================================== */\n\n// `default` needs no table — an unresolved set falls through to the\n// engine's built-in glyphs everywhere.\nregisterBorderGlyphs(\"default\", {});\n\n// PETSCII/C64 flavor: solid corners become arcs; everything else keeps\n// the defaults (dashed/dotted corners stay square — the arc glyphs\n// exist only in the light-solid weight).\nregisterBorderGlyphs(\"rounded\", {\n solid: { tl: \"╭\", tr: \"╮\", bl: \"╰\", br: \"╯\" },\n});\n\n// Teletype: 7-bit ASCII only. `double` keeps emphasis via `=`.\nconst asciiTable: GlyphTable = { ...uniformTable(\"+\"), h: \"-\", v: \"|\" };\nregisterBorderGlyphs(\"ascii\", {\n solid: { ...asciiTable, scrollTrack: \"|\", scrollThumb: \"#\" },\n double: { ...asciiTable, h: \"=\" },\n dashed: asciiTable,\n dotted: { ...asciiTable, h: \".\", v: \":\" },\n});\n\nconst lightTable = tableFrom(LIGHT_JUNCTIONS);\n\n// DEC/VT-style terminals drew one line style only: double, dashed,\n// and dotted all downgrade to solid light lines.\nregisterBorderGlyphs(\"single\", {\n double: lightTable,\n dashed: lightTable,\n dotted: lightTable,\n});\n\n// CP437 hardware: double survives, but the dashed/dotted line glyphs\n// don't exist in the codepage (bitmap fonts lack them — a fallback\n// font would break the grid), so they downgrade to solid.\nregisterBorderGlyphs(\"cp437\", { dashed: lightTable, dotted: lightTable });\n\n/** Gutter ink through the owner's set — solid-table roles, defaults\n * `░` / `█` (specs/scrolling.md). */\nexport function scrollGlyphs(set: BorderGlyphSet | undefined): { track: string; thumb: string } {\n return {\n track: set?.solid?.scrollTrack ?? \"\\u2591\",\n thumb: set?.solid?.scrollThumb ?? \"\\u2588\",\n };\n}\n\n// BBS/ANSI-art flavor: CP437 blocks, styles mapped to shade density.\nregisterBorderGlyphs(\"blocks\", {\n solid: uniformTable(\"█\"),\n double: uniformTable(\"█\"),\n dashed: uniformTable(\"▒\"),\n dotted: uniformTable(\"░\"),\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}`, warnSubject(el));\n}\n\n/** The element for a warning: the reference itself in a browser (an\n * inspectable link in DevTools), a one-line description under Node\n * (tests), whose console would print the whole object graph. */\nexport function warnSubject(el: Element): Element | string {\n const node = (globalThis as { process?: { versions?: { node?: string } } }).process?.versions\n ?.node;\n if (!node) return el;\n const id = el.id ? `#${el.id}` : \"\";\n const classes = el.classList.length ? `.${Array.from(el.classList).join(\".\")}` : \"\";\n return `<${el.tagName.toLowerCase()}${id}${classes}>`;\n}\n","import { warnOnce } from \"./warn.ts\";\n\n/**\n * Public leaf-renderer API (specs/leaf-renderers.md): a custom element\n * registers as a GRID LEAF and supplies its own cell content instead\n * of laid-out children — the generalization of what the tree builder\n * special-cases for form controls. `@monowind/ascii` is the first\n * consumer.\n *\n * Stability contract: this surface is public — every future change is\n * ADDITIVE (new optional fields/parameters), per the spec's evolution\n * policy.\n */\n\n/** Per-cell styling for a run — an extensible subset of what the grid\n * paints. Color values are CSS `<color>` strings, vars welcome\n * (`var(--mw-ansi-red)`); they resolve at paint time against the\n * host, so themes restyle content with no re-render. */\nexport interface LeafPaint {\n color?: string;\n backgroundColor?: string;\n fontWeight?: string;\n fontStyle?: string;\n textDecorationLine?: string;\n}\n\n/** One painted span of a content line: cells `[start, end)` of\n * `lines[line]`. */\nexport interface LeafRun {\n line: number;\n start: number;\n end: number;\n paint: LeafPaint;\n}\n\n/** What a renderer returns: preformatted content lines (the leaf's\n * intrinsic width is the longest line, height the line count —\n * white-space styling does not apply to renderer content) plus\n * optional paint runs. */\nexport interface LeafContent {\n lines: string[];\n runs?: LeafRun[];\n}\n\nexport interface LeafRegistration {\n /** Custom-element tag name (must contain a hyphen — built-ins are\n * never claimable). Stored lowercased. */\n tag: string;\n /** SYNCHRONOUS and DOM-read-only; called each layout pass (caching\n * is the renderer's own business). Asynchrony (font loading, …)\n * lives outside: finish the work, then `invalidateLeaves()`. Must\n * also run under happy-dom/Node — `renderPlainText` traverses the\n * same tree. */\n render: (el: Element) => LeafContent;\n /** Attributes whose changes re-render this leaf (merged into the\n * host's mutation-observer filter; `class`/`style` and character\n * data are always observed). */\n observedAttributes?: string[];\n /** The node whose contents a semantic gesture ON the leaf selects\n * (specs/semantic-selection.md) — a shadow transcript that sits\n * under the art, say. Absent: the leaf's light contents. */\n selectionTarget?: (el: Element) => Node | null;\n}\n\nconst leaves = new Map<string, LeafRegistration>();\nconst listeners = new Set<() => void>();\n\n/** Register (or last-wins replace, with a warning) a leaf renderer.\n * Connected hosts relayout, so registration after first paint is\n * safe — the post-hoc-registration idiom every monowind registry\n * shares. */\nexport function registerLeafRenderer(registration: LeafRegistration): void {\n const tag = registration.tag.toLowerCase();\n if (!tag.includes(\"-\")) {\n console.warn(\n `[monowind] registerLeafRenderer: \"${registration.tag}\" is not a custom-element tag name (needs a hyphen); ignored.`,\n );\n return;\n }\n if (leaves.has(tag)) {\n console.warn(\n `[monowind] registerLeafRenderer: replacing existing renderer for <${tag}> (last registration wins).`,\n );\n }\n leaves.set(tag, { ...registration, tag });\n notify();\n}\n\n/** Relayout every connected host — the invalidation hook for leaf\n * content whose inputs changed outside the DOM (a font finished\n * registering, …). Coalesced per frame by the hosts themselves. */\nexport function invalidateLeaves(): void {\n notify();\n}\n\nexport function leafRendererFor(tagName: string): LeafRegistration | undefined {\n return leaves.get(tagName.toLowerCase());\n}\n\n/** The union of every registration's observed attributes — the host\n * extends its MutationObserver filter with these. */\nexport function leafObservedAttributes(): string[] {\n const all = new Set<string>();\n for (const leaf of leaves.values()) {\n for (const attribute of leaf.observedAttributes ?? []) all.add(attribute.toLowerCase());\n }\n return [...all];\n}\n\n/** Host subscription to registry changes (registration or\n * invalidation); returns the unsubscriber. Internal to the engine. */\nexport function onLeafRegistryChange(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\n/** Run a renderer with the spec's error contract: a throw must never\n * break layout — warn once per element and render nothing this pass. */\nexport function renderLeafContent(leaf: LeafRegistration, el: Element): LeafContent | null {\n try {\n return leaf.render(el);\n } catch (err) {\n warnOnce(el, `<${leaf.tag}> renderer threw; rendering nothing. ${String(err)}`);\n return null;\n }\n}\n\nfunction notify(): void {\n for (const listener of listeners) listener();\n}\n","import { DOUBLE_JUNCTIONS, LIGHT_JUNCTIONS, glyphSetFor, junctionRole } from \"./glyphs.ts\";\nimport type { BorderGlyphSet } from \"./glyphs.ts\";\nimport type {\n RuleBreak,\n RuleVisibilityItems,\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(\n out,\n style.borderStyle,\n style.borderColor,\n ringRect,\n sides,\n glyphSetFor(style.glyphSet),\n );\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 set?: BorderGlyphSet,\n): void {\n const top = borderGlyphs(styles.top, set);\n const right = borderGlyphs(styles.right, set);\n const bottom = borderGlyphs(styles.bottom, set);\n const left = borderGlyphs(styles.left, set);\n const corner = (a: BorderStyle, b: BorderStyle, pick: (g: Glyphs) => string): string =>\n a === b ? pick(borderGlyphs(a, set)) : pick(borderGlyphs(\"solid\", set));\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/** Whether the child paints in the positioned step (Appendix E step\n * 8+): positioned elements, and flex/grid items with an explicit\n * z-index (z-index applies there per CSS, but `auto` items paint as\n * normal flow, steps 4-7 — source order only decides among them,\n * never over a positioned sibling). */\nexport function paintsInPositionedStep(child: LayoutNode, parent: LayoutNode): boolean {\n return (\n child.style.position !== \"static\" ||\n ((parent.style.display === \"flex\" || parent.style.display === \"grid\") &&\n child.style.zIndex !== null)\n );\n}\n\n/** Children in paint order (CSS 2.1 Appendix E, no floats and sibling\n * stacking only): negative z-index (asc), then non-positioned block,\n * then non-positioned inline, then positioned with z-index >= 0 or\n * auto (asc, auto counts as 0). Stable within a bucket, so DOM order\n * breaks ties. Bucketed instead of full-sorted so the common case\n * (single bucket, no z-index) is allocation-free. */\nexport function paintOrderedChildren(node: LayoutNode): LayoutNode[] {\n if (node.children.length <= 1) return node.children;\n let negatives: LayoutNode[] | null = null;\n let blocks: LayoutNode[] | null = null;\n let inlines: LayoutNode[] | null = null;\n let positioned: LayoutNode[] | null = null;\n for (const child of node.children) {\n if (paintsInPositionedStep(child, node)) {\n if ((child.style.zIndex ?? 0) < 0) (negatives ??= []).push(child);\n else (positioned ??= []).push(child);\n } else if (child.inlineBox) (inlines ??= []).push(child);\n else (blocks ??= []).push(child);\n }\n if (negatives && negatives.length > 1) {\n negatives.sort((a, b) => (a.style.zIndex ?? 0) - (b.style.zIndex ?? 0));\n }\n if (positioned && positioned.length > 1) {\n positioned.sort((a, b) => (a.style.zIndex ?? 0) - (b.style.zIndex ?? 0));\n }\n if (!negatives && blocks && !inlines && !positioned) return blocks;\n if (!negatives && !blocks && inlines && !positioned) return inlines;\n if (!negatives && !blocks && !inlines && positioned) return positioned;\n return [...(negatives ?? []), ...(blocks ?? []), ...(inlines ?? []), ...(positioned ?? [])];\n}\n\n/** A style's straight line glyph, for lattice segments. */\nexport function lineGlyph(style: BorderStyle, axis: \"h\" | \"v\", set?: BorderGlyphSet): string {\n const glyphs = borderGlyphs(style, set);\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. An active glyph SET (specs/theming.md) overrides PER\n * GLYPH by junction role. */\nexport function junctionGlyph(\n style: BorderStyle,\n up: boolean,\n down: boolean,\n left: boolean,\n right: boolean,\n set?: BorderGlyphSet,\n): string {\n const mask = (up ? 8 : 0) | (down ? 4 : 0) | (left ? 2 : 0) | (right ? 1 : 0);\n if (set) {\n const role = junctionRole(mask);\n const override = role && set[style]?.[role];\n if (override) return override;\n }\n const table = style === \"double\" ? DOUBLE_JUNCTIONS : LIGHT_JUNCTIONS;\n return table[mask]!;\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, set?: BorderGlyphSet): Glyphs {\n const j = (up: boolean, down: boolean, left: boolean, right: boolean) =>\n junctionGlyph(style, up, down, left, right, set);\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 { h: \"╌\", v: \"╎\", ...withoutLines(base), ...setLines(set, style) };\n if (style === \"dotted\") return { h: \"┄\", v: \"┊\", ...withoutLines(base), ...setLines(set, style) };\n return base;\n}\n\nfunction withoutLines(glyphs: Glyphs): Omit<Glyphs, \"h\" | \"v\"> {\n const { h: _h, v: _v, ...rest } = glyphs;\n return rest;\n}\n\nfunction setLines(set: BorderGlyphSet | undefined, style: BorderStyle): Partial<Glyphs> {\n const table = set?.[style];\n const lines: Partial<Glyphs> = {};\n if (table?.h) lines.h = table.h;\n if (table?.v) lines.v = table.v;\n return lines;\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. A `half` endpoint is an overlap-join extension\n * tip: its ink reaches only the end cell's centerline, so meeting\n * rules connect there (`┘`) instead of crossing past each other. */\nexport interface RuleSegment {\n bandStart: number;\n bandSize: number;\n start: number;\n end: number;\n startHalf?: boolean;\n endHalf?: boolean;\n}\n\n/** One cross-axis strip of a gap band: the cells beside a crossing\n * track, `[start, end)` along the band, with what borders it. */\nexport interface GapStrip {\n start: number;\n end: number;\n /** An item spans ACROSS the gap here — the gap doesn't exist. */\n spanned: boolean;\n /** The cells on either side of the gap hold items. */\n beforeOccupied: boolean;\n afterOccupied: boolean;\n}\n\nexport interface GapSegment {\n start: number;\n end: number;\n startHalf?: boolean;\n endHalf?: boolean;\n}\n\n/**\n * Split one gap band into painted segments (specs/gap-decorations.md\n * \"Segments\", probed in Chromium 151): track strips kept per spanning\n * occupancy and rule-visibility-items, crossing-gap strips joined per\n * rule-break, contiguous runs merged, endpoints retracted by the inset.\n */\nexport function ruleBandSegments(\n strips: GapStrip[],\n ruleBreak: RuleBreak,\n visibility: RuleVisibilityItems,\n inset: number | \"overlap-join\",\n): GapSegment[] {\n const covered = strips.map((strip) => {\n if (strip.spanned) return false;\n if (visibility === \"between\") return strip.beforeOccupied && strip.afterOccupied;\n if (visibility === \"around\") return strip.beforeOccupied || strip.afterOccupied;\n return true; // all — and grid's normal\n });\n const pieces: { start: number; end: number; covered: boolean }[] = [];\n for (let i = 0; i < strips.length; i++) {\n pieces.push({ start: strips[i]!.start, end: strips[i]!.end, covered: covered[i]! });\n if (i + 1 < strips.length) {\n const joined =\n ruleBreak === \"intersection\"\n ? false\n : ruleBreak === \"none\"\n ? covered[i]! || covered[i + 1]!\n : covered[i]! && covered[i + 1]!;\n pieces.push({ start: strips[i]!.end, end: strips[i + 1]!.start, covered: joined });\n }\n }\n const segments: GapSegment[] = [];\n for (const piece of pieces) {\n if (!piece.covered) continue;\n const last = segments[segments.length - 1];\n if (last && last.end === piece.start) last.end = piece.end;\n else segments.push({ start: piece.start, end: piece.end });\n }\n if (inset === \"overlap-join\") {\n // Junction endpoints extend into the crossing gap to its centerline\n // (half the gap plus half the crossing rule, probed — Chromium\n // extends whether or not a crossing rule paints there); segments\n // that run through a crossing don't end at its boundary, so the\n // lookups miss them. Cap endpoints stay put, per the spec.\n const startExtension = new Map<number, number>();\n const endExtension = new Map<number, number>();\n for (let i = 0; i + 1 < strips.length; i++) {\n const crossingStart = strips[i]!.end;\n const width = strips[i + 1]!.start - crossingStart;\n if (width <= 0) continue;\n endExtension.set(crossingStart, crossingStart + Math.ceil(width / 2));\n startExtension.set(strips[i + 1]!.start, crossingStart + Math.floor(width / 2));\n }\n return segments.map((segment) => {\n const start = startExtension.get(segment.start);\n const end = endExtension.get(segment.end);\n return {\n start: start ?? segment.start,\n end: end ?? segment.end,\n startHalf: start !== undefined,\n endHalf: end !== undefined,\n };\n });\n }\n return segments\n .map((segment) => ({ start: segment.start + inset, end: segment.end - inset }))\n .filter((segment) => segment.end > segment.start);\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 /** The owning container's resolved glyph set (specs/theming.md). */\n glyphs?: BorderGlyphSet | undefined;\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 startHalf: seg.startHalf === true,\n endHalf: seg.endHalf === true,\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 /** Junction arms come from INK AT CELL BOUNDARIES over the union of\n * segments: a segment through boundary `b`, or full-ending exactly\n * there — a `half` overlap-join tip stops at its cell's centerline\n * and contributes no arm past it (elbows over crosses). */\n const inkAtBoundary = (lines: typeof vLines, width: number, across: number, b: number): boolean =>\n lines.some(\n (l) =>\n across >= l.line &&\n across < l.line + width &&\n ((l.start < b && l.end > b) ||\n (l.end === b && !l.endHalf) ||\n (l.start === b && !l.startHalf)),\n );\n /** Is the cell inside a horizontal segment? (Those cells belong to\n * the horizontal pass, which paints the junctions — no double glyphs.) */\n const insideHorizontal = (x: number, y: number): boolean =>\n hLines.some((l) => y >= l.line && y < l.line + hWidth && x >= l.start && x < l.end);\n\n if (ctx.ruleX) {\n const glyph = lineGlyph(ctx.ruleX.style, \"v\", ctx.glyphs);\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(line.line + t, 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 up = inkAtBoundary(vLines, vWidth, x, y);\n const down = inkAtBoundary(vLines, vWidth, x, y + 1);\n out.push({\n glyph:\n up || down\n ? junctionGlyph(\n allDouble ? \"double\" : \"solid\",\n up,\n down,\n inkAtBoundary(hLines, hWidth, y, x),\n inkAtBoundary(hLines, hWidth, y, x + 1),\n ctx.glyphs,\n )\n : lineGlyph(ctx.ruleY.style, \"h\", ctx.glyphs),\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({\n glyph: junctionGlyph(style, up, down, left, right, ctx.glyphs),\n x,\n y,\n length: 1,\n color,\n });\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 // Glyph ink vs line box: a Range rect spans the font's ascent + descent,\n // which some fonts draw TALLER than their `normal` line box. WebKit\n // fragments columns at ink bottoms, so multicol needs the overhang.\n const range = probe.ownerDocument.createRange();\n range.selectNodeContents(probe);\n const inkOverhang = Math.max(0, range.getBoundingClientRect().height - rect.height);\n return { width: rect.width / 100, height: rect.height, letterSpacing, inkOverhang };\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 /** `text-indent` in cells: reduces the first hard line's usable width\n * (the paint layer offsets that line's x by the same amount). Per CSS,\n * subsequent hard lines (`<br>`-separated) don't re-indent. */\n firstLineIndent?: number | undefined;\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/** A final `\\n` produces no last line box (probed, all engines: `a<br>`\n * is one line, `a<br><br>` two, `<br>` alone one) — drop the empty span\n * it would otherwise create. */\nfunction dropFinalBreakSpan(spans: LineSpan[], text: string): LineSpan[] {\n if (text.endsWith(\"\\n\")) spans.pop();\n return spans;\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 dropFinalBreakSpan(spans, text);\n}\n\nexport function wrapLineSpans(text: string, width: number, options: WrapOptions = {}): LineSpan[] {\n // Empty = nothing but collapsible white space — but a `\\n` is a hard\n // break (a `<br>`), never collapsible. NOT `trim()`, which would also\n // eat NBSP — an NBSP-only leaf still renders a line in the browser.\n if (!/[^ \\t\\r\\f]/.test(text)) return [];\n const spans: LineSpan[] = [];\n let lineStart = 0;\n let indent = options.firstLineIndent ?? 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, indent));\n indent = 0; // Only the very first hard line gets the indent.\n lineStart = i + 1;\n }\n }\n return dropFinalBreakSpan(spans, text);\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 firstLineIndent = 0,\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 // Only the first line box (before the first `lines.push`) is charged\n // the text-indent — subsequent lines get the full width back.\n let lineIndent = Math.max(0, firstLineIndent);\n const availableWidth = () => width - lineIndent;\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 <= availableWidth()) {\n current.end = segEnd;\n advancesSum = candidate;\n } else {\n if (current !== null) {\n lines.push(current);\n lineIndent = 0;\n }\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 (\n fit < segEnd &&\n lineAdvance(segStart, fit + 1, advances, tracking) <= availableWidth()\n )\n fit++;\n if (fit === segEnd || fit === segStart) break;\n lines.push({ start: segStart, end: fit });\n lineIndent = 0;\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 { glyphSetFor } from \"./glyphs.ts\";\nimport { collectGapRuleRuns, ruleBandSegments } from \"./borders.ts\";\nimport type { GapSegment, GapStrip, 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\ninterface FlexLine {\n row: { node: LayoutNode }[];\n}\n\n/** Column-gap x-ranges of one line: the space between adjacent item\n * rects in visual order (whatever gap, justify, and margins produced). */\nfunction lineGapRanges(line: FlexLine, originX: number): { start: number; end: number }[] {\n const rects = line.row.map((item) => item.node.localRect).sort((a, b) => a.x - b.x);\n const ranges: { start: number; end: number }[] = [];\n for (let i = 1; i < rects.length; i++) {\n const start = rects[i - 1]!.x + rects[i - 1]!.width - originX;\n const end = rects[i]!.x - originX;\n if (end > start) ranges.push({ start, end });\n }\n return ranges;\n}\n\n/** Segments of the row-gap band above line `r`: under `rule-break:\n * intersection` the band breaks at the union of the two adjacent lines'\n * column gaps (probed in Chromium — a T from either side counts);\n * otherwise one full-width segment. */\nfunction rowBandSegments(\n node: LayoutNode,\n lines: FlexLine[],\n r: number,\n originX: number,\n innerWidth: number,\n): GapSegment[] {\n if (node.style.ruleBreak !== \"intersection\") return [{ start: 0, end: innerWidth }];\n const crossings = [lines[r - 1]!, lines[r]!]\n .flatMap((line) => lineGapRanges(line, originX))\n .sort((a, b) => a.start - b.start);\n // Item strips (the complement of the merged crossings) feed the shared\n // segmenter; every strip is plain occupied track.\n const occupiedStrip = (start: number, end: number): GapStrip => ({\n start,\n end,\n spanned: false,\n beforeOccupied: true,\n afterOccupied: true,\n });\n const strips: GapStrip[] = [];\n let cursor = 0;\n for (const crossing of crossings) {\n if (crossing.start > cursor) strips.push(occupiedStrip(cursor, crossing.start));\n cursor = Math.max(cursor, crossing.end);\n }\n if (cursor < innerWidth) strips.push(occupiedStrip(cursor, innerWidth));\n return ruleBandSegments(\n strips,\n \"intersection\",\n \"all\",\n node.style.ruleInset === \"overlap-join\" ? \"overlap-join\" : 0,\n );\n}\n\nexport function insetSegments(\n segments: RuleSegment[],\n inset: number | \"overlap-join\",\n): RuleSegment[] {\n if (typeof inset !== \"number\" || inset <= 0) return segments;\n return segments\n .map((segment) => ({ ...segment, start: segment.start + inset, end: segment.end - inset }))\n .filter((segment) => segment.end > segment.start);\n}\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's cross size IS a definite inner height (css-flexbox §9.4.8 —\n // stretched items shrink to it, content overflowing), and stretches to\n // a min-height floor so items-center / items-end have the enforced size\n // to align against. A wrap-enabled (\"multi-line\", per CSS — even with\n // one line) container distributes bounded leftover cross space per\n // `align-content`: `stretch` grows the lines; the other keywords offset\n // 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 (definiteInnerHeight !== undefined) rowHeights[0] = definiteInnerHeight;\n else if (Number.isFinite(innerHeight))\n 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) takes the row's\n // height — grown or shrunk (`min-height: auto` is 0 in the cross\n // axis; content overflows). Re-run layoutNode with the height forced\n // so nested content that depends on the parent's height sees it.\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 for (const gap of lineGapRanges(lines[r]!, originX)) {\n vertical.push({\n bandStart: gap.start,\n bandSize: gap.end - gap.start,\n start: top,\n end: top + rowHeights[r]!,\n });\n }\n if (r > 0) {\n const prevBottom = lineOffsets[r - 1]! + (r - 1) * gapY + rowHeights[r - 1]!;\n if (top > prevBottom) {\n for (const segment of rowBandSegments(node, lines, r, originX, innerWidth)) {\n horizontal.push({ bandStart: prevBottom, bandSize: top - prevBottom, ...segment });\n }\n }\n }\n }\n // `normal` behaves as `none` in flex and visibility-items is\n // grid/multicol-only (css-gaps), so beyond intersection breaks the\n // bands only honor rule-inset (specs/gap-decorations.md \"Segments\").\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(node.style.glyphSet),\n ruleX: node.style.ruleX,\n ruleY: node.style.ruleY,\n vertical: insetSegments(vertical, node.style.ruleInset),\n horizontal: insetSegments(horizontal, node.style.ruleInset),\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.y === \"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), retracted by rule-inset.\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 glyphs: glyphSetFor(node.style.glyphSet),\n ruleX: null,\n ruleY: node.style.ruleY,\n vertical: [],\n horizontal: insetSegments(horizontal, node.style.ruleInset),\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.x === \"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\" | \"multicol\" | \"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\";\n/** Per-axis overflow state. `hidden` reads as `\"clip\"` (no scroll\n * container, cheaper — the precise semantic for what the engine\n * does); `auto` and `scroll` are both scroll containers\n * (`scrollsAxis`), differing only in the gutter — `scroll` reserves\n * it always, `auto` only once content overflows. */\nexport type OverflowAxis = \"visible\" | \"clip\" | \"auto\" | \"scroll\";\n\nexport function scrollsAxis(axis: OverflowAxis): boolean {\n return axis === \"auto\" || axis === \"scroll\";\n}\nexport interface Overflow {\n x: OverflowAxis;\n y: OverflowAxis;\n}\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. */\n/** One run of a leaf's character → source map (see `LayoutNode.charSource`). */\nexport interface CharSourceRun {\n index: number;\n length: number;\n node: Text;\n offset: number;\n}\n\nexport interface InheritedTracks {\n positions: number[];\n sizes: number[];\n gapBefore: number[];\n gap: number;\n}\n\n/** A leaf's atomic inline boxes in MARKER order — the order of its\n * U+FFFC characters, which is document order (`children` is built in\n * document order). Every marker ↔ box pairing (layout widths and line\n * placement, copy splicing, boundary points inside a box) reads it here\n * and nowhere else. */\nexport function inlineBoxesOf(node: LayoutNode): LayoutNode[] {\n return node.children.filter((child) => child.inlineBox);\n}\n\n/** The gutter band each axis's bar occupies when reserved\n * (specs/scrolling.md): the bar's thickness plus the perpendicular\n * inset that moves it inward — the rightmost columns for y, the\n * bottom rows for x. */\nexport function scrollGutterBands(style: CellStyle): { right: number; bottom: number } {\n return {\n right: style.scrollbarSize.y + style.scrollbarInset.x,\n bottom: style.scrollbarSize.x + style.scrollbarInset.y,\n };\n}\n\n/** The gutters an explicit `scroll` axis reserves unconditionally\n * (specs/scrolling.md). Folded into padding wherever padding cells\n * are derived, so content-box math, intrinsic sizes, and the native\n * overlay (--mw-p*) agree. `auto` axes reserve only on overflow, in\n * layoutNode's second pass — never here. */\nexport function scrollGutter(style: CellStyle): { right: number; bottom: number } {\n if (style.scrollbarWidth === \"none\") return { right: 0, bottom: 0 };\n const bands = scrollGutterBands(style);\n return {\n right: style.overflow.y === \"scroll\" ? bands.right : 0,\n bottom: style.overflow.x === \"scroll\" ? bands.bottom : 0,\n };\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/** Where rule segments break at gap intersections (css-gaps-1\n * rule-break; specs/gap-decorations.md \"Segments\"). */\nexport type RuleBreak = \"none\" | \"normal\" | \"intersection\";\n\n/** Which segments paint next to empty grid areas (css-gaps-1\n * rule-visibility-items; `normal` acts as `all` in grid). */\nexport type RuleVisibilityItems = \"normal\" | \"all\" | \"around\" | \"between\";\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 /** `scrollbar-width: none` suppresses the gutter and bar entirely;\n * `thin` and `auto` both defer to `scrollbarSize`\n * (specs/scrolling.md). */\n scrollbarWidth: \"auto\" | \"none\";\n /** Bar thickness in cells per axis — `x` the horizontal bar's\n * height, `y` the vertical bar's width (`--mw-scrollbar-size-x/y`,\n * the scrollbar-*, scrollbar-x-*, scrollbar-y-* utilities; default\n * 1). */\n scrollbarSize: { x: number; y: number };\n /** Cells kept clear around the bars for the author's arrow buttons\n * (`--mw-scrollbar-inset-x/y`, the scrollbar-inset-* utilities;\n * default 0; specs/scrolling.md). */\n scrollbarInset: { x: number; y: number };\n /** `scrollbar-color` thumb/track ink; `null` = currentColor pair. */\n scrollbarColor: { thumb: string; track: string } | null;\n /** Per-axis `overscroll-behavior`: whether a boundary gesture may\n * CHAIN to an ancestor scroller (the grid-mode wheel router's\n * gesture-start decision; the native path honors it natively). */\n overscroll: { x: boolean; y: boolean };\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 /** `bg-clear` marker (`--mw-bg-clear: 1`): occlude ancestor decoration\n * glyphs under this element's border box WITHOUT painting a bg color.\n * `backgroundColor` stays undefined; the renderer fills with plain\n * spaces instead of colored spaces. */\n backgroundClear: boolean;\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 `justify` — forced back to `start` (its\n * extra per-line word spacing is fractional). See cell-model spec. */\n textAlignBlocked: boolean;\n /** Computed text-align, normalized LTR. `end` offsets each line by\n * W − line, `center` by floor((W − line) / 2) — whole cells, painted\n * by the grid (the browser's own fractional centering only touches\n * the invisible light-DOM copy). */\n textAlign: \"start\" | \"center\" | \"end\";\n /** First-line indent in cells (per CSS: applies once to the first\n * formatted line of the block; `<br>` doesn't re-indent). Charged\n * against the wrap width of the first line and offsets that line's\n * paint x. Percentages resolve to 0 (unsupported). */\n textIndent: number;\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 /** Effective element opacity input (0..1). Ancestors MULTIPLY down\n * the paint walk (CSS opacity nests, it doesn't inherit); the product\n * rides on every emitted grid span, which composites against the\n * page — translucency blends with what's behind the host, never with\n * covered cells (deviation; front paint wins a cell as always). */\n opacity: number;\n /** The border glyph SET name from `--mw-border-glyphs` (`null` =\n * default) — the theming vocabulary borders/lattices/rules resolve\n * through (specs/theming.md); resolved on the decoration's owner. */\n glyphSet: string | null;\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 ruleBreak: RuleBreak;\n /** Cells retracted from every rule-segment endpoint (rule-inset,\n * quantized like border widths) — or `overlap-join`, which instead\n * extends junction endpoints into the crossing gap so meeting rules\n * connect. */\n ruleInset: number | \"overlap-join\";\n ruleVisibilityItems: RuleVisibilityItems;\n /** Multicol container inputs (specs/multicol.md): authored\n * column-count / column-width (cells), null = auto. A container is\n * multicol (display \"multicol\") when either is set on a block. */\n columnCount: number | null;\n columnWidth: number | null;\n columnFill: \"auto\" | \"balance\";\n /** column-span: all on a child — closes the column row, spans the\n * container's full content width (specs/multicol.md \"Spanners\"). */\n columnSpan: boolean;\n /** Forced column breaks (`break-before/after-column`). */\n breakBeforeColumn: boolean;\n breakAfterColumn: boolean;\n /** `break-inside: avoid` / `avoid-column` — a paragraph-flow child\n * fragments as one unbreakable unit (specs/multicol.md). */\n breakInsideAvoid: boolean;\n}\n\nexport interface LayoutNode {\n source: Element;\n style: CellStyle;\n /** In document order (tree.ts): paint-order ties resolve later-wins,\n * and a leaf's atomic inline boxes are in marker order — see\n * `inlineBoxesOf`, the one place that pairing is read. */\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 styling mirrored into the grid (the browser's own\n * ink is transparent-locked). `backgroundColor` fills the run's\n * cells — how a focus-inverted inline link shows its highlight. */\n color: string | undefined;\n backgroundColor: 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 /** Where each character of `text` came from, as runs of consecutive\n * characters (specs/semantic-selection.md): `text[index + k]` is\n * `node.data[offset + k]` for `k < length`. Characters with no source\n * position (`<br>` newlines, inline-box and padding markers) fall\n * between runs; renderer leaves have no map. */\n charSource?: CharSourceRun[];\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 /** A text leaf's ink extent in content cells (widest line, rows) —\n * written by the leaf pass; scrollable-overflow accounting reads it\n * instead of re-wrapping. */\n textExtent?: { width: number; rows: number };\n /** Scroll geometry (specs/scrolling.md), written by layoutNode on\n * containers with a scroll axis: content extent and the derived\n * max offset, both in cells. Absent elsewhere. */\n scrollRange?: { sizeX: number; sizeY: number; maxX: number; maxY: number };\n /** Current scroll offset in cells (paint-time input, written by the\n * element from native scrollTop/scrollLeft; absent = 0/0). */\n scroll?: { x: number; y: number };\n /** The gutter cells this container actually reserved — `scroll`\n * axes always, `auto` axes only when content overflows (the layout\n * second pass). Paint, hit-testing, and thumb drags read THIS, not\n * the style. */\n scrollGutterCells?: { right: number; bottom: 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 /** Fragmented line map of a multicol text leaf (specs/multicol.md):\n * text wrapped at the column width, each line assigned a column and\n * column-local rows. Written by layout; the plain-text renderer reads\n * it back so both place lines identically. A paragraph-flow container\n * carries a spanless one for its rules, height fold, and native\n * column vars; its children carry their own line maps in\n * container-content coordinates. */\n multicolGeometry?: MulticolLeafGeometry;\n /** Paragraph-flow multicol child (specs/multicol.md \"Fragmenting\n * text-leaf children\"): stays IN FLOW in the browser inside the\n * container's native columns so the browser fragments it itself.\n * Carries the engine-resolved margins the companion re-applies\n * quantized. */\n multicolFlow?: NullableInsets;\n /** In-flow multicol SPANNER (specs/multicol.md): a normally laid-out\n * box that stays in the native flow with `column-span: all`, its\n * geometry forced like a laid-out element's. Carries the quantized\n * native margins (`left` = the engine's cross offset). */\n multicolFlowSpan?: NullableInsets;\n}\n\n/** A multicol text leaf's per-line fragmentation. `lineY`/`textY` are\n * COLUMN-local rows; `lineX` is the line's column's content-relative x.\n * Leaf columns are all `columnWidth` wide (the division remainder is\n * folded into the engine-owned right padding so the browser's equal\n * fractional columns land on the same whole cells). */\nexport interface MulticolLeafGeometry {\n spans: { start: number; end: number }[];\n lineY: number[];\n textY: number[];\n lineX: number[];\n totalRows: number;\n columnCount: number;\n columnWidth: number;\n gap: number;\n /** Columns holding at least one line — overflow columns included. */\n columnsUsed: number;\n /** Spanner-split flow: one rule extent per SEGMENT (content-relative\n * rows and its occupied columns); absent = one full-height segment. */\n ruleSegments?: { start: number; end: number; columns: number }[];\n /** Spanner-split flow relies on the NATIVE balancer per segment (the\n * companion keeps `column-fill: balance` and the natural height)\n * instead of the fill-to-computed-height reconstruction. */\n nativeBalance?: boolean;\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 /** How far a glyph's ink extends past the cell's line box, in px\n * (some fonts' ascent + descent exceed their `normal` line box).\n * WebKit breaks columns at ink bottoms, so multicol leaves get this\n * much extra native column height (see styles.css). */\n inkOverhang?: 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: { x: \"visible\", y: \"visible\" },\n scrollbarWidth: \"auto\",\n scrollbarSize: { x: 1, y: 1 },\n scrollbarInset: { x: 0, y: 0 },\n overscroll: { x: true, y: true },\n scrollbarColor: null,\n whiteSpace: \"normal\",\n tabSize: 8,\n lineGap: 0,\n tracking: 0,\n textOverflow: \"clip\",\n color: undefined,\n backgroundColor: undefined,\n backgroundClear: false,\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 textIndent: 0,\n tableRole: \"none\",\n tableLayout: \"auto\",\n borderCollapse: false,\n borderSpacingX: 0,\n borderSpacingY: 0,\n captionSide: \"top\",\n verticalAlign: \"start\",\n glyphSet: null,\n opacity: 1,\n zIndex: null,\n latticeBorder: null,\n ruleX: null,\n ruleY: null,\n ruleBreak: \"normal\",\n ruleInset: 0,\n ruleVisibilityItems: \"normal\",\n columnCount: null,\n columnWidth: null,\n columnFill: \"balance\",\n columnSpan: false,\n breakBeforeColumn: false,\n breakAfterColumn: false,\n breakInsideAvoid: 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 { collectGapRuleRuns, ruleBandSegments } from \"./borders.ts\";\nimport { glyphSetFor } from \"./glyphs.ts\";\nimport type { GapStrip } from \"./borders.ts\";\nimport type { RuleSegment } from \"./borders.ts\";\nimport { percentToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack } from \"./types.ts\";\nimport {\n clampSize,\n isOutOfFlow,\n layoutNode,\n minContentOuterWidth,\n resolveGap,\n resolveLength,\n resolveLimit,\n resolveMargin,\n resolveWidthLimit,\n widthContribution,\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.x === \"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 // an item's max-content block contribution IS its laid-out height; its\n // minimum is the automatic minimum) — or the parent's tracks when this\n // 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.y === \"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 // segmented per placement occupancy, rule-break, rule-visibility-items,\n // and rule-inset (see the spec's \"Segments\" section).\n if (style.ruleX || style.ruleY) {\n const colCount = colSizing.sizes.length;\n const rowCount = rowSizing.sizes.length;\n // occupied[c][r]: a cell holds (part of) an item. crossesCol[g][r]:\n // an item spans across column-gap g (between columns g and g+1)\n // at row r — the gap doesn't exist there; crossesRow likewise.\n const occupied = Array.from({ length: colCount }, () =>\n Array.from({ length: rowCount }, () => false),\n );\n const crossesCol = Array.from({ length: Math.max(0, colCount - 1) }, () =>\n Array.from({ length: rowCount }, () => false),\n );\n const crossesRow = Array.from({ length: Math.max(0, rowCount - 1) }, () =>\n Array.from({ length: colCount }, () => false),\n );\n for (const p of placed.items) {\n for (let c = p.col.start; c < p.col.start + p.col.span && c < colCount; c++) {\n for (let r = p.row.start; r < p.row.start + p.row.span && r < rowCount; r++) {\n occupied[c]![r] = true;\n if (c + 1 < p.col.start + p.col.span && c < colCount - 1) crossesCol[c]![r] = true;\n if (r + 1 < p.row.start + p.row.span && r < rowCount - 1) crossesRow[r]![c] = true;\n }\n }\n }\n const strips = (\n gap: number,\n positions: number[],\n sizes: number[],\n crosses: boolean[][],\n before: (t: number) => boolean,\n after: (t: number) => boolean,\n ): GapStrip[] =>\n positions.map((position, t) => ({\n start: position,\n end: position + sizes[t]!,\n spanned: crosses[gap]?.[t] ?? false,\n beforeOccupied: before(t),\n afterOccupied: after(t),\n }));\n const bandSegments = (\n positions: number[],\n sizes: number[],\n stripsFor: (gap: number) => GapStrip[],\n ): 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) continue;\n for (const segment of ruleBandSegments(\n stripsFor(i - 1),\n style.ruleBreak,\n style.ruleVisibilityItems,\n style.ruleInset,\n )) {\n bands.push({ bandStart, bandSize, ...segment });\n }\n }\n return bands;\n };\n const vertical = bandSegments(colPos, colSizing.sizes, (gap) =>\n strips(\n gap,\n rowPos,\n rowSizing.sizes,\n crossesCol,\n (r) => occupied[gap]?.[r] ?? false,\n (r) => occupied[gap + 1]?.[r] ?? false,\n ),\n );\n const horizontal = bandSegments(rowPos, rowSizing.sizes, (gap) =>\n strips(\n gap,\n colPos,\n colSizing.sizes,\n crossesRow,\n (c) => occupied[c]?.[gap] ?? false,\n (c) => occupied[c]?.[gap + 1] ?? false,\n ),\n );\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(style.glyphSet),\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 // The minimum contribution is the automatic minimum (CSS §11.5.1 /\n // css-sizing): the content height while overflow is visible, 0 for\n // a scroll container — so `fr` rows can shrink one against a cap.\n const min =\n child.style.minHeight === \"auto\" && child.style.overflow.y !== \"visible\"\n ? fixedY(margin)\n : height;\n items.push({ start: p.row.start, span: p.row.span, min, 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// ---------------------------------------------------------------------------\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 { collectGapRuleRuns } from \"./borders.ts\";\nimport { glyphSetFor } from \"./glyphs.ts\";\nimport type { RuleSegment } from \"./borders.ts\";\nimport { insetSegments } from \"./flex.ts\";\nimport {\n blockCrossOffset,\n collapseMargins,\n isOutOfFlow,\n layoutNode,\n leafLineMetrics,\n leafLineSpans,\n resolveGap,\n resolveMargin,\n} from \"./layout.ts\";\nimport type { IntrinsicCache } from \"./layout.ts\";\nimport { wrapLineSpans } from \"./wrap.ts\";\nimport type {\n CellStyle,\n Insets,\n LayoutNode,\n MulticolLeafGeometry,\n NullableInsets,\n} from \"./types.ts\";\n\n/**\n * Multi-column layout (specs/multicol.md): css-multicol §3.4 column\n * resolution in cells, sequential/balanced fill, spanners, and column\n * rules through the gap-decoration pipeline. Direct-text leaves fragment\n * at line granularity; element children distribute atomically. Part of\n * the deliberate layout-module import cycle (see layout.ts).\n */\n\n/** Used column count per css-multicol §3.4, from the computed\n * `column-count`/`column-width` pair. */\nfunction usedColumnCount(style: CellStyle, available: number, gap: number): number {\n const fit =\n style.columnWidth !== null\n ? Math.max(1, Math.floor((available + gap) / (style.columnWidth + gap)))\n : null;\n if (style.columnCount !== null && fit !== null)\n return Math.max(1, Math.min(style.columnCount, fit));\n if (fit !== null) return fit;\n return Math.max(1, style.columnCount ?? 1);\n}\n\n/** Column tracks for an element-children container: base width\n * `floor((available − (count − 1) × gap) / count)` with the remainder\n * distributed one cell per column left to right. */\nexport function resolveColumnTracks(style: CellStyle, available: number, gap: number): number[] {\n const count = usedColumnCount(style, available, gap);\n const base = Math.max(1, Math.floor((available - (count - 1) * gap) / count));\n const leftover = Math.max(0, available - (count * base + (count - 1) * gap));\n return Array.from({ length: count }, (_, i) => base + (i < leftover ? 1 : 0));\n}\n\n/** Max-content inner width: `count × content + (count − 1) × gap` when\n * `column-count` drives the count (probed: all three engines agree);\n * with only `column-width`, the content's own max-content floored at\n * one `W`-wide column (Chromium/WebKit; Firefox clamps to `W` — a\n * documented divergence, specs/multicol.md). */\nexport function multicolIntrinsicInnerWidth(style: CellStyle, contentMax: number): number {\n const gap = Math.max(typeof style.gapX === \"number\" ? style.gapX : 0, style.ruleX?.width ?? 0);\n if (style.columnCount !== null) {\n return style.columnCount * contentMax + (style.columnCount - 1) * gap;\n }\n return Math.max(style.columnWidth ?? 1, contentMax);\n}\n\n/** The column-height restriction (css-multicol §7): the smaller of the\n * definite height and the max-height, either alone, or none. */\nexport function restrictingHeight(\n definite: number | undefined,\n max: number | undefined,\n): number | undefined {\n if (definite === undefined) return max;\n if (max === undefined) return definite;\n return Math.min(definite, max);\n}\n\n/** Smallest `height` in `[lo, hi]` accepted by `fits` (monotonic). */\nfunction minimalHeight(lo: number, hi: number, fits: (height: number) => boolean): number {\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (fits(mid)) hi = mid;\n else lo = mid + 1;\n }\n return lo;\n}\n\n/** Column geometry for a TEXT LEAF: all columns equal at the base width,\n * the remainder reported so layout can fold it into the engine-owned\n * right padding — the browser's equal fractional columns then start on\n * the same whole cells as the engine's. */\nexport function resolveLeafColumns(\n style: CellStyle,\n available: number,\n gap: number,\n): { count: number; width: number; leftover: number } {\n const count = usedColumnCount(style, available, gap);\n const width = Math.max(1, Math.floor((available - (count - 1) * gap) / count));\n const leftover = Math.max(0, available - (count * width + (count - 1) * gap));\n return { count, width, leftover };\n}\n\n/** Whether a rule paints in a gap given which side columns hold content:\n * CSS paints rules only between two columns that both have content\n * (`normal`/`between`); `around` needs either side, `all` always paints\n * (specs/gap-decorations.md item visibility). */\nfunction ruleVisible(\n mode: CellStyle[\"ruleVisibilityItems\"],\n before: boolean,\n after: boolean,\n): boolean {\n if (mode === \"all\") return true;\n if (mode === \"around\") return before || after;\n return before && after;\n}\n\n/**\n * Fragment a multicol text leaf into columns (specs/multicol.md \"Direct\n * text\"): wrap at the column width, then fill columns sequentially into\n * the fill height — every line box spans its own leading (`height +\n * lineGap` rows, the browser's line-box model), and a line never splits\n * across columns. `balance` packs into the minimal height that needs at\n * most `count` columns (clamped to a definite height); `auto` with a\n * definite height fills each column to it, overflow columns catching\n * the rest.\n */\nexport function multicolLeafGeometry(\n node: LayoutNode,\n columns: { count: number; width: number },\n gap: number,\n definiteHeight: number | undefined,\n): MulticolLeafGeometry {\n // Tracked text wraps at `width − tracking`: the browser fits a line\n // into its column COUNTING the phantom trailing letter-spacing gap\n // (probed in all three engines — the single-column carve-out has no\n // per-column equivalent, so the fit rule tightens instead).\n const spans = leafLineSpans(node, Math.max(1, columns.width - node.style.tracking));\n const { heights, textOffsets } = leafLineMetrics(node, spans);\n const lineGap = node.style.lineGap;\n const units = lineUnits(heights.map((h) => h + lineGap));\n\n let height: number;\n if (node.style.columnFill === \"auto\" && definiteHeight !== undefined) {\n height = Math.max(1, definiteHeight);\n } else {\n const balanced = minimalHeight(\n units.reduce((max, unit) => Math.max(max, unit.rows - lineGap), 1),\n Math.max(1, units.reduce((sum, unit) => sum + unit.rows, 0) - lineGap),\n (limit) => fillLineColumns(units, lineGap, limit).columns <= columns.count,\n );\n height =\n definiteHeight !== undefined ? Math.max(1, Math.min(balanced, definiteHeight)) : balanced;\n }\n\n const filled = fillLineColumns(units, lineGap, height);\n return {\n spans,\n lineY: filled.top,\n textY: filled.top.map((top, s) => top + textOffsets[s]!),\n lineX: filled.column.map((c) => c * (columns.width + gap)),\n totalRows: filled.maxUsed,\n columnCount: columns.count,\n columnWidth: columns.width,\n gap,\n columnsUsed: spans.length > 0 ? filled.columns : 0,\n };\n}\n\n/** One unit of a column fill: its rows (line box heights + trailing\n * leading), the collapsed margin rows before it (0 within a child),\n * whether a forced break precedes it, and its line count — an\n * unbreakable `break-inside: avoid` child contributes ONE unit\n * carrying all its lines. */\ninterface FillUnit {\n rows: number;\n pre: number;\n /** Glued trailing rows (a paragraph gap as padding-bottom): counted\n * with the unit at break checks, never trimmed or spilled. */\n post: number;\n forced: boolean;\n lines: number;\n}\n\n/** How `pre` rows behave at a column break (specs/multicol.md):\n * - \"truncate\": a break swallows the margin it lands in (CSS\n * Fragmentation §5.2) — the spanless forced-height reconstruction,\n * where the native gaps ARE margins.\n * - \"glue\": the spanner path, where the companion rewrites each gap as\n * padding-bottom on the PRECEDING paragraph (`post` rows) —\n * Chromium/Firefox keep a trailing padding monolithic with its last\n * line (probed pixel-exact), so the gap sits invisibly at a column\n * bottom and the next paragraph starts flush at the column top, the\n * CSS-truncation look. WebKit instead slice-spills padding across\n * breaks AND adds further in-engine divergences (fractional balance\n * heights, post-spanner segment misplacement), so\n * `detectGluedPreBreak` gates it back to the zero-margin constraint —\n * see the layoutMulticol dispatch. */\ntype PreBreakMode = \"truncate\" | \"glue\";\n\n/** Greedy sequential fill of line units into columns at `limit`:\n * LINE-major columns and top rows. Heights are TIGHT — a column of L\n * lines occupies `Σ(h + lineGap) − lineGap` rows, its last line's\n * trailing leading trimmed like a single-column leaf's (the companion\n * re-extends the native box by `lineGap` so the browser still counts\n * full line boxes). `pre` rows follow `mode` at breaks (see\n * PreBreakMode); the very first margin stays — a multicol container is\n * an independent formatting context, so it never parent-collapses. A\n * multi-line unit too tall for ANY column breaks to a fresh column and\n * then splits greedily (probed: Chromium/Firefox; WebKit instead\n * abandons `avoid` — documented divergence). Drives the balance\n * searches, the final maps, and the public `multicolLines` predictor. */\nfunction fillLineColumns(\n units: FillUnit[],\n lineGap: number,\n limit: number,\n mode: PreBreakMode = \"truncate\",\n): { columns: number; maxUsed: number; column: number[]; top: number[] } {\n let column = 0;\n let used = 0;\n let maxUsed = 0;\n const columnOf: number[] = [];\n const top: number[] = [];\n for (let i = 0; i < units.length; i++) {\n const unit = units[i]!;\n let lead = mode === \"glue\" || i === 0 || used > 0 ? unit.pre : 0;\n // A glued trailing pad is monolithic with its unit: the break check\n // counts it, and it never spills to the next column (probed).\n if (used > 0 && (unit.forced || used + lead + unit.rows + unit.post - lineGap > limit)) {\n if (mode === \"truncate\") lead = 0;\n column += 1;\n used = 0;\n }\n const lineRows = unit.rows / unit.lines;\n if (unit.lines > 1 && unit.rows - lineGap > limit) {\n // Too tall to keep whole: split greedily from the (fresh) column.\n for (let line = 0; line < unit.lines; line++) {\n if (used > 0 && used + lead + lineRows - lineGap > limit) {\n if (mode === \"truncate\") lead = 0;\n column += 1;\n used = 0;\n }\n columnOf.push(column);\n top.push(used + lead);\n used += lead + lineRows;\n lead = 0;\n maxUsed = Math.max(maxUsed, used - lineGap);\n }\n used += unit.post;\n if (unit.post > 0) maxUsed = Math.max(maxUsed, used);\n continue;\n }\n for (let line = 0; line < unit.lines; line++) {\n columnOf.push(column);\n top.push(used + lead + line * lineRows);\n }\n used += lead + unit.rows + unit.post;\n // A column ending in a bare line trims its trailing leading (tight\n // model); a glued pad sits below the FULL line box, untrimmed.\n maxUsed = Math.max(maxUsed, used - (unit.post > 0 ? 0 : lineGap));\n }\n return { columns: column + 1, maxUsed, column: columnOf, top };\n}\n\n/** Margin-less, break-less line units from per-line row heights. */\nfunction lineUnits(rows: number[]): FillUnit[] {\n return rows.map((r) => ({ rows: r, pre: 0, post: 0, forced: false, lines: 1 }));\n}\n\n/** Whether the running browser GLUES a trailing padding to its last\n * line at a column break — measured once from a hidden fixture\n * replaying the probes' distinguishing case: a 3-line paragraph with\n * one row of padding-bottom, then a 2-line one, balanced into 2\n * columns. Glue (Chromium/Firefox) keeps the pad in column 0 and the\n * second paragraph starts flush atop column 1; WebKit slice-spills the\n * pad into column 1, pushing the paragraph a row down. An environment\n * that doesn't lay the fixture out (unit tests) measures nothing and\n * counts as glued. */\nlet detectedGluedPreBreak: boolean | null = null;\nfunction detectGluedPreBreak(): boolean {\n if (detectedGluedPreBreak !== null) return detectedGluedPreBreak;\n // The fixture carries its own fixed geometry (the behavior it probes\n // is font-independent): `row` px per line, one row of padding-bottom,\n // 2 columns of 10 characters.\n const row = 20;\n const fixture = document.createElement(\"div\");\n fixture.style.cssText =\n \"position:absolute;left:-9999px;visibility:hidden;columns:2;column-gap:0;\" +\n `column-fill:balance;width:200px;font:10px/${row}px monospace;orphans:1;widows:1`;\n fixture.innerHTML =\n `<div style=\"margin:0;padding:0 0 ${row}px 0\">aaaaaa aaaaaa aaaaaa</div>` +\n '<div style=\"margin:0\"><span>bbbbbb</span> bbbbbb</div>';\n document.body.appendChild(fixture);\n const fixtureTop = fixture.getBoundingClientRect().top;\n const probe = fixture.querySelector(\"span\")!.getBoundingClientRect();\n fixture.remove();\n // Glued: the second paragraph starts at the column top (offset 0);\n // sliced: the spilled pad pushes it a full row down. Split the\n // difference for sub-pixel robustness.\n detectedGluedPreBreak = !(probe.width > 0 && probe.top - fixtureTop >= row / 2);\n return detectedGluedPreBreak;\n}\n\n/**\n * Predict a multicol TEXT LEAF's fragmentation — the multicol analogue\n * of `wrapLines`, sharing the engine's wrap and fill code so a\n * prediction can never drift from the layout. Returns each line with\n * its column and its TIGHT top row within the column. `restrictingHeight`\n * (the content-box height in rows, e.g. read from a rendered element)\n * reproduces any final layout — sequential fill into the final height\n * IS the layout, whatever fill mode produced it; without it, lines\n * balance into `columnCount` columns.\n */\nexport function multicolLines(\n text: string,\n options: {\n columnWidth: number;\n columnCount: number;\n tracking?: number;\n lineGap?: number;\n restrictingHeight?: number;\n /** `text-indent` charged to the first line (cells). */\n firstLineIndent?: number;\n },\n): { text: string; column: number; top: number }[] {\n const { columnWidth, columnCount, tracking = 0, lineGap = 0, restrictingHeight } = options;\n const advances = tracking > 0 ? Array.from(text, () => 1 + tracking) : undefined;\n const spans = wrapLineSpans(text, Math.max(1, columnWidth - tracking), {\n advances,\n tracking,\n firstLineIndent: options.firstLineIndent,\n });\n const units = lineUnits(spans.map(() => 1 + lineGap));\n const height =\n restrictingHeight ??\n minimalHeight(1, Math.max(1, spans.length * (1 + lineGap) - lineGap), (limit) => {\n return fillLineColumns(units, lineGap, limit).columns <= columnCount;\n });\n const filled = fillLineColumns(units, lineGap, height);\n return spans.map((span, i) => ({\n text: text.slice(span.start, span.end),\n column: filled.column[i]!,\n top: filled.top[i]!,\n }));\n}\n\n/** Column rules for a multicol leaf or paragraph-flow container: one\n * band per gap per SEGMENT (a spanless geometry paints one full-height\n * segment), visibility per the side columns' occupancy. */\nexport function multicolLeafRuleRuns(\n node: LayoutNode,\n geometry: MulticolLeafGeometry,\n border: Insets,\n padding: Insets,\n): void {\n const style = node.style;\n if (!style.ruleX) return;\n const contentWidth =\n geometry.columnCount * geometry.columnWidth + (geometry.columnCount - 1) * geometry.gap;\n const extents = geometry.ruleSegments ?? [\n { start: 0, end: geometry.totalRows, columns: geometry.columnsUsed },\n ];\n const vertical: RuleSegment[] = [];\n for (const extent of extents) {\n const occupied = Math.min(extent.columns, geometry.columnCount);\n for (let g = 0; g < geometry.columnCount - 1; g++) {\n if (!ruleVisible(style.ruleVisibilityItems, g < occupied, g + 1 < occupied)) continue;\n vertical.push({\n bandStart: (g + 1) * geometry.columnWidth + g * geometry.gap,\n bandSize: geometry.gap,\n start: extent.start,\n end: extent.end,\n });\n }\n }\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(style.glyphSet),\n ruleX: style.ruleX,\n ruleY: null,\n vertical: insetSegments(vertical, style.ruleInset),\n horizontal: [],\n contentWidth,\n contentHeight: geometry.totalRows,\n border,\n borderStyle: style.borderStyle,\n borderColor: style.borderColor,\n padding,\n });\n}\n\ninterface MulticolUnit {\n node: LayoutNode;\n margin: NullableInsets;\n breakBefore: boolean;\n}\n\n/** A chrome-less text-leaf child, eligible to fragment at line\n * granularity in a paragraph-flow container (specs/multicol.md\n * \"Fragmenting text-leaf children\"): static block, childless text, no\n * border/padding/background/sizing/span, normal white-space, and the\n * container's own line gap (the native box shares the container's\n * inherited line-height and trailing-leading extension). */\nfunction isFragmentableLeaf(child: LayoutNode, container: CellStyle): boolean {\n const style = child.style;\n const insets = style.padding;\n return (\n child.text !== \"\" &&\n child.children.length === 0 &&\n style.display === \"block\" &&\n style.position === \"static\" &&\n !style.columnSpan &&\n style.whiteSpace === \"normal\" &&\n style.lineGap === container.lineGap &&\n style.border.top === 0 &&\n style.border.right === 0 &&\n style.border.bottom === 0 &&\n style.border.left === 0 &&\n insets.top === 0 &&\n insets.right === 0 &&\n insets.bottom === 0 &&\n insets.left === 0 &&\n style.backgroundColor === undefined &&\n !style.backgroundClear &&\n style.overflow.x === \"visible\" &&\n style.overflow.y === \"visible\" &&\n (style.width === undefined || style.width.kind === \"auto\") &&\n (style.height === undefined || style.height.kind === \"auto\") &&\n (style.minWidth === \"auto\" || style.minWidth === 0 || style.minWidth === undefined) &&\n (style.minHeight === \"auto\" || style.minHeight === 0 || style.minHeight === undefined) &&\n style.maxWidth === undefined &&\n style.maxHeight === undefined\n );\n}\n\n/**\n * Paragraph flow (specs/multicol.md \"Fragmenting text-leaf children\"):\n * every in-flow child is a chrome-less text leaf, so children fragment\n * at line granularity like the container's own direct text. One unit\n * stream drives the fill — each child's wrapped lines as full line\n * boxes, collapsed margins between children, a break truncating any\n * margin it lands in, the column end trimming the trailing leading\n * (tight model). Children keep their per-line maps\n * (`multicolGeometry`, container-content coordinates) and stay IN FLOW\n * in the browser (`multicolFlow`); the container gets a spanless\n * geometry for its rules, height fold, and native column vars.\n * Returns content height (rows used).\n */\nfunction layoutMulticolFlow(\n node: LayoutNode,\n inFlow: LayoutNode[],\n innerWidth: number,\n restriction: number | undefined,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n const gap = resolveGap(style, \"x\", innerWidth);\n const columns = resolveLeafColumns(style, innerWidth, gap);\n padding.right += columns.leftover;\n const lineGap = style.lineGap;\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n const contentWidth = innerWidth - columns.leftover;\n\n // Split the flow into segments at in-flow spanners.\n const segments: LayoutNode[][] = [[]];\n const spannerAfter: (LayoutNode | undefined)[] = [];\n for (const child of inFlow) {\n if (child.style.columnSpan) {\n spannerAfter[segments.length - 1] = child;\n segments.push([]);\n } else {\n segments[segments.length - 1]!.push(child);\n }\n }\n const hasSpanners = segments.length > 1;\n // With spanners the native balancer is trusted, and the companion\n // rewrites inter-paragraph gaps as padding-bottom on the preceding\n // paragraph (margins derail it — see the spec), glued to its last\n // line. No detection needed HERE: the dispatch gate keeps non-glue\n // (WebKit) spanner flow margin-less, and with every gap 0 the two\n // modes are identical. Spanless flow keeps real native margins under\n // a forced height, where breaks truncate them.\n const preBreakMode: PreBreakMode = hasSpanners ? \"glue\" : \"truncate\";\n\n const ruleSegments: { start: number; end: number; columns: number }[] = [];\n let segTop = 0;\n let columnsUsed = 0;\n for (let seg = 0; seg < segments.length; seg++) {\n const paragraphs = segments[seg]!;\n // A segment's last bottom margin: the companion zeroes native\n // paragraph bottoms, so it survives by transfer into the following\n // spanner's top margin — a SUM, per css-multicol §6.1 (spanner\n // margins never collapse with column content).\n let trailingBottom = 0;\n if (paragraphs.length > 0) {\n const children = paragraphs.map((child) => ({\n node: child,\n spans: leafLineSpans(child, Math.max(1, columns.width - child.style.tracking)),\n margin: resolveMargin(child.style.margin, columns.width),\n pre: 0,\n post: 0,\n }));\n const units: FillUnit[] = [];\n let prevBottom: number | null = null;\n let prevChild: (typeof children)[number] | null = null;\n let pendingBreak = false;\n for (const child of children) {\n const { node, spans, margin } = child;\n const gap =\n prevBottom === null ? (margin.top ?? 0) : collapseMargins(prevBottom, margin.top ?? 0);\n // Glue mode rides each inter-paragraph gap as the PRECEDING\n // child's padding-bottom (its last unit's glued `post`); the\n // segment-leading gap, which no break can precede, stays the\n // first child's own padding-top. Truncate mode keeps every gap\n // as the following child's margin (`pre`).\n let pre = gap;\n if (preBreakMode === \"glue\" && prevChild !== null) {\n pre = 0;\n prevChild.post = gap;\n units[units.length - 1]!.post = gap;\n } else {\n child.pre = gap;\n }\n const forced = pendingBreak || node.style.breakBeforeColumn;\n if (node.style.breakInsideAvoid && spans.length > 0) {\n // The whole child is one unbreakable unit (probed: engines\n // keep it whole, or split from a fresh column when too tall).\n units.push({\n rows: spans.length * (1 + lineGap),\n pre,\n post: 0,\n forced,\n lines: spans.length,\n });\n } else {\n for (let s = 0; s < spans.length; s++) {\n units.push({\n rows: 1 + lineGap,\n pre: s > 0 ? 0 : pre,\n post: 0,\n forced: s === 0 && forced,\n lines: 1,\n });\n }\n }\n if (spans.length > 0) {\n prevBottom = margin.bottom ?? 0;\n prevChild = child;\n }\n pendingBreak = node.style.breakAfterColumn;\n }\n trailingBottom = prevBottom ?? 0;\n\n let height: number;\n if (style.columnFill === \"auto\" && restriction !== undefined) {\n height = Math.max(1, restriction);\n } else {\n const balanced = minimalHeight(\n 1,\n Math.max(\n 1,\n fillLineColumns(units, lineGap, Number.POSITIVE_INFINITY, preBreakMode).maxUsed,\n ),\n (limit) => fillLineColumns(units, lineGap, limit, preBreakMode).columns <= columns.count,\n );\n height =\n restriction !== undefined ? Math.max(1, Math.min(balanced, restriction)) : balanced;\n }\n const filled = fillLineColumns(units, lineGap, height, preBreakMode);\n\n for (let c = 0, line = 0; c < children.length; c++) {\n const { node: child, spans, margin, pre, post } = children[c]!;\n const lineY: number[] = [];\n const lineX: number[] = [];\n for (let s = 0; s < spans.length; s++, line++) {\n lineY.push(segTop + filled.top[line]!);\n lineX.push(filled.column[line]! * (columns.width + gap));\n }\n delete child.decorationRuns;\n child.multicolGeometry = {\n spans,\n lineY,\n textY: lineY,\n lineX,\n totalRows: segTop + filled.maxUsed,\n columnCount: columns.count,\n columnWidth: columns.width,\n gap,\n columnsUsed: filled.columns,\n };\n // Spanner containers: the companion reinterprets the vertical\n // gaps as padding (engine-collapsed, so native sibling\n // collapsing can't disagree) — the segment-leading gap as this\n // child's padding-top, each inter-paragraph gap as the\n // PRECEDING child's padding-bottom — see the\n // [data-mw-multicol-balance] child rule.\n child.multicolFlow = hasSpanners\n ? { top: pre, right: margin.right, bottom: post, left: margin.left }\n : margin;\n child.localRect = { x: originX, y: originY, width: contentWidth, height: filled.maxUsed };\n child.resolvedPadding = { top: 0, right: 0, bottom: 0, left: 0 };\n }\n if (units.length > 0) {\n ruleSegments.push({ start: segTop, end: segTop + filled.maxUsed, columns: filled.columns });\n columnsUsed = Math.max(columnsUsed, filled.columns);\n // The browser stacks a non-final segment's columns as FULL line\n // boxes — its trailing leading stays before the spanner.\n segTop += filled.maxUsed + (seg < segments.length - 1 ? lineGap : 0);\n }\n }\n const spanner = spannerAfter[seg];\n if (spanner) {\n // In-flow spanner (css-multicol §6.1, probed): the columns' full\n // extent (the folded content width, so it aligns with the tracks),\n // margins never collapsing with column content, the native\n // balancer handling the segments around it.\n const margin = resolveMargin(spanner.style.margin, contentWidth);\n const marginX = (margin.left ?? 0) + (margin.right ?? 0);\n layoutNode(spanner, Math.max(0, contentWidth - marginX), undefined, 0, 0, \"fill\", cache);\n const cross = blockCrossOffset(margin, contentWidth, spanner.localRect.width);\n const marginTop = (margin.top ?? 0) + trailingBottom;\n segTop += marginTop;\n spanner.localRect = { ...spanner.localRect, x: originX + cross, y: originY + segTop };\n spanner.multicolFlowSpan = {\n top: marginTop,\n right: 0,\n bottom: margin.bottom ?? 0,\n left: cross,\n };\n segTop += spanner.localRect.height + (margin.bottom ?? 0);\n }\n }\n const totalRows = segTop;\n\n for (const child of node.children) {\n if (!isOutOfFlow(child.style)) continue;\n const margin = resolveMargin(child.style.margin, innerWidth);\n child.staticSlot = {\n kind: \"block\",\n x: originX + (margin.left ?? 0),\n y: originY + (margin.top ?? 0),\n };\n }\n // Spanless container geometry: drives the column rules and the\n // vertical-slack fold in layoutNode, and the native column vars.\n node.multicolGeometry = {\n spans: [],\n lineY: [],\n textY: [],\n lineX: [],\n totalRows,\n columnCount: columns.count,\n columnWidth: columns.width,\n gap,\n columnsUsed,\n ...(hasSpanners ? { ruleSegments, nativeBalance: true } : {}),\n };\n return totalRows;\n}\n\n/**\n * Lay out a multicol container's element children (specs/multicol.md\n * \"Element children\"): children are atomic (never split across columns),\n * measured at the column width, and packed sequentially — a new column\n * when the next child would exceed the fill height or at a forced break.\n * Adjacent margins collapse within a column; a margin at a column break\n * truncates at the column top. `column-span: all` children split the\n * flow into stacked segments that each balance independently. Returns\n * content height (rows used).\n */\nexport function layoutMulticol(\n node: LayoutNode,\n innerWidth: number,\n definiteInnerHeight: number | undefined,\n maxInnerHeight: number | undefined,\n border: Insets,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n // Only a definite height makes `column-fill: auto` pad segments (and\n // rules) to the full fill; max-height merely restricts.\n const restriction = restrictingHeight(definiteInnerHeight, maxInnerHeight);\n // Paragraph flow: every in-flow child a chrome-less text leaf (or a\n // spanner) → text fragments at line granularity instead of\n // distributing atomically. With spanners the native balancer handles\n // the segments, which the probes pin down for unrestricted heights\n // and `column-fill: balance`; paragraph margins ride along as\n // companion-written padding glued to the preceding paragraph. Both\n // require a browser whose balancer the engine can predict. WebKit\n // slice-spills padding at breaks (so margins there fall back to\n // atomic) and balances segments in INK-HEIGHT sub-pixels — the\n // fractional height corrupts the ORIGIN of whatever segment follows,\n // flipping its distribution (probed live) — so WebKit flow also\n // requires all paragraphs in ONE segment (spanners only at the\n // edges), whose origin is engine-quantized boxes alone.\n const inFlow = node.children.filter((child) => !isOutOfFlow(child.style));\n const paragraphs = inFlow.filter((child) => !child.style.columnSpan);\n const paragraphSegments = inFlow.reduce(\n (count, child, i) =>\n !child.style.columnSpan && (i === 0 || inFlow[i - 1]!.style.columnSpan) ? count + 1 : count,\n 0,\n );\n if (\n paragraphs.length > 0 &&\n paragraphs.every((child) => isFragmentableLeaf(child, style)) &&\n (paragraphs.length === inFlow.length ||\n (style.columnFill === \"balance\" &&\n restriction === undefined &&\n (detectGluedPreBreak() ||\n (paragraphSegments <= 1 &&\n paragraphs.every(\n (child) =>\n (child.style.margin.top === 0 || child.style.margin.top === null) &&\n (child.style.margin.bottom === 0 || child.style.margin.bottom === null),\n )))))\n ) {\n return layoutMulticolFlow(node, inFlow, innerWidth, restriction, border, padding, cache);\n }\n const gap = resolveGap(style, \"x\", innerWidth);\n const widths = resolveColumnTracks(style, innerWidth, gap);\n const count = widths.length;\n const xOffsets: number[] = [];\n {\n let x = 0;\n for (const w of widths) {\n xOffsets.push(x);\n x += w + gap;\n }\n }\n // Overflow columns (css-multicol §7.2) continue past the last track at\n // its width.\n const columnX = (c: number): number =>\n c < count ? xOffsets[c]! : xOffsets[count - 1]! + (c - count + 1) * (widths[count - 1]! + gap);\n const columnWidthAt = (c: number): number => widths[Math.min(c, count - 1)]!;\n // Children measure at the NARROWEST track so a remainder column never\n // overflows its fill height; placement re-lays out at the real width.\n const measureWidth = widths[count - 1]!;\n const originX = border.left + padding.left;\n const originY = border.top + padding.top;\n\n const vertical: RuleSegment[] = [];\n let y = 0;\n let segment: MulticolUnit[] = [];\n let pendingSlots: { child: LayoutNode; margin: NullableInsets; index: number }[] = [];\n let pendingBreak = false;\n\n /** Greedy sequential pack of the segment at `limit`; `place` also\n * writes child rects and resolves out-of-flow static slots at their\n * column-flow positions. Returns columns used and the tallest column. */\n const pack = (limit: number, place: boolean): { columns: number; maxUsed: number } => {\n let c = 0;\n let used = 0;\n let prevBottom: number | null = null;\n let maxUsed = 0;\n // Static position of an out-of-flow child between two units: the\n // current column-flow position, its own top margin collapsing like a\n // sibling's (specs/positioning.md).\n const resolveSlots = (index: number): void => {\n if (!place) return;\n for (const pending of pendingSlots) {\n if (pending.index !== index) continue;\n const lead =\n prevBottom === null\n ? (pending.margin.top ?? 0)\n : collapseMargins(prevBottom, pending.margin.top ?? 0);\n pending.child.staticSlot = {\n kind: \"block\",\n x: originX + columnX(c) + (pending.margin.left ?? 0),\n y: originY + y + used + lead,\n };\n }\n };\n for (let i = 0; i < segment.length; i++) {\n const unit = segment[i]!;\n resolveSlots(i);\n let joint =\n prevBottom === null\n ? i === 0\n ? (unit.margin.top ?? 0)\n : 0\n : collapseMargins(prevBottom, unit.margin.top ?? 0);\n const height = unit.node.localRect.height;\n if (prevBottom !== null && (unit.breakBefore || used + joint + height > limit)) {\n c += 1;\n used = 0;\n prevBottom = null;\n joint = 0;\n }\n if (place) {\n const child = unit.node;\n const colWidth = columnWidthAt(c);\n if (colWidth !== measureWidth) {\n const marginX = (unit.margin.left ?? 0) + (unit.margin.right ?? 0);\n layoutNode(\n child,\n Math.max(0, colWidth - marginX),\n definiteInnerHeight,\n 0,\n 0,\n \"fill\",\n cache,\n );\n }\n child.localRect = {\n ...child.localRect,\n x: originX + columnX(c) + blockCrossOffset(unit.margin, colWidth, child.localRect.width),\n y: originY + y + used + joint,\n };\n }\n used += joint + unit.node.localRect.height;\n maxUsed = Math.max(maxUsed, used);\n prevBottom = unit.margin.bottom ?? 0;\n }\n resolveSlots(segment.length);\n return { columns: c + 1, maxUsed };\n };\n\n const flushSegment = (): void => {\n if (segment.length === 0) {\n // Out-of-flow children in an empty segment sit at its start.\n for (const pending of pendingSlots) {\n pending.child.staticSlot = {\n kind: \"block\",\n x: originX + (pending.margin.left ?? 0),\n y: originY + y + (pending.margin.top ?? 0),\n };\n }\n pendingSlots = [];\n return;\n }\n const availableH = restriction === undefined ? undefined : Math.max(1, restriction - y);\n const fillsToHeight = style.columnFill === \"auto\" && availableH !== undefined;\n let height: number;\n if (fillsToHeight) {\n height = availableH!;\n } else {\n // Minimal height needing at most `count` columns; forced breaks and\n // margin collapsing are inside `pack`, so the search runs on it.\n const balanced = minimalHeight(1, pack(Number.POSITIVE_INFINITY, false).maxUsed, (limit) => {\n return pack(limit, false).columns <= count;\n });\n height = availableH !== undefined ? Math.min(balanced, availableH) : balanced;\n }\n const packed = pack(height, true);\n // A DEFINITE-height sequential fill keeps its column boxes (and\n // rules) at the full fill height; balanced and max-height-restricted\n // segments are exactly as tall as their tallest column. A lone child\n // taller than the fill height still grows the segment (monolithic\n // overflow).\n const segmentRows =\n fillsToHeight && definiteInnerHeight !== undefined\n ? Math.max(packed.maxUsed, height)\n : packed.maxUsed;\n if (style.ruleX) {\n for (let g = 0; g < count - 1; g++) {\n const columnsFilled = Math.min(packed.columns, count);\n if (!ruleVisible(style.ruleVisibilityItems, g < columnsFilled, g + 1 < columnsFilled))\n continue;\n vertical.push({\n bandStart: xOffsets[g]! + widths[g]!,\n bandSize: gap,\n start: y,\n end: y + segmentRows,\n });\n }\n }\n y += segmentRows;\n segment = [];\n pendingSlots = [];\n };\n\n for (const child of node.children) {\n if (isOutOfFlow(child.style)) {\n // Deferred: the placement pack resolves the static slot at the\n // column-flow position the box would have occupied.\n pendingSlots.push({\n child,\n margin: resolveMargin(child.style.margin, innerWidth),\n index: segment.length,\n });\n continue;\n }\n if (child.style.columnSpan) {\n // Spanner (css-multicol §6.1): full content width, stacked between\n // segments; its margins don't collapse with column content\n // (specs/multicol.md deviation 5).\n flushSegment();\n pendingBreak = false;\n const margin = resolveMargin(child.style.margin, innerWidth);\n const marginX = (margin.left ?? 0) + (margin.right ?? 0);\n layoutNode(\n child,\n Math.max(0, innerWidth - marginX),\n definiteInnerHeight,\n 0,\n 0,\n \"fill\",\n cache,\n );\n y += margin.top ?? 0;\n child.localRect = {\n ...child.localRect,\n x: originX + blockCrossOffset(margin, innerWidth, child.localRect.width),\n y: originY + y,\n };\n y += child.localRect.height + (margin.bottom ?? 0);\n continue;\n }\n const columnMargin = resolveMargin(child.style.margin, measureWidth);\n const marginX = (columnMargin.left ?? 0) + (columnMargin.right ?? 0);\n layoutNode(\n child,\n Math.max(0, measureWidth - marginX),\n definiteInnerHeight,\n 0,\n 0,\n \"fill\",\n cache,\n );\n segment.push({\n node: child,\n margin: columnMargin,\n breakBefore: pendingBreak || child.style.breakBeforeColumn,\n });\n pendingBreak = child.style.breakAfterColumn;\n }\n flushSegment();\n\n if (style.ruleX && vertical.length > 0) {\n node.decorationRuns = collectGapRuleRuns({\n glyphs: glyphSetFor(style.glyphSet),\n ruleX: style.ruleX,\n ruleY: null,\n vertical: insetSegments(vertical, style.ruleInset),\n horizontal: [],\n contentWidth: innerWidth,\n contentHeight: y,\n border,\n borderStyle: style.borderStyle,\n borderColor: style.borderColor,\n padding,\n });\n }\n return y;\n}\n","import { junctionGlyph, lineGlyph } from \"./borders.ts\";\nimport { scrollGutter } from \"./types.ts\";\nimport { glyphSetFor } from \"./glyphs.ts\";\nimport type { BorderGlyphSet } from \"./glyphs.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 scrollGutter(style).right;\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 glyphSetFor(node.style.glyphSet),\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 set?: BorderGlyphSet,\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\", set);\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\", set);\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(\n style,\n up !== null,\n down !== null,\n left !== null,\n right !== null,\n set,\n );\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 {\n layoutMulticol,\n multicolIntrinsicInnerWidth,\n multicolLeafGeometry,\n multicolLeafRuleRuns,\n resolveLeafColumns,\n restrictingHeight,\n} from \"./multicol.ts\";\nimport { layoutTable, tableIntrinsicInnerWidths, tableUsedOuterWidth } from \"./table.ts\";\nimport type { TableData } from \"./table.ts\";\nimport { walkPositioned } from \"./positioning.ts\";\nimport { inlineBoxesOf, scrollGutter, scrollGutterBands, scrollsAxis } from \"./types.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport type {\n CellLength,\n CellStyle,\n Insets,\n LayoutNode,\n MulticolLeafGeometry,\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 // The host keeps its in-flow height; the grid covers the INK — visible\n // overflow paints past the host like CSS paints it past any box\n // (specs/cell-model.md \"Overflow\"). A clipping axis keeps the box: the\n // root leaf under `truncate` (specs/host-leaf.md) cuts at its width.\n const height = root.localRect.height;\n const ink = contentExtent(root);\n const { overflow } = root.style;\n if (overflow.x === \"visible\") root.localRect.width = Math.max(root.localRect.width, ink.x);\n if (overflow.y === \"visible\") root.localRect.height = Math.max(height, ink.y);\n return { 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?: {\n width?: number | undefined;\n height?: number | undefined;\n /** Second-pass auto-gutter reservation (see the scrollRange block):\n * an overflowing `auto` axis re-lays out once WITH its gutter and\n * keeps it regardless of the new extent — no oscillation. */\n gutter?: { right: boolean; bottom: boolean };\n },\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, multicol) repopulates them.\n delete node.decorationRuns;\n delete node.multicolGeometry;\n delete node.multicolFlow;\n delete node.multicolFlowSpan;\n delete node.textExtent;\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 gutter = scrollGutter(style);\n const bands = scrollGutterBands(style);\n if (forced?.gutter?.right) gutter.right = bands.right;\n if (forced?.gutter?.bottom) gutter.bottom = bands.bottom;\n const padding: Insets = {\n top: resolveLength(style.padding.top, availableWidth),\n right: resolveLength(style.padding.right, availableWidth) + gutter.right,\n bottom: resolveLength(style.padding.bottom, availableWidth) + gutter.bottom,\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\n // `height` and `max-height` both RESTRICT multicol column heights\n // (css-multicol §7), unlike other displays where max-height only clamps\n // the final rect and overflow spills.\n const maxInnerHeight =\n maxHeight === undefined\n ? undefined\n : Math.max(\n 0,\n maxHeight - style.border.top - style.border.bottom - padding.top - padding.bottom,\n );\n\n // Content layout against an inner height and whether it is definite.\n // Flex and grid containers size their content against a definite\n // height, and a `max-height` on an indefinite one caps the USED size,\n // not just the box (css-flexbox §9.2 / §9.4, css-grid §11.1): content\n // past the cap re-flexes against it — a scroll-container item\n // (automatic minimum 0) shrinks and scrolls.\n const isLeaf = laysOutAsTextLeaf(node);\n const layoutContent = (innerHeight: number, definite: boolean): number => {\n const definiteInner = definite && Number.isFinite(innerHeight) ? innerHeight : undefined;\n if (isLeaf) {\n return layoutTextLeaf(\n node,\n inner.width,\n innerHeight,\n definiteInner,\n maxInnerHeight,\n padding,\n cache,\n );\n }\n if (style.display === \"flex\" && style.flexDirection === \"row\") {\n return layoutFlexRow(\n node,\n inner.width,\n innerHeight,\n definiteInner,\n style.border,\n padding,\n cache,\n );\n }\n if (style.display === \"flex\") {\n return layoutFlexColumn(\n node,\n inner.width,\n innerHeight,\n definite,\n style.border,\n padding,\n cache,\n );\n }\n if (style.display === \"grid\") {\n return layoutGrid(node, inner.width, innerHeight, style.border, padding, cache);\n }\n if (style.display === \"table\") {\n return layoutTable(node, inner.width, definiteInner, style.border, padding, cache);\n }\n if (style.display === \"multicol\") {\n return layoutMulticol(\n node,\n inner.width,\n definiteInner,\n maxInnerHeight,\n style.border,\n padding,\n cache,\n );\n }\n return layoutBlock(node, inner.width, definiteInner, style.border, padding, cache);\n };\n let contentHeight = layoutContent(inner.height, heightIsDefinite);\n const capsUsedHeight = !isLeaf && (style.display === \"flex\" || style.display === \"grid\");\n if (capsUsedHeight && !heightIsDefinite && maxHeight !== undefined) {\n // The USED size: max clamps, and a larger min wins over it (CSS).\n const chromeY = style.border.top + style.border.bottom + padding.top + padding.bottom;\n const usedInner = clampSize(contentHeight + chromeY, minHeight, maxHeight) - chromeY;\n if (usedInner < contentHeight) contentHeight = layoutContent(Math.max(0, usedInner), true);\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 // Multicol browser agreement (leaf and paragraph-flow container,\n // specs/multicol.md): fold the FINAL box's vertical slack into the\n // engine-owned bottom padding so the browser's column box is exactly\n // as tall as the engine's fill (its sequential fill then breaks on\n // the same lines), and only then paint the column rules — the fold\n // decides whether they tee into the bottom border.\n // The cast defeats stale narrowing from the `delete` above (the leaf\n // pass re-populates the property behind a call TS doesn't track).\n const multicolGeometry = node.multicolGeometry as MulticolLeafGeometry | undefined;\n if (multicolGeometry) {\n const finalContentHeight =\n finalHeight - style.border.top - style.border.bottom - padding.top - padding.bottom;\n if (finalContentHeight > multicolGeometry.totalRows)\n padding.bottom += finalContentHeight - multicolGeometry.totalRows;\n multicolLeafRuleRuns(node, multicolGeometry, style.border, padding);\n }\n\n node.localRect = { x: parentX, y: parentY, width: outerWidth, height: finalHeight };\n\n // Scroll geometry (specs/scrolling.md): content extent and max\n // offset, from the ENGINE's layout — never native scrollHeight.\n if (scrollsAxis(style.overflow.x) || scrollsAxis(style.overflow.y)) {\n const extent = contentExtent(node);\n const sizeX = Math.max(0, extent.x - style.border.left - padding.left);\n const sizeY = Math.max(0, extent.y - style.border.top - padding.top);\n const contentW = Math.max(\n 0,\n outerWidth - style.border.left - style.border.right - padding.left - padding.right,\n );\n const contentH = Math.max(\n 0,\n finalHeight - style.border.top - style.border.bottom - padding.top - padding.bottom,\n );\n node.scrollRange = {\n sizeX,\n sizeY,\n maxX: scrollsAxis(style.overflow.x) ? Math.max(0, sizeX - contentW) : 0,\n maxY: scrollsAxis(style.overflow.y) ? Math.max(0, sizeY - contentH) : 0,\n };\n // CSS parity for `auto`: reserve the gutter only when content\n // actually overflows, and keep it even if the narrower re-layout no\n // longer overflows (browsers' own anti-oscillation rule). One axis's\n // gutter can push the OTHER axis into overflow, so the pass repeats\n // while a newly overflowing axis lacks its gutter — gutters only\n // accrue, so at most one more pass.\n if (style.scrollbarWidth !== \"none\") {\n const have = forced?.gutter ?? { right: false, bottom: false };\n const needY = have.right || (style.overflow.y === \"auto\" && node.scrollRange.maxY > 0);\n const needX = have.bottom || (style.overflow.x === \"auto\" && node.scrollRange.maxX > 0);\n if (needY !== have.right || needX !== have.bottom) {\n layoutNode(node, availableWidth, availableHeight, parentX, parentY, widthMode, cache, {\n ...forced,\n gutter: { right: needY, bottom: needX },\n });\n return;\n }\n }\n node.scrollGutterCells = { right: gutter.right, bottom: gutter.bottom };\n } else {\n delete node.scrollRange;\n delete node.scrollGutterCells;\n }\n}\n\n/**\n * Layout for a TEXT LEAF (possibly carrying out-of-flow children), or an\n * empty box. `white-space: nowrap` text never soft-wraps: its height is\n * the hard-line (`<br>`) count, regardless of width. `leading-*` adds\n * `lineGap` empty rows BETWEEN lines only (specs/cell-model.md). Returns\n * content height (rows used); mutates `padding` (=== resolvedPadding)\n * for quantized content alignment and multicol column folding.\n */\nfunction layoutTextLeaf(\n node: LayoutNode,\n innerWidth: number,\n innerHeight: number,\n definiteInnerHeight: number | undefined,\n maxInnerHeight: number | undefined,\n padding: Insets,\n cache: IntrinsicCache,\n): number {\n const style = node.style;\n let contentHeight: number;\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 = inlineBoxesOf(node);\n eachObjectMarker(node.text, (charIndex, boxIndex) => {\n const box = boxes[boxIndex]!;\n layoutNode(box, innerWidth, undefined, 0, 0, \"shrink\", cache);\n node.advances![charIndex] = Math.max(1, box.localRect.width);\n });\n let geometry: { spans: LineSpan[]; lineY: number[]; textY: number[]; totalRows: number };\n let lineX: number[] | undefined;\n if (style.display === \"multicol\") {\n // Direct-text multicol leaf (specs/multicol.md): fragment the\n // wrapped lines into columns, the fill restricted by a definite\n // height or max-height (css-multicol §7). The division remainder\n // folds into the engine-owned right padding so the browser's\n // equal fractional columns start on the engine's whole cells;\n // vertical slack folds after the final height clamp (layoutNode).\n const gap = resolveGap(style, \"x\", innerWidth);\n const columns = resolveLeafColumns(style, innerWidth, gap);\n padding.right += columns.leftover;\n const multicol = multicolLeafGeometry(\n node,\n columns,\n gap,\n restrictingHeight(definiteInnerHeight, maxInnerHeight),\n );\n node.multicolGeometry = multicol;\n geometry = multicol;\n lineX = multicol.lineX;\n } else {\n geometry = leafLineGeometry(node, innerWidth);\n }\n contentHeight = geometry.totalRows;\n node.textExtent = {\n width: geometry.spans.reduce(\n (max, span) =>\n Math.max(max, lineAdvance(span.start, span.end, node.advances, style.tracking)),\n 0,\n ),\n rows: geometry.totalRows,\n };\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, innerWidth, innerHeight, 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:\n style.border.left +\n padding.left +\n (lineX?.[line] ?? 0) +\n 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, innerWidth);\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 return contentHeight;\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/** A single-column text leaf's wrapped lines with their vertical\n * geometry: `lineGap` rows between lines, per-line heights and text\n * drops from leafLineMetrics (multicol leaves fragment through\n * multicolLeafGeometry instead). Marker advances must be resolved. */\nexport function leafLineGeometry(\n node: LayoutNode,\n contentWidth: number,\n): { spans: LineSpan[]; lineY: number[]; textY: number[]; totalRows: number } {\n const spans = leafLineSpans(node, contentWidth);\n const { heights, textOffsets } = leafLineMetrics(node, spans);\n const lineY: number[] = [];\n const textY: number[] = [];\n let y = 0;\n for (let s = 0; s < spans.length; s++) {\n lineY.push(y);\n textY.push(y + textOffsets[s]!);\n y += heights[s]! + (s < spans.length - 1 ? node.style.lineGap : 0);\n }\n return { spans, lineY, textY, totalRows: y };\n}\n\n/** A leaf's line spans: hard `<br>` lines under nowrap/pre, greedy\n * word-wrap at the content width otherwise. */\nexport function leafLineSpans(node: LayoutNode, contentWidth: number): LineSpan[] {\n return node.style.whiteSpace !== \"normal\"\n ? hardLineSpans(node.text)\n : wrapLineSpans(node.text, contentWidth, {\n advances: node.advances,\n tracking: node.style.tracking,\n firstLineIndent: node.style.textIndent,\n });\n}\n\n/**\n * Per-line height and text drop for a leaf's wrapped lines. 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). `vertical-align:\n * bottom` on a box drops the line's TEXT to the box's last row\n * (grid-exact in every engine, probed); the largest such box wins.\n * top/middle/baseline behave as top (cell-model deviation — middle and\n * baseline are off-grid). Requires the leaf's inline boxes to be laid\n * out already (their rect heights are read here).\n */\nexport function leafLineMetrics(\n node: LayoutNode,\n spans: LineSpan[],\n): { heights: number[]; textOffsets: number[] } {\n const boxes = inlineBoxesOf(node);\n const heights: number[] = [];\n const textOffsets: number[] = [];\n let boxIndex = 0;\n for (const span of spans) {\n let height = 1;\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 heights.push(height);\n textOffsets.push(Math.min(textOffset, height - 1));\n }\n return { heights, textOffsets };\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 crossOffset = blockCrossOffset(childMargin, innerWidth, child.localRect.width);\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/** Horizontal placement of a box inside its block-flow slot: `auto`\n * margins center or end-align, fixed margins offset (CSS block flow;\n * multicol columns use the same rule). */\nexport function blockCrossOffset(\n margin: NullableInsets,\n slotWidth: number,\n boxWidth: number,\n): number {\n const available = slotWidth - boxWidth;\n if (margin.left === null && margin.right === null) return Math.floor(available / 2);\n if (margin.left === null) return available - (margin.right ?? 0);\n return margin.left;\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 */\nexport function 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\n/** How far a box's content reaches past its border-box origin, in\n * cells: children's own scrollable extents plus its text's extent —\n * CSS scrollable overflow counts descendants' overflow unless a box\n * clips it (`scrollableExtent`). */\nfunction contentExtent(node: LayoutNode): { x: number; y: number } {\n let x = 0;\n let y = 0;\n for (const child of node.children) {\n if (child.style.position === \"fixed\") continue;\n const extent = scrollableExtent(child);\n x = Math.max(x, child.localRect.x + extent.x);\n y = Math.max(y, child.localRect.y + extent.y);\n }\n if (node.textExtent) {\n const { border } = node.style;\n const padding = node.resolvedPadding;\n x = Math.max(x, border.left + padding.left + node.textExtent.width);\n y = Math.max(y, border.top + padding.top + node.textExtent.rows);\n }\n return { x, y };\n}\n\n/** A box's contribution to its parent's scrollable overflow: its own\n * box, grown by its content's overflow on each axis it leaves\n * visible. */\nfunction scrollableExtent(node: LayoutNode): { x: number; y: number } {\n const { width, height } = node.localRect;\n const clipsX = node.style.overflow.x !== \"visible\";\n const clipsY = node.style.overflow.y !== \"visible\";\n if (clipsX && clipsY) return { x: width, y: height };\n const content = contentExtent(node);\n return {\n x: clipsX ? width : Math.max(width, content.x),\n y: clipsY ? height : Math.max(height, content.y),\n };\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 scrollGutter(style).right\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 scrollGutter(style).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) {\n if (node.style.display === \"multicol\")\n return multicolIntrinsicInnerWidth(node.style, node.intrinsicWidth);\n return node.intrinsicWidth;\n }\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 + widthContribution(c, \"max\", cache), 0) + gap;\n }\n const widest = inFlow.reduce((max, c) => Math.max(max, widthContribution(c, \"max\", cache)), 0);\n if (node.style.display === \"multicol\") return multicolIntrinsicInnerWidth(node.style, widest);\n return widest;\n}\n\n/** A child's outer width contribution to its parent's intrinsic size: its\n * explicit width if fixed (percent behaves as auto, per intrinsic\n * contribution rules), else its min-/max-content outer width; clamped by\n * its own fixed min/max. */\nexport function widthContribution(\n child: LayoutNode,\n kind: \"min\" | \"max\",\n cache: IntrinsicCache,\n): 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 * 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 scrollGutter(style).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 + widthContribution(c, \"min\", cache), 0) + gap;\n }\n return inFlow.reduce((max, c) => Math.max(max, widthContribution(c, \"min\", 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 { glyphSetFor, scrollGlyphs } from \"./glyphs.ts\";\nimport { advanceOf, INLINE_PAD, lineAdvance, OBJECT_REPLACEMENT } from \"./wrap.ts\";\nimport type { LineSpan } from \"./wrap.ts\";\nimport type { LayoutNode, Rect } 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 * The grid covers the layout's ink extent (layoutRoot grows the root\n * to it); ink above or left of the origin has no cells and is dropped.\n */\nexport function renderPlainText(root: LayoutNode): string {\n return renderGrids(root)\n .grid.map((row) => row.join(\"\").trimEnd())\n .join(\"\\n\");\n}\n\n/** Per-cell paint; every field optional so spans only carry what\n * differs from the host's inherited text style. `color` paints the\n * glyph, `backgroundColor` fills the cell (the light DOM's own bg is\n * neutralized in styles.css so the grid owns backgrounds outright). */\nexport interface CellPaint {\n color?: string;\n /** `string | undefined` (not just optional): a bg-clear fill merges\n * an EXPLICIT undefined over the cell to erase the bg beneath. */\n backgroundColor?: string | undefined;\n fontWeight?: string;\n fontStyle?: string;\n textDecorationLine?: string;\n /** Effective opacity (ancestor product, baked by the walk) as a CSS\n * value — the span composites against the page, so translucency\n * blends with what's behind the HOST, never with covered cells.\n * `\"0\"` still paints: the glyphs stay selectable in grid mode. */\n opacity?: string;\n}\n\n/** One row of same-paint runs. Joining every segment's text gives the\n * row at the grid's full width (specs/cell-model.md \"Selection\"): the\n * <pre> is a rectangle of cells, so a drag's highlight sweeps whole\n * rows and a copy is the visible rectangle. */\nexport interface CellSegment extends CellPaint {\n text: string;\n}\n\n/** Row-major cell segments. Each row is `rowSegments(grid[y],\n * paints[y])` — the DOM adapter (paint.ts) uses this, and tests\n * assert paint fields against it. */\nexport function renderCellSegments(root: LayoutNode): CellSegment[][] {\n const { grid, paints } = renderGrids(root);\n return grid.map((row, y) => rowSegments(row, paints[y]!));\n}\n\n/** One rendered row → its same-paint runs. Painted spaces stay in\n * their run (underline spans an inline run's inner spaces; a\n * borderless focus-invert fill is nothing but spaces). */\nfunction rowSegments(row: string[], paints: (CellPaint | undefined)[]): CellSegment[] {\n const segments: CellSegment[] = [];\n for (let x = 0; x < row.length; x++) {\n const paint = paints[x];\n const last = segments[segments.length - 1];\n if (last && samePaint(last, paint)) last.text += row[x]!;\n else segments.push({ text: row[x]!, ...paint });\n }\n return segments;\n}\n\nexport function samePaint(a: CellPaint, b: CellPaint | undefined): boolean {\n return (\n a.color === b?.color &&\n a.backgroundColor === b?.backgroundColor &&\n a.fontWeight === b?.fontWeight &&\n a.fontStyle === b?.fontStyle &&\n a.textDecorationLine === b?.textDecorationLine &&\n a.opacity === b?.opacity\n );\n}\n\n/** Apply a `CellPaint` to a `CSSStyleDeclaration`. Kept in this file\n * alongside samePaint / textPaint so the paint schema has one home. */\nexport function applyCellPaint(paint: CellPaint, style: CSSStyleDeclaration): void {\n if (paint.color !== undefined) style.color = paint.color;\n if (paint.backgroundColor !== undefined) style.backgroundColor = paint.backgroundColor;\n if (paint.fontWeight !== undefined) style.fontWeight = paint.fontWeight;\n if (paint.fontStyle !== undefined) style.fontStyle = paint.fontStyle;\n if (paint.textDecorationLine !== undefined) style.textDecoration = paint.textDecorationLine;\n if (paint.opacity !== undefined) style.opacity = paint.opacity;\n}\n\n/** True when a segment carries no paint — the DOM adapter emits a bare\n * text node for these instead of an empty <span>. */\nexport function isBarePaint(paint: CellPaint): boolean {\n return (\n paint.color === undefined &&\n paint.backgroundColor === undefined &&\n paint.fontWeight === undefined &&\n paint.fontStyle === undefined &&\n paint.textDecorationLine === undefined &&\n paint.opacity === undefined\n );\n}\n\nfunction renderGrids(root: LayoutNode): {\n grid: string[][];\n paints: (CellPaint | undefined)[][];\n} {\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 // Merge paints per field: a later glyph over an earlier fill\n // keeps the fill's fields (bg-fill's backgroundColor survives\n // when text paints its color on top). Same-field overlaps still\n // last-wins.\n const existing = paints[y]![x];\n paints[y]![x] = existing ? { ...existing, ...paint } : paint;\n }\n });\n return { grid, paints };\n}\n\n/** Non-default text styling only, so unstyled runs stay bare.\n * `backgroundColor` rides along for INLINE elements (a leaf's own bg\n * paints via the border-box fill instead). */\nfunction textPaint(source: {\n color: string | undefined;\n backgroundColor?: 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.backgroundColor) paint.backgroundColor = source.backgroundColor;\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(\n node: LayoutNode,\n parentAbsX: number,\n parentAbsY: number,\n put: PutGlyph,\n alpha = 1,\n): 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 // Effective opacity (specs/cell-model.md \"Opacity\"): ancestors\n // multiply (CSS nests, it doesn't inherit) and the value rides on\n // every paint this node produces — including an opacity of 0, whose\n // glyphs must stay in the grid for select=\"grid\" selection.\n const alphaPaint = (paint: CellPaint | undefined): CellPaint | undefined =>\n alpha >= 1 ? paint : { ...paint, opacity: String(Math.round(alpha * 1000) / 1000) };\n\n // Fill the border-box with painted spaces so this element's bg\n // wipes ancestor decoration glyphs at these cells; own borders /\n // text / decoration paint after and layer on top. `bg-clear` runs\n // the same fill without a visible color.\n if (style.backgroundColor !== undefined || style.backgroundClear) {\n // bg-clear fills with an EXPLICIT undefined so the merge in put()\n // strips the cell's painted background too — the wipe covers\n // ancestor backgrounds, not just their glyphs.\n const fillPaint: CellPaint | undefined =\n style.backgroundColor !== undefined\n ? alphaPaint({ backgroundColor: style.backgroundColor })\n : { backgroundColor: undefined };\n for (let dy = 0; dy < node.localRect.height; dy++) {\n for (let dx = 0; dx < node.localRect.width; dx++) {\n put(absX + dx, absY + dy, \" \", fillPaint);\n }\n }\n }\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 = alphaPaint(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 = alphaPaint(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 // Overflow (specs/scrolling.md): a clipping/scrolling axis culls the\n // node's CONTENT ink (text and children — own decorations paint\n // unclipped) at the PADDING box, per CSS: padding cells sit blank at\n // the scroll extremes but content flows through them mid-scroll. A\n // reserved gutter cell stays excluded (the bar owns it). Nested\n // containers compose: the wrapped put chains to the parent's.\n const gutter = node.scrollGutterCells;\n const clipsX = style.overflow.x !== \"visible\";\n const clipsY = style.overflow.y !== \"visible\";\n const scrolledX = absX - (node.scroll?.x ?? 0);\n const scrolledY = absY - (node.scroll?.y ?? 0);\n let contentPut = put;\n if (clipsX || clipsY) {\n const x0 = absX + style.border.left;\n const y0 = absY + style.border.top;\n const x1 = absX + node.localRect.width - style.border.right - (gutter?.right ?? 0);\n const y1 = absY + node.localRect.height - style.border.bottom - (gutter?.bottom ?? 0);\n contentPut = (x, y, glyph, paint) => {\n if (clipsX && (x < x0 || x >= x1)) return;\n if (clipsY && (y < y0 || y >= y1)) return;\n put(x, y, 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 leafPaint = alphaPaint(textPaint(style));\n const inlinePaints = node.inlineElements?.map((entry) => alphaPaint(textPaint(entry)));\n forEachLeafCell(\n node,\n scrolledX,\n scrolledY,\n (k, x, y) => {\n const inlineIndex = node.charInline?.[k] ?? -1;\n const entry = inlineIndex >= 0 ? node.inlineElements![inlineIndex] : undefined;\n // INLINE_PAD marks a blank inline-padding cell: no glyph, but\n // its element's background still fills it.\n if (node.text[k] === INLINE_PAD) {\n if (entry?.backgroundColor) {\n contentPut(x, y, \" \", alphaPaint({ backgroundColor: entry.backgroundColor }));\n }\n } else {\n contentPut(x, y, node.text[k]!, entry ? inlinePaints![inlineIndex] : leafPaint);\n }\n },\n (x, y) => contentPut(x, y, \"…\", leafPaint),\n );\n }\n\n for (const child of paintOrderedChildren(node)) {\n walk(child, scrolledX, scrolledY, contentPut, alpha * child.style.opacity);\n }\n\n // Scrollbars last, over content (specs/scrolling.md): every\n // reserved gutter paints track + thumb (full-length when nothing\n // overflows — the `scroll` case; an `auto` gutter exists only with\n // overflow). The shared corner cell of two bars stays blank.\n const range = node.scrollRange;\n if (range && gutter && (gutter.right > 0 || gutter.bottom > 0)) {\n const { track, thumb } = scrollGlyphs(glyphSetFor(style.glyphSet));\n // `scrollbar-color: auto` means the container's own color (its\n // currentColor, like borders) — not the inherited grid default.\n const barPaint = (color: string | undefined): CellPaint | undefined =>\n alphaPaint(color ? { color } : undefined);\n const trackPaint = barPaint(style.scrollbarColor?.track ?? style.color);\n const thumbPaint = barPaint(style.scrollbarColor?.thumb ?? style.color);\n const bars = scrollbarGeometry(node, absX, absY);\n if (bars.y) {\n const { col, row, thick, len } = bars.y;\n const { at, len: thumbLen } = thumbSpan(len, range.sizeY, range.maxY, node.scroll?.y ?? 0);\n for (let dx = 0; dx < thick; dx++) {\n for (let i = 0; i < len; i++) {\n const isThumb = i >= at && i < at + thumbLen;\n put(col + dx, row + i, isThumb ? thumb : track, isThumb ? thumbPaint : trackPaint);\n }\n }\n }\n if (bars.x) {\n const { col, row, thick, len } = bars.x;\n const { at, len: thumbLen } = thumbSpan(len, range.sizeX, range.maxX, node.scroll?.x ?? 0);\n for (let dy = 0; dy < thick; dy++) {\n for (let i = 0; i < len; i++) {\n const isThumb = i >= at && i < at + thumbLen;\n put(col + i, row + dy, isThumb ? thumb : track, isThumb ? thumbPaint : trackPaint);\n }\n }\n }\n }\n}\n\n/** The cells a leaf's text occupies: the per-line placement — line\n * geometry (a multicol leaf's stored fragmentation, else recomputed),\n * first-line indent, alignment, truncation, inline relative shifts,\n * per-character advances — in ONE place, so mapping a cell back to a\n * character (charIndexAtCell) cannot drift from the paint. `absX/absY`\n * is the leaf's border-box origin with its own scroll applied; U+FFFC\n * markers are skipped (their boxes paint themselves). */\nfunction forEachLeafCell(\n node: LayoutNode,\n absX: number,\n absY: number,\n onChar: (index: number, x: number, y: number, advance: number) => void,\n onEllipsis?: (x: number, y: number) => void,\n): void {\n const style = node.style;\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 multicol = node.multicolGeometry;\n const { spans, textY } = multicol ?? leafLineGeometry(node, contentWidth);\n // Alignment and truncation act within one column of a multicol leaf,\n // against the tracked wrap width — the browser's own alignment\n // includes the trailing letter-spacing gap, so the engine ends lines\n // at `width − tracking` to sit under it.\n const alignWidth = multicol ? Math.max(1, multicol.columnWidth - style.tracking) : contentWidth;\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i]!;\n const row = contentY + textY[i]!;\n // First-line indent reduces the usable width and shifts the origin\n // (per CSS, `<br>` doesn't re-indent, so only spans[0] is charged).\n const indent = i === 0 ? style.textIndent : 0;\n const truncated =\n style.whiteSpace !== \"normal\" && style.overflow.x === \"clip\"\n ? truncateSpan(node.text, span, alignWidth - indent, node.advances, style)\n : { end: span.end, ellipsis: false };\n // `text-align: end` offsets each line to the content box's right\n // edge; `center` to floor((W − line) / 2). Whole cells; a line at\n // or over the width stays at start, matching truncation.\n const lineWidth = lineAdvance(span.start, span.end, node.advances, style.tracking);\n const leftover = Math.max(0, alignWidth - indent - lineWidth);\n const alignOffset =\n style.textAlign === \"end\"\n ? leftover\n : style.textAlign === \"center\"\n ? Math.floor(leftover / 2)\n : 0;\n let x = contentX + (multicol?.lineX[i] ?? 0) + alignOffset + indent;\n for (let k = span.start; k < truncated.end; k++) {\n const advance = advanceOf(k, k + 1, node.advances);\n if (node.text[k] !== OBJECT_REPLACEMENT) {\n // Inline relative shifts, whole cells (specs/positioning.md):\n // the over-constrained sides resolve like CSS (top/left win).\n const insets = node.inlineElements?.[node.charInline?.[k] ?? -1]?.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 onChar(k, x + dx, row + dy, advance);\n }\n x += advance;\n }\n if (truncated.ellipsis) onEllipsis?.(x, row);\n }\n}\n\n/** Whether a cell lies on one of a fragmented leaf's line boxes — the\n * hit test for paragraph-flow multicol children, whose `localRect` is\n * the shared container box (specs/multicol.md): each line covers its\n * column's width and the rows down to the next line in that column\n * (its own line box when it is the column's last). */\nexport function leafLineCovers(\n node: LayoutNode,\n absX: number,\n absY: number,\n col: number,\n row: number,\n): boolean {\n const geometry = node.multicolGeometry;\n if (!geometry) return false;\n const style = node.style;\n const padding = node.resolvedPadding;\n const x = col - (absX + style.border.left + padding.left);\n const y = row - (absY + style.border.top + padding.top);\n const { lineX, lineY } = geometry;\n for (let i = 0; i < lineY.length; i++) {\n if (x < lineX[i]! || x >= lineX[i]! + geometry.columnWidth) continue;\n const next = i + 1 < lineY.length && lineX[i + 1] === lineX[i] ? lineY[i + 1]! : undefined;\n const bottom = next ?? lineY[i]! + 1 + style.lineGap;\n if (y >= lineY[i]! && y < bottom) return true;\n }\n return false;\n}\n\n/** The index into `node.text` of the character painted at a cell, or\n * null for a blank cell (specs/semantic-selection.md). `absX/absY` is\n * the leaf's painted border-box origin as hitStack reports it. */\nexport function charIndexAtCell(\n node: LayoutNode,\n absX: number,\n absY: number,\n col: number,\n row: number,\n): number | null {\n let found: number | null = null;\n forEachLeafCell(\n node,\n absX - (node.scroll?.x ?? 0),\n absY - (node.scroll?.y ?? 0),\n (k, x, y, advance) => {\n if (found === null && y === row && col >= x && col < x + advance) found = k;\n },\n );\n return found;\n}\n\n/** The cells a leaf's inline elements cover, one rect per element per\n * row — the span of its characters and pad cells there, an outer\n * element's including its inline descendants' — in run order then row\n * order, elements without a cell left out (specs/focus-navigation.md).\n * `absX/absY` as for charIndexAtCell. */\nexport function inlineElementRects(\n node: LayoutNode,\n absX: number,\n absY: number,\n): { element: Element; rect: Rect }[] {\n const entries = node.inlineElements;\n if (!entries || !node.charInline) return [];\n // Each entry's own index plus the indices of the entries containing\n // it: a character belongs to its innermost element and every ancestor.\n const owners = entries.map((entry, i) =>\n entries.flatMap((outer, j) => (j === i || outer.element.contains(entry.element) ? [j] : [])),\n );\n const rows = entries.map(() => new Map<number, { x0: number; x1: number }>());\n forEachLeafCell(\n node,\n absX - (node.scroll?.x ?? 0),\n absY - (node.scroll?.y ?? 0),\n (k, x, y, advance) => {\n const inner = node.charInline![k] ?? -1;\n if (inner < 0) return;\n for (const i of owners[inner]!) {\n const span = rows[i]!.get(y);\n if (!span) rows[i]!.set(y, { x0: x, x1: x + advance });\n else {\n span.x0 = Math.min(span.x0, x);\n span.x1 = Math.max(span.x1, x + advance);\n }\n }\n },\n );\n return entries.flatMap((entry, i) =>\n [...rows[i]!]\n .sort(([a], [b]) => a - b)\n .map(([y, span]) => ({\n element: entry.element,\n rect: { x: span.x0, y, width: span.x1 - span.x0, height: 1 },\n })),\n );\n}\n\n/** Where a container's bars paint, in absolute cells from its\n * border-box origin (specs/scrolling.md): each bar sits at the inner\n * edge of its reserved band (`scrollbar-inset` moves it inward, the\n * freed cells stay blank), `thick` cells across; its track starts\n * inset from its own edge and ends against the other axis's band, or\n * inset from the far edge when there is none. Shared with thumb\n * dragging (element.ts). */\nexport function scrollbarGeometry(\n node: LayoutNode,\n absX: number,\n absY: number,\n): { y?: Scrollbar; x?: Scrollbar } {\n const gutter = node.scrollGutterCells;\n if (!gutter) return {};\n const { border, scrollbarSize: size, scrollbarInset: inset } = node.style;\n const innerTop = absY + border.top;\n const innerLeft = absX + border.left;\n const innerBottom = absY + node.localRect.height - border.bottom;\n const innerRight = absX + node.localRect.width - border.right;\n // A track ends against the other axis's band when there is one (the\n // corner cell between the bars stays blank), else inset from the edge.\n const bottomEnd = gutter.bottom > 0 ? innerBottom - gutter.bottom : innerBottom - inset.y;\n const rightEnd = gutter.right > 0 ? innerRight - gutter.right : innerRight - inset.x;\n const bars: { y?: Scrollbar; x?: Scrollbar } = {};\n if (gutter.right > 0) {\n bars.y = {\n col: innerRight - gutter.right,\n row: innerTop + inset.y,\n thick: Math.min(size.y, gutter.right),\n len: Math.max(0, bottomEnd - innerTop - inset.y),\n };\n }\n if (gutter.bottom > 0) {\n bars.x = {\n col: innerLeft + inset.x,\n row: innerBottom - gutter.bottom,\n thick: Math.min(size.x, gutter.bottom),\n len: Math.max(0, rightEnd - innerLeft - inset.x),\n };\n }\n return bars;\n}\n\n/** One bar: the cell its track starts at, its thickness across, and\n * its length along its axis. */\nexport interface Scrollbar {\n col: number;\n row: number;\n thick: number;\n len: number;\n}\n\n/** Thumb geometry on a bar `trackLen` cells long: proportional to the\n * visible fraction, but shrunk until every scroll offset gets its own\n * thumb position (`trackLen − max` cells at most, one at least) — so a\n * scrollable bar always shows track, and each step moves the thumb\n * while the track has room. Shared with thumb dragging (element.ts). */\nexport function thumbSpan(\n trackLen: number,\n size: number,\n max: number,\n offset: number,\n): { at: number; len: number } {\n const frac = size > 0 ? Math.min(1, trackLen / size) : 1;\n let len = Math.max(1, Math.round(frac * trackLen));\n if (max > 0) len = Math.max(1, Math.min(len, trackLen - max));\n const at = max > 0 ? Math.round((Math.min(offset, max) / max) * (trackLen - len)) : 0;\n return { at, len };\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 { paintOrderedChildren } from \"./borders.ts\";\nimport { leafLineCovers } from \"./plain-text.ts\";\nimport type { LayoutNode } from \"./types.ts\";\n\n/**\n * Cell hit-testing for the synthesized pointer states\n * (specs/cell-model.md \"Pointer states\"): under select=\"grid\" the\n * light DOM is pointer-events: none, so :hover/:active can never\n * match — the engine derives them from the pointer's cell instead,\n * leaving every event on the grid (selection stays intact).\n */\n\nexport interface HitEntry {\n node: LayoutNode;\n /** The node's PAINTED border-box origin, in absolute cells\n * (ancestor scroll offsets applied). */\n x: number;\n y: number;\n}\n\n/** The nodes under a cell with their painted origins, outermost\n * first: the innermost node whose border-box covers the cell, plus\n * its ancestors — native :hover marks the whole chain, so the\n * synthesized attribute does too. Overlapping siblings resolve to the\n * TOPMOST in paint order (z-index, document-order ties), matching\n * what the grid shows at that cell. */\nexport function hitStack(root: LayoutNode, col: number, row: number): HitEntry[] {\n const stack: HitEntry[] = [];\n let node = root;\n let x = root.localRect.x;\n let y = root.localRect.y;\n for (;;) {\n let hit: LayoutNode | null = null;\n for (const child of paintOrderedChildren(node)) {\n if (child.tableHidden) continue;\n const cx = x + child.localRect.x;\n const cy = y + child.localRect.y;\n // A paragraph-flow multicol child shares the container's box with\n // its siblings; its ink is where its line fragments are.\n const inside = child.multicolFlow\n ? leafLineCovers(child, cx, cy, col, row)\n : col >= cx &&\n col < cx + child.localRect.width &&\n row >= cy &&\n row < cy + child.localRect.height;\n if (inside) hit = child;\n }\n if (!hit) return stack;\n stack.push({ node: hit, x: x + hit.localRect.x, y: y + hit.localRect.y });\n // Descend with the hit's scroll applied: its children paint (and\n // therefore hit) shifted by the offset (specs/scrolling.md).\n x += hit.localRect.x - (hit.scroll?.x ?? 0);\n y += hit.localRect.y - (hit.scroll?.y ?? 0);\n node = hit;\n }\n}\n\n/** Inside an `inert` subtree: absent for user interaction, as natively\n * — no hover, no wheel routing, no thumb drag, no focus, no text\n * selection. */\nexport function isInert(element: Element): boolean {\n // Optional call: layout tests build nodes on bare stub sources.\n return element.closest?.(\"[inert]\") != null;\n}\n\n/** The hit stack's elements — what the synthesized states mark — cut\n * at the first inert one, where native :hover stops too. */\nexport function hitChain(root: LayoutNode, col: number, row: number): Element[] {\n const chain: Element[] = [];\n for (const entry of hitStack(root, col, row)) {\n if (isInert(entry.node.source)) break;\n chain.push(entry.node.source);\n }\n return chain;\n}\n","import { inlineElementRects } from \"./plain-text.ts\";\nimport { isInert } from \"./pointer.ts\";\nimport type { LayoutNode, Rect } from \"./types.ts\";\n\n/**\n * Arrow-key focus navigation (specs/focus-navigation.md): the pure\n * part. From the focused element's painted cells, an arrow moves to\n * the nearest focusable element entirely beyond that edge; the element\n * side (`focus=\"arrows\"`) is plumbing around `nextFocus`.\n */\n\nexport type Direction = \"up\" | \"down\" | \"left\" | \"right\";\n\nexport interface Focusable {\n element: Element;\n rect: Rect;\n}\n\nconst DIRECTIONS: Record<string, Direction> = {\n ArrowUp: \"up\",\n ArrowDown: \"down\",\n ArrowLeft: \"left\",\n ArrowRight: \"right\",\n};\n\n/** The direction an arrow key names; null for any other key. */\nexport function directionOf(key: string): Direction | null {\n return DIRECTIONS[key] ?? null;\n}\n\n/** The candidate to focus for an arrow from `current`: entirely beyond\n * the edge in that direction; one overlapping `current` across the\n * other axis (aligned) before any that does not; then the nearest\n * along the axis; then the smaller cross-axis gap; then the first in\n * `candidates` (document order). null when nothing lies beyond the\n * edge — no wrap. */\nexport function nextFocus(\n direction: Direction,\n current: Rect,\n candidates: Focusable[],\n): Element | null {\n let best: Focusable | null = null;\n let bestKey: Rank | null = null;\n for (const candidate of candidates) {\n const key = rank(direction, current, candidate.rect);\n if (key && (!bestKey || ranksBefore(key, bestKey))) {\n best = candidate;\n bestKey = key;\n }\n }\n return best?.element ?? null;\n}\n\n/** [0 when overlapping across the other axis else 1, axis distance,\n * cross-axis gap] — compared lexicographically. */\ntype Rank = [number, number, number];\n\nfunction ranksBefore(a: Rank, b: Rank): boolean {\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return a[i]! < b[i]!;\n }\n return false;\n}\n\n/** A candidate's rank; null when `rect` is not beyond `current`'s edge. */\nfunction rank(direction: Direction, current: Rect, rect: Rect): Rank | null {\n const vertical = direction === \"up\" || direction === \"down\";\n const [start, end, size] = vertical\n ? ([\"y\", \"x\", \"height\"] as const)\n : ([\"x\", \"y\", \"width\"] as const);\n const currentEnd = current[start] + current[size];\n const rectEnd = rect[start] + rect[size];\n const forward = direction === \"down\" || direction === \"right\";\n const distance = forward ? rect[start] - currentEnd : current[start] - rectEnd;\n if (distance < 0) return null;\n const crossSize = vertical ? \"width\" : \"height\";\n const overlap =\n Math.min(current[end] + current[crossSize], rect[end] + rect[crossSize]) -\n Math.max(current[end], rect[end]);\n return overlap > 0 ? [0, distance, 0] : [1, distance, -overlap];\n}\n\n/** Every focusable element the layout knows, with its painted cells\n * (ancestor scroll offsets applied, as the paint walk descends), in\n * tree order: laid-out boxes and atomic inline boxes at their border\n * boxes, a text leaf's inline elements one rect per line they cover\n * (a wrapped link is reachable from each of its lines). The root\n * itself — the host — is the navigation's container, never a\n * candidate. */\nexport function focusableRects(root: LayoutNode): Focusable[] {\n const out: Focusable[] = [];\n const walk = (node: LayoutNode, parentX: number, parentY: number, isRoot: boolean) => {\n if (node.tableHidden) return;\n const x = parentX + node.localRect.x;\n const y = parentY + node.localRect.y;\n if (!isRoot && isFocusable(node.source)) {\n out.push({\n element: node.source,\n rect: { x, y, width: node.localRect.width, height: node.localRect.height },\n });\n }\n for (const inline of inlineElementRects(node, x, y)) {\n if (isFocusable(inline.element)) out.push(inline);\n }\n const scrollX = node.scroll?.x ?? 0;\n const scrollY = node.scroll?.y ?? 0;\n for (const child of node.children) walk(child, x - scrollX, y - scrollY, false);\n };\n walk(root, 0, 0, true);\n return out;\n}\n\n/** An element's own extent: the union of its rects (a wrapped inline\n * element has one per line); null when it has none. */\nexport function extentOf(rects: Focusable[], element: Element): Rect | null {\n let extent: Rect | null = null;\n for (const { element: candidate, rect } of rects) {\n if (candidate !== element) continue;\n if (!extent) extent = { ...rect };\n else {\n const x1 = Math.max(extent.x + extent.width, rect.x + rect.width);\n const y1 = Math.max(extent.y + extent.height, rect.y + rect.height);\n extent.x = Math.min(extent.x, rect.x);\n extent.y = Math.min(extent.y, rect.y);\n extent.width = x1 - extent.x;\n extent.height = y1 - extent.y;\n }\n }\n return extent;\n}\n\n/** The browser's own answer: a non-negative tabIndex, not disabled, not\n * inert. */\nfunction isFocusable(element: Element): boolean {\n const tabIndex = (element as HTMLElement).tabIndex;\n if (typeof tabIndex !== \"number\" || tabIndex < 0) return false;\n return !element.matches(\":disabled\") && !isInert(element);\n}\n\nconst TEXTUAL_INPUTS = new Set([\"text\", \"search\", \"url\", \"tel\", \"email\", \"password\"]);\n/** Inputs whose arrows mean nothing natively: navigation takes them. */\nconst BUTTON_INPUTS = new Set([\"checkbox\", \"button\", \"submit\", \"reset\", \"image\", \"file\"]);\n\n/** Whether an arrow key pressed on `element` belongs to the control:\n * caret movement in text fields (Left/Right in a single-line input,\n * all four in a textarea or contenteditable), a radio group's own\n * selection, a listbox select's, a value change on a stepped input\n * (number, range, dates, color), and a single select's open picker. */\nexport function arrowIsNative(element: Element, key: string, pickerOpen = false): boolean {\n const tag = element.tagName;\n if (tag === \"TEXTAREA\") return true;\n if (element.closest(\"[contenteditable]:not([contenteditable='false'])\")) return true;\n if (tag === \"INPUT\") {\n const type = (element as HTMLInputElement).type;\n if (type === \"radio\") return true;\n if (TEXTUAL_INPUTS.has(type)) return key === \"ArrowLeft\" || key === \"ArrowRight\";\n return !BUTTON_INPUTS.has(type);\n }\n if (tag === \"SELECT\") {\n const select = element as HTMLSelectElement;\n // The attribute fallback: happy-dom (tests) leaves `size` unset.\n const size = Number(select.size) || Number(select.getAttribute(\"size\")) || 0;\n return select.multiple || size > 1 || pickerOpen;\n }\n return false;\n}\n","import { inlineBoxesOf } from \"./types.ts\";\nimport type { LayoutNode } from \"./types.ts\";\nimport { INLINE_PAD, OBJECT_REPLACEMENT } from \"./wrap.ts\";\n\n/**\n * Character ↔ DOM position mapping over a leaf's `charSource` runs\n * (specs/semantic-selection.md): word boundaries map forward to\n * `setBaseAndExtent` points, and a Range's boundary points map\n * backward to slices of the leaf's layout text.\n */\n\n/** Negative when point `a` precedes point `b` in DOM order, 0 when equal. */\nexport function comparePoints(aNode: Node, aOffset: number, bNode: Node, bOffset: number): number {\n const document = aNode.ownerDocument!;\n const a = document.createRange();\n a.setStart(aNode, aOffset);\n a.collapse(true);\n const b = document.createRange();\n b.setStart(bNode, bOffset);\n b.collapse(true);\n return a.compareBoundaryPoints(a.START_TO_START, b);\n}\n\n/** The index into `leaf.text` of the character at or after a DOM\n * boundary point: a point inside a collapsed whitespace run is that\n * run's space, a point past a node's mapped characters is the next\n * mapped index (or `text.length`), and a point inside an atomic inline\n * box's subtree is the box's U+FFFC marker. */\nexport function charIndexAt(leaf: LayoutNode, container: Node, offset: number): number {\n const boxes = inlineBoxesOf(leaf);\n const boxIndex = boxes.findIndex((box) => box.source.contains(container));\n if (boxIndex >= 0) {\n let marker = -1;\n for (let i = 0; i <= boxIndex; i++) marker = leaf.text.indexOf(OBJECT_REPLACEMENT, marker + 1);\n if (marker >= 0) return marker;\n }\n const runs = leaf.charSource ?? [];\n // Runs are in DOM order: the last one starting at or before the point.\n let low = 0;\n let high = runs.length;\n while (low < high) {\n const mid = (low + high) >> 1;\n const run = runs[mid]!;\n if (comparePoints(run.node, run.offset, container, offset) <= 0) low = mid + 1;\n else high = mid;\n }\n if (low === 0) return 0;\n const run = runs[low - 1]!;\n if (container === run.node && offset < run.offset + run.length) {\n return run.index + (offset - run.offset);\n }\n return run.index + run.length;\n}\n\n/** The DOM position of `leaf.text[index]` (or of the end of the run\n * ending there); null for a character with no source position. */\nexport function positionOf(leaf: LayoutNode, index: number): { node: Text; offset: number } | null {\n const runs = leaf.charSource ?? [];\n let low = 0;\n let high = runs.length;\n while (low < high) {\n const mid = (low + high) >> 1;\n if (runs[mid]!.index <= index) low = mid + 1;\n else high = mid;\n }\n const run = runs[low - 1];\n if (!run) return null;\n const delta = index - run.index;\n return delta <= run.length ? { node: run.node, offset: run.offset + delta } : null;\n}\n\n/* === Selection location ============================================= */\n\nexport interface BoundaryPoints {\n startContainer: Node;\n startOffset: number;\n endContainer: Node;\n endOffset: number;\n}\n\n/** The document Selection's first range as seen through `shadowRoot`\n * (`getComposedRanges` on Firefox/WebKit and standards-path Chromium;\n * `ShadowRoot.getSelection()` as the legacy Chromium fallback —\n * verified 2026-09-01). A selection inside some OTHER shadow root (a\n * custom leaf's transcript) comes back retargeted onto that root's\n * host, which is exactly the light-tree range around the leaf. Any API\n * surprise reads as no selection, never an error. */\nexport function selectionRangeThrough(shadowRoot: ShadowRoot): BoundaryPoints | null {\n try {\n const selection = shadowRoot.ownerDocument.getSelection();\n if (!selection) return null;\n if (selection.getComposedRanges) {\n const ranges = selection.getComposedRanges({ shadowRoots: [shadowRoot] });\n return ranges[0] ?? null;\n }\n const shadowSelection = (\n shadowRoot as { getSelection?: () => Selection | null }\n ).getSelection?.();\n if (!shadowSelection || shadowSelection.rangeCount === 0) return null;\n return shadowSelection.getRangeAt(0);\n } catch {\n return null;\n }\n}\n\n/** Where a selection lives relative to a host: in its shadow `grid`,\n * in its light DOM (both points, the host's own child list included),\n * or anywhere else — including straddling the two. */\nexport type SelectionKind = \"grid\" | \"light\" | \"outside\";\n\nexport function classifySelection(\n host: Element,\n grid: Element,\n range: BoundaryPoints,\n): SelectionKind {\n const { startContainer: start, endContainer: end } = range;\n if (grid.contains(start) && grid.contains(end)) return \"grid\";\n if (host.contains(start) && host.contains(end)) return \"light\";\n return \"outside\";\n}\n\n/* === Copy serialization ============================================== */\n\n/** A required line break count (collapses with neighbors, dropped at\n * the ends) or literal text (a leaf's slice, a table's tab or row\n * newline) — the HTML `innerText` rendered-text items. */\ntype TextItem = { text: string } | { breaks: number };\n\n/** `text/plain` for a light-DOM selection (specs/semantic-selection.md\n * \"Copy serialization\"): every node the range intersects, in tree\n * order, laid out by the `innerText` rules — a `<p>` surrounded by a\n * blank line, any other block-level box by one line break, table cells\n * separated by tabs and rows by newlines — over each leaf's layout\n * text. The browsers' own serializers lose block breaks for the\n * engine's out-of-flow boxes; this restores what they would have\n * produced in flow. */\nexport function serializeSelection(root: LayoutNode, points: BoundaryPoints): string {\n const range = root.source.ownerDocument!.createRange();\n range.setStart(points.startContainer, points.startOffset);\n range.setEnd(points.endContainer, points.endOffset);\n const items: TextItem[] = [];\n collectItems(root, range, items);\n return assemble(items);\n}\n\nfunction collectItems(node: LayoutNode, range: Range, items: TextItem[]): void {\n if (node.tableHidden || !range.intersectsNode(node.source)) return;\n const breaks = requiredBreaks(node);\n if (breaks) items.push({ breaks });\n if (node.style.tableRole === \"row\") {\n collectRow(node, range, items);\n } else if (node.style.display === \"table\") {\n const rows = tableRows(node);\n for (const child of node.children) {\n if (child.style.tableRole === \"row\" || isRowGroup(child)) continue;\n collectItems(child, range, items); // captions\n }\n // Separators only between rows the range reaches, like the\n // browsers' own partial-table copies.\n let emitted = false;\n for (const row of rows) {\n if (!range.intersectsNode(row.source)) continue;\n if (emitted) items.push({ text: \"\\n\" });\n collectItems(row, range, items);\n emitted = true;\n }\n } else {\n if (isTextLeaf(node)) items.push({ text: leafSlice(node, range) });\n for (const child of node.children) {\n if (!child.inlineBox) collectItems(child, range, items);\n }\n }\n if (breaks) items.push({ breaks });\n}\n\nfunction collectRow(row: LayoutNode, range: Range, items: TextItem[]): void {\n let emitted = false;\n for (const cell of row.children) {\n if (cell.style.tableRole !== \"cell\" || cell.tableHidden) continue;\n if (!range.intersectsNode(cell.source)) continue;\n if (emitted) items.push({ text: \"\\t\" });\n collectItems(cell, range, items);\n emitted = true;\n }\n}\n\nfunction isRowGroup(node: LayoutNode): boolean {\n const role = node.style.tableRole;\n return role === \"header-group\" || role === \"row-group\" || role === \"footer-group\";\n}\n\nfunction tableRows(table: LayoutNode): LayoutNode[] {\n const rows: LayoutNode[] = [];\n for (const child of table.children) {\n if (child.style.tableRole === \"row\") rows.push(child);\n else if (isRowGroup(child)) {\n for (const row of child.children) if (row.style.tableRole === \"row\") rows.push(row);\n }\n }\n return rows;\n}\n\n/** `innerText`: a `<p>` gets two required breaks, any other block-level\n * box (a caption included) one; inline boxes and table internals none. */\nfunction requiredBreaks(node: LayoutNode): number {\n if (node.inlineBox) return 0;\n const role = node.style.tableRole;\n if (role === \"row\" || role === \"cell\" || isRowGroup(node)) return 0;\n if (role === \"column\" || role === \"column-group\") return 0;\n return node.source.tagName === \"P\" ? 2 : 1;\n}\n\ninterface Point {\n node: Node;\n offset: number;\n}\n\n/** The DOM extent of a leaf's run — its first mapped character or\n * inline box through its last; null for a run with neither. */\nexport function leafExtent(leaf: LayoutNode): { start: Point; end: Point } | null {\n const points: { start: Point; end: Point }[] = [];\n const runs = leaf.charSource ?? [];\n if (runs.length > 0) {\n const first = runs[0]!;\n const last = runs[runs.length - 1]!;\n points.push({\n start: { node: first.node, offset: first.offset },\n end: { node: last.node, offset: last.offset + last.length },\n });\n }\n for (const box of inlineBoxesOf(leaf)) {\n const parent = box.source.parentNode;\n if (!parent) continue;\n const index = Array.prototype.indexOf.call(parent.childNodes, box.source);\n points.push({\n start: { node: parent, offset: index },\n end: { node: parent, offset: index + 1 },\n });\n }\n if (points.length === 0) return null;\n const before = (a: Point, b: Point) => comparePoints(a.node, a.offset, b.node, b.offset) < 0;\n let { start, end } = points[0]!;\n for (const point of points.slice(1)) {\n if (before(point.start, start)) start = point.start;\n if (before(end, point.end)) end = point.end;\n }\n return { start, end };\n}\n\n/** A node whose text is painted: text and no in-flow children (the\n * paint walk's own test); renderer leaves included. */\nexport function isTextLeaf(node: LayoutNode): boolean {\n if (node.text.length === 0) return false;\n return !node.children.some(\n (child) =>\n !child.inlineBox && child.style.position !== \"absolute\" && child.style.position !== \"fixed\",\n );\n}\n\n/** The part of a leaf's layout text the range covers — all of it for a\n * renderer leaf (its text has no source positions) — with inline\n * boxes spliced in for their U+FFFC markers and padding markers\n * dropped. A final newline (a trailing `<br>`, which the wrap layer\n * drops) goes too. */\nfunction leafSlice(leaf: LayoutNode, range: Range): string {\n const { text } = leaf;\n let start = 0;\n let end = text.length;\n if (leaf.charSource) {\n if (leaf.source.contains(range.startContainer)) {\n start = charIndexAt(leaf, range.startContainer, range.startOffset);\n }\n if (leaf.source.contains(range.endContainer)) {\n end = charIndexAt(leaf, range.endContainer, range.endOffset);\n }\n }\n let slice = text.slice(start, end);\n if (end === text.length && slice.endsWith(\"\\n\")) slice = slice.slice(0, -1);\n const boxes = inlineBoxesOf(leaf);\n let boxIndex = text.slice(0, start).split(OBJECT_REPLACEMENT).length - 1;\n slice = slice.replaceAll(OBJECT_REPLACEMENT, () => {\n const box = boxes[boxIndex++];\n if (!box || !range.intersectsNode(box.source)) return \"\";\n const items: TextItem[] = [];\n collectItems(box, range, items);\n return assemble(items);\n });\n return slice.replaceAll(INLINE_PAD, \"\");\n}\n\n/** Required breaks collapse to the largest of a run and vanish at\n * either end; text items concatenate. */\nfunction assemble(items: TextItem[]): string {\n let out = \"\";\n let pending = 0;\n for (const item of items) {\n if (\"breaks\" in item) {\n pending = Math.max(pending, item.breaks);\n continue;\n }\n if (item.text.length === 0) continue;\n if (out.length > 0 && pending > 0) out += \"\\n\".repeat(pending);\n pending = 0;\n out += item.text;\n }\n return out;\n}\n\n/* === Words ============================================================ */\n\nconst segmenters = new Map<string, Intl.Segmenter | null>();\n\n/** The word containing `leaf.text[index]` — the `Intl.Segmenter`\n * segment (word-like or not) within the run of text between markers\n * and newlines, in the element's language. null off a character, at a\n * marker, or without a Segmenter. */\nexport function wordAt(leaf: LayoutNode, index: number): { start: number; end: number } | null {\n const { text } = leaf;\n if (index < 0 || index >= text.length || isWordBoundary(text[index]!)) return null;\n let start = index;\n while (start > 0 && !isWordBoundary(text[start - 1]!)) start--;\n let end = index;\n while (end < text.length && !isWordBoundary(text[end]!)) end++;\n const segmenter = segmenterFor(leaf.source.closest?.(\"[lang]\")?.getAttribute(\"lang\") ?? \"\");\n if (!segmenter) return null;\n for (const segment of segmenter.segment(text.slice(start, end))) {\n const from = start + segment.index;\n const to = from + segment.segment.length;\n if (index >= from && index < to) return { start: from, end: to };\n }\n return null;\n}\n\nfunction isWordBoundary(ch: string): boolean {\n return ch === \"\\n\" || ch === OBJECT_REPLACEMENT || ch === INLINE_PAD;\n}\n\n/** One Segmenter per language, cached (construction is not free and\n * word extension asks per pointermove); an invalid tag falls back to\n * the default locale. */\nfunction segmenterFor(lang: string): Intl.Segmenter | null {\n let segmenter = segmenters.get(lang);\n if (segmenter === undefined) {\n segmenter = createSegmenter(lang) ?? createSegmenter(\"\");\n segmenters.set(lang, segmenter);\n }\n return segmenter;\n}\n\nfunction createSegmenter(lang: string): Intl.Segmenter | null {\n if (typeof Intl.Segmenter !== \"function\") return null;\n try {\n return new Intl.Segmenter(lang || undefined, { granularity: \"word\" });\n } catch {\n return null;\n }\n}\n","import { applyCellPaint, isBarePaint, renderCellSegments, samePaint } from \"./plain-text.ts\";\nimport type { CellSegment } from \"./plain-text.ts\";\nimport { selectionRangeThrough } from \"./selection.ts\";\nimport type { LayoutNode } from \"./types.ts\";\n\n/**\n * Paint the laid-out tree into the shadow's `#grid` (a `<pre>`): each\n * text line is a cell row, same-paint runs coalesce into spans.\n *\n * Node identity is preserved wherever possible (specs/cell-model.md\n * \"Selection\"): an unchanged paint skips the write entirely, and a\n * paint whose STRUCTURE (segment texts and span/bare split) matches\n * the last one only patches span styles in place — no node churn, so\n * live Selections (and an in-flight drag's anchor, which no engine\n * lets us restore) survive animation frames untouched. A structural\n * change rebuilds the nodes: the selection is captured as flat\n * character offsets before the swap and restored after, and while a\n * primary press is down with a selection anchor in the grid the\n * rebuild is HELD for release instead (element.ts) — even restored\n * nodes collapse Chromium's drag.\n */\nconst lastPaintSignature = new WeakMap<HTMLElement, string>();\ninterface PaintedRows {\n nodes: (Text | HTMLElement)[][];\n segments: CellSegment[][];\n}\nconst lastPaint = new WeakMap<HTMLElement, PaintedRows>();\n\n/** True when a Selection boundary (a collapsed press anchor counts —\n * the drag it starts must survive) lies inside the grid. */\nfunction hasSelectionInside(target: HTMLElement): boolean {\n return captureSelection(target, true) !== null;\n}\n\n/** Returns false when the paint was HELD: the caller asked to defer\n * structural rebuilds (a primary press is down) and a selection\n * anchor is in the grid — repeat the paint on release. */\nexport function paintGrid(root: LayoutNode, target: HTMLElement, holdStructural = false): boolean {\n const rows = renderCellSegments(root);\n const signature = signatureOf(rows);\n if (lastPaintSignature.get(target) === signature) return true;\n\n // Style-only pass: same texts in the same span/bare segmentation —\n // patch the spans whose paint actually changed and leave every\n // node's identity alone.\n const previous = lastPaint.get(target);\n if (previous && structureMatches(target, previous.nodes, rows)) {\n lastPaintSignature.set(target, signature);\n for (let y = 0; y < rows.length; y++) {\n for (let i = 0; i < rows[y]!.length; i++) {\n const segment = rows[y]![i]!;\n if (isBarePaint(segment) || samePaint(segment, previous.segments[y]![i])) continue;\n const span = previous.nodes[y]![i]! as HTMLElement;\n span.style.cssText = \"\";\n applyCellPaint(segment, span.style);\n }\n }\n previous.segments = rows;\n return true;\n }\n\n if (holdStructural && hasSelectionInside(target)) return false;\n lastPaintSignature.set(target, signature);\n const fragment = document.createDocumentFragment();\n const nodes: (Text | HTMLElement)[][] = [];\n for (let y = 0; y < rows.length; y++) {\n if (y > 0) fragment.appendChild(document.createTextNode(\"\\n\"));\n const rowNodes: (Text | HTMLElement)[] = [];\n for (const segment of rows[y]!) {\n if (isBarePaint(segment)) {\n const text = document.createTextNode(segment.text);\n rowNodes.push(text);\n fragment.appendChild(text);\n continue;\n }\n const span = document.createElement(\"span\");\n applyCellPaint(segment, span.style);\n span.textContent = segment.text;\n rowNodes.push(span);\n fragment.appendChild(span);\n }\n nodes.push(rowNodes);\n }\n lastPaint.set(target, { nodes, segments: rows });\n const saved = captureSelection(target, false);\n target.replaceChildren(fragment);\n if (saved) restoreSelection(target, saved);\n return true;\n}\n\nfunction structureMatches(\n target: HTMLElement,\n previous: (Text | HTMLElement)[][],\n rows: CellSegment[][],\n): boolean {\n if (previous.length !== rows.length) return false;\n for (let y = 0; y < rows.length; y++) {\n const prevRow = previous[y]!;\n const row = rows[y]!;\n if (prevRow.length !== row.length) return false;\n for (let i = 0; i < row.length; i++) {\n const node = prevRow[i]!;\n const bare = isBarePaint(row[i]!);\n if (bare !== (node.nodeType === Node.TEXT_NODE)) return false;\n if (node.textContent !== row[i]!.text) return false;\n // A node detached from the grid can't be patched.\n if (node.parentNode !== target) return false;\n }\n }\n return true;\n}\n\n/* === Selection preservation ========================================== */\n\ninterface SavedSelection {\n start: number; // flat character offsets into the grid's textContent\n end: number;\n backward: boolean;\n}\n\n/** Anything unexpected degrades to the old behavior (selection lost),\n * never an error. */\nfunction captureSelection(target: HTMLElement, allowCollapsed: boolean): SavedSelection | null {\n try {\n const selection = target.ownerDocument.getSelection();\n if (!selection) return null;\n const shadowRoot = target.getRootNode();\n if (!(shadowRoot instanceof ShadowRoot)) return null;\n const range = selectionRangeThrough(shadowRoot);\n if (!range) return null;\n const start = flatOffset(target, range.startContainer, range.startOffset);\n const end = flatOffset(target, range.endContainer, range.endOffset);\n if (start === null || end === null) return null;\n if (start === end && !allowCollapsed) return null;\n // `direction` is unsupported in some engines; forward is the safe\n // default (a restored backward drag then extends from its focus\n // end — visible only if the user keeps dragging).\n const direction = (selection as { direction?: string }).direction;\n return { start, end, backward: direction === \"backward\" };\n } catch {\n return null;\n }\n}\n\nfunction restoreSelection(target: HTMLElement, saved: SavedSelection): void {\n try {\n const start = nodeAtOffset(target, saved.start);\n const end = nodeAtOffset(target, saved.end);\n if (!start || !end) return;\n // Chromium: restore through the shadow root's own selection — the\n // document-level restore leaves a live drag's internal anchor on\n // the detached nodes and the next mousemove collapses it.\n const shadowRoot = target.getRootNode() as { getSelection?: () => Selection | null };\n const selection = shadowRoot.getSelection?.() ?? target.ownerDocument.getSelection();\n if (saved.backward) {\n selection?.setBaseAndExtent(end[0], end[1], start[0], start[1]);\n } else {\n selection?.setBaseAndExtent(start[0], start[1], end[0], end[1]);\n }\n } catch {\n // Leave whatever the browser collapsed the selection to.\n }\n}\n\n/** Boundary point → offset into the grid's flat text; null when the\n * point is outside the grid (the selection reaches past it — restoring\n * only our half would corrupt it). A Range does the flattening: its\n * string is exactly the text between the grid's start and the point. */\nfunction flatOffset(target: HTMLElement, container: Node, offset: number): number | null {\n if (!target.contains(container)) return null;\n const range = target.ownerDocument.createRange();\n range.selectNodeContents(target);\n range.setEnd(container, offset);\n return range.toString().length;\n}\n\nexport function nodeAtOffset(target: HTMLElement, offset: number): [Text, number] | null {\n let remaining = offset;\n let last: [Text, number] | null = null;\n for (const text of textNodesOf(target)) {\n if (remaining <= text.data.length) return [text, remaining];\n remaining -= text.data.length;\n last = [text, text.data.length];\n }\n // Offset past the new content (the grid shrank): clamp to the end.\n return last;\n}\n\nfunction* textNodesOf(target: HTMLElement): Generator<Text> {\n const walker = target.ownerDocument.createTreeWalker(target, NodeFilter.SHOW_TEXT);\n let node = walker.nextNode();\n while (node) {\n yield node as Text;\n node = walker.nextNode();\n }\n}\n\nfunction signatureOf(rows: CellSegment[][]): string {\n const parts: string[] = [];\n for (const row of rows) {\n for (const s of row) {\n parts.push(\n s.text,\n s.color ?? \"\",\n s.backgroundColor ?? \"\",\n s.fontWeight ?? \"\",\n s.fontStyle ?? \"\",\n s.textDecorationLine ?? \"\",\n s.opacity ?? \"\",\n );\n }\n parts.push(\"\\n\");\n }\n return parts.join(\"\\x1f\");\n}\n","import { paintOrderedChildren, paintsInPositionedStep } from \"./borders.ts\";\nimport { leafLineSpans } from \"./layout.ts\";\nimport type { LayoutNode, PerSide } from \"./types.ts\";\nimport { lineAdvance } from \"./wrap.ts\";\n\n/**\n * Write geometry custom properties, quantized inline padding, and z-index\n * markers on each source element in the light DOM. Coordinates on\n * LayoutNode are parent-relative; the companion stylesheet turns them\n * into px via the measured cell size. No painting: decoration and text\n * glyphs land in the shadow grid via `paint.ts`.\n *\n * Every write is change-checked: a relayout that computes the same\n * result mutates nothing. Chrome dismisses an open <select> popup on\n * style mutations near it, and the dynamic-state listeners relayout on\n * the very events that open one (focusin/pointerover) — idempotent\n * writes keep the popup up.\n */\nexport function render(root: LayoutNode): void {\n const inlineInsetElements = new Set<Element>();\n walk(root, true, inlineInsetElements);\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\n/** setProperty, skipped when the value is already there. */\nfunction setVar(el: HTMLElement, prop: string, value: string): void {\n if (el.style.getPropertyValue(prop) !== value) el.style.setProperty(prop, value);\n}\n\n/** removeProperty, skipped when the property isn't set. */\nfunction clearVar(el: HTMLElement, prop: string): void {\n if (el.style.getPropertyValue(prop) !== \"\") el.style.removeProperty(prop);\n}\n\n/** Boolean attribute toggle, skipped when already in the target state. */\nfunction setFlag(el: Element, name: string, on: boolean): void {\n if (el.hasAttribute(name) === on) return;\n if (on) el.setAttribute(name, \"\");\n else el.removeAttribute(name);\n}\n\nfunction walk(node: LayoutNode, isRoot: boolean, inlineInsetElements: Set<Element>): void {\n if (node.inlineElements) {\n for (const { element, tracking, padLeft, padRight, insets } of node.inlineElements) {\n const el = element as HTMLElement;\n setVar(el, \"--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) setVar(el, \"--mw-ipl\", String(padLeft));\n else clearVar(el, \"--mw-ipl\");\n if (padRight > 0) setVar(el, \"--mw-ipr\", String(padRight));\n else clearVar(el, \"--mw-ipr\");\n if (insets) {\n inlineInsetElements.add(element);\n applyInlineInsets(el, insets);\n }\n }\n }\n\n if (isRoot) markRoot(node);\n else positionElement(node);\n // A hidden table box (misparented content, <col>) hides its whole\n // subtree browser-side; nothing to recurse into.\n if (node.tableHidden) return;\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 && paintsInPositionedStep(child, node) && !child.inlineBox)\n setVar(el, \"--mw-z\", String(child.style.zIndex));\n else clearVar(el, \"--mw-z\");\n walk(child, false, inlineInsetElements);\n }\n}\n\n/** The host's flags when its own content is the root leaf\n * (specs/host-leaf.md): the companion's host variants of the leaf\n * typography rules key on them. No geometry — the host is its own box.\n * A new leaf flag in positionElement that shapes native text needs a\n * line here and a host variant in styles.css. */\nfunction markRoot(node: LayoutNode): void {\n const el = node.source as HTMLElement;\n const leaf = node.text.length > 0;\n const { whiteSpace, textAlignBlocked, textIndent } = node.style;\n setFlag(el, \"data-mw-leaf\", leaf);\n setFlag(el, \"data-mw-nowrap\", leaf && whiteSpace !== \"normal\");\n setFlag(el, \"data-mw-pre\", leaf && whiteSpace === \"pre\");\n setFlag(el, \"data-mw-text-align-blocked\", leaf && textAlignBlocked);\n if (leaf) setVar(el, \"--mw-ti\", String(textIndent));\n else clearVar(el, \"--mw-ti\");\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 setFlag(el, \"data-mw-inline-inset\", true);\n const write = (prop: string, cells: number | null) => {\n if (cells === null) clearVar(el, prop);\n else setVar(el, 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\n/** Centered text: the grid paints `floor(leftover / 2)` whole cells,\n * the browser centers the native copy fractionally — half a cell apart\n * on odd-leftover lines (specs/cell-model.md \"Text alignment\"). When\n * EVERY line shares the odd-parity drift (a single-line heading, most\n * commonly), the companion nudges the native copy half a cell left so\n * selection sits on the glyphs. CHILDLESS text leaves only: the nudge\n * would also shift an embedded atomic box's visible native ink and an\n * absolutized child's selectable text, and an inline box's own\n * form-control ink keeps browser centering per the spec. The leftover\n * math mirrors the paint's alignOffset (plain-text.ts). */\nfunction needsCenterNudge(node: LayoutNode): boolean {\n const style = node.style;\n if (style.textAlign !== \"center\" || !node.text) return false;\n if (node.inlineBox || node.children.length > 0) return false;\n const multicol = node.multicolGeometry;\n const padding = node.resolvedPadding;\n const contentWidth =\n node.localRect.width - style.border.left - style.border.right - padding.left - padding.right;\n const alignWidth = multicol ? Math.max(1, multicol.columnWidth - style.tracking) : contentWidth;\n const spans = multicol?.spans ?? leafLineSpans(node, contentWidth);\n if (spans.length === 0) return false;\n return spans.every((span, i) => {\n const indent = i === 0 ? style.textIndent : 0;\n const leftover =\n alignWidth - indent - lineAdvance(span.start, span.end, node.advances, style.tracking);\n return leftover > 0 && leftover % 2 === 1;\n });\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 and paragraph-flow multicol children stay IN\n // FLOW (the browser's own line layout / column fragmentation places\n // them); everything else is engine-positioned. Same geometry vars, a\n // different companion rule each (see styles.css).\n const flow = node.multicolFlow;\n const flowSpan = node.multicolFlowSpan;\n setFlag(el, \"data-mw-laid-out\", !node.inlineBox && !flow && !flowSpan);\n setFlag(el, \"data-mw-inline-box\", Boolean(node.inlineBox));\n setFlag(el, \"data-mw-multicol-flow\", Boolean(flow));\n setFlag(el, \"data-mw-multicol-flow-span\", Boolean(flowSpan));\n const flowMargins = flow ?? flowSpan;\n if (flowMargins) {\n setVar(el, \"--mw-mt\", String(flowMargins.top ?? 0));\n setVar(el, \"--mw-mr\", String(flowMargins.right ?? 0));\n setVar(el, \"--mw-mb\", String(flowMargins.bottom ?? 0));\n setVar(el, \"--mw-ml\", String(flowMargins.left ?? 0));\n } else {\n clearVar(el, \"--mw-mt\");\n clearVar(el, \"--mw-mr\");\n clearVar(el, \"--mw-mb\");\n clearVar(el, \"--mw-ml\");\n }\n // Bottom-aligned atomic boxes keep their browser alignment (grid-exact,\n // probed); everything else is pinned top by the companion rule.\n setFlag(el, \"data-mw-vbottom\", Boolean(node.inlineBox) && node.style.verticalAlign === \"end\");\n // Grid typography (specs/cell-model.md): extra cells per character, rows\n // per wrapped line, and the half-leading cancellation shift.\n setVar(el, \"--mw-ls\", String(tracking));\n setVar(el, \"--mw-lh\", String(lineGap + 1));\n setVar(el, \"--mw-lhs\", String(-lineGap / 2));\n setFlag(el, \"data-mw-nowrap\", whiteSpace !== \"normal\");\n // A multicol TEXT LEAF or paragraph-flow container keeps native\n // columns, driven by the engine's used values so the browser\n // fragments on the same lines (specs/multicol.md \"Browser\n // agreement\"); a spanner-split flow additionally trusts the NATIVE\n // balancer per segment (probed exact). Atomic element-children\n // containers get no flag: their light DOM has nothing in flow.\n // Flow CHILDREN carry a geometry too (their line maps) but must never\n // get native columns themselves — only the container fragments.\n const multicol = flow || flowSpan ? undefined : node.multicolGeometry;\n setFlag(el, \"data-mw-multicol\", Boolean(multicol));\n setFlag(el, \"data-mw-multicol-balance\", Boolean(multicol?.nativeBalance));\n if (multicol) {\n setVar(el, \"--mw-colc\", String(multicol.columnCount));\n setVar(el, \"--mw-colg\", String(multicol.gap));\n } else {\n clearVar(el, \"--mw-colc\");\n clearVar(el, \"--mw-colg\");\n }\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 setFlag(el, \"data-mw-pre\", whiteSpace === \"pre\");\n setVar(el, \"--mw-x\", String(rect.x));\n setVar(el, \"--mw-y\", String(rect.y));\n setVar(el, \"--mw-w\", String(rect.width));\n setVar(el, \"--mw-h\", String(rect.height));\n setFlag(el, \"data-mw-clip\", overflow.x === \"clip\" || overflow.y === \"clip\");\n setFlag(el, \"data-mw-scroll\", node.scrollRange !== undefined);\n if (node.scrollRange) {\n // Native range == engine range by construction: a 1px ::after\n // spacer (companion CSS) ends at exactly max + box cells, so\n // scrollHeight - clientHeight lands on the engine's max in every\n // engine (browsers disagree about end padding in the scrollable\n // overflow area). An axis with no range parks the spacer in the\n // first cell — a box outside the padding box (at -1px) is dropped\n // from the overflow area on BOTH axes.\n const { maxX, maxY } = node.scrollRange;\n setVar(el, \"--mw-se-x\", String(maxX > 0 ? maxX + node.localRect.width : 1));\n setVar(el, \"--mw-se-y\", String(maxY > 0 ? maxY + node.localRect.height : 1));\n } else {\n clearVar(el, \"--mw-se-x\");\n clearVar(el, \"--mw-se-y\");\n }\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 setVar(el, \"--mw-pt\", String(padding.top));\n setVar(el, \"--mw-pr\", String(padding.right));\n setVar(el, \"--mw-pb\", String(padding.bottom));\n setVar(el, \"--mw-pl\", String(padding.left));\n setVar(el, \"--mw-bt\", String(border.top));\n setVar(el, \"--mw-br\", String(border.right));\n setVar(el, \"--mw-bb\", String(border.bottom));\n setVar(el, \"--mw-bl\", String(border.left));\n // Native text-indent is authored in px; overwrite it in cells so the\n // browser's own line (the selectable, transparent-locked text under\n // the grid) sits under the glyphs the engine painted. Always set —\n // custom properties inherit, so an unset var on an `indent-0` child\n // would resolve to an indented ancestor's value.\n setVar(el, \"--mw-ti\", String(node.style.textIndent));\n setFlag(el, \"data-mw-text-align-blocked\", textAlignBlocked);\n setFlag(el, \"data-mw-center-nudge\", needsCenterNudge(node));\n // Un-laid-out direct text (mixed with block children) would otherwise\n // paint unpositioned over the children — hide it (see styles.css).\n setFlag(el, \"data-mw-dropped-text\", Boolean(node.droppedText));\n setFlag(el, \"data-mw-table-hidden\", Boolean(node.tableHidden));\n}\n","import { trackBackground } from \"./animate.ts\";\nimport { pxToCells, roundHalfAwayFromZero } from \"./metrics.ts\";\nimport { autoTrack, zeroInsets } from \"./types.ts\";\nimport { leafRendererFor } from \"./leaf.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport type {\n AlignItems,\n Overflow,\n OverflowAxis,\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 // A min/max limit: an authored calc() or viewport length first (their\n // units carry intent the computed px has lost), then the computed px.\n const limit = (property: string, resolved: string, prefix: string): SizeLimit | undefined =>\n authoredCalcCells(\n csm,\n property,\n resolved,\n classAttr,\n prefix,\n inlineStyle,\n metrics,\n rootFontSizePx,\n ) ??\n viewportLimit(\n csm,\n property,\n resolved,\n classAttr,\n prefix,\n inlineStyle,\n metrics,\n rootFontSizePx,\n ) ??\n readLimit(resolved, rootFontSizePx);\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 // Multicol: a block with an authored column-count or column-width\n // (specs/multicol.md). Computed values are specified values (probed\n // — no used-value trap).\n const columnCount =\n cs.columnCount && cs.columnCount !== \"auto\"\n ? Math.max(1, Math.floor(Number(cs.columnCount) || 1))\n : null;\n const columnWidthPx =\n cs.columnWidth && cs.columnWidth !== \"auto\" ? parseFloat(cs.columnWidth) : NaN;\n const columnWidth = Number.isFinite(columnWidthPx)\n ? Math.max(1, pxToCells(columnWidthPx, rootFontSizePx))\n : null;\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\" || isZeroClipped(el, cs)\n ? \"none\"\n : columnCount !== null || columnWidth !== null\n ? \"multicol\"\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, metrics),\n height: readSize(csm, cs.height, \"height\", rootFontSizePx, classAttr, inlineStyle, metrics),\n minWidth: limit(\"min-width\", cs.minWidth, \"min-w\") ?? \"auto\",\n minHeight: limit(\"min-height\", cs.minHeight, \"min-h\") ?? \"auto\",\n maxWidth: limit(\"max-width\", cs.maxWidth, \"max-w\"),\n maxHeight: limit(\"max-height\", cs.maxHeight, \"max-h\"),\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 // `column-gap: normal` is 0 in flex/grid but 1em in multicol, per\n // CSS (specs/multicol.md \"Reading\"). Headless DOMs report unset as\n // an empty string — same initial value.\n gapX: readSpacing(\n cs.columnGap === \"normal\" || cs.columnGap === \"\"\n ? display === \"multicol\"\n ? `${fontSizePx}px`\n : \"0px\"\n : cs.columnGap,\n rootFontSizePx,\n ),\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 overflow: readOverflow(cs),\n scrollbarWidth: readScrollbarWidth(el, cs),\n scrollbarColor: readScrollbarColor(cs.scrollbarColor),\n overscroll: {\n x: (cs.overscrollBehaviorX || \"auto\") === \"auto\",\n y: (cs.overscrollBehaviorY || \"auto\") === \"auto\",\n },\n scrollbarSize: {\n x: readCells(cs.getPropertyValue(\"--mw-scrollbar-size-x\")),\n y: readCells(cs.getPropertyValue(\"--mw-scrollbar-size-y\")),\n },\n scrollbarInset: {\n x: readCells(cs.getPropertyValue(\"--mw-scrollbar-inset-x\"), 0),\n y: readCells(cs.getPropertyValue(\"--mw-scrollbar-inset-y\"), 0),\n },\n ...readTextStyle(el, cs, rootFontSizePx),\n // Both readable because the companion stylesheet's typography rewrite\n // is gated on `:not([measuring])`.\n lineGap: lineGapRows(cs.lineHeight, fontSizePx),\n tracking: trackingCells(cs.letterSpacing, fontSizePx, metrics?.letterSpacing ?? 0),\n color: cs.color,\n fontWeight: cs.fontWeight,\n fontStyle: cs.fontStyle,\n backgroundColor: readAnimatedBackground(el, cs.backgroundColor, cs),\n backgroundClear: cs.getPropertyValue(\"--mw-bg-clear\").trim() === \"1\",\n borderColor: {\n top: cs.borderTopColor,\n right: cs.borderRightColor,\n bottom: cs.borderBottomColor,\n left: cs.borderLeftColor,\n },\n opacity: readOpacity(cs.opacity),\n glyphSet: cs.getPropertyValue(\"--mw-border-glyphs\").trim() || null,\n zIndex: cs.zIndex === \"auto\" || cs.zIndex === \"\" ? null : Number(cs.zIndex) || 0,\n latticeBorder: null,\n ruleX:\n display === \"flex\" || display === \"grid\" || display === \"multicol\"\n ? readGapRule(cs, \"x\")\n : null,\n ruleY: display === \"flex\" || display === \"grid\" ? readGapRule(cs, \"y\") : null,\n ruleBreak: readKeyword(cs, \"--mw-rule-break\", [\"none\", \"intersection\"] as const, \"normal\"),\n ruleInset:\n cs.getPropertyValue(\"--mw-rule-inset\").trim() === \"overlap-join\"\n ? \"overlap-join\"\n : Math.max(\n 0,\n roundHalfAwayFromZero(parseFloat(cs.getPropertyValue(\"--mw-rule-inset\")) || 0),\n ),\n ruleVisibilityItems: readKeyword(\n cs,\n \"--mw-rule-visibility-items\",\n [\"all\", \"around\", \"between\"] as const,\n \"normal\",\n ),\n columnCount,\n columnWidth,\n columnFill: cs.columnFill === \"auto\" ? \"auto\" : \"balance\",\n columnSpan: cs.columnSpan === \"all\",\n breakBeforeColumn: cs.breakBefore === \"column\",\n breakAfterColumn: cs.breakAfter === \"column\",\n breakInsideAvoid: cs.breakInside === \"avoid\" || cs.breakInside === \"avoid-column\",\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\n/** True for a computed `background-color` that shouldn't trigger the\n * bg-occludes-decorations fill. Real browsers resolve transparent to\n * `rgba(0, 0, 0, 0)`; the empty-string and `currentcolor` branches\n * cover happy-dom (test env), which leaves some computed values\n * unresolved. */\nexport function isTransparentColor(value: string): boolean {\n if (!value) return true;\n const normalized = value.trim().toLowerCase();\n return (\n normalized === \"\" ||\n normalized === \"transparent\" ||\n normalized === \"rgba(0, 0, 0, 0)\" ||\n normalized === \"currentcolor\"\n );\n}\n\n/** Background-color read, routed through the synthesized-transition\n * tracker (animate.ts): a mid-fade read returns the interpolated color\n * — including near-transparent frames of a fade to/from unset, which\n * must paint rather than read as \"no background\". */\nfunction readAnimatedBackground(\n el: Element,\n raw: string,\n cs: CSSStyleDeclaration,\n): string | undefined {\n const tracked = trackBackground(el, isTransparentColor(raw) ? \"\" : raw, cs);\n return tracked === \"\" ? undefined : tracked;\n}\n\nfunction isClipping(value: string): boolean {\n return value === \"hidden\" || value === \"clip\";\n}\n\n/** Authored `scrollbar-width`, cached from the first CLEAN read: once\n * the element carries data-mw-scroll our own hiding lock sets it to\n * none, and Firefox never re-resolves the computed value when the\n * lock's [measuring] gate flips — so the pre-lock value is the truth\n * (authored changes after the first layout won't re-read there;\n * documented deviation). */\nconst scrollbarWidthCache = new WeakMap<Element, \"auto\" | \"none\">();\nlet scrollbarWidthReadable: boolean | null = null;\n\n/** Environments with forced overlay scrollbars (headless Firefox\n * among them) compute `scrollbar-width: none` on EVERY element — a\n * pristine probe reading `none` means reads carry no authored signal,\n * so the engine ignores the property there instead of hiding every\n * bar. */\nfunction scrollbarWidthReadsTrustworthy(doc: Document): boolean {\n if (scrollbarWidthReadable !== null) return scrollbarWidthReadable;\n if (!doc.body) return true; // decide later, on a real read\n const probe = doc.createElement(\"div\");\n probe.style.cssText = \"position: absolute; width: 0; height: 0; overflow: auto\";\n doc.body.appendChild(probe);\n scrollbarWidthReadable = getComputedStyle(probe).scrollbarWidth !== \"none\";\n probe.remove();\n return scrollbarWidthReadable;\n}\n\nfunction readScrollbarWidth(el: Element, cs: CSSStyleDeclaration): \"auto\" | \"none\" {\n if (!scrollbarWidthReadsTrustworthy(el.ownerDocument)) return \"auto\";\n if (el.hasAttribute(\"data-mw-scroll\")) {\n const cached = scrollbarWidthCache.get(el);\n if (cached !== undefined) return cached;\n }\n const value: \"auto\" | \"none\" = cs.scrollbarWidth === \"none\" ? \"none\" : \"auto\";\n scrollbarWidthCache.set(el, value);\n return value;\n}\n\n/** `scrollbar-color: <thumb> <track>` — two computed colors, split at\n * the top parenthesis level (rgb()/color() carry inner spaces). */\nfunction readScrollbarColor(value: string): { thumb: string; track: string } | null {\n const v = (value ?? \"\").trim();\n if (!v || v === \"auto\") return null;\n let depth = 0;\n for (let i = 0; i < v.length; i++) {\n const ch = v[i]!;\n if (ch === \"(\") depth++;\n else if (ch === \")\") depth--;\n else if (ch === \" \" && depth === 0) {\n return { thumb: v.slice(0, i), track: v.slice(i + 1).trim() };\n }\n }\n return null;\n}\n\n/** A `<integer>` custom property in cells, floored at `min`. */\nfunction readCells(value: string, min = 1): number {\n return Math.max(min, Math.floor(Number(value) || min));\n}\n\nfunction overflowAxis(value: string): OverflowAxis {\n if (isClipping(value)) return \"clip\";\n if (value === \"auto\" || value === \"scroll\") return value;\n return \"visible\";\n}\n\n/** Per-axis overflow (specs/scrolling.md). Longhands read first (the\n * shorthand sets both in real browsers; happy-dom may leave them \"\",\n * hence the fallback), then the CSS coercion: one non-visible axis\n * forces the other's `visible` to compute `auto`. */\nexport function readOverflow(cs: CSSStyleDeclaration): Overflow {\n let x = overflowAxis(cs.overflowX || cs.overflow);\n let y = overflowAxis(cs.overflowY || cs.overflow);\n if (x !== \"visible\" && y === \"visible\") y = \"auto\";\n if (y !== \"visible\" && x === \"visible\") x = \"auto\";\n return { x, y };\n}\n\n/** The screen-reader-only pattern (Tailwind `sr-only` and friends): an\n * absolutely positioned box whose ink can't show — a zero `clip` rect,\n * or a clipped ≤1px box. Treated as display:none by the ENGINE only:\n * the light-DOM element keeps its authored styles, so assistive tech\n * still reads it. */\nfunction isZeroClipped(el: Element, cs: CSSStyleDeclaration): boolean {\n if (cs.position !== \"absolute\" && cs.position !== \"fixed\") return false;\n const clip = cs.clip.replace(/\\s/g, \"\");\n if (clip === \"rect(0px,0px,0px,0px)\" || clip === \"rect(0,0,0,0)\") return true;\n // The clipped-box half reads the browser's NATURAL size, which for a\n // renderer leaf is meaningless (its size comes from the renderer's\n // lines; its light content is invisible) — a fresh absolute leaf\n // with overflow-clip and no padding measures 0x0 and would be\n // dropped before it ever renders, staying 0x0 forever.\n if (leafRendererFor(el.tagName)) return false;\n return (\n (isClipping(cs.overflow) || isClipping(cs.overflowX)) &&\n parseFloat(cs.width) <= 1 &&\n parseFloat(cs.height) <= 1\n );\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/** The text properties a leaf takes from its own element — the host's\n * contribution to the root leaf too (specs/host-leaf.md). */\nexport function readTextStyle(\n el: Element,\n cs: CSSStyleDeclaration,\n rootFontSizePx: number,\n): Pick<\n CellStyle,\n | \"whiteSpace\"\n | \"tabSize\"\n | \"textOverflow\"\n | \"textDecorationLine\"\n | \"textAlignBlocked\"\n | \"textAlign\"\n | \"textIndent\"\n> {\n return {\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 textOverflow: cs.textOverflow === \"ellipsis\" ? \"ellipsis\" : \"clip\",\n textDecorationLine: cs.textDecorationLine,\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: readTextAlign(el, cs),\n textIndent: readTextIndent(cs, rootFontSizePx),\n };\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 readKeyword<T extends string, D extends string>(\n cs: CSSStyleDeclaration,\n property: string,\n values: readonly T[],\n fallback: D,\n): T | D {\n const value = cs.getPropertyValue(property).trim() as T;\n return values.includes(value) ? value : fallback;\n}\n\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\n/** Only `justify` is blocked (its per-line extra word spacing is\n * fractional and off-grid). `center` is engine-quantized: the grid\n * paints each line at floor((W − line) / 2); the browser's own\n * (fractional) centering only touches the invisible light-DOM copy. */\nfunction authoredTextAlignBlocked(el: Element, cs: CSSStyleDeclaration): boolean {\n if (cs.textAlign === \"justify\") return true;\n // Hint fallback for environments that don't map `align` (happy-dom).\n return el.getAttribute(\"align\")?.toLowerCase() === \"justify\";\n}\n\nfunction readTextAlign(el: Element, cs: CSSStyleDeclaration): \"start\" | \"center\" | \"end\" {\n const value = cs.textAlign || el.getAttribute(\"align\")?.toLowerCase() || \"\";\n if (value === \"right\" || value === \"end\") return \"end\";\n // -webkit-center / -moz-center: the legacy `align` attribute's\n // computed form in real browsers.\n if (value === \"center\" || value.endsWith(\"-center\")) return \"center\";\n return \"start\";\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 ÷ font-size) − 1,\n * never negative. Computed line-height is always px (or `normal`); the\n * divisor is FONT-SIZE, not cell-height, so unitless ratios keep their\n * CSS meaning (`leading-loose` = 2 → 2 rows per line, 1 gap) even when\n * cell-height ≠ 1em (default `line-height: normal` on the root makes\n * the cell ~1.15em). */\nfunction lineGapRows(lineHeight: string, fontSizePx: number): number {\n if (!lineHeight || lineHeight === \"normal\" || fontSizePx <= 0) return 0;\n const px = parseFloat(lineHeight);\n if (!Number.isFinite(px)) return 0;\n return Math.max(0, Math.floor(px / fontSizePx + 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\n/** Computed `opacity`, clamped to [0, 1]; a non-numeric read is opaque. */\nfunction readOpacity(value: string): number {\n const parsed = parseFloat(value);\n return Number.isFinite(parsed) ? Math.min(1, Math.max(0, parsed)) : 1;\n}\n\n/** `text-indent` in cells. Percentages come through as `Npx` after\n * `getComputedStyle` only when a definite width is around, and even then\n * they'd need per-line resolution; treat them as 0. */\nfunction readTextIndent(cs: CSSStyleDeclaration, rootFontSizePx: number): number {\n const value = cs.textIndent;\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\nfunction readSize(\n csm: StylePropertyMapReadOnly | null,\n fallback: string,\n key: \"width\" | \"height\",\n rootFontSizePx: number,\n classAttr: string,\n inlineStyle: CSSStyleDeclaration,\n metrics: CellMetrics | undefined,\n): Size | undefined {\n // Viewport-relative lengths (h-screen, style=\"height: 100dvh\", …)\n // express PHYSICAL screen intent, so they convert via the measured\n // cell size, not the spacing scale (specs/cell-model.md\n // \"Viewport-relative lengths\"). The inline style attribute keeps the\n // authored unit verbatim — and inline beats classes, per cascade.\n const inlineViewport = viewportLengthPx(key === \"width\" ? inlineStyle.width : inlineStyle.height);\n if (inlineViewport !== null) {\n return { kind: \"cells\", value: physicalCells(inlineViewport, key, metrics, rootFontSizePx) };\n }\n const calc = authoredCalcCells(\n csm,\n key,\n fallback,\n classAttr,\n key === \"width\" ? \"w\" : \"h\",\n inlineStyle,\n metrics,\n rootFontSizePx,\n );\n if (calc !== undefined) return { kind: \"cells\", value: calc };\n // Class scan, every engine: computed values (Typed OM included)\n // resolve viewport units to plain px, indistinguishable from\n // spacing-scale lengths.\n const viewportPx = viewportUtilityPx(classAttr, key === \"width\" ? \"w\" : \"h\");\n if (viewportPx !== null) {\n // Confirm the utility is ACTIVE against the resolved value — an\n // inactive variant (md:h-screen below md) or an overriding inline\n // style resolves elsewhere and must win. When it agrees, prefer\n // the RESOLVED px: it also carries sv/lv/dv bases the innerWidth/\n // Height estimate can't know. No resolved value at all (headless\n // test env, stylesheet not loaded yet) trusts the scan.\n const resolved = parseFloat(csm ? String(csm.get(key) ?? \"\") : fallback);\n const agrees = Number.isFinite(resolved) && Math.abs(resolved - viewportPx) <= viewportPx * 0.3;\n if (agrees || !Number.isFinite(resolved)) {\n const px = agrees ? resolved : viewportPx;\n return { kind: \"cells\", value: physicalCells(px, key, metrics, rootFontSizePx) };\n }\n }\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 // Authored viewport units that survive to the computed string\n // (engine-dependent; arbitrary values like h-[50vh]).\n const authoredViewport = viewportLengthPx(s);\n if (authoredViewport !== null) {\n return {\n kind: \"cells\",\n value: physicalCells(authoredViewport, key, metrics, rootFontSizePx),\n };\n }\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 // Numeric spacing-scale utility (`h-7`, `w-0.5`, …): map the class\n // directly to cells. Match the Tailwind spacing scale (N * 0.25rem\n // = N cells) so we don't have to trust `cs.height` — same result\n // for most elements, but critical for <td>/<th> in Firefox where\n // `cs.height` returns the USED height from the table layout\n // (including rowspan effects), not the authored value.\n const numeric = new RegExp(`(?:^|[\\\\s:.[!])${axis}-(\\\\d+(?:\\\\.\\\\d+)?)(?![\\\\w-/])`).exec(\n classAttr,\n );\n if (numeric) return { kind: \"cells\", value: roundHalfAwayFromZero(Number(numeric[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/** Parse an authored viewport-relative length (\"100dvh\", \"50vw\", …)\n * into px against the current viewport. null for anything else. */\nfunction viewportLengthPx(value: string): number | null {\n const match = /^(-?[\\d.]+)((?:[dsl]?v)(?:h|w|min|max)|vi|vb)$/.exec(value.trim());\n if (!match || typeof window === \"undefined\") return null;\n const amount = parseFloat(match[1]!);\n if (!Number.isFinite(amount)) return null;\n const unit = match[2]!;\n const height = window.innerHeight;\n const width = window.innerWidth;\n const basis = unit.endsWith(\"h\")\n ? height\n : unit.endsWith(\"min\")\n ? Math.min(width, height)\n : unit.endsWith(\"max\")\n ? Math.max(width, height)\n : unit === \"vb\"\n ? height\n : width; // vw / vi\n return (amount / 100) * basis;\n}\n\n/** Tailwind viewport utilities (`h-screen`, `min-h-dvh`, `h-[95dvh]`,\n * …) → px. Scanned in EVERY engine (computed values resolve viewport\n * units to plain px); callers active-check the result. `prefix` is\n * the utility stem (\"h\", \"w\", \"min-h\", …). */\nfunction viewportUtilityPx(classAttr: string, prefix: string): number | null {\n if (typeof window === \"undefined\") return null;\n const named = new RegExp(`(?:^|[\\\\s:.[!])${prefix}-(screen|[dsl]v[hw])(?![\\\\w-])`).exec(\n classAttr,\n );\n if (named) {\n const name = named[1]!;\n // h-screen = 100vh, w-screen = 100vw; explicit units name their axis.\n if (name === \"screen\") return prefix.includes(\"h\") ? window.innerHeight : window.innerWidth;\n return name.endsWith(\"h\") ? window.innerHeight : window.innerWidth;\n }\n // Arbitrary viewport values: h-[95dvh], min-h-[50vh], …\n const arbitrary = new RegExp(\n `(?:^|[\\\\s:.[!])${prefix}-\\\\[(-?[\\\\d.]+(?:[dsl]?v(?:h|w|min|max)|vi|vb))\\\\]`,\n ).exec(classAttr);\n return arbitrary ? viewportLengthPx(arbitrary[1]!) : null;\n}\n\n/** Convert PHYSICAL px to cells on the given axis using the measured\n * cell size — viewport-relative lengths mean real screen distance, not\n * the spacing scale. Headless fallback: the spacing scale. */\nfunction physicalCells(\n px: number,\n key: \"width\" | \"height\",\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): number {\n const cellPx = key === \"width\" ? metrics?.width : metrics?.height;\n if (cellPx && cellPx > 0) return Math.max(0, Math.floor(px / cellPx));\n return pxToCells(px, rootFontSizePx);\n}\n\n/** An authored `calc()` length, evaluated PER TERM into cells\n * (specs/cell-model.md \"Mixed-unit calc()\"): viewport units through the\n * measured cell like `h-screen`, `rem` and `--spacing(N)` on the\n * spacing scale, `px` on the same scale — so `calc(100vh -\n * --spacing(2))` is \"the rows that fit, minus two\", which the single\n * computed px can no longer say. Sourced from the inline style or the\n * arbitrary-value utility (`max-h-[calc(…)]`, `_` for spaces), and\n * active-checked against the computed px like viewport utilities. A\n * term the evaluator does not model (%, em, var()) leaves the value to\n * the computed px. undefined = no authored calc. */\nfunction authoredCalcCells(\n csm: StylePropertyMapReadOnly | null,\n property: string,\n resolvedValue: string,\n classAttr: string,\n utilityPrefix: string,\n inlineStyle: CSSStyleDeclaration,\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): number | undefined {\n const key = property.endsWith(\"width\") ? \"width\" : \"height\";\n const inline = inlineStyle.getPropertyValue(property).trim();\n const fromInline = inline.startsWith(\"calc(\");\n // Six reads per element: the substring test spares the regex almost always.\n if (!fromInline && !classAttr.includes(\"-[calc(\")) return undefined;\n const utility = new RegExp(`(?:^|[\\\\s:.[!])${utilityPrefix}-\\\\[(calc\\\\([^\\\\]]*\\\\))\\\\]`).exec(\n classAttr,\n );\n const authored = fromInline ? inline : utility?.[1]?.replaceAll(\"_\", \" \");\n if (!authored) return undefined;\n const value = evaluateCalc(authored, key, metrics, rootFontSizePx);\n if (!value || value.unitless) return undefined;\n const cells = Math.max(0, roundHalfAwayFromZero(value.cells));\n // The inline style wins by cascade; a class needs the active-check: an\n // inactive variant or an overriding declaration resolves elsewhere — to\n // other px, or to a keyword (`none`, `auto`). No resolved value at all\n // (headless, stylesheet not loaded) trusts the class.\n if (fromInline) return cells;\n const resolvedText = (csm ? String(csm.get(property) ?? \"\") : resolvedValue).trim();\n const resolved = parseFloat(resolvedText);\n const agrees = Number.isFinite(resolved)\n ? Math.abs(resolved - value.px) <= Math.abs(value.px) * 0.3\n : resolvedText === \"\";\n return agrees ? cells : undefined;\n}\n\n/** A calc term carried two ways: the engine's cells (per-unit\n * semantics) and the px the browser computes (for the active-check). */\ninterface CalcValue {\n cells: number;\n px: number;\n unitless: boolean;\n}\n\n/** Recursive-descent evaluation of `calc()` arithmetic over lengths.\n * null for anything outside the modeled units. */\nfunction evaluateCalc(\n source: string,\n key: \"width\" | \"height\",\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): CalcValue | null {\n const tokens = source.match(/--spacing\\(\\s*-?[\\d.]+\\s*\\)|calc|[\\d.]+[a-z%]*|[()+\\-*/]/g);\n if (!tokens || tokens.join(\"\").replace(/\\s+/g, \"\") !== source.replace(/\\s+/g, \"\")) return null;\n let i = 0;\n const peek = (): string | undefined => tokens[i];\n const next = (): string | undefined => tokens[i++];\n const length = (cells: number, px: number): CalcValue => ({ cells, px, unitless: false });\n const term = (token: string): CalcValue | null => {\n const spacing = /^--spacing\\(\\s*(-?[\\d.]+)\\s*\\)$/.exec(token);\n if (spacing) {\n const n = parseFloat(spacing[1]!);\n return length(n, (n * rootFontSizePx) / 4);\n }\n const match = /^([\\d.]+)([a-z%]*)$/.exec(token);\n if (!match) return null;\n const amount = parseFloat(match[1]!);\n const unit = match[2]!;\n if (!Number.isFinite(amount)) return null;\n if (unit === \"\") return { cells: amount, px: amount, unitless: true };\n if (unit === \"px\") return length(amount / (rootFontSizePx / 4), amount);\n if (unit === \"rem\") return length(amount * 4, amount * rootFontSizePx);\n const viewport = viewportLengthPx(token);\n if (viewport === null) return null;\n return length(physicalCells(viewport, key, metrics, rootFontSizePx), viewport);\n };\n const combine = (op: string, a: CalcValue, b: CalcValue): CalcValue | null => {\n if (op === \"+\" || op === \"-\") {\n if (a.unitless !== b.unitless) return null;\n const sign = op === \"+\" ? 1 : -1;\n return { cells: a.cells + sign * b.cells, px: a.px + sign * b.px, unitless: a.unitless };\n }\n if (op === \"*\") {\n if (!a.unitless && !b.unitless) return null;\n const [n, v] = a.unitless ? [a, b] : [b, a];\n return { cells: v.cells * n.cells, px: v.px * n.px, unitless: v.unitless && n.unitless };\n }\n if (!b.unitless || b.px === 0) return null;\n return { cells: a.cells / b.cells, px: a.px / b.px, unitless: a.unitless };\n };\n const factor = (): CalcValue | null => {\n const token = next();\n if (token === undefined) return null;\n if (token === \"-\") {\n const value = factor();\n return value && { cells: -value.cells, px: -value.px, unitless: value.unitless };\n }\n if (token === \"calc\") return next() === \"(\" ? group() : null;\n if (token === \"(\") return group();\n return term(token);\n };\n const group = (): CalcValue | null => {\n const value = sum();\n return next() === \")\" ? value : null;\n };\n const product = (): CalcValue | null => {\n let value = factor();\n while (value && (peek() === \"*\" || peek() === \"/\")) {\n const op = next()!;\n const rhs = factor();\n value = rhs ? combine(op, value, rhs) : null;\n }\n return value;\n };\n const sum = (): CalcValue | null => {\n let value = product();\n while (value && (peek() === \"+\" || peek() === \"-\")) {\n const op = next()!;\n const rhs = product();\n value = rhs ? combine(op, value, rhs) : null;\n }\n return value;\n };\n const result = sum();\n return i === tokens.length ? result : null;\n}\n\n/** Viewport-relative min/max limit, when one is authored. Class scan\n * (`min-h-screen`, `min-h-[95dvh]`, …) — computed values resolve\n * viewport units to plain px in every engine, so the class list is the\n * only reliable signal — active-checked against the resolved value,\n * same rules as readSize's viewport branch. undefined = not\n * viewport-relative (caller falls through to the normal readLimit). */\nfunction viewportLimit(\n csm: StylePropertyMapReadOnly | null,\n property: string,\n resolvedValue: string,\n classAttr: string,\n utilityPrefix: string,\n inlineStyle: CSSStyleDeclaration,\n metrics: CellMetrics | undefined,\n rootFontSizePx: number,\n): number | undefined {\n const key = property.endsWith(\"width\") ? \"width\" : \"height\";\n // An authored viewport string — inline style (kept verbatim in the\n // style attribute) or a computed value that survives resolution —\n // is proof in itself: no active-check needed (or possible: parsing\n // it as px would misread \"100dvh\" as 100).\n const authoredPx =\n viewportLengthPx(inlineStyle.getPropertyValue(property)) ??\n viewportLengthPx(csm?.get(property)?.toString().trim() ?? \"\");\n if (authoredPx !== null) return physicalCells(authoredPx, key, metrics, rootFontSizePx);\n // Class scan needs the active-check, same rules as readSize's\n // viewport branch.\n const scanned = viewportUtilityPx(classAttr, utilityPrefix);\n if (scanned === null) return undefined;\n const resolvedText = (csm ? String(csm.get(property) ?? \"\") : resolvedValue).trim();\n const resolved = parseFloat(resolvedText);\n const agrees = Number.isFinite(resolved) && Math.abs(resolved - scanned) <= scanned * 0.3;\n // A keyword (`none`, `auto`) is a resolved value too: the utility lost.\n if (!agrees && resolvedText !== \"\") return undefined;\n return physicalCells(agrees ? resolved : scanned, key, metrics, rootFontSizePx);\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 { leafRendererFor, renderLeafContent } from \"./leaf.ts\";\nimport type { LeafRegistration } from \"./leaf.ts\";\nimport { pxToCells } from \"./metrics.ts\";\nimport {\n isTransparentColor,\n readCellStyle,\n readOverflow,\n readTextStyle,\n trackingCells,\n} from \"./style.ts\";\nimport { defaultCellStyle, zeroInsets } from \"./types.ts\";\nimport { warnOnce } from \"./warn.ts\";\nimport {\n eachObjectMarker,\n hardLineSpans,\n INLINE_PAD,\n lineAdvance,\n OBJECT_REPLACEMENT,\n wrapLineCount,\n} from \"./wrap.ts\";\nimport type { CellMetrics, CellStyle, CharSourceRun, LayoutNode, PerSide } from \"./types.ts\";\n\n/** Per-textarea content width in cells, captured by the host BEFORE\n * the measuring attribute goes on — the engine's width rule is off\n * during measuring, so `textarea.clientWidth` read then would reflect\n * the browser-default width instead of our engine-assigned one (which\n * may itself be constrained by max-width / flex parent). */\nexport type TextareaWidths = Map<HTMLTextAreaElement, number>;\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 * - The host follows the same rule through `buildRootLeaf`\n * (specs/host-leaf.md).\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 textareaWidths?: TextareaWidths,\n): LayoutNode | null {\n const style = readCellStyle(root, rootFontSizePx, cellMetrics);\n if (style.display === \"none\") return null;\n\n // Registered leaf renderers (specs/leaf-renderers.md) supply their\n // own grid content; children are skipped entirely. The light DOM\n // stays untouched — it keeps the a11y tree and select=\"text\"\n // semantics while the grid shows the rendered content.\n const leaf = leafRendererFor(root.tagName);\n if (leaf) return buildRendererLeaf(root, style, leaf);\n\n const elementChildren = Array.from(root.children);\n const roles = elementChildren.map(childRole);\n const context = { rootFontSizePx, cellMetrics, textareaWidths };\n\n // Form controls are always leaves — descending into a <select>'s\n // <option>s would leak that text into the grid.\n if (!roles.includes(\"block\") || isFormControlTag(root.tagName)) {\n return buildLeaf(root, style, elementChildren, roles, context);\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, textareaWidths);\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\ninterface BuildContext {\n rootFontSizePx: number;\n cellMetrics: CellMetrics | undefined;\n textareaWidths: TextareaWidths | undefined;\n}\n\n/** The host's own inline content as the ROOT leaf (specs/host-leaf.md):\n * null when an element child is block-level (the host is a container)\n * or there is no inline content at all (the empty root). The metrics\n * probe is never part of the run. */\nexport function buildRootLeaf(\n host: Element,\n rootFontSizePx: number,\n cellMetrics?: CellMetrics,\n textareaWidths?: TextareaWidths,\n): LayoutNode | null {\n const nodes = Array.from(host.childNodes).filter(\n (node) => !(node instanceof Element && node.hasAttribute(\"data-mw-probe\")),\n );\n const elementChildren = nodes.filter((node): node is Element => node instanceof Element);\n const roles = elementChildren.map(childRole);\n if (roles.includes(\"block\")) return null;\n if (!hasDirectText(host) && !roles.includes(\"inline\")) return null;\n const style = rootLeafStyle(host, rootFontSizePx);\n const context = { rootFontSizePx, cellMetrics, textareaWidths };\n return buildLeaf(host, style, elementChildren, roles, context, nodes);\n}\n\n/** The root leaf's style: the virtual root's box (no padding, border,\n * margin, or size — the host's own stay outside the grid) with the\n * host's text properties. Tracking and line gap are zero by\n * definition: the host's letter-spacing and line-height ARE the cell. */\nfunction rootLeafStyle(host: Element, rootFontSizePx: number): CellStyle {\n const cs = getComputedStyle(host);\n const style = { ...defaultCellStyle(), ...readTextStyle(host, cs, rootFontSizePx) };\n // Truncation needs the clip; any other overflow stays the root's.\n if (readOverflow(cs).x === \"clip\") style.overflow = { ...style.overflow, x: \"clip\" };\n return style;\n}\n\n/** A leaf over `nodes` (the element's child nodes by default): in-flow\n * inline content forms the text run (atomic inline boxes ride it as\n * U+FFFC markers); out-of-flow children become layout nodes for the\n * positioning pass. */\nfunction buildLeaf(\n root: Element,\n style: CellStyle,\n elementChildren: Element[],\n roles: ChildRole[],\n context: BuildContext,\n nodes?: ChildNode[],\n): LayoutNode {\n const { rootFontSizePx, cellMetrics, textareaWidths } = context;\n const tag = root.tagName;\n const formControl = isFormControlTag(tag);\n const run = extractLeafRun(\n root,\n style.tracking,\n {\n rootFontSizePx,\n rootLetterSpacingPx: cellMetrics?.letterSpacing ?? 0,\n cellMetrics,\n textareaWidths,\n preserve: style.whiteSpace === \"pre\",\n tabSize: style.tabSize,\n },\n nodes,\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 // Form controls with no explicit width would otherwise be 0 cells\n // wide (their leaf is empty; the value renders natively). Intrinsic\n // widths mirror the native ones: input's size attribute, textarea's\n // cols, and a select's option labels — the longest by default, the\n // SELECTED one under `field-sizing: content`, like the browser.\n let intrinsicWidth = longestLineAdvance(text, run.advances, style.tracking);\n if (formControl && intrinsicWidth === 0) {\n // Number(): happy-dom (tests) returns these attributes as strings.\n if (tag === \"INPUT\") intrinsicWidth = Number((root as HTMLInputElement).size) || 20;\n else if (tag === \"TEXTAREA\") intrinsicWidth = Number((root as HTMLTextAreaElement).cols) || 20;\n else {\n const select = root as HTMLSelectElement;\n // .label ?? .textContent: happy-dom (tests) lacks option.label.\n const labelOf = (option: HTMLOptionElement | undefined) =>\n option?.label || option?.textContent || \"\";\n const labels =\n getComputedStyle(root).getPropertyValue(\"field-sizing\") === \"content\"\n ? [labelOf(select.selectedOptions[0])]\n : Array.from(select.options, labelOf);\n intrinsicWidth = Math.max(1, ...labels.map((label) => label.trim().length));\n }\n }\n // Form controls always reserve at least one content row (native\n // shows a caret-height field even empty). CSS `min-height` can't\n // do it — it floors the outer box, which the border already\n // exceeds.\n const contentHeight = text.length > 0 ? countHardLines(text) : 0;\n let intrinsicHeight: number;\n if (tag === \"TEXTAREA\") {\n const textarea = root as HTMLTextAreaElement;\n const value = textarea.value ?? \"\";\n // Row count = wrap the value against the textarea's current\n // content-area width in cells (captured by the host pre-\n // measuring so it reflects the engine-assigned width, not the\n // browser default that applies while measuring is on). Pure\n // and monotonic, so the box grows AND shrinks as the width\n // changes — max-w-full under viewport resize, flex reflow,\n // typing that wraps. Fallback for the first-ever layout (no\n // snapshot yet): hard-line count only.\n const contentCells = textareaWidths?.get(textarea);\n // Unlike `<br>` (whose trailing break is dropped, per CSS),\n // a textarea SHOWS the empty line after a trailing `\\n` — that\n // extra visible row is where the caret sits after Enter.\n const trailingLine = value.endsWith(\"\\n\") ? 1 : 0;\n const wrappedLines =\n contentCells !== undefined && contentCells > 0\n ? wrapLineCount(value, contentCells) + trailingLine\n : value === \"\"\n ? 0\n : value.split(/\\r\\n?|\\n/).length;\n const rowsFloor =\n getComputedStyle(root).getPropertyValue(\"field-sizing\") === \"content\"\n ? 1\n : Number(textarea.rows) || 2;\n const lines = Math.max(rowsFloor, wrappedLines);\n // Leading: N lines occupy N + (N − 1) × gap rows, same as any\n // laid-out leaf (specs/cell-model.md \"Line height on the grid\").\n intrinsicHeight = lines + Math.max(0, lines - 1) * style.lineGap;\n } else if (formControl) {\n intrinsicHeight = Math.max(1, contentHeight);\n } else {\n intrinsicHeight = contentHeight;\n }\n // `children` in DOCUMENT order: paint-order ties (same z-index)\n // resolve as CSS would — later DOM wins — and the atomic inline\n // boxes come out in U+FFFC marker order (inlineBoxesOf). Direct\n // boxes interleave with out-of-flow siblings by construction; a\n // box nested in an inline ancestor is sorted into place.\n const directBoxes = new Map<Element, LayoutNode>();\n const nestedBoxes: LayoutNode[] = [];\n for (const box of run.boxes) {\n if (box.source.parentElement === root) directBoxes.set(box.source, box);\n else nestedBoxes.push(box);\n }\n const children: LayoutNode[] = [];\n for (let i = 0; i < elementChildren.length; i++) {\n const el = elementChildren[i]!;\n const box = directBoxes.get(el);\n if (box) children.push(box);\n else if (roles[i] === \"out-of-flow\") {\n const child = buildTree(el, rootFontSizePx, cellMetrics, textareaWidths);\n if (child) children.push(child);\n }\n }\n if (nestedBoxes.length > 0) {\n children.push(...nestedBoxes);\n children.sort((a, b) =>\n a.source.compareDocumentPosition(b.source) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1,\n );\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 const charSource = charSourceRuns(run);\n if (charSource.length > 0) node.charSource = charSource;\n return node;\n}\n\n/** A registered leaf renderer's node (specs/leaf-renderers.md): the\n * renderer's lines become the leaf's preformatted text (white-space\n * styling does not apply — the lines ARE the content), and its paint\n * runs ride the existing inline-run machinery as paint-only entries\n * with neutral geometry, so the painters need no new path. */\nfunction buildRendererLeaf(\n root: Element,\n style: ReturnType<typeof readCellStyle>,\n leaf: LeafRegistration,\n): LayoutNode {\n const content = renderLeafContent(leaf, root);\n const lines = content?.lines ?? [];\n const text = lines.join(\"\\n\");\n style.whiteSpace = \"pre\";\n // Replaced-element sizing (like <img>): auto width means intrinsic,\n // not stretch — and it must live HERE, not in companion CSS, because\n // Gecko's computed styles never surface intrinsic keywords (only the\n // class scan would see a `w-max`, and a stylesheet rule has neither).\n if (style.width === undefined || style.width.kind === \"auto\") {\n style.width = { kind: \"max-content\" };\n }\n // One cell per UTF-16 unit — consistent with the run mapping below\n // (astral glyph art is out of scope; fonts are BMP in practice) —\n // plus tracking, applied uniformly so the art stretches coherently\n // (columns stay aligned across rows, like letter-spacing on a pre).\n const advances = Array.from({ length: text.length }, () => 1 + style.tracking);\n const intrinsicWidth = longestLineAdvance(text, advances, style.tracking);\n const intrinsicHeight = lines.length;\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 (style.tracking > 0) node.advances = advances;\n const runs = content?.runs ?? [];\n if (runs.length > 0 && text.length > 0) {\n // Line start offsets into the joined text (newlines included).\n const lineStart: number[] = [0];\n for (const line of lines) lineStart.push(lineStart[lineStart.length - 1]! + line.length + 1);\n const charInline = Array.from({ length: text.length }, () => -1);\n node.inlineElements = runs.map((run) => ({\n element: root,\n tracking: 0,\n padLeft: 0,\n padRight: 0,\n insets: null,\n color: run.paint.color,\n backgroundColor: run.paint.backgroundColor,\n fontWeight: run.paint.fontWeight ?? \"\",\n fontStyle: run.paint.fontStyle ?? \"\",\n textDecorationLine: run.paint.textDecorationLine ?? \"\",\n }));\n runs.forEach((run, index) => {\n const line = lines[run.line];\n if (line === undefined) return;\n const from = Math.max(0, run.start);\n const to = Math.min(line.length, run.end);\n for (let col = from; col < to; col++) charInline[lineStart[run.line]! + col] = index;\n });\n node.charInline = charInline;\n }\n return node;\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). */\ntype ChildRole = \"none\" | \"out-of-flow\" | \"inline\" | \"block\";\n\nfunction childRole(el: Element): ChildRole {\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 // Registered leaf renderers are always block participants — an\n // unstyled custom element computes to `inline`, which would fold\n // its semantic text into the parent's run instead of rendering.\n if (leafRendererFor(el.tagName)) return \"block\";\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: the source Text node and offset (`null`/-1 for\n * `<br>` newlines and markers). Compacted into `charSource` runs. */\n sourceNode: (Text | null)[];\n sourceOffset: 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 textareaWidths: TextareaWidths | 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(\n el: Element,\n tracking: number,\n ctx: RunContext,\n nodes?: ChildNode[],\n): LeafRun {\n const run: LeafRun = {\n chars: [],\n advances: [],\n sourceNode: [],\n sourceOffset: [],\n inlineIndex: [],\n inlineElements: [],\n boxes: [],\n };\n if (nodes) collectNodes(nodes, tracking, ctx, run);\n else collectRun(el, tracking, ctx, run);\n if (ctx.preserve) {\n // A final newline gets no line box of its own — the wrap layer's\n // dropFinalBreakSpan rule (the HTML parser already ate the one right\n // after the opening tag).\n return run;\n }\n return normalizeRun(run);\n}\n\nfunction collectRun(el: Element, tracking: number, ctx: RunContext, run: LeafRun): void {\n // Form controls render their value / caret / selection natively —\n // leave the leaf empty so the grid doesn't double-render, and skip\n // descending into their internals (e.g. <select>'s <option>s).\n if (isFormControlTag(el.tagName)) return;\n collectNodes(Array.from(el.childNodes), tracking, ctx, run);\n}\n\nfunction collectNodes(nodes: ChildNode[], 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 nodes) {\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 const text = node.textContent ?? \"\";\n let offset = 0;\n for (const ch of text) {\n const at = offset;\n offset += ch.length;\n if (ch === \"\\r\") {\n if (text[offset] === \"\\n\") continue; // CRLF: the LF carries the break\n pushChar(run, \"\\n\", 0, node as Text, at);\n } else if (ch === \"\\n\") {\n pushChar(run, \"\\n\", 0, node as Text, at);\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 pushChar(run, \" \", 1, node as Text, at);\n }\n } else {\n pushChar(run, ch, 1 + tracking, node as Text, at);\n }\n }\n } else {\n // Collapsible white space (space/tab/CR/LF/FF) folds to one\n // space that keeps the first collapsed character's offset.\n let offset = 0;\n let inSpace = false;\n for (const ch of node.textContent ?? \"\") {\n const collapsible =\n ch === \" \" || ch === \"\\t\" || ch === \"\\r\" || ch === \"\\n\" || ch === \"\\f\";\n if (!collapsible) pushChar(run, ch, 1 + tracking, node as Text, offset);\n else if (!inSpace) pushChar(run, \" \", 1 + tracking, node as Text, offset);\n inSpace = collapsible;\n offset += ch.length;\n }\n }\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const child = node as Element;\n if (child.tagName === \"BR\") {\n pushChar(run, \"\\n\", 0, null, -1);\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, ctx.textareaWidths);\n if (box) {\n box.inlineBox = true;\n pushChar(run, OBJECT_REPLACEMENT, 1, null, -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 backgroundColor: isTransparentColor(cs.backgroundColor) ? undefined : cs.backgroundColor,\n fontWeight: cs.fontWeight,\n fontStyle: cs.fontStyle,\n textDecorationLine: cs.textDecorationLine,\n });\n const inlineIndex = run.inlineElements.length - 1;\n // Pad cells belong to the element too (its bg must fill them).\n for (let i = 0; i < padLeft; i++) {\n run.inlineIndex[run.chars.length] = inlineIndex;\n pushChar(run, INLINE_PAD, 1, null, -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.inlineIndex[run.chars.length] = inlineIndex;\n pushChar(run, INLINE_PAD, 1, null, -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 sourceNode: (Text | null)[] = [];\n const sourceOffset: 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 sourceNode.pop();\n sourceOffset.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 sourceNode.push(run.sourceNode[i] ?? null);\n sourceOffset.push(run.sourceOffset[i] ?? -1);\n inlineIndex.push(run.inlineIndex[i] ?? -1);\n }\n trimLineEnd();\n // Edge `\\n`s stay: every leading <br> creates a line box and all but\n // the final trailing one do (probed, all engines) — the wrap layer\n // drops exactly that last one (dropFinalBreakSpan).\n return {\n chars,\n advances,\n sourceNode,\n sourceOffset,\n inlineIndex,\n inlineElements: run.inlineElements,\n boxes: run.boxes,\n };\n}\n\nfunction pushChar(run: LeafRun, ch: string, advance: number, source: Text | null, offset: number) {\n run.chars.push(ch);\n run.advances.push(advance);\n run.sourceNode.push(source);\n run.sourceOffset.push(offset);\n}\n\n/** Compact the per-character source map into runs (`LayoutNode.charSource`):\n * a run grows while the next character continues the same Text node at\n * the next offset. */\nfunction charSourceRuns(run: LeafRun): CharSourceRun[] {\n const runs: CharSourceRun[] = [];\n let index = 0;\n for (let i = 0; i < run.chars.length; i++) {\n const ch = run.chars[i]!;\n const node = run.sourceNode[i];\n const offset = run.sourceOffset[i]!;\n const last = runs[runs.length - 1];\n if (node) {\n if (last && last.node === node && last.offset + last.length === offset)\n last.length += ch.length;\n else runs.push({ index, length: ch.length, node, offset });\n }\n index += ch.length;\n }\n return runs;\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 hardLineSpans(text).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/** True if `el` has any direct text child that isn't just whitespace. */\nexport function hasDirectText(el: Element): boolean {\n return Array.from(el.childNodes).some(\n (child) => child.nodeType === Node.TEXT_NODE && /[^ \\t\\r\\n\\f]/.test(child.textContent ?? \"\"),\n );\n}\n\n/** Author-facing warning when direct text can't be laid out alongside\n * block children — shared by the nested-container path here and the\n * host-level path in element.ts. */\nexport const DIRECT_TEXT_DROPPED =\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/** True for tags whose value/caret/selection are handled by the browser\n * natively — the tree builder treats them as empty leaves. */\nexport function isFormControlTag(tag: string): boolean {\n return tag === \"INPUT\" || tag === \"SELECT\" || tag === \"TEXTAREA\";\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 if (!hasDirectText(el)) return;\n node.droppedText = true;\n warnOnce(el, DIRECT_TEXT_DROPPED);\n}\n","import { hasSynthesizedTransitions, resolvePendingTransitions } from \"./animate.ts\";\nimport { onGlyphRegistryChange } from \"./glyphs.ts\";\nimport { leafObservedAttributes, leafRendererFor, onLeafRegistryChange } from \"./leaf.ts\";\nimport { arrowIsNative, directionOf, extentOf, focusableRects, nextFocus } from \"./focus.ts\";\nimport { hitChain, hitStack, isInert } from \"./pointer.ts\";\nimport { charIndexAtCell, renderPlainText, scrollbarGeometry, thumbSpan } from \"./plain-text.ts\";\nimport {\n classifySelection,\n comparePoints,\n isTextLeaf,\n leafExtent,\n positionOf,\n selectionRangeThrough,\n serializeSelection,\n wordAt,\n} from \"./selection.ts\";\nimport type { BoundaryPoints } from \"./selection.ts\";\nimport { nodeAtOffset, paintGrid } from \"./paint.ts\";\nimport { getRootFontSizePx, measureCellMetrics } from \"./metrics.ts\";\nimport { layoutRoot } from \"./layout.ts\";\nimport { render } from \"./render.ts\";\nimport { buildRootLeaf, buildTree, DIRECT_TEXT_DROPPED, hasDirectText } from \"./tree.ts\";\nimport type { TextareaWidths } from \"./tree.ts\";\nimport { defaultCellStyle, zeroInsets } from \"./types.ts\";\nimport { warnSubject } from \"./warn.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%; background: inherit; }\n /* The slot as a positioned box: the light DOM paints ABOVE the grid\n * (the elements are absolute; the host's own in-flow text, specs/host-leaf.md,\n * would otherwise sit under the <pre> and lose its selection ink) and\n * laid-out elements position against it — the same origin as #viewport. */\n slot { display: block; position: relative; }\n /* The host's own dropped direct text (specs/cell-model.md deviation 7)\n * hides through the slot; laid-out children re-declare visible in\n * styles.css. */\n :host([data-mw-dropped-text]) slot { visibility: hidden; }\n /* The unified grid: one <pre> with same-paint-run spans, cell-precise\n * (one monospace character = one cell). In select=\"grid\" (the\n * default, reflected onto the attribute — see DEFAULT_SELECT) the\n * grid catches drags for native selection of the ASCII; interactive\n * elements opt back into pointer-events via styles.css so clicks\n * still work. In select=\"text\" the grid is inert to events and drag\n * selects the light DOM natively. */\n /* Sized by the engine's ink extent (element.ts), not the host box:\n * visible overflow paints past the host (specs/cell-model.md\n * \"Overflow\"), and the host's background follows it there — the\n * host is the canvas, as the root element's background covers a\n * document's overflow — inherited through #viewport, the shadow\n * parent. (A translucent host background paints repeatedly inside\n * the box.) */\n /* The text-fill reset: the host's own invisibility lock (specs/host-leaf.md)\n * inherits across the shadow boundary; currentColor stays a keyword\n * at computed time, so every run keeps its own color. */\n #grid { position: absolute; top: 0; left: 0; margin: 0; background: inherit; font: inherit; line-height: inherit; letter-spacing: inherit; white-space: pre; pointer-events: none; user-select: none; -webkit-user-select: none; -webkit-text-fill-color: currentColor; }\n :host([select=\"grid\"]) #grid { pointer-events: auto; user-select: text; -webkit-user-select: text; }\n :host([select=\"grid\"]) slot { pointer-events: none; user-select: none; -webkit-user-select: none; }\n /* A live semantic selection (specs/semantic-selection.md) lifts the\n * lock so the element selection copies; pointer events stay off. */\n :host([select=\"grid\"][data-mw-semantic-selection]) slot { user-select: text; -webkit-user-select: text; }\n /* Selection invert — mirror of the canonical rule in styles.css\n * (which explains the field choices); update together. */\n ::selection { color: var(--mw-bg, canvas); text-shadow: 0 0 0 var(--mw-bg, canvas); background: var(--mw-fg, canvastext); }\n</style>\n<div id=\"viewport\">\n <pre id=\"grid\" aria-hidden=\"true\"></pre>\n <slot></slot>\n</div>\n`;\n\n/** The `select` attribute's default, reflected onto the attribute when\n * it is absent or unrecognized so every stylesheet keys on an explicit\n * value — the single place the default lives. */\nconst DEFAULT_SELECT = \"grid\";\n\n/** The `focus` attribute's default (specs/focus-navigation.md): Tab\n * alone moves focus; `focus=\"arrows\"` adds arrow-key navigation.\n * Reflected like `select`. */\nconst DEFAULT_FOCUS = \"tab\";\n\n/** Set on the host while an element selection made by a semantic\n * gesture is live (specs/semantic-selection.md): the shadow stylesheet\n * lifts the grid-mode user-select lock under it. */\nconst SEMANTIC_SELECTION = \"data-mw-semantic-selection\";\n\ninterface Point {\n node: Node;\n offset: number;\n}\n\n/** A selectable unit — a word's or paragraph's DOM range. */\ninterface SelectionUnit {\n start: Point;\n end: Point;\n}\n\ninterface SemanticGesture {\n unit: \"word\" | \"paragraph\";\n anchor: SelectionUnit;\n}\n\n/** Light elements that legitimately receive pointer events in grid\n * mode — the styles.css opt-in list. Any other light target got the\n * event by a browser quirk (Firefox hit-tests a multicol spanner's\n * anonymous wrapper as its container despite pointer-events: none)\n * and is handled as a grid event at the same coordinates. */\nconst INTERACTIVE = \"a, button, input, select, textarea, label, [tabindex], [role='button']\";\n\nconst DYNAMIC_RELAYOUT_EVENTS = [\n \"pointerover\",\n \"pointerleave\",\n // `:active` styles (`active:opacity-50`) need a repaint on both edges\n // of a press — pointer and keyboard (Space/Enter activation).\n \"pointerdown\",\n \"pointerup\",\n \"pointercancel\",\n \"keydown\",\n \"keyup\",\n \"focusin\",\n \"focusout\",\n \"input\",\n \"change\",\n] as const;\n\n/** Transition properties the engine SAMPLES per animation frame (the\n * grid repaints with true mid-fade values): computed `color` stays live\n * under the text-fill lock, and nothing locks border colors or opacity.\n * Lock-owned properties (backgrounds, decoration color, geometry) are\n * snapped by the measuring/settling `transition-property` allow-list\n * instead — keep the two in sync (styles.css \"Lock toggles must\n * never…\"). */\nconst SAMPLED_TRANSITION = /^(color|opacity|border-(top|right|bottom|left)-color|border-color)$/;\n\n/** Safety valve for the sampling loop: a transition whose end/cancel\n * event never arrives (subtree torn down mid-fade) must not pin a rAF\n * loop forever. */\nconst SAMPLING_VALVE_MS = 30_000;\n\n/* Wheel-gesture model (specs/scrolling.md \"Gesture latching\"). */\n/** Ticks further apart than this begin a new gesture — and settle. */\nconst WHEEL_QUIESCE_MS = 200;\n/** Pointer jitter that still counts as stationary. */\nconst WHEEL_POINTER_SLOP_PX = 3;\n/** An undecided first tick this small is eaten, not latched. */\nconst WHEEL_LEAD_IN_PX = 4;\n/** Non-increasing ticks that confirm momentum. */\nconst INERTIA_TICKS = 8;\n/** Settle only once scrolling has gone QUIET after `scrollend`: a held\n * key fires scrollend after every step's animation, and an immediate\n * (instant) settle would cut the next step's animation short. */\nconst SETTLE_QUIESCE_MS = 100;\n/** Settle debounce where `scrollend` is missing (older Safari). */\nconst SETTLE_FALLBACK_MS = 160;\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 = [\"select\", \"focus\"];\n\n // Stylesheets can apply after a host's first layout (vite dev\n // injection, the CDN's in-browser Tailwind compile, HMR) — a pure\n // <head> mutation no per-host observer sees, which would otherwise\n // leave UA-styled geometry until an unrelated trigger. One shared\n // watcher relayouts every connected host on any head change (rare, and\n // relayout coalesces per frame); a still-loading <link> applies its CSS\n // at load time, so those get a one-shot listener too.\n static #headHosts = new Set<MonoWindElement>();\n static #headWatcher: MutationObserver | null = null;\n\n static #onHeadStylesChanged = (): void => {\n for (const host of MonoWindElement.#headHosts) host.#scheduleLayout();\n };\n\n static #watchLoadingLink(node: Node): void {\n if (node instanceof HTMLLinkElement && node.rel === \"stylesheet\" && !node.sheet) {\n node.addEventListener(\"load\", MonoWindElement.#onHeadStylesChanged, { once: true });\n }\n }\n\n static #watchHead(host: MonoWindElement): void {\n MonoWindElement.#headHosts.add(host);\n if (MonoWindElement.#headWatcher) return;\n // Stylesheets already in flight when the first host connects apply\n // without any head mutation — catch their loads too.\n for (const link of document.querySelectorAll(\"link[rel=stylesheet]\")) {\n MonoWindElement.#watchLoadingLink(link);\n }\n const watcher = new MutationObserver((records) => {\n for (const record of records) {\n for (const node of record.addedNodes) MonoWindElement.#watchLoadingLink(node);\n }\n MonoWindElement.#onHeadStylesChanged();\n });\n watcher.observe(document.head, { childList: true, subtree: true, characterData: true });\n MonoWindElement.#headWatcher = watcher;\n }\n\n static #unwatchHead(host: MonoWindElement): void {\n MonoWindElement.#headHosts.delete(host);\n if (MonoWindElement.#headHosts.size === 0) {\n MonoWindElement.#headWatcher?.disconnect();\n MonoWindElement.#headWatcher = null;\n }\n }\n\n #shadow: ShadowRoot;\n #grid: 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 #unsubscribeLeafRegistry: (() => void) | null = null;\n #unsubscribeGlyphRegistry: (() => void) | null = null;\n #paintPending = false;\n /** Scroll containers of the LAST layout (specs/scrolling.md). */\n #scrollNodes: LayoutNode[] = [];\n #settleTimers = new Map<Element, ReturnType<typeof setTimeout>>();\n /** Last routed-wheel activity per scroll container: each scrollBy is a separate\n * PROGRAMMATIC scroll, so the browser fires scrollend between wheel\n * ticks — mid-gesture settles would keep snapping small deltas back\n * (the \"resistance\"). Recent activity suppresses them; the wheel\n * quiesce timer settles instead. */\n #routedWheelAt = new WeakMap<Element, number>();\n /** What the current wheel gesture is LATCHED to — a scroll container, or the\n * page (`el: null`): chaining is a gesture-START decision (native\n * scroll-chaining semantics), so mid-gesture boundary hits stay on\n * the scroll container and a scroll container sliding under the pointer never captures a\n * page gesture. `mag`/`decayed` track the delta trend (see\n * #onWheel). */\n #wheelLatch: WheelLatch | null = null;\n #thumbDrag: ThumbDrag | null = null;\n /** The last primary pointerdown's type: a `mousedown` counts as a\n * semantic gesture only after a mouse or pen (a tap's compatibility\n * mousedown follows a touch pointerdown). */\n #lastPointerType = \"\";\n #semanticGesture: SemanticGesture | null = null;\n /** An engine-driven grid drag, anchored at a flat text offset: the\n * fallback when a plain mousedown lands on a phantom light target\n * (see INTERACTIVE), where no native selection can start. */\n #gridDrag: { anchor: number } | null = null;\n /** A primary press that landed on the grid: the first pointermove with\n * the button down marks the host `data-mw-dragging`, which drops\n * interactive light elements' pointer events so a native drag sweeps\n * through their cells instead of stalling at their edge. */\n #pressOnGrid = false;\n /** Native scrollers outside the host (ancestors with scrollable\n * overflow, then the page), collected per layout so a wheel tick\n * never reads computed styles (see #outsideCanScroll). */\n #outerScrollers: Element[] = [];\n\n /** (Re-)observe the light DOM; re-run when the leaf registry adds\n * observed attributes to the filter. `observe` on the same target\n * replaces the previous options in place. */\n #observeLightDom(): void {\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 // leaf renderers declare theirs at registration.\n attributeFilter: [\n \"class\",\n \"style\",\n \"colspan\",\n \"rowspan\",\n \"span\",\n ...leafObservedAttributes(),\n ],\n });\n }\n\n constructor() {\n super();\n this.#shadow = this.attachShadow({ mode: \"open\" });\n this.#shadow.innerHTML = SHADOW_TEMPLATE;\n this.#grid = this.#shadow.getElementById(\"grid\") 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 // attributeChangedCallback only fires on changes; an absent\n // attribute reflects its default here.\n if (!this.hasAttribute(\"select\")) this.setAttribute(\"select\", DEFAULT_SELECT);\n if (!this.hasAttribute(\"focus\")) this.setAttribute(\"focus\", DEFAULT_FOCUS);\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 this.#observeSurroundings();\n // The probe too: a freshly inserted probe can transiently font-match\n // the FALLBACK at first layout even when the real font is already\n // loaded (WebKit; no fonts event ever follows). The swap changes the\n // probe's size, so observing it is the missing re-measure signal.\n // (The probe is absolutely positioned, hence blockified — inline\n // boxes would be unobservable.)\n this.#resizeObserver.observe(this.#probe);\n // Viewport-relative lengths (h-screen, h-[95dvh], …) read\n // window.innerWidth/Height at layout time; a window resize that\n // doesn't change the HOST's size (height-only, typically) would\n // otherwise never retrigger them.\n window.addEventListener(\"resize\", this.#onWindowResize);\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.#observeLightDom();\n // Leaf renderers (specs/leaf-renderers.md): a registration or\n // invalidation after this host's first layout must repaint it, and\n // new observed attributes must join the filter.\n this.#unsubscribeLeafRegistry = onLeafRegistryChange(() => {\n this.#observeLightDom();\n this.#scheduleLayout();\n });\n this.#unsubscribeGlyphRegistry = onGlyphRegistryChange(() => this.#scheduleLayout());\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 // Pseudo-classes (:hover/:focus-visible/:active) and form-control\n // value changes flip computed styles without any MutationObserver\n // signal. Delegated events on the host schedule a relayout; the\n // rAF debouncer collapses hover storms into at most one per frame.\n for (const evt of DYNAMIC_RELAYOUT_EVENTS) {\n this.addEventListener(evt, this.#scheduleDynamicRelayout);\n }\n\n // Animation sampling (specs/cell-model.md \"Animation\"): a running\n // transition of a sampled property re-lays-out every frame, so the\n // grid repaints with the browser's own interpolated values.\n this.addEventListener(\"transitionrun\", this.#onTransitionRun);\n this.addEventListener(\"transitionend\", this.#onTransitionDone);\n this.addEventListener(\"transitioncancel\", this.#onTransitionDone);\n\n // Synthesized pointer states (specs/cell-model.md \"Pointer\n // states\"): under select=\"grid\" the light DOM is pointer-events:\n // none, so :hover/:active can't match — the engine hit-tests the\n // pointer's cell and marks the chain with data-mw-hover /\n // data-mw-active (utilities.css retargets the Tailwind variants).\n this.addEventListener(\"pointermove\", this.#onPointerMove);\n this.addEventListener(\"pointerleave\", this.#onPointerLeave);\n this.addEventListener(\"pointerdown\", this.#onPointerDown);\n // Scroll events don't bubble — capture catches every light-DOM\n // container's scroll (specs/scrolling.md).\n this.addEventListener(\"scroll\", this.#onScroll, { capture: true, passive: true });\n this.addEventListener(\"scrollend\", this.#onScrollEnd, { capture: true });\n this.addEventListener(\"wheel\", this.#onWheel, { passive: false });\n // A selection in the light DOM copies as the engine's plain text\n // (specs/semantic-selection.md): the browsers' serializers lose\n // block breaks for the out-of-flow boxes the render uses.\n this.addEventListener(\"copy\", this.#onCopy);\n // Multi-click gestures (specs/semantic-selection.md): the click\n // count rides mousedown (PointerEvent.detail is 0).\n this.addEventListener(\"mousedown\", this.#onMouseDown);\n this.addEventListener(\"keydown\", this.#onKeyDown);\n document.addEventListener(\"selectionchange\", this.#onSelectionChange);\n // Release on the window: a selection drag routinely ends outside\n // the host, and the press state must thaw wherever it ends.\n window.addEventListener(\"pointerup\", this.#onPointerUp);\n window.addEventListener(\"pointercancel\", this.#onPointerUp);\n // Content scrolling under a stationary pointer moves cells beneath\n // it — native :hover re-evaluates there, so the synthesis must\n // too. Capture catches nested scrollers (scroll doesn't bubble).\n document.addEventListener(\"scroll\", this.#onAnyScroll, { capture: true, passive: true });\n\n MonoWindElement.#watchHead(this);\n this.#scheduleLayout();\n }\n\n disconnectedCallback(): void {\n window.removeEventListener(\"resize\", this.#onWindowResize);\n this.#resizeObserver?.disconnect();\n this.#mutationObserver?.disconnect();\n this.#resizeObserver = null;\n this.#mutationObserver = null;\n this.#unsubscribeLeafRegistry?.();\n this.#unsubscribeLeafRegistry = null;\n this.#unsubscribeGlyphRegistry?.();\n this.#unsubscribeGlyphRegistry = null;\n document.fonts?.removeEventListener(\"loadingdone\", this.#onFontsLoaded);\n for (const evt of DYNAMIC_RELAYOUT_EVENTS) {\n this.removeEventListener(evt, this.#scheduleDynamicRelayout);\n }\n this.removeEventListener(\"transitionrun\", this.#onTransitionRun);\n this.removeEventListener(\"transitionend\", this.#onTransitionDone);\n this.removeEventListener(\"transitioncancel\", this.#onTransitionDone);\n this.#activeTransitions = 0;\n this.removeEventListener(\"pointermove\", this.#onPointerMove);\n this.removeEventListener(\"pointerleave\", this.#onPointerLeave);\n this.removeEventListener(\"pointerdown\", this.#onPointerDown);\n this.removeEventListener(\"scroll\", this.#onScroll, { capture: true });\n this.removeEventListener(\"scrollend\", this.#onScrollEnd, { capture: true });\n this.removeEventListener(\"wheel\", this.#onWheel);\n this.removeEventListener(\"copy\", this.#onCopy);\n this.removeEventListener(\"keydown\", this.#onKeyDown);\n this.removeEventListener(\"mousedown\", this.#onMouseDown);\n document.removeEventListener(\"selectionchange\", this.#onSelectionChange);\n for (const timer of this.#settleTimers.values()) clearTimeout(timer);\n this.#settleTimers.clear();\n this.#thumbDrag = null;\n this.#wheelLatch = null;\n window.removeEventListener(\"pointerup\", this.#onPointerUp);\n window.removeEventListener(\"pointercancel\", this.#onPointerUp);\n document.removeEventListener(\"scroll\", this.#onAnyScroll, { capture: true });\n this.#hoverClient = null;\n this.#pressTarget = null;\n this.#pressing = false;\n this.#paintHeld = false;\n this.#updatePointerStates();\n MonoWindElement.#unwatchHead(this);\n }\n\n /* === Synthesized pointer states ==================================== */\n\n #hovered = new Set<Element>();\n #pressed = new Set<Element>();\n #pressTarget: Element | null = null;\n #pressing = false;\n #paintHeld = false;\n #hoverClient: { x: number; y: number } | null = null;\n #hoverCol = NaN;\n #hoverRow = NaN;\n #gridOrigin: { left: number; top: number } | null = null;\n static #hoverCapable = typeof matchMedia === \"undefined\" ? null : matchMedia(\"(hover: hover)\");\n\n /** Paint-only pass (specs/scrolling.md): reruns paintGrid from the\n * last layout with current scroll offsets — no measuring, no\n * layout. Scroll events coalesce into one frame. */\n #schedulePaint(): void {\n // A queued layout repaints (and re-syncs offsets) itself.\n if (this.#paintPending || this.#layoutPending) return;\n this.#paintPending = true;\n // rAF, with a timeout backstop: headless/backgrounded Firefox can\n // throttle rAF into never firing, freezing scroll mirroring.\n let done = false;\n const run = (): void => {\n if (done) return;\n done = true;\n this.#paintPending = false;\n const metrics = this.#cellMetrics;\n if (!this.isConnected || !this.#lastLayout || !metrics) return;\n this.#syncScrollOffsets(metrics);\n this.#paintHeld = !paintGrid(this.#lastLayout, this.#grid, this.#holdsNativeDrag());\n // The cells under a stationary pointer changed with the scroll.\n this.#updatePointerStates();\n };\n requestAnimationFrame(run);\n setTimeout(run, 50);\n }\n\n /** Per-container offsets for the paint: from the pre-mask snapshot during\n * a layout pass (native reads are clamped inside the mask; pins\n * resolve to the NEW max), from the live position on a scroll\n * repaint. */\n #syncScrollOffsets(metrics: CellMetrics, snapshot?: ScrollSnapshot): void {\n for (const node of this.#scrollNodes) {\n const el = node.source as HTMLElement;\n const { maxX, maxY } = node.scrollRange!;\n const entry = snapshot?.get(el);\n node.scroll = entry\n ? {\n x: entry.pinX ? maxX : Math.min(entry.x, maxX),\n y: entry.pinY ? maxY : Math.min(entry.y, maxY),\n }\n : this.#quantize(node, metrics);\n }\n }\n\n /** A container's native position in cells (see scrollCells), ties\n * broken away from the last painted offset. */\n #quantize(node: LayoutNode, metrics: CellMetrics): { x: number; y: number } {\n const el = node.source as HTMLElement;\n const { maxX, maxY } = node.scrollRange!;\n const base = node.scroll ?? { x: 0, y: 0 };\n return {\n x: scrollCells(el, \"x\", metrics.width, maxX, base.x),\n y: scrollCells(el, \"y\", metrics.height, maxY, base.y),\n };\n }\n\n /** Snapshot of every scroll container's native position, taken BEFORE the\n * measuring mask goes on: the mask collapses container geometry (the\n * range spacer is off) and browsers clamp native positions during\n * that reflow — Chromium eagerly, Firefox lazily — so any read inside\n * the pass is wrong. Bottom-stick rides along: a scroll container settled at a\n * real end (pre-layout max > 0) re-pins to the NEW max. */\n #captureScrollState(): ScrollSnapshot {\n const snapshot: ScrollSnapshot = new Map();\n const metrics = this.#cellMetrics;\n if (!metrics) return snapshot;\n for (const node of this.#scrollNodes) {\n const el = node.source as HTMLElement;\n const { maxX, maxY } = node.scrollRange!;\n const { x, y } = this.#quantize(node, metrics);\n snapshot.set(el, {\n top: el.scrollTop,\n left: el.scrollLeft,\n x,\n y,\n pinX: maxX > 0 && x >= maxX,\n pinY: maxY > 0 && y >= maxY,\n });\n }\n return snapshot;\n }\n\n /** Write the snapshot back after the unmask (pins to the native\n * ceiling — the new max). Firefox and WebKit hold post-reflow scroll\n * clamping in a lazy state where a write that looks like the\n * pre-clamp value coalesces with the pending clamp into \"no\n * change\" — no scroll event, and the container desyncs. Reading\n * FIRST commits the clamp, so the write is a real change (same-value\n * writes are no-ops). */\n #restoreScrollPositions(snapshot: ScrollSnapshot): void {\n for (const node of this.#scrollNodes) {\n const el = node.source as HTMLElement;\n const entry = snapshot.get(el);\n if (!entry) continue;\n void el.scrollTop;\n void el.scrollLeft;\n el.scrollTop = entry.pinY ? el.scrollHeight : entry.top;\n el.scrollLeft = entry.pinX ? el.scrollWidth : entry.left;\n }\n }\n\n /** Arm (or re-arm) a pane's settle for after `delay` of quiet. */\n #settleAfter(el: HTMLElement, delay: number): void {\n clearTimeout(this.#settleTimers.get(el));\n this.#settleTimers.set(\n el,\n setTimeout(() => this.#settle(el), delay),\n );\n }\n\n #onScroll = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof HTMLElement) || target === this) return;\n if (!target.hasAttribute(\"data-mw-scroll\")) return;\n this.#schedulePaint();\n // Routed wheel ticks keep their own quiesce timer (#onWheel).\n if (Date.now() - (this.#routedWheelAt.get(target) ?? 0) < WHEEL_QUIESCE_MS) return;\n // Still scrolling: a pending settle waits; without scrollend\n // (older Safari) the pause after the last event settles instead.\n clearTimeout(this.#settleTimers.get(target));\n if (!(\"onscrollend\" in window)) this.#settleAfter(target, SETTLE_FALLBACK_MS);\n };\n\n #onScrollEnd = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof HTMLElement) || target === this) return;\n if (!target.hasAttribute(\"data-mw-scroll\")) return;\n // Mid-gesture scrollends: routed wheel ticks and thumb drags\n // settle on quiesce/release instead (see #routedWheelAt).\n if (Date.now() - (this.#routedWheelAt.get(target) ?? 0) < WHEEL_QUIESCE_MS) return;\n this.#settleAfter(target, SETTLE_QUIESCE_MS);\n };\n\n /** Snap the native position to the cell the grid already SHOWS\n * (the same quantization as the paint) — never a different cell,\n * or the grid would visibly jump after the gesture. Idempotent: its\n * own scroll event changes no cell. The max cell settles on the\n * native CEILING, not the multiple: leftover native room would\n * latch the next text-mode gesture to an invisible scroll instead\n * of chaining. */\n #settle(el: HTMLElement): void {\n if (this.#thumbDrag?.el === el) return; // release settles\n // Repaint unconditionally: scroll events can coalesce away under\n // load (observed in Firefox), and the settle is the gesture's\n // reliable terminal signal — a current grid makes this a no-op.\n this.#schedulePaint();\n const metrics = this.#cellMetrics;\n const node = this.#scrollNodes.find((candidate) => candidate.source === el);\n if (!metrics || !node) return;\n const range = node.scrollRange!;\n // The painted cell: the settle lands where the grid already is.\n const cells = node.scroll ?? this.#quantize(node, metrics);\n const top =\n cells.y === range.maxY ? el.scrollHeight - el.clientHeight : cells.y * metrics.height;\n const left = cells.x === range.maxX ? el.scrollWidth - el.clientWidth : cells.x * metrics.width;\n if (Math.abs(el.scrollTop - top) > 0.5 || Math.abs(el.scrollLeft - left) > 0.5) {\n el.scrollTo({ top, left, behavior: \"instant\" });\n }\n }\n\n /** Grid-mode wheel routing (specs/scrolling.md): the light DOM is\n * pointer-inert, so the engine hit-tests the cell and scrolls the\n * nearest consuming container — chaining OUTWARD per axis, since\n * programmatic scrollBy never chains natively. preventDefault only\n * for ticks a scroll container owns, so page scrolling survives. */\n #onWheel = (event: Event): void => {\n if (this.getAttribute(\"select\") !== \"grid\") return;\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n if (!layout || !metrics || this.#scrollNodes.length === 0) return;\n const e = event as WheelEvent;\n const scale = e.deltaMode === 1 ? metrics.height : e.deltaMode === 2 ? this.clientHeight : 1;\n const dx = e.deltaX * scale;\n const dy = e.deltaY * scale;\n // Chromium marks every tick after an uncanceled first one in a\n // native scroll sequence non-cancelable: the page owns that\n // gesture — unless nothing outside the host can scroll that way,\n // where routing is the only thing the tick can usefully do.\n if (!e.cancelable && this.#outsideCanScroll(dx, dy)) return;\n const { col, row } = this.#cellAt(e.clientX, e.clientY, metrics);\n const now = Date.now();\n const mag = Math.abs(dx) + Math.abs(dy);\n // Zero-delta ticks mark gesture phases (Safari's, and Chromium's\n // momentum cancel when a finger lands mid-inertia): a boundary.\n // Canceled, so a sequence they open stays cancelable.\n if (mag === 0) {\n this.#wheelLatch = null;\n e.preventDefault();\n return;\n }\n // Native room decides (the native ceiling IS the engine's max);\n // an axis without engine range never consumes.\n const canMove = (node: LayoutNode): boolean => {\n const range = node.scrollRange!;\n const el = node.source as HTMLElement;\n if (dy !== 0 && range.maxY > 0) {\n if (\n (dy > 0 && el.scrollTop < el.scrollHeight - el.clientHeight - 0.5) ||\n (dy < 0 && el.scrollTop > 0.5)\n )\n return true;\n }\n if (dx !== 0 && range.maxX > 0) {\n if (\n (dx > 0 && el.scrollLeft < el.scrollWidth - el.clientWidth - 0.5) ||\n (dx < 0 && el.scrollLeft > 0.5)\n )\n return true;\n }\n return false;\n };\n // Gesture boundaries without native phase info: a gesture ends\n // when ticks quiesce or the delta RISES after confirmed inertia —\n // momentum never rises (it often repeats a delta: 3, 3, 2, 2, 1…),\n // finger ticks wobble — so a scroll container at its end hands a new push to\n // the page instead of blocking until the inertia dies. Confirmed\n // inertia STICKS: a new push usually starts below the momentum it\n // interrupts, and only its second tick rises. Momentum follows the\n // pointer (its ticks land wherever the cursor went), so after a\n // move a same-axis tick that continues the decay is still the old\n // gesture; any rise or a new dominant axis is the new one.\n const latch = this.#wheelLatch;\n const axis = Math.abs(dx) >= Math.abs(dy) ? \"x\" : \"y\";\n const rise = latch !== null && mag > latch.mag * 1.25 + 1;\n const moved =\n latch !== null &&\n (Math.abs(e.clientX - latch.x) > WHEEL_POINTER_SLOP_PX ||\n Math.abs(e.clientY - latch.y) > WHEEL_POINTER_SLOP_PX);\n const inertia = latch !== null && latch.decayed >= INERTIA_TICKS;\n const held =\n latch !== null &&\n now - latch.at < WHEEL_QUIESCE_MS &&\n axis === latch.axis &&\n (moved ? mag <= latch.mag : !(inertia && rise));\n let target: LayoutNode | null = null;\n if (held) {\n const smooth = mag <= latch.mag && mag >= latch.mag * 0.5;\n latch.decayed = smooth ? latch.decayed + 1 : inertia ? latch.decayed : 0;\n latch.mag = mag;\n latch.at = now;\n if (!latch.el) return; // the page's gesture\n target = this.#scrollNodes.find((node) => node.source === latch.el) ?? null;\n }\n if (!target) {\n const stack = hitStack(layout, col, row);\n for (let i = stack.length - 1; i >= 0; i--) {\n const node = stack[i]!.node;\n if (!node.scrollRange || isInert(node.source)) continue;\n if (canMove(node)) {\n target = node;\n break;\n }\n // At its boundary already: chain outward only if this scroll container's\n // overscroll-behavior allows it on the gesture's axis.\n const overscroll = node.style.overscroll;\n if ((dy !== 0 && !overscroll.y) || (dx !== 0 && !overscroll.x)) {\n target = node; // contain/none: the gesture stays here, inert\n break;\n }\n }\n // A swipe's first tick often carries only a tiny cross-axis\n // delta; over a scroll container that cannot consume it, it decides nothing\n // yet: eaten (keeping the sequence cancelable), unlatched — the\n // next, decisive tick picks the scroll container.\n if (!target && mag < WHEEL_LEAD_IN_PX) {\n e.preventDefault();\n return;\n }\n this.#wheelLatch = {\n el: target ? (target.source as HTMLElement) : null,\n x: e.clientX,\n y: e.clientY,\n axis,\n at: now,\n mag,\n decayed: 0,\n };\n }\n if (!target) return; // the page's gesture\n e.preventDefault();\n if (!canMove(target)) return; // latched at the boundary: consume, no chain\n const el = target.source as HTMLElement;\n const range = target.scrollRange!;\n const apply: ScrollToOptions = { behavior: \"instant\" };\n if (dy !== 0 && range.maxY > 0) apply.top = dy;\n if (dx !== 0 && range.maxX > 0) apply.left = dx;\n el.scrollBy(apply);\n // One gesture, not N programmatic scrolls: suppress the per-tick\n // scrollend settles and settle after quiesce.\n this.#routedWheelAt.set(el, now);\n this.#settleAfter(el, WHEEL_QUIESCE_MS);\n };\n\n /** Whether a native scroller outside the host has room in the\n * delta's direction (offset reads only — the list is per layout). */\n #outsideCanScroll(dx: number, dy: number): boolean {\n return this.#outerScrollers.some(\n (el) =>\n (dy > 0 && el.scrollTop < el.scrollHeight - el.clientHeight - 0.5) ||\n (dy < 0 && el.scrollTop > 0.5) ||\n (dx > 0 && el.scrollLeft < el.scrollWidth - el.clientWidth - 0.5) ||\n (dx < 0 && el.scrollLeft > 0.5),\n );\n }\n\n /** The host's width is capped to whole cells (styles.css), so a\n * growing slot no longer resizes the host: observe the parent (a\n * growing container) and the siblings (a flex or grid slot that\n * grows because a sibling shrank). Re-run per layout — observe() is\n * idempotent, and new siblings join. */\n #observeSurroundings(): void {\n const parent = this.parentElement;\n if (!parent || !this.#resizeObserver) return;\n this.#resizeObserver.observe(parent);\n for (const sibling of parent.children) {\n if (sibling !== this) this.#resizeObserver.observe(sibling);\n }\n }\n\n /** The grid cell under a client point. The origin is cached until\n * the next layout or page scroll invalidates it. */\n #cellAt(clientX: number, clientY: number, metrics: CellMetrics): { col: number; row: number } {\n if (!this.#gridOrigin) {\n const rect = this.#grid.getBoundingClientRect();\n this.#gridOrigin = { left: rect.left, top: rect.top };\n }\n return {\n col: Math.floor((clientX - this.#gridOrigin.left) / metrics.width),\n row: Math.floor((clientY - this.#gridOrigin.top) / metrics.height),\n };\n }\n\n /** A pointerdown on a visible gutter bar begins a thumb drag —\n * engine-routed in BOTH modes (the gutter is grid ink; there is no\n * native scrollbar). Proportional: the draggable track maps onto\n * the scroll range. */\n #gutterDragAt(clientX: number, clientY: number): ThumbDrag | null {\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n if (!layout || !metrics || this.#scrollNodes.length === 0) return null;\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n const stack = hitStack(layout, col, row);\n for (let i = stack.length - 1; i >= 0; i--) {\n const { node, x, y } = stack[i]!;\n const range = node.scrollRange;\n if (!range || isInert(node.source)) continue;\n const el = node.source as HTMLElement;\n const { y: yBar, x: xBar } = scrollbarGeometry(node, x, y);\n if (\n yBar &&\n range.maxY > 0 &&\n col >= yBar.col &&\n col < yBar.col + yBar.thick &&\n row >= yBar.row &&\n row < yBar.row + yBar.len\n ) {\n const thumbLen = thumbSpan(yBar.len, range.sizeY, range.maxY, 0).len;\n const draggablePx = Math.max(1, (yBar.len - thumbLen) * metrics.height);\n return {\n el,\n axis: \"y\",\n startClient: clientY,\n startPx: el.scrollTop,\n factor: (range.maxY * metrics.height) / draggablePx,\n };\n }\n if (\n xBar &&\n range.maxX > 0 &&\n row >= xBar.row &&\n row < xBar.row + xBar.thick &&\n col >= xBar.col &&\n col < xBar.col + xBar.len\n ) {\n const thumbLen = thumbSpan(xBar.len, range.sizeX, range.maxX, 0).len;\n const draggablePx = Math.max(1, (xBar.len - thumbLen) * metrics.width);\n return {\n el,\n axis: \"x\",\n startClient: clientX,\n startPx: el.scrollLeft,\n factor: (range.maxX * metrics.width) / draggablePx,\n };\n }\n }\n return null;\n }\n\n #onPointerMove = (event: Event): void => {\n if (isTouchInProgress(event)) return; // see #scheduleDynamicRelayout\n const { clientX, clientY } = event as PointerEvent;\n const drag = this.#thumbDrag;\n if (drag) {\n const delta = (drag.axis === \"y\" ? clientY : clientX) - drag.startClient;\n const target = drag.startPx + delta * drag.factor;\n if (drag.axis === \"y\") drag.el.scrollTop = target;\n else drag.el.scrollLeft = target;\n return;\n }\n const held = ((event as PointerEvent).buttons & 1) !== 0;\n if (held && this.#semanticGesture)\n this.#extendSemantic(this.#semanticGesture, clientX, clientY);\n if (held && this.#gridDrag) this.#extendGridDrag(this.#gridDrag, clientX, clientY);\n if (held && this.#pressOnGrid && !this.hasAttribute(\"data-mw-dragging\")) {\n this.setAttribute(\"data-mw-dragging\", \"\");\n }\n this.#hoverClient = { x: clientX, y: clientY };\n // High-frequency path: skip the update while the pointer stays in\n // the same cell (state can only change with the cell — relayouts\n // and scrolls have their own refresh calls).\n const metrics = this.#cellMetrics;\n if (metrics) {\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n if (col === this.#hoverCol && row === this.#hoverRow) return;\n }\n this.#updatePointerStates();\n };\n\n #onCopy = (event: Event): void => {\n const { clipboardData } = event as ClipboardEvent;\n const layout = this.#lastLayout;\n const range = this.#elementSelection();\n if (!clipboardData || !layout || !range) return;\n clipboardData.setData(\"text/plain\", serializeSelection(layout, range));\n event.preventDefault();\n };\n\n /** Double- and triple-click on the grid select the element's word or\n * paragraph (specs/semantic-selection.md); a plain click ends a\n * semantic selection's lift synchronously, ahead of selectionchange. */\n #onMouseDown = (event: Event): void => {\n const e = event as MouseEvent;\n if (e.button !== 0 || this.getAttribute(\"select\") !== \"grid\") return;\n const onGrid = e.composedPath().includes(this.#grid);\n if (!onGrid && !this.#isPhantomTarget(e.target)) return;\n const finePointer = this.#lastPointerType === \"mouse\" || this.#lastPointerType === \"pen\";\n if (e.detail <= 1) {\n if (e.detail !== 1) return;\n this.removeAttribute(SEMANTIC_SELECTION);\n // A press that blurs a control inside the host repaints the focus\n // invert — a structural rebuild a native drag anchor would not\n // survive (paintGrid holds those until release). Take such a\n // press over, like a phantom one: blur now, drag through the\n // engine.\n const focused = this.#focusedInside();\n if (finePointer && (!onGrid || focused)) {\n focused?.blur();\n this.#startGridDrag(e);\n }\n return;\n }\n if (!finePointer) return;\n const unit = e.detail === 2 ? \"word\" : \"paragraph\";\n const selection = document.getSelection();\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n if (!selection || !layout || !metrics) return;\n const { col, row } = this.#cellAt(e.clientX, e.clientY, metrics);\n const target = this.#unitAt(col, row, unit);\n if (!target) {\n // No word or paragraph under the cell (a gap, a border, a blank):\n // the browser's own gesture on the grid — a run of glyphs, or the\n // grid line on a triple-click.\n this.removeAttribute(SEMANTIC_SELECTION);\n this.#semanticGesture = null;\n return;\n }\n // Ours from here: no native word/whole-grid selection, no native\n // drag. A canceled mousedown moves no focus, so move it as the\n // click would have (a focused control would otherwise keep the\n // copy command).\n e.preventDefault();\n this.#focusedInside()?.blur();\n this.#liftLock(target);\n // Shift extends the existing element selection from its anchor.\n const anchor: SelectionUnit =\n e.shiftKey && selection.anchorNode && this.#elementSelection()\n ? pointUnit({ node: selection.anchorNode, offset: selection.anchorOffset })\n : target;\n this.#selectThrough(selection, anchor, target);\n this.#semanticGesture = { unit, anchor };\n };\n\n /** focus=\"arrows\" (specs/focus-navigation.md): an unmodified arrow on a\n * focused descendant whose control does not own it moves focus to the\n * nearest focusable element beyond that edge and reveals it; nothing\n * beyond leaves the key native (no wrap). */\n #onKeyDown = (event: Event): void => {\n const e = event as KeyboardEvent;\n if (this.getAttribute(\"focus\") !== \"arrows\") return;\n const direction = directionOf(e.key);\n if (!direction || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;\n const layout = this.#lastLayout;\n const target = e.target;\n if (!layout || !(target instanceof Element) || target === this) return;\n if (arrowIsNative(target, e.key, this.#openSelectPicker())) return;\n const rects = focusableRects(layout);\n const current = extentOf(rects, target);\n if (!current) return;\n const next = nextFocus(\n direction,\n current,\n rects.filter((candidate) => candidate.element !== target),\n );\n if (!next) return;\n e.preventDefault();\n (next as HTMLElement).focus({ preventScroll: true });\n next.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n };\n\n /** The root as a container over the element children. Direct text on\n * it can't be laid out then — hidden and warned (cell-model deviation),\n * as tree.ts does for nested containers. */\n #buildRootContainer(\n rootFontSizePx: number,\n metrics: CellMetrics,\n textareaWidths: TextareaWidths,\n ): LayoutNode {\n const children: LayoutNode[] = [];\n for (const child of Array.from(this.children)) {\n if (child === this.#probe) continue;\n const node = buildTree(child, rootFontSizePx, metrics, textareaWidths);\n if (node) children.push(node);\n }\n if (hasDirectText(this)) {\n if (!this.hasAttribute(\"data-mw-dropped-text\")) {\n console.warn(`[monowind] ${DIRECT_TEXT_DROPPED}`, warnSubject(this));\n }\n this.setAttribute(\"data-mw-dropped-text\", \"\");\n } else {\n this.removeAttribute(\"data-mw-dropped-text\");\n }\n return {\n source: this,\n style: defaultCellStyle(),\n children,\n text: \"\",\n intrinsicWidth: 0,\n intrinsicHeight: 0,\n localRect: { x: 0, y: 0, width: 0, height: 0 },\n unclampedHeight: 0,\n resolvedPadding: zeroInsets(),\n };\n }\n\n /** The focused element, when it is inside the host. */\n #focusedInside(): HTMLElement | null {\n const active = document.activeElement;\n return active instanceof HTMLElement && active !== document.body && this.contains(active)\n ? active\n : null;\n }\n\n /** Structural repaints are held while a NATIVE drag may be in flight\n * (its browser-internal anchor would not survive a rebuild); an\n * engine-driven grid drag re-derives its points from flat offsets and\n * needs no hold. */\n #holdsNativeDrag(): boolean {\n return this.#pressing && !this.#gridDrag;\n }\n\n /** A non-interactive light element inside the host: never a legitimate\n * pointer target in grid mode, so an event there is a grid event. */\n #isPhantomTarget(target: EventTarget | null): boolean {\n return (\n target instanceof Element &&\n target !== this &&\n this.contains(target) &&\n !target.matches(INTERACTIVE)\n );\n }\n\n /** The grid's flat text offset for a cell: every row is painted at the\n * grid's full width (cell-model.md \"Selection\"), so a row is\n * `width + 1` characters with its newline. */\n #gridOffsetAt(col: number, row: number): number {\n const rows = this.#grid.textContent!.split(\"\\n\");\n const width = rows[0]?.length ?? 0;\n const y = Math.max(0, Math.min(row, rows.length - 1));\n return y * (width + 1) + Math.max(0, Math.min(col, width));\n }\n\n /** The grid text position under a client point: its flat offset and\n * the text node holding it. */\n #gridPointAt(clientX: number, clientY: number): { offset: number; at: [Text, number] } | null {\n const metrics = this.#cellMetrics;\n if (!metrics) return null;\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n const offset = this.#gridOffsetAt(col, row);\n const at = nodeAtOffset(this.#grid, offset);\n return at && { offset, at };\n }\n\n #startGridDrag(e: MouseEvent): void {\n const point = this.#gridPointAt(e.clientX, e.clientY);\n if (!point) return;\n e.preventDefault();\n document.getSelection()?.setBaseAndExtent(...point.at, ...point.at);\n this.#gridDrag = { anchor: point.offset };\n }\n\n #extendGridDrag(drag: { anchor: number }, clientX: number, clientY: number): void {\n const base = nodeAtOffset(this.#grid, drag.anchor);\n const point = this.#gridPointAt(clientX, clientY);\n if (base && point) document.getSelection()?.setBaseAndExtent(...base, ...point.at);\n }\n\n /** Drag extension: the anchor unit through the unit under the pointer,\n * in DOM order (base at the anchor's far edge, so the browser's\n * selection direction matches the drag). */\n #extendSemantic(gesture: SemanticGesture, clientX: number, clientY: number): void {\n const metrics = this.#cellMetrics;\n const selection = document.getSelection();\n if (!metrics || !selection) return;\n const { col, row } = this.#cellAt(clientX, clientY, metrics);\n const current = this.#unitAt(col, row, gesture.unit);\n if (current) this.#selectThrough(selection, gesture.anchor, current);\n }\n\n /** Select from the anchor unit through `unit`: the anchor's far edge\n * becomes the base, so the browser's selection direction matches the\n * gesture. Points inside a custom leaf's shadow cannot pair with\n * light-tree points, so each side is expressed at light-tree edges\n * unless both are the same shadow unit. */\n #selectThrough(selection: Selection, anchor: SelectionUnit, unit: SelectionUnit): void {\n if (sameUnit(anchor, unit)) {\n selectBetween(selection, unit.start, unit.end);\n return;\n }\n const from = this.#lightEdges(anchor);\n const to = this.#lightEdges(unit);\n const forward =\n comparePoints(from.start.node, from.start.offset, to.start.node, to.start.offset) <= 0;\n if (forward) selectBetween(selection, from.start, to.end);\n else selectBetween(selection, from.end, to.start);\n }\n\n /** The word or paragraph under a cell — null unless a CHARACTER of a\n * text leaf is painted there (padding, borders, gaps, and blank tails\n * are the browser's). The innermost hit text leaf; its\n * selectionTarget's contents for a custom leaf; a Segmenter word\n * mapped to DOM positions for the word gesture (falling back to the\n * paragraph where the text has no positions). */\n #unitAt(col: number, row: number, unit: \"word\" | \"paragraph\"): SelectionUnit | null {\n const layout = this.#lastLayout;\n if (!layout) return null;\n const stack = hitStack(layout, col, row);\n for (let i = stack.length - 1; i >= 0; i--) {\n const { node, x, y } = stack[i]!;\n // An inert leaf's text is unselectable natively: no unit there.\n if (isTextLeaf(node)) {\n return isInert(node.source) ? null : this.#leafUnit(node, x, y, col, row, unit);\n }\n }\n // The host's own text (specs/host-leaf.md): the root leaf lies under\n // every cell no child covers.\n return isTextLeaf(layout) ? this.#leafUnit(layout, 0, 0, col, row, unit) : null;\n }\n\n /** The word or paragraph of a text leaf at a cell; null off its\n * characters. A paragraph is the element's contents — a custom leaf's\n * selectionTarget's — or, for the root leaf, the run's own extent (the\n * host's child list also holds the metrics probe). */\n #leafUnit(\n node: LayoutNode,\n x: number,\n y: number,\n col: number,\n row: number,\n unit: \"word\" | \"paragraph\",\n ): SelectionUnit | null {\n const index = charIndexAtCell(node, x, y, col, row);\n if (index === null) return null;\n const target = leafRendererFor(node.source.tagName)?.selectionTarget?.(node.source);\n if (unit === \"word\" && !target) {\n const word = wordAt(node, index);\n const start = word && positionOf(node, word.start);\n const end = word && positionOf(node, word.end);\n if (start && end) return { start, end };\n }\n if (node === this.#lastLayout) return leafExtent(node);\n const container = target ?? node.source;\n return {\n start: { node: container, offset: 0 },\n end: { node: container, offset: container.childNodes.length },\n };\n }\n\n /** A unit inside a custom leaf's shadow, as the light-tree range\n * around its host; a light unit unchanged. The edges sit at the\n * neighbors' content ends rather than on the parent: a point on this\n * host itself comes back from Firefox's getComposedRanges re-expressed\n * inside the shadow slot, which would read as outside the light DOM. */\n #lightEdges(unit: SelectionUnit): SelectionUnit {\n const root = unit.start.node.getRootNode();\n if (!(root instanceof ShadowRoot) || root === this.#grid.getRootNode()) return unit;\n const host = root.host;\n const parent = host.parentNode;\n if (!parent) return unit;\n const index = Array.prototype.indexOf.call(parent.childNodes, host);\n const before = host.previousSibling;\n const after = host.nextSibling;\n return {\n start: isPlainNode(before)\n ? {\n node: before,\n offset: before instanceof Text ? before.length : before.childNodes.length,\n }\n : { node: parent, offset: index },\n end: isPlainNode(after) ? { node: after, offset: 0 } : { node: parent, offset: index + 1 },\n };\n }\n\n /** Lift the grid-mode lock before the range is set — a forced style\n * resolution on the unit's element, so the range only ever lands in\n * selectable content. */\n #liftLock(unit: SelectionUnit): void {\n this.setAttribute(SEMANTIC_SELECTION, \"\");\n const node = unit.start.node;\n const element = node instanceof Element ? node : node.parentElement;\n if (element) void getComputedStyle(element).userSelect;\n }\n\n /** The document selection when it is a non-collapsed range in this\n * host's light DOM (a custom leaf's shadow selection reads as the\n * light range around its host); null otherwise. */\n #elementSelection(): BoundaryPoints | null {\n const range = selectionRangeThrough(this.#grid.getRootNode() as ShadowRoot);\n if (!range || classifySelection(this, this.#grid, range) !== \"light\") return null;\n const collapsed =\n range.startContainer === range.endContainer && range.startOffset === range.endOffset;\n return collapsed ? null : range;\n }\n\n /** The lift ends once the selection left the light DOM or collapsed. */\n #onSelectionChange = (): void => {\n if (!this.hasAttribute(SEMANTIC_SELECTION)) return;\n if (!this.#elementSelection()) this.removeAttribute(SEMANTIC_SELECTION);\n };\n\n #onPointerLeave = (): void => {\n this.#hoverClient = null;\n this.#updatePointerStates();\n };\n\n #onPointerDown = (event: Event): void => {\n const e = event as PointerEvent;\n if (!e.isPrimary || e.button !== 0) return;\n this.#lastPointerType = e.pointerType;\n // A finger pans natively (styles.css \"Touch panning\") and must not\n // relayout before release (see #scheduleDynamicRelayout): no thumb\n // drag, no synthesized press.\n if (isTouchInProgress(e)) return;\n const drag = this.#gutterDragAt(e.clientX, e.clientY);\n if (drag) {\n this.#thumbDrag = drag;\n e.preventDefault();\n // Keep tracking past the host's edge, like a native thumb\n // (synthetic events have no pointer to capture).\n if (e.isTrusted) this.setPointerCapture(e.pointerId);\n return;\n }\n this.#hoverClient = { x: e.clientX, y: e.clientY };\n this.#pressing = true;\n this.#pressOnGrid = e.composedPath().includes(this.#grid);\n this.#updatePointerStates(true);\n };\n\n #onPointerUp = (event: Event): void => {\n if (!(event as PointerEvent).isPrimary) return;\n this.#semanticGesture = null;\n this.#gridDrag = null;\n this.#pressOnGrid = false;\n this.removeAttribute(\"data-mw-dragging\");\n if (this.#thumbDrag) {\n this.#settle(this.#thumbDrag.el);\n this.#thumbDrag = null;\n return;\n }\n if (!this.#pressing && !this.#pressTarget) return;\n this.#pressing = false;\n this.#pressTarget = null;\n this.#updatePointerStates();\n if (this.#paintHeld) this.#scheduleLayout();\n };\n\n #onAnyScroll = (event: Event): void => {\n if (!this.#hoverClient) return;\n // Container scrolls are #onScroll's: hover refreshes in the paint frame\n // AFTER the offsets sync (a per-event refresh here would read\n // stale offsets), and a container's scroll never moves the grid itself.\n const target = event.target;\n if (target instanceof HTMLElement && target.hasAttribute(\"data-mw-scroll\")) return;\n this.#gridOrigin = null;\n this.#updatePointerStates();\n };\n\n /** Recompute both synthesized chains from the stored pointer\n * position and diff them onto the DOM; a change schedules a repaint.\n * `claimPress` (pointerdown only) makes the fresh chain's innermost\n * element the press target before the active chain derives from\n * it. */\n #updatePointerStates(claimPress = false): void {\n const layout = this.#lastLayout;\n const metrics = this.#cellMetrics;\n let chain: Element[] = [];\n if (\n this.#hoverClient &&\n layout &&\n metrics &&\n this.isConnected &&\n this.getAttribute(\"select\") === \"grid\" &&\n (this.#pressing || MonoWindElement.#hoverCapable?.matches)\n ) {\n const { col, row } = this.#cellAt(this.#hoverClient.x, this.#hoverClient.y, metrics);\n this.#hoverCol = col;\n this.#hoverRow = row;\n chain = hitChain(layout, col, row);\n } else {\n this.#hoverCol = NaN;\n this.#hoverRow = NaN;\n }\n const innermost = chain.at(-1) ?? null;\n if (claimPress) this.#pressTarget = innermost;\n // Hover applies only on hover-capable pointers; the press chain\n // exists regardless (touch has :active). Like native :active, the\n // pressed element and its ancestors stay marked while the pointer\n // is over the pressed element, drop when it leaves, return when it\n // re-enters. (Mid-drag hover changes track normally — the paint\n // hold keeps their restyles off the grid until release.)\n const hover = MonoWindElement.#hoverCapable?.matches ? chain : [];\n const pressIndex = this.#pressTarget ? chain.indexOf(this.#pressTarget) : -1;\n const press = pressIndex >= 0 ? chain.slice(0, pressIndex + 1) : [];\n let changed = this.#applyChain(\"data-mw-hover\", this.#hovered, hover);\n changed = this.#applyChain(\"data-mw-active\", this.#pressed, press) || changed;\n // Mirror the hovered cursor onto the grid (the real hit target) —\n // `cursor-pointer` on a click-wired element is invisible otherwise.\n const cursor = innermost ? getComputedStyle(innermost).cursor : \"\";\n this.#grid.style.cursor = cursor === \"auto\" ? \"\" : cursor;\n if (changed && this.isConnected) this.#scheduleLayout();\n }\n\n #applyChain(attribute: string, previous: Set<Element>, next: Element[]): boolean {\n let changed = false;\n const nextSet = new Set(next);\n for (const el of previous) {\n if (!nextSet.has(el)) {\n el.removeAttribute(attribute);\n changed = true;\n }\n }\n for (const el of nextSet) {\n if (!previous.has(el)) {\n el.setAttribute(attribute, \"\");\n changed = true;\n }\n }\n previous.clear();\n for (const el of nextSet) previous.add(el);\n return changed;\n }\n\n #activeTransitions = 0;\n #samplingLoopRunning = false;\n #lastTransitionRun = 0;\n\n #onTransitionRun = (event: Event): void => {\n if (!SAMPLED_TRANSITION.test((event as TransitionEvent).propertyName)) return;\n this.#activeTransitions++;\n this.#lastTransitionRun = performance.now();\n this.#startSamplingLoop();\n };\n\n #onTransitionDone = (event: Event): void => {\n if (!SAMPLED_TRANSITION.test((event as TransitionEvent).propertyName)) return;\n this.#activeTransitions = Math.max(0, this.#activeTransitions - 1);\n };\n\n #startSamplingLoop(): void {\n if (this.#samplingLoopRunning) return;\n this.#samplingLoopRunning = true;\n const tick = (): void => {\n if (\n !this.isConnected ||\n (this.#activeTransitions === 0 && !hasSynthesizedTransitions()) ||\n performance.now() - this.#lastTransitionRun > SAMPLING_VALVE_MS\n ) {\n this.#samplingLoopRunning = false;\n this.#activeTransitions = 0;\n // One final settle pass so the grid lands exactly on the\n // transitions' target values.\n this.#scheduleLayout();\n return;\n }\n this.#performLayoutSafely();\n requestAnimationFrame(tick);\n };\n requestAnimationFrame(tick);\n }\n\n #scheduleDynamicRelayout = (event: Event): void => {\n // A touch must not relayout before it is released: iOS decides\n // which scroller owns a pan in the first frames, and a relayout\n // reflows the light DOM under the finger, which abandons the pan\n // to the page. Touch has no hover to reflect, and the release\n // relayout picks up the tap's outcome.\n if (isTouchInProgress(event)) return;\n // Focus moving onto or off a <select>: relayout NOW, while still\n // inside the event dispatch — the click's default action opens the\n // picker right after, and once it's open relayouts are held (see\n // #openSelectPicker). Deferring here would freeze the grid with\n // the PREVIOUS focus-invert while native text colors update,\n // leaving the old select white-on-white.\n if (\n (event.type === \"focusin\" || event.type === \"focusout\") &&\n event.target instanceof HTMLSelectElement\n ) {\n this.#performLayoutSafely();\n return;\n }\n this.#scheduleLayout();\n };\n\n attributeChangedCallback(name: string, _previous: string | null, next: string | null): void {\n if (name === \"focus\") {\n // Keyboard-only: no layout depends on it.\n if (next !== \"tab\" && next !== \"arrows\") {\n if (next !== null) {\n console.warn(\n `[monowind] Ignoring unrecognized focus=\"${next}\". Expected \"tab\" (default) or \"arrows\".`,\n warnSubject(this),\n );\n }\n this.setAttribute(\"focus\", DEFAULT_FOCUS);\n }\n return;\n }\n if (name === \"select\" && next !== \"text\" && next !== \"grid\") {\n if (next !== null) {\n console.warn(\n `[monowind] Ignoring unrecognized select=\"${next}\". Expected \"grid\" (default) or \"text\".`,\n warnSubject(this),\n );\n }\n // Reflect the default so the attribute is the single source of\n // truth — every selector keys on an explicit value, and no CSS\n // has to know what an absent attribute means.\n this.setAttribute(\"select\", DEFAULT_SELECT);\n return;\n }\n // select=\"text\" hands pointer events back to the light DOM — the\n // synthesized chains must not double up with the native states.\n if (name === \"select\") this.#updatePointerStates();\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 #onWindowResize = (): void => {\n this.#scheduleLayout();\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 /** True while a focused in-host <select> has its picker open. A\n * relayout then would churn styles and make Chrome dismiss the\n * picker instantly (`:open` on <select> is Chromium-only for now;\n * browsers without it don't dismiss and fall through). */\n #openSelectPicker(): boolean {\n const active = document.activeElement;\n if (!(active instanceof HTMLSelectElement) || !this.contains(active)) return false;\n try {\n return active.matches(\":open\");\n } catch {\n return false;\n }\n }\n\n #performLayoutSafely(): void {\n try {\n this.#performLayout();\n } catch (err) {\n console.error(\"[monowind] layout failed:\", err);\n }\n }\n\n #scheduleLayout(): void {\n if (this.#layoutPending) return;\n this.#layoutPending = true;\n requestAnimationFrame(() => {\n this.#layoutPending = false;\n // Hold the relayout while a select picker is up — re-arm so it\n // runs the frame after the picker closes (change or dismiss).\n if (this.#openSelectPicker()) {\n this.#scheduleLayout();\n return;\n }\n this.#performLayoutSafely();\n });\n }\n\n #performLayout(): void {\n // A queued frame can outlive the host's removal (story/app teardown,\n // SPA navigation): computed styles on a detached tree read as empty\n // strings, which would misclassify every element and misfire author\n // warnings. Reconnection schedules a fresh layout.\n if (!this.isConnected) return;\n // Container positions are read before the mask and written back after\n // it (specs/scrolling.md); bottom-stick resolves in between.\n const scrollState = this.#captureScrollState();\n // Snapshot each textarea's content-area width in cells BEFORE the\n // measuring attribute goes on. Inside measuring the engine's width\n // rule is off — the textarea reverts to its browser-default width\n // and any read would be wrong. The tree builder wraps the value\n // against this width to compute the row count.\n const textareaWidths: TextareaWidths = new Map();\n const cellWidth = getComputedStyle(this).getPropertyValue(\"--mw-cw\").trim();\n const cellWidthPx = parseFloat(cellWidth);\n if (Number.isFinite(cellWidthPx) && cellWidthPx > 0) {\n for (const ta of this.querySelectorAll<HTMLTextAreaElement>(\"textarea\")) {\n const style = getComputedStyle(ta);\n const contentPx =\n ta.clientWidth -\n (parseFloat(style.paddingLeft) || 0) -\n (parseFloat(style.paddingRight) || 0);\n // `round` (not `floor`) so subpixel remainders don't chop one\n // cell off the width — the browser rarely wraps a character\n // that fits within half a cell of the edge.\n textareaWidths.set(ta, Math.max(0, Math.round(contentPx / cellWidthPx)));\n }\n }\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. A host innerHTML swap wipes the probe (a\n // detached node measures 0×0, and 0-px cells blow the layout up) —\n // re-adopt it here; the childList record drains with the engine's\n // own writes below.\n if (this.#probe.parentNode !== this) this.appendChild(this.#probe);\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 previous.inkOverhang !== metrics.inkOverhang\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 this.style.setProperty(\"--mw-ink\", `${metrics.inkOverhang ?? 0}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 slot box, 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: the host's own inline\n // content is the root leaf (specs/host-leaf.md); with a block-level\n // child the root is a virtual container over the element children.\n const rootFontSizePx = getRootFontSizePx();\n const virtualRoot =\n buildRootLeaf(this, rootFontSizePx, metrics, textareaWidths) ??\n this.#buildRootContainer(rootFontSizePx, metrics, textareaWidths);\n\n // (4) Compute integer layout.\n const { height } = layoutRoot(virtualRoot, availableCols);\n\n // (5) Write geometry to light DOM + paint the shadow grid. Do this\n // before clearing the measuring attribute so the browser only\n // paints the final state.\n render(virtualRoot);\n this.#scrollNodes = collectScrollContainers(virtualRoot);\n this.#syncScrollOffsets(metrics, scrollState);\n // Style-only paints patch nodes in place (drag anchors survive);\n // a STRUCTURAL rebuild while a primary press holds a selection\n // anchor in the grid is deferred to release — a drag in flight\n // re-derives from the browser's internal anchor, which the\n // rebuild would destroy (Chromium collapses even across a\n // capture-and-restore).\n this.#paintHeld = !paintGrid(virtualRoot, this.#grid, this.#holdsNativeDrag());\n this.#lastLayout = virtualRoot;\n // The grid box is the ink extent in engine cells: a glyph a\n // fallback font draws wider still overhangs as ink, but the box\n // (and the background it inherits) never grows from it.\n const gridWidth = `${virtualRoot.localRect.width * metrics.width}px`;\n const gridHeight = `${virtualRoot.localRect.height * metrics.height}px`;\n if (this.#grid.style.width !== gridWidth) this.#grid.style.width = gridWidth;\n if (this.#grid.style.height !== gridHeight) this.#grid.style.height = gridHeight;\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 const hostHeight = `${height * metrics.height + chrome}px`;\n if (this.style.height !== hostHeight) this.style.height = hostHeight;\n // Cap the width to the columns laid out (specs/cell-model.md \"Host\n // sizing\"); the companion applies it outside measuring.\n const chromeX =\n cs.boxSizing === \"border-box\"\n ? padX + (parseFloat(cs.borderLeftWidth) || 0) + (parseFloat(cs.borderRightWidth) || 0)\n : 0;\n const hostWidth = `${availableCols * metrics.width + chromeX}px`;\n if (this.style.getPropertyValue(\"--mw-host-w\") !== hostWidth)\n this.style.setProperty(\"--mw-host-w\", hostWidth);\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 if (!this.hasAttribute(\"data-mw-ready\")) this.setAttribute(\"data-mw-ready\", \"\");\n } finally {\n // The measured real values are about to snap back to the locks —\n // a delta that must never start a native fade (transitions beat\n // `!important`, and a native background fade paints the light-DOM\n // element's box ON TOP of the grid). [settling] holds the\n // transition-property mask up while the snap-back COMMITS: the\n // forced flush consumes every lock delta under the mask, so the\n // unmasked commits that follow (this frame's end included) see no\n // delta and the authored lists stay fully respected.\n this.setAttribute(\"settling\", \"\");\n this.removeAttribute(\"measuring\");\n void getComputedStyle(this).transitionProperty;\n this.removeAttribute(\"settling\");\n // Restore native container positions AFTER the unmask — the browser\n // re-clamps them when the mask lifts (Firefox lazily), so any\n // earlier write gets wiped. The grid already painted from the\n // same snapshot; a changed native position fires its scroll\n // event into a same-cell repaint.\n this.#restoreScrollPositions(scrollState);\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 // Synthesized transitions (animate.ts): background changes the\n // read detected arm HERE, outside the masks, where the authored\n // `transition-property` list is readable — then the sampling loop\n // drives the fade. A pending change that did NOT arm was painted\n // stale this pass; one more relayout paints its target.\n if (resolvePendingTransitions(this)) {\n if (hasSynthesizedTransitions()) {\n this.#lastTransitionRun = performance.now();\n this.#startSamplingLoop();\n } else {\n this.#scheduleLayout();\n }\n }\n // Surroundings, outside the mask so the reads are authored values:\n // the resize signals a capped host needs, and the native scrollers\n // a page-owned wheel sequence may still have room in.\n this.#observeSurroundings();\n this.#outerScrollers = [];\n const scrolling = document.scrollingElement ?? document.documentElement;\n for (let el = this.parentElement; el; el = el.parentElement) {\n if (el === scrolling || /auto|scroll/.test(getComputedStyle(el).overflow)) {\n this.#outerScrollers.push(el);\n }\n }\n // The layout may have moved content under a stationary pointer —\n // re-derive the synthesized pointer states (cheap when nothing\n // changed; a chain change coalesces into the next frame).\n this.#gridOrigin = null;\n if (this.#hoverClient) this.#updatePointerStates();\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\n/** Pre-layout native container positions, by element (specs/scrolling.md):\n * px, the cells they meant under the OLD range, and end pins. */\ntype ScrollSnapshot = Map<\n HTMLElement,\n { top: number; left: number; x: number; y: number; pinX: boolean; pinY: boolean }\n>;\n\ninterface WheelLatch {\n /** The latched scroll container; null = the page. */\n el: HTMLElement | null;\n x: number;\n y: number;\n /** The gesture's dominant axis at its start. */\n axis: \"x\" | \"y\";\n at: number;\n /** Last tick's |delta| and how many ticks it has decayed smoothly\n * (sticky once INERTIA_TICKS confirm momentum). */\n mag: number;\n decayed: number;\n}\n\n/** An in-flight scrollbar-thumb drag (specs/scrolling.md). */\ninterface ThumbDrag {\n el: HTMLElement;\n axis: \"x\" | \"y\";\n startClient: number;\n startPx: number;\n factor: number;\n}\n\n/** A container's native position on one axis, in cells (see\n * quantizeScroll). */\nfunction scrollCells(\n el: HTMLElement,\n axis: \"x\" | \"y\",\n cellSize: number,\n max: number,\n base: number,\n): number {\n const px = axis === \"y\" ? el.scrollTop : el.scrollLeft;\n const ceiling =\n axis === \"y\" ? el.scrollHeight - el.clientHeight : el.scrollWidth - el.clientWidth;\n return quantizeScroll(px, ceiling, cellSize, max, base);\n}\n\n/** Native scroll position → whole-cell offset within the engine's\n * range (specs/scrolling.md). Within half a cell of `base` (the last\n * painted offset) the shown cell stays — a wobble never flips it;\n * beyond that, the NEAREST cell, ties away from `base`, so a keyboard\n * step of two and a half cells moves three in either direction. At\n * the native `ceiling` the container IS at max: the spacer ends at the\n * engine's edge, but scrollHeight and clientHeight round\n * independently, so the ceiling can sit a pixel either side of the\n * multiple. (A container still at 0 never reads as \"at max\", whatever\n * its ceiling — the spacer may not have applied yet.) */\nexport function quantizeScroll(\n px: number,\n ceiling: number,\n cellSize: number,\n max: number,\n base: number,\n): number {\n if (max > 0 && px > 0 && px >= ceiling - 1) return max;\n const delta = px / cellSize - base;\n const cells =\n Math.abs(delta) <= 0.5 ? base : base + Math.sign(delta) * Math.round(Math.abs(delta));\n return Math.min(Math.max(0, cells), max);\n}\n\n/** A touch pointer that has not been lifted — the phase in which the\n * engine must not reflow anything (see #scheduleDynamicRelayout).\n * `pointercancel` counts as in progress: iOS fires it the moment it\n * takes the pan, and a relayout there kills the gesture. */\nfunction isTouchInProgress(event: Event): boolean {\n return (\n event instanceof PointerEvent && event.pointerType === \"touch\" && event.type !== \"pointerup\"\n );\n}\n\n/** A light node that can hold a boundary point of its own: anything\n * but another shadow host. */\nfunction isPlainNode(node: Node | null): node is Node {\n return node !== null && !(node instanceof Element && node.shadowRoot);\n}\n\n/** A collapsed unit — an existing selection's anchor, for Shift. */\nfunction pointUnit(point: Point): SelectionUnit {\n return { start: point, end: point };\n}\n\nfunction selectBetween(selection: Selection, base: Point, extent: Point): void {\n selection.setBaseAndExtent(base.node, base.offset, extent.node, extent.offset);\n}\n\nfunction sameUnit(a: SelectionUnit, b: SelectionUnit): boolean {\n return (\n a.start.node === b.start.node &&\n a.start.offset === b.start.offset &&\n a.end.node === b.end.node &&\n a.end.offset === b.end.offset\n );\n}\n\nfunction collectScrollContainers(root: LayoutNode): LayoutNode[] {\n const out: LayoutNode[] = [];\n const visit = (node: LayoutNode): void => {\n if (node.scrollRange) out.push(node);\n for (const child of node.children) visit(child);\n };\n visit(root);\n return out;\n}\n"],"mappings":";AAoCA,IAAM,oBAAiB,IAAI,QAAyB,GAC9C,IAAuD,CAAC,GAKxD,oBAAS,IAAI,IAAoC;AAavD,SAAgB,EAAgB,GAAa,GAAe,GAAiC;CAC3F,IAAM,IAAW,EAAe,IAAI,CAAE;CACtC,EAAe,IAAI,GAAI,CAAK;CAC5B,IAAM,IAAU,EAAO,IAAI,CAAE;CAC7B,IAAI,GAAS;EACX,IAAI,MAAU,EAAQ,SAAS;GAG7B,IAAM,IAAO,EAAY,CAAO;GAGhC,OAFA,EAAO,OAAO,CAAE,GAChB,EAAQ,KAAK;IAAE;IAAI;IAAM,IAAI;GAAM,CAAC,GAC7B;EACT;EACA,IAAM,IAAU,EAAY,CAAO;EAEnC,OADI,MAAY,EAAQ,WAAS,EAAO,OAAO,CAAE,GAC1C;CACT;CASA,OAPE,MAAa,KAAA,KACb,MAAa,KACb,EAAG,mBAAmB,MAAM,GAAG,CAAC,CAAC,MAAM,MAAa,WAAW,CAAQ,IAAI,CAAC,KAE5E,EAAQ,KAAK;EAAE;EAAI,MAAM;EAAU,IAAI;CAAM,CAAC,GACvC,KAEF;AACT;AAUA,SAAgB,EAA0B,GAAwB;CAChE,IAAI,IAAa;CACjB,KAAK,IAAI,IAAI,EAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;EAC5C,IAAM,EAAE,OAAI,SAAM,UAAO,EAAQ;EAGjC,IAAI,CAAC,EAAG,aAAa;GACnB,EAAQ,OAAO,GAAG,CAAC;GACnB;EACF;EACA,IAAI,CAAC,EAAK,SAAS,CAAE,GAAG;EAExB,AADA,EAAQ,OAAO,GAAG,CAAC,GACnB,IAAa;EACb,IAAM,IAAS,EAAoB,iBAAiB,CAAE,GAAG,kBAAkB,GACrE,IAAY,EAAW,CAAI,GAC3B,IAAU,EAAW,CAAE;EACzB,AAAC,KAAW,KAAc,KAC9B,EAAO,IAAI,GAAI;GACb,MAAM;GACN,IAAI;GACJ,SAAS;GACT,OAAO,YAAY,IAAI,IAAI,EAAO;GAClC,UAAU,EAAO;GACjB,QAAQ,EAAO;EACjB,CAAC;CACH;CACA,OAAO;AACT;AAEA,SAAgB,IAAqC;CAInD,IAAM,IAAM,YAAY,IAAI;CAC5B,KAAK,IAAM,CAAC,GAAI,MAAe,GAC7B,CAAI,CAAC,EAAG,eAAe,KAAO,EAAW,QAAQ,EAAW,aAAU,EAAO,OAAO,CAAE;CAExF,OAAO,EAAO,OAAO;AACvB;AAEA,SAAS,EAAY,GAA2C;CAC9D,IAAM,KAAK,YAAY,IAAI,IAAI,EAAW,SAAS,EAAW;CAC9D,IAAI,KAAK,GAAG,OAAO,EAAW;CAC9B,IAAM,IAAQ,KAAK,IAAI,IAAI,EAAW,OAAO,CAAC;CAC9C,OAAO,EAAU,EAAI,EAAW,MAAM,EAAW,IAAI,CAAK,CAAC;AAC7D;AAIA,IAAM,IAAoE;CACxE,MAAM;EAAC;EAAM;EAAK;EAAM;CAAC;CACzB,WAAW;EAAC;EAAM;EAAG;EAAG;CAAC;CACzB,YAAY;EAAC;EAAG;EAAG;EAAM;CAAC;CAC1B,eAAe;EAAC;EAAM;EAAG;EAAM;CAAC;AAClC;AAEA,SAAS,EACP,GACA,GAC2E;CAC3E,IAAM,IAAa,EAAG,mBAAmB,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC,GAGnE,IAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,QAAQ,KACrC,CAAI,EAAW,OAAO,KAAY,EAAW,OAAO,WAAO,IAAQ;CAErE,IAAI,IAAQ,GAAG,OAAO;CACtB,IAAM,KAAO,MAAyB;EACpC,IAAM,IAAS,EAAK,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;EAClD,OAAO,EAAO,IAAQ,EAAO,WAAW;CAC1C,GACM,IAAW,EAAa,EAAI,EAAG,kBAAkB,CAAC;CAExD,OADI,KAAY,IAAU,OACnB;EACL,UAAU,IAAW;EACrB,OAAO,EAAa,EAAI,EAAG,eAAe,CAAC,IAAI;EAC/C,QAAQ,EAAY,EAAI,EAAG,wBAAwB,CAAC;CACtD;AACF;AAEA,SAAS,EAAa,GAAuB;CAC3C,IAAM,IAAS,WAAW,CAAK;CAE/B,OADK,OAAO,SAAS,CAAM,IACpB,EAAM,SAAS,IAAI,IAAI,IAAS,MAAO,IADT;AAEvC;AAEA,SAAS,EAAY,GAAsC;CACzD,IAAI,MAAU,UAAU,QAAQ,MAAM;CACtC,IAAM,IAAU,EAAgB;CAChC,IAAI,GAAS,OAAO,EAAY,GAAG,CAAO;CAC1C,IAAM,IAAS,EAAM,MAAM,2BAA2B;CACtD,IAAI,GAAQ;EACV,IAAM,CAAC,GAAI,GAAI,GAAI,KAAM,EAAO,EAAE,CAAE,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,WAAW,CAAC,CAAC;EACvE,IAAI;GAAC;GAAI;GAAI;GAAI;EAAE,CAAC,CAAC,OAAO,MAAM,OAAO,SAAS,CAAC,CAAC,GAClD,OAAO,EAAY,GAAK,GAAK,GAAK,CAAG;CAEzC;CAGA,QAAQ,MAAM;AAChB;AAIA,SAAS,EAAY,GAAY,GAAY,GAAY,GAAmC;CAC1F,IAAM,KAAS,GAAW,GAAW,MACnC,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI;CACpE,QAAQ,MAAM;EACZ,IAAI,IAAK,GACL,IAAK;EACT,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;GAC3B,IAAM,KAAO,IAAK,KAAM;GACxB,AAAI,EAAM,GAAI,GAAI,CAAG,IAAI,IAAG,IAAK,IAC5B,IAAK;EACZ;EACA,OAAO,EAAM,GAAI,IAAK,IAAK,KAAM,CAAC;CACpC;AACF;AAIA,SAAS,EAAW,GAA4B;CAC9C,IAAI,MAAU,MAAM,MAAU,eAAe,OAAO;EAAE,GAAG;EAAG,GAAG;EAAG,GAAG;EAAG,GAAG;EAAG,QAAQ;CAAK;CAC3F,IAAI,IAAQ,EAAM,MAAM,oBAAoB;CAC5C,IAAI,GAAO;EACT,IAAM,IAAQ,EAAM,EAAE,CAAE,MAAM,SAAS,CAAC,CAAC,KAAK,MAAM,WAAW,CAAC,CAAC;EAEjE,OADI,EAAM,SAAS,KAAK,EAAM,MAAM,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC,IAAU,OAChE;GACL,GAAG,EAAM,KAAM;GACf,GAAG,EAAM,KAAM;GACf,GAAG,EAAM,KAAM;GACf,GAAG,EAAM,MAAM;GACf,QAAQ;EACV;CACF;CAEA,IADA,IAAQ,EAAM,MAAM,yBAAyB,GACzC,GAAO;EACT,IAAM,IAAQ,EAAM,EAAE,CAAE,MAAM,QAAQ,CAAC,CAAC,KAAK,MAAM,WAAW,CAAC,CAAC;EAEhE,OADI,EAAM,SAAS,KAAK,EAAM,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC,IAAU,OAC5E;GAAE,GAAG,EAAM;GAAK,GAAG,EAAM;GAAK,GAAG,EAAM;GAAK,GAAG,EAAM,MAAM;GAAG,QAAQ;EAAM;CACrF;CAEA,IADA,IAAQ,EAAM,MAAM,yBAAyB,GACzC,GAAO;EACT,IAAM,IAAQ,EAAM,OAAO,MACrB,IAAQ,EAAM,EAAE,CACnB,WAAW,QAAQ,GAAG,CAAC,CACvB,MAAM,QAAQ,CAAC,CACf,KAAK,MAAM,WAAW,CAAC,CAAC;EAC3B,IAAI,EAAM,SAAS,KAAK,EAAM,MAAM,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC,GAAG,OAAO;EACvE,IAAM,CAAC,GAAG,GAAI,KAAM;EAGpB,OAAO;GAAE,GAAG,EAAY,GAFd,IAAQ,IAAK,KAAK,IAAK,IAAK,KAAK,KAAM,GAAG,IAAI,GAC9C,IAAQ,IAAK,KAAK,IAAK,IAAK,KAAK,KAAM,GAAG,IAAI,CACzB;GAAG,GAAG,EAAM,MAAM;GAAG,QAAQ;EAAM;CACpE;CACA,OAAO;AACT;AAEA,SAAS,EAAI,GAAY,GAAU,GAAiB;CAIlD,IAAM,IAAI,EAAK,KAAK,EAAG,IAAI,EAAK,KAAK,GAC/B,KAAQ,GAAW,MAAsB;EAC7C,IAAM,IAAW,IAAI,EAAK,KAAK,IAAI,EAAG,IAAI,IAAI,EAAK,KAAK;EACxD,OAAO,MAAM,IAAI,IAAI,IAAW;CAClC;CACA,IAAI,EAAK,UAAU,EAAG,QACpB,OAAO;EAAE,GAAG,EAAK,EAAK,GAAG,EAAG,CAAC;EAAG,GAAG,EAAK,EAAK,GAAG,EAAG,CAAC;EAAG,GAAG,EAAK,EAAK,GAAG,EAAG,CAAC;EAAG;EAAG,QAAQ;CAAK;CAEhG,IAAM,IAAI,EAAY,EAAK,GAAG,EAAK,GAAG,EAAK,CAAC,GACtC,IAAI,EAAY,EAAG,GAAG,EAAG,GAAG,EAAG,CAAC;CAEtC,OAAO;EAAE,GADG,EAAY,EAAK,EAAE,GAAG,EAAE,CAAC,GAAG,EAAK,EAAE,GAAG,EAAE,CAAC,GAAG,EAAK,EAAE,GAAG,EAAE,CAAC,CACzD;EAAK;EAAG,QAAQ;CAAM;AACpC;AAEA,SAAS,EAAU,GAAqB;CACtC,IAAM,KAAW,MAAsB,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,GAC7E,IAAQ,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,EAAM,CAAC,CAAC,IAAI,GAAI,IAAI;CACrE,OAAO,QAAQ,EAAQ,EAAM,CAAC,EAAE,IAAI,EAAQ,EAAM,CAAC,EAAE,IAAI,EAAQ,EAAM,CAAC,EAAE,IAAI,EAAM;AACtF;AAEA,SAAS,EAAU,GAAmB;CACpC,OAAO,KAAK,SAAU,IAAI,UAAkB,IAAI,QAAS,UAAO;AAClE;AAEA,SAAS,EAAY,GAAmB;CACtC,OAAO,KAAK,WAAY,IAAI,QAAQ,QAAiB,MAAG,IAAI,OAAO;AACrE;AAEA,SAAS,EAAY,GAAW,GAAW,GAAgD;CACzF,IAAM,IAAK,EAAU,CAAC,GAChB,IAAK,EAAU,CAAC,GAChB,IAAK,EAAU,CAAC,GAChB,IAAI,KAAK,KAAK,cAAe,IAAK,cAAe,IAAK,cAAe,CAAE,GACvE,IAAI,KAAK,KAAK,cAAe,IAAK,cAAe,IAAK,cAAe,CAAE,GACvE,IAAI,KAAK,KAAK,cAAe,IAAK,cAAe,IAAK,cAAe,CAAE;CAC7E,OAAO;EACL,GAAG,cAAe,IAAI,aAAc,IAAI,cAAe;EACvD,GAAG,eAAe,IAAI,cAAc,IAAI,cAAe;EACvD,GAAG,cAAe,IAAI,cAAe,IAAI,aAAc;CACzD;AACF;AAEA,SAAS,EAAY,GAAW,GAAW,GAAgD;CACzF,IAAM,KAAc,IAAI,cAAe,IAAI,cAAe,MAAG,GACvD,KAAc,IAAI,cAAe,IAAI,cAAe,MAAG,GACvD,KAAc,IAAI,cAAe,IAAI,cAAc,MAAG;CAC5D,OAAO;EACL,GAAG,EAAY,eAAe,IAAK,eAAe,IAAK,cAAe,CAAE;EACxE,GAAG,EAAY,gBAAgB,IAAK,eAAe,IAAK,cAAe,CAAE;EACzE,GAAG,EAAY,eAAgB,IAAK,cAAe,IAAK,cAAc,CAAE;CAC1E;AACF;;;ACxQA,IAAM,oBAAO,IAAI,IAA4B,GACvC,oBAAY,IAAI,IAAgB;AAItC,SAAgB,EAAqB,GAAc,GAA2B;CAC5E,IAAM,IAAM,EAAK,YAAY,CAAC,CAAC,KAAK;CAIpC,AAHI,EAAK,IAAI,CAAG,KACd,QAAQ,KAAK,+CAA+C,EAAI,4BAA4B,GAE9F,EAAK,IAAI,GAAK,CAAG;CACjB,KAAK,IAAM,KAAY,GAAW,EAAS;AAC7C;AAMA,SAAgB,EAAY,GAA6D;CAClF,OACL,OAAO,EAAK,IAAI,EAAK,YAAY,CAAC,CAAC,KAAK,CAAC;AAC3C;AAGA,SAAgB,EAAsB,GAAkC;CAEtE,OADA,EAAU,IAAI,CAAQ,SACT,EAAU,OAAO,CAAQ;AACxC;AAIA,SAAgB,EAAa,GAAuC;CAClE,QAAQ,GAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK,GACH,OAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK,IACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,IACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,IACH,OAAO;EACT,KAAK,IACH,OAAO;EACT,KAAK,IACH,OAAO;EACT,KAAK,IACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAKA,IAAa,IAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,GACa,IAAmB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAIA,SAAS,EAAU,GAA0C;CAC3D,IAAM,IAAoB,CAAC;CAC3B,KAAK,IAAI,IAAO,GAAG,IAAO,IAAI,KAAQ;EACpC,IAAM,IAAO,EAAa,CAAI;EAC9B,AAAI,KAAQ,EAAE,KAAQ,OAAQ,EAAM,KAAQ,EAAU;CACxD;CACA,OAAO;AACT;AAGA,IAAM,KAAgB,MACpB,EAAU,MAAM,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAK,CAAC;AAMnD,EAAqB,WAAW,CAAC,CAAC,GAKlC,EAAqB,WAAW,EAC9B,OAAO;CAAE,IAAI;CAAK,IAAI;CAAK,IAAI;CAAK,IAAI;AAAI,EAC9C,CAAC;AAGD,IAAM,IAAyB;CAAE,GAAG,EAAa,GAAG;CAAG,GAAG;CAAK,GAAG;AAAI;AACtE,EAAqB,SAAS;CAC5B,OAAO;EAAE,GAAG;EAAY,aAAa;EAAK,aAAa;CAAI;CAC3D,QAAQ;EAAE,GAAG;EAAY,GAAG;CAAI;CAChC,QAAQ;CACR,QAAQ;EAAE,GAAG;EAAY,GAAG;EAAK,GAAG;CAAI;AAC1C,CAAC;AAED,IAAM,IAAa,EAAU,CAAe;AAI5C,EAAqB,UAAU;CAC7B,QAAQ;CACR,QAAQ;CACR,QAAQ;AACV,CAAC,GAKD,EAAqB,SAAS;CAAE,QAAQ;CAAY,QAAQ;AAAW,CAAC;AAIxE,SAAgB,EAAa,GAAmE;CAC9F,OAAO;EACL,OAAO,GAAK,OAAO,eAAe;EAClC,OAAO,GAAK,OAAO,eAAe;CACpC;AACF;AAGA,EAAqB,UAAU;CAC7B,OAAO,EAAa,GAAG;CACvB,QAAQ,EAAa,GAAG;CACxB,QAAQ,EAAa,GAAG;CACxB,QAAQ,EAAa,GAAG;AAC1B,CAAC;;;AChND,IAAM,oBAAS,IAAI,QAA8B;AAEjD,SAAgB,EAAS,GAAa,GAAuB;CAC3D,IAAI,IAAW,EAAO,IAAI,CAAE;CAC5B,AAAK,KAAU,EAAO,IAAI,GAAK,oBAAW,IAAI,IAAI,CAAE,GAChD,GAAS,IAAI,CAAO,MACxB,EAAS,IAAI,CAAO,GACpB,QAAQ,KAAK,cAAc,KAAW,GAAY,CAAE,CAAC;AACvD;AAKA,SAAgB,GAAY,GAA+B;CAGzD,IAAI,CAFU,WAA8D,SAAS,UACjF,MACO,OAAO;CAClB,IAAM,IAAK,EAAG,KAAK,IAAI,EAAG,OAAO,IAC3B,IAAU,EAAG,UAAU,SAAS,IAAI,MAAM,KAAK,EAAG,SAAS,CAAC,CAAC,KAAK,GAAG,MAAM;CACjF,OAAO,IAAI,EAAG,QAAQ,YAAY,IAAI,IAAK,EAAQ;AACrD;;;ACyCA,IAAM,qBAAS,IAAI,IAA8B,GAC3C,qBAAY,IAAI,IAAgB;AAMtC,SAAgB,GAAqB,GAAsC;CACzE,IAAM,IAAM,EAAa,IAAI,YAAY;CACzC,IAAI,CAAC,EAAI,SAAS,GAAG,GAAG;EACtB,QAAQ,KACN,qCAAqC,EAAa,IAAI,8DACxD;EACA;CACF;CAOA,AANI,GAAO,IAAI,CAAG,KAChB,QAAQ,KACN,qEAAqE,EAAI,4BAC3E,GAEF,GAAO,IAAI,GAAK;EAAE,GAAG;EAAc;CAAI,CAAC,GACxC,GAAO;AACT;AAKA,SAAgB,KAAyB;CACvC,GAAO;AACT;AAEA,SAAgB,GAAgB,GAA+C;CAC7E,OAAO,GAAO,IAAI,EAAQ,YAAY,CAAC;AACzC;AAIA,SAAgB,KAAmC;CACjD,IAAM,oBAAM,IAAI,IAAY;CAC5B,KAAK,IAAM,KAAQ,GAAO,OAAO,GAC/B,KAAK,IAAM,KAAa,EAAK,sBAAsB,CAAC,GAAG,EAAI,IAAI,EAAU,YAAY,CAAC;CAExF,OAAO,CAAC,GAAG,CAAG;AAChB;AAIA,SAAgB,GAAqB,GAAkC;CAErE,OADA,GAAU,IAAI,CAAQ,SACT,GAAU,OAAO,CAAQ;AACxC;AAIA,SAAgB,GAAkB,GAAwB,GAAiC;CACzF,IAAI;EACF,OAAO,EAAK,OAAO,CAAE;CACvB,SAAS,GAAK;EAEZ,OADA,EAAS,GAAI,IAAI,EAAK,IAAI,uCAAuC,OAAO,CAAG,GAAG,GACvE;CACT;AACF;AAEA,SAAS,KAAe;CACtB,KAAK,IAAM,KAAY,IAAW,EAAS;AAC7C;;;ACtFA,SAAgB,GAAkB,GAAkB,GAAW,GAAwB;CACrF,IAAM,IAAS,EAAM;CACrB,IAAI,EAAO,QAAQ,KAAK,EAAO,UAAU,KAAK,EAAO,WAAW,KAAK,EAAO,SAAS,GAAG;CACxF,IAAM,IAAQ,KAAK,IAAI,EAAO,KAAK,EAAO,OAAO,EAAO,QAAQ,EAAO,IAAI;CAC3E,KAAK,IAAI,IAAO,GAAG,IAAO,GAAO,KAAQ;EACvC,IAAM,IAAQ;GACZ,KAAK,IAAO,EAAO;GACnB,OAAO,IAAO,EAAO;GACrB,QAAQ,IAAO,EAAO;GACtB,MAAM,IAAO,EAAO;EACtB,GACM,IAAW;GACf,GAAG,EAAI,KAAK,EAAM,OAAO,IAAO;GAChC,GAAG,EAAI,KAAK,EAAM,MAAM,IAAO;GAC/B,OAAO,EAAI,SAAS,EAAM,OAAO,IAAO,MAAM,EAAM,QAAQ,IAAO;GACnE,QAAQ,EAAI,UAAU,EAAM,MAAM,IAAO,MAAM,EAAM,SAAS,IAAO;EACvE;EACI,EAAS,SAAS,KAAK,EAAS,UAAU,KAC9C,GACE,GACA,EAAM,aACN,EAAM,aACN,GACA,GACA,EAAY,EAAM,QAAQ,CAC5B;CACF;AACF;AAUA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACM;CACN,IAAM,IAAM,GAAa,EAAO,KAAK,CAAG,GAClC,IAAQ,GAAa,EAAO,OAAO,CAAG,GACtC,IAAS,GAAa,EAAO,QAAQ,CAAG,GACxC,IAAO,GAAa,EAAO,MAAM,CAAG,GACpC,KAAU,GAAgB,GAAgB,MACpC,EAAK,GAAf,MAAM,IAAsB,IAA6B,SAA1B,CAAzB,CAAgE,GAClE,EAAE,MAAG,MAAG,UAAO,cAAW,GAC1B,IAAa,KAAS,KAAK,KAAU,GACrC,IAAiB,IAAK,KAAM,MAC5B,IAAe,IAAI,IAAS,KAAM,OAClC,IAAiB,IAAK,KAAM,KAC5B,IAAe,IAAI,IAAU,KAAM;CAsBzC,IAnBI,EAAM,OAAO,IAAe,KAC9B,EAAI,KAAK;EACP,OAAO,EAAI;EACX,GAAG;EACH;EACA,QAAQ,IAAe;EACvB,OAAO,EAAO;CAChB,CAAC,GAEC,EAAM,UAAU,IAAU,KAAM,OAAgB,IAAe,KACjE,EAAI,KAAK;EACP,OAAO,EAAO;EACd,GAAG;EACH,GAAG,IAAI,IAAS;EAChB,QAAQ,IAAe;EACvB,OAAO,EAAO;CAChB,CAAC,GAGC,EAAM,MACR,KAAK,IAAI,IAAK,GAAgB,IAAK,GAAc,KAC/C,EAAI,KAAK;EAAE,OAAO,EAAK;EAAG;EAAG,GAAG;EAAI,QAAQ;EAAG,OAAO,EAAO;CAAK,CAAC;CAEvE,IAAI,EAAM,SAAS,IAAS,KAAM,MAChC,KAAK,IAAI,IAAK,GAAgB,IAAK,GAAc,KAC/C,EAAI,KAAK;EAAE,OAAO,EAAM;EAAG,GAAG,IAAI,IAAQ;EAAG,GAAG;EAAI,QAAQ;EAAG,OAAO,EAAO;CAAM,CAAC;CAGxF,AAAI,MACE,EAAM,OAAO,EAAM,QACrB,EAAI,KAAK;EACP,OAAO,EAAO,EAAO,KAAK,EAAO,OAAO,MAAM,EAAE,EAAE;EAClD;EACA;EACA,QAAQ;EACR,OAAO,EAAO;CAChB,CAAC,GACC,EAAM,OAAO,EAAM,SACrB,EAAI,KAAK;EACP,OAAO,EAAO,EAAO,KAAK,EAAO,QAAQ,MAAM,EAAE,EAAE;EACnD,GAAG,IAAI,IAAQ;EACf;EACA,QAAQ;EACR,OAAO,EAAO;CAChB,CAAC,GACC,EAAM,UAAU,EAAM,QACxB,EAAI,KAAK;EACP,OAAO,EAAO,EAAO,QAAQ,EAAO,OAAO,MAAM,EAAE,EAAE;EACrD;EACA,GAAG,IAAI,IAAS;EAChB,QAAQ;EACR,OAAO,EAAO;CAChB,CAAC,GACC,EAAM,UAAU,EAAM,SACxB,EAAI,KAAK;EACP,OAAO,EAAO,EAAO,QAAQ,EAAO,QAAQ,MAAM,EAAE,EAAE;EACtD,GAAG,IAAI,IAAQ;EACf,GAAG,IAAI,IAAS;EAChB,QAAQ;EACR,OAAO,EAAO;CAChB,CAAC;AAEP;AAOA,SAAgB,GAAuB,GAAmB,GAA6B;CACrF,OACE,EAAM,MAAM,aAAa,aACvB,EAAO,MAAM,YAAY,UAAU,EAAO,MAAM,YAAY,WAC5D,EAAM,MAAM,WAAW;AAE7B;AAQA,SAAgB,GAAqB,GAAgC;CACnE,IAAI,EAAK,SAAS,UAAU,GAAG,OAAO,EAAK;CAC3C,IAAI,IAAiC,MACjC,IAA8B,MAC9B,IAA+B,MAC/B,IAAkC;CACtC,KAAK,IAAM,KAAS,EAAK,UACvB,AAAI,GAAuB,GAAO,CAAI,KAC/B,EAAM,MAAM,UAAU,KAAK,KAAI,MAAc,CAAC,EAAA,CAAG,KAAK,CAAK,KAC1D,MAAe,CAAC,EAAA,CAAG,KAAK,CAAK,IAC1B,EAAM,aAAY,MAAY,CAAC,EAAA,CAAG,KAAK,CAAK,KACjD,MAAW,CAAC,EAAA,CAAG,KAAK,CAAK;CAWjC,OATI,KAAa,EAAU,SAAS,KAClC,EAAU,MAAM,GAAG,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,MAAM,UAAU,EAAE,GAEpE,KAAc,EAAW,SAAS,KACpC,EAAW,MAAM,GAAG,OAAO,EAAE,MAAM,UAAU,MAAM,EAAE,MAAM,UAAU,EAAE,GAErE,CAAC,KAAa,KAAU,CAAC,KAAW,CAAC,IAAmB,IACxD,CAAC,KAAa,CAAC,KAAU,KAAW,CAAC,IAAmB,IACxD,CAAC,KAAa,CAAC,KAAU,CAAC,KAAW,IAAmB,IACrD;EAAC,GAAI,KAAa,CAAC;EAAI,GAAI,KAAU,CAAC;EAAI,GAAI,KAAW,CAAC;EAAI,GAAI,KAAc,CAAC;CAAE;AAC5F;AAGA,SAAgB,GAAU,GAAoB,GAAiB,GAA8B;CAC3F,IAAM,IAAS,GAAa,GAAO,CAAG;CACtC,OAAO,MAAS,MAAM,EAAO,IAAI,EAAO;AAC1C;AAQA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,KAAQ,IAAK,IAAI,MAAM,IAAO,IAAI,MAAM,IAAO,IAAI,KAAM;CAC/D,IAAI,GAAK;EACP,IAAM,IAAO,EAAa,CAAI,GACxB,IAAW,KAAQ,EAAI,EAAM,GAAG;EACtC,IAAI,GAAU,OAAO;CACvB;CAEA,QADc,MAAU,WAAW,IAAmB,EAAA,CACzC;AACf;AAOA,SAAS,GAAa,GAAoB,GAA8B;CACtE,IAAM,KAAK,GAAa,GAAe,GAAe,MACpD,GAAc,GAAO,GAAI,GAAM,GAAM,GAAO,CAAG,GAC3C,IAAe;EACnB,GAAG,EAAE,IAAO,IAAO,IAAM,EAAI;EAC7B,GAAG,EAAE,IAAM,IAAM,IAAO,EAAK;EAC7B,IAAI,EAAE,IAAO,IAAM,IAAO,EAAI;EAC9B,IAAI,EAAE,IAAO,IAAM,IAAM,EAAK;EAC9B,IAAI,EAAE,IAAM,IAAO,IAAO,EAAI;EAC9B,IAAI,EAAE,IAAM,IAAO,IAAM,EAAK;CAChC;CAGA,OAFI,MAAU,WAAiB;EAAE,GAAG;EAAK,GAAG;EAAK,GAAG,GAAa,CAAI;EAAG,GAAG,GAAS,GAAK,CAAK;CAAE,IAC5F,MAAU,WAAiB;EAAE,GAAG;EAAK,GAAG;EAAK,GAAG,GAAa,CAAI;EAAG,GAAG,GAAS,GAAK,CAAK;CAAE,IACzF;AACT;AAEA,SAAS,GAAa,GAAyC;CAC7D,IAAM,EAAE,GAAG,GAAI,GAAG,GAAI,GAAG,MAAS;CAClC,OAAO;AACT;AAEA,SAAS,GAAS,GAAiC,GAAqC;CACtF,IAAM,IAAQ,IAAM,IACd,IAAyB,CAAC;CAGhC,OAFI,GAAO,MAAG,EAAM,IAAI,EAAM,IAC1B,GAAO,MAAG,EAAM,IAAI,EAAM,IACvB;AACT;AA4CA,SAAgB,GACd,GACA,GACA,GACA,GACc;CACd,IAAM,IAAU,EAAO,KAAK,MACtB,EAAM,UAAgB,KACtB,MAAe,YAAkB,EAAM,kBAAkB,EAAM,gBAC/D,MAAe,YAAiB,EAAM,kBAAkB,EAAM,aAEnE,GACK,IAA6D,CAAC;CACpE,KAAK,IAAI,IAAI,GAAG,IAAI,EAAO,QAAQ,KAEjC,IADA,EAAO,KAAK;EAAE,OAAO,EAAO,EAAE,CAAE;EAAO,KAAK,EAAO,EAAE,CAAE;EAAK,SAAS,EAAQ;CAAI,CAAC,GAC9E,IAAI,IAAI,EAAO,QAAQ;EACzB,IAAM,IACJ,MAAc,iBACV,KACA,MAAc,SACZ,EAAQ,MAAO,EAAQ,IAAI,KAC3B,EAAQ,MAAO,EAAQ,IAAI;EACnC,EAAO,KAAK;GAAE,OAAO,EAAO,EAAE,CAAE;GAAK,KAAK,EAAO,IAAI,EAAE,CAAE;GAAO,SAAS;EAAO,CAAC;CACnF;CAEF,IAAM,IAAyB,CAAC;CAChC,KAAK,IAAM,KAAS,GAAQ;EAC1B,IAAI,CAAC,EAAM,SAAS;EACpB,IAAM,IAAO,EAAS,EAAS,SAAS;EACxC,AAAI,KAAQ,EAAK,QAAQ,EAAM,QAAO,EAAK,MAAM,EAAM,MAClD,EAAS,KAAK;GAAE,OAAO,EAAM;GAAO,KAAK,EAAM;EAAI,CAAC;CAC3D;CACA,IAAI,MAAU,gBAAgB;EAM5B,IAAM,oBAAiB,IAAI,IAAoB,GACzC,oBAAe,IAAI,IAAoB;EAC7C,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,EAAO,QAAQ,KAAK;GAC1C,IAAM,IAAgB,EAAO,EAAE,CAAE,KAC3B,IAAQ,EAAO,IAAI,EAAE,CAAE,QAAQ;GACjC,KAAS,MACb,EAAa,IAAI,GAAe,IAAgB,KAAK,KAAK,IAAQ,CAAC,CAAC,GACpE,EAAe,IAAI,EAAO,IAAI,EAAE,CAAE,OAAO,IAAgB,KAAK,MAAM,IAAQ,CAAC,CAAC;EAChF;EACA,OAAO,EAAS,KAAK,MAAY;GAC/B,IAAM,IAAQ,EAAe,IAAI,EAAQ,KAAK,GACxC,IAAM,EAAa,IAAI,EAAQ,GAAG;GACxC,OAAO;IACL,OAAO,KAAS,EAAQ;IACxB,KAAK,KAAO,EAAQ;IACpB,WAAW,MAAU,KAAA;IACrB,SAAS,MAAQ,KAAA;GACnB;EACF,CAAC;CACH;CACA,OAAO,EACJ,KAAK,OAAa;EAAE,OAAO,EAAQ,QAAQ;EAAO,KAAK,EAAQ,MAAM;CAAM,EAAE,CAAC,CAC9E,QAAQ,MAAY,EAAQ,MAAM,EAAQ,KAAK;AACpD;AAyBA,SAAgB,GAAmB,GAAkC;CACnE,IAAM,IAAmB,CAAC,GACpB,IAAU,EAAI,OAAO,OAAO,EAAI,QAAQ,MACxC,IAAU,EAAI,OAAO,MAAM,EAAI,QAAQ,KACvC,KAAU,GAAe,OAAsB;EACnD,MAAM,EAAI,YAAY,KAAK,OAAO,EAAI,WAAW,EAAK,SAAS,CAAC;EAChE,OAAO,EAAI;EACX,KAAK,EAAI;EACT,WAAW,EAAI,cAAc;EAC7B,SAAS,EAAI,YAAY;CAC3B,IACM,IAAS,EAAI,QAAQ,EAAI,SAAS,KAAK,MAAQ,EAAO,EAAI,OAAQ,CAAG,CAAC,IAAI,CAAC,GAC3E,IAAS,EAAI,QAAQ,EAAI,WAAW,KAAK,MAAQ,EAAO,EAAI,OAAQ,CAAG,CAAC,IAAI,CAAC,GAC7E,IAAS,EAAI,OAAO,SAAS,GAC7B,IAAS,EAAI,OAAO,SAAS,GAK7B,KAAiB,GAAsB,GAAe,GAAgB,MAC1E,EAAM,MACH,MACC,KAAU,EAAE,QACZ,IAAS,EAAE,OAAO,MAChB,EAAE,QAAQ,KAAK,EAAE,MAAM,KACtB,EAAE,QAAQ,KAAK,CAAC,EAAE,WAClB,EAAE,UAAU,KAAK,CAAC,EAAE,UAC3B,GAGI,KAAoB,GAAW,MACnC,EAAO,MAAM,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,OAAO,KAAU,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG;CAEpF,IAAI,EAAI,OAAO;EACb,IAAM,IAAQ,GAAU,EAAI,MAAM,OAAO,KAAK,EAAI,MAAM;EACxD,KAAK,IAAM,KAAQ,GAAQ;GACzB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAQ,KAC1B,KAAK,IAAI,IAAI,EAAK,OAAO,IAAI,EAAK,KAAK,KACjC,EAAiB,EAAK,OAAO,GAAG,CAAC,KACrC,EAAI,KAAK;IACP;IACA,GAAG,IAAU,EAAK,OAAO;IACzB,GAAG,IAAU;IACb,QAAQ;IACR,OAAO,EAAI,MAAM;GACnB,CAAC;GAEL,GAAsB,GAAK,GAAK,KAAK,EAAK,MAAM,EAAK,OAAO,EAAK,GAAG;EACtE;CACF;CACA,IAAI,EAAI,OAAO;EACb,IAAM,IAAY,EAAI,MAAM,UAAU,YAAY,EAAI,OAAO,UAAU;EACvE,KAAK,IAAM,KAAQ,GAAQ;GACzB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAQ,KAAK;IAC/B,IAAM,IAAI,EAAK,OAAO;IACtB,KAAK,IAAI,IAAI,EAAK,OAAO,IAAI,EAAK,KAAK,KAAK;KAC1C,IAAM,IAAK,EAAc,GAAQ,GAAQ,GAAG,CAAC,GACvC,IAAO,EAAc,GAAQ,GAAQ,GAAG,IAAI,CAAC;KACnD,EAAI,KAAK;MACP,OACE,KAAM,IACF,GACE,IAAY,WAAW,SACvB,GACA,GACA,EAAc,GAAQ,GAAQ,GAAG,CAAC,GAClC,EAAc,GAAQ,GAAQ,GAAG,IAAI,CAAC,GACtC,EAAI,MACN,IACA,GAAU,EAAI,MAAM,OAAO,KAAK,EAAI,MAAM;MAChD,GAAG,IAAU;MACb,GAAG,IAAU;MACb,QAAQ;MACR,OAAO,EAAI,MAAM;KACnB,CAAC;IACH;GACF;GACA,GAAsB,GAAK,GAAK,KAAK,EAAK,MAAM,EAAK,OAAO,EAAK,GAAG;EACtE;CACF;CACA,OAAO;AACT;AAIA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACM;CACN,IAAM,IAAO,MAAS,MAAM,EAAI,QAAS,EAAI,OACvC,IAAU,EAAI,OAAO,OAAO,EAAI,QAAQ,MACxC,IAAU,EAAI,OAAO,MAAM,EAAI,QAAQ,KACvC,IAAY,IAAU,EAAI,eAAe,EAAI,QAAQ,QAAQ,EAAI,OAAO,OACxE,IAAa,IAAU,EAAI,gBAAgB,EAAI,QAAQ,SAAS,EAAI,OAAO,QAC3E,KACJ,GACA,GACA,GACA,GACA,GACA,GACA,GACA,MACG;EACH,IAAM,IAAQ,EAAK,UAAU,YAAY,MAAe,WAAW,WAAW;EAC9E,EAAI,KAAK;GACP,OAAO,GAAc,GAAO,GAAI,GAAM,GAAM,GAAO,EAAI,MAAM;GAC7D;GACA;GACA,QAAQ;GACR;EACF,CAAC;CACH;CACA,IAAI,MAAS,KACX,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,OAAO,KAAK;EACnC,IAAM,IAAI,IAAU,IAAO;EAY3B,AAXI,KAAS,KAAK,EAAI,QAAQ,QAAQ,KAAK,EAAI,OAAO,MAAM,KAC1D,EACE,GACA,EAAI,OAAO,MAAM,GACjB,EAAI,YAAY,KAChB,EAAI,YAAY,KAChB,IACA,IACA,IACA,EACF,GACE,KAAO,EAAI,iBAAiB,EAAI,QAAQ,WAAW,KAAK,EAAI,OAAO,SAAS,KAC9E,EACE,GACA,IAAa,EAAI,OAAO,QACxB,EAAI,YAAY,QAChB,EAAI,YAAY,QAChB,IACA,IACA,IACA,EACF;CACJ;MAEA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,OAAO,KAAK;EACnC,IAAM,IAAI,IAAU,IAAO;EAY3B,AAXI,KAAS,KAAK,EAAI,QAAQ,SAAS,KAAK,EAAI,OAAO,OAAO,KAC5D,EACE,EAAI,OAAO,OAAO,GAClB,GACA,EAAI,YAAY,MAChB,EAAI,YAAY,MAChB,IACA,IACA,IACA,EACF,GACE,KAAO,EAAI,gBAAgB,EAAI,QAAQ,UAAU,KAAK,EAAI,OAAO,QAAQ,KAC3E,EACE,IAAY,EAAI,OAAO,OACvB,GACA,EAAI,YAAY,OAChB,EAAI,YAAY,OAChB,IACA,IACA,IACA,EACF;CACJ;AAEJ;;;ACzjBA,SAAgB,EAAsB,GAAuB;CAE3D,QADgB,KAAS,IAAI,KAAK,MAAM,IAAQ,EAAG,IAAI,CAAC,KAAK,MAAM,CAAC,IAAQ,EAAG,MAC7D;AACpB;AAGA,SAAgB,EAAU,GAAY,GAAgC;CAEpE,OADI,KAAkB,IAAU,IACzB,EAAsB,KAAM,MAAO,EAAe;AAC3D;AAGA,SAAgB,GAAe,GAAiB,GAAgC;CAC9E,OAAO,EAAuB,IAAiB,IAAW,GAAG;AAC/D;AAWA,SAAgB,GAAmB,GAAmB,GAAiC;CACrF,IAAM,IAAO,EAAM,sBAAsB,GACnC,IAAgB,WAAW,iBAAiB,CAAI,CAAC,CAAC,aAAa,KAAK,GAIpE,IAAQ,EAAM,cAAc,YAAY;CAC9C,EAAM,mBAAmB,CAAK;CAC9B,IAAM,IAAc,KAAK,IAAI,GAAG,EAAM,sBAAsB,CAAC,CAAC,SAAS,EAAK,MAAM;CAClF,OAAO;EAAE,OAAO,EAAK,QAAQ;EAAK,QAAQ,EAAK;EAAQ;EAAe;CAAY;AACpF;AAEA,SAAgB,KAA4B;CAC1C,OAAO,WAAW,iBAAiB,SAAS,eAAe,CAAC,CAAC,QAAQ,KAAK;AAC5E;;;ACCA,SAAgB,GAAU,GAAc,GAAe,IAAuB,CAAC,GAAa;CAC1F,OAAO,GAAc,GAAM,GAAO,CAAO,CAAC,CAAC,KAAK,MAAS,EAAK,MAAM,EAAK,OAAO,EAAK,GAAG,CAAC;AAC3F;AAGA,SAAgB,GAAc,GAAc,GAAe,IAAuB,CAAC,GAAW;CAC5F,OAAO,GAAc,GAAM,GAAO,CAAO,CAAC,CAAC;AAC7C;AAKA,SAAS,GAAmB,GAAmB,GAA0B;CAEvE,OADI,EAAK,SAAS,IAAI,KAAG,EAAM,IAAI,GAC5B;AACT;AAGA,SAAgB,GAAc,GAA0B;CACtD,IAAM,IAAoB,CAAC,GACvB,IAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,KAAK,EAAK,QAAQ,KAChC,CAAI,MAAM,EAAK,UAAU,EAAK,OAAO,UACnC,EAAM,KAAK;EAAE;EAAO,KAAK;CAAE,CAAC,GAC5B,IAAQ,IAAI;CAGhB,OAAO,GAAmB,GAAO,CAAI;AACvC;AAEA,SAAgB,GAAc,GAAc,GAAe,IAAuB,CAAC,GAAe;CAIhG,IAAI,CAAC,aAAa,KAAK,CAAI,GAAG,OAAO,CAAC;CACtC,IAAM,IAAoB,CAAC,GACvB,IAAY,GACZ,IAAS,EAAQ,mBAAmB;CACxC,KAAK,IAAI,IAAI,GAAG,KAAK,EAAK,QAAQ,KAChC,CAAI,MAAM,EAAK,UAAU,EAAK,OAAO,UACnC,EAAM,KAAK,GAAG,GAAa,GAAM,GAAW,GAAG,GAAO,GAAS,CAAM,CAAC,GACtE,IAAS,GACT,IAAY,IAAI;CAGpB,OAAO,GAAmB,GAAO,CAAI;AACvC;AAGA,SAAgB,GAAU,GAAe,GAAa,GAA6B;CACjF,IAAI,CAAC,GAAU,OAAO,IAAM;CAC5B,IAAI,IAAM;CACV,KAAK,IAAI,IAAI,GAAO,IAAI,GAAK,KAAK,KAAO,EAAS,MAAM;CACxD,OAAO;AACT;AASA,SAAgB,EAAY,GAAe,GAAa,GAAqB,IAAW,GAAW;CAEjG,OADI,KAAO,IAAc,IAClB,GAAU,GAAO,GAAK,CAAQ,IAAI,KAAK,IAAI,GAAU,GAAY,IAAM,GAAG,CAAQ,CAAC;AAC5F;AAEA,SAAS,GAAY,GAAe,GAA6B;CAC/D,OAAO,KAAY,EAAS,MAAU,KAAK,IAAI;AACjD;AAIA,SAAgB,GAAsB,GAAc,IAAuB,CAAC,GAAW;CACrF,IAAM,EAAE,aAAU,cAAW,MAAM,GAC/B,IAAU;CACd,KAAK,IAAM,KAAQ,GAAW,GAAM,GAAG,EAAK,MAAM,GAChD,KAAK,IAAM,KAAW,GAAuB,GAAM,EAAK,OAAO,EAAK,GAAG,GACrE,IAAU,KAAK,IAAI,GAAS,EAAY,EAAQ,OAAO,EAAQ,KAAK,GAAU,CAAQ,CAAC;CAG3F,OAAO;AACT;AA4BA,SAAgB,GACd,GACA,GACM;CACN,IAAI,IAAW;CACf,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAC3B,EAAK,OAAA,QACT,EAAM,GAAG,CAAQ,GACjB;AAEJ;AAEA,SAAS,GAAuB,GAAc,GAAe,GAAyB;CACpF,IAAM,IAAuB,CAAC,GAC1B,IAAe;CACnB,KAAK,IAAI,IAAI,GAAO,IAAI,GAAK,KAAK;EAChC,IAAI,EAAK,OAAA,KAA2B;GAGlC,AAFI,IAAI,KAAc,EAAS,KAAK;IAAE,OAAO;IAAc,KAAK;GAAE,CAAC,GACnE,EAAS,KAAK;IAAE,OAAO;IAAG,KAAK,IAAI;GAAE,CAAC,GACtC,IAAe,IAAI;GACnB;EACF;EACA,IAAI,EAAK,OAAO,KAAK;EAErB,IAAM,IAAc,MAAM;EAC1B,OAAO,IAAI,IAAI,KAAO,EAAK,IAAI,OAAO,MAAK;EAC3C,IAAM,IAAO,IAAI;EACjB,AAAI,CAAC,KAAe,IAAO,MACzB,EAAS,KAAK;GAAE,OAAO;GAAc,KAAK;EAAK,CAAC,GAChD,IAAe;CAEnB;CAEA,OADA,EAAS,KAAK;EAAE,OAAO;EAAc;CAAI,CAAC,GACnC;AACT;AAKA,IAAM,KAAc;AAEpB,SAAS,GAAW,GAAc,GAAe,GAAyB;CACxE,IAAM,IAAoB,CAAC,GACvB,IAAI;CACR,OAAO,IAAI,IAAK;EACd,OAAO,IAAI,KAAO,GAAY,KAAK,EAAK,EAAG,IAAG;EAC9C,IAAI,KAAK,GAAK;EACd,IAAM,IAAY;EAClB,OAAO,IAAI,KAAO,CAAC,GAAY,KAAK,EAAK,EAAG,IAAG;EAC/C,EAAM,KAAK;GAAE,OAAO;GAAW,KAAK;EAAE,CAAC;CACzC;CACA,OAAO;AACT;AAEA,SAAS,GACP,GACA,GACA,GACA,GACA,EAAE,aAAU,cAAW,KACvB,IAAkB,GACN;CACZ,IAAM,IAAQ,GAAW,GAAM,GAAO,CAAG;CACzC,IAAI,EAAM,WAAW,GAAG,OAAO,CAAC;EAAE;EAAO,KAAK;CAAM,CAAC;CACrD,IAAI,KAAS,GAAG,OAAO,CAAC;EAAE,OAAO,EAAM,EAAE,CAAE;EAAO,KAAK,EAAM,EAAM,SAAS,EAAE,CAAE;CAAI,CAAC;CAErF,IAAM,IAAoB,CAAC,GACvB,IAA2B,MAG3B,IAAc,GAGd,IAAa,KAAK,IAAI,GAAG,CAAe,GACtC,UAAuB,IAAQ;CAErC,KAAK,IAAM,KAAQ,GAAO;EACxB,IAAI,IAAgB;EACpB,KAAK,IAAM,KAAW,GAAuB,GAAM,EAAK,OAAO,EAAK,GAAG,GAAG;GACxE,IAAI,IAAW,EAAQ,OACjB,IAAS,EAAQ,KACjB,IAAiB,MAAY,QAAQ,CAAC,IAAgB,IAAW,IAAI,GACrE,IAAY,IAAc,GAAU,GAAgB,GAAQ,CAAQ,GACpE,IAAW,KAAK,IAAI,GAAU,GAAY,IAAS,GAAG,CAAQ,CAAC;GACrE,IAAI,MAAY,QAAQ,IAAY,KAAY,EAAe,GAE7D,AADA,EAAQ,MAAM,GACd,IAAc;QACT;IAOL,KANI,MAAY,SACd,EAAM,KAAK,CAAO,GAClB,IAAa,MAIN;KACP,IAAI,IAAM;KACV,OACE,IAAM,KACN,EAAY,GAAU,IAAM,GAAG,GAAU,CAAQ,KAAK,EAAe,IAErE;KACF,IAAI,MAAQ,KAAU,MAAQ,GAAU;KAGxC,AAFA,EAAM,KAAK;MAAE,OAAO;MAAU,KAAK;KAAI,CAAC,GACxC,IAAa,GACb,IAAW;IACb;IAEA,AADA,IAAU;KAAE,OAAO;KAAU,KAAK;IAAO,GACzC,IAAc,GAAU,GAAU,GAAQ,CAAQ;GACpD;GACA,IAAgB;EAClB;CACF;CAEA,OADI,MAAY,QAAM,EAAM,KAAK,CAAO,GACjC;AACT;;;ACpPA,SAAS,GAAc,GAAgB,GAAmD;CACxF,IAAM,IAAQ,EAAK,IAAI,KAAK,MAAS,EAAK,KAAK,SAAS,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,GAC5E,IAA2C,CAAC;CAClD,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAQ,EAAM,IAAI,EAAE,CAAE,IAAI,EAAM,IAAI,EAAE,CAAE,QAAQ,GAChD,IAAM,EAAM,EAAE,CAAE,IAAI;EAC1B,AAAI,IAAM,KAAO,EAAO,KAAK;GAAE;GAAO;EAAI,CAAC;CAC7C;CACA,OAAO;AACT;AAMA,SAAS,GACP,GACA,GACA,GACA,GACA,GACc;CACd,IAAI,EAAK,MAAM,cAAc,gBAAgB,OAAO,CAAC;EAAE,OAAO;EAAG,KAAK;CAAW,CAAC;CAClF,IAAM,IAAY,CAAC,EAAM,IAAI,IAAK,EAAM,EAAG,CAAC,CACzC,SAAS,MAAS,GAAc,GAAM,CAAO,CAAC,CAAC,CAC/C,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,GAG7B,KAAiB,GAAe,OAA2B;EAC/D;EACA;EACA,SAAS;EACT,gBAAgB;EAChB,eAAe;CACjB,IACM,IAAqB,CAAC,GACxB,IAAS;CACb,KAAK,IAAM,KAAY,GAErB,AADI,EAAS,QAAQ,KAAQ,EAAO,KAAK,EAAc,GAAQ,EAAS,KAAK,CAAC,GAC9E,IAAS,KAAK,IAAI,GAAQ,EAAS,GAAG;CAGxC,OADI,IAAS,KAAY,EAAO,KAAK,EAAc,GAAQ,CAAU,CAAC,GAC/D,GACL,GACA,gBACA,OACA,EAAK,MAAM,cAAc,iBAAiB,iBAAiB,CAC7D;AACF;AAEA,SAAgB,GACd,GACA,GACe;CAEf,OADI,OAAO,KAAU,YAAY,KAAS,IAAU,IAC7C,EACJ,KAAK,OAAa;EAAE,GAAG;EAAS,OAAO,EAAQ,QAAQ;EAAO,KAAK,EAAQ,MAAM;CAAM,EAAE,CAAC,CAC1F,QAAQ,MAAY,EAAQ,MAAM,EAAQ,KAAK;AACpD;AAQA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAO,GAAW,EAAK,OAAO,KAAK,CAAU,GAC7C,IAAO,GAAW,EAAK,OAAO,KAAK,CAAW,GAC9C,IAAQ,GAAoB,CAAI,CAAC,CAAC,KAAK,MAAU;EACrD,IAAM,IAAS,EAAc,EAAM,MAAM,QAAQ,CAAU;EAC3D,OAAO;GACL,MAAM;GACN,MAAM,GAAmB,GAAO,GAAY,CAAK;GACjD,MAAM,EAAM,MAAM;GAClB,QAAQ,EAAM,MAAM;GACpB,KAAK,GAAiB,GAAO,GAAY,CAAK;GAC9C,KAAK,EAAa,EAAM,MAAM,UAAU,CAAU;GAClD;EACF;CACF,CAAC,GAKK,IAAyB,CAAC;CAChC,IAAI,EAAK,MAAM,aAAa,QAAQ;EAClC,IAAI,IAAwB,CAAC,GACzB,IAAO;EACX,KAAK,IAAM,KAAQ,GAAO;GAGxB,IAAM,IADe,KAAK,IAAI,GAAG,EAAU,EAAK,MAAM,EAAK,KAAK,EAAK,GAAG,CACtD,KAAgB,EAAK,OAAO,QAAQ,MAAM,EAAK,OAAO,SAAS,IAC3E,IAAO,EAAQ,WAAW,IAAI,IAAY,IAAO,IAAO;GAO9D,AANI,EAAQ,SAAS,KAAK,IAAO,MAC/B,EAAK,KAAK,CAAO,GACjB,IAAU,CAAC,GACX,IAAO,IAET,EAAQ,KAAK,CAAI,GACjB,IAAO,EAAQ,WAAW,IAAI,IAAY,IAAO,IAAO;EAC1D;EAIA,AAHI,EAAQ,SAAS,KAAG,EAAK,KAAK,CAAO,GAGrC,EAAK,MAAM,eAAa,EAAK,QAAQ;CAC3C,OACE,EAAK,KAAK,CAAK;CAGjB,IAAM,IAAU,EAAO,OAAO,EAAQ,MAChC,IAAU,EAAO,MAAM,EAAQ,KAI/B,IAAQ,EAAK,KAAK,MAAQ;EAC9B,IAAM,IAAW,IAAO,KAAK,IAAI,GAAG,EAAI,SAAS,CAAC,GAC5C,IAAmB,EAAI,QAC1B,GAAK,MAAS,KAAO,EAAK,OAAO,QAAQ,MAAM,EAAK,OAAO,SAAS,IACrE,CACF,GACM,IAAoB,KAAK,IAAI,GAAG,IAAa,IAAW,CAAgB,GAKxE,IAAuB,EAAI,MAC9B,MAAS,EAAK,OAAO,SAAS,QAAQ,EAAK,OAAO,UAAU,IAC/D,GACM,IAAe,EAAI,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC,GAKjD,IAJyB,KAAwB,KAAgB,IAKnE,EAAI,KAAK,MAAM,KAAK,IAAI,GAAG,EAAU,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,IAC3D,GAAoB,GAAK,CAAiB;EAC9C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAC9B,EAAW,EAAI,EAAE,CAAE,MAAM,GAAY,GAAqB,GAAG,GAAG,QAAQ,GAAO,EAC7E,OAAO,EAAO,GAChB,CAAC;EAGH,OAAO;GAAE;GAAK;GAAQ;GAAmB,QAD1B,EAAI,QAAQ,GAAG,MAAS,KAAK,IAAI,GAAG,EAAK,KAAK,UAAU,MAAM,GAAG,CACvC;EAAO;CAClD,CAAC,GAUK,IAAa,EAAM,KAAK,MAAS,EAAK,MAAM,GAC5C,IAAY,IAAO,KAAK,IAAI,GAAG,EAAM,SAAS,CAAC,GACjD;CACJ,IAAI,EAAK,MAAM,aAAa,UAI1B,AAHI,MAAwB,KAAA,IACnB,OAAO,SAAS,CAAW,MAClC,EAAW,KAAK,KAAK,IAAI,GAAa,EAAW,MAAM,CAAC,KAFnB,EAAW,KAAK,GAGvD,IAAc,CAAC,CAAC;MACX;EACL,IAAM,IAAe,EAAW,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,GACnD,IAAW,OAAO,SAAS,CAAW,IACxC,KAAK,IAAI,GAAG,IAAc,IAAe,CAAS,IAClD,GACE,IAAe,GAAsB,EAAK,KAAK;EACrD,IAAI,MAAiB,aAAa,IAAW,GAAG;GAC9C,IAAM,IAAS,EACb,MAAM,KAAK,EAAE,QAAQ,EAAM,OAAO,SAAS,CAAC,GAC5C,CACF;GACA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,QAAQ,KAAK,EAAW,MAAO,EAAO;GACrE,IAAc,EAAgB,SAAS,GAAY,CAAC;EACtD,OACE,IAAc,EACZ,MAAiB,YAAY,UAAU,GACvC,GACA,CACF;CAEJ;CAIA,KAAK,IAAI,IAAW,GAAG,IAAW,EAAM,QAAQ,KAAY;EAC1D,IAAM,EAAE,QAAK,WAAQ,yBAAsB,EAAM,IAC3C,IAAY,EAAW,IACvB,IAAI,EAAY,KAAa,IAAW;EAO9C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK;GACnC,IAAM,IAAQ,EAAI,EAAE,CAAE,MAChB,IAAQ,GAAe,GAAO,CAAI,GAClC,IAAa,EAAI,EAAE,CAAE,QACrB,IAAqB,EAAW,QAAQ,QAAQ,EAAW,WAAW,MAItE,IACJ,EAAM,MAAM,WAAW,KAAA,KAAa,EAAM,MAAM,OAAO,SAAS;GAClE,IACE,MAAU,aACV,CAAC,KACD,CAAC,KACD,MAAc,EAAM,UAAU,QAC9B;IACA,IAAM,IAAY,EAAW,OAAO,GAC9B,IAAe,EAAW,UAAU,GAIpC,IAAa,OAAO,SAAS,CAAW,IAAI,IAAc,KAAA,GAC1D,IAAkB,EACtB,KAAK,IAAI,GAAG,IAAY,IAAY,CAAY,GAChD,EAAa,EAAM,MAAM,WAAW,CAAU,KAAK,GACnD,EAAa,EAAM,MAAM,WAAW,CAAU,CAChD;IACA,IAAI,MAAoB,EAAM,UAAU,QAAQ;IAChD,EAAW,GAAO,GAAY,GAAqB,GAAG,GAAG,QAAQ,GAAO;KACtE,OAAO,EAAO;KACd,QAAQ;IACV,CAAC;GACH;EACF;EACA,IAAM,IAAY,EAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,GAC5C,IAAW,KAAK,IAAI,GAAG,IAAoB,CAAS,GAIpD,IAAY,EAAI,QACnB,GAAG,MAAS,IAAK,IAAK,OAAO,SAAS,QAAiB,IAAK,OAAO,UAAU,OAC9E,CACF,GACM,IAA6B,MAAM,KAAK,EAAE,QAAQ,EAAI,OAAO,SAAS,CAAC,GACvE,IAA4B,MAAM,KAAK,EAAE,QAAQ,EAAI,OAAO,SAAS,CAAC,GACxE;EACJ,IAAI,IAAY,KAAK,IAAW,GAAG;GACjC,IAAM,IAAS,EACb,MAAM,KAAK,EAAE,QAAQ,EAAU,SAAS,CAAC,GACzC,CACF,GACI,IAAa;GACjB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAE9B,AADI,EAAI,EAAE,CAAE,OAAO,SAAS,SAAM,EAAiB,KAAK,EAAO,OAC3D,EAAI,EAAE,CAAE,OAAO,UAAU,SAAM,EAAgB,KAAK,EAAO;GAEjE,IAAU,EAAgB,SAAS,GAAQ,CAAC;EAC9C,OACE,IAAU,EAAgB,GAAiB,EAAK,KAAK,GAAG,GAAQ,CAAQ;EAG1E,IAAI,IAAwB;EAC5B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK;GACnC,IAAM,IAAO,EAAI,IACX,IAAQ,EAAK,MACb,IAAY,EAAK,OAAO,QAAQ,GAChC,IAAa,EAAK,OAAO,SAAS;GAOxC,AANA,KAAyB,EAAiB,KAAM,GAChD,EAAM,YAAY;IAChB,GAAG,EAAM;IACT,GAAG,IAAU,EAAQ,KAAM,IAAI,IAAO;IACtC,GAAG,IAAU,IAAI,GAAgB,GAAO,EAAK,MAAM,YAAY,GAAW,EAAK,MAAM;GACvF,GACA,KAAyB,EAAgB,KAAM;EACjD;CACF;CAEA,IAAM,IAAgB,EAAW,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,GACxD,IAAgB,OAAO,SAAS,CAAW,IAC7C,KAAK,IAAI,GAAa,CAAa,IACnC;CAMJ,IAAI,EAAK,MAAM,SAAS,EAAK,MAAM,OAAO;EACxC,IAAM,IAA0B,CAAC,GAC3B,IAA4B,CAAC;EACnC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;GACrC,IAAM,IAAM,EAAY,KAAM,IAAI;GAClC,KAAK,IAAM,KAAO,GAAc,EAAM,IAAK,CAAO,GAChD,EAAS,KAAK;IACZ,WAAW,EAAI;IACf,UAAU,EAAI,MAAM,EAAI;IACxB,OAAO;IACP,KAAK,IAAM,EAAW;GACxB,CAAC;GAEH,IAAI,IAAI,GAAG;IACT,IAAM,IAAa,EAAY,IAAI,MAAO,IAAI,KAAK,IAAO,EAAW,IAAI;IACzE,IAAI,IAAM,GACR,KAAK,IAAM,KAAW,GAAgB,GAAM,GAAO,GAAG,GAAS,CAAU,GACvE,EAAW,KAAK;KAAE,WAAW;KAAY,UAAU,IAAM;KAAY,GAAG;IAAQ,CAAC;GAGvF;EACF;EAIA,EAAK,iBAAiB,GAAmB;GACvC,QAAQ,EAAY,EAAK,MAAM,QAAQ;GACvC,OAAO,EAAK,MAAM;GAClB,OAAO,EAAK,MAAM;GAClB,UAAU,GAAc,GAAU,EAAK,MAAM,SAAS;GACtD,YAAY,GAAc,GAAY,EAAK,MAAM,SAAS;GAC1D,cAAc;GACd;GACA;GACA,aAAa,EAAK,MAAM;GACxB,aAAa,EAAK,MAAM;GACxB;EACF,CAAC;CACH;CAGA,OADA,GAAsB,GAAM,GAAQ,GAAS,GAAY,CAAa,GAC/D;AACT;AAKA,SAAS,GACP,GACA,GACA,GACA,GACA,GACM;CACN,KAAK,IAAM,KAAS,EAAK,UAClB,EAAY,EAAM,KAAK,MAC5B,EAAM,aAAa;EACjB,MAAM;EACN,WAAW,EAAK,MAAM;EACtB,SAAS,EAAO,OAAO,EAAQ;EAC/B,SAAS,EAAO,MAAM,EAAQ;EAC9B;EACA,aAAa;CACf;AAEJ;AAEA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAO,GAAW,EAAK,OAAO,KAAK,CAAW,GAE9C,IAAQ,GAAoB,CAAI,CAAC,CAAC,KAAK,MAAU;EACrD,IAAM,IAAS,EAAc,EAAM,MAAM,QAAQ,CAAU,GACrD,IAAsB,KAAK,IAAI,GAAG,KAAc,EAAO,QAAQ,MAAM,EAAO,SAAS,EAAE,GAIvF,IAAe,GAAe,GAAO,CAAI,MAAM;EAGrD,EACE,GACA,GACA,KAAoB,OAAO,SAAS,CAAW,IAAI,IAAc,KAAA,GACjE,GACA,GACA,IAAe,SAAS,UACxB,CACF;EACA,IAAM,IAAa,OAAO,SAAS,CAAW,IAAI,IAAc,KAAA,GAK1D,IAAQ,EAAM,MAAM,WACpB,IACJ,MAAU,KAAA,KAAa,EAAM,SAAS,SAClC,EAAM,kBACN,EAAM,SAAS,UACb,EAAM,QACN,EAAM,SAAS,aAAa,MAAe,KAAA,IACzC,GAAe,EAAM,OAAO,CAAU,IACtC,EAAM,iBAIV,IACJ,EAAM,MAAM,cAAc,SACtB,EAAM,MAAM,SAAS,MAAM,YACzB,EAAM,UAAU,SAChB,IACF,KAAA;EACN,OAAO;GACL,MAAM;GACN;GACA,MAAM,EAAM,MAAM;GAClB,QAAQ,EAAM,MAAM;GACpB,KAAK,KAAW,EAAa,EAAM,MAAM,WAAW,CAAU,KAAK;GACnE,KAAK,EAAa,EAAM,MAAM,WAAW,CAAU;GACnD;EACF;CACF,CAAC,GAEK,IAAW,IAAO,KAAK,IAAI,GAAG,EAAM,SAAS,CAAC,GAC9C,IAAmB,EAAM,QAC5B,GAAK,MAAS,KAAO,EAAK,OAAO,OAAO,MAAM,EAAK,OAAO,UAAU,IACrE,CACF,GACM,IAAc,OAAO,SAAS,CAAW,GACzC,IAAkB,EAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC,GACtD,IAAoB,IACtB,KAAK,IAAI,GAAG,IAAc,IAAW,CAAgB,IACrD,GAIE,IAAoB,IACtB,IACA,KAAK,IAAI,GAAmB,CAAe,GAIzC,IAA0B,EAAM,MACnC,MAAS,EAAK,OAAO,QAAQ,QAAQ,EAAK,OAAO,WAAW,IAC/D,GAMM,IACJ,KAAe,EALf,KAAe,KAA2B,KAAmB,KAMzD,GAAoB,GAAO,CAAiB,IAC5C,EAAM,KAAK,MAAM,KAAK,IAAI,GAAG,EAAU,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;CAInE,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAChC,IAAI,EAAa,OAAO,EAAM,EAAE,CAAE,KAAK,UAAU,QAAQ;EACvD,IAAM,IAAO,EAAM,IACb,IAAsB,KAAK,IAC/B,GACA,KAAc,EAAK,OAAO,QAAQ,MAAM,EAAK,OAAO,SAAS,EAC/D,GACM,IAAe,GAAe,EAAK,MAAM,CAAI,MAAM;EACzD,EACE,EAAK,MACL,GACA,EAAa,IACb,GACA,GACA,IAAe,SAAS,UACxB,GACA,EAAE,QAAQ,EAAa,GAAI,CAC7B;CACF;CAGF,IAAM,IAAY,EAAa,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,GAClD,IAAW,KAAK,IAAI,GAAG,IAAoB,CAAS,GAEpD,IAAY,EAAM,QACrB,GAAG,MAAS,IAAK,IAAK,OAAO,QAAQ,QAAiB,IAAK,OAAO,WAAW,OAC9E,CACF,GACM,IAA6B,MAAM,KAAK,EAAE,QAAQ,EAAM,OAAO,SAAS,CAAC,GACzE,IAA4B,MAAM,KAAK,EAAE,QAAQ,EAAM,OAAO,SAAS,CAAC,GAC1E;CACJ,IAAI,IAAY,KAAK,IAAW,GAAG;EACjC,IAAM,IAAS,EACb,MAAM,KAAK,EAAE,QAAQ,EAAU,SAAS,CAAC,GACzC,CACF,GACI,IAAa;EACjB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAEhC,AADI,EAAM,EAAE,CAAE,OAAO,QAAQ,SAAM,EAAiB,KAAK,EAAO,OAC5D,EAAM,EAAE,CAAE,OAAO,WAAW,SAAM,EAAgB,KAAK,EAAO;EAEpE,IAAU,EAAgB,SAAS,GAAc,CAAC;CACpD,OACE,IAAU,EAAgB,GAAiB,EAAK,KAAK,GAAG,GAAc,CAAQ;CAGhF,IAAM,IAAU,EAAO,OAAO,EAAQ,MAChC,IAAU,EAAO,MAAM,EAAQ,KACjC,IAAwB;CAC5B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAO,EAAM,IACb,IAAQ,EAAK,MACb,IAAW,EAAK,OAAO,OAAO,GAC9B,IAAc,EAAK,OAAO,UAAU;EAO1C,AANA,KAAyB,EAAiB,KAAM,GAChD,EAAM,YAAY;GAChB,GAAG,EAAM;GACT,GAAG,IAAU,GAAiB,GAAO,EAAK,MAAM,YAAY,GAAY,EAAK,MAAM;GACnF,GAAG,IAAU,EAAQ,KAAM,IAAI,IAAO;EACxC,GACA,KAAyB,EAAgB,KAAM;CACjD;CAEA,IAAM,IAAgB,IAAY,IAAW,GACvC,IAAgB,IAAc,KAAK,IAAI,GAAa,CAAa,IAAI;CAI3E,IAAI,EAAK,MAAM,SAAS,EAAM,SAAS,GAAG;EACxC,IAAM,IAA4B,CAAC,GAC7B,IAAQ,EACX,KAAK,MAAS,EAAK,KAAK,SAAS,CAAC,CAClC,MAAM,CAAC,CACP,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;EAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;GACrC,IAAM,IAAY,EAAM,IAAI,EAAE,CAAE,IAAI,EAAM,IAAI,EAAE,CAAE,SAAS,GACrD,IAAW,EAAM,EAAE,CAAE,IAAI,IAAU;GACzC,AAAI,IAAW,KAAG,EAAW,KAAK;IAAE;IAAW;IAAU,OAAO;IAAG,KAAK;GAAW,CAAC;EACtF;EACA,EAAK,iBAAiB,GAAmB;GACvC,QAAQ,EAAY,EAAK,MAAM,QAAQ;GACvC,OAAO;GACP,OAAO,EAAK,MAAM;GAClB,UAAU,CAAC;GACX,YAAY,GAAc,GAAY,EAAK,MAAM,SAAS;GAC1D,cAAc;GACd;GACA;GACA,aAAa,EAAK,MAAM;GACxB,aAAa,EAAK,MAAM;GACxB;EACF,CAAC;CACH;CAGA,OADA,GAAsB,GAAM,GAAQ,GAAS,GAAY,CAAa,GAC/D;AACT;AAMA,SAAS,GACP,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAM,MAAM,cAAc,SAAS,IAAc,EAAM,MAAM,WACrE,IAAY,EAAE,OAAO,GACrB,IAAe,EAAE,UAAU,GAC3B,IAAiB,IAAY,EAAM,UAAU,QAC7C,IAAW,EAAE,QAAQ,QAAQ,EAAE,WAAW,MAC1C,IAAa,EAAE,QAAQ,QAAQ,EAAE,WAAW,MAC5C,IAAgB,EAAE,WAAW,QAAQ,EAAE,QAAQ;CAIrD,OAHI,IAAiB,KAAK,MAAM,IAAiB,CAAC,IAC9C,IAAmB,IAAiB,IACpC,IAAsB,IACnB,IAAY,EAAiB,GAAO,GAAW,EAAM,UAAU,MAAM;AAC9E;AAMA,SAAS,GACP,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAM,MAAM,cAAc,SAAS,IAAc,EAAM,MAAM,WACrE,IAAa,EAAE,QAAQ,GACvB,IAAc,EAAE,SAAS,GACzB,IAAiB,IAAiB,EAAM,UAAU,OAClD,IAAW,EAAE,SAAS,QAAQ,EAAE,UAAU,MAC1C,IAAc,EAAE,SAAS,QAAQ,EAAE,UAAU,MAC7C,IAAe,EAAE,UAAU,QAAQ,EAAE,SAAS;CAIpD,OAHI,IAAiB,KAAK,MAAM,IAAiB,CAAC,IAC9C,IAAoB,IAAiB,IACrC,IAAqB,IAClB,IAAa,EAAiB,GAAO,GAAgB,EAAM,UAAU,KAAK;AACnF;AAMA,SAAgB,EACd,GACA,GACA,GACU;CACV,IAAM,IAAQ,EAAM;CACpB,IAAI,MAAU,GAAG,OAAO,CAAC;CAEzB,IAAM,IAAoB,CAAC,GACvB,IAAS;CAEb,IAAI,MAAY,mBAAmB,IAAQ,GAAG;EAC5C,IAAM,IAAU,KAAK,MAAM,KAAY,IAAQ,EAAE,GAC3C,IAAQ,IAAW,KAAW,IAAQ;EAC5C,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAEzB,AADA,EAAQ,KAAK,CAAM,GACnB,KAAU,EAAM,KAAM,IAAW,MAAI;EAEvC,OAAO;CACT;CAMA,KAAK,MAAY,kBAAkB,MAAY,mBAAmB,IAAW,GAAG;EAI9E,IAAM,IAAO,EAHG,MAAM,KAAK,EAAE,QAAQ,IAAQ,EAAE,IAAI,GAAG,MACpD,MAAY,kBAAkB,MAAM,KAAK,MAAM,IAAQ,IAAI,CAE9B,GAAS,CAAQ;EAChD,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAGzB,AAFA,KAAU,EAAK,IACf,EAAQ,KAAK,CAAM,GACnB,KAAU,EAAM;EAElB,OAAO;CACT;CAEA,AAAI,MAAY,WAAU,IAAS,KAAK,MAAM,IAAW,CAAC,IACjD,MAAY,UAAO,IAAS;CAErC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAEzB,AADA,EAAQ,KAAK,CAAM,GACnB,KAAU,EAAM;CAElB,OAAO;AACT;AAgBA,SAAgB,GACd,GAOA,GACU;CACV,IAAM,IAAQ,EAAM,QACd,KAAS,GAAe,MAC5B,KAAK,IAAI,GAAG,EAAU,GAAO,EAAM,EAAM,CAAE,OAAO,GAAG,EAAM,EAAM,CAAE,GAAG,CAAC,GACnE,IAAO,EAAM,KAAK,MAAM,EAAE,IAAI,GAI9B,IAAU,KADU,EAAK,QAAQ,GAAG,GAAG,MAAM,IAAI,EAAM,GAAG,CAAC,GAAG,CACvC,GAEvB,IAAkB,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,CAAC,GACvD,IAAoB,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,EAAK;CAMnE,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK;EAC9B,IAAM,IAAe,EAAM,EAAK,IAAK,CAAC;EAEtC,EADmB,IAAU,EAAM,EAAE,CAAE,OAAO,EAAM,EAAE,CAAE,YAEvC,KACd,KAAW,EAAK,KAAM,KACtB,CAAC,KAAW,EAAK,KAAM,OAExB,EAAM,KAAK,GACX,EAAO,KAAK;CAEhB;CAIA,SAAS;EACP,IAAM,IAAqB,CAAC;EAC5B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK,AAAK,EAAO,MAAI,EAAS,KAAK,CAAC;EAC/D,IAAI,EAAS,WAAW,GAAG;EAE3B,IAAM,IAAc,EAAM,QAAQ,GAAG,GAAG,MAAO,EAAO,KAAK,IAAI,IAAI,GAAI,CAAC,GAClE,IAAoB,EAAS,QAAQ,GAAG,MAAM,IAAI,EAAK,IAAK,CAAC,GAC7D,IAAY,IAAY,IAAc,GACtC,IAAS,IAAU,KAAK,IAAI,GAAG,CAAS,IAAI,KAAK,IAAI,GAAG,CAAC,CAAS,GAGlE,IAAS,EADC,EAAS,KAAK,MAAO,IAAU,EAAM,EAAE,CAAE,OAAO,EAAK,KAAM,EAAM,EAAE,CAAE,MACpD,GAAS,CAAM,GAC1C,IAAY,EAAS,KAAK,GAAG,MAAM,EAAK,MAAO,IAAU,EAAO,KAAM,CAAC,EAAO,GAAI,GAClF,IAAU,EAAS,KAAK,GAAG,MAAM,EAAM,EAAU,IAAK,CAAC,CAAC,GACxD,IAAiB,EAAQ,QAAQ,GAAG,GAAG,MAAM,KAAK,IAAI,EAAU,KAAM,CAAC;EAE7E,IAAI,MAAmB,GAAG;GACxB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAS,QAAQ,KAAK,EAAM,EAAS,MAAO,EAAQ;GACxE;EACF;EAGA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAS,QAAQ,KAAK;GACxC,IAAM,IAAY,EAAQ,KAAM,EAAU;GAC1C,CAAI,IAAiB,IAAI,IAAY,IAAI,IAAY,OACnD,EAAM,EAAS,MAAO,EAAQ,IAC9B,EAAO,EAAS,MAAO;EAE3B;CACF;CACA,OAAO;AACT;AAOA,SAAgB,EAAkB,GAAmB,GAAyB;CAC5E,IAAM,IAAM,EAAQ,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC;CAC7C,IAAI,MAAQ,KAAK,KAAS,GAAG,OAAO,EAAQ,UAAU,CAAC;CACvD,IAAM,IAAM,EAAQ,KAAK,MAAO,IAAI,IAAO,CAAK,GAC1C,IAAU,EAAI,IAAI,KAAK,KAAK,GAC9B,IAAU,IAAQ,EAAQ,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC;CACvD,IAAI,IAAU,GAAG;EACf,IAAM,IAAQ,EACX,KAAK,GAAG,MAAM,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAU,CAAC,CAC9C,MAAM,GAAG,MAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAG;EAC7D,KAAK,IAAM,CAAC,MAAM,GAAO;GACvB,IAAI,KAAW,GAAG;GAElB,AADA,EAAQ,MAAO,GACf;EACF;CACF;CACA,OAAO;AACT;AAIA,SAAgB,GAAe,GAAmB,GAA6C;CAC7F,OAAO,EAAM,MAAM,cAAc,SAC7B,EAAO,MAAM,aACZ,EAAM,MAAM;AACnB;AAEA,SAAgB,EACd,GACA,GACA,GACQ;CAGR,OAFI,MAAU,WAAiB,KAAK,IAAI,GAAG,KAAK,OAAO,IAAY,KAAS,CAAC,CAAC,IAC1E,MAAU,QAAc,KAAK,IAAI,GAAG,IAAY,CAAK,IAClD;AACT;AAWA,SAAS,GAAmB,GAAmB,GAAoB,GAA+B;CAChG,IAAM,IAAQ,EAAM,MAAM,WACpB,IAAQ,EAAM,MAAM;CAO1B,OANI,MAAU,KAAA,KAAa,EAAM,SAAS,SACjC,EAAmB,GAAO,GAAY,GAAO,CAAK,IAEvD,MAAU,KAAA,KAAa,EAAM,SAAS,SACjC,EAAmB,GAAO,GAAY,GAAO,CAAK,IAEpD,EAAoB,GAAO,CAAK;AACzC;AAQA,SAAS,GAAoB,GAAgC;CAC3D,IAAM,IAAW,EAAK,SACnB,QAAQ,MAAM,CAAC,EAAY,EAAE,KAAK,CAAC,CAAC,CACpC,MAAM,GAAG,MAAM,EAAE,MAAM,QAAQ,EAAE,MAAM,KAAK;CAE/C,OADI,EAAK,MAAM,eAAa,EAAS,QAAQ,GACtC;AACT;AAKA,SAAS,GAAsB,GAA6C;CAI1E,OAHK,EAAM,cACP,EAAM,iBAAiB,UAAgB,QACvC,EAAM,iBAAiB,QAAc,UAClC,EAAM,eAHkB,EAAM;AAIvC;AAEA,SAAgB,GAAiB,GAA+C;CAI9E,IAAM,IAAU,EAAM,mBAAmB,YAAY,UAAU,EAAM;CAIrE,OAHK,EAAM,cACP,MAAY,UAAgB,QAC5B,MAAY,QAAc,UACvB,IAHwB;AAIjC;AASA,SAAS,GAAiB,GAAmB,GAAoB,GAA+B;CAI9F,OAHI,EAAM,MAAM,aAAa,SACpB,EAAM,MAAM,SAAS,MAAM,YAAY,GAAqB,GAAO,CAAK,IAAI,IAE9E,EAAa,EAAM,MAAM,UAAU,CAAU,KAAK;AAC3D;;;AC3xBA,SAAgB,GAAY,GAA6B;CACvD,OAAO,MAAS,UAAU,MAAS;AACrC;AAsIA,SAAgB,GAAc,GAAgC;CAC5D,OAAO,EAAK,SAAS,QAAQ,MAAU,EAAM,SAAS;AACxD;AAMA,SAAgB,GAAkB,GAAqD;CACrF,OAAO;EACL,OAAO,EAAM,cAAc,IAAI,EAAM,eAAe;EACpD,QAAQ,EAAM,cAAc,IAAI,EAAM,eAAe;CACvD;AACF;AAOA,SAAgB,GAAa,GAAqD;CAChF,IAAI,EAAM,mBAAmB,QAAQ,OAAO;EAAE,OAAO;EAAG,QAAQ;CAAE;CAClE,IAAM,IAAQ,GAAkB,CAAK;CACrC,OAAO;EACL,OAAO,EAAM,SAAS,MAAM,WAAW,EAAM,QAAQ;EACrD,QAAQ,EAAM,SAAS,MAAM,WAAW,EAAM,SAAS;CACzD;AACF;AA8bA,SAAgB,KAA8B;CAC5C,OAAO;EACL,SAAS;EACT,eAAe;EACf,aAAa;EACb,UAAU;EACV,aAAa;EACb,UAAU;EACV,YAAY;EACZ,WAAW,KAAA;EACX,OAAO;EAGP,gBAAgB;EAChB,cAAc;EACd,YAAY;EACZ,WAAW;EACX,cAAc;EACd,aAAa;EACb,qBAAqB,EAAE,MAAM,OAAO;EACpC,kBAAkB,EAAE,MAAM,OAAO;EACjC,iBAAiB,CAAC,GAAU,CAAC;EAC7B,cAAc,CAAC,GAAU,CAAC;EAC1B,cAAc;GAAE,WAAW;GAAO,OAAO;EAAM;EAC/C,mBAAmB;EACnB,iBAAiB,EAAE,MAAM,OAAO;EAChC,eAAe,EAAE,MAAM,OAAO;EAC9B,cAAc,EAAE,MAAM,OAAO;EAC7B,YAAY,EAAE,MAAM,OAAO;EAC3B,OAAO,KAAA;EACP,QAAQ,KAAA;EACR,UAAU;EACV,WAAW;EACX,UAAU,KAAA;EACV,WAAW,KAAA;EACX,SAAS,EAAW;EACpB,QAAQ;GAAE,KAAK;GAAG,OAAO;GAAG,QAAQ;GAAG,MAAM;EAAE;EAC/C,UAAU;EACV,QAAQ;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;EAC3D,MAAM;EACN,MAAM;EACN,QAAQ,EAAW;EACnB,aAAa;GAAE,KAAK;GAAS,OAAO;GAAS,QAAQ;GAAS,MAAM;EAAQ;EAC5E,UAAU;GAAE,GAAG;GAAW,GAAG;EAAU;EACvC,gBAAgB;EAChB,eAAe;GAAE,GAAG;GAAG,GAAG;EAAE;EAC5B,gBAAgB;GAAE,GAAG;GAAG,GAAG;EAAE;EAC7B,YAAY;GAAE,GAAG;GAAM,GAAG;EAAK;EAC/B,gBAAgB;EAChB,YAAY;EACZ,SAAS;EACT,SAAS;EACT,UAAU;EACV,cAAc;EACd,OAAO,KAAA;EACP,iBAAiB,KAAA;EACjB,iBAAiB;EACjB,YAAY;EACZ,WAAW;EACX,oBAAoB;EACpB,aAAa;GAAE,KAAK,KAAA;GAAW,OAAO,KAAA;GAAW,QAAQ,KAAA;GAAW,MAAM,KAAA;EAAU;EACpF,kBAAkB;EAClB,WAAW;EACX,YAAY;EACZ,WAAW;EACX,aAAa;EACb,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAChB,aAAa;EACb,eAAe;EACf,UAAU;EACV,SAAS;EACT,QAAQ;EACR,eAAe;EACf,OAAO;EACP,OAAO;EACP,WAAW;EACX,WAAW;EACX,qBAAqB;EACrB,aAAa;EACb,aAAa;EACb,YAAY;EACZ,YAAY;EACZ,mBAAmB;EACnB,kBAAkB;EAClB,kBAAkB;CACpB;AACF;AAEA,SAAgB,IAAqB;CACnC,OAAO;EAAE,KAAK;EAAG,OAAO;EAAG,QAAQ;EAAG,MAAM;CAAE;AAChD;AAGA,SAAgB,KAAuB;CACrC,OAAO;EAAE,KAAK,EAAE,MAAM,OAAO;EAAG,KAAK,EAAE,MAAM,OAAO;CAAE;AACxD;;;ACpuBA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAK,OAIb,IAAe,OAAO,SAAS,CAAW,IAAI,IAAc,KAAA,GAI5D,IAAgB,EAAK,SAAS,MAC9B,IAAgB,EAAK,SAAS,MAC9B,IAAO,IAAgB,EAAc,MAAM,GAAW,GAAO,KAAK,CAAU,GAC5E,IAAO,IAAgB,EAAc,MAAM,GAAW,GAAO,KAAK,CAAY,GAE9E,IAAY,GAChB,GACA,GACA,GACA,GACA,GACA,EAAK,UAAU;EAAE,KAAK,EAAK,QAAQ;EAAS,KAAK,EAAK,QAAQ;CAAQ,IAAI,KAAA,CAC5E,GACM,EAAE,aAAU,WAAQ,aAAU,aAAU,cAAW,cAAW,iBAAc,oBAChF,GACI,IAAU,EAAS,KAAK,MAAU,EAAc,EAAM,MAAM,QAAQ,CAAU,CAAC,GAC/E,IAAY,EAAS,KAAK,MAC9B,EAAM,MAAM,gBAAgB,SAAS,EAAM,eAAe,EAAM,MAAM,WACxE,GAIM,IAAO,EAAS,IAAI,EAAW,GAM/B,IAA0B,IAC5B,GAA0B,CAAa,IACvC,GACE,GACA,GACA,GAAkB,GAAW,GAAM,GAAS,CAAK,GACjD,GACA,GACA,EAAM,mBAAmB,SAC3B,GACE,IAAS,IACX,EAAc,YACd,GAAe,GAAW,GAAY,EAAM,cAAc,GAOxD,IAAuB,CAAC;CAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAS,QAAQ,KAAK;EACxC,IAAM,IAAQ,EAAS,IACjB,IAAI,EAAO,MAAM,IACjB,IAAQ,GAAW,GAAQ,EAAU,OAAO,EAAE,IAAI,OAAO,EAAE,IAAI,IAAI,GACnE,IAAS,EAAQ,IACjB,IAAS,KAAK,IAAI,GAAG,IAAQ,GAAO,CAAM,CAAC,GAC3C,IAAM,EAAK;EAGjB,IAAI,EAAI,QAAQ,EAAI,MAAM;GACxB,IAAM,IAAO,EAAI,OACb,GACE,GACA,GACA,GACA,EAAE,IAAI,OACN,EAAE,IAAI,MACN,GAAc,GAAO,QAAQ,GAAQ,CAAK,CAC5C,IACA,KAAA;GACJ,EAAM,UAAU;IAAE,SAAS,EAAE,IAAI;IAAM,SAAS,EAAE,IAAI;IAAM;IAAM,MAAM,KAAA;GAAU;EACpF,OACE,EAAM,UAAU,KAAA;EAElB,IAAM,IAAU,EAAU,IACpB,IAAW,EAAO,SAAS,QAAQ,EAAO,UAAU,MACpD,IAAmB,EAAM,MAAM,UAAU,KAAA,KAAa,EAAM,MAAM,MAAM,SAAS;EAoBvF,AAnBI,EAAI,OACN,EAAW,GAAO,GAAO,KAAA,GAAW,GAAG,GAAG,QAAQ,GAAO,EAAE,OAAO,EAAO,CAAC,IACjE,MAAY,aAAa,CAAC,KAAY,CAAC,IAahD,EAAW,GAAO,GAAO,KAAA,GAAW,GAAG,GAAG,QAAQ,GAAO,EAAE,OADzC,EAAU,GAN1B,EAAM,MAAM,aAAa,SACrB,EAAM,MAAM,SAAS,MAAM,YACzB,GAAqB,GAAO,CAAK,IACjC,IACD,EAAa,EAAM,MAAM,UAAU,CAAK,KAAK,GACvC,GAAkB,EAAM,MAAM,UAAU,GAAO,GAAO,CACzB,CACwB,EAAU,CAAC,IAE7E,EAAW,GAAO,GAAQ,KAAA,GAAW,GAAG,GAAG,UAAU,CAAK,GAE5D,EAAW,KAAK,EAAM,UAAU,KAAK;CACvC;CAMA,IAAM,IAA0B,IAC5B,GAA0B,CAAa,IACvC,GACE,GACA,GACA,GAAe,GAAW,GAAM,CAAO,GACvC,KAAgB,eAChB,GACA,EAAM,iBAAiB,SACzB,GACE,IAAc,GAAY,CAAS,GACnC,IAAS,IACX,EAAc,YACd,GAAe,GAAW,KAAgB,GAAa,EAAM,YAAY,GAIvE,IAAU,EAAO,OAAO,EAAQ,MAChC,IAAU,EAAO,MAAM,EAAQ;CACrC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAS,QAAQ,KAAK;EACxC,IAAM,IAAQ,EAAS,IACjB,IAAI,EAAO,MAAM,IACjB,IAAS,EAAQ,IACjB,IAAQ,GAAW,GAAQ,EAAU,OAAO,EAAE,IAAI,OAAO,EAAE,IAAI,IAAI,GACnE,IAAQ,GAAW,GAAQ,EAAU,OAAO,EAAE,IAAI,OAAO,EAAE,IAAI,IAAI,GACnE,IAAS,KAAK,IAAI,GAAG,IAAQ,GAAO,CAAM,CAAC,GAC3C,IAAQ,GAAe,GAAO,CAAI,GAClC,IAAW,EAAO,QAAQ,QAAQ,EAAO,WAAW,MACpD,IACJ,EAAM,MAAM,WAAW,KAAA,KAAa,EAAM,MAAM,OAAO,SAAS;EAClE,IAAI,EAAK,EAAE,CAAE,MASX,AARA,EAAM,QAAS,OAAO,GACpB,GACA,GACA,GACA,EAAE,IAAI,OACN,EAAE,IAAI,MACN,GAAc,GAAO,QAAQ,GAAQ,CAAK,CAC5C,GACA,EAAW,GAAO,GAAO,GAAO,GAAG,GAAG,QAAQ,GAAO;GACnD,OAAO,EAAW;GAClB,QAAQ;EACV,CAAC;OACI,IAAI,MAAU,aAAa,CAAC,KAAY,CAAC,GAAmB;GAWjE,IAAM,IAAY,EAAU,GAN1B,EAAM,MAAM,cAAc,SACtB,EAAM,MAAM,SAAS,MAAM,YACzB,EAAM,UAAU,SAChB,IACD,EAAa,EAAM,MAAM,WAAW,CAAK,KAAK,GACxC,EAAa,EAAM,MAAM,WAAW,CACP,CAAI;GAC9C,AAAI,MAAc,EAAM,UAAU,UAChC,EAAW,GAAO,GAAO,GAAO,GAAG,GAAG,QAAQ,GAAO;IACnD,OAAO,EAAW;IAClB,QAAQ;GACV,CAAC;EAEL,OAAO,AAAI,EAAM,MAAM,QAAQ,SAAS,aAItC,EAAW,GAAO,GAAO,GAAO,GAAG,GAAG,QAAQ,GAAO,EAAE,OAAO,EAAW,GAAI,CAAC;EAEhF,EAAM,YAAY;GAChB,GAAG,EAAM;GACT,GACE,IACA,EAAO,EAAE,IAAI,SACb,GAAe,EAAU,IAAK,EAAO,MAAM,EAAO,OAAO,GAAO,EAAM,UAAU,KAAK;GACvF,GACE,IACA,EAAO,EAAE,IAAI,SACb,GAAe,GAAO,EAAO,KAAK,EAAO,QAAQ,GAAO,EAAM,UAAU,MAAM;EAClF;CACF;CAEA,IAAM,IAAgB,OAAO,SAAS,CAAW,IAC7C,KAAK,IAAI,GAAa,CAAW,IACjC;CAMJ,IAAI,EAAM,SAAS,EAAM,OAAO;EAC9B,IAAM,IAAW,EAAU,MAAM,QAC3B,IAAW,EAAU,MAAM,QAI3B,IAAW,MAAM,KAAK,EAAE,QAAQ,EAAS,SAC7C,MAAM,KAAK,EAAE,QAAQ,EAAS,SAAS,EAAK,CAC9C,GACM,IAAa,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAW,CAAC,EAAE,SAChE,MAAM,KAAK,EAAE,QAAQ,EAAS,SAAS,EAAK,CAC9C,GACM,IAAa,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAW,CAAC,EAAE,SAChE,MAAM,KAAK,EAAE,QAAQ,EAAS,SAAS,EAAK,CAC9C;EACA,KAAK,IAAM,KAAK,EAAO,OACrB,KAAK,IAAI,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI,QAAQ,EAAE,IAAI,QAAQ,IAAI,GAAU,KACtE,KAAK,IAAI,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI,QAAQ,EAAE,IAAI,QAAQ,IAAI,GAAU,KAGtE,AAFA,EAAS,EAAE,CAAE,KAAK,IACd,IAAI,IAAI,EAAE,IAAI,QAAQ,EAAE,IAAI,QAAQ,IAAI,IAAW,MAAG,EAAW,EAAE,CAAE,KAAK,KAC1E,IAAI,IAAI,EAAE,IAAI,QAAQ,EAAE,IAAI,QAAQ,IAAI,IAAW,MAAG,EAAW,EAAE,CAAE,KAAK;EAIpF,IAAM,KACJ,GACA,GACA,GACA,GACA,GACA,MAEA,EAAU,KAAK,GAAU,OAAO;GAC9B,OAAO;GACP,KAAK,IAAW,EAAM;GACtB,SAAS,EAAQ,EAAI,GAAG,MAAM;GAC9B,gBAAgB,EAAO,CAAC;GACxB,eAAe,EAAM,CAAC;EACxB,EAAE,GACE,KACJ,GACA,GACA,MACkB;GAClB,IAAM,IAAuB,CAAC;GAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAU,QAAQ,KAAK;IACzC,IAAM,IAAY,EAAU,IAAI,KAAM,EAAM,IAAI,IAC1C,IAAW,EAAU,KAAM;IAC7B,WAAY,IAChB,KAAK,IAAM,KAAW,GACpB,EAAU,IAAI,CAAC,GACf,EAAM,WACN,EAAM,qBACN,EAAM,SACR,GACE,EAAM,KAAK;KAAE;KAAW;KAAU,GAAG;IAAQ,CAAC;GAElD;GACA,OAAO;EACT,GACM,IAAW,EAAa,GAAQ,EAAU,QAAQ,MACtD,EACE,GACA,GACA,EAAU,OACV,IACC,MAAM,EAAS,EAAI,GAAG,MAAM,KAC5B,MAAM,EAAS,IAAM,EAAE,GAAG,MAAM,EACnC,CACF,GACM,IAAa,EAAa,GAAQ,EAAU,QAAQ,MACxD,EACE,GACA,GACA,EAAU,OACV,IACC,MAAM,EAAS,EAAE,GAAG,MAAQ,KAC5B,MAAM,EAAS,EAAE,GAAG,IAAM,MAAM,EACnC,CACF;EACA,EAAK,iBAAiB,GAAmB;GACvC,QAAQ,EAAY,EAAM,QAAQ;GAClC,OAAO,EAAM;GACb,OAAO,EAAM;GACb;GACA;GACA,cAAc;GACd;GACA;GACA,aAAa,EAAM;GACnB,aAAa,EAAM;GACnB;EACF,CAAC;CACH;CAMA,IAAM,KAAY,EAAK,SAAS,QAAQ,MAAU,EAAY,EAAM,KAAK,CAAC;CAC1E,IAAI,GAAU,SAAS,GAAG;EACxB,IAAM,IAAmB,EAAY,CAAK,IACtC;GACE,GAAG,EAAO;GACV,GAAG,EAAO;GACV,OAAO,EAAQ,OAAO,IAAa,EAAQ;GAC3C,QAAQ,EAAQ,MAAM,IAAgB,EAAQ;EAChD,IACA;GAAE,GAAG;GAAS,GAAG;GAAS,OAAO;GAAY,QAAQ;EAAc;EACvE,KAAK,IAAM,KAAS,IAAW;GAC7B,IAAM,IAAO,GACX,EAAM,MAAM,iBACZ,EAAM,MAAM,eACZ,GACA,EAAO,WACP,GACA,EAAU,OACV,CAAC,EAAQ,MACT,IAAa,EAAQ,KACvB,GACM,IAAO,GACX,EAAM,MAAM,cACZ,EAAM,MAAM,YACZ,GACA,EAAO,WACP,GACA,EAAU,OACV,CAAC,EAAQ,KACT,IAAgB,EAAQ,MAC1B;GACA,EAAM,aAAa;IACjB,MAAM;IACN,MAAM;KACJ,GAAG,IAAU,EAAK;KAClB,GAAG,IAAU,EAAK;KAClB,OAAO,KAAK,IAAI,GAAG,EAAK,MAAM,EAAK,KAAK;KACxC,QAAQ,KAAK,IAAI,GAAG,EAAK,MAAM,EAAK,KAAK;IAC3C;IACA;GACF;EACF;CACF;CAEA,OAAO;AACT;AAGA,SAAS,GAAY,GAAqD;CACxE,IAAM,IAAS,EAAM,MAAM,YAAY;CACvC,OAAO;EACL,MAAM,KAAU,EAAM,MAAM,oBAAoB,SAAS;EACzD,MAAM,KAAU,EAAM,MAAM,iBAAiB,SAAS;CACxD;AACF;AAWA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACiB;CACjB,IAAM,IAAO,EAAU,KAAU,EAAO,OAClC,IAAQ,EAAO,MAAM,MAAM,GAAO,IAAQ,CAAI;CAGpD,OAFA,EAAM,KAAK,KAAK,IAAI,GAAG,EAAM,KAAM,EAAO,KAAK,GAC/C,EAAM,IAAO,KAAK,KAAK,IAAI,GAAG,EAAM,IAAO,KAAM,EAAO,GAAG,GACpD;EACL,WAAW,MAAM,KAAK,EAAE,QAAQ,EAAK,IAAI,GAAG,MAAO,MAAM,IAAI,IAAI,EAAU,IAAQ,KAAM,CAAK;EAC9F;EACA,WAAW,MAAM,KAAK,EAAE,QAAQ,EAAK,IAAI,GAAG,MAAO,MAAM,IAAI,IAAI,EAAO,UAAU,IAAQ,EAAI;EAC9F;CACF;AACF;AAMA,SAAS,GAA0B,GAAkC;CACnE,OAAO;EAAE,OAAO,EAAE;EAAO,WAAW,EAAE;EAAW,QAAQ,EAAE;CAAM;AACnE;AAKA,SAAS,GACP,GACA,GACA,GACA,GACc;CACd,IAAM,IAAsB,CAAC;CAkB7B,OAjBA,EAAU,SAAS,SAAS,GAAO,MAAM;EACvC,IAAM,IAAI,EAAU,OAAO,MAAM,IAC3B,IAAS,EAAQ;EACvB,IAAI,EAAK,EAAE,CAAE,MAAM;GACjB,IAAM,IAAS,GAAc,GAAO,QAAQ,GAAQ,CAAC;GACrD,KAAK,IAAM,KAAQ,GAAqB,GAAO,QAAQ,GAAG,GAAQ,CAAK,GACrE,EAAM,KAAK;IAAE,GAAG;IAAM,OAAO,EAAK,QAAQ,EAAE,IAAI;GAAM,CAAC;GAEzD;EACF;EACA,EAAM,KAAK;GACT,OAAO,EAAE,IAAI;GACb,MAAM,EAAE,IAAI;GACZ,KAAK,GAAkB,GAAO,OAAO,CAAK,IAAI,GAAO,CAAM;GAC3D,KAAK,GAAkB,GAAO,OAAO,CAAK,IAAI,GAAO,CAAM;EAC7D,CAAC;CACH,CAAC,GACM;AACT;AAKA,SAAS,GACP,GACA,GACA,GACc;CACd,IAAM,IAAsB,CAAC;CAqB7B,OApBA,EAAU,SAAS,SAAS,GAAO,MAAM;EACvC,IAAM,IAAI,EAAU,OAAO,MAAM,IAC3B,IAAS,EAAQ;EACvB,IAAI,EAAK,EAAE,CAAE,MAAM;GACjB,IAAM,IAAS,GAAc,GAAO,QAAQ,GAAQ,CAAC;GACrD,KAAK,IAAM,KAAQ,GAAqB,GAAO,QAAQ,GAAG,CAAM,GAC9D,EAAM,KAAK;IAAE,GAAG;IAAM,OAAO,EAAK,QAAQ,EAAE,IAAI;GAAM,CAAC;GAEzD;EACF;EACA,IAAM,IAAS,EAAM,UAAU,SAAS,GAAO,CAAM,GAI/C,IACJ,EAAM,MAAM,cAAc,UAAU,EAAM,MAAM,SAAS,MAAM,YAC3D,GAAO,CAAM,IACb;EACN,EAAM,KAAK;GAAE,OAAO,EAAE,IAAI;GAAO,MAAM,EAAE,IAAI;GAAM;GAAK,KAAK;EAAO,CAAC;CACvE,CAAC,GACM;AACT;AAQA,SAAS,GACP,GACA,GACA,GACA,GACgC;CAChC,IAAM,EAAE,WAAQ,eAAY,EAAM;CAClC,OAAO,MAAS,SACZ;EACE,QAAQ,EAAO,QAAQ,KAAK,EAAO,OAAO,EAAc,EAAQ,MAAM,CAAK;EAC3E,MAAM,EAAO,SAAS,KAAK,EAAO,QAAQ,EAAc,EAAQ,OAAO,CAAK;CAC9E,IACA;EACE,QAAQ,EAAO,OAAO,KAAK,EAAO,MAAM,EAAc,EAAQ,KAAK,CAAK;EACxE,MAAM,EAAO,UAAU,KAAK,EAAO,SAAS,EAAc,EAAQ,QAAQ,CAAK;CACjF;AACN;AAeA,SAAS,GACP,GACA,GACA,GACA,GACA,GACc;CACd,IAAM,IAAO,MAAS,SAAS,EAAU,IAAI,OAAO,EAAU,IAAI,MAC5D,IAAY,GAAqB,GAAO,KAAA,GAAW,KAAA,GAAW,GAAG,GAAG;EACxE,KAAK,EAAU,IAAI;EACnB,KAAK,EAAU,IAAI;CACrB,CAAC,GACK,IAAsB,CAAC;CAgC7B,IA/BA,EAAU,SAAS,SAAS,GAAM,MAAM;EACtC,IAAM,IAAI,EAAU,OAAO,MAAM,IAC3B,IAAI,MAAS,SAAS,EAAE,MAAM,EAAE,KAChC,IAAQ,EAAE,UAAU,GACpB,IAAO,EAAE,QAAQ,EAAE,SAAS,GAC5B,KAAS,IAAQ,EAAO,QAAQ,MAAM,IAAO,EAAO,MAAM,IAC1D,IAAS,EAAc,EAAK,MAAM,QAAQ,CAAC;EACjD,IAAI,GAAY,CAAI,CAAC,CAAC,IAAO;GAC3B,IAAM,IAAM,GAAc,GAAM,GAAM,GAAQ,CAAC,GACzC,IAAS,GACb,GACA,GACA,GACA;IAAE,OAAO,EAAI,SAAS,IAAQ,EAAO,QAAQ;IAAI,KAAK,EAAI,OAAO,IAAO,EAAO,MAAM;GAAG,GACxF,CACF;GACA,KAAK,IAAM,KAAK,GAAQ,EAAM,KAAK;IAAE,GAAG;IAAG,OAAO,EAAE,QAAQ,EAAE;GAAM,CAAC;GACrE;EACF;EACA,IAAI,MAAS,QACX,EAAM,KAAK;GACT,OAAO,EAAE;GACT,MAAM,EAAE;GACR,KAAK,GAAkB,GAAM,OAAO,CAAM,IAAI,GAAO,CAAM,IAAI;GAC/D,KAAK,GAAkB,GAAM,OAAO,CAAM,IAAI,GAAO,CAAM,IAAI;EACjE,CAAC;OACI;GACL,IAAM,IAAS,EAAK,UAAU,SAAS,GAAO,CAAM,IAAI;GACxD,EAAM,KAAK;IAAE,OAAO,EAAE;IAAO,MAAM,EAAE;IAAM,KAAK;IAAQ,KAAK;GAAO,CAAC;EACvE;CACF,CAAC,GACG,EAAM,WAAW,GAAG;EACtB,IAAM,IAAQ,EAAO,QAAQ,EAAO;EACpC,EAAM,KAAK;GAAE,OAAO;GAAG;GAAM,KAAK;GAAO,KAAK;EAAM,CAAC;CACvD;CACA,OAAO;AACT;AASA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACgC;CAChC,IAAI,IAAQ,GAAY,GAAW,SAAS,CAAK,GAC7C,IAAM,GAAY,GAAS,OAAO,CAAK;CAC3C,AAAI,MAAU,QAAQ,MAAQ,OACxB,IAAQ,IAAK,CAAC,GAAO,KAAO,CAAC,GAAK,CAAK,IAClC,MAAU,MAAK,IAAM,QACrB,MAAU,QAAQ,EAAQ,SAAS,SAC5C,IAAM,GAAS,GAAO,GAAS,GAAG,CAAK,IAC9B,MAAQ,QAAQ,EAAU,SAAS,WAC5C,IAAQ,GAAS,GAAK,GAAW,IAAI,CAAK;CAK5C,IAAM,IAAQ,EAAU,QAClB,KAAc,MAA4C;EAC9D,IAAI,MAAS,MAAM;EACnB,IAAM,IAAI,IAAO;EACjB,OAAO,IAAI,KAAK,IAAI,KAAS,MAAU,IAAI,KAAA,IAAY;CACzD,GACM,KAAe,MACnB,MAAM,IAAQ,EAAU,IAAQ,KAAM,EAAM,IAAQ,KAAM,EAAU,IAChE,KAAa,MACjB,MAAM,IAAI,EAAU,KAAM,EAAU,IAAI,KAAM,EAAM,IAAI,IACpD,IAAI,EAAW,CAAK,GACpB,IAAI,EAAW,CAAG;CACxB,OAAO;EACL,OAAO,MAAM,KAAA,IAAY,IAAY,EAAY,CAAC;EAClD,KAAK,MAAM,KAAA,IAAY,IAAU,EAAU,CAAC;CAC9C;AACF;AAOA,SAAgB,GACd,GACA,GAC8B;CAC9B,IAAM,IAAS,EAAM,cAAc,IAAI,CAAI;CAC3C,IAAI,MAAW,KAAA,GAAW,OAAO;CACjC,IAAM,IAAQ,EAAK,OACb,IAAO,KAAK,IAAI,OAAO,EAAM,QAAS,WAAW,EAAM,OAAO,GAAG,EAAM,OAAO,SAAS,CAAC,GACxF,IAAY,GAChB,GACA,KAAA,GACA,KAAA,GACA,GACA,GACA,EAAK,UAAU;EAAE,KAAK,EAAK,QAAQ;EAAS,KAAK,EAAK,QAAQ;CAAQ,IAAI,KAAA,CAC5E,GACM,IAAO,EAAU,SAAS,IAAI,EAAW,GACzC,IAAU,EAAU,SAAS,KAAK,MAAU,EAAc,EAAM,MAAM,QAAQ,CAAC,CAAC,GAChF,IAAS,GACb,EAAU,WACV,EAAU,cACV,GAAkB,GAAW,GAAM,GAAS,CAAK,GACjD,eACA,GACA,EACF,GACM,IAAO,EAAO,UAAU,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,GACjD,IAAS;EACb,KAAK,EAAO,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI;EAC/C,KAAK,EAAO,OAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI;CAClD;CAEA,OADA,EAAM,cAAc,IAAI,GAAM,CAAM,GAC7B;AACT;AAoBA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACe;CACf,IAAM,IAAQ,EAAK,OACb,IAAW,GAAoB,CAAI,GACnC,IAAa,EAAM,oBAAoB,SAAS,aAAa,MAAiB,KAAA,GAC9E,IAAa,EAAM,iBAAiB,SAAS,aAAa,MAAiB,KAAA,GAC3E,IAAc,IAChB,GAAoB,EAAa,GAAG,IACpC,GAAgB,EAAM,qBAAqB,GAAc,CAAI,GAC3D,IAAc,IAChB,GAAoB,EAAa,GAAG,IACpC,GAAgB,EAAM,kBAAkB,GAAc,CAAI,GAMxD,IAAQ,EAAM,mBACd,IAAc,CAAC,GAAG,EAAY,MAAM,GACpC,IAAc,CAAC,GAAG,EAAY,MAAM;CAC1C,IAAI,GAAO;EAST,AARK,KACH,GACE,GACA,EAAY,WACZ,EAAM,SACN,EAAM,eACR,GAEG,KACH,GAAqB,GAAa,EAAY,WAAW,EAAM,MAAM,EAAM,YAAY;EAEzF,KAAK,IAAM,CAAC,GAAM,MAAS,EAAM,OAI/B,AAHA,EAAY,UAAU,KAAK,IAAI,EAAK,UAAU,EAAY,MAAM,EAAE,CAAE,KAAK,GAAG,EAAK,OAAO,GACxF,EAAY,UAAU,KAAK,IAAI,EAAK,QAAQ,EAAY,MAAM,EAAE,CAAE,KAAK,GAAG,EAAK,KAAK,GACpF,EAAY,UAAU,KAAK,IAAI,EAAK,UAAU,EAAY,MAAM,EAAE,CAAE,KAAK,GAAG,EAAK,OAAO,GACxF,EAAY,UAAU,KAAK,IAAI,EAAK,QAAQ,EAAY,MAAM,EAAE,CAAE,KAAK,GAAG,EAAK,KAAK;CAExF;CACA,IAAM,IAAsB;EAAE,eAAe,EAAY;EAAQ,OAAO,EAAY;CAAU,GACxF,IAAsB;EAAE,eAAe,EAAY;EAAQ,OAAO,EAAY;CAAU,GAKxF,IAAS,GAJD,EAAS,KAAK,OAAW;EACrC,KAAK,GAAqB,EAAM,MAAM,iBAAiB,EAAM,MAAM,eAAe,CAAQ;EAC1F,KAAK,GAAqB,EAAM,MAAM,cAAc,EAAM,MAAM,YAAY,CAAQ;CACtF,EAC0B,GAAO,EAAY,QAAQ,EAAY,QAAQ,EAAM,YAAY;CAG3F,OAFI,KAAY,GAAgB,GAAQ,OAAO,EAAY,MAAM,GAC7D,KAAY,GAAgB,GAAQ,OAAO,EAAY,MAAM,GAC1D;EACL;EACA;EACA;EACA;EACA,WAAW,GACT,GACA,EAAO,WACP,EAAO,UACP,EAAM,eACR;EACA,WAAW,GAAgB,GAAa,EAAO,WAAW,EAAO,UAAU,EAAM,YAAY;EAC7F,cAAc,GACZ,GACA,EAAO,WACP,EAAO,UACP,EAAO,MAAM,KAAK,MAAM,EAAE,GAAG,CAC/B;EACA,cAAc,GACZ,GACA,EAAO,WACP,EAAO,UACP,EAAO,MAAM,KAAK,MAAM,EAAE,GAAG,CAC/B;CACF;AACF;AAKA,SAAS,GAAoB,GAAgC;CAC3D,OAAO;EACL,QAAQ,MAAM,KAAK,EAAE,QAAQ,EAAK,SAAS,GAAU,CAAC;EACtD,WAAW,MAAM,KAAK,EAAE,QAAQ,IAAO,EAAE,SAAS,CAAC,CAAC;CACtD;AACF;AAKA,SAAS,GAAgB,GAAyB,GAAqB,GAAqB;CAC1F,IAAM,IAAS,MAAS,QAAQ,EAAO,YAAY,EAAO;CAC1D,KAAK,IAAM,KAAQ,EAAO,OAAO;EAC/B,IAAM,IAAI,EAAK,IACT,IAAQ,KAAK,IAAI,KAAK,IAAI,EAAE,QAAQ,GAAQ,CAAC,GAAG,IAAQ,CAAC,GACzD,IAAM,KAAK,IAAI,KAAK,IAAI,EAAE,QAAQ,IAAS,EAAE,MAAM,IAAQ,CAAC,GAAG,CAAK;EAE1E,AADA,EAAE,QAAQ,GACV,EAAE,OAAO,IAAM;CACjB;CACA,AAAI,MAAS,SACX,EAAO,YAAY,GACnB,EAAO,WAAW,MAElB,EAAO,YAAY,GACnB,EAAO,WAAW;AAEtB;AAIA,SAAS,GAAoB,GAAgC;CAC3D,OAAO,EAAK,SACT,QAAQ,MAAU,CAAC,EAAY,EAAM,KAAK,KAAK,CAAC,EAAM,SAAS,CAAC,CAChE,MAAM,GAAG,MAAM,EAAE,MAAM,QAAQ,EAAE,MAAM,KAAK;AACjD;AAEA,SAAS,GAAO,GAAgC;CAC9C,QAAQ,EAAO,QAAQ,MAAM,EAAO,SAAS;AAC/C;AAEA,SAAS,GAAO,GAAgC;CAC9C,QAAQ,EAAO,OAAO,MAAM,EAAO,UAAU;AAC/C;AAwBA,SAAS,GACP,GACA,GACA,GACkB;CAClB,IAAI,EAAS,SAAS,UAAU,OAAO;EAAE,QAAQ,CAAC;EAAG,WAAW,CAAC,CAAC,CAAC;CAAE;CACrE,IAAM,KACJ,EAAS,aAAa,MAAM,KAAK,EAAE,QAAQ,EAAS,OAAO,SAAS,EAAE,SAAS,CAAC,CAAC,EAAA,CACjF,KAAK,MAAU,CAAC,GAAG,CAAK,CAAC;CAC3B,IAAI,CAAC,EAAS,YAAY,OAAO;EAAE,QAAQ,EAAS;EAAQ,WAAW;CAAU;CACjF,IAAM,EAAE,UAAO,QAAQ,GAAY,YAAS,EAAS,YACjD,IAAQ;CACZ,IAAI,MAAc,KAAA,GAAW;EAC3B,IAAM,IAAY,EAAW,QAAQ,GAAK,MAAU;GAClD,IAAM,IAAM,GAAa,EAAM,KAAK,CAAS,KAAK,GAAa,EAAM,KAAK,CAAS,KAAK;GACxF,OAAO,IAAM,KAAK,IAAI,GAAG,CAAG;EAC9B,GAAG,CAAC;EACJ,IAAQ,KAAK,IAAI,GAAG,KAAK,OAAO,IAAY,MAAQ,IAAY,IAAM,EAAW,OAAO,CAAC;CAC3F;CACA,IAAM,IAAwB,CAAC;CAC/B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK,EAAS,KAAK,GAAG,CAAU;CAC3D,IAAM,IAAS;EAAC,GAAG,EAAS,OAAO,MAAM,GAAG,CAAK;EAAG,GAAG;EAAU,GAAG,EAAS,OAAO,MAAM,CAAK;CAAC,GAI1F,IACJ,EAAS,WAAW,aAAa,MAAM,KAAK,EAAE,QAAQ,EAAW,SAAS,EAAE,SAAS,CAAC,CAAC,GACnF,IAAwB,EAAU,MAAM,GAAG,CAAK,GAClD,IAAU,CAAC,GAAI,EAAS,WAAW,gBAAgB,CAAC,CAAE;CAC1D,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK;EAC9B,EAAQ,KAAK,GAAG,EAAS,EAAG;EAC5B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,QAAQ,KAErC,AADA,EAAU,KAAK,CAAO,GACtB,IAAU,CAAC,GAAG,EAAS,IAAI,EAAG;CAElC;CAMA,OALA,EAAU,KAAK,CAAC,GAAG,GAAS,GAAG,EAAU,EAAO,CAAC,GACjD,EAAU,KAAK,GAAG,EAAU,MAAM,IAAQ,CAAC,CAAC,GACxC,MAAS,aACJ;EAAE;EAAQ;EAAW,SAAS;GAAE,OAAO;GAAO,KAAK,IAAQ,EAAS;EAAO;CAAE,IAE/E;EAAE;EAAQ;CAAU;AAC7B;AAKA,SAAS,GAAa,GAAuB,GAAmD;CAC9F,IAAI,EAAQ,SAAS,SAAS,OAAO,EAAQ;CAC7C,IAAI,EAAQ,SAAS,aAAa,MAAc,KAAA,GAC9C,OAAO,GAAe,EAAQ,OAAO,CAAS;CAEhD,IAAI,EAAQ,SAAS,QAAQ;EAC3B,IAAM,IAAmB,CAAC;EAC1B,KAAK,IAAM,KAAO,EAAQ,MAAM;GAC9B,IAAM,IAAQ,GAAa,GAAK,CAAS;GACzC,IAAI,MAAU,KAAA,GAAW;GACzB,EAAO,KAAK,CAAK;EACnB;EACA,OAAO,EAAQ,OAAO,QAAQ,KAAK,IAAI,GAAG,CAAM,IAAI,KAAK,IAAI,GAAG,CAAM;CACxE;AAEF;AAKA,SAAS,GACP,GACA,GACA,GACA,GACM;CACN,KAAK,IAAI,IAAI,EAAO,QAAQ,IAAI,GAAO,KAErC,AADA,EAAO,KAAK,GAAU,IAAI,EAAO,UAAU,EAAS,OAAQ,GAC5D,EAAU,KAAK,CAAC,CAAC;AAErB;AAMA,SAAS,GACP,GACA,GACA,GACA,GACa;CACb,IAAM,IAAsB,CAAC;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK;EAC9B,IAAM,IAAW,IAAI;EACrB,IAAI,KAAY,KAAK,IAAW,EAAS,QACvC,EAAO,KAAK,EAAS,EAAU;OAC1B;GACL,IAAM,IAAQ,IAAW,IAAI,IAAW,IAAW,EAAS;GAC5D,EAAO,KAAK,GAAW,IAAQ,EAAS,SAAU,EAAS,UAAU,EAAS,OAAQ;EACxF;CACF;CACA,OAAO;AACT;AAIA,SAAS,GACP,GACA,GACA,GACA,GACW;CACX,IAAM,IAAuB,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,EAAK;CACtE,IAAI,CAAC,EAAS,SAAS,OAAO;CAC9B,KAAK,IAAI,IAAW,EAAS,QAAQ,OAAO,IAAW,EAAS,QAAQ,KAAK,KAAY;EACvF,IAAM,IAAQ,IAAW;EACrB,IAAQ,KAAK,KAAS,KACT,EAAM,MAAM,MAAM,KAAS,EAAE,SAAS,IAAQ,EAAE,QAAQ,EAAE,IACtE,MAAU,EAAU,KAAS;CACpC;CACA,OAAO;AACT;AAgCA,SAAS,GAAY,GAAgB,GAAuB,GAAiC;CAC3F,IAAI,EAAK,SAAS,QAChB,OAAO,EAAK,QAAQ,IAAI,EAAK,QAAQ,IAAI,EAAM,gBAAgB,IAAI,EAAK;CAE1E,IAAI,EAAK,SAAS,QAAQ,OAAO;CACjC,IAAI,EAAK,QAAQ,KAAA,GAAW;EAC1B,IAAM,IAAO,GAAG,EAAK,KAAK,GAAG,KACvB,IAAQ,EAAM,MAAM,WAAW,MAAU,EAAM,SAAS,CAAI,CAAC;EACnE,IAAI,MAAU,IAAI,OAAO;CAC3B;CACA,IAAM,IAAM,EAAK,OAAO,GAClB,IAAQ,EAAM,eAChB,IAAO;CACX,IAAI,IAAM,GAAG;EACX,KAAK,IAAI,IAAI,GAAG,KAAK,GAAO,KAC1B,IAAI,EAAM,MAAM,EAAE,CAAE,SAAS,EAAK,IAAI,KAAK,EAAE,MAAS,GAAK,OAAO;EAEpE,OAAO,KAAS,IAAM;CACxB;CACA,KAAK,IAAI,IAAI,GAAO,KAAK,GAAG,KAC1B,IAAI,EAAM,MAAM,EAAE,CAAE,SAAS,EAAK,IAAI,KAAK,EAAE,MAAS,CAAC,GAAK,OAAO;CAErE,OAAO,EAAE,CAAC,IAAM;AAClB;AAKA,SAAS,GACP,GACA,GACA,GACA,GACQ;CACR,IAAI,EAAK,SAAS,KAAA,GAAW,OAAO,IAAO,IAAY,EAAK;CAC5D,IAAI,IAAY,EAAK,OACjB,IAAI;CACR,OAAO,IAAY,IAGjB,AAFA,KAAK,IAED,EADa,KAAK,KAAK,KAAK,EAAM,kBACrB,EAAM,MAAM,EAAE,CAAE,SAAS,EAAK,IAAI,MAAG;CAExD,OAAO;AACT;AAUA,SAAgB,GACd,GACA,GACA,GACU;CACV,IAAM,IAAQ,GAAY,GAAW,SAAS,CAAK,GAC7C,IAAM,GAAY,GAAS,OAAO,CAAK;CAC7C,IAAI,MAAU,QAAQ,MAAQ,MAE5B,OADI,MAAU,IAAY;EAAE;EAAO,MAAM;CAAE,IACpC;EAAE,OAAO,KAAK,IAAI,GAAO,CAAG;EAAG,MAAM,KAAK,IAAI,IAAM,CAAK;CAAE;CAEpE,IAAI,MAAU,MAEZ,OAAO;EAAE;EAAO,OADA,EAAQ,SAAS,SAAS,GAAS,GAAO,GAAS,GAAG,CAAK,IAAI,IAAQ,KACvD;CAAM;CAExC,IAAI,MAAQ,MAAM;EAChB,IAAM,IAAY,EAAU,SAAS,SAAS,GAAS,GAAK,GAAW,IAAI,CAAK,IAAI,IAAM;EAC1F,OAAO;GAAE,OAAO;GAAW,MAAM,IAAM;EAAU;CACnD;CAGA,OAAO;EAAE,OAAO;EAAM,MADpB,EAAU,SAAS,SAAS,EAAU,QAAQ,EAAQ,SAAS,SAAS,EAAQ,QAAQ;CAC/D;AAC7B;AAqBA,SAAgB,GACd,GACA,GACA,GACA,GACiB;CACjB,IAAM,IAAU,EAAK,cAAc,OAC7B,IAAQ,EAAM,KAAK,MAAO,IAAU,EAAE,MAAM,EAAE,GAAI,GAClD,IAAQ,EAAM,KAAK,MAAO,IAAU,EAAE,MAAM,EAAE,GAAI,GAClD,IAAgB,IAAU,IAAe,GACzC,IAAgB,IAAU,IAAe,GAK3C,IAAc,GACd,IAAW,KAAK,IAAI,GAAe,CAAC;CACxC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAI,EAAM;EAChB,AAAI,EAAE,UAAU,SACd,IAAc,KAAK,IAAI,GAAa,EAAE,KAAK,GAC3C,IAAW,KAAK,IAAI,GAAU,EAAE,QAAQ,EAAE,IAAI;CAElD;CACA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAI,EAAM;EAChB,AAAI,EAAE,UAAU,SAAM,IAAW,KAAK,IAAI,GAAU,IAAc,EAAE,IAAI;CAC1E;CACA,IAAI,IAAc;CAClB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAK,EAAM;EACjB,AAAI,EAAG,UAAU,SAAM,IAAc,KAAK,IAAI,GAAa,EAAG,KAAK;CACrE;CAEA,IAAM,oBAAW,IAAI,IAAY,GAC3B,KAAQ,GAAY,GAAY,GAAgB,MAA4B;EAChF,KAAK,IAAI,IAAI,GAAI,IAAI,IAAK,GAAQ,KAChC,KAAK,IAAI,IAAI,GAAI,IAAI,IAAK,GAAQ,KAAK,IAAI,EAAS,IAAI,GAAG,EAAE,GAAG,GAAG,GAAG,OAAO;EAE/E,OAAO;CACT,GACM,KAAQ,GAAY,GAAY,GAAgB,MAAyB;EAC7E,KAAK,IAAI,IAAI,GAAI,IAAI,IAAK,GAAQ,KAChC,KAAK,IAAI,IAAI,GAAI,IAAI,IAAK,GAAQ,KAAK,EAAS,IAAI,GAAG,EAAE,GAAG,GAAG;CAEnE,GAEM,IAAsD,EAAM,UAAU,IAAI;CAGhF,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAK,EAAM,IACX,IAAK,EAAM;EACb,EAAG,UAAU,QAAQ,EAAG,UAAU,SACtC,EAAO,KAAK;GAAE,OAAO,EAAG;GAAO,OAAO,EAAG;EAAM,GAC/C,EAAK,EAAG,OAAO,EAAG,OAAO,EAAG,MAAM,EAAG,IAAI;CAC3C;CAIA,IAAM,oBAAa,IAAI,IAAoB;CAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAK,EAAM,IACX,IAAK,EAAM;EACjB,IAAI,EAAG,UAAU,QAAQ,EAAG,UAAU,MAAM;EAI5C,IAAI,IAHS,EAAK,QACd,IACA,KAAK,IAAI,GAAa,EAAW,IAAI,EAAG,KAAK,KAAK,CAAW;EAEjE,OAAO,CAAC,EAAK,EAAG,OAAO,GAAU,EAAG,MAAM,EAAG,IAAI,IAAG;EAIpD,AAHA,EAAO,KAAK;GAAE,OAAO,EAAG;GAAO,OAAO;EAAS,GAC/C,EAAK,EAAG,OAAO,GAAU,EAAG,MAAM,EAAG,IAAI,GACpC,EAAK,SAAO,EAAW,IAAI,EAAG,OAAO,IAAW,EAAG,IAAI,GAC5D,IAAW,KAAK,IAAI,GAAU,IAAW,EAAG,IAAI;CAClD;CAGA,IAAI,IAAW,GACX,IAAW;CACf,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAI,EAAO,OAAO,MAAM;EACxB,IAAM,IAAK,EAAM,IACX,IAAK,EAAM;EAKjB,IAJI,EAAK,UACP,IAAW,GACX,IAAW,IAET,EAAG,UAAU,MAAM;GAKrB,KADI,EAAG,QAAQ,KAAU,KAClB,CAAC,EAAK,GAAU,EAAG,OAAO,EAAG,MAAM,EAAG,IAAI,IAAG;GAGpD,AAFA,EAAO,KAAK;IAAE,OAAO;IAAU,OAAO,EAAG;GAAM,GAC/C,EAAK,GAAU,EAAG,OAAO,EAAG,MAAM,EAAG,IAAI,GACzC,IAAW,EAAG,QAAQ,EAAG;EAC3B,OAAO;GACL,IAAI,IAAQ,GACR,IAAQ;GACZ,SAAS;IACP,IAAI,IAAQ,EAAG,OAAO,GAAU;KAE9B,AADA,KACA,IAAQ;KACR;IACF;IACA,IAAI,EAAK,GAAO,GAAO,EAAG,MAAM,EAAG,IAAI,GAAG;IAC1C;GACF;GAIA,AAHA,EAAO,KAAK;IAAE,OAAO;IAAO,OAAO;GAAM,GACzC,EAAK,GAAO,GAAO,EAAG,MAAM,EAAG,IAAI,GACnC,IAAW,GACX,IAAW,IAAQ,EAAG;EACxB;CACF;CAEA,IAAI,IAAW,KAAK,IAAI,GAAe,CAAW;CAClD,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAChC,IAAW,KAAK,IAAI,GAAU,EAAO,EAAE,CAAE,QAAQ,EAAM,EAAE,CAAE,IAAI;CAGjE,IAAM,IAAQ,EAAM,KAAK,GAAG,MAAM;EAChC,IAAM,IAAY;GAAE,OAAO,EAAO,EAAE,CAAE,QAAQ;GAAa,MAAM,EAAM,EAAE,CAAE;EAAK,GAC1E,IAAY;GAAE,OAAO,EAAO,EAAE,CAAE,QAAQ;GAAa,MAAM,EAAM,EAAE,CAAE;EAAK;EAChF,OAAO,IAAU;GAAE,KAAK;GAAW,KAAK;EAAU,IAAI;GAAE,KAAK;GAAW,KAAK;EAAU;CACzF,CAAC,GACK,IAAa,IAAW,GACxB,IAAa,IAAW;CAC9B,OAAO,IACH;EACE;EACA,WAAW;EACX,UAAU;EACV,WAAW;EACX,UAAU;CACZ,IACA;EACE;EACA,WAAW;EACX,UAAU;EACV,WAAW;EACX,UAAU;CACZ;AACN;AAwDA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACA,GACc;CACd,IAAM,IAAY,OAAO,KAAU,WAAW,IAAQ,KAAA,GAChD,IAAuB,EAAW,KAAK,GAAM,MAAM;EACvD,IAAI,EAAU,IACZ,OAAO;GACL,MAAM;GACN,OAAO;GACP,eAAe;GACf,WAAW;GACX,UAAU;GACV,WAAW;EACb;EAEF,IAAM,IAAW,GAAa,EAAK,KAAK,CAAS,GAC3C,IAAO,KAAY,GACnB,IAAgB,MAAa,KAAA,GAC7B,IAAM,EAAK;EACjB,IAAI,EAAI,SAAS,MACf,OAAO;GACL;GACA,OAAO;GACP;GACA,WAAW;GACX,UAAU,EAAI;GACd,WAAW;EACb;EAEF,IAAM,IAAW,GAAa,GAAK,CAAS;EAW5C,OAVI,MAAa,KAAA,IAUV;GACL;GACA,OAAO;GACP;GACA,WAAW,EAAI,SAAS,gBAAgB,kBAAkB;GAC1D,UAAU;GACV,WAAW;EACb,IAhBS;GACL;GACA,OAAO;GACP;GACA,WAAW;GACX,UAAU;GACV,WAAW;EACb;CAUJ,CAAC,GAEK,IAAsB,EAAO,KAAK,GAAG,MACrC,MAAM,KAAK,EAAE,YAAkB,IAC5B,EAAO,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,EAAE,SAAS,IAAI,IAAM,CAC7D,GACK,KAAgB,GAAe,MAAyB;EAC5D,IAAI,IAAM;EACV,KAAK,IAAI,IAAI,IAAQ,GAAG,IAAI,IAAQ,GAAM,KAAK,KAAO,EAAU;EAChE,OAAO;CACT,GACM,KAAkB,MACtB,EAAE,YAAY,IAAI,EAAE,cAAc,UAAU,EAAE,QAAS,KAAK,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAQrF,IAAS,CAAC,GAAG,CAAK,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;CACxD,KAAK,IAAM,KAAQ,GAAQ;EACzB,IAAM,IAAwB,CAAC,GAC3B,IAAY;EAChB,KAAK,IAAI,IAAI,EAAK,OAAO,IAAI,EAAK,QAAQ,EAAK,MAAM,KAAK;GACxD,IAAM,IAAI,EAAO;GACb,MAAM,KAAA,MACN,EAAE,cAAc,SAAM,IAAY,KACtC,EAAQ,KAAK,CAAC;EAChB;EACA,IAAI,EAAQ,WAAW,GAAG;EAC1B,IAAM,IAAO,EAAa,EAAK,OAAO,EAAK,IAAI;EAC/C,IAAI,GAAW;GAIb,IAAM,IAAc,EAAQ,QACzB,MAAM,EAAE,cAAc,QAAQ,EAAE,iBAAiB,CAAC,EAAE,SACvD;GACA,IAAI,EAAY,WAAW,GAAG;GAC9B,IAAM,IAAU,EAAQ,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC,IAAI,GACpD,IAAS,EAAK,MAAM;GAC1B,IAAI,IAAS,GAAG;IACd,IAAM,IAAY,EAAY,QAAQ,GAAG,MAAM,IAAI,EAAE,UAAU,CAAC,GAC1D,IAAS,EACb,EAAY,KAAK,MAAO,IAAY,IAAI,EAAE,WAAW,CAAE,GACvD,CACF;IACA,EAAY,SAAS,GAAG,MAAM;KAC5B,EAAE,QAAQ,EAAO;IACnB,CAAC;GACH;GACA;EACF;EAIA,IAAM,IAAgB,EAAQ,QAAQ,MAAM,EAAE,iBAAiB,CAAC,EAAE,SAAS;EAC3E,IAAI,EAAc,SAAS,GAAG;GAC5B,IAAM,IAAU,EAAQ,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC,IAAI,GACpD,IAAS,EAAK,MAAM;GAC1B,IAAI,IAAS,GAAG;IACd,IAAM,IAAS,EACb,EAAc,UAAU,CAAC,GACzB,CACF;IACA,EAAc,SAAS,GAAG,MAAM;KAC9B,EAAE,QAAQ,EAAO;IACnB,CAAC;GACH;EACF;EAGA,KAAK,IAAM,CAAC,GAAM,MAAiB,CACjC,CAAC,iBAAiB,EAAK,GAAG,GAC1B,CAAC,iBAAiB,EAAK,GAAG,CAC5B,GAAY;GACV,IAAM,IAAY,EAAQ,QAAQ,MAAM,EAAE,cAAc,KAAQ,CAAC,EAAE,SAAS;GAC5E,IAAI,EAAU,WAAW,GAAG;GAE5B,IAAM,IAAS,KADC,EAAQ,QAAQ,GAAG,MAAM,IAAI,EAAe,CAAC,GAAG,CAAC,IAAI;GAErE,IAAI,IAAS,GAAG;IACd,IAAM,IAAS,EACb,EAAU,UAAU,CAAC,GACrB,CACF;IACA,EAAU,SAAS,GAAG,MAAM;KAC1B,EAAE,QAAQ,EAAe,CAAC,IAAI,EAAO;IACvC,CAAC;GACH;EACF;CACF;CAKA,KAAK,IAAM,KAAK,GACV,EAAE,cACF,EAAE,cAAc,UAAS,EAAE,OAAO,KAAK,IAAI,EAAE,MAAM,EAAE,KAAM,IACtD,EAAE,cAAc,SAAM,EAAE,QAAQ,KAAK,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI;CAG7E,IAAI,MAAc,KAAA,GAAW;EAQ3B,IAAM,IAAW,EAAO,QAAQ,MAAM,EAAE,cAAc,QAAQ,CAAC,EAAE,SAAS;EAC1E,IAAI,EAAS,SAAS,GAAG;GACvB,IAAI,IAAW;GACf,KAAK,IAAM,KAAK,GACd,AAAI,EAAE,WAAW,MAAG,IAAW,KAAK,IAAI,GAAU,EAAE,OAAO,EAAE,QAAQ;GAEvE,KAAK,IAAM,KAAQ,GAAO;IACxB,IAAI,IAAY,GACZ,IAAc,EAAa,EAAK,OAAO,EAAK,IAAI;IACpD,KAAK,IAAI,IAAI,EAAK,OAAO,IAAI,EAAK,QAAQ,EAAK,MAAM,KAAK;KACxD,IAAM,IAAI,EAAO;KACb,MAAM,KAAA,KAAa,EAAE,cACrB,EAAE,cAAc,OAAM,KAAa,EAAE,WACpC,KAAe,EAAe,CAAC;IACtC;IACI,KAAa,MACjB,IAAW,KAAK,IAAI,IAAW,EAAK,MAAM,KAAe,KAAK,IAAI,GAAW,CAAC,CAAC;GACjF;GACA,KAAK,IAAM,KAAK,GAAU;IACxB,IAAM,IAAO,KAAK,IAAI,EAAE,MAAM,EAAsB,EAAE,WAAW,CAAQ,CAAC;IAE1E,AADA,EAAE,QAAQ,GACN,MAAU,kBAAe,EAAE,OAAO;GACxC;EACF;EAGA,IAAI,MAAU,eACP,KAAA,IAAM,KAAK,GACd,AAAI,CAAC,EAAE,aAAa,EAAE,cAAc,SAAM,EAAE,OAAO,EAAe,CAAC;CAGzE,OAAO;EACL,IAAM,IAAY,EAAU,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,GAGjD,IAAO,IAAY,IAAY,EAAO,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC;EACxE,OACM,OAAQ,KADL;GAEP,IAAM,IAAW,EAAO,QACrB,MAAM,CAAC,EAAE,aAAa,EAAE,cAAc,QAAQ,EAAE,OAAO,EAAe,CAAC,CAC1E;GACA,IAAI,EAAS,WAAW,GAAG;GAC3B,IAAM,IAAS,EACb,EAAS,UAAU,CAAC,GACpB,CACF,GACI,IAAQ;GAOZ,IANA,EAAS,SAAS,GAAG,MAAM;IACzB,IAAM,IAAO,KAAK,IAAI,EAAO,IAAK,EAAe,CAAC,IAAI,EAAE,IAAI;IAE5D,AADA,EAAE,QAAQ,GACV,KAAS;GACX,CAAC,GACD,KAAQ,GACJ,MAAU,GAAG;EACnB;EAOA,IAAM,IAAW,EAAO,QAAQ,MAAM,EAAE,cAAc,IAAI;EAC1D,IAAI,EAAS,SAAS,GAAG;GACvB,IAAM,IAAW,KAAK,IACpB,GACA,IAAY,IAAY,EAAO,QAAQ,GAAG,MAAM,KAAK,EAAE,cAAc,OAAO,IAAI,EAAE,OAAO,CAAC,CAC5F,GACI,IAAS,GACT,IAAQ,GACN,IAAY,EAAS,QAAQ,GAAG,MAAM,IAAI,EAAE,UAAU,CAAC;GAE7D,KADI,IAAY,MAAG,IAAQ,KAAK,MAAM,IAAQ,CAAS,MAC9C;IACP,IAAM,IAAS,EACb,EAAO,KAAK,MAAM,EAAE,QAAQ,GAC5B,CACF,GACM,IAAY,EAAO,QAAQ,GAAG,MAAM,EAAO,KAAM,EAAE,IAAI;IAC7D,IAAI,EAAU,WAAW,GAAG;KAC1B,EAAO,SAAS,GAAG,MAAM;MACvB,EAAE,OAAO,KAAK,IAAI,EAAE,MAAM,EAAO,EAAG;KACtC,CAAC;KACD;IACF;IACA,KAAK,IAAM,KAAK,GAAW,KAAS,EAAE;IAGtC,IAFA,IAAQ,KAAK,IAAI,GAAG,CAAK,GACzB,IAAS,EAAO,QAAQ,MAAM,CAAC,EAAU,SAAS,CAAC,CAAC,GAChD,EAAO,WAAW,GAAG;GAC3B;EACF;EAIA,IAAI,GAAa;GACf,IAAM,IAAY,IAAY,IAAY,EAAO,QAAQ,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC,GACzE,IAAa,EAAO,QAAQ,MAAM,CAAC,EAAE,aAAa,EAAE,cAAc,eAAe;GACvF,IAAI,IAAY,KAAK,EAAW,SAAS,GAAG;IAC1C,IAAM,IAAS,EACb,EAAW,UAAU,CAAC,GACtB,CACF;IACA,EAAW,SAAS,GAAG,MAAM;KAC3B,EAAE,QAAQ,EAAO;IACnB,CAAC;GACH;EACF;CACF;CAEA,OAAO;EACL,OAAO,EAAO,KAAK,MAAM,EAAE,IAAI;EAC/B;EACA,QAAQ,EAAO,KAAK,MAAM,EAAe,CAAC,CAAC;CAC7C;AACF;AAQA,SAAS,GACP,GACA,GACA,GACU;CACV,IAAM,EAAE,UAAO,iBAAc,GACvB,IAAW,KAAK,IAAI,GAAG,IAAY,GAAY,CAAM,CAAC,GACtD,IAAU,EAAgB,MAAe,YAAY,UAAU,GAAY,GAAO,CAAQ,GAC1F,IAAsB,CAAC,GACzB,IAAS;CACb,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAEhC,AADA,KAAU,EAAU,IACpB,EAAU,KAAK,EAAQ,KAAM,CAAM;CAErC,OAAO;AACT;AAEA,SAAS,GAAY,GAA8B;CACjD,OAAO,EAAO,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAO,UAAU,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC;AAC7F;AAGA,SAAS,GAAW,GAAqB,GAAiB,GAAe,GAAsB;CAC7F,IAAM,IAAO,IAAQ,IAAO;CAE5B,OADI,EAAU,OAAW,KAAA,KAAa,EAAU,OAAU,KAAA,IAAkB,IACrE,EAAU,KAAS,EAAM,KAAS,EAAU;AACrD;AAMA,SAAS,GACP,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAc,KAAU,GACxB,IAAa,KAAS,GACtB,IAAQ,IAAO;CAIrB,OAHI,MAAW,QAAQ,MAAU,OAAa,KAAK,MAAM,IAAQ,CAAC,IAC9D,MAAW,OAAa,IAAQ,IAChC,MAAU,OAAa,IACpB,IAAc,EAAiB,GAAO,GAAM,IAAO,IAAc,CAAU;AACpF;;;ACljDA,SAAS,GAAgB,GAAkB,GAAmB,GAAqB;CACjF,IAAM,IACJ,EAAM,gBAAgB,OAElB,OADA,KAAK,IAAI,GAAG,KAAK,OAAO,IAAY,MAAQ,EAAM,cAAc,EAAI,CAAC;CAK3E,OAHI,EAAM,gBAAgB,QAAQ,MAAQ,OACjC,KAAK,IAAI,GAAG,KAAK,IAAI,EAAM,aAAa,CAAG,CAAC,IACjD,MAAQ,OACL,KAAK,IAAI,GAAG,EAAM,eAAe,CAAC,IADhB;AAE3B;AAKA,SAAgB,GAAoB,GAAkB,GAAmB,GAAuB;CAC9F,IAAM,IAAQ,GAAgB,GAAO,GAAW,CAAG,GAC7C,IAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAa,IAAQ,KAAK,KAAO,CAAK,CAAC,GACtE,IAAW,KAAK,IAAI,GAAG,KAAa,IAAQ,KAAQ,IAAQ,KAAK,EAAI;CAC3E,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAM,IAAI,GAAG,MAAM,IAAQ,MAAI,EAAiB;AAC9E;AAOA,SAAgB,GAA4B,GAAkB,GAA4B;CACxF,IAAM,IAAM,KAAK,IAAI,OAAO,EAAM,QAAS,WAAW,EAAM,OAAO,GAAG,EAAM,OAAO,SAAS,CAAC;CAI7F,OAHI,EAAM,gBAAgB,OAGnB,KAAK,IAAI,EAAM,eAAe,GAAG,CAAU,IAFzC,EAAM,cAAc,KAAc,EAAM,cAAc,KAAK;AAGtE;AAIA,SAAgB,GACd,GACA,GACoB;CAGpB,OAFI,MAAa,KAAA,IAAkB,IAC/B,MAAQ,KAAA,IAAkB,IACvB,KAAK,IAAI,GAAU,CAAG;AAC/B;AAGA,SAAS,GAAc,GAAY,GAAY,GAA2C;CACxF,OAAO,IAAK,IAAI;EACd,IAAM,IAAO,IAAK,KAAO;EACzB,AAAI,EAAK,CAAG,IAAG,IAAK,IACf,IAAK,IAAM;CAClB;CACA,OAAO;AACT;AAMA,SAAgB,GACd,GACA,GACA,GACoD;CACpD,IAAM,IAAQ,GAAgB,GAAO,GAAW,CAAG,GAC7C,IAAQ,KAAK,IAAI,GAAG,KAAK,OAAO,KAAa,IAAQ,KAAK,KAAO,CAAK,CAAC;CAE7E,OAAO;EAAE;EAAO;EAAO,UADN,KAAK,IAAI,GAAG,KAAa,IAAQ,KAAS,IAAQ,KAAK,EACjD;CAAS;AAClC;AAMA,SAAS,GACP,GACA,GACA,GACS;CAGT,OAFI,MAAS,QAAc,KACvB,MAAS,WAAiB,KAAU,IACjC,KAAU;AACnB;AAYA,SAAgB,GACd,GACA,GACA,GACA,GACsB;CAKtB,IAAM,IAAQ,GAAc,GAAM,KAAK,IAAI,GAAG,EAAQ,QAAQ,EAAK,MAAM,QAAQ,CAAC,GAC5E,EAAE,YAAS,mBAAgB,GAAgB,GAAM,CAAK,GACtD,IAAU,EAAK,MAAM,SACrB,IAAQ,GAAU,EAAQ,KAAK,MAAM,IAAI,CAAO,CAAC,GAEnD;CACJ,IAAI,EAAK,MAAM,eAAe,UAAU,MAAmB,KAAA,GACzD,IAAS,KAAK,IAAI,GAAG,CAAc;MAC9B;EACL,IAAM,IAAW,GACf,EAAM,QAAQ,GAAK,MAAS,KAAK,IAAI,GAAK,EAAK,OAAO,CAAO,GAAG,CAAC,GACjE,KAAK,IAAI,GAAG,EAAM,QAAQ,GAAK,MAAS,IAAM,EAAK,MAAM,CAAC,IAAI,CAAO,IACpE,MAAU,GAAgB,GAAO,GAAS,CAAK,CAAC,CAAC,WAAW,EAAQ,KACvE;EACA,IACE,MAAmB,KAAA,IAA8D,IAAlD,KAAK,IAAI,GAAG,KAAK,IAAI,GAAU,CAAc,CAAC;CACjF;CAEA,IAAM,IAAS,GAAgB,GAAO,GAAS,CAAM;CACrD,OAAO;EACL;EACA,OAAO,EAAO;EACd,OAAO,EAAO,IAAI,KAAK,GAAK,MAAM,IAAM,EAAY,EAAG;EACvD,OAAO,EAAO,OAAO,KAAK,MAAM,KAAK,EAAQ,QAAQ,EAAI;EACzD,WAAW,EAAO;EAClB,aAAa,EAAQ;EACrB,aAAa,EAAQ;EACrB;EACA,aAAa,EAAM,SAAS,IAAI,EAAO,UAAU;CACnD;AACF;AA6CA,SAAS,GACP,GACA,GACA,GACA,IAAqB,YACkD;CACvE,IAAI,IAAS,GACT,IAAO,GACP,IAAU,GACR,IAAqB,CAAC,GACtB,IAAgB,CAAC;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAO,EAAM,IACf,IAAO,MAAS,UAAU,MAAM,KAAK,IAAO,IAAI,EAAK,MAAM;EAG/D,AAAI,IAAO,MAAM,EAAK,UAAU,IAAO,IAAO,EAAK,OAAO,EAAK,OAAO,IAAU,OAC1E,MAAS,eAAY,IAAO,IAChC,KAAU,GACV,IAAO;EAET,IAAM,IAAW,EAAK,OAAO,EAAK;EAClC,IAAI,EAAK,QAAQ,KAAK,EAAK,OAAO,IAAU,GAAO;GAEjD,KAAK,IAAI,IAAO,GAAG,IAAO,EAAK,OAAO,KAUpC,AATI,IAAO,KAAK,IAAO,IAAO,IAAW,IAAU,MAC7C,MAAS,eAAY,IAAO,IAChC,KAAU,GACV,IAAO,IAET,EAAS,KAAK,CAAM,GACpB,EAAI,KAAK,IAAO,CAAI,GACpB,KAAQ,IAAO,GACf,IAAO,GACP,IAAU,KAAK,IAAI,GAAS,IAAO,CAAO;GAG5C,AADA,KAAQ,EAAK,MACT,EAAK,OAAO,MAAG,IAAU,KAAK,IAAI,GAAS,CAAI;GACnD;EACF;EACA,KAAK,IAAI,IAAO,GAAG,IAAO,EAAK,OAAO,KAEpC,AADA,EAAS,KAAK,CAAM,GACpB,EAAI,KAAK,IAAO,IAAO,IAAO,CAAQ;EAKxC,AAHA,KAAQ,IAAO,EAAK,OAAO,EAAK,MAGhC,IAAU,KAAK,IAAI,GAAS,KAAQ,EAAK,OAAO,IAAI,IAAI,EAAQ;CAClE;CACA,OAAO;EAAE,SAAS,IAAS;EAAG;EAAS,QAAQ;EAAU;CAAI;AAC/D;AAGA,SAAS,GAAU,GAA4B;CAC7C,OAAO,EAAK,KAAK,OAAO;EAAE,MAAM;EAAG,KAAK;EAAG,MAAM;EAAG,QAAQ;EAAO,OAAO;CAAE,EAAE;AAChF;AAWA,IAAI,KAAwC;AAC5C,SAAS,KAA+B;CACtC,IAAI,OAA0B,MAAM,OAAO;CAI3C,IACM,IAAU,SAAS,cAAc,KAAK;CAO5C,AANA,EAAQ,MAAM,UACZ,uJAEF,EAAQ,YACN,iIAEF,SAAS,KAAK,YAAY,CAAO;CACjC,IAAM,IAAa,EAAQ,sBAAsB,CAAC,CAAC,KAC7C,IAAQ,EAAQ,cAAc,MAAM,CAAC,CAAE,sBAAsB;CAMnE,OALA,EAAQ,OAAO,GAIf,KAAwB,EAAE,EAAM,QAAQ,KAAK,EAAM,MAAM,KAAc,KAChE;AACT;AAYA,SAAgB,GACd,GACA,GASiD;CACjD,IAAM,EAAE,gBAAa,gBAAa,cAAW,GAAG,aAAU,GAAG,yBAAsB,GAC7E,IAAW,IAAW,IAAI,MAAM,KAAK,SAAY,IAAI,CAAQ,IAAI,KAAA,GACjE,IAAQ,GAAc,GAAM,KAAK,IAAI,GAAG,IAAc,CAAQ,GAAG;EACrE;EACA;EACA,iBAAiB,EAAQ;CAC3B,CAAC,GACK,IAAQ,GAAU,EAAM,UAAU,IAAI,CAAO,CAAC,GAM9C,IAAS,GAAgB,GAAO,GAJpC,KACA,GAAc,GAAG,KAAK,IAAI,GAAG,EAAM,UAAU,IAAI,KAAW,CAAO,IAAI,MAC9D,GAAgB,GAAO,GAAS,CAAK,CAAC,CAAC,WAAW,CAC1D,CACkD;CACrD,OAAO,EAAM,KAAK,GAAM,OAAO;EAC7B,MAAM,EAAK,MAAM,EAAK,OAAO,EAAK,GAAG;EACrC,QAAQ,EAAO,OAAO;EACtB,KAAK,EAAO,IAAI;CAClB,EAAE;AACJ;AAKA,SAAgB,GACd,GACA,GACA,GACA,GACM;CACN,IAAM,IAAQ,EAAK;CACnB,IAAI,CAAC,EAAM,OAAO;CAClB,IAAM,IACJ,EAAS,cAAc,EAAS,eAAe,EAAS,cAAc,KAAK,EAAS,KAChF,IAAU,EAAS,gBAAgB,CACvC;EAAE,OAAO;EAAG,KAAK,EAAS;EAAW,SAAS,EAAS;CAAY,CACrE,GACM,IAA0B,CAAC;CACjC,KAAK,IAAM,KAAU,GAAS;EAC5B,IAAM,IAAW,KAAK,IAAI,EAAO,SAAS,EAAS,WAAW;EAC9D,KAAK,IAAI,IAAI,GAAG,IAAI,EAAS,cAAc,GAAG,KACvC,GAAY,EAAM,qBAAqB,IAAI,GAAU,IAAI,IAAI,CAAQ,KAC1E,EAAS,KAAK;GACZ,YAAY,IAAI,KAAK,EAAS,cAAc,IAAI,EAAS;GACzD,UAAU,EAAS;GACnB,OAAO,EAAO;GACd,KAAK,EAAO;EACd,CAAC;CAEL;CACA,EAAK,iBAAiB,GAAmB;EACvC,QAAQ,EAAY,EAAM,QAAQ;EAClC,OAAO,EAAM;EACb,OAAO;EACP,UAAU,GAAc,GAAU,EAAM,SAAS;EACjD,YAAY,CAAC;EACb;EACA,eAAe,EAAS;EACxB;EACA,aAAa,EAAM;EACnB,aAAa,EAAM;EACnB;CACF,CAAC;AACH;AAcA,SAAS,GAAmB,GAAmB,GAA+B;CAC5E,IAAM,IAAQ,EAAM,OACd,IAAS,EAAM;CACrB,OACE,EAAM,SAAS,MACf,EAAM,SAAS,WAAW,KAC1B,EAAM,YAAY,WAClB,EAAM,aAAa,YACnB,CAAC,EAAM,cACP,EAAM,eAAe,YACrB,EAAM,YAAY,EAAU,WAC5B,EAAM,OAAO,QAAQ,KACrB,EAAM,OAAO,UAAU,KACvB,EAAM,OAAO,WAAW,KACxB,EAAM,OAAO,SAAS,KACtB,EAAO,QAAQ,KACf,EAAO,UAAU,KACjB,EAAO,WAAW,KAClB,EAAO,SAAS,KAChB,EAAM,oBAAoB,KAAA,KAC1B,CAAC,EAAM,mBACP,EAAM,SAAS,MAAM,aACrB,EAAM,SAAS,MAAM,cACpB,EAAM,UAAU,KAAA,KAAa,EAAM,MAAM,SAAS,YAClD,EAAM,WAAW,KAAA,KAAa,EAAM,OAAO,SAAS,YACpD,EAAM,aAAa,UAAU,EAAM,aAAa,KAAK,EAAM,aAAa,KAAA,OACxE,EAAM,cAAc,UAAU,EAAM,cAAc,KAAK,EAAM,cAAc,KAAA,MAC5E,EAAM,aAAa,KAAA,KACnB,EAAM,cAAc,KAAA;AAExB;AAeA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAK,OACb,IAAM,GAAW,GAAO,KAAK,CAAU,GACvC,IAAU,GAAmB,GAAO,GAAY,CAAG;CACzD,EAAQ,SAAS,EAAQ;CACzB,IAAM,IAAU,EAAM,SAChB,IAAU,EAAO,OAAO,EAAQ,MAChC,IAAU,EAAO,MAAM,EAAQ,KAC/B,IAAe,IAAa,EAAQ,UAGpC,IAA2B,CAAC,CAAC,CAAC,GAC9B,IAA2C,CAAC;CAClD,KAAK,IAAM,KAAS,GAClB,AAAI,EAAM,MAAM,cACd,EAAa,EAAS,SAAS,KAAK,GACpC,EAAS,KAAK,CAAC,CAAC,KAEhB,EAAS,EAAS,SAAS,EAAE,CAAE,KAAK,CAAK;CAG7C,IAAM,IAAc,EAAS,SAAS,GAQhC,IAA6B,IAAc,SAAS,YAEpD,IAAkE,CAAC,GACrE,IAAS,GACT,IAAc;CAClB,KAAK,IAAI,IAAM,GAAG,IAAM,EAAS,QAAQ,KAAO;EAC9C,IAAM,IAAa,EAAS,IAKxB,IAAiB;EACrB,IAAI,EAAW,SAAS,GAAG;GACzB,IAAM,IAAW,EAAW,KAAK,OAAW;IAC1C,MAAM;IACN,OAAO,GAAc,GAAO,KAAK,IAAI,GAAG,EAAQ,QAAQ,EAAM,MAAM,QAAQ,CAAC;IAC7E,QAAQ,EAAc,EAAM,MAAM,QAAQ,EAAQ,KAAK;IACvD,KAAK;IACL,MAAM;GACR,EAAE,GACI,IAAoB,CAAC,GACvB,IAA4B,MAC5B,IAA8C,MAC9C,IAAe;GACnB,KAAK,IAAM,KAAS,GAAU;IAC5B,IAAM,EAAE,SAAM,UAAO,cAAW,GAC1B,IACJ,MAAe,OAAQ,EAAO,OAAO,IAAK,GAAgB,GAAY,EAAO,OAAO,CAAC,GAMnF,IAAM;IACV,AAAI,MAAiB,UAAU,MAAc,QAC3C,IAAM,GACN,EAAU,OAAO,GACjB,EAAM,EAAM,SAAS,EAAE,CAAE,OAAO,KAEhC,EAAM,MAAM;IAEd,IAAM,IAAS,KAAgB,EAAK,MAAM;IAC1C,IAAI,EAAK,MAAM,oBAAoB,EAAM,SAAS,GAGhD,EAAM,KAAK;KACT,MAAM,EAAM,UAAU,IAAI;KAC1B;KACA,MAAM;KACN;KACA,OAAO,EAAM;IACf,CAAC;SAED,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAChC,EAAM,KAAK;KACT,MAAM,IAAI;KACV,KAAK,IAAI,IAAI,IAAI;KACjB,MAAM;KACN,QAAQ,MAAM,KAAK;KACnB,OAAO;IACT,CAAC;IAOL,AAJI,EAAM,SAAS,MACjB,IAAa,EAAO,UAAU,GAC9B,IAAY,IAEd,IAAe,EAAK,MAAM;GAC5B;GACA,IAAiB,KAAc;GAE/B,IAAI;GACJ,IAAI,EAAM,eAAe,UAAU,MAAgB,KAAA,GACjD,IAAS,KAAK,IAAI,GAAG,CAAW;QAC3B;IACL,IAAM,IAAW,GACf,GACA,KAAK,IACH,GACA,GAAgB,GAAO,GAAS,UAA0B,CAAY,CAAC,CAAC,OAC1E,IACC,MAAU,GAAgB,GAAO,GAAS,GAAO,CAAY,CAAC,CAAC,WAAW,EAAQ,KACrF;IACA,IACE,MAAgB,KAAA,IAA2D,IAA/C,KAAK,IAAI,GAAG,KAAK,IAAI,GAAU,CAAW,CAAC;GAC3E;GACA,IAAM,IAAS,GAAgB,GAAO,GAAS,GAAQ,CAAY;GAEnE,KAAK,IAAI,IAAI,GAAG,IAAO,GAAG,IAAI,EAAS,QAAQ,KAAK;IAClD,IAAM,EAAE,MAAM,GAAO,UAAO,WAAQ,QAAK,YAAS,EAAS,IACrD,IAAkB,CAAC,GACnB,IAAkB,CAAC;IACzB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK,KAErC,AADA,EAAM,KAAK,IAAS,EAAO,IAAI,EAAM,GACrC,EAAM,KAAK,EAAO,OAAO,MAAU,EAAQ,QAAQ,EAAI;IAwBzD,AAtBA,OAAO,EAAM,gBACb,EAAM,mBAAmB;KACvB;KACA;KACA,OAAO;KACP;KACA,WAAW,IAAS,EAAO;KAC3B,aAAa,EAAQ;KACrB,aAAa,EAAQ;KACrB;KACA,aAAa,EAAO;IACtB,GAOA,EAAM,eAAe,IACjB;KAAE,KAAK;KAAK,OAAO,EAAO;KAAO,QAAQ;KAAM,MAAM,EAAO;IAAK,IACjE,GACJ,EAAM,YAAY;KAAE,GAAG;KAAS,GAAG;KAAS,OAAO;KAAc,QAAQ,EAAO;IAAQ,GACxF,EAAM,kBAAkB;KAAE,KAAK;KAAG,OAAO;KAAG,QAAQ;KAAG,MAAM;IAAE;GACjE;GACA,AAAI,EAAM,SAAS,MACjB,EAAa,KAAK;IAAE,OAAO;IAAQ,KAAK,IAAS,EAAO;IAAS,SAAS,EAAO;GAAQ,CAAC,GAC1F,IAAc,KAAK,IAAI,GAAa,EAAO,OAAO,GAGlD,KAAU,EAAO,WAAW,IAAM,EAAS,SAAS,IAAI,IAAU;EAEtE;EACA,IAAM,IAAU,EAAa;EAC7B,IAAI,GAAS;GAKX,IAAM,IAAS,EAAc,EAAQ,MAAM,QAAQ,CAAY,GACzD,KAAW,EAAO,QAAQ,MAAM,EAAO,SAAS;GACtD,EAAW,GAAS,KAAK,IAAI,GAAG,IAAe,CAAO,GAAG,KAAA,GAAW,GAAG,GAAG,QAAQ,CAAK;GACvF,IAAM,IAAQ,GAAiB,GAAQ,GAAc,EAAQ,UAAU,KAAK,GACtE,KAAa,EAAO,OAAO,KAAK;GAStC,AARA,KAAU,GACV,EAAQ,YAAY;IAAE,GAAG,EAAQ;IAAW,GAAG,IAAU;IAAO,GAAG,IAAU;GAAO,GACpF,EAAQ,mBAAmB;IACzB,KAAK;IACL,OAAO;IACP,QAAQ,EAAO,UAAU;IACzB,MAAM;GACR,GACA,KAAU,EAAQ,UAAU,UAAU,EAAO,UAAU;EACzD;CACF;CACA,IAAM,IAAY;CAElB,KAAK,IAAM,KAAS,EAAK,UAAU;EACjC,IAAI,CAAC,EAAY,EAAM,KAAK,GAAG;EAC/B,IAAM,IAAS,EAAc,EAAM,MAAM,QAAQ,CAAU;EAC3D,EAAM,aAAa;GACjB,MAAM;GACN,GAAG,KAAW,EAAO,QAAQ;GAC7B,GAAG,KAAW,EAAO,OAAO;EAC9B;CACF;CAeA,OAZA,EAAK,mBAAmB;EACtB,OAAO,CAAC;EACR,OAAO,CAAC;EACR,OAAO,CAAC;EACR,OAAO,CAAC;EACR;EACA,aAAa,EAAQ;EACrB,aAAa,EAAQ;EACrB;EACA;EACA,GAAI,IAAc;GAAE;GAAc,eAAe;EAAK,IAAI,CAAC;CAC7D,GACO;AACT;AAYA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAK,OAGb,IAAc,GAAkB,GAAqB,CAAc,GAcnE,IAAS,EAAK,SAAS,QAAQ,MAAU,CAAC,EAAY,EAAM,KAAK,CAAC,GAClE,IAAa,EAAO,QAAQ,MAAU,CAAC,EAAM,MAAM,UAAU,GAC7D,IAAoB,EAAO,QAC9B,GAAO,GAAO,MACb,CAAC,EAAM,MAAM,eAAe,MAAM,KAAK,EAAO,IAAI,EAAE,CAAE,MAAM,cAAc,IAAQ,IAAI,GACxF,CACF;CACA,IACE,EAAW,SAAS,KACpB,EAAW,OAAO,MAAU,GAAmB,GAAO,CAAK,CAAC,MAC3D,EAAW,WAAW,EAAO,UAC3B,EAAM,eAAe,aACpB,MAAgB,KAAA,MACf,GAAoB,KAClB,KAAqB,KACpB,EAAW,OACR,OACE,EAAM,MAAM,OAAO,QAAQ,KAAK,EAAM,MAAM,OAAO,QAAQ,UAC3D,EAAM,MAAM,OAAO,WAAW,KAAK,EAAM,MAAM,OAAO,WAAW,KACtE,KAER,OAAO,GAAmB,GAAM,GAAQ,GAAY,GAAa,GAAQ,GAAS,CAAK;CAEzF,IAAM,IAAM,GAAW,GAAO,KAAK,CAAU,GACvC,IAAS,GAAoB,GAAO,GAAY,CAAG,GACnD,IAAQ,EAAO,QACf,IAAqB,CAAC;CAC5B;EACE,IAAI,IAAI;EACR,KAAK,IAAM,KAAK,GAEd,AADA,EAAS,KAAK,CAAC,GACf,KAAK,IAAI;CAEb;CAGA,IAAM,KAAW,MACf,IAAI,IAAQ,EAAS,KAAM,EAAS,IAAQ,MAAO,IAAI,IAAQ,MAAM,EAAO,IAAQ,KAAM,IACtF,KAAiB,MAAsB,EAAO,KAAK,IAAI,GAAG,IAAQ,CAAC,IAGnE,IAAe,EAAO,IAAQ,IAC9B,IAAU,EAAO,OAAO,EAAQ,MAChC,IAAU,EAAO,MAAM,EAAQ,KAE/B,IAA0B,CAAC,GAC7B,IAAI,GACJ,IAA0B,CAAC,GAC3B,IAA+E,CAAC,GAChF,IAAe,IAKb,KAAQ,GAAe,MAAyD;EACpF,IAAI,IAAI,GACJ,IAAO,GACP,IAA4B,MAC5B,IAAU,GAIR,KAAgB,MAAwB;GACvC,OACL,KAAK,IAAM,KAAW,GAAc;IAClC,IAAI,EAAQ,UAAU,GAAO;IAC7B,IAAM,IACJ,MAAe,OACV,EAAQ,OAAO,OAAO,IACvB,GAAgB,GAAY,EAAQ,OAAO,OAAO,CAAC;IACzD,EAAQ,MAAM,aAAa;KACzB,MAAM;KACN,GAAG,IAAU,EAAQ,CAAC,KAAK,EAAQ,OAAO,QAAQ;KAClD,GAAG,IAAU,IAAI,IAAO;IAC1B;GACF;EACF;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAQ,QAAQ,KAAK;GACvC,IAAM,IAAO,EAAQ;GACrB,EAAa,CAAC;GACd,IAAI,IACF,MAAe,OACX,MAAM,IACH,EAAK,OAAO,OAAO,IACpB,IACF,GAAgB,GAAY,EAAK,OAAO,OAAO,CAAC,GAChD,IAAS,EAAK,KAAK,UAAU;GAOnC,IANI,MAAe,SAAS,EAAK,eAAe,IAAO,IAAQ,IAAS,OACtE,KAAK,GACL,IAAO,GACP,IAAa,MACb,IAAQ,IAEN,GAAO;IACT,IAAM,IAAQ,EAAK,MACb,IAAW,EAAc,CAAC;IAChC,IAAI,MAAa,GAAc;KAC7B,IAAM,KAAW,EAAK,OAAO,QAAQ,MAAM,EAAK,OAAO,SAAS;KAChE,EACE,GACA,KAAK,IAAI,GAAG,IAAW,CAAO,GAC9B,GACA,GACA,GACA,QACA,CACF;IACF;IACA,EAAM,YAAY;KAChB,GAAG,EAAM;KACT,GAAG,IAAU,EAAQ,CAAC,IAAI,GAAiB,EAAK,QAAQ,GAAU,EAAM,UAAU,KAAK;KACvF,GAAG,IAAU,IAAI,IAAO;IAC1B;GACF;GAGA,AAFA,KAAQ,IAAQ,EAAK,KAAK,UAAU,QACpC,IAAU,KAAK,IAAI,GAAS,CAAI,GAChC,IAAa,EAAK,OAAO,UAAU;EACrC;EAEA,OADA,EAAa,EAAQ,MAAM,GACpB;GAAE,SAAS,IAAI;GAAG;EAAQ;CACnC,GAEM,UAA2B;EAC/B,IAAI,EAAQ,WAAW,GAAG;GAExB,KAAK,IAAM,KAAW,GACpB,EAAQ,MAAM,aAAa;IACzB,MAAM;IACN,GAAG,KAAW,EAAQ,OAAO,QAAQ;IACrC,GAAG,IAAU,KAAK,EAAQ,OAAO,OAAO;GAC1C;GAEF,IAAe,CAAC;GAChB;EACF;EACA,IAAM,IAAa,MAAgB,KAAA,IAAY,KAAA,IAAY,KAAK,IAAI,GAAG,IAAc,CAAC,GAChF,IAAgB,EAAM,eAAe,UAAU,MAAe,KAAA,GAChE;EACJ,IAAI,GACF,IAAS;OACJ;GAGL,IAAM,IAAW,GAAc,GAAG,EAAK,UAA0B,EAAK,CAAC,CAAC,UAAU,MACzE,EAAK,GAAO,EAAK,CAAC,CAAC,WAAW,CACtC;GACD,IAAS,MAAe,KAAA,IAA6C,IAAjC,KAAK,IAAI,GAAU,CAAU;EACnE;EACA,IAAM,IAAS,EAAK,GAAQ,EAAI,GAM1B,IACJ,KAAiB,MAAwB,KAAA,IACrC,KAAK,IAAI,EAAO,SAAS,CAAM,IAC/B,EAAO;EACb,IAAI,EAAM,OACR,KAAK,IAAI,IAAI,GAAG,IAAI,IAAQ,GAAG,KAAK;GAClC,IAAM,IAAgB,KAAK,IAAI,EAAO,SAAS,CAAK;GAC/C,GAAY,EAAM,qBAAqB,IAAI,GAAe,IAAI,IAAI,CAAa,KAEpF,EAAS,KAAK;IACZ,WAAW,EAAS,KAAM,EAAO;IACjC,UAAU;IACV,OAAO;IACP,KAAK,IAAI;GACX,CAAC;EACH;EAIF,AAFA,KAAK,GACL,IAAU,CAAC,GACX,IAAe,CAAC;CAClB;CAEA,KAAK,IAAM,KAAS,EAAK,UAAU;EACjC,IAAI,EAAY,EAAM,KAAK,GAAG;GAG5B,EAAa,KAAK;IAChB;IACA,QAAQ,EAAc,EAAM,MAAM,QAAQ,CAAU;IACpD,OAAO,EAAQ;GACjB,CAAC;GACD;EACF;EACA,IAAI,EAAM,MAAM,YAAY;GAK1B,AADA,EAAa,GACb,IAAe;GACf,IAAM,IAAS,EAAc,EAAM,MAAM,QAAQ,CAAU,GACrD,KAAW,EAAO,QAAQ,MAAM,EAAO,SAAS;GAgBtD,AAfA,EACE,GACA,KAAK,IAAI,GAAG,IAAa,CAAO,GAChC,GACA,GACA,GACA,QACA,CACF,GACA,KAAK,EAAO,OAAO,GACnB,EAAM,YAAY;IAChB,GAAG,EAAM;IACT,GAAG,IAAU,GAAiB,GAAQ,GAAY,EAAM,UAAU,KAAK;IACvE,GAAG,IAAU;GACf,GACA,KAAK,EAAM,UAAU,UAAU,EAAO,UAAU;GAChD;EACF;EACA,IAAM,IAAe,EAAc,EAAM,MAAM,QAAQ,CAAY,GAC7D,KAAW,EAAa,QAAQ,MAAM,EAAa,SAAS;EAelE,AAdA,EACE,GACA,KAAK,IAAI,GAAG,IAAe,CAAO,GAClC,GACA,GACA,GACA,QACA,CACF,GACA,EAAQ,KAAK;GACX,MAAM;GACN,QAAQ;GACR,aAAa,KAAgB,EAAM,MAAM;EAC3C,CAAC,GACD,IAAe,EAAM,MAAM;CAC7B;CAkBA,OAjBA,EAAa,GAET,EAAM,SAAS,EAAS,SAAS,MACnC,EAAK,iBAAiB,GAAmB;EACvC,QAAQ,EAAY,EAAM,QAAQ;EAClC,OAAO,EAAM;EACb,OAAO;EACP,UAAU,GAAc,GAAU,EAAM,SAAS;EACjD,YAAY,CAAC;EACb,cAAc;EACd,eAAe;EACf;EACA,aAAa,EAAM;EACnB,aAAa,EAAM;EACnB;CACF,CAAC,IAEI;AACT;;;ACz3BA,SAAS,GAAW,GAA2B,GAAwB;CACrE,EAAU,OAAO,KAAK,CAAI,GACtB,EAAK,MAAM,cAAc,YAAY,EAAK,MAAM,cAAc,kBAClE,EACE,EAAK,QACL,4JAEF;AACF;AAIA,SAAS,GAAc,GAAa,GAAqC;CACvE,IAAM,IAAM,OAAO,SAAS,EAAG,aAAa,CAAI,KAAK,IAAI,EAAE;CAG3D,OAFI,OAAO,MAAM,CAAG,IAAU,IAC1B,MAAS,YAAkB,KAAK,IAAI,KAAM,KAAK,IAAI,GAAG,CAAG,CAAC,IACvD,KAAK,IAAI,OAAO,KAAK,IAAI,GAAG,CAAG,CAAC;AACzC;AAEA,SAAS,GAAY,GAA2B,GAAkB,GAA6B;CAC7F,IAAM,KAAU,GAAiB,MAAkB;EACjD,IAAM,IAAQ,EAAI,MAAM,OAClB,IACJ,KAAS,EAAM,SAAS,UAAU,EAAM,SAAS,YAC7C,EAAmB,GAAO,GAAG,GAAK,CAAK,IACvC,KAAA,GACA,IAAU,KAAS,EAAM,SAAS,YAAY,EAAM,QAAQ,KAAA;EAClE,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAEzB,AADA,EAAU,SAAS,KAAK,CAAK,GAC7B,EAAU,WAAW,KAAK,CAAO;CAErC;CACA,IAAI,EAAK,MAAM,cAAc,UAAU;EACrC,EAAO,GAAM,GAAU,EAAK,MAAM,CAAC;EACnC;CACF;CACA,IAAM,IAAO,EAAK,SAAS,QAAQ,MAAU,EAAM,MAAM,cAAc,QAAQ;CAC/E,IAAI,EAAK,WAAW,GAAG,EAAO,GAAM,GAAU,EAAK,MAAM,CAAC;MACrD,KAAK,IAAM,KAAO,GAAM,EAAO,GAAK,GAAU,EAAI,MAAM,CAAC;CAC9D,KAAK,IAAM,KAAS,EAAK,UACvB,AAAI,EAAM,MAAM,cAAc,YAAU,GAAW,GAAW,CAAK;AACvE;AAGA,SAAS,GAAU,GAAqB;CACtC,IAAM,IAAM,OAAO,SAAS,EAAG,aAAa,MAAM,KAAK,IAAI,EAAE;CAC7D,OAAO,OAAO,MAAM,CAAG,IAAI,IAAI,KAAK,IAAI,KAAM,KAAK,IAAI,GAAG,CAAG,CAAC;AAChE;AAEA,SAAS,GAAsB,GAAkB,GAAuC;CACtF,IAAM,IAA4B;EAChC,SAAS;EACT,MAAM,CAAC;EACP,WAAW,CAAC;EACZ,WAAW,CAAC;EACZ,OAAO,CAAC;EACR,aAAa;EACb,UAAU,CAAC;EACX,YAAY,CAAC;EACb,QAAQ,CAAC;CACX,GAIM,IAAuD,CAAC,GACxD,IAA4D,CAAC,GAC7D,IAAuD,CAAC;CAC9D,KAAK,IAAM,KAAS,EAAK,UAAU;EACjC,IAAI,EAAY,EAAM,KAAK,GAAG;EAC9B,IAAM,IAAO,EAAM,MAAM;EACzB,IAAI,MAAS,OACX,EAAS,KAAK;GAAE,KAAK;GAAO,OAAO;EAAK,CAAC;OACpC,IAAI,MAAS,kBAAkB,MAAS,eAAe,MAAS,gBAAgB;GACrF,IAAM,IACJ,MAAS,iBAAiB,IAAa,MAAS,iBAAiB,IAAa;GAChF,KAAK,IAAM,KAAY,EAAM,UACvB,EAAY,EAAS,KAAK,MAC1B,EAAS,MAAM,cAAc,QAAO,EAAO,KAAK;IAAE,KAAK;IAAU,OAAO;GAAM,CAAC,IAC9E,GAAW,GAAW,CAAQ;EAEvC,OAAO,AAAI,MAAS,YACd,EAAU,YAAY,OAAM,EAAU,UAAU,IAC/C,GAAW,GAAW,CAAK,IACvB,MAAS,YAAY,MAAS,kBACvC,GAAY,GAAW,GAAO,CAAK,GACnC,EAAU,OAAO,KAAK,CAAK,KAE3B,GAAW,GAAW,CAAK;CAE/B;CAIA,IAAM,IAAU;EAAC,GAAG;EAAY,GAAG;EAAU,GAAG;CAAU,GACtD,IAAa;CACjB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAQ,QAAQ,KAAK;EAEvC,AADA,EAAU,KAAK,KAAK,EAAQ,EAAE,CAAE,GAAG,GACnC,EAAU,UAAU,KAAK,EAAQ,EAAE,CAAE,KAAK;EAC1C,IAAM,IAAY,EAAQ,IAAI,EAAE,EAAE;EAIlC,IAAI,EAFF,IAAI,IAAI,EAAQ,WACf,EAAQ,EAAE,CAAE,UAAU,KAAc,EAAQ,EAAE,CAAE,UAAU,QAAQ,MAAc,QACnE;GACd,KAAK,IAAI,IAAI,GAAY,KAAK,GAAG,KAAK,EAAU,UAAU,KAAK,IAAI,CAAC;GACpE,IAAa,IAAI;EACnB;CACF;CAGA,OADA,GAAW,CAAS,GACb;AACT;AAKA,SAAS,GAAW,GAAiC;CAEnD,IAAM,IAAyB,CAAC;CAChC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAU,KAAK,QAAQ,KAAK;EAC9C,IAAM,IAAU,EAAU,KAAK,IAC3B,IAAI;EACR,KAAK,IAAM,KAAS,EAAQ,UAAU;GACpC,IAAI,EAAY,EAAM,KAAK,GAAG;GAC9B,IAAI,EAAM,MAAM,cAAc,QAAQ;IACpC,GAAW,GAAW,CAAK;IAC3B;GACF;GACA,QAAQ,EAAa,MAAM,KAAK,IAAG;GACnC,IAAM,IAAU,GAAc,EAAM,QAAQ,SAAS,GAC/C,IAAa,GAAc,EAAM,QAAQ,SAAS,GAClD,IAAW,EAAU,UAAU,IAC/B,IAAU,KAAK,IACnB,GACA,KAAK,IAAI,MAAe,IAAI,IAAW,IAAI,GAAY,IAAW,CAAC,CACrE;GACA,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,GAAS,KAC/B,EAAa,KAAK,KAAK,IAAI,EAAa,MAAM,GAAG,IAAI,CAAO;GAE9D,AADA,EAAU,MAAM,KAAK;IAAE,MAAM;IAAO;IAAS,KAAK;IAAG,KAAK;IAAG;IAAS;GAAQ,CAAC,GAC/E,KAAK;EACP;CACF;CACA,EAAU,cAAc,KAAK,IAAI,EAAa,QAAQ,EAAU,SAAS,MAAM;AACjF;AAgBA,SAAS,GAAiB,GAAkB,GAAqB,GAA+B;CAC9F,IAAM,IAAQ,EAAK,OACb,IAAa,GAAqB,GAAM,CAAK,GAC/C;CACJ,IAAI,MAAS,OACX,IAAQ;MACH;EACL,IAAM,IACJ,EAAM,UAAU,KAAA,KAAa,EAAM,MAAM,SAAS,UAAU,EAAM,MAAM,SAAS,YAC7E,EAAmB,EAAM,OAAO,GAAG,GAAM,CAAK,IAC9C,KAAA;EACN,IAAQ,MAAU,KAAA,IAA0C,EAAoB,GAAM,CAAK,IAA7D,KAAK,IAAI,GAAY,CAAK;CAC1D;CACA,IAAM,IAAM,OAAO,EAAM,YAAa,WAAW,EAAM,WAAW,GAC5D,IAAM,OAAO,EAAM,YAAa,WAAW,EAAM,WAAW,KAAA;CAClE,OAAO,KAAK,IAAI,GAAG,EAAU,GAAO,GAAK,CAAG,CAAC;AAC/C;AAEA,SAAS,GAAY,GAAsC;CACzD,IAAM,IAAQ,EAAK,MAAM;CACzB,OAAO,KAAS,EAAM,SAAS,YAAY,EAAM,QAAQ,KAAA;AAC3D;AAEA,SAAS,GACP,GACA,GACA,GACc;CACd,IAAM,IAAQ,EAAU,aAClB,IAAM,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,CAAC,GAC3C,IAAM,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,CAAC,GAC3C,IAAU,MAAM,KAAK,EAAE,QAAQ,EAAM,SAA6B,KAAA,CAAS;CACjF,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAEzB,AADI,EAAU,SAAS,OAAO,KAAA,MAAW,EAAI,KAAK,EAAU,SAAS,KACrE,EAAQ,KAAK,EAAU,WAAW;CAGpC,IAAM,IAAyB,CAAC;CAChC,KAAK,IAAM,KAAQ,EAAU,OAAO;EAClC,IAAI,EAAK,UAAU,GAAG;GACpB,EAAS,KAAK,CAAI;GAClB;EACF;EAEA,AADA,EAAI,EAAK,OAAO,KAAK,IAAI,EAAI,EAAK,MAAO,GAAiB,EAAK,MAAM,OAAO,CAAK,CAAC,GAClF,EAAI,EAAK,OAAO,KAAK,IAAI,EAAI,EAAK,MAAO,GAAiB,EAAK,MAAM,OAAO,CAAK,CAAC;EAClF,IAAM,IAAI,GAAY,EAAK,IAAI;EAC/B,AAAI,MAAM,KAAA,MAAW,EAAQ,EAAK,OAAO,KAAK,IAAI,EAAQ,EAAK,QAAQ,GAAG,CAAC;CAC7E;CAKA,EAAS,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;CAC7C,KAAK,IAAM,KAAQ,GAAU;EAC3B,IAAM,IAAK,EAAK,KACV,IAAK,EAAK,MAAM,EAAK,SACrB,IAAW,GAAqB,GAAQ,GAAI,CAAE,GAC9C,IAAU,EAAI,MAAM,GAAI,CAAE;EAChC,KAAK,IAAM,KAAQ,CAAC,OAAO,KAAK,GAAY;GAC1C,IAAM,IAAS,MAAS,QAAQ,IAAM,GAChC,IAAW,EAAO,MAAM,GAAI,CAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,GAC7D,IAAS,GAAiB,EAAK,MAAM,GAAM,CAAK,IAAI;GAC1D,IAAI,KAAU,GAAG;GACjB,IAAM,IAAS,EACb,EAAQ,MAAM,MAAM,IAAI,CAAC,IAAI,IAAU,EAAQ,UAAU,CAAC,GAC1D,CACF;GACA,KAAK,IAAI,IAAI,GAAI,IAAI,GAAI,KAAK,EAAO,MAAO,EAAO,IAAI;EACzD;CACF;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK,EAAI,KAAK,KAAK,IAAI,EAAI,IAAK,EAAI,EAAG;CAClE,OAAO;EAAE;EAAK;EAAK;CAAQ;AAC7B;AAMA,SAAS,GAAkB,GAAsB,GAA+B;CAC9E,IAAM,IAAQ,EAAO,IAAI,QACnB,IAAS,EAAO,IAAI,MAAM,GAC1B,IAA2B,CAAC,GAC5B,IAAwB,CAAC;CAC/B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KACzB,CAAC,EAAO,QAAQ,OAAO,KAAA,IAA6B,IAAjB,EAAiB,CAAa,KAAK,CAAC;CAEzE,IAAI,EAAe,SAAS,GAAG;EAC7B,IAAM,IAAe,EAAe,QAAQ,GAAK,MAAM,IAAM,EAAO,QAAQ,IAAK,CAAC,GAC5E,IAAQ,KAAK,IAAI,KAAK,CAAY;EACxC,KAAK,IAAM,KAAK,GAAgB;GAC9B,IAAM,IAAM,KAAK,MAAO,IAAc,EAAO,QAAQ,KAAO,CAAK;GACjE,EAAO,KAAK,KAAK,IAAI,EAAO,IAAI,IAAK,CAAG;EAC1C;EAGA,IAAM,IAAW,EAAY,QAAQ,GAAK,MAAM,IAAM,EAAO,IAAI,IAAK,CAAC,GAEjE,IADe,EAAe,QAAQ,GAAK,MAAM,IAAM,EAAO,IAAK,CAC5D,KAAgB,IAAc;EAC3C,IAAI,IAAO,GAAG;GACZ,IAAM,IAAY,EAAe,KAAK,MAAM,EAAO,KAAM,EAAO,IAAI,EAAG,GACjE,IAAO,EACX,GACA,KAAK,IACH,GACA,EAAU,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,CACrC,CACF;GACA,EAAe,SAAS,GAAG,MAAO,EAAO,MAAO,EAAK,EAAI;EAC3D;CACF;CAEA,IAAI,IAAY,IAAc,EAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC;CAC9D,IAAI,IAAY,KAAK,EAAY,SAAS,GAAG;EAC3C,IAAM,IAAO,EAAY,KAAK,MAAM,EAAO,IAAI,KAAM,EAAO,IAAI,EAAG,GAC7D,IAAW,EAAK,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,GACzC,IAAO,EAAkB,GAAM,KAAK,IAAI,GAAW,CAAQ,CAAC;EAElE,AADA,EAAY,SAAS,GAAG,MAAO,EAAO,MAAO,EAAK,EAAI,GACtD,KAAa,KAAK,IAAI,GAAW,CAAQ;CAC3C;CACA,IAAI,IAAY,GAAG;EAGjB,IAAM,IAAU,EAAY,SAAS,IAAI,IAAc;EACvD,IAAI,EAAQ,SAAS,GAAG;GACtB,IAAM,IAAU,EAAQ,KAAK,MAAM,EAAO,IAAI,EAAG,GAC3C,IAAQ,EACZ,EAAQ,MAAM,MAAM,IAAI,CAAC,IAAI,IAAU,EAAQ,UAAU,CAAC,GAC1D,CACF;GACA,EAAQ,SAAS,GAAG,MAAO,EAAO,MAAO,EAAM,EAAI;EACrD;CACF;CACA,OAAO;AACT;AAKA,SAAS,GACP,GACA,GACA,GACU;CACV,IAAM,IAAQ,EAAU,aAClB,IAAS,MAAM,KAAK,EAAE,QAAQ,EAAM,SAA6B,KAAA,CAAS;CAChF,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KACzB,AAAI,EAAU,SAAS,OAAO,KAAA,IACrB,EAAU,WAAW,OAAO,KAAA,MACnC,EAAO,KAAK,KAAK,IAAI,GAAG,KAAK,MAAO,IAAc,EAAU,WAAW,KAAO,GAAG,CAAC,KAF3C,EAAO,KAAK,EAAU,SAAS;CAI1E,KAAK,IAAM,KAAQ,EAAU,OAAO;EAClC,IAAI,EAAK,QAAQ,GAAG;EACpB,IAAM,IAAQ,EAAK,KAAK,OACpB;EAKJ,IAJI,EAAM,SAAS,EAAM,MAAM,SAAS,YACtC,IAAY,KAAK,IAAI,GAAG,KAAK,MAAO,IAAc,EAAM,MAAM,QAAS,GAAG,CAAC,IACpE,EAAM,SAAS,EAAM,MAAM,SAAS,WAC3C,IAAY,EAAmB,EAAM,OAAO,GAAG,EAAK,MAAM,CAAK,IAC7D,MAAc,KAAA,GAAW;EAC7B,IAAM,IAAQ,EACZ,MAAM,KAAK,EAAE,QAAQ,EAAK,QAAQ,SAAS,CAAC,GAC5C,CACF;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,SAAS,KAAK;GACrC,IAAM,IAAI,EAAK,MAAM;GACrB,AAAI,EAAO,OAAO,KAAA,MAAW,EAAO,KAAK,EAAM;EACjD;CACF;CACA,IAAM,IAAQ,EAAO,QAAgB,GAAK,MAAM,KAAO,KAAK,IAAI,CAAC,GAC3D,IAAU,EAAO,QAAQ,MAAM,MAAM,KAAA,CAAS,CAAC,CAAC;CACtD,IAAI,IAAU,GAAG;EACf,IAAM,IAAS,EACb,MAAM,KAAK,EAAE,QAAQ,EAAQ,SAAS,CAAC,GACvC,KAAK,IAAI,GAAG,IAAc,CAAK,CACjC,GACI,IAAI;EACR,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KAAK,AAAI,EAAO,OAAO,KAAA,MAAW,EAAO,KAAK,EAAO;CAClF;CACA,OAAO,EAAO,KAAK,MAAM,KAAK,CAAC;AACjC;AA4BA,IAAM,KAA0C;CAAE,QAAQ;CAAG,OAAO;CAAG,QAAQ;CAAG,QAAQ;AAAE;AAI5F,SAAS,GACP,GACuB;CACvB,KAAK,IAAM,EAAE,WAAQ,aAAU,GAAY,IAAI,GAAQ,OAAO,IAAO,OAAO;CAC5E,IAAI,IAAgC;CACpC,KAAK,IAAM,EAAE,WAAQ,aAAU,GAAY;EACzC,IAAI,CAAC,GAAQ;EACb,IAAM,IAAQ,EAAO,MAAM;EAC3B,IAAI,KAAS,GAAG;EAChB,IAAM,IAAQ,EAAO,MAAM;EAC3B,CACE,MAAW,QACX,IAAQ,EAAO,SACd,MAAU,EAAO,SAAS,GAAW,KAAS,GAAW,EAAO,YAEjE,IAAS;GAAE;GAAO;GAAO,OAAO,EAAO,MAAM;EAAM;CAEvD;CACA,OAAO;AACT;AAEA,SAAS,GAAc,GAAkB,GAAwC;CAC/E,IAAM,IAAI,EAAU,aACd,IAAI,EAAU,KAAK,QACnB,IAAY,EAAK,MAAM,gBACvB,IAAsB;EAC1B;EACA,QAAQ,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,SAAS,CAAC;EAC7C,QAAQ,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,SAAS,CAAC;EAC7C,UAAU,IAAY,IAAI,EAAK,MAAM;EACrC,UAAU,IAAY,IAAI,EAAK,MAAM;EACrC,WAAW,CAAC;EACZ,WAAW,CAAC;CACd;CACA,IAAI,CAAC,KAAa,MAAM,KAAK,MAAM,GAAG,OAAO;CAG7C,IAAM,IAAuC,MAAM,KAAK,EAAE,QAAQ,EAAE,SAClE,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAiC,KAAA,CAAS,CACnE;CACA,KAAK,IAAM,KAAQ,EAAU,OAC3B,KAAK,IAAI,IAAI,EAAK,KAAK,IAAI,EAAK,MAAM,EAAK,SAAS,KAClD,KAAK,IAAI,IAAI,EAAK,KAAK,IAAI,EAAK,MAAM,EAAK,SAAS,KAAK,EAAO,EAAE,CAAE,KAAK;CAE7E,IAAM,IAAQ,EAAK,MAAM;CACzB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,IAAsC,CAAC;EAC7C,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,IAAM,IAAO,IAAI,IAAI,EAAO,EAAE,CAAE,IAAI,KAAK,KAAA,GACnC,IAAQ,IAAI,IAAI,EAAO,EAAE,CAAE,KAAK,KAAA;GACtC,IAAI,MAAS,KAAA,KAAa,MAAS,GAAO;IACxC,EAAS,KAAK,IAAI;IAClB;GACF;GACA,IAAM,IAA6D,CAAC;GAGpE,AAFI,KAAQ,EAAK,MAAM,EAAK,YAAY,KACtC,EAAW,KAAK;IAAE,QAAQ,EAAK,KAAK,MAAM;IAAe,MAAM;GAAQ,CAAC,GACtE,KAAS,EAAM,QAAQ,KACzB,EAAW,KAAK;IAAE,QAAQ,EAAM,KAAK,MAAM;IAAe,MAAM;GAAO,CAAC;GAE1E,IAAM,IAAoB,MAAM,IAAI,SAAS,MAAM,IAAI,UAAU;GACjE,IAAI,GAAM;IACR,EAAW,KAAK;KAAE,QAAQ,EAAU,KAAK,EAAE,CAAE,MAAM;KAAe,MAAM;IAAK,CAAC;IAC9E,IAAM,IAAQ,EAAU,UAAU;IAElC,AADI,KAAO,EAAW,KAAK;KAAE,QAAQ,EAAM,MAAM;KAAe,MAAM;IAAK,CAAC,GAC5E,EAAW,KAAK;KAAE,QAAQ;KAAO,MAAM;IAAK,CAAC;GAC/C;GACA,EAAS,KAAK,GAAe,CAAU,CAAC;EAC1C;EAEA,AADA,EAAO,UAAU,KAAK,CAAQ,GAC9B,EAAO,OAAO,KAAK,EAAS,QAAQ,GAAG,MAAM,KAAK,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC;CAC5E;CACA,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,IAAsC,CAAC;EAC7C,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,IAAM,IAAQ,IAAI,IAAI,EAAO,IAAI,EAAE,CAAE,KAAK,KAAA,GACpC,IAAQ,IAAI,IAAI,EAAO,EAAE,CAAE,KAAK,KAAA;GACtC,IAAI,MAAU,KAAA,KAAa,MAAU,GAAO;IAC1C,EAAS,KAAK,IAAI;IAClB;GACF;GACA,IAAM,IAA6D,CAAC;GAOpE,AANI,KAAS,EAAM,MAAM,EAAM,YAAY,KACzC,EAAW,KAAK;IAAE,QAAQ,EAAM,KAAK,MAAM;IAAe,MAAM;GAAS,CAAC,GACxE,KAAS,EAAM,QAAQ,KACzB,EAAW,KAAK;IAAE,QAAQ,EAAM,KAAK,MAAM;IAAe,MAAM;GAAM,CAAC,GACrE,IAAI,KACN,EAAW,KAAK;IAAE,QAAQ,EAAU,KAAK,IAAI,EAAE,CAAE,MAAM;IAAe,MAAM;GAAS,CAAC,GACpF,IAAI,KAAG,EAAW,KAAK;IAAE,QAAQ,EAAU,KAAK,EAAE,CAAE,MAAM;IAAe,MAAM;GAAM,CAAC;GAC1F,IAAM,IAAa,IAAI,IAAI,EAAU,UAAU,IAAI,KAAK,MAClD,IAAa,IAAI,IAAI,EAAU,UAAU,KAAK;GAOpD,AANI,KAAc,MAAe,KAC/B,EAAW,KAAK;IAAE,QAAQ,EAAW,MAAM;IAAe,MAAM;GAAS,CAAC,GACxE,KAAc,MAAe,KAC/B,EAAW,KAAK;IAAE,QAAQ,EAAW,MAAM;IAAe,MAAM;GAAM,CAAC,GACrE,MAAM,KAAG,EAAW,KAAK;IAAE,QAAQ;IAAO,MAAM;GAAM,CAAC,GACvD,MAAM,KAAG,EAAW,KAAK;IAAE,QAAQ;IAAO,MAAM;GAAS,CAAC,GAC9D,EAAS,KAAK,GAAe,CAAU,CAAC;EAC1C;EAEA,AADA,EAAO,UAAU,KAAK,CAAQ,GAC9B,EAAO,OAAO,KAAK,EAAS,QAAQ,GAAG,MAAM,KAAK,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC;CAC5E;CACA,OAAO;AACT;AAEA,SAAS,GAAa,GAAqB,GAA6B;CACtE,OAAO,EAAO,YACV,EAAO,OAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,KACtC,IAAc,KAAK,EAAO;AACjC;AAGA,SAAS,GAAqB,GAAqB,GAAY,GAAoB;CACjF,IAAI,CAAC,EAAO,WAAW,OAAO,EAAO,YAAY,IAAK,IAAK;CAC3D,IAAI,IAAM;CACV,KAAK,IAAI,IAAI,IAAK,GAAG,IAAI,GAAI,KAAK,KAAO,EAAO,OAAO;CACvD,OAAO;AACT;AAEA,SAAS,GAAkB,GAAqB,GAAY,GAAoB;CAC9E,IAAI,CAAC,EAAO,WAAW,OAAO,EAAO,YAAY,IAAK,IAAK;CAC3D,IAAI,IAAM;CACV,KAAK,IAAI,IAAI,IAAK,GAAG,IAAI,GAAI,KAAK,KAAO,EAAO,OAAO;CACvD,OAAO;AACT;AAYA,SAAS,GAAU,GAAkB,GAAkC;CACrE,IAAM,IAAS,EAAM,UAAU,IAAI,CAAI;CACvC,IAAI,GAAQ,OAAO;CACnB,IAAM,IAAY,GAAsB,GAAM,CAAK,GAC7C,IAAS,GAAc,GAAM,CAAS,GAEtC,IAAkB;EACtB;EACA;EACA,QAJa,GAAiB,GAAW,GAAQ,CAIjD;EACA,SAAS,GAAa,GAAQ,EAAU,WAAW;CACrD;CAEA,OADA,EAAM,UAAU,IAAI,GAAM,CAAI,GACvB;AACT;AAMA,SAAgB,GACd,GACA,GAC8B;CAC9B,IAAM,EAAE,cAAW,WAAQ,eAAY,GAAU,GAAM,CAAK,GACxD,IAAM,EAAO,IAAI,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,GAC9C,IAAM,EAAO,IAAI,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI;CAKlD,OAJI,EAAU,YACZ,IAAM,KAAK,IAAI,GAAK,GAAqB,EAAU,SAAS,CAAK,CAAC,GAClE,IAAM,KAAK,IAAI,GAAK,EAAoB,EAAU,SAAS,CAAK,CAAC,IAE5D;EAAE;EAAK;CAAI;AACpB;AAKA,SAAgB,GACd,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAK,OACb,EAAE,WAAQ,eAAY,GAAU,GAAM,CAAK,GAC3C,EAAE,QAAK,WAAQ,GAA0B,GAAM,CAAK,GACpD,IACJ,EAAM,OAAO,OACb,EAAM,OAAO,QACb,EAAc,EAAM,QAAQ,MAAM,CAAc,IAChD,EAAc,EAAM,QAAQ,OAAO,CAAc,IACjD,GAAa,CAAK,CAAC,CAAC,OAKlB,IAAS,EAAO,IAAI,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,GAC7C,IAAa,GACb,IAAgB;CACpB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAO,IAAI,QAAQ,KAAK;EAC1C,IAAM,IAAI,EAAO,QAAQ;EACzB,AAAI,MAAM,KAAA,IAAW,KAAiB,EAAO,IAAI,KAC5C,KAAc;CACrB;CACA,IAAI,KAAc,KAChB,IAAS;MACJ,IAAI,IAAa,GAAG;EACzB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAO,IAAI,QAAQ,KAAK;GAC1C,IAAM,IAAI,EAAO,QAAQ;GACzB,AAAI,MAAM,KAAA,KAAa,IAAI,MACzB,IAAS,KAAK,IAAI,GAAQ,KAAK,KAAM,EAAO,IAAI,KAAM,MAAO,CAAC,CAAC;EACnE;EACA,IAAS,KAAK,IAAI,GAAQ,KAAK,KAAM,IAAgB,OAAQ,MAAM,EAAW,CAAC;CACjF;CAGA,IAAM,IAAS,KAAK,IAAI,IAAS,GAAS,CAAG,IAAI;CACjD,OAAO,KAAK,IAAI,IAAM,GAAc,KAAK,IAAI,GAAQ,CAAc,CAAC;AACtE;AAKA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,EAAE,cAAW,WAAQ,cAAW,GAAU,GAAM,CAAK,GACrD,IAAI,EAAU,aACd,IAAI,EAAU,KAAK,QACnB,IAAc,EAAO,OAAO,EAAQ,MACpC,IAAa,EAAO,MAAM,EAAQ;CAExC,KAAK,IAAM,KAAc,EAAU,QAIjC,AAHA,EAAW,cAAc,IACzB,EAAW,YAAY;EAAE,GAAG;EAAG,GAAG;EAAG,OAAO;EAAG,QAAQ;CAAE,GACzD,EAAW,kBAAkB;EAAE,KAAK;EAAG,OAAO;EAAG,QAAQ;EAAG,MAAM;CAAE,GACpE,EAAW,kBAAkB;CAG/B,IAAM,IAAc,KAAK,IAAI,GAAG,IAAa,GAAa,GAAQ,CAAC,CAAC,GAG9D,IAAQ,EAAK,OAGb,IADJ,EAAM,gBAAgB,WAAW,EAAM,UAAU,KAAA,KAAa,EAAM,MAAM,SAAS,SAEjF,GAAmB,GAAW,GAAa,CAAK,IAChD,GAAkB,GAAQ,CAAW,GAGnC,IAAiB,CAAC,GACpB,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAGrB,AAFA,KAAK,EAAO,YAAY,EAAO,OAAO,KAAM,EAAO,UACnD,EAAK,KAAK,CAAC,GACX,KAAK,EAAO;CAEd,IAAM,IAAY,KAAK,EAAO,YAAa,EAAO,OAAO,MAAM,IAAK,EAAO,WAGvE,IAAgB;CACpB,AAAI,EAAU,YACZ,EAAW,EAAU,SAAS,GAAY,KAAA,GAAW,GAAa,GAAY,QAAQ,CAAK,GAC3F,IAAgB,EAAU,QAAQ,UAAU;CAK9C,IAAM,oBAAiB,IAAI,IAAwB,GAC7C,oBAAa,IAAI,IAAwB;CAC/C,KAAK,IAAM,KAAQ,EAAU,OAAO;EAClC,IAAM,IAAK,EAAK,MAAM,EAAK,SACrB,IACJ,EAAO,MAAM,EAAK,KAAK,CAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IACpD,GAAqB,GAAQ,EAAK,KAAK,CAAE;EAG3C,AAFA,EAAW,IAAI,GAAM,CAAK,GAC1B,EAAW,EAAK,MAAM,GAAO,KAAA,GAAW,GAAG,GAAG,QAAQ,GAAO,EAAE,OAAO,EAAM,CAAC,GAC7E,EAAe,IAAI,GAAM,EAAK,KAAK,UAAU,MAAM;CACrD;CAOA,IAAM,IAAU,EAAO,YACnB,EAAO,OAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,KACtC,IAAI,KAAK,EAAO,UACf,IACJ,MAAwB,KAAA,IACpB,KAAA,IACA,KAAK,IAAI,GAAG,IAAsB,IAAgB,CAAO,GACzD,KAAgB,MACpB,MAAS,KAAA,KAAa,EAAK,SAAS,aAAa,MAAa,KAAA,IAC1D,GAAe,EAAK,OAAO,CAAQ,IACnC,GACA,IAAa,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,GAC9C,IAAc,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAK;CACzD,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,IAAM,IAAI,EAAU,KAAK,EAAE,CAAE,MAAM;EACnC,AAAI,MAAM,KAAA,KAAa,EAAE,SAAS,YAAS,EAAW,KAAK,EAAE;EAC7D,IAAM,IAAQ,EAAa,CAAC;EAC5B,AAAI,IAAQ,MACV,EAAW,KAAK,KAAK,IAAI,EAAW,IAAK,CAAK,GAC9C,EAAY,KAAK;CAErB;CACA,KAAK,IAAM,KAAQ,EAAU,OAC3B,IAAI,EAAK,YAAY,GAAG;EACtB,IAAM,IAAQ,EAAa,EAAK,KAAK,MAAM,MAAM;EAEjD,AADI,IAAQ,MAAG,EAAY,EAAK,OAAO,KACvC,EAAW,EAAK,OAAO,KAAK,IAAI,EAAW,EAAK,MAAO,EAAe,IAAI,CAAI,GAAI,CAAK;CACzF;CACF,IAAM,IAAc,EAAU,MAC3B,QAAQ,MAAS,EAAK,UAAU,CAAC,CAAC,CAClC,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;CACvC,KAAK,IAAM,KAAQ,GAAa;EAC9B,IAAM,IAAK,EAAK,MAAM,EAAK,SACrB,IACJ,EAAW,MAAM,EAAK,KAAK,CAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IACxD,GAAkB,GAAQ,EAAK,KAAK,CAAE,GAClC,IAAS,EAAe,IAAI,CAAI,IAAK;EAC3C,IAAI,KAAU,GAAG;EACjB,IAAM,IAAS,EACb,MAAM,KAAK,EAAE,QAAQ,EAAK,QAAQ,SAAS,CAAC,GAC5C,CACF;EACA,KAAK,IAAI,IAAI,EAAK,KAAK,IAAI,GAAI,KAAK,EAAW,MAAO,EAAO,IAAI,EAAK;CACxE;CACA,IAAI,MAAwB,KAAA,KAAa,IAAI,GAAG;EAC9C,IAAM,IACJ,IAAsB,IAAgB,IAAU,EAAW,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC;EACtF,IAAI,IAAQ,GAAG;GAGb,IAAM,IAAsB,CAAC;GAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,AAAK,EAAY,MAAI,EAAU,KAAK,CAAC;GACjE,IAAM,IAAU,EAAU,SAAS,IAAI,IAAY,MAAM,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAC,GAClF,IAAS,EACb,EAAQ,UAAU,CAAC,GACnB,CACF;GACA,EAAQ,SAAS,GAAG,MAAO,EAAW,MAAO,EAAO,EAAI;EAC1D;CACF;CAGA,IAAM,IAAU,EAAU,WAAW,EAAK,MAAM,gBAAgB,QAAQ,IAAgB,GAClF,IAAiB,CAAC,GACpB,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAGrB,AAFA,KAAK,EAAO,YAAY,EAAO,OAAO,KAAM,EAAO,UACnD,EAAK,KAAK,CAAC,GACX,KAAK,EAAW;CAElB,IAAM,IACJ,IAAI,IAAI,KAAK,EAAO,YAAa,EAAO,OAAO,MAAM,IAAK,EAAO,YAAY,GAKzE,oBAAY,IAAI,IAAwB;CAC9C,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,IAAM,IAAQ,EAAU,UAAU;EAClC,AAAI,KAAS,CAAC,EAAU,IAAI,CAAK,KAAG,EAAU,IAAI,GAAO,EAAK,EAAG;CACnE;CACA,KAAK,IAAM,CAAC,GAAO,MAAQ,GAAW;EACpC,IAAI,IAAS;EACb,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,AAAI,EAAU,UAAU,OAAO,MAAO,IAAS,EAAK,KAAM,EAAW;EAQvE,AAPA,EAAM,YAAY;GAChB,GAAG;GACH,GAAG,IAAa;GAChB,OAAO;GACP,QAAQ,IAAS;EACnB,GACA,EAAM,kBAAkB;GAAE,KAAK;GAAG,OAAO;GAAG,QAAQ;GAAG,MAAM;EAAE,GAC/D,EAAM,kBAAkB,IAAS;CACnC;CACA,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,IAAM,IAAU,EAAU,KAAK,IACzB,IAAQ,EAAU,UAAU,IAC5B,IAAW,IAAQ,EAAU,IAAI,CAAK,IAAK,KAAA;EAQjD,AAPA,EAAQ,YAAY;GAClB,GAAG,MAAa,KAAA,IAAY,IAAc;GAC1C,GAAG,MAAa,KAAA,IAAY,IAAa,EAAK,KAAM,EAAK,KAAM;GAC/D,OAAO;GACP,QAAQ,EAAW;EACrB,GACA,EAAQ,kBAAkB;GAAE,KAAK;GAAG,OAAO;GAAG,QAAQ;GAAG,MAAM;EAAE,GACjE,EAAQ,kBAAkB,EAAW;CACvC;CACA,KAAK,IAAM,KAAQ,EAAU,OAAO;EAClC,IAAM,IAAK,EAAK,MAAM,EAAK,SACrB,IACJ,EAAW,MAAM,EAAK,KAAK,CAAE,CAAC,CAAC,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IACxD,GAAkB,GAAQ,EAAK,KAAK,CAAE;EAoBxC,AAf8B,EAAK,KAAK,SAAS,MAC9C,MAAU,CAAC,EAAY,EAAM,KAAK,KAAK,EAAM,MAAM,QAAQ,SAAS,SAEnE,KAAyB,MAAU,EAAe,IAAI,CAAI,KAC5D,EAAW,EAAK,MAAM,EAAW,IAAI,CAAI,GAAI,GAAO,GAAG,GAAG,QAAQ,GAAO;GACvE,OAAO,EAAW,IAAI,CAAI;GAC1B,QAAQ;EACV,CAAC,GAIH,GACE,EAAK,MACL,KAAS,EAAK,KAAK,wBAAwB,EAAK,KAAK,UAAU,OACjE,GACA,EAAK,KAAK,YAAY;GACpB,GAAG,EAAK,EAAK;GACb,GAAG;GACH,OAAO,EAAK,KAAK,UAAU;GAC3B,QAAQ;EACV;CACF;CAIA,KAAK,IAAM,KAAS,EAAK,UACvB,AAAI,EAAY,EAAM,KAAK,MACzB,EAAM,aAAa;EAAE,MAAM;EAAS,GAAG;EAAa,GAAG;CAAW;CAmBtE,OAjBI,EAAU,WAAW,EAAK,MAAM,gBAAgB,aAClD,EAAU,QAAQ,UAAU,IAAI,IAAa,IAE3C,EAAO,aAAa,IAAI,KAAK,IAAI,MACnC,EAAK,iBAAiB,GACpB,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,EAAY,EAAK,MAAM,QAAQ,CACjC,IAGK,EAAK,MAAM,gBAAgB,WAAW,IAAa,IAAgB;AAC5E;AAKA,SAAS,GAAiB,GAAkB,GAAqB;CAC/D,IAAI,KAAS,GAAG;CAChB,IAAM,IAAQ,EAAK,MAAM,eACnB,IAAS,MAAU,WAAW,KAAK,MAAM,IAAQ,CAAC,IAAI,MAAU,QAAQ,IAAQ;CAEtF,IAAI,CADc,EAAK,SAAS,MAAM,MAAM,CAAC,EAAY,EAAE,KAAK,KAAK,CAAC,EAAE,SACnE,GAAW;EAId,AADA,EAAK,gBAAgB,OAAO,GAC5B,EAAK,gBAAgB,UAAU,IAAQ;EACvC;CACF;CACI,WAAU,IACd,KAAK,IAAM,KAAS,EAAK,UACnB,EAAM,cACN,EAAY,EAAM,KAAK,IACrB,EAAM,YAAY,SAAS,YAAS,EAAM,WAAW,KAAK,KAE9D,EAAM,UAAU,KAAK;AAG3B;AAKA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACa;CACb,IAAM,IAAI,EAAU,aACd,IAAI,EAAU,KAAK,QACnB,IAAmB,CAAC,GACpB,KAAS,MACb,IAAI,IAAI,EAAK,KAAM,EAAO,OAAO,KAAM,EAAK,IAAI,KAAM,EAAO,IAAI,IAC7D,KAAS,MACb,IAAI,IAAI,EAAK,KAAM,EAAO,OAAO,KAAM,EAAK,IAAI,KAAM,EAAW,IAAI;CAGvE,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,IAAW,EAAO,UAAU;EAClC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,IAAM,IAAM,EAAS;GACrB,IAAI,CAAC,GAAK;GAGV,IAAM,IAAQ,GAAU,EAAI,OAAO,KAAK,CAAG;GAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,OAAO,KAC7B,KAAK,IAAI,IAAK,EAAK,IAAK,IAAK,EAAK,KAAM,EAAW,IAAK,KACtD,EAAI,KAAK;IACP;IACA,GAAG,IAAc,EAAM,CAAC,IAAI;IAC5B,GAAG,IAAa;IAChB,QAAQ;IACR,OAAO,EAAI;GACb,CAAC;EACP;CACF;CAEA,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAM,IAAW,EAAO,UAAU;EAClC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;GAC1B,IAAM,IAAM,EAAS;GACrB,IAAI,CAAC,GAAK;GACV,IAAM,IAAQ,GAAU,EAAI,OAAO,KAAK,CAAG;GAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,OAAO,KAC7B,EAAI,KAAK;IACP;IACA,GAAG,IAAc,EAAK;IACtB,GAAG,IAAa,EAAM,CAAC,IAAI;IAC3B,QAAQ,EAAO;IACf,OAAO,EAAI;GACb,CAAC;EACL;CACF;CAEA,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAClB,QAAO,OAAO,MAAO,IACzB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;EAC3B,IAAI,EAAO,OAAO,MAAO,GAAG;EAC5B,IAAM,IAAK,IAAI,IAAI,EAAO,UAAU,EAAE,CAAE,IAAI,KAAK,MAC3C,IAAO,IAAI,IAAI,EAAO,UAAU,EAAE,CAAE,KAAK,MACzC,IAAO,IAAI,IAAI,EAAO,UAAU,EAAE,CAAE,IAAI,KAAK,MAC7C,IAAQ,IAAI,IAAI,EAAO,UAAU,EAAE,CAAE,KAAK,MAC1C,IAAO;GAAC;GAAI;GAAM;GAAM;EAAK,CAAC,CAAC,QAAQ,MAA2B,MAAM,IAAI;EAClF,IAAI,EAAK,WAAW,GAAG;EAGvB,IAAM,IAAqB,EAAK,OAAO,MAAM,EAAE,UAAU,QAAQ,IAAI,WAAW,SAC1E,IAAW,EAAK,QAAQ,GAAG,MAC/B,EAAE,QAAQ,EAAE,SAAU,EAAE,UAAU,EAAE,SAAS,GAAW,EAAE,SAAS,GAAW,EAAE,SAC5E,IACA,CACN,GACM,IAAQ,GACZ,GACA,MAAO,MACP,MAAS,MACT,MAAS,MACT,MAAU,MACV,CACF;EAEA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAO,OAAO,IAAK,KACrC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAO,OAAO,IAAK,KACrC,EAAI,KAAK;GACP;GACA,GAAG,IAAc,EAAM,CAAC,IAAI;GAC5B,GAAG,IAAa,EAAM,CAAC,IAAI;GAC3B,QAAQ;GACR,OAAO,EAAS;EAClB,CAAC;CACP;CAEF,OAAO;AACT;;;ACj9BA,SAAS,GAAkB,GAA6B;CAGtD,OAFI,EAAM,aAAa,cAAc,EAAM,aAAa,UAAgB,aACpE,EAAM,aAAa,cAAc,EAAM,aAAa,WAAiB,aAClE;AACT;AAQA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACM;CACN,KAAK,IAAM,KAAS,EAAK,UAAU;EACjC,IAAM,IAAY,GAAkB,EAAM,KAAK;EAC/C,IAAI,MAAc,YAAY;GAG5B,IAAM,IACJ,EAAK,UAAU,QACf,EAAK,MAAM,OAAO,OAClB,EAAK,MAAM,OAAO,QAClB,EAAK,gBAAgB,OACrB,EAAK,gBAAgB,OACjB,IACJ,EAAK,UAAU,SACf,EAAK,MAAM,OAAO,MAClB,EAAK,MAAM,OAAO,SAClB,EAAK,gBAAgB,MACrB,EAAK,gBAAgB;GAMvB,AALA,EAAM,UAAU,KAAK,GACnB,EAAM,MAAM,OAAO,MACnB,EAAM,MAAM,OAAO,OACnB,CACF,GACA,EAAM,UAAU,KAAK,GACnB,EAAM,MAAM,OAAO,KACnB,EAAM,MAAM,OAAO,QACnB,CACF;EACF,OAAO,AAAI,MAAc,cACvB,GAAc,GAAO,GAAM,GAAM,GAAM,GAAW,CAAK;EAEzD,GACE,GACA,IAAO,EAAM,UAAU,GACvB,IAAO,EAAM,UAAU,GACvB,CACE,GAAG,GACH;GAAE,MAAM;GAAO,MAAM,IAAO,EAAM,UAAU;GAAG,MAAM,IAAO,EAAM,UAAU;EAAE,CAChF,GACA,CACF;CACF;AACF;AAEA,SAAS,GAAe,GAA0B,GAAwB,GAAuB;CAG/F,OAFI,MAAU,OACV,MAAQ,OACL,IADkB,CAAC,EAAc,GAAK,CAAK,IADvB,EAAc,GAAO,CAAK;AAGvD;AAIA,SAAS,GAAgB,GAAoB,GAAsB;CACjE,IAAI,CAAC,GACH,KAAK,IAAI,IAAI,EAAU,SAAS,GAAG,IAAI,GAAG,KAAK;EAC7C,IAAM,IAAQ,EAAU;EACxB,IAAI,CAAC,GAAa,EAAM,KAAK,KAAK,GAAG;EACrC,IAAM,IAAI,EAAM,KAAK,MAAM;EAC3B,OAAO;GACL,GAAG,EAAM,OAAO,EAAE;GAClB,GAAG,EAAM,OAAO,EAAE;GAClB,OAAO,KAAK,IAAI,GAAG,EAAM,KAAK,UAAU,QAAQ,EAAE,OAAO,EAAE,KAAK;GAChE,QAAQ,KAAK,IAAI,GAAG,EAAM,KAAK,UAAU,SAAS,EAAE,MAAM,EAAE,MAAM;EACpE;CACF;CAEF,IAAM,IAAO,EAAU;CACvB,OAAO;EACL,GAAG,EAAK;EACR,GAAG,EAAK;EACR,OAAO,EAAK,KAAK,UAAU;EAC3B,QAAQ,EAAK,KAAK,UAAU;CAC9B;AACF;AAEA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACM;CACN,IAAM,IAAQ,EAAM,OACd,IAAQ,EAAM,aAAa,SAC3B,IAAO,EAAM,YAGb,IACJ,GAAM,SAAS,UAAU,CAAC,KAAS,GAAa,EAAO,KAAK,IACxD;EACE,GAAG,IAAa,EAAK,KAAK;EAC1B,GAAG,IAAa,EAAK,KAAK;EAC1B,OAAO,EAAK,KAAK;EACjB,QAAQ,EAAK,KAAK;CACpB,IACA,GAAgB,GAAW,CAAK,GAChC,IAAO,EAAM,OAAO,SAAS,OAAO,OAAO,EAAc,EAAM,OAAO,MAAM,EAAG,KAAK,GACpF,IAAQ,EAAM,OAAO,UAAU,OAAO,OAAO,EAAc,EAAM,OAAO,OAAO,EAAG,KAAK,GACvF,IAAM,EAAM,OAAO,QAAQ,OAAO,OAAO,EAAc,EAAM,OAAO,KAAK,EAAG,MAAM,GAClF,IACJ,EAAM,OAAO,WAAW,OAAO,OAAO,EAAc,EAAM,OAAO,QAAQ,EAAG,MAAM,GAC9E,IAAS,EAAc,EAAM,QAAQ,EAAG,KAAK,GAC7C,IAAa,EAAO,QAAQ,GAC5B,IAAc,EAAO,SAAS,GAC9B,IAAY,EAAO,OAAO,GAC1B,IAAe,EAAO,UAAU,GAOhC,IAAY,EAAM,UAAU,KAAA,KAAa,EAAM,MAAM,SAAS,QAC9D,IAAa,EAAM,WAAW,KAAA,KAAa,EAAM,OAAO,SAAS,QACjE,IAAO,GAAkB,EAAM,UAAU,EAAG,OAAO,GAAO,CAAK,KAAK,GACpE,IAAO,GAAkB,EAAM,UAAU,EAAG,OAAO,GAAO,CAAK,GAC/D,IAA8C,CAAC;CACrD,IAAI,CAAC,GACH,EAAO,QAAQ,EAAU,EAAmB,EAAM,OAAQ,EAAG,OAAO,GAAO,CAAK,GAAG,GAAM,CAAI;MACxF,IAAI,MAAS,QAAQ,MAAU,MACpC,EAAO,QAAQ,EACb,KAAK,IAAI,GAAG,EAAG,QAAQ,IAAO,IAAQ,IAAa,CAAW,GAC9D,GACA,CACF;MACK;EACL,IAAM,IAAY,KAAK,IAAI,GAAG,EAAG,SAAS,KAAQ,MAAM,KAAS,KAAK,IAAa,CAAW;EAC9F,EAAO,QAAQ,EACb,KAAK,IACH,EAAoB,GAAO,CAAK,GAChC,KAAK,IAAI,GAAqB,GAAO,CAAK,GAAG,CAAS,CACxD,GACA,GACA,CACF;CACF;CAQA,AAPI,MAAQ,QAAQ,MAAW,QAAQ,MACrC,EAAO,SAAS,EACd,KAAK,IAAI,GAAG,EAAG,SAAS,IAAM,IAAS,IAAY,CAAY,GAC/D,EAAa,EAAM,WAAW,EAAG,MAAM,KAAK,GAC5C,EAAa,EAAM,WAAW,EAAG,MAAM,CACzC,IAEF,EAAW,GAAO,EAAG,OAAO,EAAG,QAAQ,GAAG,GAAG,UAAU,GAAO,CAAM;CACpE,IAAM,IAAQ,EAAM,UAAU,OACxB,IAAS,EAAM,UAAU,QAI3B;CACJ,IAAI,MAAS,QAAQ,MAAU,MAAM;EACnC,IAAM,IAAQ,KAAK,IAAI,GAAG,EAAG,QAAQ,IAAO,IAAQ,IAAQ,IAAa,CAAW,GAC9E,IAAW,EAAO,SAAS,QAAQ,EAAO,UAAU;EAC1D,IACE,EAAG,IACH,IACA,KACC,IAAW,KAAK,MAAM,IAAQ,CAAC,IAAI,EAAO,SAAS,OAAO,IAAQ;CACvE,OAAO,AACL,IADS,MAAS,OAET,MAAU,OAGf,GAAgB,GAAO,GAAQ,GAAY,CAAK,IAFhD,EAAG,IAAI,EAAG,QAAQ,IAAQ,IAAQ,IAFlC,EAAG,IAAI,IAAO;CAMpB,IAAI;CACJ,IAAI,MAAQ,QAAQ,MAAW,MAAM;EACnC,IAAM,IAAQ,KAAK,IAAI,GAAG,EAAG,SAAS,IAAM,IAAS,IAAS,IAAY,CAAY,GAChF,IAAW,EAAO,QAAQ,QAAQ,EAAO,WAAW;EAC1D,IACE,EAAG,IAAI,IAAM,KAAa,IAAW,KAAK,MAAM,IAAQ,CAAC,IAAI,EAAO,QAAQ,OAAO,IAAQ;CAC/F,OAAO,AACL,IADS,MAAQ,OAER,MAAW,OAGhB,GAAgB,GAAO,GAAQ,GAAY,CAAM,IAFjD,EAAG,IAAI,EAAG,SAAS,IAAS,IAAS,IAFrC,EAAG,IAAI,IAAM;CAOnB,EAAM,YAAY;EAAE,GAAG,EAAM;EAAW,GAAG,IAAI;EAAY,GAAG,IAAI;CAAW;AAC/E;AAKA,SAAS,GACP,GACA,GACA,GACQ;CACR,OAAO,EAAgB,GAAS,CAAC,CAAI,GAAG,KAAK,IAAI,GAAG,IAAQ,CAAI,CAAC,CAAC,CAAC;AACrE;AAGA,SAAS,GACP,GACA,GACA,GACA,GACQ;CACR,OAAO,EAAiB,GAAe,GAAO,CAAM,GAAG,GAAO,CAAI;AACpE;AAIA,SAAS,GACP,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAS,EAAc,EAAM,MAAM,QAAQ,EAAK,UAAU,GAC1D,CAAC,GAAQ,GAAO,GAAO,KAC3B,MAAS,MACJ;EAAC,EAAO,QAAQ;EAAG,EAAO,SAAS;EAAG,EAAK;EAAY,EAAK,cAAc;CAAK,IAC/E;EACC,EAAO,OAAO;EACd,EAAO,UAAU;EACjB,EAAK;EACL,EAAK,cAAc;CACrB,GACA,IAAQ,IAAO,IAAS;CAI9B,QAHe,IACX,GAAmB,GAAiB,EAAO,KAAK,GAAG,GAAO,CAAK,IAC/D,GAAoB,GAAO,GAAQ,GAAO,CAAK,KACnC;AAClB;AAKA,SAAS,GACP,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAS,EAAc,EAAM,MAAM,QAAQ,EAAK,KAAK,GACrD,IACJ,EAAM,MAAM,gBAAgB,SACxB,EAAO,MAAM,eACZ,EAAM,MAAM,aACb,CAAC,GAAQ,GAAO,GAAO,KAC3B,MAAS,MACJ;EAAC,EAAO,QAAQ;EAAG,EAAO,SAAS;EAAG,EAAK;EAAO;CAAO,IACzD;EACC,EAAO,OAAO;EACd,EAAO,UAAU;EACjB,EAAK;EACL,GAAe,GAAO,CAAM;CAC9B;CACN,OAAO,EAAiB,GAAO,GAAO,IAAO,IAAS,CAAK,IAAI;AACjE;AAEA,SAAS,GACP,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAO,EAAM;CAQnB,OAPI,MAAS,KAAA,IAAkB,IAC3B,EAAK,SAAS,UAAgB,IAAa,EAAK,IAChD,EAAK,SAAS,SAEd,IAAa,EAAK,WAAW,IAAI,GAAiB,GAAO,GAAQ,EAAK,YAAY,KAAK,CAAK,IAGzF,IAAa,EAAK,UAAU,GAAiB,GAAO,GAAQ,GAAM,KAAK,CAAK;AACrF;AAEA,SAAS,GACP,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAO,EAAM;CAQnB,OAPI,MAAS,KAAA,IAAkB,IAC3B,EAAK,SAAS,UAAgB,IAAa,EAAK,IAChD,EAAK,SAAS,SAEd,IAAa,EAAK,WAAW,IAAI,GAAiB,GAAO,GAAQ,EAAK,YAAY,KAAK,CAAM,IAG1F,IAAa,EAAK,UAAU,GAAiB,GAAO,GAAQ,GAAM,KAAK,CAAM;AACtF;;;ACrRA,SAAgB,GAAW,GAAkB,GAA4C;CACvF,IAAM,IAAQ,GAAmB;CAKjC,AAJA,EAAW,GAAM,GAAgB,KAAA,GAAW,GAAG,GAAG,QAAQ,CAAK,GAI/D,GAAe,GAAM,GAAG,GAAG,CAAC;EAAE,MAAM;EAAM,MAAM;EAAG,MAAM;CAAE,CAAC,GAAG,CAAK;CAKpE,IAAM,IAAS,EAAK,UAAU,QACxB,IAAM,GAAc,CAAI,GACxB,EAAE,gBAAa,EAAK;CAG1B,OAFI,EAAS,MAAM,cAAW,EAAK,UAAU,QAAQ,KAAK,IAAI,EAAK,UAAU,OAAO,EAAI,CAAC,IACrF,EAAS,MAAM,cAAW,EAAK,UAAU,SAAS,KAAK,IAAI,GAAQ,EAAI,CAAC,IACrE,EAAE,UAAO;AAClB;AAGA,SAAgB,EAAY,GAA2B;CACrD,OAAO,EAAM,aAAa,cAAc,EAAM,aAAa;AAC7D;AAGA,SAAgB,GAAa,GAA2B;CACtD,OAAO,EAAM,aAAa;AAC5B;AAeA,SAAgB,KAAqC;CACnD,OAAO;EACL,4BAAY,IAAI,QAAQ;EACxB,4BAAY,IAAI,QAAQ;EACxB,+BAAe,IAAI,QAAQ;EAC3B,2BAAW,IAAI,QAAQ;CACzB;AACF;AASA,SAAgB,EACd,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GAQM;CACN,IAAM,IAAQ,EAAK,OACb,IAAe,GAAQ;CAO7B,AAJA,OAAO,EAAK,gBACZ,OAAO,EAAK,kBACZ,OAAO,EAAK,cACZ,OAAO,EAAK,kBACZ,OAAO,EAAK;CAQZ,IAAM,IAAW,GAAkB,EAAM,UAAU,GAAgB,GAAM,CAAK,KAAK,GAC7E,IAAW,GAAkB,EAAM,UAAU,GAAgB,GAAM,CAAK,GACxE,IAAY,EAAa,EAAM,WAAW,CAAe,KAAK,GAC9D,IAAY,EAAa,EAAM,WAAW,CAAe,GAIzD,IAAS,GAAa,CAAK,GAC3B,IAAQ,GAAkB,CAAK;CAErC,AADI,GAAQ,QAAQ,UAAO,EAAO,QAAQ,EAAM,QAC5C,GAAQ,QAAQ,WAAQ,EAAO,SAAS,EAAM;CAClD,IAAM,IAAkB;EACtB,KAAK,EAAc,EAAM,QAAQ,KAAK,CAAc;EACpD,OAAO,EAAc,EAAM,QAAQ,OAAO,CAAc,IAAI,EAAO;EACnE,QAAQ,EAAc,EAAM,QAAQ,QAAQ,CAAc,IAAI,EAAO;EACrE,MAAM,EAAc,EAAM,QAAQ,MAAM,CAAc;CACxD;CACA,EAAK,kBAAkB;CACvB,IAAM,IACJ,GAAQ,SACR,EAAU,GAAa,GAAO,GAAgB,GAAW,GAAM,CAAK,GAAG,GAAU,CAAQ,GACrF,IAAsB,GAAc,GAAO,CAAe,GAS1D,IAAQ,GACZ,GAHA,KAAgB,MAAwB,IAAY,IAAI,IAAY,KAAA,MAIhD,UACpB,EAAM,QACN,CACF,GAMM,IAAmB,MAAiB,KAAA,KAAa,MAAwB,KAAA,GAKzE,IACJ,MAAc,KAAA,IACV,KAAA,IACA,KAAK,IACH,GACA,IAAY,EAAM,OAAO,MAAM,EAAM,OAAO,SAAS,EAAQ,MAAM,EAAQ,MAC7E,GAQA,IAAS,GAAkB,CAAI,GAC/B,KAAiB,GAAqB,MAA8B;EACxE,IAAM,IAAgB,KAAY,OAAO,SAAS,CAAW,IAAI,IAAc,KAAA;EAmD/E,OAlDI,IACK,GACL,GACA,EAAM,OACN,GACA,GACA,GACA,GACA,CACF,IAEE,EAAM,YAAY,UAAU,EAAM,kBAAkB,QAC/C,GACL,GACA,EAAM,OACN,GACA,GACA,EAAM,QACN,GACA,CACF,IAEE,EAAM,YAAY,SACb,GACL,GACA,EAAM,OACN,GACA,GACA,EAAM,QACN,GACA,CACF,IAEE,EAAM,YAAY,SACb,GAAW,GAAM,EAAM,OAAO,GAAa,EAAM,QAAQ,GAAS,CAAK,IAE5E,EAAM,YAAY,UACb,GAAY,GAAM,EAAM,OAAO,GAAe,EAAM,QAAQ,GAAS,CAAK,IAE/E,EAAM,YAAY,aACb,GACL,GACA,EAAM,OACN,GACA,GACA,EAAM,QACN,GACA,CACF,IAEK,GAAY,GAAM,EAAM,OAAO,GAAe,EAAM,QAAQ,GAAS,CAAK;CACnF,GACI,IAAgB,EAAc,EAAM,QAAQ,CAAgB;CAEhE,IADuB,CAAC,MAAW,EAAM,YAAY,UAAU,EAAM,YAAY,WAC3D,CAAC,KAAoB,MAAc,KAAA,GAAW;EAElE,IAAM,IAAU,EAAM,OAAO,MAAM,EAAM,OAAO,SAAS,EAAQ,MAAM,EAAQ,QACzE,IAAY,EAAU,IAAgB,GAAS,GAAW,CAAS,IAAI;EAC7E,AAAI,IAAY,MAAe,IAAgB,EAAc,KAAK,IAAI,GAAG,CAAS,GAAG,EAAI;CAC3F;CAEA,IAAM,IACJ,IAAgB,EAAM,OAAO,MAAM,EAAM,OAAO,SAAS,EAAQ,MAAM,EAAQ,QAM3E,IAAkB,KAAgB,KAAuB;CAE/D,AADA,EAAK,kBAAkB,GACvB,EAAK,uBAAuB;CAC5B,IAAM,IAAc,EAAU,GAAiB,GAAW,CAAS,GAU7D,IAAmB,EAAK;CAC9B,IAAI,GAAkB;EACpB,IAAM,IACJ,IAAc,EAAM,OAAO,MAAM,EAAM,OAAO,SAAS,EAAQ,MAAM,EAAQ;EAG/E,AAFI,IAAqB,EAAiB,cACxC,EAAQ,UAAU,IAAqB,EAAiB,YAC1D,GAAqB,GAAM,GAAkB,EAAM,QAAQ,CAAO;CACpE;CAMA,IAJA,EAAK,YAAY;EAAE,GAAG;EAAS,GAAG;EAAS,OAAO;EAAY,QAAQ;CAAY,GAI9E,GAAY,EAAM,SAAS,CAAC,KAAK,GAAY,EAAM,SAAS,CAAC,GAAG;EAClE,IAAM,IAAS,GAAc,CAAI,GAC3B,IAAQ,KAAK,IAAI,GAAG,EAAO,IAAI,EAAM,OAAO,OAAO,EAAQ,IAAI,GAC/D,IAAQ,KAAK,IAAI,GAAG,EAAO,IAAI,EAAM,OAAO,MAAM,EAAQ,GAAG,GAC7D,IAAW,KAAK,IACpB,GACA,IAAa,EAAM,OAAO,OAAO,EAAM,OAAO,QAAQ,EAAQ,OAAO,EAAQ,KAC/E,GACM,IAAW,KAAK,IACpB,GACA,IAAc,EAAM,OAAO,MAAM,EAAM,OAAO,SAAS,EAAQ,MAAM,EAAQ,MAC/E;EAaA,IAZA,EAAK,cAAc;GACjB;GACA;GACA,MAAM,GAAY,EAAM,SAAS,CAAC,IAAI,KAAK,IAAI,GAAG,IAAQ,CAAQ,IAAI;GACtE,MAAM,GAAY,EAAM,SAAS,CAAC,IAAI,KAAK,IAAI,GAAG,IAAQ,CAAQ,IAAI;EACxE,GAOI,EAAM,mBAAmB,QAAQ;GACnC,IAAM,IAAO,GAAQ,UAAU;IAAE,OAAO;IAAO,QAAQ;GAAM,GACvD,IAAQ,EAAK,SAAU,EAAM,SAAS,MAAM,UAAU,EAAK,YAAY,OAAO,GAC9E,IAAQ,EAAK,UAAW,EAAM,SAAS,MAAM,UAAU,EAAK,YAAY,OAAO;GACrF,IAAI,MAAU,EAAK,SAAS,MAAU,EAAK,QAAQ;IACjD,EAAW,GAAM,GAAgB,GAAiB,GAAS,GAAS,GAAW,GAAO;KACpF,GAAG;KACH,QAAQ;MAAE,OAAO;MAAO,QAAQ;KAAM;IACxC,CAAC;IACD;GACF;EACF;EACA,EAAK,oBAAoB;GAAE,OAAO,EAAO;GAAO,QAAQ,EAAO;EAAO;CACxE,OAEE,AADA,OAAO,EAAK,aACZ,OAAO,EAAK;AAEhB;AAUA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAK,OACf;CACJ,IAAI,EAAK,MAAM;EAKb,IAAM,IAAQ,GAAc,CAAI;EAChC,GAAiB,EAAK,OAAO,GAAW,MAAa;GACnD,IAAM,IAAM,EAAM;GAElB,AADA,EAAW,GAAK,GAAY,KAAA,GAAW,GAAG,GAAG,UAAU,CAAK,GAC5D,EAAK,SAAU,KAAa,KAAK,IAAI,GAAG,EAAI,UAAU,KAAK;EAC7D,CAAC;EACD,IAAI,GACA;EACJ,IAAI,EAAM,YAAY,YAAY;GAOhC,IAAM,IAAM,GAAW,GAAO,KAAK,CAAU,GACvC,IAAU,GAAmB,GAAO,GAAY,CAAG;GACzD,EAAQ,SAAS,EAAQ;GACzB,IAAM,IAAW,GACf,GACA,GACA,GACA,GAAkB,GAAqB,CAAc,CACvD;GAGA,AAFA,EAAK,mBAAmB,GACxB,IAAW,GACX,IAAQ,EAAS;EACnB,OACE,IAAW,GAAiB,GAAM,CAAU;EA0B9C,IAxBA,IAAgB,EAAS,WACzB,EAAK,aAAa;GAChB,OAAO,EAAS,MAAM,QACnB,GAAK,MACJ,KAAK,IAAI,GAAK,EAAY,EAAK,OAAO,EAAK,KAAK,EAAK,UAAU,EAAM,QAAQ,CAAC,GAChF,CACF;GACA,MAAM,EAAS;EACjB,GAUA,GAAc,GAAM,GAAU,GAAY,GAAa,CAAO,GAM1D,EAAM,SAAS,GAAG;GACpB,IAAM,KAAc,MAClB,EAAS,MAAM,WAAW,MAAS,KAAa,EAAK,SAAS,IAAY,EAAK,GAAG;GACpF,GAAiB,EAAK,OAAO,GAAW,MAAa;IACnD,IAAM,IAAO,EAAW,CAAS;IACjC,IAAI,MAAS,IAAI;IACjB,IAAM,IAAO,EAAS,MAAM;IAC5B,EAAM,EAAS,CAAE,YAAY;KAC3B,GAAG,EAAM,EAAS,CAAE;KACpB,GACE,EAAM,OAAO,OACb,EAAQ,QACP,IAAQ,MAAS,KAClB,GAAU,EAAK,OAAO,GAAW,EAAK,QAAQ;KAChD,GAAG,EAAM,OAAO,MAAM,EAAQ,MAAM,EAAS,MAAM;IACrD;GACF,CAAC;EACH;CACF,OACE,IAAgB,EAAK;CAKvB,KAAK,IAAM,KAAS,EAAK,UAAU;EACjC,IAAI,EAAM,WAAW;EACrB,IAAM,IAAS,EAAc,EAAM,MAAM,QAAQ,CAAU;EAC3D,EAAM,aAAa;GACjB,MAAM;GACN,GAAG,EAAM,OAAO,OAAO,EAAQ,QAAQ,EAAO,QAAQ;GACtD,GAAG,EAAM,OAAO,MAAM,EAAQ,OAAO,EAAO,OAAO;EACrD;CACF;CACA,OAAO;AACT;AAcA,SAAS,GAAkB,GAA2B;CAKpD,OAJ0B,EAAK,SAAS,MACrC,MAAU,CAAC,EAAY,EAAM,KAAK,KAAK,CAAC,EAAM,SAE7C,IAA0B,KACvB,EAAK,SAAS,MAAO,EAAK,MAAM,YAAY,UAAU,EAAK,MAAM,YAAY;AACtF;AAEA,SAAgB,EAAU,GAAe,GAAa,GAAiC;CAErF,OAAO,KAAK,IAAI,GADA,MAAQ,KAAA,IAAmC,IAAvB,KAAK,IAAI,GAAO,CAAG,CAC3B;AAC9B;AAaA,SAAS,GACP,GACA,GACA,GACA,GACA,GACM;CACN,IAAM,IAAQ,EAAK;CAEnB,IADI,EAAM,YAAY,UAAU,EAAM,YAAY,UAC9C,EAAS,MAAM,WAAW,GAAG;CACjC,IAAM,IAAW,EAAM,YAAY,UAAU,EAAM,kBAAkB,UAE/D,IAAY,EAAS,MAAM,QAC9B,GAAK,MAAS,KAAK,IAAI,GAAK,EAAY,EAAK,OAAO,EAAK,KAAK,EAAK,UAAU,EAAM,QAAQ,CAAC,GAC7F,CACF,GACM,IAAY,KAAK,IAAI,GAAG,IAAa,CAAS;CACpD,IAAI,IAAY,GAAG;EACjB,IAAM,IACJ,EAAM,YAAY,SACd,EAAiB,EAAM,cAAc,GAAY,CAAS,IAC1D,IACE,EAAiB,EAAM,YAAY,GAAY,CAAS,IACxD,EAAgB,GAAiB,CAAK,GAAG,CAAC,CAAS,GAAG,CAAS,CAAC,CAAC;EACzE,AAAI,IAAK,MACP,EAAQ,QAAQ,GAChB,EAAQ,SAAS,IAAY;CAEjC;CAIA,IAAI,OAAO,SAAS,CAAW,GAAG;EAChC,IAAM,IAAY,KAAK,IAAI,GAAG,IAAc,EAAS,SAAS;EAC9D,IAAI,IAAY,GAAG;GACjB,IAAM,IACJ,EAAM,YAAY,UAAU,CAAC,IACzB,EAAiB,EAAM,YAAY,GAAa,EAAS,SAAS,IAClE,EAAgB,GAAiB,CAAK,GAAG,CAAC,EAAS,SAAS,GAAG,CAAS,CAAC,CAAC;GAChF,AAAI,IAAK,MACP,EAAQ,OAAO,GACf,EAAQ,UAAU,IAAY;EAElC;CACF;AACF;AAMA,SAAgB,GACd,GACA,GAC4E;CAC5E,IAAM,IAAQ,GAAc,GAAM,CAAY,GACxC,EAAE,YAAS,mBAAgB,GAAgB,GAAM,CAAK,GACtD,IAAkB,CAAC,GACnB,IAAkB,CAAC,GACrB,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAGhC,AAFA,EAAM,KAAK,CAAC,GACZ,EAAM,KAAK,IAAI,EAAY,EAAG,GAC9B,KAAK,EAAQ,MAAO,IAAI,EAAM,SAAS,IAAI,EAAK,MAAM,UAAU;CAElE,OAAO;EAAE;EAAO;EAAO;EAAO,WAAW;CAAE;AAC7C;AAIA,SAAgB,GAAc,GAAkB,GAAkC;CAChF,OAAO,EAAK,MAAM,eAAe,WAE7B,GAAc,EAAK,MAAM,GAAc;EACrC,UAAU,EAAK;EACf,UAAU,EAAK,MAAM;EACrB,iBAAiB,EAAK,MAAM;CAC9B,CAAC,IALD,GAAc,EAAK,IAAI;AAM7B;AAYA,SAAgB,GACd,GACA,GAC8C;CAC9C,IAAM,IAAQ,GAAc,CAAI,GAC1B,IAAoB,CAAC,GACrB,IAAwB,CAAC,GAC3B,IAAW;CACf,KAAK,IAAM,KAAQ,GAAO;EACxB,IAAI,IAAS,GACT,IAAa;EACjB,KAAK,IAAI,IAAI,EAAK,OAAO,IAAI,EAAK,KAAK,KAAK;GAC1C,IAAI,EAAK,KAAK,OAAA,KAA2B;GACzC,IAAM,IAAM,EAAM;GAUlB,AATA,IAAS,KAAK,IAAI,GAAQ,EAAI,UAAU,MAAM,GAC1C,EAAI,MAAM,kBAAkB,QAC9B,IAAa,KAAK,IAAI,GAAY,EAAI,UAAU,SAAS,CAAC,IACnD,EAAI,MAAM,kBAAkB,YACnC,EACE,EAAI,QACJ,qHAEF,GACF;EACF;EAEA,AADA,EAAQ,KAAK,CAAM,GACnB,EAAY,KAAK,KAAK,IAAI,GAAY,IAAS,CAAC,CAAC;CACnD;CACA,OAAO;EAAE;EAAS;CAAY;AAChC;AAKA,SAAgB,GAAW,GAAkB,GAAiB,GAAmC;CAC/F,IAAM,IAAM,EAAc,MAAS,MAAM,EAAM,OAAO,EAAM,MAAM,CAAK,GACjE,IAAO,MAAS,MAAM,EAAM,QAAQ,EAAM;CAChD,OAAO,KAAK,IAAI,GAAK,GAAM,SAAS,CAAC;AACvC;AAIA,SAAgB,EAAc,GAAoB,GAAmC;CAEnF,OADI,OAAO,KAAW,WAAiB,IAChC,MAAU,KAAA,KAAa,CAAC,OAAO,SAAS,CAAK,IAAI,IAAI,GAAe,EAAO,SAAS,CAAK;AAClG;AAIA,SAAgB,EAAc,GAAoC,GAA+B;CAC/F,IAAM,KAAQ,MAA0B,MAAM,OAAO,OAAO,EAAc,GAAG,CAAK;CAClF,OAAO;EACL,KAAK,EAAK,EAAO,GAAG;EACpB,OAAO,EAAK,EAAO,KAAK;EACxB,QAAQ,EAAK,EAAO,MAAM;EAC1B,MAAM,EAAK,EAAO,IAAI;CACxB;AACF;AAIA,SAAS,GAAe,GAA4B;CAClD,OAAO,OAAO,KAAW,WAAW,IAAS;AAC/C;AAMA,SAAgB,EACd,GACA,GACoB;CAChB,UAAU,KAAA,KAAa,OAAO,KAAU,UAE5C,OADI,OAAO,KAAU,WAAiB,IAC/B,MAAc,KAAA,IAAY,KAAA,IAAY,GAAe,EAAM,SAAS,CAAS;AACtF;AAKA,SAAgB,GACd,GACA,GACA,GACA,GACoB;CAIpB,OAHI,MAAU,iBAAiB,MAAU,iBAAiB,MAAU,gBAC3D,EAAmB,EAAE,MAAM,EAAM,GAAG,GAAW,GAAM,CAAK,IAE5D,EAAa,GAAO,CAAS;AACtC;AAaA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAU,EAAO,OAAO,EAAQ,MAChC,IAAS,EAAO,MAAM,EAAQ,KAChC,IAAI,GACJ,IAAsC;CAC1C,KAAK,IAAM,KAAS,EAAK,UAAU;EACjC,IAAM,IAAc,EAAc,EAAM,MAAM,QAAQ,CAAU,GAC1D,IAAY,EAAY,OAAO,GAC/B,IAAe,EAAY,UAAU,GACrC,IAAa,EAAY,QAAQ,GACjC,IAAc,EAAY,SAAS;EACzC,IAAI,EAAY,EAAM,KAAK,GAAG;GAG5B,EAAM,aAAa;IACjB,MAAM;IACN,GAAG,IAAU;IACb,GACE,KACC,MAAyB,OACtB,IACA,GAAgB,GAAsB,CAAS;GACvD;GACA;EACF;EACA,EACE,GACA,KAAK,IAAI,GAAG,IAAa,IAAa,CAAW,GACjD,GACA,GACA,GACA,QACA,CACF;EACA,IAAM,IAAc,GAAiB,GAAa,GAAY,EAAM,UAAU,KAAK;EAUnF,AAJA,KACE,MAAyB,OAAO,IAAY,GAAgB,GAAsB,CAAS,GAC7F,EAAM,YAAY;GAAE,GAAG,EAAM;GAAW,GAAG,IAAU;GAAa;EAAE,GACpE,KAAK,EAAM,UAAU,QACrB,IAAuB;CACzB;CAEA,OADI,MAAyB,SAAM,KAAK,IACjC,IAAI;AACb;AAKA,SAAgB,GACd,GACA,GACA,GACQ;CACR,IAAM,IAAY,IAAY;CAG9B,OAFI,EAAO,SAAS,QAAQ,EAAO,UAAU,OAAa,KAAK,MAAM,IAAY,CAAC,IAC9E,EAAO,SAAS,OAAa,KAAa,EAAO,SAAS,KACvD,EAAO;AAChB;AAQA,SAAgB,GAAgB,GAAW,GAAmB;CAG5D,OAFI,KAAK,KAAK,KAAK,IAAU,KAAK,IAAI,GAAG,CAAC,IACtC,KAAK,KAAK,KAAK,IAAU,KAAK,IAAI,GAAG,CAAC,IACnC,IAAI;AACb;AAEA,SAAS,GACP,GACA,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAM;CACpB,IAAI,EAAM,YAAY,SAAS;EAQ7B,IAAI,CAHiB,EAAK,SAAS,MAChC,MAAU,CAAC,EAAY,EAAM,KAAK,KAAK,CAAC,EAAM,SAE5C,GAGH,OAFI,MAAU,KAAA,KAAa,EAAM,SAAS,SACjC,EAAmB,GAAO,GAAW,GAAM,CAAK,IAClD,KAAK,IAAI,GAAW,EAAoB,GAAM,CAAK,CAAC;EAE7D,IAAI,MAAU,KAAA,KAAa,EAAM,SAAS,QAAQ;GAChD,IAAM,IAAW,EAAmB,GAAO,GAAW,GAAM,CAAK;GACjE,OAAO,KAAK,IAAI,GAAU,GAAmB,GAAM,GAAW,CAAK,CAAC;EACtE;EACA,OAAO,GAAoB,GAAM,GAAW,CAAK;CACnD;CAGA,OAFI,MAAU,KAAA,KAAa,EAAM,SAAS,SACjC,EAAmB,GAAO,GAAW,GAAM,CAAK,IAClD,MAAS,WAAW,KAAK,IAAI,GAAW,EAAoB,GAAM,CAAK,CAAC,IAAI;AACrF;AAMA,SAAS,GAAc,GAA4C;CACjE,IAAI,IAAI,GACJ,IAAI;CACR,KAAK,IAAM,KAAS,EAAK,UAAU;EACjC,IAAI,EAAM,MAAM,aAAa,SAAS;EACtC,IAAM,IAAS,GAAiB,CAAK;EAErC,AADA,IAAI,KAAK,IAAI,GAAG,EAAM,UAAU,IAAI,EAAO,CAAC,GAC5C,IAAI,KAAK,IAAI,GAAG,EAAM,UAAU,IAAI,EAAO,CAAC;CAC9C;CACA,IAAI,EAAK,YAAY;EACnB,IAAM,EAAE,cAAW,EAAK,OAClB,IAAU,EAAK;EAErB,AADA,IAAI,KAAK,IAAI,GAAG,EAAO,OAAO,EAAQ,OAAO,EAAK,WAAW,KAAK,GAClE,IAAI,KAAK,IAAI,GAAG,EAAO,MAAM,EAAQ,MAAM,EAAK,WAAW,IAAI;CACjE;CACA,OAAO;EAAE;EAAG;CAAE;AAChB;AAKA,SAAS,GAAiB,GAA4C;CACpE,IAAM,EAAE,UAAO,cAAW,EAAK,WACzB,IAAS,EAAK,MAAM,SAAS,MAAM,WACnC,IAAS,EAAK,MAAM,SAAS,MAAM;CACzC,IAAI,KAAU,GAAQ,OAAO;EAAE,GAAG;EAAO,GAAG;CAAO;CACnD,IAAM,IAAU,GAAc,CAAI;CAClC,OAAO;EACL,GAAG,IAAS,IAAQ,KAAK,IAAI,GAAO,EAAQ,CAAC;EAC7C,GAAG,IAAS,IAAS,KAAK,IAAI,GAAQ,EAAQ,CAAC;CACjD;AACF;AAEA,SAAS,GAAmB,GAAkB,GAAmB,GAA+B;CAC9F,IAAM,IAAQ,EAAK;CACnB,OACE,GAA0B,GAAM,CAAK,CAAC,CAAC,MACvC,EAAM,OAAO,OACb,EAAM,OAAO,QACb,EAAc,EAAM,QAAQ,MAAM,CAAS,IAC3C,EAAc,EAAM,QAAQ,OAAO,CAAS,IAC5C,GAAa,CAAK,CAAC,CAAC;AAExB;AAEA,SAAS,GAAc,GAAkB,GAAmD;CAC1F,IAAI,EAAM,QAAQ,SAAS,SAAS,OAAO,EAAM,OAAO;CACxD,IAAI,EAAM,QAAQ,SAAS,aAAa,KAAa,MACnD,OAAO,GAAe,EAAM,OAAO,OAAO,CAAS;AAEvD;AAIA,SAAgB,EACd,GACA,GACA,GACA,GACQ;CACR,QAAQ,EAAK,MAAb;EACE,KAAK,SACH,OAAO,EAAK;EACd,KAAK,WACH,OAAO,GAAe,EAAK,OAAO,CAAS;EAC7C,KAAK,eACH,OAAO,GAAqB,GAAM,CAAK;EACzC,KAAK,eACH,OAAO,EAAoB,GAAM,CAAK;EACxC,KAAK,eACH,OAAO,KAAK,IACV,EAAoB,GAAM,CAAK,GAC/B,KAAK,IAAI,GAAqB,GAAM,CAAK,GAAG,CAAS,CACvD;EACF,KAAK,QACH,OAAO,EAAoB,GAAM,CAAK;CAC1C;AACF;AAGA,SAAgB,EAAoB,GAAkB,GAA+B;CACnF,IAAM,IAAS,EAAM,WAAW,IAAI,CAAI;CACxC,IAAI,MAAW,KAAA,GAAW,OAAO;CACjC,IAAM,IAAQ,EAAK,OAEb,IADQ,GAAoB,GAAM,CAEtC,IACA,EAAM,OAAO,OACb,EAAM,OAAO,QACb,GAAe,EAAM,QAAQ,IAAI,IACjC,GAAe,EAAM,QAAQ,KAAK,IAClC,GAAa,CAAK,CAAC,CAAC;CAEtB,OADA,EAAM,WAAW,IAAI,GAAM,CAAM,GAC1B;AACT;AAEA,SAAS,GAAoB,GAAkB,GAA+B;CAC5E,IAAM,IAAS,EAAK,SAAS,QAAQ,MAAM,CAAC,EAAY,EAAE,KAAK,KAAK,CAAC,EAAE,SAAS;CAChF,IAAI,EAAO,WAAW,GAGpB,OAFI,EAAK,MAAM,YAAY,aAClB,GAA4B,EAAK,OAAO,EAAK,cAAc,IAC7D,EAAK;CAEd,IAAI,EAAK,MAAM,YAAY,QAAQ,OAAO,GAAyB,GAAM,CAAK,CAAC,CAAC;CAChF,IAAI,EAAK,MAAM,YAAY,SAAS,OAAO,GAA0B,GAAM,CAAK,CAAC,CAAC;CAClF,IAAI,EAAK,MAAM,YAAY,UAAU,EAAK,MAAM,kBAAkB,OAAO;EACvE,IAAM,IACJ,KAAK,IAAI,GAAe,EAAK,MAAM,IAAI,GAAG,EAAK,MAAM,OAAO,SAAS,CAAC,IACtE,KAAK,IAAI,GAAG,EAAO,SAAS,CAAC;EAC/B,OAAO,EAAO,QAAQ,GAAK,MAAM,IAAM,GAAkB,GAAG,OAAO,CAAK,GAAG,CAAC,IAAI;CAClF;CACA,IAAM,IAAS,EAAO,QAAQ,GAAK,MAAM,KAAK,IAAI,GAAK,GAAkB,GAAG,OAAO,CAAK,CAAC,GAAG,CAAC;CAE7F,OADI,EAAK,MAAM,YAAY,aAAmB,GAA4B,EAAK,OAAO,CAAM,IACrF;AACT;AAMA,SAAgB,GACd,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAM,OAChB;CAIJ,AAHI,EAAM,UAAU,KAAA,KAAa,EAAM,MAAM,SAAS,UAAU,EAAM,MAAM,SAAS,cACnF,IAAQ,EAAmB,EAAM,OAAO,GAAG,GAAO,CAAK,IAErD,MAAU,KAAA,MACZ,IAAQ,MAAS,QAAQ,GAAqB,GAAO,CAAK,IAAI,EAAoB,GAAO,CAAK;CAEhG,IAAM,IAAM,OAAO,EAAM,YAAa,WAAW,EAAM,WAAW,GAC5D,IAAM,OAAO,EAAM,YAAa,WAAW,EAAM,WAAW,KAAA;CAClE,OAAO,KAAK,IAAI,GAAG,EAAU,GAAO,GAAK,CAAG,CAAC;AAC/C;AASA,SAAgB,GAAqB,GAAkB,GAA+B;CACpF,IAAM,IAAS,EAAM,WAAW,IAAI,CAAI;CACxC,IAAI,MAAW,KAAA,GAAW,OAAO;CACjC,IAAM,IAAQ,EAAK,OAEb,IADQ,GAAqB,GAAM,CAEvC,IACA,EAAM,OAAO,OACb,EAAM,OAAO,QACb,GAAe,EAAM,QAAQ,IAAI,IACjC,GAAe,EAAM,QAAQ,KAAK,IAClC,GAAa,CAAK,CAAC,CAAC;CAEtB,OADA,EAAM,WAAW,IAAI,GAAM,CAAM,GAC1B;AACT;AAEA,SAAS,GAAqB,GAAkB,GAA+B;CAC7E,IAAM,IAAS,EAAK,SAAS,QAAQ,MAAM,CAAC,EAAY,EAAE,KAAK,KAAK,CAAC,EAAE,SAAS;CAChF,IAAI,EAAO,WAAW,GAEpB,OADI,CAAC,EAAK,QAAQ,EAAK,MAAM,eAAe,WAAiB,EAAK,iBAC3D,GAAsB,EAAK,MAAM;EACtC,UAAU,EAAK;EACf,UAAU,EAAK,MAAM;CACvB,CAAC;CAEH,IAAI,EAAK,MAAM,YAAY,QAAQ,OAAO,GAAyB,GAAM,CAAK,CAAC,CAAC;CAChF,IAAI,EAAK,MAAM,YAAY,SAAS,OAAO,GAA0B,GAAM,CAAK,CAAC,CAAC;CAClF,IACE,EAAK,MAAM,YAAY,UACvB,EAAK,MAAM,kBAAkB,SAC7B,EAAK,MAAM,aAAa,UACxB;EACA,IAAM,IACJ,KAAK,IAAI,GAAe,EAAK,MAAM,IAAI,GAAG,EAAK,MAAM,OAAO,SAAS,CAAC,IACtE,KAAK,IAAI,GAAG,EAAO,SAAS,CAAC;EAC/B,OAAO,EAAO,QAAQ,GAAK,MAAM,IAAM,GAAkB,GAAG,OAAO,CAAK,GAAG,CAAC,IAAI;CAClF;CACA,OAAO,EAAO,QAAQ,GAAK,MAAM,KAAK,IAAI,GAAK,GAAkB,GAAG,OAAO,CAAK,CAAC,GAAG,CAAC;AACvF;AAEA,SAAS,GACP,GACA,GACA,GACA,GACmC;CACnC,OAAO;EACL,OAAO,KAAK,IAAI,GAAG,IAAQ,EAAO,OAAO,EAAO,QAAQ,EAAQ,OAAO,EAAQ,KAAK;EACpF,QAAQ,KAAK,IAAI,GAAG,IAAS,EAAO,MAAM,EAAO,SAAS,EAAQ,MAAM,EAAQ,MAAM;CACxF;AACF;;;ACx9BA,SAAgB,GAAgB,GAA0B;CACxD,OAAO,GAAY,CAAI,CAAC,CACrB,KAAK,KAAK,MAAQ,EAAI,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CACzC,KAAK,IAAI;AACd;AAgCA,SAAgB,GAAmB,GAAmC;CACpE,IAAM,EAAE,SAAM,cAAW,GAAY,CAAI;CACzC,OAAO,EAAK,KAAK,GAAK,MAAM,GAAY,GAAK,EAAO,EAAG,CAAC;AAC1D;AAKA,SAAS,GAAY,GAAe,GAAkD;CACpF,IAAM,IAA0B,CAAC;CACjC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK;EACnC,IAAM,IAAQ,EAAO,IACf,IAAO,EAAS,EAAS,SAAS;EACxC,AAAI,KAAQ,GAAU,GAAM,CAAK,IAAG,EAAK,QAAQ,EAAI,KAChD,EAAS,KAAK;GAAE,MAAM,EAAI;GAAK,GAAG;EAAM,CAAC;CAChD;CACA,OAAO;AACT;AAEA,SAAgB,GAAU,GAAc,GAAmC;CACzE,OACE,EAAE,UAAU,GAAG,SACf,EAAE,oBAAoB,GAAG,mBACzB,EAAE,eAAe,GAAG,cACpB,EAAE,cAAc,GAAG,aACnB,EAAE,uBAAuB,GAAG,sBAC5B,EAAE,YAAY,GAAG;AAErB;AAIA,SAAgB,GAAe,GAAkB,GAAkC;CAMjF,AALI,EAAM,UAAU,KAAA,MAAW,EAAM,QAAQ,EAAM,QAC/C,EAAM,oBAAoB,KAAA,MAAW,EAAM,kBAAkB,EAAM,kBACnE,EAAM,eAAe,KAAA,MAAW,EAAM,aAAa,EAAM,aACzD,EAAM,cAAc,KAAA,MAAW,EAAM,YAAY,EAAM,YACvD,EAAM,uBAAuB,KAAA,MAAW,EAAM,iBAAiB,EAAM,qBACrE,EAAM,YAAY,KAAA,MAAW,EAAM,UAAU,EAAM;AACzD;AAIA,SAAgB,GAAY,GAA2B;CACrD,OACE,EAAM,UAAU,KAAA,KAChB,EAAM,oBAAoB,KAAA,KAC1B,EAAM,eAAe,KAAA,KACrB,EAAM,cAAc,KAAA,KACpB,EAAM,uBAAuB,KAAA,KAC7B,EAAM,YAAY,KAAA;AAEtB;AAEA,SAAS,GAAY,GAGnB;CACA,IAAM,IAAQ,KAAK,IAAI,GAAG,EAAK,UAAU,KAAK,GACxC,IAAS,KAAK,IAAI,GAAG,EAAK,UAAU,MAAM,GAC1C,IAAmB,MAAM,KAAK,EAAE,QAAQ,EAAO,SACnD,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAS,GAAG,CACzC,GACM,IAAsC,MAAM,KAAK,EAAE,QAAQ,EAAO,SACtE,MAAM,KAAK,EAAE,QAAQ,EAAM,SAAgC,KAAA,CAAS,CACtE;CAYA,OAXA,GAAK,GAAM,GAAG,IAAI,GAAG,GAAG,GAAO,MAAU;EACvC,IAAI,KAAK,KAAK,IAAI,KAAS,KAAK,KAAK,IAAI,GAAQ;GAC/C,EAAK,EAAE,CAAE,KAAK;GAKd,IAAM,IAAW,EAAO,EAAE,CAAE;GAC5B,EAAO,EAAE,CAAE,KAAK,IAAW;IAAE,GAAG;IAAU,GAAG;GAAM,IAAI;EACzD;CACF,CAAC,GACM;EAAE;EAAM;CAAO;AACxB;AAKA,SAAS,GAAU,GAML;CACZ,IAAM,IAAmB,CAAC;CAQ1B,OAPI,EAAO,UAAO,EAAM,QAAQ,EAAO,QACnC,EAAO,oBAAiB,EAAM,kBAAkB,EAAO,kBACvD,EAAO,eAAe,SAAS,EAAO,eAAe,YAAY,EAAO,eAAe,OACzF,EAAM,aAAa,EAAO,aACxB,EAAO,cAAc,YAAY,EAAO,cAAc,OAAI,EAAM,YAAY,EAAO,YACnF,EAAO,uBAAuB,UAAU,EAAO,uBAAuB,OACxE,EAAM,qBAAqB,EAAO,qBAC7B;AACT;AAIA,SAAS,GACP,GACA,GACA,GACA,GACA,IAAQ,GACF;CACN,IAAI,EAAK,aAAa;CACtB,IAAM,IAAO,IAAa,EAAK,UAAU,GACnC,IAAO,IAAa,EAAK,UAAU,GACnC,IAAQ,EAAK,OAKb,KAAc,MAClB,KAAS,IAAI,IAAQ;EAAE,GAAG;EAAO,SAAS,OAAO,KAAK,MAAM,IAAQ,GAAI,IAAI,GAAI;CAAE;CAMpF,IAAI,EAAM,oBAAoB,KAAA,KAAa,EAAM,iBAAiB;EAIhE,IAAM,IACJ,EAAM,oBAAoB,KAAA,IAEtB,EAAE,iBAAiB,KAAA,EAAU,IAD7B,EAAW,EAAE,iBAAiB,EAAM,gBAAgB,CAAC;EAE3D,KAAK,IAAI,IAAK,GAAG,IAAK,EAAK,UAAU,QAAQ,KAC3C,KAAK,IAAI,IAAK,GAAG,IAAK,EAAK,UAAU,OAAO,KAC1C,EAAI,IAAO,GAAI,IAAO,GAAI,KAAK,CAAS;CAG9C;CAEA,IAAM,IAA0B,CAAC;CACjC,GACE,GACA;EAAE,GAAG;EAAM,GAAG;EAAM,OAAO,EAAK,UAAU;EAAO,QAAQ,EAAK,UAAU;CAAO,GAC/E,CACF;CACA,KAAK,IAAM,KAAO,GAAY;EAC5B,IAAM,IAAQ,EAAW,EAAI,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO,EAAI,MAAM,CAAC;EACnF,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK,EAAI,EAAI,IAAI,GAAG,EAAI,GAAG,EAAI,OAAO,CAAK;CAC7E;CACA,IAAI,EAAK,gBACP,KAAK,IAAM,KAAO,EAAK,gBAAgB;EACrC,IAAM,IAAQ,EAAW,EAAI,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO,EAAI,MAAM,CAAC;EACnF,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK,EAAI,IAAO,EAAI,IAAI,GAAG,IAAO,EAAI,GAAG,EAAI,OAAO,CAAK;CAC3F;CASF,IAAM,IAAS,EAAK,mBACd,IAAS,EAAM,SAAS,MAAM,WAC9B,IAAS,EAAM,SAAS,MAAM,WAC9B,IAAY,KAAQ,EAAK,QAAQ,KAAK,IACtC,IAAY,KAAQ,EAAK,QAAQ,KAAK,IACxC,IAAa;CACjB,IAAI,KAAU,GAAQ;EACpB,IAAM,IAAK,IAAO,EAAM,OAAO,MACzB,IAAK,IAAO,EAAM,OAAO,KACzB,IAAK,IAAO,EAAK,UAAU,QAAQ,EAAM,OAAO,SAAS,GAAQ,SAAS,IAC1E,IAAK,IAAO,EAAK,UAAU,SAAS,EAAM,OAAO,UAAU,GAAQ,UAAU;EACnF,KAAc,GAAG,GAAG,GAAO,MAAU;GAC/B,MAAW,IAAI,KAAM,KAAK,MAC1B,MAAW,IAAI,KAAM,KAAK,MAC9B,EAAI,GAAG,GAAG,GAAO,CAAK;EACxB;CACF;CAMA,IAAI,CAJsB,EAAK,SAAS,MACrC,MACC,CAAC,EAAM,aAAa,EAAM,MAAM,aAAa,cAAc,EAAM,MAAM,aAAa,OAEnF,KAAqB,EAAK,MAAM;EACnC,IAAM,IAAY,EAAW,GAAU,CAAK,CAAC,GACvC,IAAe,EAAK,gBAAgB,KAAK,MAAU,EAAW,GAAU,CAAK,CAAC,CAAC;EACrF,GACE,GACA,GACA,IACC,GAAG,GAAG,MAAM;GACX,IAAM,IAAc,EAAK,aAAa,MAAM,IACtC,IAAQ,KAAe,IAAI,EAAK,eAAgB,KAAe,KAAA;GAGrE,AAAI,EAAK,KAAK,OAAA,MACR,GAAO,mBACT,EAAW,GAAG,GAAG,KAAK,EAAW,EAAE,iBAAiB,EAAM,gBAAgB,CAAC,CAAC,IAG9E,EAAW,GAAG,GAAG,EAAK,KAAK,IAAK,IAAQ,EAAc,KAAe,CAAS;EAElF,IACC,GAAG,MAAM,EAAW,GAAG,GAAG,KAAK,CAAS,CAC3C;CACF;CAEA,KAAK,IAAM,KAAS,GAAqB,CAAI,GAC3C,GAAK,GAAO,GAAW,GAAW,GAAY,IAAQ,EAAM,MAAM,OAAO;CAO3E,IAAM,IAAQ,EAAK;CACnB,IAAI,KAAS,MAAW,EAAO,QAAQ,KAAK,EAAO,SAAS,IAAI;EAC9D,IAAM,EAAE,UAAO,aAAU,EAAa,EAAY,EAAM,QAAQ,CAAC,GAG3D,KAAY,MAChB,EAAW,IAAQ,EAAE,SAAM,IAAI,KAAA,CAAS,GACpC,IAAa,EAAS,EAAM,gBAAgB,SAAS,EAAM,KAAK,GAChE,IAAa,EAAS,EAAM,gBAAgB,SAAS,EAAM,KAAK,GAChE,IAAO,GAAkB,GAAM,GAAM,CAAI;EAC/C,IAAI,EAAK,GAAG;GACV,IAAM,EAAE,QAAK,QAAK,UAAO,WAAQ,EAAK,GAChC,EAAE,OAAI,KAAK,MAAa,GAAU,GAAK,EAAM,OAAO,EAAM,MAAM,EAAK,QAAQ,KAAK,CAAC;GACzF,KAAK,IAAI,IAAK,GAAG,IAAK,GAAO,KAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAK,KAAK;IAC5B,IAAM,IAAU,KAAK,KAAM,IAAI,IAAK;IACpC,EAAI,IAAM,GAAI,IAAM,GAAG,IAAU,IAAQ,GAAO,IAAU,IAAa,CAAU;GACnF;EAEJ;EACA,IAAI,EAAK,GAAG;GACV,IAAM,EAAE,QAAK,QAAK,UAAO,WAAQ,EAAK,GAChC,EAAE,OAAI,KAAK,MAAa,GAAU,GAAK,EAAM,OAAO,EAAM,MAAM,EAAK,QAAQ,KAAK,CAAC;GACzF,KAAK,IAAI,IAAK,GAAG,IAAK,GAAO,KAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAK,KAAK;IAC5B,IAAM,IAAU,KAAK,KAAM,IAAI,IAAK;IACpC,EAAI,IAAM,GAAG,IAAM,GAAI,IAAU,IAAQ,GAAO,IAAU,IAAa,CAAU;GACnF;EAEJ;CACF;AACF;AASA,SAAS,GACP,GACA,GACA,GACA,GACA,GACM;CACN,IAAM,IAAQ,EAAK,OACb,IAAU,EAAK,iBACf,IAAW,IAAO,EAAM,OAAO,OAAO,EAAQ,MAC9C,IAAW,IAAO,EAAM,OAAO,MAAM,EAAQ,KAC7C,IACJ,EAAK,UAAU,QAAQ,EAAM,OAAO,OAAO,EAAM,OAAO,QAAQ,EAAQ,OAAO,EAAQ,OACnF,IAAW,EAAK,kBAChB,EAAE,UAAO,aAAU,KAAY,GAAiB,GAAM,CAAY,GAKlE,IAAa,IAAW,KAAK,IAAI,GAAG,EAAS,cAAc,EAAM,QAAQ,IAAI;CACnF,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAO,EAAM,IACb,IAAM,IAAW,EAAM,IAGvB,IAAS,MAAM,IAAI,EAAM,aAAa,GACtC,IACJ,EAAM,eAAe,YAAY,EAAM,SAAS,MAAM,SAClD,GAAa,EAAK,MAAM,GAAM,IAAa,GAAQ,EAAK,UAAU,CAAK,IACvE;GAAE,KAAK,EAAK;GAAK,UAAU;EAAM,GAIjC,IAAY,EAAY,EAAK,OAAO,EAAK,KAAK,EAAK,UAAU,EAAM,QAAQ,GAC3E,IAAW,KAAK,IAAI,GAAG,IAAa,IAAS,CAAS,GACtD,IACJ,EAAM,cAAc,QAChB,IACA,EAAM,cAAc,WAClB,KAAK,MAAM,IAAW,CAAC,IACvB,GACJ,IAAI,KAAY,GAAU,MAAM,MAAM,KAAK,IAAc;EAC7D,KAAK,IAAI,IAAI,EAAK,OAAO,IAAI,EAAU,KAAK,KAAK;GAC/C,IAAM,IAAU,GAAU,GAAG,IAAI,GAAG,EAAK,QAAQ;GACjD,IAAI,EAAK,KAAK,OAAA,KAA2B;IAGvC,IAAM,IAAS,EAAK,iBAAiB,EAAK,aAAa,MAAM,GAAG,EAAE,QAC5D,IAAK,IAAU,EAAO,SAAS,EAAO,UAAU,OAAuB,IAAhB,CAAC,EAAO,SAAc,GAC7E,IAAK,IAAU,EAAO,QAAQ,EAAO,WAAW,OAAwB,IAAjB,CAAC,EAAO,UAAe;IACpF,EAAO,GAAG,IAAI,GAAI,IAAM,GAAI,CAAO;GACrC;GACA,KAAK;EACP;EACA,AAAI,EAAU,YAAU,IAAa,GAAG,CAAG;CAC7C;AACF;AAOA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACS;CACT,IAAM,IAAW,EAAK;CACtB,IAAI,CAAC,GAAU,OAAO;CACtB,IAAM,IAAQ,EAAK,OACb,IAAU,EAAK,iBACf,IAAI,KAAO,IAAO,EAAM,OAAO,OAAO,EAAQ,OAC9C,IAAI,KAAO,IAAO,EAAM,OAAO,MAAM,EAAQ,MAC7C,EAAE,UAAO,aAAU;CACzB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAI,IAAI,EAAM,MAAO,KAAK,EAAM,KAAM,EAAS,aAAa;EAE5D,IAAM,KADO,IAAI,IAAI,EAAM,UAAU,EAAM,IAAI,OAAO,EAAM,KAAK,EAAM,IAAI,KAAM,KAAA,MAC1D,EAAM,KAAM,IAAI,EAAM;EAC7C,IAAI,KAAK,EAAM,MAAO,IAAI,GAAQ,OAAO;CAC3C;CACA,OAAO;AACT;AAKA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACe;CACf,IAAI,IAAuB;CAS3B,OARA,GACE,GACA,KAAQ,EAAK,QAAQ,KAAK,IAC1B,KAAQ,EAAK,QAAQ,KAAK,KACzB,GAAG,GAAG,GAAG,MAAY;EACpB,AAAI,MAAU,QAAQ,MAAM,KAAO,KAAO,KAAK,IAAM,IAAI,MAAS,IAAQ;CAC5E,CACF,GACO;AACT;AAOA,SAAgB,GACd,GACA,GACA,GACoC;CACpC,IAAM,IAAU,EAAK;CACrB,IAAI,CAAC,KAAW,CAAC,EAAK,YAAY,OAAO,CAAC;CAG1C,IAAM,IAAS,EAAQ,KAAK,GAAO,MACjC,EAAQ,SAAS,GAAO,MAAO,MAAM,KAAK,EAAM,QAAQ,SAAS,EAAM,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,CAAE,CAC7F,GACM,IAAO,EAAQ,0BAAU,IAAI,IAAwC,CAAC;CAkB5E,OAjBA,GACE,GACA,KAAQ,EAAK,QAAQ,KAAK,IAC1B,KAAQ,EAAK,QAAQ,KAAK,KACzB,GAAG,GAAG,GAAG,MAAY;EACpB,IAAM,IAAQ,EAAK,WAAY,MAAM;EACjC,UAAQ,IACZ,KAAK,IAAM,KAAK,EAAO,IAAS;GAC9B,IAAM,IAAO,EAAK,EAAE,CAAE,IAAI,CAAC;GAC3B,AAAK,KAEH,EAAK,KAAK,KAAK,IAAI,EAAK,IAAI,CAAC,GAC7B,EAAK,KAAK,KAAK,IAAI,EAAK,IAAI,IAAI,CAAO,KAH9B,EAAK,EAAE,CAAE,IAAI,GAAG;IAAE,IAAI;IAAG,IAAI,IAAI;GAAQ,CAAC;EAKvD;CACF,CACF,GACO,EAAQ,SAAS,GAAO,MAC7B,CAAC,GAAG,EAAK,EAAG,CAAC,CACV,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CACzB,KAAK,CAAC,GAAG,QAAW;EACnB,SAAS,EAAM;EACf,MAAM;GAAE,GAAG,EAAK;GAAI;GAAG,OAAO,EAAK,KAAK,EAAK;GAAI,QAAQ;EAAE;CAC7D,EAAE,CACN;AACF;AASA,SAAgB,GACd,GACA,GACA,GACkC;CAClC,IAAM,IAAS,EAAK;CACpB,IAAI,CAAC,GAAQ,OAAO,CAAC;CACrB,IAAM,EAAE,WAAQ,eAAe,GAAM,gBAAgB,MAAU,EAAK,OAC9D,IAAW,IAAO,EAAO,KACzB,IAAY,IAAO,EAAO,MAC1B,IAAc,IAAO,EAAK,UAAU,SAAS,EAAO,QACpD,IAAa,IAAO,EAAK,UAAU,QAAQ,EAAO,OAGlD,IAAY,EAAO,SAAS,IAAI,IAAc,EAAO,SAAS,IAAc,EAAM,GAClF,IAAW,EAAO,QAAQ,IAAI,IAAa,EAAO,QAAQ,IAAa,EAAM,GAC7E,IAAyC,CAAC;CAiBhD,OAhBI,EAAO,QAAQ,MACjB,EAAK,IAAI;EACP,KAAK,IAAa,EAAO;EACzB,KAAK,IAAW,EAAM;EACtB,OAAO,KAAK,IAAI,EAAK,GAAG,EAAO,KAAK;EACpC,KAAK,KAAK,IAAI,GAAG,IAAY,IAAW,EAAM,CAAC;CACjD,IAEE,EAAO,SAAS,MAClB,EAAK,IAAI;EACP,KAAK,IAAY,EAAM;EACvB,KAAK,IAAc,EAAO;EAC1B,OAAO,KAAK,IAAI,EAAK,GAAG,EAAO,MAAM;EACrC,KAAK,KAAK,IAAI,GAAG,IAAW,IAAY,EAAM,CAAC;CACjD,IAEK;AACT;AAgBA,SAAgB,GACd,GACA,GACA,GACA,GAC6B;CAC7B,IAAM,IAAO,IAAO,IAAI,KAAK,IAAI,GAAG,IAAW,CAAI,IAAI,GACnD,IAAM,KAAK,IAAI,GAAG,KAAK,MAAM,IAAO,CAAQ,CAAC;CAGjD,OAFI,IAAM,MAAG,IAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAK,IAAW,CAAG,CAAC,IAErD;EAAE,IADE,IAAM,IAAI,KAAK,MAAO,KAAK,IAAI,GAAQ,CAAG,IAAI,KAAQ,IAAW,EAAI,IAAI;EACvE;CAAI;AACnB;AAOA,SAAS,GACP,GACA,GACA,GACA,GACA,GACoC;CACpC,IAAM,EAAE,iBAAc,gBAAa;CACnC,IAAI,EAAY,EAAK,OAAO,EAAK,KAAK,GAAU,CAAQ,KAAK,GAC3D,OAAO;EAAE,KAAK,EAAK;EAAK,UAAU;CAAM;CAE1C,IAAM,IAAQ,MAAiB,aAAa,IAAe,IAAI,GAC3D,IAAM,EAAK;CACf,OAAO,IAAM,EAAK,OAAO,EAAY,EAAK,OAAO,IAAM,GAAG,GAAU,CAAQ,KAAK,IAAO;CACxF,OAAO;EAAE;EAAK,UAAU,MAAiB,cAAc,IAAe;CAAE;AAC1E;;;ACphBA,SAAgB,GAAS,GAAkB,GAAa,GAAyB;CAC/E,IAAM,IAAoB,CAAC,GACvB,IAAO,GACP,IAAI,EAAK,UAAU,GACnB,IAAI,EAAK,UAAU;CACvB,SAAS;EACP,IAAI,IAAyB;EAC7B,KAAK,IAAM,KAAS,GAAqB,CAAI,GAAG;GAC9C,IAAI,EAAM,aAAa;GACvB,IAAM,IAAK,IAAI,EAAM,UAAU,GACzB,IAAK,IAAI,EAAM,UAAU;GAS/B,CANe,EAAM,eACjB,GAAe,GAAO,GAAI,GAAI,GAAK,CAAG,IACtC,KAAO,KACP,IAAM,IAAK,EAAM,UAAU,SAC3B,KAAO,KACP,IAAM,IAAK,EAAM,UAAU,YACnB,IAAM;EACpB;EACA,IAAI,CAAC,GAAK,OAAO;EAMjB,AALA,EAAM,KAAK;GAAE,MAAM;GAAK,GAAG,IAAI,EAAI,UAAU;GAAG,GAAG,IAAI,EAAI,UAAU;EAAE,CAAC,GAGxE,KAAK,EAAI,UAAU,KAAK,EAAI,QAAQ,KAAK,IACzC,KAAK,EAAI,UAAU,KAAK,EAAI,QAAQ,KAAK,IACzC,IAAO;CACT;AACF;AAKA,SAAgB,GAAQ,GAA2B;CAEjD,OAAO,EAAQ,UAAU,SAAS,KAAK;AACzC;AAIA,SAAgB,GAAS,GAAkB,GAAa,GAAwB;CAC9E,IAAM,IAAmB,CAAC;CAC1B,KAAK,IAAM,KAAS,GAAS,GAAM,GAAK,CAAG,GAAG;EAC5C,IAAI,GAAQ,EAAM,KAAK,MAAM,GAAG;EAChC,EAAM,KAAK,EAAM,KAAK,MAAM;CAC9B;CACA,OAAO;AACT;;;ACxDA,IAAM,KAAwC;CAC5C,SAAS;CACT,WAAW;CACX,WAAW;CACX,YAAY;AACd;AAGA,SAAgB,GAAY,GAA+B;CACzD,OAAO,GAAW,MAAQ;AAC5B;AAQA,SAAgB,GACd,GACA,GACA,GACgB;CAChB,IAAI,IAAyB,MACzB,IAAuB;CAC3B,KAAK,IAAM,KAAa,GAAY;EAClC,IAAM,IAAM,GAAK,GAAW,GAAS,EAAU,IAAI;EACnD,AAAI,MAAQ,CAAC,KAAW,GAAY,GAAK,CAAO,OAC9C,IAAO,GACP,IAAU;CAEd;CACA,OAAO,GAAM,WAAW;AAC1B;AAMA,SAAS,GAAY,GAAS,GAAkB;CAC9C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAC5B,IAAI,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,KAAM,EAAE;CAEtC,OAAO;AACT;AAGA,SAAS,GAAK,GAAsB,GAAe,GAAyB;CAC1E,IAAM,IAAW,MAAc,QAAQ,MAAc,QAC/C,CAAC,GAAO,GAAK,KAAQ,IACtB;EAAC;EAAK;EAAK;CAAQ,IACnB;EAAC;EAAK;EAAK;CAAO,GACjB,IAAa,EAAQ,KAAS,EAAQ,IACtC,IAAU,EAAK,KAAS,EAAK,IAE7B,IADU,MAAc,UAAU,MAAc,UAC3B,EAAK,KAAS,IAAa,EAAQ,KAAS;CACvE,IAAI,IAAW,GAAG,OAAO;CACzB,IAAM,IAAY,IAAW,UAAU,UACjC,IACJ,KAAK,IAAI,EAAQ,KAAO,EAAQ,IAAY,EAAK,KAAO,EAAK,EAAU,IACvE,KAAK,IAAI,EAAQ,IAAM,EAAK,EAAI;CAClC,OAAO,IAAU,IAAI;EAAC;EAAG;EAAU;CAAC,IAAI;EAAC;EAAG;EAAU,CAAC;CAAO;AAChE;AASA,SAAgB,GAAe,GAA+B;CAC5D,IAAM,IAAmB,CAAC,GACpB,KAAQ,GAAkB,GAAiB,GAAiB,MAAoB;EACpF,IAAI,EAAK,aAAa;EACtB,IAAM,IAAI,IAAU,EAAK,UAAU,GAC7B,IAAI,IAAU,EAAK,UAAU;EACnC,AAAI,CAAC,KAAU,GAAY,EAAK,MAAM,KACpC,EAAI,KAAK;GACP,SAAS,EAAK;GACd,MAAM;IAAE;IAAG;IAAG,OAAO,EAAK,UAAU;IAAO,QAAQ,EAAK,UAAU;GAAO;EAC3E,CAAC;EAEH,KAAK,IAAM,KAAU,GAAmB,GAAM,GAAG,CAAC,GAChD,AAAI,GAAY,EAAO,OAAO,KAAG,EAAI,KAAK,CAAM;EAElD,IAAM,IAAU,EAAK,QAAQ,KAAK,GAC5B,IAAU,EAAK,QAAQ,KAAK;EAClC,KAAK,IAAM,KAAS,EAAK,UAAU,EAAK,GAAO,IAAI,GAAS,IAAI,GAAS,EAAK;CAChF;CAEA,OADA,EAAK,GAAM,GAAG,GAAG,EAAI,GACd;AACT;AAIA,SAAgB,GAAS,GAAoB,GAA+B;CAC1E,IAAI,IAAsB;CAC1B,KAAK,IAAM,EAAE,SAAS,GAAW,aAAU,GACrC,UAAc,GAClB;MAAI,CAAC,GAAQ,IAAS,EAAE,GAAG,EAAK;OAC3B;GACH,IAAM,IAAK,KAAK,IAAI,EAAO,IAAI,EAAO,OAAO,EAAK,IAAI,EAAK,KAAK,GAC1D,IAAK,KAAK,IAAI,EAAO,IAAI,EAAO,QAAQ,EAAK,IAAI,EAAK,MAAM;GAIlE,AAHA,EAAO,IAAI,KAAK,IAAI,EAAO,GAAG,EAAK,CAAC,GACpC,EAAO,IAAI,KAAK,IAAI,EAAO,GAAG,EAAK,CAAC,GACpC,EAAO,QAAQ,IAAK,EAAO,GAC3B,EAAO,SAAS,IAAK,EAAO;EAC9B;;CAEF,OAAO;AACT;AAIA,SAAS,GAAY,GAA2B;CAC9C,IAAM,IAAY,EAAwB;CAE1C,OADI,OAAO,KAAa,YAAY,IAAW,IAAU,KAClD,CAAC,EAAQ,QAAQ,WAAW,KAAK,CAAC,GAAQ,CAAO;AAC1D;AAEA,IAAM,qBAAiB,IAAI,IAAI;CAAC;CAAQ;CAAU;CAAO;CAAO;CAAS;AAAU,CAAC,GAE9E,qBAAgB,IAAI,IAAI;CAAC;CAAY;CAAU;CAAU;CAAS;CAAS;AAAM,CAAC;AAOxF,SAAgB,GAAc,GAAkB,GAAa,IAAa,IAAgB;CACxF,IAAM,IAAM,EAAQ;CAEpB,IADI,MAAQ,cACR,EAAQ,QAAQ,kDAAkD,GAAG,OAAO;CAChF,IAAI,MAAQ,SAAS;EACnB,IAAM,IAAQ,EAA6B;EAG3C,OAFI,MAAS,UAAgB,KACzB,GAAe,IAAI,CAAI,IAAU,MAAQ,eAAe,MAAQ,eAC7D,CAAC,GAAc,IAAI,CAAI;CAChC;CACA,IAAI,MAAQ,UAAU;EACpB,IAAM,IAAS,GAET,IAAO,OAAO,EAAO,IAAI,KAAK,OAAO,EAAO,aAAa,MAAM,CAAC,KAAK;EAC3E,OAAO,EAAO,YAAY,IAAO,KAAK;CACxC;CACA,OAAO;AACT;;;ACzJA,SAAgB,GAAc,GAAa,GAAiB,GAAa,GAAyB;CAChG,IAAM,IAAW,EAAM,eACjB,IAAI,EAAS,YAAY;CAE/B,AADA,EAAE,SAAS,GAAO,CAAO,GACzB,EAAE,SAAS,EAAI;CACf,IAAM,IAAI,EAAS,YAAY;CAG/B,OAFA,EAAE,SAAS,GAAO,CAAO,GACzB,EAAE,SAAS,EAAI,GACR,EAAE,sBAAsB,EAAE,gBAAgB,CAAC;AACpD;AAOA,SAAgB,GAAY,GAAkB,GAAiB,GAAwB;CAErF,IAAM,IADQ,GAAc,CACX,CAAA,CAAM,WAAW,MAAQ,EAAI,OAAO,SAAS,CAAS,CAAC;CACxE,IAAI,KAAY,GAAG;EACjB,IAAI,IAAS;EACb,KAAK,IAAI,IAAI,GAAG,KAAK,GAAU,KAAK,IAAS,EAAK,KAAK,QAAA,KAA4B,IAAS,CAAC;EAC7F,IAAI,KAAU,GAAG,OAAO;CAC1B;CACA,IAAM,IAAO,EAAK,cAAc,CAAC,GAE7B,IAAM,GACN,IAAO,EAAK;CAChB,OAAO,IAAM,IAAM;EACjB,IAAM,IAAO,IAAM,KAAS,GACtB,IAAM,EAAK;EACjB,AAAI,GAAc,EAAI,MAAM,EAAI,QAAQ,GAAW,CAAM,KAAK,IAAG,IAAM,IAAM,IACxE,IAAO;CACd;CACA,IAAI,MAAQ,GAAG,OAAO;CACtB,IAAM,IAAM,EAAK,IAAM;CAIvB,OAHI,MAAc,EAAI,QAAQ,IAAS,EAAI,SAAS,EAAI,SAC/C,EAAI,SAAS,IAAS,EAAI,UAE5B,EAAI,QAAQ,EAAI;AACzB;AAIA,SAAgB,GAAW,GAAkB,GAAsD;CACjG,IAAM,IAAO,EAAK,cAAc,CAAC,GAC7B,IAAM,GACN,IAAO,EAAK;CAChB,OAAO,IAAM,IAAM;EACjB,IAAM,IAAO,IAAM,KAAS;EAC5B,AAAI,EAAK,EAAI,CAAE,SAAS,IAAO,IAAM,IAAM,IACtC,IAAO;CACd;CACA,IAAM,IAAM,EAAK,IAAM;CACvB,IAAI,CAAC,GAAK,OAAO;CACjB,IAAM,IAAQ,IAAQ,EAAI;CAC1B,OAAO,KAAS,EAAI,SAAS;EAAE,MAAM,EAAI;EAAM,QAAQ,EAAI,SAAS;CAAM,IAAI;AAChF;AAkBA,SAAgB,GAAsB,GAA+C;CACnF,IAAI;EACF,IAAM,IAAY,EAAW,cAAc,aAAa;EACxD,IAAI,CAAC,GAAW,OAAO;EACvB,IAAI,EAAU,mBAEZ,OADe,EAAU,kBAAkB,EAAE,aAAa,CAAC,CAAU,EAAE,CAChE,CAAA,CAAO,MAAM;EAEtB,IAAM,IACJ,EACA,eAAe;EAEjB,OADI,CAAC,KAAmB,EAAgB,eAAe,IAAU,OAC1D,EAAgB,WAAW,CAAC;CACrC,QAAQ;EACN,OAAO;CACT;AACF;AAOA,SAAgB,GACd,GACA,GACA,GACe;CACf,IAAM,EAAE,gBAAgB,GAAO,cAAc,MAAQ;CAGrD,OAFI,EAAK,SAAS,CAAK,KAAK,EAAK,SAAS,CAAG,IAAU,SACnD,EAAK,SAAS,CAAK,KAAK,EAAK,SAAS,CAAG,IAAU,UAChD;AACT;AAiBA,SAAgB,GAAmB,GAAkB,GAAgC;CACnF,IAAM,IAAQ,EAAK,OAAO,cAAe,YAAY;CAErD,AADA,EAAM,SAAS,EAAO,gBAAgB,EAAO,WAAW,GACxD,EAAM,OAAO,EAAO,cAAc,EAAO,SAAS;CAClD,IAAM,IAAoB,CAAC;CAE3B,OADA,GAAa,GAAM,GAAO,CAAK,GACxB,GAAS,CAAK;AACvB;AAEA,SAAS,GAAa,GAAkB,GAAc,GAAyB;CAC7E,IAAI,EAAK,eAAe,CAAC,EAAM,eAAe,EAAK,MAAM,GAAG;CAC5D,IAAM,IAAS,GAAe,CAAI;CAElC,IADI,KAAQ,EAAM,KAAK,EAAE,UAAO,CAAC,GAC7B,EAAK,MAAM,cAAc,OAC3B,GAAW,GAAM,GAAO,CAAK;MACxB,IAAI,EAAK,MAAM,YAAY,SAAS;EACzC,IAAM,IAAO,GAAU,CAAI;EAC3B,KAAK,IAAM,KAAS,EAAK,UACnB,EAAM,MAAM,cAAc,SAAS,GAAW,CAAK,KACvD,GAAa,GAAO,GAAO,CAAK;EAIlC,IAAI,IAAU;EACd,KAAK,IAAM,KAAO,GACX,EAAM,eAAe,EAAI,MAAM,MAChC,KAAS,EAAM,KAAK,EAAE,MAAM,KAAK,CAAC,GACtC,GAAa,GAAK,GAAO,CAAK,GAC9B,IAAU;CAEd,OAAO;EACL,AAAI,GAAW,CAAI,KAAG,EAAM,KAAK,EAAE,MAAM,GAAU,GAAM,CAAK,EAAE,CAAC;EACjE,KAAK,IAAM,KAAS,EAAK,UACvB,AAAK,EAAM,aAAW,GAAa,GAAO,GAAO,CAAK;CAE1D;CACA,AAAI,KAAQ,EAAM,KAAK,EAAE,UAAO,CAAC;AACnC;AAEA,SAAS,GAAW,GAAiB,GAAc,GAAyB;CAC1E,IAAI,IAAU;CACd,KAAK,IAAM,KAAQ,EAAI,UACjB,EAAK,MAAM,cAAc,UAAU,EAAK,eACvC,EAAM,eAAe,EAAK,MAAM,MACjC,KAAS,EAAM,KAAK,EAAE,MAAM,IAAK,CAAC,GACtC,GAAa,GAAM,GAAO,CAAK,GAC/B,IAAU;AAEd;AAEA,SAAS,GAAW,GAA2B;CAC7C,IAAM,IAAO,EAAK,MAAM;CACxB,OAAO,MAAS,kBAAkB,MAAS,eAAe,MAAS;AACrE;AAEA,SAAS,GAAU,GAAiC;CAClD,IAAM,IAAqB,CAAC;CAC5B,KAAK,IAAM,KAAS,EAAM,UACxB,IAAI,EAAM,MAAM,cAAc,OAAO,EAAK,KAAK,CAAK;MAC/C,IAAI,GAAW,CAAK,GAClB,KAAA,IAAM,KAAO,EAAM,UAAU,AAAI,EAAI,MAAM,cAAc,SAAO,EAAK,KAAK,CAAG;CAGtF,OAAO;AACT;AAIA,SAAS,GAAe,GAA0B;CAChD,IAAI,EAAK,WAAW,OAAO;CAC3B,IAAM,IAAO,EAAK,MAAM;CAGxB,OAFI,MAAS,SAAS,MAAS,UAAU,GAAW,CAAI,KACpD,MAAS,YAAY,MAAS,iBAAuB,IAClD,EAAK,OAAO,YAAY,MAAM,IAAI;AAC3C;AASA,SAAgB,GAAW,GAAuD;CAChF,IAAM,IAAyC,CAAC,GAC1C,IAAO,EAAK,cAAc,CAAC;CACjC,IAAI,EAAK,SAAS,GAAG;EACnB,IAAM,IAAQ,EAAK,IACb,IAAO,EAAK,EAAK,SAAS;EAChC,EAAO,KAAK;GACV,OAAO;IAAE,MAAM,EAAM;IAAM,QAAQ,EAAM;GAAO;GAChD,KAAK;IAAE,MAAM,EAAK;IAAM,QAAQ,EAAK,SAAS,EAAK;GAAO;EAC5D,CAAC;CACH;CACA,KAAK,IAAM,KAAO,GAAc,CAAI,GAAG;EACrC,IAAM,IAAS,EAAI,OAAO;EAC1B,IAAI,CAAC,GAAQ;EACb,IAAM,IAAQ,MAAM,UAAU,QAAQ,KAAK,EAAO,YAAY,EAAI,MAAM;EACxE,EAAO,KAAK;GACV,OAAO;IAAE,MAAM;IAAQ,QAAQ;GAAM;GACrC,KAAK;IAAE,MAAM;IAAQ,QAAQ,IAAQ;GAAE;EACzC,CAAC;CACH;CACA,IAAI,EAAO,WAAW,GAAG,OAAO;CAChC,IAAM,KAAU,GAAU,MAAa,GAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,GACvF,EAAE,UAAO,WAAQ,EAAO;CAC5B,KAAK,IAAM,KAAS,EAAO,MAAM,CAAC,GAEhC,AADI,EAAO,EAAM,OAAO,CAAK,MAAG,IAAQ,EAAM,QAC1C,EAAO,GAAK,EAAM,GAAG,MAAG,IAAM,EAAM;CAE1C,OAAO;EAAE;EAAO;CAAI;AACtB;AAIA,SAAgB,GAAW,GAA2B;CAEpD,OADI,EAAK,KAAK,WAAW,KAClB,CAAC,EAAK,SAAS,MACnB,MACC,CAAC,EAAM,aAAa,EAAM,MAAM,aAAa,cAAc,EAAM,MAAM,aAAa,OACxF;AACF;AAOA,SAAS,GAAU,GAAkB,GAAsB;CACzD,IAAM,EAAE,YAAS,GACb,IAAQ,GACR,IAAM,EAAK;CACf,AAAI,EAAK,eACH,EAAK,OAAO,SAAS,EAAM,cAAc,MAC3C,IAAQ,GAAY,GAAM,EAAM,gBAAgB,EAAM,WAAW,IAE/D,EAAK,OAAO,SAAS,EAAM,YAAY,MACzC,IAAM,GAAY,GAAM,EAAM,cAAc,EAAM,SAAS;CAG/D,IAAI,IAAQ,EAAK,MAAM,GAAO,CAAG;CACjC,AAAI,MAAQ,EAAK,UAAU,EAAM,SAAS,IAAI,MAAG,IAAQ,EAAM,MAAM,GAAG,EAAE;CAC1E,IAAM,IAAQ,GAAc,CAAI,GAC5B,IAAW,EAAK,MAAM,GAAG,CAAK,CAAC,CAAC,MAAA,GAAwB,CAAC,CAAC,SAAS;CAQvE,OAPA,IAAQ,EAAM,WAAA,WAAqC;EACjD,IAAM,IAAM,EAAM;EAClB,IAAI,CAAC,KAAO,CAAC,EAAM,eAAe,EAAI,MAAM,GAAG,OAAO;EACtD,IAAM,IAAoB,CAAC;EAE3B,OADA,GAAa,GAAK,GAAO,CAAK,GACvB,GAAS,CAAK;CACvB,CAAC,GACM,EAAM,WAAA,KAAuB,EAAE;AACxC;AAIA,SAAS,GAAS,GAA2B;CAC3C,IAAI,IAAM,IACN,IAAU;CACd,KAAK,IAAM,KAAQ,GAAO;EACxB,IAAI,YAAY,GAAM;GACpB,IAAU,KAAK,IAAI,GAAS,EAAK,MAAM;GACvC;EACF;EACI,EAAK,KAAK,WAAW,MACrB,EAAI,SAAS,KAAK,IAAU,MAAG,KAAO,KAAK,OAAO,CAAO,IAC7D,IAAU,GACV,KAAO,EAAK;CACd;CACA,OAAO;AACT;AAIA,IAAM,qBAAa,IAAI,IAAmC;AAM1D,SAAgB,GAAO,GAAkB,GAAsD;CAC7F,IAAM,EAAE,YAAS;CACjB,IAAI,IAAQ,KAAK,KAAS,EAAK,UAAU,GAAe,EAAK,EAAO,GAAG,OAAO;CAC9E,IAAI,IAAQ;CACZ,OAAO,IAAQ,KAAK,CAAC,GAAe,EAAK,IAAQ,EAAG,IAAG;CACvD,IAAI,IAAM;CACV,OAAO,IAAM,EAAK,UAAU,CAAC,GAAe,EAAK,EAAK,IAAG;CACzD,IAAM,IAAY,GAAa,EAAK,OAAO,UAAU,QAAQ,CAAC,EAAE,aAAa,MAAM,KAAK,EAAE;CAC1F,IAAI,CAAC,GAAW,OAAO;CACvB,KAAK,IAAM,KAAW,EAAU,QAAQ,EAAK,MAAM,GAAO,CAAG,CAAC,GAAG;EAC/D,IAAM,IAAO,IAAQ,EAAQ,OACvB,IAAK,IAAO,EAAQ,QAAQ;EAClC,IAAI,KAAS,KAAQ,IAAQ,GAAI,OAAO;GAAE,OAAO;GAAM,KAAK;EAAG;CACjE;CACA,OAAO;AACT;AAEA,SAAS,GAAe,GAAqB;CAC3C,OAAO,MAAO,QAAQ,MAAA,OAA6B,MAAA;AACrD;AAKA,SAAS,GAAa,GAAqC;CACzD,IAAI,IAAY,GAAW,IAAI,CAAI;CAKnC,OAJI,MAAc,KAAA,MAChB,IAAY,GAAgB,CAAI,KAAK,GAAgB,EAAE,GACvD,GAAW,IAAI,GAAM,CAAS,IAEzB;AACT;AAEA,SAAS,GAAgB,GAAqC;CAC5D,IAAI,OAAO,KAAK,aAAc,YAAY,OAAO;CACjD,IAAI;EACF,OAAO,IAAI,KAAK,UAAU,KAAQ,KAAA,GAAW,EAAE,aAAa,OAAO,CAAC;CACtE,QAAQ;EACN,OAAO;CACT;AACF;;;AC/UA,IAAM,qBAAqB,IAAI,QAA6B,GAKtD,qBAAY,IAAI,QAAkC;AAIxD,SAAS,GAAmB,GAA8B;CACxD,OAAO,GAAiB,GAAQ,EAAI,MAAM;AAC5C;AAKA,SAAgB,GAAU,GAAkB,GAAqB,IAAiB,IAAgB;CAChG,IAAM,IAAO,GAAmB,CAAI,GAC9B,IAAY,GAAY,CAAI;CAClC,IAAI,GAAmB,IAAI,CAAM,MAAM,GAAW,OAAO;CAKzD,IAAM,IAAW,GAAU,IAAI,CAAM;CACrC,IAAI,KAAY,GAAiB,GAAQ,EAAS,OAAO,CAAI,GAAG;EAC9D,GAAmB,IAAI,GAAQ,CAAS;EACxC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAC/B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,EAAE,CAAE,QAAQ,KAAK;GACxC,IAAM,IAAU,EAAK,EAAE,CAAE;GACzB,IAAI,GAAY,CAAO,KAAK,GAAU,GAAS,EAAS,SAAS,EAAE,CAAE,EAAE,GAAG;GAC1E,IAAM,IAAO,EAAS,MAAM,EAAE,CAAE;GAEhC,AADA,EAAK,MAAM,UAAU,IACrB,GAAe,GAAS,EAAK,KAAK;EACpC;EAGF,OADA,EAAS,WAAW,GACb;CACT;CAEA,IAAI,KAAkB,GAAmB,CAAM,GAAG,OAAO;CACzD,GAAmB,IAAI,GAAQ,CAAS;CACxC,IAAM,IAAW,SAAS,uBAAuB,GAC3C,IAAkC,CAAC;CACzC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK;EACpC,AAAI,IAAI,KAAG,EAAS,YAAY,SAAS,eAAe,IAAI,CAAC;EAC7D,IAAM,IAAmC,CAAC;EAC1C,KAAK,IAAM,KAAW,EAAK,IAAK;GAC9B,IAAI,GAAY,CAAO,GAAG;IACxB,IAAM,IAAO,SAAS,eAAe,EAAQ,IAAI;IAEjD,AADA,EAAS,KAAK,CAAI,GAClB,EAAS,YAAY,CAAI;IACzB;GACF;GACA,IAAM,IAAO,SAAS,cAAc,MAAM;GAI1C,AAHA,GAAe,GAAS,EAAK,KAAK,GAClC,EAAK,cAAc,EAAQ,MAC3B,EAAS,KAAK,CAAI,GAClB,EAAS,YAAY,CAAI;EAC3B;EACA,EAAM,KAAK,CAAQ;CACrB;CACA,GAAU,IAAI,GAAQ;EAAE;EAAO,UAAU;CAAK,CAAC;CAC/C,IAAM,IAAQ,GAAiB,GAAQ,EAAK;CAG5C,OAFA,EAAO,gBAAgB,CAAQ,GAC3B,KAAO,GAAiB,GAAQ,CAAK,GAClC;AACT;AAEA,SAAS,GACP,GACA,GACA,GACS;CACT,IAAI,EAAS,WAAW,EAAK,QAAQ,OAAO;CAC5C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK;EACpC,IAAM,IAAU,EAAS,IACnB,IAAM,EAAK;EACjB,IAAI,EAAQ,WAAW,EAAI,QAAQ,OAAO;EAC1C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,QAAQ,KAAK;GACnC,IAAM,IAAO,EAAQ;GAKrB,IAJa,GAAY,EAAI,EACzB,OAAU,EAAK,aAAa,KAAK,cACjC,EAAK,gBAAgB,EAAI,EAAE,CAAE,QAE7B,EAAK,eAAe,GAAQ,OAAO;EACzC;CACF;CACA,OAAO;AACT;AAYA,SAAS,GAAiB,GAAqB,GAAgD;CAC7F,IAAI;EACF,IAAM,IAAY,EAAO,cAAc,aAAa;EACpD,IAAI,CAAC,GAAW,OAAO;EACvB,IAAM,IAAa,EAAO,YAAY;EACtC,IAAI,EAAE,aAAsB,aAAa,OAAO;EAChD,IAAM,IAAQ,GAAsB,CAAU;EAC9C,IAAI,CAAC,GAAO,OAAO;EACnB,IAAM,IAAQ,GAAW,GAAQ,EAAM,gBAAgB,EAAM,WAAW,GAClE,IAAM,GAAW,GAAQ,EAAM,cAAc,EAAM,SAAS;EAOlE,OANI,MAAU,QAAQ,MAAQ,QAC1B,MAAU,KAAO,CAAC,IAAuB,OAKtC;GAAE;GAAO;GAAK,UADF,EAAqC,cACX;EAAW;CAC1D,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,GAAiB,GAAqB,GAA6B;CAC1E,IAAI;EACF,IAAM,IAAQ,GAAa,GAAQ,EAAM,KAAK,GACxC,IAAM,GAAa,GAAQ,EAAM,GAAG;EAC1C,IAAI,CAAC,KAAS,CAAC,GAAK;EAKpB,IAAM,IADa,EAAO,YACR,CAAA,CAAW,eAAe,KAAK,EAAO,cAAc,aAAa;EACnF,AAAI,EAAM,WACR,GAAW,iBAAiB,EAAI,IAAI,EAAI,IAAI,EAAM,IAAI,EAAM,EAAE,IAE9D,GAAW,iBAAiB,EAAM,IAAI,EAAM,IAAI,EAAI,IAAI,EAAI,EAAE;CAElE,QAAQ,CAER;AACF;AAMA,SAAS,GAAW,GAAqB,GAAiB,GAA+B;CACvF,IAAI,CAAC,EAAO,SAAS,CAAS,GAAG,OAAO;CACxC,IAAM,IAAQ,EAAO,cAAc,YAAY;CAG/C,OAFA,EAAM,mBAAmB,CAAM,GAC/B,EAAM,OAAO,GAAW,CAAM,GACvB,EAAM,SAAS,CAAC,CAAC;AAC1B;AAEA,SAAgB,GAAa,GAAqB,GAAuC;CACvF,IAAI,IAAY,GACZ,IAA8B;CAClC,KAAK,IAAM,KAAQ,GAAY,CAAM,GAAG;EACtC,IAAI,KAAa,EAAK,KAAK,QAAQ,OAAO,CAAC,GAAM,CAAS;EAE1D,AADA,KAAa,EAAK,KAAK,QACvB,IAAO,CAAC,GAAM,EAAK,KAAK,MAAM;CAChC;CAEA,OAAO;AACT;AAEA,UAAU,GAAY,GAAsC;CAC1D,IAAM,IAAS,EAAO,cAAc,iBAAiB,GAAQ,WAAW,SAAS,GAC7E,IAAO,EAAO,SAAS;CAC3B,OAAO,IAEL,AADA,MAAM,GACN,IAAO,EAAO,SAAS;AAE3B;AAEA,SAAS,GAAY,GAA+B;CAClD,IAAM,IAAkB,CAAC;CACzB,KAAK,IAAM,KAAO,GAAM;EACtB,KAAK,IAAM,KAAK,GACd,EAAM,KACJ,EAAE,MACF,EAAE,SAAS,IACX,EAAE,mBAAmB,IACrB,EAAE,cAAc,IAChB,EAAE,aAAa,IACf,EAAE,sBAAsB,IACxB,EAAE,WAAW,EACf;EAEF,EAAM,KAAK,IAAI;CACjB;CACA,OAAO,EAAM,KAAK,GAAM;AAC1B;;;ACpMA,SAAgB,GAAO,GAAwB;CAC7C,IAAM,oBAAsB,IAAI,IAAa;CAC7C,GAAK,GAAM,IAAM,CAAmB;CAGpC,KAAK,IAAM,KAAM,MAAM,KAAK,EAAK,OAAO,iBAAiB,wBAAwB,CAAC,GAChF,IAAI,CAAC,EAAoB,IAAI,CAAE,GAAG;EAChC,EAAG,gBAAgB,sBAAsB;EACzC,IAAM,IAAS,EAAmB;EAClC,KAAK,IAAM,KAAQ;GAAC;GAAW;GAAW;GAAW;EAAS,GAAG,EAAM,eAAe,CAAI;CAC5F;AAEJ;AAGA,SAAS,EAAO,GAAiB,GAAc,GAAqB;CAClE,AAAI,EAAG,MAAM,iBAAiB,CAAI,MAAM,KAAO,EAAG,MAAM,YAAY,GAAM,CAAK;AACjF;AAGA,SAAS,EAAS,GAAiB,GAAoB;CACrD,AAAI,EAAG,MAAM,iBAAiB,CAAI,MAAM,MAAI,EAAG,MAAM,eAAe,CAAI;AAC1E;AAGA,SAAS,EAAQ,GAAa,GAAc,GAAmB;CACzD,EAAG,aAAa,CAAI,MAAM,MAC1B,IAAI,EAAG,aAAa,GAAM,EAAE,IAC3B,EAAG,gBAAgB,CAAI;AAC9B;AAEA,SAAS,GAAK,GAAkB,GAAiB,GAAyC;CACxF,IAAI,EAAK,gBACP,KAAK,IAAM,EAAE,YAAS,aAAU,YAAS,aAAU,eAAY,EAAK,gBAAgB;EAClF,IAAM,IAAK;EAUX,AATA,EAAO,GAAI,WAAW,OAAO,CAAQ,CAAC,GAKlC,IAAU,IAAG,EAAO,GAAI,YAAY,OAAO,CAAO,CAAC,IAClD,EAAS,GAAI,UAAU,GACxB,IAAW,IAAG,EAAO,GAAI,YAAY,OAAO,CAAQ,CAAC,IACpD,EAAS,GAAI,UAAU,GACxB,MACF,EAAoB,IAAI,CAAO,GAC/B,GAAkB,GAAI,CAAM;CAEhC;CAGF,IAAI,IAAQ,GAAS,CAAI,IACpB,GAAgB,CAAI,GAGrB,GAAK,aAET,KAAK,IAAM,KAAS,GAAqB,CAAI,GAAG;EAI9C,IAAM,IAAK,EAAM;EAIjB,AAHI,EAAM,MAAM,WAAW,QAAQ,GAAuB,GAAO,CAAI,KAAK,CAAC,EAAM,YAC/E,EAAO,GAAI,UAAU,OAAO,EAAM,MAAM,MAAM,CAAC,IAC5C,EAAS,GAAI,QAAQ,GAC1B,GAAK,GAAO,IAAO,CAAmB;CACxC;AACF;AAOA,SAAS,GAAS,GAAwB;CACxC,IAAM,IAAK,EAAK,QACV,IAAO,EAAK,KAAK,SAAS,GAC1B,EAAE,eAAY,qBAAkB,kBAAe,EAAK;CAK1D,AAJA,EAAQ,GAAI,gBAAgB,CAAI,GAChC,EAAQ,GAAI,kBAAkB,KAAQ,MAAe,QAAQ,GAC7D,EAAQ,GAAI,eAAe,KAAQ,MAAe,KAAK,GACvD,EAAQ,GAAI,8BAA8B,KAAQ,CAAgB,GAC9D,IAAM,EAAO,GAAI,WAAW,OAAO,CAAU,CAAC,IAC7C,EAAS,GAAI,SAAS;AAC7B;AAWA,SAAS,GAAkB,GAAiB,GAAsC;CAChF,EAAQ,GAAI,wBAAwB,EAAI;CACxC,IAAM,KAAS,GAAc,MAAyB;EACpD,AAAI,MAAU,OAAM,EAAS,GAAI,CAAI,IAChC,EAAO,GAAI,GAAM,OAAO,CAAK,CAAC;CACrC;CAIA,AAHA,EAAM,WAAW,EAAO,GAAG,GAC3B,EAAM,WAAW,EAAO,KAAK,GAC7B,EAAM,WAAW,EAAO,MAAM,GAC9B,EAAM,WAAW,EAAO,IAAI;AAC9B;AAYA,SAAS,GAAiB,GAA2B;CACnD,IAAM,IAAQ,EAAK;CAEnB,IADI,EAAM,cAAc,YAAY,CAAC,EAAK,QACtC,EAAK,aAAa,EAAK,SAAS,SAAS,GAAG,OAAO;CACvD,IAAM,IAAW,EAAK,kBAChB,IAAU,EAAK,iBACf,IACJ,EAAK,UAAU,QAAQ,EAAM,OAAO,OAAO,EAAM,OAAO,QAAQ,EAAQ,OAAO,EAAQ,OACnF,IAAa,IAAW,KAAK,IAAI,GAAG,EAAS,cAAc,EAAM,QAAQ,IAAI,GAC7E,IAAQ,GAAU,SAAS,GAAc,GAAM,CAAY;CAEjE,OADI,EAAM,WAAW,KACd,EAAM,OAAO,GAAM,MAAM;EAC9B,IAAM,IAAS,MAAM,IAAI,EAAM,aAAa,GACtC,IACJ,IAAa,IAAS,EAAY,EAAK,OAAO,EAAK,KAAK,EAAK,UAAU,EAAM,QAAQ;EACvF,OAAO,IAAW,KAAK,IAAW,KAAM;CAC1C,CAAC;AACH;AAEA,SAAS,GAAgB,GAAwB;CAC/C,IAAM,IAAK,EAAK,QACV,IAAO,EAAK,WACZ,IAAU,EAAK,iBACf,EAAE,WAAQ,qBAAkB,aAAU,eAAY,aAAU,eAAY,EAAK,OAK7E,IAAO,EAAK,cACZ,IAAW,EAAK;CAItB,AAHA,EAAQ,GAAI,oBAAoB,CAAC,EAAK,aAAa,CAAC,KAAQ,CAAC,CAAQ,GACrE,EAAQ,GAAI,sBAAsB,EAAQ,EAAK,SAAU,GACzD,EAAQ,GAAI,yBAAyB,EAAQ,CAAK,GAClD,EAAQ,GAAI,8BAA8B,EAAQ,CAAS;CAC3D,IAAM,IAAc,KAAQ;CAoB5B,AAnBI,KACF,EAAO,GAAI,WAAW,OAAO,EAAY,OAAO,CAAC,CAAC,GAClD,EAAO,GAAI,WAAW,OAAO,EAAY,SAAS,CAAC,CAAC,GACpD,EAAO,GAAI,WAAW,OAAO,EAAY,UAAU,CAAC,CAAC,GACrD,EAAO,GAAI,WAAW,OAAO,EAAY,QAAQ,CAAC,CAAC,MAEnD,EAAS,GAAI,SAAS,GACtB,EAAS,GAAI,SAAS,GACtB,EAAS,GAAI,SAAS,GACtB,EAAS,GAAI,SAAS,IAIxB,EAAQ,GAAI,mBAAmB,EAAQ,EAAK,aAAc,EAAK,MAAM,kBAAkB,KAAK,GAG5F,EAAO,GAAI,WAAW,OAAO,CAAQ,CAAC,GACtC,EAAO,GAAI,WAAW,OAAO,IAAU,CAAC,CAAC,GACzC,EAAO,GAAI,YAAY,OAAO,CAAC,IAAU,CAAC,CAAC,GAC3C,EAAQ,GAAI,kBAAkB,MAAe,QAAQ;CASrD,IAAM,IAAW,KAAQ,IAAW,KAAA,IAAY,EAAK;CAmBrD,IAlBA,EAAQ,GAAI,oBAAoB,EAAQ,CAAS,GACjD,EAAQ,GAAI,4BAA4B,EAAQ,GAAU,aAAc,GACpE,KACF,EAAO,GAAI,aAAa,OAAO,EAAS,WAAW,CAAC,GACpD,EAAO,GAAI,aAAa,OAAO,EAAS,GAAG,CAAC,MAE5C,EAAS,GAAI,WAAW,GACxB,EAAS,GAAI,WAAW,IAI1B,EAAQ,GAAI,eAAe,MAAe,KAAK,GAC/C,EAAO,GAAI,UAAU,OAAO,EAAK,CAAC,CAAC,GACnC,EAAO,GAAI,UAAU,OAAO,EAAK,CAAC,CAAC,GACnC,EAAO,GAAI,UAAU,OAAO,EAAK,KAAK,CAAC,GACvC,EAAO,GAAI,UAAU,OAAO,EAAK,MAAM,CAAC,GACxC,EAAQ,GAAI,gBAAgB,EAAS,MAAM,UAAU,EAAS,MAAM,MAAM,GAC1E,EAAQ,GAAI,kBAAkB,EAAK,gBAAgB,KAAA,CAAS,GACxD,EAAK,aAAa;EAQpB,IAAM,EAAE,SAAM,YAAS,EAAK;EAE5B,AADA,EAAO,GAAI,aAAa,OAAO,IAAO,IAAI,IAAO,EAAK,UAAU,QAAQ,CAAC,CAAC,GAC1E,EAAO,GAAI,aAAa,OAAO,IAAO,IAAI,IAAO,EAAK,UAAU,SAAS,CAAC,CAAC;CAC7E,OAEE,AADA,EAAS,GAAI,WAAW,GACxB,EAAS,GAAI,WAAW;CAyB1B,AAnBA,EAAO,GAAI,WAAW,OAAO,EAAQ,GAAG,CAAC,GACzC,EAAO,GAAI,WAAW,OAAO,EAAQ,KAAK,CAAC,GAC3C,EAAO,GAAI,WAAW,OAAO,EAAQ,MAAM,CAAC,GAC5C,EAAO,GAAI,WAAW,OAAO,EAAQ,IAAI,CAAC,GAC1C,EAAO,GAAI,WAAW,OAAO,EAAO,GAAG,CAAC,GACxC,EAAO,GAAI,WAAW,OAAO,EAAO,KAAK,CAAC,GAC1C,EAAO,GAAI,WAAW,OAAO,EAAO,MAAM,CAAC,GAC3C,EAAO,GAAI,WAAW,OAAO,EAAO,IAAI,CAAC,GAMzC,EAAO,GAAI,WAAW,OAAO,EAAK,MAAM,UAAU,CAAC,GACnD,EAAQ,GAAI,8BAA8B,CAAgB,GAC1D,EAAQ,GAAI,wBAAwB,GAAiB,CAAI,CAAC,GAG1D,EAAQ,GAAI,wBAAwB,EAAQ,EAAK,WAAY,GAC7D,EAAQ,GAAI,wBAAwB,EAAQ,EAAK,WAAY;AAC/D;;;ACtNA,SAAgB,GACd,GACA,GACA,GACW;CACX,IAAM,IAAK,iBAAiB,CAAE,GACxB,IAAa,WAAW,EAAG,QAAQ,KAAK,GACxC,IAAM,GAAgB,CAAE,IAAI,EAAG,iBAAiB,IAAI,MACpD,IAAY,EAAG,aAAa,OAAO,KAAK,IACxC,IAAe,EAAmB;CACxC,GAAqB,GAAI,GAAW,CAAW;CAG/C,IAAM,KAAS,GAAkB,GAAkB,MACjD,GACE,GACA,GACA,GACA,GACA,GACA,GACA,GACA,CACF,KACA,GACE,GACA,GACA,GACA,GACA,GACA,GACA,GACA,CACF,KACA,GAAU,GAAU,CAAc,GAK9B,IAAa,EAAG,WAAW,GAAuB,EAAG,YAAY,IACjE,IAAuB,GAAY,MAAe,QAIlD,IACJ,EAAG,eAAe,EAAG,gBAAgB,SACjC,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,EAAG,WAAW,KAAK,CAAC,CAAC,IACnD,MACA,IACJ,EAAG,eAAe,EAAG,gBAAgB,SAAS,WAAW,EAAG,WAAW,IAAI,KACvE,IAAc,OAAO,SAAS,CAAa,IAC7C,KAAK,IAAI,GAAG,EAAU,GAAe,CAAc,CAAC,IACpD,MACE,IACJ,MAAe,UAAU,MAAe,gBACpC,SACA,MAAe,UAAU,MAAe,gBACtC,SACA,MAAe,WAAW,MAAe,iBACvC,UACA,MAAe,UAAU,GAAc,GAAI,CAAE,IAC3C,SACA,MAAgB,QAAQ,MAAgB,OACtC,aACA,SAYV,IAAoC,EAAE,MAAM,OAAO,GACnD,IAAiC,EAAE,MAAM,OAAO,GAChD,IAA+B,CAAC,GAAU,CAAC,GAC3C,IAA4B,CAAC,GAAU,CAAC,GACxC,IAA6B;EAAE,WAAW;EAAO,OAAO;CAAM,GAC9D,IAAsC;CAC1C,IAAI,MAAY,QAAQ;EACtB,IAAI,GAKF,AAJA,IAAsB,GACpB,EAAI,IAAI,uBAAuB,CAAC,EAAE,SAAS,KAAK,IAChD,CACF,GACA,IAAmB,GACjB,EAAI,IAAI,oBAAoB,CAAC,EAAE,SAAS,KAAK,IAC7C,CACF;OACK;GACL,EAAG,aAAa,kBAAkB,EAAE;GACpC,IAAI;IAKF,AAJA,IAAsB,GACpB,EAAG,iBAAiB,uBAAuB,GAC3C,CACF,GACA,IAAmB,GACjB,EAAG,iBAAiB,oBAAoB,GACxC,CACF;GACF,UAAU;IACR,EAAG,gBAAgB,gBAAgB;GACrC;EACF;EAMA,AAHA,IAAkB,GAAgB,EAAG,iBAAiB,mBAAmB,GAAG,CAAc,GAC1F,IAAe,GAAgB,EAAG,iBAAiB,gBAAgB,GAAG,CAAc,GACpF,IAAe,GAAkB,EAAG,iBAAiB,gBAAgB,CAAC,GACtE,IAAoB,GAAuB,EAAG,iBAAiB,qBAAqB,CAAC;CACvF;CAEA,IAAI,IAAgC,QAChC,IAAiB,IACjB,IAAiB,GACjB,IAAiB;CACrB,IAAI,MAAY,YACd,IAAc,EAAG,gBAAgB,UAAU,UAAU,QACrD,IAAiB,EAAG,mBAAmB,YACnC,CAAC,IAAgB;EAEnB,IAAM,IAAQ,EAAG,cAAc,MAAM,GAAG;EAExC,AADA,IAAiB,EAAU,WAAW,EAAM,MAAM,EAAE,KAAK,GAAG,CAAc,GAC1E,IAAiB,EAAU,WAAW,EAAM,MAAM,EAAM,MAAM,EAAE,KAAK,GAAG,CAAc;CACxF;CAGF,IAAM,IAAmB;EACvB;EACA;EACA;EACA;EACA;EACA;EACA,aAAa,EAAG,gBAAgB,WAAW,WAAW;EAEtD,eACE,MAAc,UAAU,EAAW,WAAW,SAAS,IACnD,GAAkB,GAAI,CAAE,IACxB;EACN,eAAe,EAAG,cAAc,WAAW,QAAQ,IAAI,WAAW;EAClE,aAAa,EAAG,cAAc,SAAS,UAAU;EACjD,UAAU,EAAG,SAAS,WAAW,MAAM,IAAI,SAAS;EACpD,aAAa,EAAG,aAAa;EAC7B,UAAU,OAAO,EAAG,QAAQ,KAAK;EACjC,YAAY,EAAG,eAAe,KAAK,IAAI,OAAO,EAAG,UAAU,KAAK;EAGhE,WAAW,GAAc,EAAG,WAAW,CAAc;EACrD,OAAO,OAAO,EAAG,KAAK,KAAK;EAC3B,gBAAgB,GAAW,EAAG,cAAc;EAC5C,cAAc,GAAW,EAAG,YAAY;EACxC,YAAY,GAAS,EAAG,UAAU;EAClC,WAAW,GAAa,EAAG,SAAS;EACpC,cAAc,GAAS,EAAG,YAAY;EACtC,aAAa,GAAa,EAAG,WAAW;EACxC;EACA;EACA;EACA;EACA;EACA;EAIA,iBAAiB,GAAc,EAAG,iBAAiB,mBAAmB,CAAC;EACvE,eAAe,GAAc,EAAG,iBAAiB,iBAAiB,CAAC;EACnE,cAAc,GAAc,EAAG,iBAAiB,gBAAgB,CAAC;EACjE,YAAY,GAAc,EAAG,iBAAiB,cAAc,CAAC;EAC7D,OAAO,GAAS,GAAK,EAAG,OAAO,SAAS,GAAgB,GAAW,GAAa,CAAO;EACvF,QAAQ,GAAS,GAAK,EAAG,QAAQ,UAAU,GAAgB,GAAW,GAAa,CAAO;EAC1F,UAAU,EAAM,aAAa,EAAG,UAAU,OAAO,KAAK;EACtD,WAAW,EAAM,cAAc,EAAG,WAAW,OAAO,KAAK;EACzD,UAAU,EAAM,aAAa,EAAG,UAAU,OAAO;EACjD,WAAW,EAAM,cAAc,EAAG,WAAW,OAAO;EACpD,SAAS,GAAY,GAAI,CAAc;EACvC,QAAQ,GAAW,GAAI,GAAK,GAAW,GAAa,CAAc;EAClE,UAAU,GAAa,EAAG,QAAQ;EAClC,QAAQ,GAAW,GAAI,GAAK,GAAW,GAAa,CAAc;EAIlE,MAAM,EACJ,EAAG,cAAc,YAAY,EAAG,cAAc,KAC1C,MAAY,aACV,GAAG,EAAW,MACd,QACF,EAAG,WACP,CACF;EACA,MAAM,EAAY,EAAG,WAAW,WAAW,QAAQ,EAAG,QAAQ,CAAc;EAC5E,QAAQ,GAAiB,CAAE;EAC3B,aAAa;GACX,KAAK,GAAe,EAAG,cAAc;GACrC,OAAO,GAAe,EAAG,gBAAgB;GACzC,QAAQ,GAAe,EAAG,iBAAiB;GAC3C,MAAM,GAAe,EAAG,eAAe;EACzC;EACA,UAAU,GAAa,CAAE;EACzB,gBAAgB,GAAmB,GAAI,CAAE;EACzC,gBAAgB,GAAmB,EAAG,cAAc;EACpD,YAAY;GACV,IAAI,EAAG,uBAAuB,YAAY;GAC1C,IAAI,EAAG,uBAAuB,YAAY;EAC5C;EACA,eAAe;GACb,GAAG,GAAU,EAAG,iBAAiB,uBAAuB,CAAC;GACzD,GAAG,GAAU,EAAG,iBAAiB,uBAAuB,CAAC;EAC3D;EACA,gBAAgB;GACd,GAAG,GAAU,EAAG,iBAAiB,wBAAwB,GAAG,CAAC;GAC7D,GAAG,GAAU,EAAG,iBAAiB,wBAAwB,GAAG,CAAC;EAC/D;EACA,GAAG,GAAc,GAAI,GAAI,CAAc;EAGvC,SAAS,GAAY,EAAG,YAAY,CAAU;EAC9C,UAAU,GAAc,EAAG,eAAe,GAAY,GAAS,iBAAiB,CAAC;EACjF,OAAO,EAAG;EACV,YAAY,EAAG;EACf,WAAW,EAAG;EACd,iBAAiB,GAAuB,GAAI,EAAG,iBAAiB,CAAE;EAClE,iBAAiB,EAAG,iBAAiB,eAAe,CAAC,CAAC,KAAK,MAAM;EACjE,aAAa;GACX,KAAK,EAAG;GACR,OAAO,EAAG;GACV,QAAQ,EAAG;GACX,MAAM,EAAG;EACX;EACA,SAAS,GAAY,EAAG,OAAO;EAC/B,UAAU,EAAG,iBAAiB,oBAAoB,CAAC,CAAC,KAAK,KAAK;EAC9D,QAAQ,EAAG,WAAW,UAAU,EAAG,WAAW,KAAK,OAAO,OAAO,EAAG,MAAM,KAAK;EAC/E,eAAe;EACf,OACE,MAAY,UAAU,MAAY,UAAU,MAAY,aACpD,GAAY,GAAI,GAAG,IACnB;EACN,OAAO,MAAY,UAAU,MAAY,SAAS,GAAY,GAAI,GAAG,IAAI;EACzE,WAAW,GAAY,GAAI,mBAAmB,CAAC,QAAQ,cAAc,GAAY,QAAQ;EACzF,WACE,EAAG,iBAAiB,iBAAiB,CAAC,CAAC,KAAK,MAAM,iBAC9C,iBACA,KAAK,IACH,GACA,EAAsB,WAAW,EAAG,iBAAiB,iBAAiB,CAAC,KAAK,CAAC,CAC/E;EACN,qBAAqB,GACnB,GACA,8BACA;GAAC;GAAO;GAAU;EAAS,GAC3B,QACF;EACA;EACA;EACA,YAAY,EAAG,eAAe,SAAS,SAAS;EAChD,YAAY,EAAG,eAAe;EAC9B,mBAAmB,EAAG,gBAAgB;EACtC,kBAAkB,EAAG,eAAe;EACpC,kBAAkB,EAAG,gBAAgB,WAAW,EAAG,gBAAgB;CACrE;CAEA,OADA,GAAoB,GAAO,CAAE,GACtB;AACT;AAKA,SAAS,GAAoB,GAAkB,GAA+B;CACxE,EAAG,mBAAmB,eAExB,EAAM,YAAY,WAClB,EAAM,cAAc,UACpB,EAAM,cAAc,SACpB,EAAM,cAAc,eACpB,EAAM,cAAc,kBACpB,EAAM,cAAc,oBAEtB,EAAM,gBAAgB;EACpB,OAAO,EAAM;EACb,OAAO,EAAM;EACb,OAAO,EAAM;EACb,QAAQ;GACN,KAAK,EAAG,mBAAmB;GAC3B,OAAO,EAAG,qBAAqB;GAC/B,QAAQ,EAAG,sBAAsB;GACjC,MAAM,EAAG,oBAAoB;EAC/B;CACF,GACA,EAAM,SAAS,EAAW,GACtB,EAAM,YAAY,YAAS,EAAM,UAAU,EAAW;AAC5D;AAOA,SAAgB,GAAmB,GAAwB;CACzD,IAAI,CAAC,GAAO,OAAO;CACnB,IAAM,IAAa,EAAM,KAAK,CAAC,CAAC,YAAY;CAC5C,OACE,MAAe,MACf,MAAe,iBACf,MAAe,sBACf,MAAe;AAEnB;AAMA,SAAS,GACP,GACA,GACA,GACoB;CACpB,IAAM,IAAU,EAAgB,GAAI,GAAmB,CAAG,IAAI,KAAK,GAAK,CAAE;CAC1E,OAAO,MAAY,KAAK,KAAA,IAAY;AACtC;AAEA,SAAS,GAAW,GAAwB;CAC1C,OAAO,MAAU,YAAY,MAAU;AACzC;AAQA,IAAM,qBAAsB,IAAI,QAAkC,GAC9D,KAAyC;AAO7C,SAAS,GAA+B,GAAwB;CAC9D,IAAI,OAA2B,MAAM,OAAO;CAC5C,IAAI,CAAC,EAAI,MAAM,OAAO;CACtB,IAAM,IAAQ,EAAI,cAAc,KAAK;CAKrC,OAJA,EAAM,MAAM,UAAU,2DACtB,EAAI,KAAK,YAAY,CAAK,GAC1B,KAAyB,iBAAiB,CAAK,CAAC,CAAC,mBAAmB,QACpE,EAAM,OAAO,GACN;AACT;AAEA,SAAS,GAAmB,GAAa,GAA0C;CACjF,IAAI,CAAC,GAA+B,EAAG,aAAa,GAAG,OAAO;CAC9D,IAAI,EAAG,aAAa,gBAAgB,GAAG;EACrC,IAAM,IAAS,GAAoB,IAAI,CAAE;EACzC,IAAI,MAAW,KAAA,GAAW,OAAO;CACnC;CACA,IAAM,IAAyB,EAAG,mBAAmB,SAAS,SAAS;CAEvE,OADA,GAAoB,IAAI,GAAI,CAAK,GAC1B;AACT;AAIA,SAAS,GAAmB,GAAwD;CAClF,IAAM,KAAK,KAAS,GAAA,CAAI,KAAK;CAC7B,IAAI,CAAC,KAAK,MAAM,QAAQ,OAAO;CAC/B,IAAI,IAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;EACjC,IAAM,IAAK,EAAE;EACb,IAAI,MAAO,KAAK;OACX,IAAI,MAAO,KAAK;OAChB,IAAI,MAAO,OAAO,MAAU,GAC/B,OAAO;GAAE,OAAO,EAAE,MAAM,GAAG,CAAC;GAAG,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK;EAAE;CAEhE;CACA,OAAO;AACT;AAGA,SAAS,GAAU,GAAe,IAAM,GAAW;CACjD,OAAO,KAAK,IAAI,GAAK,KAAK,MAAM,OAAO,CAAK,KAAK,CAAG,CAAC;AACvD;AAEA,SAAS,GAAa,GAA6B;CAGjD,OAFI,GAAW,CAAK,IAAU,SAC1B,MAAU,UAAU,MAAU,WAAiB,IAC5C;AACT;AAMA,SAAgB,GAAa,GAAmC;CAC9D,IAAI,IAAI,GAAa,EAAG,aAAa,EAAG,QAAQ,GAC5C,IAAI,GAAa,EAAG,aAAa,EAAG,QAAQ;CAGhD,OAFI,MAAM,aAAa,MAAM,cAAW,IAAI,SACxC,MAAM,aAAa,MAAM,cAAW,IAAI,SACrC;EAAE;EAAG;CAAE;AAChB;AAOA,SAAS,GAAc,GAAa,GAAkC;CACpE,IAAI,EAAG,aAAa,cAAc,EAAG,aAAa,SAAS,OAAO;CAClE,IAAM,IAAO,EAAG,KAAK,QAAQ,OAAO,EAAE;CAQtC,OAPI,MAAS,2BAA2B,MAAS,mBAMjD,CAAI,GAAgB,EAAG,OAAO,MAE3B,GAAW,EAAG,QAAQ,KAAK,GAAW,EAAG,SAAS,MACnD,WAAW,EAAG,KAAK,KAAK,KACxB,WAAW,EAAG,MAAM,KAAK;AAE7B;AAKA,IAAM,KAAiD;CACrD,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,SAAS;CACT,KAAK;CACL,UAAU;AACZ,GAEM,KAAyC;CAC7C,sBAAsB;CACtB,mBAAmB;CACnB,sBAAsB;CACtB,aAAa;CACb,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,sBAAsB;AACxB;AASA,SAAS,GAAkB,GAAa,GAAqD;CAC3F,IAAM,IACJ,EAAG,iBACH,EAAG,aAAa,QAAQ,CAAC,EAAE,YAAY,MACtC,EAAG,YAAY,QAAQ,EAAG,YAAY,OAAO,WAAW;CAI3D,OAHI,MAAU,QAAc,UACxB,MAAU,WAAiB,WAC3B,MAAU,WAAiB,QACxB;AACT;AAIA,SAAgB,GACd,GACA,GACA,GAUA;CACA,OAAO;EAKL,YAAY,EAAG,eAAe,QAAQ,QAAQ,EAAG,eAAe,WAAW,WAAW;EACtF,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,EAAG,OAAO,CAAC,KAAK,CAAC;EAC5D,cAAc,EAAG,iBAAiB,aAAa,aAAa;EAC5D,oBAAoB,EAAG;EAKvB,kBAAkB,GAAyB,GAAI,CAAE;EACjD,WAAW,GAAc,GAAI,CAAE;EAC/B,YAAY,GAAe,GAAI,CAAc;CAC/C;AACF;AAKA,SAAS,GACP,GACA,GACA,GACM;CAEJ,0DAAyD,KAAK,CAAS,KACvE,kDAAkD,KAAK,CAAS,KAChE,EAAY,aAAa,OAE3B,EACE,GACA,8HAEF;AACF;AAKA,SAAS,GACP,GACA,GACA,GACA,GACO;CACP,IAAM,IAAQ,EAAG,iBAAiB,CAAQ,CAAC,CAAC,KAAK;CACjD,OAAO,EAAO,SAAS,CAAK,IAAI,IAAQ;AAC1C;AAEA,SAAS,GAAY,GAAyB,GAAiC;CAC7E,IAAM,IAAQ,EACZ,WAAW,EAAG,iBAAiB,aAAa,EAAK,OAAO,CAAC,KAAK,CAChE;CACA,IAAI,KAAS,GAAG,OAAO;CACvB,IAAM,IAAQ,EAAG,iBAAiB,aAAa,EAAK,OAAO,CAAC,CAAC,KAAK;CAClE,OAAO;EACL;EACA,OAAO,GAAe,EAAG,iBAAiB,aAAa,EAAK,OAAO,CAAC,CAAC,KAAK,CAAC;EAI3E,OAAO,KAAS,MAAU,kBAAkB,MAAU,iBAAiB,IAAQ,EAAG;CACpF;AACF;AAMA,SAAS,GAAyB,GAAa,GAAkC;CAG/E,OAFI,EAAG,cAAc,aAEd,EAAG,aAAa,OAAO,CAAC,EAAE,YAAY,MAAM;AACrD;AAEA,SAAS,GAAc,GAAa,GAAqD;CACvF,IAAM,IAAQ,EAAG,aAAa,EAAG,aAAa,OAAO,CAAC,EAAE,YAAY,KAAK;CAKzE,OAJI,MAAU,WAAW,MAAU,QAAc,QAG7C,MAAU,YAAY,EAAM,SAAS,SAAS,IAAU,WACrD;AACT;AAEA,SAAS,GACP,GACkE;CAClE,OAAO,OAAQ,EAAsC,oBAAqB;AAC5E;AAIA,SAAS,GAAW,GAA+B;CACjD,QAAQ,GAAR;EACE,KAAK,UACH,OAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK,SACH,OAAO;EACT,KAAK,iBACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK,IACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,SAAS,GAAS,GAA2B;CAC3C,QAAQ,GAAR;EACE,KAAK,UACH,OAAO;EACT,KAAK;EACL,KAAK,OACH,OAAO;EACT,KAAK;EAGL,KAAK;EACL,KAAK,IACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,SAAS,GAAa,GAAoC;CAExD,OADI,MAAU,UAAU,MAAU,MAAM,MAAU,WAAiB,SAC5D,GAAS,CAAK;AACvB;AAcA,SAAS,GACP,GACA,GACA,GACA,GACA,GAC4B;CAC5B,IAAM,KACJ,GACA,GACA,MACsB;EACtB,IAAI,GAAK;GACP,IAAM,IAAgB,EAAI,IAAI,CAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,KAAK;GAGzD,IAFI,MAAkB,UACD,EAAI,IAAI,CAAO,CAAC,EAAE,SAAS,CAAC,CAAC,KAAK,MAClC,QAAQ,OAAO;GAGpC,IAAI,GAAe,SAAS,GAAG,GAAG;IAChC,IAAM,IAAU,WAAW,CAAa;IACxC,IAAI,OAAO,SAAS,CAAO,KAAK,MAAY,GAAG,OAAO,EAAE,WAAQ;GAClE;EACF,OAAO,IACL,EAAiB,KAAK,CAAS,KAC/B,EAAY,iBAAiB,CAAQ,MAAM,QAE3C,OAAO;EAET,IAAM,IAAgB,EAAG,iBAAiB,CAAQ;EAClD,IAAI,MAAkB,QAAQ,OAAO;EACrC,IAAM,IAAgB,EAAY,GAAe,CAAc;EAC/D,IAAI,MAAkB,GAAG,OAAO;EAChC,IAAM,IAAe,EAAG,iBAAiB,CAAO;EAEhD,OADI,MAAiB,SAAe,OAC7B,EAAY,GAAc,CAAc;CACjD;CACA,OAAO;EACL,KAAK,EAAS,cAAc,sBAAsB,kCAAkC;EACpF,OAAO,EAAS,gBAAgB,qBAAqB,qCAAqC;EAC1F,QAAQ,EAAS,iBAAiB,oBAAoB,kCAAkC;EACxF,MAAM,EAAS,eAAe,uBAAuB,qCAAqC;CAC5F;AACF;AAMA,SAAgB,GACd,GACA,GACA,GACQ;CACR,IAAM,KACH,MAAkB,WAAW,IAAI,WAAW,CAAa,KAAK,KAAK;CAEtE,OADI,KAAM,IAAU,IACb,KAAK,MAAM,KAAM,OAAQ,KAAc,IAAI;AACpD;AAQA,SAAS,GAAY,GAAoB,GAA4B;CACnE,IAAI,CAAC,KAAc,MAAe,YAAY,KAAc,GAAG,OAAO;CACtE,IAAM,IAAK,WAAW,CAAU;CAEhC,OADK,OAAO,SAAS,CAAE,IAChB,KAAK,IAAI,GAAG,KAAK,MAAM,IAAK,IAAa,IAAI,IAAI,CAAC,IADxB;AAEnC;AAEA,SAAS,GAAa,GAAyB;CAC7C,QAAQ,GAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,UACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAaA,SAAS,GACP,GACA,GACA,GACA,GACA,GAC4B;CAC5B,IAAM,KACJ,GACA,MACsB;EACtB,IAAI,GAAK;GACP,IAAM,IAAQ,EAAI,IAAI,CAAI,CAAC,EAAE,SAAS,CAAC,CAAC,KAAK;GAE7C,OADI,CAAC,KAAS,MAAU,SAAe,OAChC,EAAY,GAAO,CAAc;EAC1C;EACA,IAAM,IAAS,EAAY;EAC3B,IAAI,GAAQ,OAAO,MAAW,SAAS,OAAO,EAAY,GAAQ,CAAc;EAChF,IAAI,CAAC,EAAe,KAAK,CAAS,GAAG,OAAO;EAC5C,IAAM,IAAQ,EAAG,iBAAiB,CAAI;EACtC,OAAO,CAAC,KAAS,MAAU,SAAS,OAAO,EAAY,GAAO,CAAc;CAC9E;CACA,OAAO;EACL,KAAK,EAAK,OAAO,wCAAwC;EACzD,OAAO,EAAK,SAAS,8CAA8C;EACnE,QAAQ,EAAK,UAAU,2CAA2C;EAClE,MAAM,EAAK,QAAQ,+CAA+C;CACpE;AACF;AAEA,SAAS,GAAe,GAA4B;CAClD,QAAQ,GAAR;EACE,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAOA,SAAS,GAAU,GAAe,GAA+C;CAC/E,IAAI,CAAC,KAAS,MAAU,UAAU,MAAU,QAAQ;CACpD,IAAI,MAAU,iBAAiB,MAAU,iBAAiB,MAAU,eAAe,OAAO;CAC1F,IAAI,EAAM,SAAS,GAAG,GAAG;EACvB,IAAM,IAAU,WAAW,CAAK;EAChC,OAAO,OAAO,SAAS,CAAO,IAAI,EAAE,WAAQ,IAAI,KAAA;CAClD;CACA,IAAM,IAAK,WAAW,CAAK;CAC3B,OAAO,OAAO,SAAS,CAAE,IAAI,EAAU,GAAI,CAAc,IAAI,KAAA;AAC/D;AAOA,SAAS,EAAY,GAAe,GAAoC;CACtE,IAAI,CAAC,KAAS,MAAU,UAAU,MAAU,QAAQ,OAAO;CAC3D,IAAI,EAAM,SAAS,GAAG,GAAG;EACvB,IAAM,IAAU,WAAW,CAAK;EAChC,OAAO,OAAO,SAAS,CAAO,KAAK,MAAY,IAAI,EAAE,WAAQ,IAAI;CACnE;CACA,IAAM,IAAK,WAAW,CAAK;CAC3B,OAAO,OAAO,SAAS,CAAE,IAAI,EAAU,GAAI,CAAc,IAAI;AAC/D;AAGA,SAAS,GAAY,GAAuB;CAC1C,IAAM,IAAS,WAAW,CAAK;CAC/B,OAAO,OAAO,SAAS,CAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAM,CAAC,IAAI;AACtE;AAKA,SAAS,GAAe,GAAyB,GAAgC;CAC/E,IAAM,IAAQ,EAAG;CACjB,IAAI,CAAC,KAAS,EAAM,SAAS,GAAG,GAAG,OAAO;CAC1C,IAAM,IAAK,WAAW,CAAK;CAC3B,OAAO,OAAO,SAAS,CAAE,IAAI,KAAK,IAAI,GAAG,EAAU,GAAI,CAAc,CAAC,IAAI;AAC5E;AAEA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACA,GACkB;CAMlB,IAAM,IAAiB,GAAiB,MAAQ,UAAU,EAAY,QAAQ,EAAY,MAAM;CAChG,IAAI,MAAmB,MACrB,OAAO;EAAE,MAAM;EAAS,OAAO,GAAc,GAAgB,GAAK,GAAS,CAAc;CAAE;CAE7F,IAAM,IAAO,GACX,GACA,GACA,GACA,GACA,MAAQ,UAAU,MAAM,KACxB,GACA,GACA,CACF;CACA,IAAI,MAAS,KAAA,GAAW,OAAO;EAAE,MAAM;EAAS,OAAO;CAAK;CAI5D,IAAM,IAAa,GAAkB,GAAW,MAAQ,UAAU,MAAM,GAAG;CAC3E,IAAI,MAAe,MAAM;EAOvB,IAAM,IAAW,WAAW,IAAM,OAAO,EAAI,IAAI,CAAG,KAAK,EAAE,IAAI,CAAQ,GACjE,IAAS,OAAO,SAAS,CAAQ,KAAK,KAAK,IAAI,IAAW,CAAU,KAAK,IAAa;EAC5F,IAAI,KAAU,CAAC,OAAO,SAAS,CAAQ,GAErC,OAAO;GAAE,MAAM;GAAS,OAAO,GADpB,IAAS,IAAW,GACkB,GAAK,GAAS,CAAc;EAAE;CAEnF;CACA,IAAI,GAAK;EACP,IAAM,IAAQ,EAAI,IAAI,CAAG;EACzB,IAAI,KAAS,MAAM;EACnB,IAAM,IAAI,EAAM,SAAS,CAAC,CAAC,KAAK;EAChC,IAAI,MAAM,QAAQ,OAAO,EAAE,MAAM,OAAO;EACxC,IAAM,IAAY,GAAqB,CAAC;EACxC,IAAI,GAAW,OAAO;EACtB,IAAI,EAAE,SAAS,GAAG,GAAG,OAAO;GAAE,MAAM;GAAW,OAAO,WAAW,CAAC;EAAE;EACpE,IAAI,EAAE,SAAS,IAAI,GAAG,OAAO;GAAE,MAAM;GAAS,OAAO,EAAU,WAAW,CAAC,GAAG,CAAc;EAAE;EAC9F,IAAI,EAAE,SAAS,KAAK,GAClB,OAAO;GAAE,MAAM;GAAS,OAAO,EAAsB,WAAW,CAAC,IAAI,GAAI;EAAE;EAG7E,IAAM,IAAmB,GAAiB,CAAC;EAC3C,IAAI,MAAqB,MACvB,OAAO;GACL,MAAM;GACN,OAAO,GAAc,GAAkB,GAAK,GAAS,CAAc;EACrE;CAEJ;CAMA,IAAM,IAAS,MAAQ,UAAU,EAAY,QAAQ,EAAY;CACjE,IAAI,GAAQ;EACV,IAAI,MAAW,QAAQ,OAAO,EAAE,MAAM,OAAO;EAC7C,IAAM,IAAY,GAAqB,CAAM;EAC7C,IAAI,GAAW,OAAO;EACtB,IAAI,EAAO,SAAS,GAAG,GAAG,OAAO;GAAE,MAAM;GAAW,OAAO,WAAW,CAAM;EAAE;EAC9E,IAAM,IAAK,WAAW,CAAM;EAC5B,IAAI,OAAO,SAAS,CAAE,GAAG,OAAO;GAAE,MAAM;GAAS,OAAO,EAAU,GAAI,CAAc;EAAE;CACxF;CAKA,IAAM,IAAO,MAAQ,UAAU,MAAM;CACrC,IAAQ,OAAO,kBAAkB,EAAK,QAAQ,CAAC,CAAC,KAAK,CAAS,GAAG,OAAO,EAAE,MAAM,cAAc;CAC9F,IAAQ,OAAO,kBAAkB,EAAK,QAAQ,CAAC,CAAC,KAAK,CAAS,GAAG,OAAO,EAAE,MAAM,cAAc;CAC9F,IAAQ,OAAO,kBAAkB,EAAK,QAAQ,CAAC,CAAC,KAAK,CAAS,GAAG,OAAO,EAAE,MAAM,cAAc;CAG9F,IAAM,IAAe,OAAO,kBAAkB,EAAK,0BAA0B,CAAC,CAAC,KAAK,CAAS;CAC7F,IAAI,GACF,OAAO;EAAE,MAAM;EAAW,OAAQ,MAAM,OAAO,EAAS,EAAE,IAAK,OAAO,EAAS,EAAE;CAAE;CACrF,IAAQ,OAAO,kBAAkB,EAAK,gBAAgB,CAAC,CAAC,KAAK,CAAS,GACpE,OAAO;EAAE,MAAM;EAAW,OAAO;CAAI;CACvC,IAAM,IAAuB,OAAO,kBAAkB,EAAK,2BAA2B,CAAC,CAAC,KACtF,CACF;CACA,IAAI,GAAkB,OAAO;EAAE,MAAM;EAAW,OAAO,OAAO,EAAiB,EAAE;CAAE;CAOnF,IAAM,IAAc,OAAO,kBAAkB,EAAK,+BAA+B,CAAC,CAAC,KACjF,CACF;CACA,IAAI,GAAS,OAAO;EAAE,MAAM;EAAS,OAAO,EAAsB,OAAO,EAAQ,EAAE,CAAC;CAAE;CAEtF,IADI,CAAC,GAAiB,GAAW,CAAI,KACjC,MAAa,QAAQ,OAAO,EAAE,MAAM,OAAO;CAC/C,IAAI,EAAS,SAAS,GAAG,GAAG,OAAO;EAAE,MAAM;EAAW,OAAO,WAAW,CAAQ;CAAE;CAClF,IAAM,IAAK,WAAW,CAAQ;CAC9B,IAAI,OAAO,SAAS,CAAE,GAAG,OAAO;EAAE,MAAM;EAAS,OAAO,EAAU,GAAI,CAAc;CAAE;AAExF;AAIA,SAAS,GAAiB,GAA8B;CACtD,IAAM,IAAQ,iDAAiD,KAAK,EAAM,KAAK,CAAC;CAChF,IAAI,CAAC,KAAS,OAAO,SAAW,KAAa,OAAO;CACpD,IAAM,IAAS,WAAW,EAAM,EAAG;CACnC,IAAI,CAAC,OAAO,SAAS,CAAM,GAAG,OAAO;CACrC,IAAM,IAAO,EAAM,IACb,IAAS,OAAO,aAChB,IAAQ,OAAO,YACf,IAAQ,EAAK,SAAS,GAAG,IAC3B,IACA,EAAK,SAAS,KAAK,IACjB,KAAK,IAAI,GAAO,CAAM,IACtB,EAAK,SAAS,KAAK,IACjB,KAAK,IAAI,GAAO,CAAM,IACtB,MAAS,OACP,IACA;CACV,OAAQ,IAAS,MAAO;AAC1B;AAMA,SAAS,GAAkB,GAAmB,GAA+B;CAC3E,IAAI,OAAO,SAAW,KAAa,OAAO;CAC1C,IAAM,IAAY,OAAO,kBAAkB,EAAO,+BAA+B,CAAC,CAAC,KACjF,CACF;CACA,IAAI,GAAO;EACT,IAAM,IAAO,EAAM;EAGnB,OADI,MAAS,WAAiB,EAAO,SAAS,GAAG,IAAI,OAAO,cAAc,OAAO,aAC1E,EAAK,SAAS,GAAG,IAAI,OAAO,cAAc,OAAO;CAC1D;CAEA,IAAM,IAAgB,OACpB,kBAAkB,EAAO,mDAC3B,CAAC,CAAC,KAAK,CAAS;CAChB,OAAO,IAAY,GAAiB,EAAU,EAAG,IAAI;AACvD;AAKA,SAAS,GACP,GACA,GACA,GACA,GACQ;CACR,IAAM,IAAS,MAAQ,UAAU,GAAS,QAAQ,GAAS;CAE3D,OADI,KAAU,IAAS,IAAU,KAAK,IAAI,GAAG,KAAK,MAAM,IAAK,CAAM,CAAC,IAC7D,EAAU,GAAI,CAAc;AACrC;AAYA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACoB;CACpB,IAAM,IAAM,EAAS,SAAS,OAAO,IAAI,UAAU,UAC7C,IAAS,EAAY,iBAAiB,CAAQ,CAAC,CAAC,KAAK,GACrD,IAAa,EAAO,WAAW,OAAO;CAE5C,IAAI,CAAC,KAAc,CAAC,EAAU,SAAS,SAAS,GAAG;CACnD,IAAM,IAAc,OAAO,kBAAkB,EAAc,2BAA2B,CAAC,CAAC,KACtF,CACF,GACM,IAAW,IAAa,IAAS,IAAU,EAAE,EAAE,WAAW,KAAK,GAAG;CACxE,IAAI,CAAC,GAAU;CACf,IAAM,IAAQ,GAAa,GAAU,GAAK,GAAS,CAAc;CACjE,IAAI,CAAC,KAAS,EAAM,UAAU;CAC9B,IAAM,IAAQ,KAAK,IAAI,GAAG,EAAsB,EAAM,KAAK,CAAC;CAK5D,IAAI,GAAY,OAAO;CACvB,IAAM,KAAgB,IAAM,OAAO,EAAI,IAAI,CAAQ,KAAK,EAAE,IAAI,EAAA,CAAe,KAAK,GAC5E,IAAW,WAAW,CAAY;CAIxC,QAHe,OAAO,SAAS,CAAQ,IACnC,KAAK,IAAI,IAAW,EAAM,EAAE,KAAK,KAAK,IAAI,EAAM,EAAE,IAAI,KACtD,MAAiB,MACL,IAAQ,KAAA;AAC1B;AAYA,SAAS,GACP,GACA,GACA,GACA,GACkB;CAClB,IAAM,IAAS,EAAO,MAAM,2DAA2D;CACvF,IAAI,CAAC,KAAU,EAAO,KAAK,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE,MAAM,EAAO,QAAQ,QAAQ,EAAE,GAAG,OAAO;CAC1F,IAAI,IAAI,GACF,UAAiC,EAAO,IACxC,UAAiC,EAAO,MACxC,KAAU,GAAe,OAA2B;EAAE;EAAO;EAAI,UAAU;CAAM,IACjF,KAAQ,MAAoC;EAChD,IAAM,IAAU,kCAAkC,KAAK,CAAK;EAC5D,IAAI,GAAS;GACX,IAAM,IAAI,WAAW,EAAQ,EAAG;GAChC,OAAO,EAAO,GAAI,IAAI,IAAkB,CAAC;EAC3C;EACA,IAAM,IAAQ,sBAAsB,KAAK,CAAK;EAC9C,IAAI,CAAC,GAAO,OAAO;EACnB,IAAM,IAAS,WAAW,EAAM,EAAG,GAC7B,IAAO,EAAM;EACnB,IAAI,CAAC,OAAO,SAAS,CAAM,GAAG,OAAO;EACrC,IAAI,MAAS,IAAI,OAAO;GAAE,OAAO;GAAQ,IAAI;GAAQ,UAAU;EAAK;EACpE,IAAI,MAAS,MAAM,OAAO,EAAO,KAAU,IAAiB,IAAI,CAAM;EACtE,IAAI,MAAS,OAAO,OAAO,EAAO,IAAS,GAAG,IAAS,CAAc;EACrE,IAAM,IAAW,GAAiB,CAAK;EAEvC,OADI,MAAa,OAAa,OACvB,EAAO,GAAc,GAAU,GAAK,GAAS,CAAc,GAAG,CAAQ;CAC/E,GACM,KAAW,GAAY,GAAc,MAAmC;EAC5E,IAAI,MAAO,OAAO,MAAO,KAAK;GAC5B,IAAI,EAAE,aAAa,EAAE,UAAU,OAAO;GACtC,IAAM,IAAO,MAAO,MAAM,IAAI;GAC9B,OAAO;IAAE,OAAO,EAAE,QAAQ,IAAO,EAAE;IAAO,IAAI,EAAE,KAAK,IAAO,EAAE;IAAI,UAAU,EAAE;GAAS;EACzF;EACA,IAAI,MAAO,KAAK;GACd,IAAI,CAAC,EAAE,YAAY,CAAC,EAAE,UAAU,OAAO;GACvC,IAAM,CAAC,GAAG,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;GAC1C,OAAO;IAAE,OAAO,EAAE,QAAQ,EAAE;IAAO,IAAI,EAAE,KAAK,EAAE;IAAI,UAAU,EAAE,YAAY,EAAE;GAAS;EACzF;EAEA,OADI,CAAC,EAAE,YAAY,EAAE,OAAO,IAAU,OAC/B;GAAE,OAAO,EAAE,QAAQ,EAAE;GAAO,IAAI,EAAE,KAAK,EAAE;GAAI,UAAU,EAAE;EAAS;CAC3E,GACM,UAAiC;EACrC,IAAM,IAAQ,EAAK;EACnB,IAAI,MAAU,KAAA,GAAW,OAAO;EAChC,IAAI,MAAU,KAAK;GACjB,IAAM,IAAQ,EAAO;GACrB,OAAO,KAAS;IAAE,OAAO,CAAC,EAAM;IAAO,IAAI,CAAC,EAAM;IAAI,UAAU,EAAM;GAAS;EACjF;EAGA,OAFI,MAAU,SAAe,EAAK,MAAM,MAAM,EAAM,IAAI,OACpD,MAAU,MAAY,EAAM,IACzB,EAAK,CAAK;CACnB,GACM,UAAgC;EACpC,IAAM,IAAQ,EAAI;EAClB,OAAO,EAAK,MAAM,MAAM,IAAQ;CAClC,GACM,UAAkC;EACtC,IAAI,IAAQ,EAAO;EACnB,OAAO,MAAU,EAAK,MAAM,OAAO,EAAK,MAAM,OAAM;GAClD,IAAM,IAAK,EAAK,GACV,IAAM,EAAO;GACnB,IAAQ,IAAM,EAAQ,GAAI,GAAO,CAAG,IAAI;EAC1C;EACA,OAAO;CACT,GACM,UAA8B;EAClC,IAAI,IAAQ,EAAQ;EACpB,OAAO,MAAU,EAAK,MAAM,OAAO,EAAK,MAAM,OAAM;GAClD,IAAM,IAAK,EAAK,GACV,IAAM,EAAQ;GACpB,IAAQ,IAAM,EAAQ,GAAI,GAAO,CAAG,IAAI;EAC1C;EACA,OAAO;CACT,GACM,IAAS,EAAI;CACnB,OAAO,MAAM,EAAO,SAAS,IAAS;AACxC;AAQA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACoB;CACpB,IAAM,IAAM,EAAS,SAAS,OAAO,IAAI,UAAU,UAK7C,IACJ,GAAiB,EAAY,iBAAiB,CAAQ,CAAC,KACvD,GAAiB,GAAK,IAAI,CAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,KAAK,KAAK,EAAE;CAC9D,IAAI,MAAe,MAAM,OAAO,GAAc,GAAY,GAAK,GAAS,CAAc;CAGtF,IAAM,IAAU,GAAkB,GAAW,CAAa;CAC1D,IAAI,MAAY,MAAM;CACtB,IAAM,KAAgB,IAAM,OAAO,EAAI,IAAI,CAAQ,KAAK,EAAE,IAAI,EAAA,CAAe,KAAK,GAC5E,IAAW,WAAW,CAAY,GAClC,IAAS,OAAO,SAAS,CAAQ,KAAK,KAAK,IAAI,IAAW,CAAO,KAAK,IAAU;CAElF,IAAC,KAAU,MAAiB,IAChC,OAAO,GAAc,IAAS,IAAW,GAAS,GAAK,GAAS,CAAc;AAChF;AAOA,SAAS,GAAc,GAAe,GAA0C;CAC9E,IAAI,CAAC,KAAS,MAAU,UAAU,MAAU,WAAW;CACvD,IAAM,IAAU,GAAqB,CAAK;CAC1C,IAAI,GAAS,OAAO;CACpB,IAAI,EAAM,SAAS,GAAG,GAAG;EACvB,IAAM,IAAU,WAAW,CAAK;EAChC,OAAO,OAAO,SAAS,CAAO,IAAI;GAAE,MAAM;GAAW,OAAO;EAAQ,IAAI,KAAA;CAC1E;CACA,IAAM,IAAK,WAAW,CAAK;CAC3B,OAAO,OAAO,SAAS,CAAE,IAAI;EAAE,MAAM;EAAS,OAAO,EAAU,GAAI,CAAc;CAAE,IAAI,KAAA;AACzF;AAEA,SAAS,GAAqB,GAAiC;CAC7D,IAAI,MAAU,eAAe,OAAO,EAAE,MAAM,cAAc;CAC1D,IAAI,MAAU,eAAe,OAAO,EAAE,MAAM,cAAc;CAC1D,IAAI,MAAU,eAAe,OAAO,EAAE,MAAM,cAAc;AAE5D;AAUA,SAAgB,GAAmB,GAAe,GAAsC;CACtF,IAAM,IAAU,EAAM,KAAK;CAC3B,IAAI,CAAC,KAAW,MAAY,QAAQ,OAAO,EAAE,MAAM,OAAO;CAC1D,IAAI,MAAY,aAAa,EAAQ,WAAW,UAAU,GAAG,OAAO,EAAE,MAAM,UAAU;CACtF,IAAM,IAAsB,CAAC,GACvB,IAAwB,CAAC,GAG3B,IAAoB,CAAC,GACnB,KAAa,MAAqB;EAGtC,AAFA,EAAU,KAAK,CAAO,GACtB,IAAU,CAAC,GACX,EAAO,KAAK,CAAK;CACnB,GACI;CACJ,KAAK,IAAM,KAAS,GAAc,CAAO,GAAG;EAC1C,IAAM,IAAQ,GAAe,CAAK;EAClC,IAAI,GAAO;GACT,EAAQ,KAAK,GAAG,CAAK;GACrB;EACF;EACA,IAAM,IAAS,EAAM,MAAM,kCAAkC;EAC7D,IAAI,GAAQ;GACV,IAAM,IAAQ,GAAe,EAAO,EAAE,CAAE,KAAK,GAAG,CAAc;GAC9D,IAAI,EAAM,OAAO,WAAW,GAAG;GAC/B,IAAM,IAAQ,EAAO;GACrB,IAAI,MAAU,eAAe,MAAU,YAAY;IAEjD,AAAK,MACH,IAAa;KAAE,OAAO,EAAO;KAAQ,QAAQ,EAAM;KAAQ,MAAM;IAAM,GACnE,EAAM,UAAU,MAAM,MAAM,EAAE,SAAS,CAAC,MAAG,EAAW,YAAY,EAAM,YACxE,EAAQ,SAAS,MAAG,EAAW,eAAe,IAClD,IAAU,CAAC;IAEb;GACF;GACA,IAAM,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,CAAK,KAAK,CAAC,CAAC;GACpD,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;IAC1B,EAAQ,KAAK,GAAG,EAAM,UAAU,EAAG;IACnC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,OAAO,QAAQ,KAEvC,AADA,EAAU,EAAM,OAAO,EAAG,GAC1B,EAAQ,KAAK,GAAG,EAAM,UAAU,IAAI,EAAG;GAE3C;GACA;EACF;EACA,EAAU,GAAe,GAAO,CAAc,CAAC;CACjD;CAEA,IADA,EAAU,KAAK,CAAO,GAClB,EAAO,WAAW,KAAK,CAAC,GAAY,OAAO,EAAE,MAAM,OAAO;CAC9D,IAAM,IAAsD;EAAE,MAAM;EAAU;CAAO;CAGrF,OAFI,EAAU,MAAM,MAAM,EAAE,SAAS,CAAC,MAAG,EAAS,YAAY,IAC1D,MAAY,EAAS,aAAa,IAC/B;AACT;AAIA,SAAS,GACP,GACA,GACgD;CAChD,IAAM,IAAsB,CAAC,GACvB,IAAwB,CAAC,GAC3B,IAAoB,CAAC;CACzB,KAAK,IAAM,KAAS,GAAc,CAAK,GAAG;EACxC,IAAM,IAAQ,GAAe,CAAK;EAClC,IAAI,GAAO;GACT,EAAQ,KAAK,GAAG,CAAK;GACrB;EACF;EAGA,AAFA,EAAU,KAAK,CAAO,GACtB,IAAU,CAAC,GACX,EAAO,KAAK,GAAe,GAAO,CAAc,CAAC;CACnD;CAEA,OADA,EAAU,KAAK,CAAO,GACf;EAAE;EAAQ;CAAU;AAC7B;AAGA,SAAS,GAAe,GAAgC;CACtD,IAAM,IAAQ,EAAM,MAAM,aAAa;CAEvC,OADK,IACE,EAAM,EAAE,CAAE,MAAM,KAAK,CAAC,CAAC,QAAQ,MAAS,MAAS,EAAE,IADvC;AAErB;AASA,SAAgB,GAAuB,GAAiC;CACtE,IAAM,IAAmB,CAAC;CAC1B,KAAK,IAAM,KAAS,EAAM,SAAS,sBAAsB,GAAG;EAC1D,IAAM,KAAS,EAAM,MAAM,EAAM,MAAM,GAAA,CACpC,KAAK,CAAC,CACN,MAAM,KAAK,CAAC,CACZ,QAAQ,MAAM,MAAM,EAAE;EACzB,IAAI,EAAM,WAAW,GAAG,OAAO;EAC/B,EAAK,KAAK,CAAK;CACjB;CACA,IAAI,EAAK,WAAW,GAAG,OAAO;CAC9B,IAAM,IAAU,EAAK,EAAE,CAAE;CACzB,IAAI,EAAK,MAAM,MAAQ,EAAI,WAAW,CAAO,GAAG,OAAO;CACvD,IAAM,oBAAQ,IAAI,IAAsB;CACxC,EAAK,SAAS,GAAK,MAAM;EACvB,EAAI,SAAS,GAAM,MAAM;GACvB,IAAI,QAAQ,KAAK,CAAI,GAAG;GACxB,IAAM,IAAO,EAAM,IAAI,CAAI;GAC3B,AAAK,KAEH,EAAK,WAAW,KAAK,IAAI,EAAK,UAAU,CAAC,GACzC,EAAK,SAAS,KAAK,IAAI,EAAK,QAAQ,IAAI,CAAC,GACzC,EAAK,WAAW,KAAK,IAAI,EAAK,UAAU,CAAC,GACzC,EAAK,SAAS,KAAK,IAAI,EAAK,QAAQ,IAAI,CAAC,KALhC,EAAM,IAAI,GAAM;IAAE,UAAU;IAAG,QAAQ,IAAI;IAAG,UAAU;IAAG,QAAQ,IAAI;GAAE,CAAC;EAOvF,CAAC;CACH,CAAC;CAED,KAAK,IAAM,CAAC,GAAM,MAAS,GACzB,KAAK,IAAI,IAAI,EAAK,UAAU,IAAI,EAAK,QAAQ,KAC3C,KAAK,IAAI,IAAI,EAAK,UAAU,IAAI,EAAK,QAAQ,KAC3C,IAAI,EAAK,EAAE,CAAE,OAAO,GAAM,OAAO;CAIvC,OAAO;EAAE;EAAS,MAAM,EAAK;EAAQ;CAAM;AAC7C;AAIA,SAAS,GAAgB,GAAe,GAAqC;CAC3E,IAAM,IAAS,GAAc,EAAM,KAAK,CAAC,CAAC,CACvC,QAAQ,MAAM,MAAM,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,CAC7C,KAAK,MAAM,GAAe,GAAG,CAAc,CAAC;CAC/C,OAAO,EAAO,SAAS,IAAI,IAAS,CAAC,GAAU,CAAC;AAClD;AAKA,SAAS,GAAe,GAAe,GAAmC;CACxE,IAAM,IAAS,EAAM,MAAM,mBAAmB;CAC9C,IAAI,GAAQ;EAGV,IAAM,IAAO,GAAoB,EAAO,EAAG,CAAC,CAAC,KAAK,MAAQ,EAAI,KAAK,CAAC;EAOpE,OANI,EAAK,WAAW,IACX;GACL,KAAK,GAAkB,EAAK,IAAK,CAAc;GAC/C,KAAK,GAAkB,EAAK,IAAK,CAAc;EACjD,IAEK;GAAE,KAAK,EAAE,MAAM,OAAO;GAAG,KAAK,EAAE,MAAM,OAAO;EAAE;CACxD;CACA,IAAM,IAAU,GAAkB,GAAO,CAAc;CAEvD,OADI,EAAQ,SAAS,OAAa;EAAE,KAAK,EAAE,MAAM,OAAO;EAAG,KAAK;CAAQ,IACjE;EAAE,KAAK;EAAS,KAAK;CAAQ;AACtC;AAEA,SAAS,GAAkB,GAAe,GAAsC;CAC9E,IAAI,MAAU,UAAU,EAAM,WAAW,aAAa,GAAG,OAAO,EAAE,MAAM,OAAO;CAC/E,IAAI,MAAU,eAAe,OAAO,EAAE,MAAM,cAAc;CAC1D,IAAI,MAAU,eAAe,OAAO,EAAE,MAAM,cAAc;CAK1D,IAAM,IAAO,EAAM,MAAM,sBAAsB;CAC/C,IAAI,GAAM;EACR,IAAM,IAAO,GAAoB,EAAK,EAAG,CAAC,CAAC,KAAK,MAC9C,GAAkB,EAAI,KAAK,GAAG,CAAc,CAC9C,GACM,IAAQ,EAAK,OAChB,MAAM,EAAE,SAAS,WAAW,EAAE,SAAS,aAAa,EAAE,SAAS,MAClE;EAIA,OAHI,EAAK,SAAS,KAAK,IACd;GAAE,MAAM;GAAQ,IAAI,EAAK;GAAqB;EAAK,IAErD,EAAE,MAAM,OAAO;CACxB;CACA,IAAI,EAAM,SAAS,IAAI,GAAG;EACxB,IAAM,IAAQ,WAAW,CAAK;EAC9B,OAAO,OAAO,SAAS,CAAK,KAAK,KAAS,IAAI;GAAE,MAAM;GAAM;EAAM,IAAI,EAAE,MAAM,OAAO;CACvF;CACA,IAAI,EAAM,SAAS,GAAG,GAAG;EACvB,IAAM,IAAU,WAAW,CAAK;EAChC,OAAO,OAAO,SAAS,CAAO,IAAI;GAAE,MAAM;GAAW,OAAO;EAAQ,IAAI,EAAE,MAAM,OAAO;CACzF;CACA,IAAM,IAAK,WAAW,CAAK;CAK3B,OAJK,OAAO,SAAS,CAAE,IAIhB;EAAE,MAAM;EAAS,OAHV,EAAM,SAAS,KAAK,IAC9B,EAAsB,IAAK,GAAI,IAC/B,EAAU,GAAI,CAAc;CACK,IAJJ,EAAE,MAAM,OAAO;AAKlD;AAIA,SAAS,GAAoB,GAAyB;CACpD,IAAM,IAAiB,CAAC,GACpB,IAAQ,GACR,IAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAK,EAAM;EACjB,AAAI,MAAO,MAAK,MACP,MAAO,MAAK,MACZ,MAAO,OAAO,MAAU,MAC/B,EAAK,KAAK,EAAM,MAAM,GAAO,CAAC,CAAC,GAC/B,IAAQ,IAAI;CAEhB;CAEA,OADA,EAAK,KAAK,EAAM,MAAM,CAAK,CAAC,GACrB,EAAK,QAAQ,MAAM,EAAE,KAAK,MAAM,EAAE;AAC3C;AAIA,SAAS,GAAc,GAAyB;CAC9C,IAAM,IAAmB,CAAC,GACtB,IAAQ,GACR,IAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAK,EAAM;EAGjB,AAFI,MAAO,OAAO,MAAO,MAAK,OACrB,MAAO,OAAO,MAAO,QAAK,KAC/B,KAAK,KAAK,CAAE,KAAK,MAAU,KACzB,MAAU,MAAI,EAAO,KAAK,EAAM,MAAM,GAAO,CAAC,CAAC,GACnD,IAAQ,MACC,MAAU,OACnB,IAAQ;CAEZ;CAEA,OADI,MAAU,MAAI,EAAO,KAAK,EAAM,MAAM,CAAK,CAAC,GACzC;AACT;AAKA,SAAgB,GAAc,GAAyB;CACrD,IAAM,IAAU,EAAM,KAAK;CAC3B,IAAI,CAAC,KAAW,MAAY,QAAQ,OAAO,EAAE,MAAM,OAAO;CAG1D,IAAI,IAAO,IACP,GACA;CACJ,KAAK,IAAM,KAAS,EAAQ,MAAM,KAAK,GACrC,AAAI,MAAU,SAAQ,IAAO,KACpB,UAAU,KAAK,CAAK,IAAG,IAAU,OAAO,CAAK,IACjD,IAAO;CAEd,IAAI,GAAM;EACR,IAAM,IAAQ,KAAW;EAEzB,OADI,IAAQ,IAAU,EAAE,MAAM,OAAO,IAC9B,MAAS,KAAA,IACZ;GAAE,MAAM;GAAQ,OAAO;EAAM,IAC7B;GAAE,MAAM;GAAQ,OAAO;GAAO;EAAK;CACzC;CAMA,OALI,MAAS,KAAA,IAIT,MAAY,KAAA,KAAa,MAAY,IAAU;EAAE,MAAM;EAAQ,OAAO;CAAQ,IAC3E,EAAE,MAAM,OAAO,IAJhB,MAAY,IAAU,EAAE,MAAM,OAAO,IAClC,MAAY,KAAA,IAAY;EAAE,MAAM;EAAQ;CAAK,IAAI;EAAE,MAAM;EAAQ;EAAM,KAAK;CAAQ;AAI/F;AAEA,SAAS,GAAkB,GAA6B;CACtD,OAAO;EACL,WAAW,EAAM,SAAS,QAAQ,IAAI,WAAW;EACjD,OAAO,EAAM,SAAS,OAAO;CAC/B;AACF;AAQA,SAAS,GAAiB,GAAmB,GAA0B;CAErE,QADgB,MAAS,MAAM,qBAAqB,mBAAA,CACrC,KAAK,CAAS;AAC/B;AAEA,SAAS,GAAY,GAAyB,GAA6C;CACzF,OAAO;EACL,KAAK,EAAY,EAAG,iBAAiB,aAAa,GAAG,CAAc;EACnE,OAAO,EAAY,EAAG,iBAAiB,eAAe,GAAG,CAAc;EACvE,QAAQ,EAAY,EAAG,iBAAiB,gBAAgB,GAAG,CAAc;EACzE,MAAM,EAAY,EAAG,iBAAiB,cAAc,GAAG,CAAc;CACvE;AACF;AAGA,SAAS,GAAiB,GAAiC;CACzD,IAAM,KAAY,GAAc,MAC1B,EAAG,iBAAiB,CAAK,MAAM,SAAe,IAC3C,EAAsB,WAAW,EAAG,iBAAiB,CAAI,CAAC,KAAK,CAAC;CAEzE,OAAO;EACL,KAAK,EAAS,oBAAoB,kBAAkB;EACpD,OAAO,EAAS,sBAAsB,oBAAoB;EAC1D,QAAQ,EAAS,uBAAuB,qBAAqB;EAC7D,MAAM,EAAS,qBAAqB,mBAAmB;CACzD;AACF;;;ACn+CA,SAAgB,GACd,GACA,GACA,GACA,GACmB;CACnB,IAAM,IAAQ,GAAc,GAAM,GAAgB,CAAW;CAC7D,IAAI,EAAM,YAAY,QAAQ,OAAO;CAMrC,IAAM,IAAO,GAAgB,EAAK,OAAO;CACzC,IAAI,GAAM,OAAO,GAAkB,GAAM,GAAO,CAAI;CAEpD,IAAM,IAAkB,MAAM,KAAK,EAAK,QAAQ,GAC1C,IAAQ,EAAgB,IAAI,EAAS,GACrC,IAAU;EAAE;EAAgB;EAAa;CAAe;CAI9D,IAAI,CAAC,EAAM,SAAS,OAAO,KAAK,GAAiB,EAAK,OAAO,GAC3D,OAAO,GAAU,GAAM,GAAO,GAAiB,GAAO,CAAO;CAG/D,IAAM,IAAyB,CAAC;CAChC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAgB,QAAQ,KAAK;EAC/C,IAAI,EAAM,OAAO,QAAQ;EACzB,IAAM,IAAO,GAAU,EAAgB,IAAK,GAAgB,GAAa,CAAc;EACvF,AAAI,KAAM,EAAS,KAAK,CAAI;CAC9B;CACA,IAAM,IAAwB;EAC5B,QAAQ;EACR;EACA;EACA,MAAM;EACN,gBAAgB;EAChB,iBAAiB;EACjB,WAAW;GAAE,GAAG;GAAG,GAAG;GAAG,OAAO;GAAG,QAAQ;EAAE;EAC7C,iBAAiB;EACjB,iBAAiB,EAAW;CAC9B;CAEA,OADA,GAAgB,GAAM,CAAS,GACxB;AACT;AAYA,SAAgB,GACd,GACA,GACA,GACA,GACmB;CACnB,IAAM,IAAQ,MAAM,KAAK,EAAK,UAAU,CAAC,CAAC,QACvC,MAAS,EAAE,aAAgB,WAAW,EAAK,aAAa,eAAe,EAC1E,GACM,IAAkB,EAAM,QAAQ,MAA0B,aAAgB,OAAO,GACjF,IAAQ,EAAgB,IAAI,EAAS;CAK3C,OAJI,EAAM,SAAS,OAAO,KACtB,CAAC,GAAc,CAAI,KAAK,CAAC,EAAM,SAAS,QAAQ,IAAU,OAGvD,GAAU,GAFH,GAAc,GAAM,CAEX,GAAO,GAAiB,GAAO;EADpC;EAAgB;EAAa;CACO,GAAS,CAAK;AACtE;AAMA,SAAS,GAAc,GAAe,GAAmC;CACvE,IAAM,IAAK,iBAAiB,CAAI,GAC1B,IAAQ;EAAE,GAAG,GAAiB;EAAG,GAAG,GAAc,GAAM,GAAI,CAAc;CAAE;CAGlF,OADI,GAAa,CAAE,CAAC,CAAC,MAAM,WAAQ,EAAM,WAAW;EAAE,GAAG,EAAM;EAAU,GAAG;CAAO,IAC5E;AACT;AAMA,SAAS,GACP,GACA,GACA,GACA,GACA,GACA,GACY;CACZ,IAAM,EAAE,mBAAgB,gBAAa,sBAAmB,GAClD,IAAM,EAAK,SACX,IAAc,GAAiB,CAAG,GAClC,IAAM,GACV,GACA,EAAM,UACN;EACE;EACA,qBAAqB,GAAa,iBAAiB;EACnD;EACA;EACA,UAAU,EAAM,eAAe;EAC/B,SAAS,EAAM;CACjB,GACA,CACF,GACM,IAAO,EAAI,MAAM,KAAK,EAAE;CAG9B,IAAI,EAAI,MAAM,SAAS,GAAG;EACxB,IAAM,IAAQ,GAAmB;EACjC,GAAiB,EAAI,QAAQ,GAAW,MAAa;GACnD,EAAI,SAAS,KAAa,KAAK,IAAI,GAAG,EAAoB,EAAI,MAAM,IAAY,CAAK,CAAC;EACxF,CAAC;CACH;CAMA,IAAI,IAAiB,GAAmB,GAAM,EAAI,UAAU,EAAM,QAAQ;CAC1E,IAAI,KAAe,MAAmB,GAAG;EAEvC,IAAI,MAAQ,SAAS,IAAiB,OAAQ,EAA0B,IAAI,KAAK;OAC5E,IAAI,MAAQ,YAAY,IAAiB,OAAQ,EAA6B,IAAI,KAAK;OACvF;GACH,IAAM,IAAS,GAET,KAAW,MACf,GAAQ,SAAS,GAAQ,eAAe,IACpC,IACJ,iBAAiB,CAAI,CAAC,CAAC,iBAAiB,cAAc,MAAM,YACxD,CAAC,EAAQ,EAAO,gBAAgB,EAAE,CAAC,IACnC,MAAM,KAAK,EAAO,SAAS,CAAO;GACxC,IAAiB,KAAK,IAAI,GAAG,GAAG,EAAO,KAAK,MAAU,EAAM,KAAK,CAAC,CAAC,MAAM,CAAC;EAC5E;CACF;CAKA,IAAM,IAAgB,EAAK,SAAS,IAAI,GAAe,CAAI,IAAI,GAC3D;CACJ,IAAI,MAAQ,YAAY;EACtB,IAAM,IAAW,GACX,IAAQ,EAAS,SAAS,IAS1B,IAAe,GAAgB,IAAI,CAAQ,GAI3C,IAAe,KAAM,SAAS,IAAI,GAClC,IACJ,MAAiB,KAAA,KAAa,IAAe,IACzC,GAAc,GAAO,CAAY,IAAI,IACrC,MAAU,KACR,IACA,EAAM,MAAM,UAAU,CAAC,CAAC,QAC1B,IACJ,iBAAiB,CAAI,CAAC,CAAC,iBAAiB,cAAc,MAAM,YACxD,IACA,OAAO,EAAS,IAAI,KAAK,GACzB,IAAQ,KAAK,IAAI,GAAW,CAAY;EAG9C,IAAkB,IAAQ,KAAK,IAAI,GAAG,IAAQ,CAAC,IAAI,EAAM;CAC3D,OAAO,AAGL,IAHS,IACS,KAAK,IAAI,GAAG,CAAa,IAEzB;CAOpB,IAAM,oBAAc,IAAI,IAAyB,GAC3C,IAA4B,CAAC;CACnC,KAAK,IAAM,KAAO,EAAI,OACpB,AAAI,EAAI,OAAO,kBAAkB,IAAM,EAAY,IAAI,EAAI,QAAQ,CAAG,IACjE,EAAY,KAAK,CAAG;CAE3B,IAAM,IAAyB,CAAC;CAChC,KAAK,IAAI,IAAI,GAAG,IAAI,EAAgB,QAAQ,KAAK;EAC/C,IAAM,IAAK,EAAgB,IACrB,IAAM,EAAY,IAAI,CAAE;EAC9B,IAAI,GAAK,EAAS,KAAK,CAAG;OACrB,IAAI,EAAM,OAAO,eAAe;GACnC,IAAM,IAAQ,GAAU,GAAI,GAAgB,GAAa,CAAc;GACvE,AAAI,KAAO,EAAS,KAAK,CAAK;EAChC;CACF;CACA,AAAI,EAAY,SAAS,MACvB,EAAS,KAAK,GAAG,CAAW,GAC5B,EAAS,MAAM,GAAG,MAChB,EAAE,OAAO,wBAAwB,EAAE,MAAM,IAAI,KAAK,8BAA8B,KAAK,CACvF;CAEF,IAAM,IAAmB;EACvB,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA,WAAW;GAAE,GAAG;GAAG,GAAG;GAAG,OAAO;GAAgB,QAAQ;EAAgB;EACxE,iBAAiB;EACjB,iBAAiB,EAAW;CAC9B;CAEA,CADI,EAAI,SAAS,MAAM,MAAM,MAAM,CAAC,KAAK,EAAI,MAAM,SAAS,OAAG,EAAK,WAAW,EAAI,WAC/E,EAAI,eAAe,SAAS,MAC9B,EAAK,iBAAiB,EAAI,gBAC1B,EAAK,aAAa,EAAI,MAAM,KAAK,GAAG,MAAM,EAAI,YAAY,MAAM,EAAE;CAEpE,IAAM,IAAa,GAAe,CAAG;CAErC,OADI,EAAW,SAAS,MAAG,EAAK,aAAa,IACtC;AACT;AAOA,SAAS,GACP,GACA,GACA,GACY;CACZ,IAAM,IAAU,GAAkB,GAAM,CAAI,GACtC,IAAQ,GAAS,SAAS,CAAC,GAC3B,IAAO,EAAM,KAAK,IAAI;CAM5B,AALA,EAAM,aAAa,QAKf,EAAM,UAAU,KAAA,KAAa,EAAM,MAAM,SAAS,YACpD,EAAM,QAAQ,EAAE,MAAM,cAAc;CAMtC,IAAM,IAAW,MAAM,KAAK,EAAE,QAAQ,EAAK,OAAO,SAAS,IAAI,EAAM,QAAQ,GACvE,IAAiB,GAAmB,GAAM,GAAU,EAAM,QAAQ,GAClE,IAAkB,EAAM,QACxB,IAAmB;EACvB,QAAQ;EACR;EACA,UAAU,CAAC;EACX;EACA;EACA;EACA,WAAW;GAAE,GAAG;GAAG,GAAG;GAAG,OAAO;GAAgB,QAAQ;EAAgB;EACxE,iBAAiB;EACjB,iBAAiB,EAAW;CAC9B;CACA,AAAI,EAAM,WAAW,MAAG,EAAK,WAAW;CACxC,IAAM,IAAO,GAAS,QAAQ,CAAC;CAC/B,IAAI,EAAK,SAAS,KAAK,EAAK,SAAS,GAAG;EAEtC,IAAM,IAAsB,CAAC,CAAC;EAC9B,KAAK,IAAM,KAAQ,GAAO,EAAU,KAAK,EAAU,EAAU,SAAS,KAAM,EAAK,SAAS,CAAC;EAC3F,IAAM,IAAa,MAAM,KAAK,EAAE,QAAQ,EAAK,OAAO,SAAS,EAAE;EAoB/D,AAnBA,EAAK,iBAAiB,EAAK,KAAK,OAAS;GACvC,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,QAAQ;GACR,OAAO,EAAI,MAAM;GACjB,iBAAiB,EAAI,MAAM;GAC3B,YAAY,EAAI,MAAM,cAAc;GACpC,WAAW,EAAI,MAAM,aAAa;GAClC,oBAAoB,EAAI,MAAM,sBAAsB;EACtD,EAAE,GACF,EAAK,SAAS,GAAK,MAAU;GAC3B,IAAM,IAAO,EAAM,EAAI;GACvB,IAAI,MAAS,KAAA,GAAW;GACxB,IAAM,IAAO,KAAK,IAAI,GAAG,EAAI,KAAK,GAC5B,IAAK,KAAK,IAAI,EAAK,QAAQ,EAAI,GAAG;GACxC,KAAK,IAAI,IAAM,GAAM,IAAM,GAAI,KAAO,EAAW,EAAU,EAAI,QAAS,KAAO;EACjF,CAAC,GACD,EAAK,aAAa;CACpB;CACA,OAAO;AACT;AAUA,IAAM,qBAAuB,IAAI,IAAI,kIA2BrC,CAAC;AAID,SAAS,GAAgB,GAAa,GAAyB;CAC7D,OAAO,MAAY,GAAqB,IAAI,EAAG,OAAO,IAAI,WAAW;AACvE;AAIA,SAAS,GAAY,GAAa,GAA0B;CAC1D,IAAM,IAAW,GAAgB,GAAI,CAAO;CAC5C,OAAO,MAAa,YAAY,MAAa;AAC/C;AAKA,SAAS,GAAe,GAAa,GAA0B;CAC7D,IAAM,IAAW,GAAgB,GAAI,CAAO;CAC5C,OAAO,EAAS,WAAW,QAAQ,KAAK,MAAa;AACvD;AAOA,SAAS,GAAU,GAAwB;CACzC,IAAM,IAAK,iBAAiB,CAAE;CAQ9B,OAPI,EAAG,YAAY,SAAe,SAC9B,EAAG,aAAa,cAAc,EAAG,aAAa,UAAgB,gBAI9D,GAAgB,EAAG,OAAO,IAAU,UACpC,GAAY,GAAI,EAAG,OAAO,KAAK,GAAe,GAAI,EAAG,OAAO,IAAU,WACnE;AACT;AA+CA,SAAS,GACP,GACA,GACA,GACA,GACS;CACT,IAAM,IAAe;EACnB,OAAO,CAAC;EACR,UAAU,CAAC;EACX,YAAY,CAAC;EACb,cAAc,CAAC;EACf,aAAa,CAAC;EACd,gBAAgB,CAAC;EACjB,OAAO,CAAC;CACV;CASA,OARI,IAAO,GAAa,GAAO,GAAU,GAAK,CAAG,IAC5C,GAAW,GAAI,GAAU,GAAK,CAAG,GAClC,EAAI,WAIC,IAEF,GAAa,CAAG;AACzB;AAEA,SAAS,GAAW,GAAa,GAAkB,GAAiB,GAAoB;CAIlF,GAAiB,EAAG,OAAO,KAC/B,GAAa,MAAM,KAAK,EAAG,UAAU,GAAG,GAAU,GAAK,CAAG;AAC5D;AAEA,SAAS,GAAa,GAAoB,GAAkB,GAAiB,GAAoB;CAE/F,IAAM,UAAuB;EAC3B,IAAI,IAAQ;EACZ,KAAK,IAAI,IAAI,EAAI,MAAM,SAAS,GAAG,KAAK,KAAK,EAAI,MAAM,OAAO,MAAM,KAClE,KAAS,EAAI,SAAS;EAExB,OAAO;CACT;CACA,KAAK,IAAM,KAAQ,GACjB,IAAI,EAAK,aAAa,KAAK,WAAW;EACpC,IAAI,EAAI,UAAU;GAIhB,IAAM,IAAO,EAAK,eAAe,IAC7B,IAAS;GACb,KAAK,IAAM,KAAM,GAAM;IACrB,IAAM,IAAK;IAEX,IADA,KAAU,EAAG,QACT,MAAO,MAAM;KACf,IAAI,EAAK,OAAY,MAAM;KAC3B,EAAS,GAAK,MAAM,GAAG,GAAc,CAAE;IACzC,OAAO,IAAI,MAAO,MAChB,EAAS,GAAK,MAAM,GAAG,GAAc,CAAE;SAClC,IAAI,MAAO,KAAM;KACtB,IAAM,KAAU,KAAK,MAAM,EAAO,IAAI,EAAI,OAAO,IAAI,KAAK,EAAI;KAC9D,KAAK,IAAI,IAAQ,EAAO,GAAG,IAAQ,GAAQ,KACzC,EAAS,GAAK,KAAK,GAAG,GAAc,CAAE;IAE1C,OACE,EAAS,GAAK,GAAI,IAAI,GAAU,GAAc,CAAE;GAEpD;EACF,OAAO;GAGL,IAAI,IAAS,GACT,IAAU;GACd,KAAK,IAAM,KAAM,EAAK,eAAe,IAAI;IACvC,IAAM,IACJ,MAAO,OAAO,MAAO,OAAQ,MAAO,QAAQ,MAAO,QAAQ,MAAO;IAIpE,AAHK,IACK,KAAS,EAAS,GAAK,KAAK,IAAI,GAAU,GAAc,CAAM,IADtD,EAAS,GAAK,GAAI,IAAI,GAAU,GAAc,CAAM,GAEtE,IAAU,GACV,KAAU,EAAG;GACf;EACF;CACF,OAAO,IAAI,EAAK,aAAa,KAAK,cAAc;EAC9C,IAAM,IAAQ;EACd,IAAI,EAAM,YAAY,MAAM;GAC1B,EAAS,GAAK,MAAM,GAAG,MAAM,EAAE;GAC/B;EACF;EAEA,IAAM,IAAK,iBAAiB,CAAK;EAGjC,IAAI,EAAG,YAAY,UAAU,EAAG,aAAa,cAAc,EAAG,aAAa,SAAS;EAGpF,IAAI,GAAe,GAAO,EAAG,OAAO,GAAG;GACrC,IAAM,IAAM,GAAU,GAAO,EAAI,gBAAgB,EAAI,aAAa,EAAI,cAAc;GACpF,AAAI,MACF,EAAI,YAAY,IAChB,EAAS,GAAA,KAAyB,GAAG,MAAM,EAAE,GAC7C,EAAI,MAAM,KAAK,CAAG;GAEpB;EACF;EAGA,IAAI,CAAC,GAAY,GAAO,EAAG,OAAO,GAAG;GACnC,GAAsB,CAAK;GAC3B;EACF;EACA,IAAM,IAAgB,GACpB,EAAG,eACH,WAAW,EAAG,QAAQ,KAAK,EAAI,gBAC/B,EAAI,mBACN,GAOM,IAAU,GAAe,EAAG,aAAa,EAAI,cAAc,GAC3D,IAAW,GAAe,EAAG,cAAc,EAAI,cAAc;EACnE,EAAI,eAAe,KAAK;GACtB,SAAS;GACT,UAAU;GACV;GACA;GACA,QAAQ,EAAG,aAAa,WAAW,OAAO,GAAa,GAAI,EAAI,cAAc;GAC7E,OAAO,EAAG;GACV,iBAAiB,GAAmB,EAAG,eAAe,IAAI,KAAA,IAAY,EAAG;GACzE,YAAY,EAAG;GACf,WAAW,EAAG;GACd,oBAAoB,EAAG;EACzB,CAAC;EACD,IAAM,IAAc,EAAI,eAAe,SAAS;EAEhD,KAAK,IAAI,IAAI,GAAG,IAAI,GAAS,KAE3B,AADA,EAAI,YAAY,EAAI,MAAM,UAAU,GACpC,EAAS,GAAA,KAAiB,GAAG,MAAM,EAAE;EAEvC,IAAM,IAAQ,EAAI,MAAM;EACxB,GAAW,GAAO,GAAe,GAAK,CAAG;EAGzC,KAAK,IAAI,IAAI,GAAO,IAAI,EAAI,MAAM,QAAQ,KACxC,AAAI,EAAI,YAAY,OAAO,KAAA,MAAW,EAAI,YAAY,KAAK;EAC7D,KAAK,IAAI,IAAI,GAAG,IAAI,GAAU,KAE5B,AADA,EAAI,YAAY,EAAI,MAAM,UAAU,GACpC,EAAS,GAAA,KAAiB,GAAG,MAAM,EAAE;CAEzC;AAEJ;AAKA,SAAS,GAAe,GAAe,GAAgC;CACrE,IAAI,CAAC,KAAS,EAAM,SAAS,GAAG,GAAG,OAAO;CAC1C,IAAM,IAAK,WAAW,CAAK;CAC3B,OAAO,OAAO,SAAS,CAAE,IAAI,KAAK,IAAI,GAAG,EAAU,GAAI,CAAc,CAAC,IAAI;AAC5E;AAOA,SAAS,GAAa,GAAyB,GAAgD;CAC7F,IAAM,KAAQ,MAAiC;EAC7C,IAAI,CAAC,KAAS,MAAU,UAAU,EAAM,SAAS,GAAG,GAAG,OAAO;EAC9D,IAAM,IAAK,WAAW,CAAK;EAC3B,OAAO,OAAO,SAAS,CAAE,IAAI,EAAU,GAAI,CAAc,IAAI;CAC/D;CACA,OAAO;EAAE,KAAK,EAAK,EAAG,GAAG;EAAG,OAAO,EAAK,EAAG,KAAK;EAAG,QAAQ,EAAK,EAAG,MAAM;EAAG,MAAM,EAAK,EAAG,IAAI;CAAE;AAClG;AAKA,SAAS,GAAa,GAAuB;CAC3C,IAAM,IAAkB,CAAC,GACnB,IAAqB,CAAC,GACtB,IAA8B,CAAC,GAC/B,IAAyB,CAAC,GAC1B,IAAwB,CAAC,GACzB,UAAkB;EACtB,IAAI,IAAI,EAAM;EACd,OAAO,IAAI,KAAK,EAAM,IAAI,OAAO,OAAM;EACvC,OAAO;CACT,GACM,UAAoB;EACxB,OAAO,EAAM,SAAS,EAAU,KAAK,EAAM,EAAM,SAAS,OAAO,MAK/D,AAJA,EAAM,IAAI,GACV,EAAS,IAAI,GACb,EAAW,IAAI,GACf,EAAa,IAAI,GACjB,EAAY,IAAI;CAEpB;CACA,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,MAAM,QAAQ,KAAK;EACzC,IAAM,IAAK,EAAI,MAAM;EACrB,IAAI,MAAO,KAAK;GAMd,IAAI,IAAW,EAAM,SAAS;GAC9B,OAAO,KAAY,KAAK,EAAM,OAAA,MAA0B;GAExD,IADoB,IAAW,KAAK,EAAM,OAAc,QACrC,EAAM,OAAc,KAAK;EAC9C,OAAO,AAAI,MAAO,QAChB,EAAY;EAMd,AAJA,EAAM,KAAK,CAAE,GACb,EAAS,KAAK,EAAI,SAAS,EAAG,GAC9B,EAAW,KAAK,EAAI,WAAW,MAAM,IAAI,GACzC,EAAa,KAAK,EAAI,aAAa,MAAM,EAAE,GAC3C,EAAY,KAAK,EAAI,YAAY,MAAM,EAAE;CAC3C;CAKA,OAJA,EAAY,GAIL;EACL;EACA;EACA;EACA;EACA;EACA,gBAAgB,EAAI;EACpB,OAAO,EAAI;CACb;AACF;AAEA,SAAS,EAAS,GAAc,GAAY,GAAiB,GAAqB,GAAgB;CAIhG,AAHA,EAAI,MAAM,KAAK,CAAE,GACjB,EAAI,SAAS,KAAK,CAAO,GACzB,EAAI,WAAW,KAAK,CAAM,GAC1B,EAAI,aAAa,KAAK,CAAM;AAC9B;AAKA,SAAS,GAAe,GAA+B;CACrD,IAAM,IAAwB,CAAC,GAC3B,IAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,IAAI,EAAI,MAAM,QAAQ,KAAK;EACzC,IAAM,IAAK,EAAI,MAAM,IACf,IAAO,EAAI,WAAW,IACtB,IAAS,EAAI,aAAa,IAC1B,IAAO,EAAK,EAAK,SAAS;EAMhC,AALI,MACE,KAAQ,EAAK,SAAS,KAAQ,EAAK,SAAS,EAAK,WAAW,IAC9D,EAAK,UAAU,EAAG,SACf,EAAK,KAAK;GAAE;GAAO,QAAQ,EAAG;GAAQ;GAAM;EAAO,CAAC,IAE3D,KAAS,EAAG;CACd;CACA,OAAO;AACT;AAEA,SAAS,GAAmB,GAAc,GAAoB,GAA0B;CACtF,IAAI,IAAM,GACN,IAAY;CAChB,KAAK,IAAI,IAAI,GAAG,KAAK,EAAK,QAAQ,KAChC,CAAI,MAAM,EAAK,UAAU,EAAK,OAAO,UACnC,IAAM,KAAK,IAAI,GAAK,EAAY,GAAW,GAAG,GAAU,CAAQ,CAAC,GACjE,IAAY,IAAI;CAGpB,OAAO;AACT;AAEA,SAAS,GAAe,GAAsB;CAC5C,OAAO,GAAc,CAAI,CAAC,CAAC;AAC7B;AAEA,SAAS,GAAsB,GAAmB;CAChD,EACE,GACA,gIAEF;AACF;AAGA,SAAgB,GAAc,GAAsB;CAClD,OAAO,MAAM,KAAK,EAAG,UAAU,CAAC,CAAC,MAC9B,MAAU,EAAM,aAAa,KAAK,aAAa,eAAe,KAAK,EAAM,eAAe,EAAE,CAC7F;AACF;AAKA,IAAa,KACX;AAKF,SAAgB,GAAiB,GAAsB;CACrD,OAAO,MAAQ,WAAW,MAAQ,YAAY,MAAQ;AACxD;AAKA,SAAS,GAAgB,GAAa,GAAwB;CACvD,GAAc,CAAE,MACrB,EAAK,cAAc,IACnB,EAAS,GAAI,EAAmB;AAClC;;;AC/vBA,IAAM,KAAkB,u5FAiDlB,KAAiB,QAKjB,KAAgB,OAKhB,KAAqB,8BAuBrB,KAAc,0EAEd,KAA0B;CAC9B;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,GASM,KAAqB,uEAKrB,KAAoB,KAIpB,KAAmB,KAEnB,KAAwB,GAExB,KAAmB,GAEnB,KAAgB,GAIhB,KAAoB,KAEpB,KAAqB,KAMrB,KACJ,OAAO,cAAgB,MAAc,MAAM,CAAC,IAAI,aAGrC,KAAb,MAAa,UAAwB,GAAgB;CACnD,OAAO,qBAAqB,CAAC,UAAU,OAAO;CAS9C,OAAO,qBAAa,IAAI,IAAqB;CAC7C,OAAO,KAAwC;CAE/C,OAAO,WAAmC;EACxC,KAAK,IAAM,KAAQ,EAAgB,IAAY,EAAK,IAAgB;CACtE;CAEA,OAAO,GAAkB,GAAkB;EACzC,AAAI,aAAgB,mBAAmB,EAAK,QAAQ,gBAAgB,CAAC,EAAK,SACxE,EAAK,iBAAiB,QAAQ,EAAgB,IAAsB,EAAE,MAAM,GAAK,CAAC;CAEtF;CAEA,OAAO,GAAW,GAA6B;EAE7C,IADA,EAAgB,GAAW,IAAI,CAAI,GAC/B,EAAgB,IAAc;EAGlC,KAAK,IAAM,KAAQ,SAAS,iBAAiB,sBAAsB,GACjE,EAAgB,GAAkB,CAAI;EAExC,IAAM,IAAU,IAAI,kBAAkB,MAAY;GAChD,KAAK,IAAM,KAAU,GACnB,KAAK,IAAM,KAAQ,EAAO,YAAY,EAAgB,GAAkB,CAAI;GAE9E,EAAgB,GAAqB;EACvC,CAAC;EAED,AADA,EAAQ,QAAQ,SAAS,MAAM;GAAE,WAAW;GAAM,SAAS;GAAM,eAAe;EAAK,CAAC,GACtF,EAAgB,KAAe;CACjC;CAEA,OAAO,GAAa,GAA6B;EAE/C,AADA,EAAgB,GAAW,OAAO,CAAI,GAClC,EAAgB,GAAW,SAAS,MACtC,EAAgB,IAAc,WAAW,GACzC,EAAgB,KAAe;CAEnC;CAEA;CACA;CACA;CACA,KAAyC;CACzC,KAA6C;CAC7C,KAAiB;CACjB,KAAmC;CACnC,KAAiC;CACjC,KAAgD;CAChD,KAAiD;CACjD,KAAgB;CAEhB,KAA6B,CAAC;CAC9B,qBAAgB,IAAI,IAA4C;CAMhE,qBAAiB,IAAI,QAAyB;CAO9C,KAAiC;CACjC,KAA+B;CAI/B,KAAmB;CACnB,KAA2C;CAI3C,KAAuC;CAKvC,KAAe;CAIf,KAA6B,CAAC;CAK9B,KAAyB;EACvB,KAAK,IAAmB,QAAQ,MAAM;GACpC,WAAW;GACX,SAAS;GACT,eAAe;GACf,YAAY;GAGZ,iBAAiB;IACf;IACA;IACA;IACA;IACA;IACA,GAAG,GAAuB;GAC5B;EACF,CAAC;CACH;CAEA,cAAc;EAqBZ,AApBA,MAAM,GACN,KAAK,KAAU,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC,GACjD,KAAK,GAAQ,YAAY,IACzB,KAAK,KAAQ,KAAK,GAAQ,eAAe,MAAM,GAS/C,KAAK,KAAS,SAAS,cAAc,MAAM,GAC3C,KAAK,GAAO,aAAa,eAAe,MAAM,GAC9C,KAAK,GAAO,aAAa,iBAAiB,EAAE,GAC5C,KAAK,GAAO,MAAM,UAChB,yQAIF,KAAK,GAAO,cAAc,IAAI,OAAO,GAAG;CAC1C;CAEA,oBAA0B;EAiDxB,AA9CK,KAAK,aAAa,QAAQ,KAAG,KAAK,aAAa,UAAU,EAAc,GACvE,KAAK,aAAa,OAAO,KAAG,KAAK,aAAa,SAAS,EAAa,GAErE,KAAK,GAAO,eAAe,QAAM,KAAK,YAAY,KAAK,EAAM,GAEjE,KAAK,KAAkB,IAAI,qBAAqB,KAAK,IAAgB,CAAC,GACtE,KAAK,GAAgB,QAAQ,IAAI,GACjC,KAAK,GAAqB,GAO1B,KAAK,GAAgB,QAAQ,KAAK,EAAM,GAKxC,OAAO,iBAAiB,UAAU,KAAK,GAAe,GAKtD,KAAK,KAAoB,IAAI,uBAAuB,KAAK,IAAgB,CAAC,GAC1E,KAAK,GAAiB,GAItB,KAAK,KAA2B,SAA2B;GAEzD,AADA,KAAK,GAAiB,GACtB,KAAK,IAAgB;EACvB,CAAC,GACD,KAAK,KAA4B,QAA4B,KAAK,IAAgB,CAAC,GAUnF,SAAS,OAAO,MAAM,KAAK,KAAK,GAAc,CAAC,CAAC,OAAO,MAAiB;GACtE,QAAQ,KAAK,2CAA2C,CAAG;EAC7D,CAAC,GACD,SAAS,OAAO,iBAAiB,eAAe,KAAK,GAAc;EAMnE,KAAK,IAAM,KAAO,IAChB,KAAK,iBAAiB,GAAK,KAAK,GAAwB;EA0C1D,AApCA,KAAK,iBAAiB,iBAAiB,KAAK,GAAgB,GAC5D,KAAK,iBAAiB,iBAAiB,KAAK,GAAiB,GAC7D,KAAK,iBAAiB,oBAAoB,KAAK,GAAiB,GAOhE,KAAK,iBAAiB,eAAe,KAAK,EAAc,GACxD,KAAK,iBAAiB,gBAAgB,KAAK,GAAe,GAC1D,KAAK,iBAAiB,eAAe,KAAK,GAAc,GAGxD,KAAK,iBAAiB,UAAU,KAAK,IAAW;GAAE,SAAS;GAAM,SAAS;EAAK,CAAC,GAChF,KAAK,iBAAiB,aAAa,KAAK,IAAc,EAAE,SAAS,GAAK,CAAC,GACvE,KAAK,iBAAiB,SAAS,KAAK,IAAU,EAAE,SAAS,GAAM,CAAC,GAIhE,KAAK,iBAAiB,QAAQ,KAAK,EAAO,GAG1C,KAAK,iBAAiB,aAAa,KAAK,GAAY,GACpD,KAAK,iBAAiB,WAAW,KAAK,GAAU,GAChD,SAAS,iBAAiB,mBAAmB,KAAK,GAAkB,GAGpE,OAAO,iBAAiB,aAAa,KAAK,GAAY,GACtD,OAAO,iBAAiB,iBAAiB,KAAK,GAAY,GAI1D,SAAS,iBAAiB,UAAU,KAAK,KAAc;GAAE,SAAS;GAAM,SAAS;EAAK,CAAC,GAEvF,EAAgB,GAAW,IAAI,GAC/B,KAAK,IAAgB;CACvB;CAEA,uBAA6B;EAU3B,AATA,OAAO,oBAAoB,UAAU,KAAK,GAAe,GACzD,KAAK,IAAiB,WAAW,GACjC,KAAK,IAAmB,WAAW,GACnC,KAAK,KAAkB,MACvB,KAAK,KAAoB,MACzB,KAAK,KAA2B,GAChC,KAAK,KAA2B,MAChC,KAAK,KAA4B,GACjC,KAAK,KAA4B,MACjC,SAAS,OAAO,oBAAoB,eAAe,KAAK,GAAc;EACtE,KAAK,IAAM,KAAO,IAChB,KAAK,oBAAoB,GAAK,KAAK,GAAwB;EAe7D,AAbA,KAAK,oBAAoB,iBAAiB,KAAK,GAAgB,GAC/D,KAAK,oBAAoB,iBAAiB,KAAK,GAAiB,GAChE,KAAK,oBAAoB,oBAAoB,KAAK,GAAiB,GACnE,KAAK,MAAqB,GAC1B,KAAK,oBAAoB,eAAe,KAAK,EAAc,GAC3D,KAAK,oBAAoB,gBAAgB,KAAK,GAAe,GAC7D,KAAK,oBAAoB,eAAe,KAAK,GAAc,GAC3D,KAAK,oBAAoB,UAAU,KAAK,IAAW,EAAE,SAAS,GAAK,CAAC,GACpE,KAAK,oBAAoB,aAAa,KAAK,IAAc,EAAE,SAAS,GAAK,CAAC,GAC1E,KAAK,oBAAoB,SAAS,KAAK,EAAQ,GAC/C,KAAK,oBAAoB,QAAQ,KAAK,EAAO,GAC7C,KAAK,oBAAoB,WAAW,KAAK,GAAU,GACnD,KAAK,oBAAoB,aAAa,KAAK,GAAY,GACvD,SAAS,oBAAoB,mBAAmB,KAAK,GAAkB;EACvE,KAAK,IAAM,KAAS,KAAK,GAAc,OAAO,GAAG,aAAa,CAAK;EAYnE,AAXA,KAAK,GAAc,MAAM,GACzB,KAAK,KAAa,MAClB,KAAK,KAAc,MACnB,OAAO,oBAAoB,aAAa,KAAK,GAAY,GACzD,OAAO,oBAAoB,iBAAiB,KAAK,GAAY,GAC7D,SAAS,oBAAoB,UAAU,KAAK,KAAc,EAAE,SAAS,GAAK,CAAC,GAC3E,KAAK,KAAe,MACpB,KAAK,KAAe,MACpB,KAAK,KAAY,IACjB,KAAK,KAAa,IAClB,KAAK,IAAqB,GAC1B,EAAgB,GAAa,IAAI;CACnC;CAIA,qBAAW,IAAI,IAAa;CAC5B,qBAAW,IAAI,IAAa;CAC5B,KAA+B;CAC/B,KAAY;CACZ,KAAa;CACb,KAAgD;CAChD,KAAY;CACZ,KAAY;CACZ,KAAoD;CACpD,OAAO,KAAgB,OAAO,aAAe,MAAc,OAAO,WAAW,gBAAgB;CAK7F,KAAuB;EAErB,IAAI,KAAK,MAAiB,KAAK,IAAgB;EAC/C,KAAK,KAAgB;EAGrB,IAAI,IAAO,IACL,UAAkB;GACtB,IAAI,GAAM;GAEV,AADA,IAAO,IACP,KAAK,KAAgB;GACrB,IAAM,IAAU,KAAK;GACjB,AAAC,KAAK,eAAgB,KAAK,MAAgB,MAC/C,KAAK,GAAmB,CAAO,GAC/B,KAAK,KAAa,CAAC,GAAU,KAAK,IAAa,KAAK,IAAO,KAAK,IAAiB,CAAC,GAElF,KAAK,IAAqB;EAC5B;EAEA,AADA,sBAAsB,CAAG,GACzB,WAAW,GAAK,EAAE;CACpB;CAMA,GAAmB,GAAsB,GAAiC;EACxE,KAAK,IAAM,KAAQ,KAAK,IAAc;GACpC,IAAM,IAAK,EAAK,QACV,EAAE,SAAM,YAAS,EAAK,aACtB,IAAQ,GAAU,IAAI,CAAE;GAC9B,EAAK,SAAS,IACV;IACE,GAAG,EAAM,OAAO,IAAO,KAAK,IAAI,EAAM,GAAG,CAAI;IAC7C,GAAG,EAAM,OAAO,IAAO,KAAK,IAAI,EAAM,GAAG,CAAI;GAC/C,IACA,KAAK,GAAU,GAAM,CAAO;EAClC;CACF;CAIA,GAAU,GAAkB,GAAgD;EAC1E,IAAM,IAAK,EAAK,QACV,EAAE,SAAM,YAAS,EAAK,aACtB,IAAO,EAAK,UAAU;GAAE,GAAG;GAAG,GAAG;EAAE;EACzC,OAAO;GACL,GAAG,GAAY,GAAI,KAAK,EAAQ,OAAO,GAAM,EAAK,CAAC;GACnD,GAAG,GAAY,GAAI,KAAK,EAAQ,QAAQ,GAAM,EAAK,CAAC;EACtD;CACF;CAQA,KAAsC;EACpC,IAAM,oBAA2B,IAAI,IAAI,GACnC,IAAU,KAAK;EACrB,IAAI,CAAC,GAAS,OAAO;EACrB,KAAK,IAAM,KAAQ,KAAK,IAAc;GACpC,IAAM,IAAK,EAAK,QACV,EAAE,SAAM,YAAS,EAAK,aACtB,EAAE,MAAG,SAAM,KAAK,GAAU,GAAM,CAAO;GAC7C,EAAS,IAAI,GAAI;IACf,KAAK,EAAG;IACR,MAAM,EAAG;IACT;IACA;IACA,MAAM,IAAO,KAAK,KAAK;IACvB,MAAM,IAAO,KAAK,KAAK;GACzB,CAAC;EACH;EACA,OAAO;CACT;CASA,GAAwB,GAAgC;EACtD,KAAK,IAAM,KAAQ,KAAK,IAAc;GACpC,IAAM,IAAK,EAAK,QACV,IAAQ,EAAS,IAAI,CAAE;GACxB,MACL,EAAQ,WACR,EAAQ,YACR,EAAG,YAAY,EAAM,OAAO,EAAG,eAAe,EAAM,KACpD,EAAG,aAAa,EAAM,OAAO,EAAG,cAAc,EAAM;EACtD;CACF;CAGA,GAAa,GAAiB,GAAqB;EAEjD,AADA,aAAa,KAAK,GAAc,IAAI,CAAE,CAAC,GACvC,KAAK,GAAc,IACjB,GACA,iBAAiB,KAAK,GAAQ,CAAE,GAAG,CAAK,CAC1C;CACF;CAEA,MAAa,MAAuB;EAClC,IAAM,IAAS,EAAM;EACjB,AAAE,aAAkB,eAAgB,MAAW,QAC9C,EAAO,aAAa,gBAAgB,MACzC,KAAK,GAAe,GAEhB,OAAK,IAAI,KAAK,KAAK,GAAe,IAAI,CAAM,KAAK,KAAK,QAG1D,aAAa,KAAK,GAAc,IAAI,CAAM,CAAC,GACrC,iBAAiB,UAAS,KAAK,GAAa,GAAQ,EAAkB;CAC9E;CAEA,MAAgB,MAAuB;EACrC,IAAM,IAAS,EAAM;EACjB,AAAE,aAAkB,eAAgB,MAAW,QAC9C,EAAO,aAAa,gBAAgB,MAGrC,KAAK,IAAI,KAAK,KAAK,GAAe,IAAI,CAAM,KAAK,KAAK,MAC1D,KAAK,GAAa,GAAQ,EAAiB;CAC7C;CASA,GAAQ,GAAuB;EAC7B,IAAI,KAAK,IAAY,OAAO,GAAI;EAIhC,KAAK,GAAe;EACpB,IAAM,IAAU,KAAK,IACf,IAAO,KAAK,GAAa,MAAM,MAAc,EAAU,WAAW,CAAE;EAC1E,IAAI,CAAC,KAAW,CAAC,GAAM;EACvB,IAAM,IAAQ,EAAK,aAEb,IAAQ,EAAK,UAAU,KAAK,GAAU,GAAM,CAAO,GACnD,IACJ,EAAM,MAAM,EAAM,OAAO,EAAG,eAAe,EAAG,eAAe,EAAM,IAAI,EAAQ,QAC3E,IAAO,EAAM,MAAM,EAAM,OAAO,EAAG,cAAc,EAAG,cAAc,EAAM,IAAI,EAAQ;EAC1F,CAAI,KAAK,IAAI,EAAG,YAAY,CAAG,IAAI,MAAO,KAAK,IAAI,EAAG,aAAa,CAAI,IAAI,OACzE,EAAG,SAAS;GAAE;GAAK;GAAM,UAAU;EAAU,CAAC;CAElD;CAOA,MAAY,MAAuB;EACjC,IAAI,KAAK,aAAa,QAAQ,MAAM,QAAQ;EAC5C,IAAM,IAAS,KAAK,IACd,IAAU,KAAK;EACrB,IAAI,CAAC,KAAU,CAAC,KAAW,KAAK,GAAa,WAAW,GAAG;EAC3D,IAAM,IAAI,GACJ,IAAQ,EAAE,cAAc,IAAI,EAAQ,SAAS,EAAE,cAAc,IAAI,KAAK,eAAe,GACrF,IAAK,EAAE,SAAS,GAChB,IAAK,EAAE,SAAS;EAKtB,IAAI,CAAC,EAAE,cAAc,KAAK,GAAkB,GAAI,CAAE,GAAG;EACrD,IAAM,EAAE,QAAK,WAAQ,KAAK,GAAQ,EAAE,SAAS,EAAE,SAAS,CAAO,GACzD,IAAM,KAAK,IAAI,GACf,IAAM,KAAK,IAAI,CAAE,IAAI,KAAK,IAAI,CAAE;EAItC,IAAI,MAAQ,GAAG;GAEb,AADA,KAAK,KAAc,MACnB,EAAE,eAAe;GACjB;EACF;EAGA,IAAM,KAAW,MAA8B;GAC7C,IAAM,IAAQ,EAAK,aACb,IAAK,EAAK;GAehB,OAdI,MAAO,KAAK,EAAM,OAAO,MAExB,IAAK,KAAK,EAAG,YAAY,EAAG,eAAe,EAAG,eAAe,MAC7D,IAAK,KAAK,EAAG,YAAY,OAI1B,MAAO,KAAK,EAAM,OAAO,MAExB,IAAK,KAAK,EAAG,aAAa,EAAG,cAAc,EAAG,cAAc,MAC5D,IAAK,KAAK,EAAG,aAAa;EAKjC,GAWM,IAAQ,KAAK,IACb,IAAO,KAAK,IAAI,CAAE,KAAK,KAAK,IAAI,CAAE,IAAI,MAAM,KAC5C,IAAO,MAAU,QAAQ,IAAM,EAAM,MAAM,OAAO,GAClD,IACJ,MAAU,SACT,KAAK,IAAI,EAAE,UAAU,EAAM,CAAC,IAAI,MAC/B,KAAK,IAAI,EAAE,UAAU,EAAM,CAAC,IAAI,KAC9B,IAAU,MAAU,QAAQ,EAAM,WAAW,IAC7C,IACJ,MAAU,QACV,IAAM,EAAM,KAAK,MACjB,MAAS,EAAM,SACd,IAAQ,KAAO,EAAM,MAAM,EAAE,KAAW,KACvC,IAA4B;EAChC,IAAI,GAAM;GAKR,IAHA,EAAM,UADS,KAAO,EAAM,OAAO,KAAO,EAAM,MAAM,KAC7B,EAAM,UAAU,IAAI,IAAU,EAAM,UAAU,GACvE,EAAM,MAAM,GACZ,EAAM,KAAK,GACP,CAAC,EAAM,IAAI;GACf,IAAS,KAAK,GAAa,MAAM,MAAS,EAAK,WAAW,EAAM,EAAE,KAAK;EACzE;EACA,IAAI,CAAC,GAAQ;GACX,IAAM,IAAQ,GAAS,GAAQ,GAAK,CAAG;GACvC,KAAK,IAAI,IAAI,EAAM,SAAS,GAAG,KAAK,GAAG,KAAK;IAC1C,IAAM,IAAO,EAAM,EAAE,CAAE;IACvB,IAAI,CAAC,EAAK,eAAe,GAAQ,EAAK,MAAM,GAAG;IAC/C,IAAI,EAAQ,CAAI,GAAG;KACjB,IAAS;KACT;IACF;IAGA,IAAM,IAAa,EAAK,MAAM;IAC9B,IAAK,MAAO,KAAK,CAAC,EAAW,KAAO,MAAO,KAAK,CAAC,EAAW,GAAI;KAC9D,IAAS;KACT;IACF;GACF;GAKA,IAAI,CAAC,KAAU,IAAM,IAAkB;IACrC,EAAE,eAAe;IACjB;GACF;GACA,KAAK,KAAc;IACjB,IAAI,IAAU,EAAO,SAAyB;IAC9C,GAAG,EAAE;IACL,GAAG,EAAE;IACL;IACA,IAAI;IACJ;IACA,SAAS;GACX;EACF;EAGA,IAFI,CAAC,MACL,EAAE,eAAe,GACb,CAAC,EAAQ,CAAM,IAAG;EACtB,IAAM,IAAK,EAAO,QACZ,IAAQ,EAAO,aACf,IAAyB,EAAE,UAAU,UAAU;EAOrD,AANI,MAAO,KAAK,EAAM,OAAO,MAAG,EAAM,MAAM,IACxC,MAAO,KAAK,EAAM,OAAO,MAAG,EAAM,OAAO,IAC7C,EAAG,SAAS,CAAK,GAGjB,KAAK,GAAe,IAAI,GAAI,CAAG,GAC/B,KAAK,GAAa,GAAI,EAAgB;CACxC;CAIA,GAAkB,GAAY,GAAqB;EACjD,OAAO,KAAK,GAAgB,MACzB,MACE,IAAK,KAAK,EAAG,YAAY,EAAG,eAAe,EAAG,eAAe,MAC7D,IAAK,KAAK,EAAG,YAAY,MACzB,IAAK,KAAK,EAAG,aAAa,EAAG,cAAc,EAAG,cAAc,MAC5D,IAAK,KAAK,EAAG,aAAa,EAC/B;CACF;CAOA,KAA6B;EAC3B,IAAM,IAAS,KAAK;EAChB,IAAC,KAAW,KAAK,IACrB;QAAK,GAAgB,QAAQ,CAAM;GACnC,KAAK,IAAM,KAAW,EAAO,UAC3B,AAAI,MAAY,QAAM,KAAK,GAAgB,QAAQ,CAAO;EAFzB;CAIrC;CAIA,GAAQ,GAAiB,GAAiB,GAAoD;EAC5F,IAAI,CAAC,KAAK,IAAa;GACrB,IAAM,IAAO,KAAK,GAAM,sBAAsB;GAC9C,KAAK,KAAc;IAAE,MAAM,EAAK;IAAM,KAAK,EAAK;GAAI;EACtD;EACA,OAAO;GACL,KAAK,KAAK,OAAO,IAAU,KAAK,GAAY,QAAQ,EAAQ,KAAK;GACjE,KAAK,KAAK,OAAO,IAAU,KAAK,GAAY,OAAO,EAAQ,MAAM;EACnE;CACF;CAMA,GAAc,GAAiB,GAAmC;EAChE,IAAM,IAAS,KAAK,IACd,IAAU,KAAK;EACrB,IAAI,CAAC,KAAU,CAAC,KAAW,KAAK,GAAa,WAAW,GAAG,OAAO;EAClE,IAAM,EAAE,QAAK,WAAQ,KAAK,GAAQ,GAAS,GAAS,CAAO,GACrD,IAAQ,GAAS,GAAQ,GAAK,CAAG;EACvC,KAAK,IAAI,IAAI,EAAM,SAAS,GAAG,KAAK,GAAG,KAAK;GAC1C,IAAM,EAAE,SAAM,MAAG,SAAM,EAAM,IACvB,IAAQ,EAAK;GACnB,IAAI,CAAC,KAAS,GAAQ,EAAK,MAAM,GAAG;GACpC,IAAM,IAAK,EAAK,QACV,EAAE,GAAG,GAAM,GAAG,MAAS,GAAkB,GAAM,GAAG,CAAC;GACzD,IACE,KACA,EAAM,OAAO,KACb,KAAO,EAAK,OACZ,IAAM,EAAK,MAAM,EAAK,SACtB,KAAO,EAAK,OACZ,IAAM,EAAK,MAAM,EAAK,KACtB;IACA,IAAM,IAAW,GAAU,EAAK,KAAK,EAAM,OAAO,EAAM,MAAM,CAAC,CAAC,CAAC,KAC3D,IAAc,KAAK,IAAI,IAAI,EAAK,MAAM,KAAY,EAAQ,MAAM;IACtE,OAAO;KACL;KACA,MAAM;KACN,aAAa;KACb,SAAS,EAAG;KACZ,QAAS,EAAM,OAAO,EAAQ,SAAU;IAC1C;GACF;GACA,IACE,KACA,EAAM,OAAO,KACb,KAAO,EAAK,OACZ,IAAM,EAAK,MAAM,EAAK,SACtB,KAAO,EAAK,OACZ,IAAM,EAAK,MAAM,EAAK,KACtB;IACA,IAAM,IAAW,GAAU,EAAK,KAAK,EAAM,OAAO,EAAM,MAAM,CAAC,CAAC,CAAC,KAC3D,IAAc,KAAK,IAAI,IAAI,EAAK,MAAM,KAAY,EAAQ,KAAK;IACrE,OAAO;KACL;KACA,MAAM;KACN,aAAa;KACb,SAAS,EAAG;KACZ,QAAS,EAAM,OAAO,EAAQ,QAAS;IACzC;GACF;EACF;EACA,OAAO;CACT;CAEA,MAAkB,MAAuB;EACvC,IAAI,GAAkB,CAAK,GAAG;EAC9B,IAAM,EAAE,YAAS,eAAY,GACvB,IAAO,KAAK;EAClB,IAAI,GAAM;GACR,IAAM,KAAS,EAAK,SAAS,MAAM,IAAU,KAAW,EAAK,aACvD,IAAS,EAAK,UAAU,IAAQ,EAAK;GAC3C,AAAI,EAAK,SAAS,MAAK,EAAK,GAAG,YAAY,IACtC,EAAK,GAAG,aAAa;GAC1B;EACF;EACA,IAAM,IAAA,GAAS,EAAuB,UAAU;EAOhD,AANI,KAAQ,KAAK,MACf,KAAK,IAAgB,KAAK,IAAkB,GAAS,CAAO,GAC1D,KAAQ,KAAK,MAAW,KAAK,IAAgB,KAAK,IAAW,GAAS,CAAO,GAC7E,KAAQ,KAAK,MAAgB,CAAC,KAAK,aAAa,kBAAkB,KACpE,KAAK,aAAa,oBAAoB,EAAE,GAE1C,KAAK,KAAe;GAAE,GAAG;GAAS,GAAG;EAAQ;EAI7C,IAAM,IAAU,KAAK;EACrB,IAAI,GAAS;GACX,IAAM,EAAE,QAAK,WAAQ,KAAK,GAAQ,GAAS,GAAS,CAAO;GAC3D,IAAI,MAAQ,KAAK,MAAa,MAAQ,KAAK,IAAW;EACxD;EACA,KAAK,IAAqB;CAC5B;CAEA,MAAW,MAAuB;EAChC,IAAM,EAAE,qBAAkB,GACpB,IAAS,KAAK,IACd,IAAQ,KAAK,IAAkB;EACjC,AAAC,KAAkB,KAAW,MAClC,EAAc,QAAQ,cAAc,GAAmB,GAAQ,CAAK,CAAC,GACrE,EAAM,eAAe;CACvB;CAKA,OAAgB,MAAuB;EACrC,IAAM,IAAI;EACV,IAAI,EAAE,WAAW,KAAK,KAAK,aAAa,QAAQ,MAAM,QAAQ;EAC9D,IAAM,IAAS,EAAE,aAAa,CAAC,CAAC,SAAS,KAAK,EAAK;EACnD,IAAI,CAAC,KAAU,CAAC,KAAK,IAAiB,EAAE,MAAM,GAAG;EACjD,IAAM,IAAc,KAAK,OAAqB,WAAW,KAAK,OAAqB;EACnF,IAAI,EAAE,UAAU,GAAG;GACjB,IAAI,EAAE,WAAW,GAAG;GACpB,KAAK,gBAAgB,EAAkB;GAMvC,IAAM,IAAU,KAAK,IAAe;GACpC,AAAI,MAAgB,CAAC,KAAU,OAC7B,GAAS,KAAK,GACd,KAAK,IAAe,CAAC;GAEvB;EACF;EACA,IAAI,CAAC,GAAa;EAClB,IAAM,IAAO,EAAE,WAAW,IAAI,SAAS,aACjC,IAAY,SAAS,aAAa,GAClC,IAAS,KAAK,IACd,IAAU,KAAK;EACrB,IAAI,CAAC,KAAa,CAAC,KAAU,CAAC,GAAS;EACvC,IAAM,EAAE,QAAK,WAAQ,KAAK,GAAQ,EAAE,SAAS,EAAE,SAAS,CAAO,GACzD,IAAS,KAAK,IAAQ,GAAK,GAAK,CAAI;EAC1C,IAAI,CAAC,GAAQ;GAKX,AADA,KAAK,gBAAgB,EAAkB,GACvC,KAAK,KAAmB;GACxB;EACF;EAOA,AAFA,EAAE,eAAe,GACjB,KAAK,IAAe,CAAC,EAAE,KAAK,GAC5B,KAAK,IAAU,CAAM;EAErB,IAAM,IACJ,EAAE,YAAY,EAAU,cAAc,KAAK,IAAkB,IACzD,GAAU;GAAE,MAAM,EAAU;GAAY,QAAQ,EAAU;EAAa,CAAC,IACxE;EAEN,AADA,KAAK,IAAe,GAAW,GAAQ,CAAM,GAC7C,KAAK,KAAmB;GAAE;GAAM;EAAO;CACzC;CAMA,OAAc,MAAuB;EACnC,IAAM,IAAI;EACV,IAAI,KAAK,aAAa,OAAO,MAAM,UAAU;EAC7C,IAAM,IAAY,GAAY,EAAE,GAAG;EACnC,IAAI,CAAC,KAAa,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU;EACpE,IAAM,IAAS,KAAK,IACd,IAAS,EAAE;EAEjB,IADI,CAAC,KAAU,EAAE,aAAkB,YAAY,MAAW,QACtD,GAAc,GAAQ,EAAE,KAAK,KAAK,IAAkB,CAAC,GAAG;EAC5D,IAAM,IAAQ,GAAe,CAAM,GAC7B,IAAU,GAAS,GAAO,CAAM;EACtC,IAAI,CAAC,GAAS;EACd,IAAM,IAAO,GACX,GACA,GACA,EAAM,QAAQ,MAAc,EAAU,YAAY,CAAM,CAC1D;EACK,MACL,EAAE,eAAe,GACjB,EAAsB,MAAM,EAAE,eAAe,GAAK,CAAC,GACnD,EAAK,eAAe;GAAE,OAAO;GAAW,QAAQ;EAAU,CAAC;CAC7D;CAKA,IACE,GACA,GACA,GACY;EACZ,IAAM,IAAyB,CAAC;EAChC,KAAK,IAAM,KAAS,MAAM,KAAK,KAAK,QAAQ,GAAG;GAC7C,IAAI,MAAU,KAAK,IAAQ;GAC3B,IAAM,IAAO,GAAU,GAAO,GAAgB,GAAS,CAAc;GACrE,AAAI,KAAM,EAAS,KAAK,CAAI;EAC9B;EASA,OARI,GAAc,IAAI,KACf,KAAK,aAAa,sBAAsB,KAC3C,QAAQ,KAAK,cAAc,MAAuB,GAAY,IAAI,CAAC,GAErE,KAAK,aAAa,wBAAwB,EAAE,KAE5C,KAAK,gBAAgB,sBAAsB,GAEtC;GACL,QAAQ;GACR,OAAO,GAAiB;GACxB;GACA,MAAM;GACN,gBAAgB;GAChB,iBAAiB;GACjB,WAAW;IAAE,GAAG;IAAG,GAAG;IAAG,OAAO;IAAG,QAAQ;GAAE;GAC7C,iBAAiB;GACjB,iBAAiB,EAAW;EAC9B;CACF;CAGA,MAAqC;EACnC,IAAM,IAAS,SAAS;EACxB,OAAO,aAAkB,eAAe,MAAW,SAAS,QAAQ,KAAK,SAAS,CAAM,IACpF,IACA;CACN;CAMA,MAA4B;EAC1B,OAAO,KAAK,MAAa,CAAC,KAAK;CACjC;CAIA,IAAiB,GAAqC;EACpD,OACE,aAAkB,WAClB,MAAW,QACX,KAAK,SAAS,CAAM,KACpB,CAAC,EAAO,QAAQ,EAAW;CAE/B;CAKA,IAAc,GAAa,GAAqB;EAC9C,IAAM,IAAO,KAAK,GAAM,YAAa,MAAM,IAAI,GACzC,IAAQ,EAAK,EAAE,EAAE,UAAU;EAEjC,OADU,KAAK,IAAI,GAAG,KAAK,IAAI,GAAK,EAAK,SAAS,CAAC,CAC5C,KAAK,IAAQ,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,GAAK,CAAK,CAAC;CAC3D;CAIA,IAAa,GAAiB,GAAgE;EAC5F,IAAM,IAAU,KAAK;EACrB,IAAI,CAAC,GAAS,OAAO;EACrB,IAAM,EAAE,QAAK,WAAQ,KAAK,GAAQ,GAAS,GAAS,CAAO,GACrD,IAAS,KAAK,IAAc,GAAK,CAAG,GACpC,IAAK,GAAa,KAAK,IAAO,CAAM;EAC1C,OAAO,KAAM;GAAE;GAAQ;EAAG;CAC5B;CAEA,IAAe,GAAqB;EAClC,IAAM,IAAQ,KAAK,IAAa,EAAE,SAAS,EAAE,OAAO;EAC/C,MACL,EAAE,eAAe,GACjB,SAAS,aAAa,CAAC,EAAE,iBAAiB,GAAG,EAAM,IAAI,GAAG,EAAM,EAAE,GAClE,KAAK,KAAY,EAAE,QAAQ,EAAM,OAAO;CAC1C;CAEA,IAAgB,GAA0B,GAAiB,GAAuB;EAChF,IAAM,IAAO,GAAa,KAAK,IAAO,EAAK,MAAM,GAC3C,IAAQ,KAAK,IAAa,GAAS,CAAO;EAChD,AAAI,KAAQ,KAAO,SAAS,aAAa,CAAC,EAAE,iBAAiB,GAAG,GAAM,GAAG,EAAM,EAAE;CACnF;CAKA,IAAgB,GAA0B,GAAiB,GAAuB;EAChF,IAAM,IAAU,KAAK,IACf,IAAY,SAAS,aAAa;EACxC,IAAI,CAAC,KAAW,CAAC,GAAW;EAC5B,IAAM,EAAE,QAAK,WAAQ,KAAK,GAAQ,GAAS,GAAS,CAAO,GACrD,IAAU,KAAK,IAAQ,GAAK,GAAK,EAAQ,IAAI;EACnD,AAAI,KAAS,KAAK,IAAe,GAAW,EAAQ,QAAQ,CAAO;CACrE;CAOA,IAAe,GAAsB,GAAuB,GAA2B;EACrF,IAAI,GAAS,GAAQ,CAAI,GAAG;GAC1B,GAAc,GAAW,EAAK,OAAO,EAAK,GAAG;GAC7C;EACF;EACA,IAAM,IAAO,KAAK,IAAY,CAAM,GAC9B,IAAK,KAAK,IAAY,CAAI;EAGhC,AADE,GAAc,EAAK,MAAM,MAAM,EAAK,MAAM,QAAQ,EAAG,MAAM,MAAM,EAAG,MAAM,MAAM,KAAK,IAC1E,GAAc,GAAW,EAAK,OAAO,EAAG,GAAG,IACnD,GAAc,GAAW,EAAK,KAAK,EAAG,KAAK;CAClD;CAQA,IAAQ,GAAa,GAAa,GAAkD;EAClF,IAAM,IAAS,KAAK;EACpB,IAAI,CAAC,GAAQ,OAAO;EACpB,IAAM,IAAQ,GAAS,GAAQ,GAAK,CAAG;EACvC,KAAK,IAAI,IAAI,EAAM,SAAS,GAAG,KAAK,GAAG,KAAK;GAC1C,IAAM,EAAE,SAAM,MAAG,SAAM,EAAM;GAE7B,IAAI,GAAW,CAAI,GACjB,OAAO,GAAQ,EAAK,MAAM,IAAI,OAAO,KAAK,IAAU,GAAM,GAAG,GAAG,GAAK,GAAK,CAAI;EAElF;EAGA,OAAO,GAAW,CAAM,IAAI,KAAK,IAAU,GAAQ,GAAG,GAAG,GAAK,GAAK,CAAI,IAAI;CAC7E;CAMA,IACE,GACA,GACA,GACA,GACA,GACA,GACsB;EACtB,IAAM,IAAQ,GAAgB,GAAM,GAAG,GAAG,GAAK,CAAG;EAClD,IAAI,MAAU,MAAM,OAAO;EAC3B,IAAM,IAAS,GAAgB,EAAK,OAAO,OAAO,CAAC,EAAE,kBAAkB,EAAK,MAAM;EAClF,IAAI,MAAS,UAAU,CAAC,GAAQ;GAC9B,IAAM,IAAO,GAAO,GAAM,CAAK,GACzB,IAAQ,KAAQ,GAAW,GAAM,EAAK,KAAK,GAC3C,IAAM,KAAQ,GAAW,GAAM,EAAK,GAAG;GAC7C,IAAI,KAAS,GAAK,OAAO;IAAE;IAAO;GAAI;EACxC;EACA,IAAI,MAAS,KAAK,IAAa,OAAO,GAAW,CAAI;EACrD,IAAM,IAAY,KAAU,EAAK;EACjC,OAAO;GACL,OAAO;IAAE,MAAM;IAAW,QAAQ;GAAE;GACpC,KAAK;IAAE,MAAM;IAAW,QAAQ,EAAU,WAAW;GAAO;EAC9D;CACF;CAOA,IAAY,GAAoC;EAC9C,IAAM,IAAO,EAAK,MAAM,KAAK,YAAY;EACzC,IAAI,EAAE,aAAgB,eAAe,MAAS,KAAK,GAAM,YAAY,GAAG,OAAO;EAC/E,IAAM,IAAO,EAAK,MACZ,IAAS,EAAK;EACpB,IAAI,CAAC,GAAQ,OAAO;EACpB,IAAM,IAAQ,MAAM,UAAU,QAAQ,KAAK,EAAO,YAAY,CAAI,GAC5D,IAAS,EAAK,iBACd,IAAQ,EAAK;EACnB,OAAO;GACL,OAAO,GAAY,CAAM,IACrB;IACE,MAAM;IACN,QAAQ,aAAkB,OAAO,EAAO,SAAS,EAAO,WAAW;GACrE,IACA;IAAE,MAAM;IAAQ,QAAQ;GAAM;GAClC,KAAK,GAAY,CAAK,IAAI;IAAE,MAAM;IAAO,QAAQ;GAAE,IAAI;IAAE,MAAM;IAAQ,QAAQ,IAAQ;GAAE;EAC3F;CACF;CAKA,IAAU,GAA2B;EACnC,KAAK,aAAa,IAAoB,EAAE;EACxC,IAAM,IAAO,EAAK,MAAM,MAClB,IAAU,aAAgB,UAAU,IAAO,EAAK;EACtD,AAAI,KAAS,iBAAsB,CAAO,CAAC,CAAC;CAC9C;CAKA,MAA2C;EACzC,IAAM,IAAQ,GAAsB,KAAK,GAAM,YAAY,CAAe;EAI1E,OAHI,CAAC,KAAS,GAAkB,MAAM,KAAK,IAAO,CAAK,MAAM,WAE3D,EAAM,mBAAmB,EAAM,gBAAgB,EAAM,gBAAgB,EAAM,YAFA,OAGnD;CAC5B;CAGA,YAAiC;EAC1B,KAAK,aAAa,EAAkB,MACpC,KAAK,IAAkB,KAAG,KAAK,gBAAgB,EAAkB;CACxE;CAEA,YAA8B;EAE5B,AADA,KAAK,KAAe,MACpB,KAAK,IAAqB;CAC5B;CAEA,OAAkB,MAAuB;EACvC,IAAM,IAAI;EAMV,IALI,CAAC,EAAE,aAAa,EAAE,WAAW,MACjC,KAAK,KAAmB,EAAE,aAItB,GAAkB,CAAC,IAAG;EAC1B,IAAM,IAAO,KAAK,GAAc,EAAE,SAAS,EAAE,OAAO;EACpD,IAAI,GAAM;GAKR,AAJA,KAAK,KAAa,GAClB,EAAE,eAAe,GAGb,EAAE,aAAW,KAAK,kBAAkB,EAAE,SAAS;GACnD;EACF;EAIA,AAHA,KAAK,KAAe;GAAE,GAAG,EAAE;GAAS,GAAG,EAAE;EAAQ,GACjD,KAAK,KAAY,IACjB,KAAK,KAAe,EAAE,aAAa,CAAC,CAAC,SAAS,KAAK,EAAK,GACxD,KAAK,IAAqB,EAAI;CAChC;CAEA,OAAgB,MAAuB;EAC/B,MAAuB,WAK7B;OAJA,KAAK,KAAmB,MACxB,KAAK,KAAY,MACjB,KAAK,KAAe,IACpB,KAAK,gBAAgB,kBAAkB,GACnC,KAAK,IAAY;IAEnB,AADA,KAAK,GAAQ,KAAK,GAAW,EAAE,GAC/B,KAAK,KAAa;IAClB;GACF;GACI,CAAC,KAAK,MAAc,KAAK,QAC7B,KAAK,KAAY,IACjB,KAAK,KAAe,MACpB,KAAK,IAAqB,GACtB,KAAK,MAAY,KAAK,IAAgB;EAL1C;CAMF;CAEA,OAAgB,MAAuB;EACrC,IAAI,CAAC,KAAK,IAAc;EAIxB,IAAM,IAAS,EAAM;EACjB,aAAkB,eAAe,EAAO,aAAa,gBAAgB,MACzE,KAAK,KAAc,MACnB,KAAK,IAAqB;CAC5B;CAOA,IAAqB,IAAa,IAAa;EAC7C,IAAM,IAAS,KAAK,IACd,IAAU,KAAK,IACjB,IAAmB,CAAC;EACxB,IACE,KAAK,MACL,KACA,KACA,KAAK,eACL,KAAK,aAAa,QAAQ,MAAM,WAC/B,KAAK,MAAa,EAAgB,IAAe,UAClD;GACA,IAAM,EAAE,QAAK,WAAQ,KAAK,GAAQ,KAAK,GAAa,GAAG,KAAK,GAAa,GAAG,CAAO;GAGnF,AAFA,KAAK,KAAY,GACjB,KAAK,KAAY,GACjB,IAAQ,GAAS,GAAQ,GAAK,CAAG;EACnC,OAEE,AADA,KAAK,KAAY,KACjB,KAAK,KAAY;EAEnB,IAAM,IAAY,EAAM,GAAG,EAAE,KAAK;EAClC,AAAI,MAAY,KAAK,KAAe;EAOpC,IAAM,IAAQ,EAAgB,IAAe,UAAU,IAAQ,CAAC,GAC1D,IAAa,KAAK,KAAe,EAAM,QAAQ,KAAK,EAAY,IAAI,IACpE,IAAQ,KAAc,IAAI,EAAM,MAAM,GAAG,IAAa,CAAC,IAAI,CAAC,GAC9D,IAAU,KAAK,IAAY,iBAAiB,KAAK,IAAU,CAAK;EACpE,IAAU,KAAK,IAAY,kBAAkB,KAAK,IAAU,CAAK,KAAK;EAGtE,IAAM,IAAS,IAAY,iBAAiB,CAAS,CAAC,CAAC,SAAS;EAEhE,AADA,KAAK,GAAM,MAAM,SAAS,MAAW,SAAS,KAAK,GAC/C,KAAW,KAAK,eAAa,KAAK,IAAgB;CACxD;CAEA,IAAY,GAAmB,GAAwB,GAA0B;EAC/E,IAAI,IAAU,IACR,IAAU,IAAI,IAAI,CAAI;EAC5B,KAAK,IAAM,KAAM,GACf,AAAK,EAAQ,IAAI,CAAE,MACjB,EAAG,gBAAgB,CAAS,GAC5B,IAAU;EAGd,KAAK,IAAM,KAAM,GACf,AAAK,EAAS,IAAI,CAAE,MAClB,EAAG,aAAa,GAAW,EAAE,GAC7B,IAAU;EAGd,EAAS,MAAM;EACf,KAAK,IAAM,KAAM,GAAS,EAAS,IAAI,CAAE;EACzC,OAAO;CACT;CAEA,MAAqB;CACrB,MAAuB;CACvB,MAAqB;CAErB,OAAoB,MAAuB;EACpC,GAAmB,KAAM,EAA0B,YAAY,MACpE,KAAK,OACL,KAAK,MAAqB,YAAY,IAAI,GAC1C,KAAK,IAAmB;CAC1B;CAEA,OAAqB,MAAuB;EACrC,GAAmB,KAAM,EAA0B,YAAY,MACpE,KAAK,MAAqB,KAAK,IAAI,GAAG,KAAK,MAAqB,CAAC;CACnE;CAEA,MAA2B;EACzB,IAAI,KAAK,KAAsB;EAC/B,KAAK,MAAuB;EAC5B,IAAM,UAAmB;GACvB,IACE,CAAC,KAAK,eACL,KAAK,QAAuB,KAAK,CAAC,EAA0B,KAC7D,YAAY,IAAI,IAAI,KAAK,MAAqB,IAC9C;IAKA,AAJA,KAAK,MAAuB,IAC5B,KAAK,MAAqB,GAG1B,KAAK,IAAgB;IACrB;GACF;GAEA,AADA,KAAK,IAAqB,GAC1B,sBAAsB,CAAI;EAC5B;EACA,sBAAsB,CAAI;CAC5B;CAEA,OAA4B,MAAuB;EAM7C,QAAkB,CAAK,GAO3B;QACG,EAAM,SAAS,aAAa,EAAM,SAAS,eAC5C,EAAM,kBAAkB,mBACxB;IACA,KAAK,IAAqB;IAC1B;GACF;GACA,KAAK,IAAgB;EADrB;CAEF;CAEA,yBAAyB,GAAc,GAA0B,GAA2B;EAC1F,IAAI,MAAS,SAAS;GAEpB,AAAI,MAAS,SAAS,MAAS,aACzB,MAAS,QACX,QAAQ,KACN,2CAA2C,EAAK,2CAChD,GAAY,IAAI,CAClB,GAEF,KAAK,aAAa,SAAS,EAAa;GAE1C;EACF;EACA,IAAI,MAAS,YAAY,MAAS,UAAU,MAAS,QAAQ;GAU3D,AATI,MAAS,QACX,QAAQ,KACN,4CAA4C,EAAK,0CACjD,GAAY,IAAI,CAClB,GAKF,KAAK,aAAa,UAAU,EAAc;GAC1C;EACF;EAIA,AADI,MAAS,YAAU,KAAK,IAAqB,GACjD,KAAK,IAAgB;CACvB;CAOA,cAAsB;EAGpB,OADI,KAAK,MAAgB,KAAK,IAAe,GACtC,KAAK,KAAc,GAAgB,KAAK,EAAW,IAAI;CAChE;CAEA,YAA8B;EAC5B,KAAK,IAAgB;CACvB;CAEA,YAA6B;EAM3B,4BAA4B,KAAK,IAAgB,CAAC;CACpD;CAMA,MAA6B;EAC3B,IAAM,IAAS,SAAS;EACxB,IAAI,EAAE,aAAkB,sBAAsB,CAAC,KAAK,SAAS,CAAM,GAAG,OAAO;EAC7E,IAAI;GACF,OAAO,EAAO,QAAQ,OAAO;EAC/B,QAAQ;GACN,OAAO;EACT;CACF;CAEA,MAA6B;EAC3B,IAAI;GACF,KAAK,IAAe;EACtB,SAAS,GAAK;GACZ,QAAQ,MAAM,6BAA6B,CAAG;EAChD;CACF;CAEA,MAAwB;EAClB,KAAK,OACT,KAAK,KAAiB,IACtB,4BAA4B;GAI1B,IAHA,KAAK,KAAiB,IAGlB,KAAK,IAAkB,GAAG;IAC5B,KAAK,IAAgB;IACrB;GACF;GACA,KAAK,IAAqB;EAC5B,CAAC;CACH;CAEA,MAAuB;EAKrB,IAAI,CAAC,KAAK,aAAa;EAGvB,IAAM,IAAc,KAAK,GAAoB,GAMvC,oBAAiC,IAAI,IAAI,GACzC,IAAY,iBAAiB,IAAI,CAAC,CAAC,iBAAiB,SAAS,CAAC,CAAC,KAAK,GACpE,IAAc,WAAW,CAAS;EACxC,IAAI,OAAO,SAAS,CAAW,KAAK,IAAc,GAChD,KAAK,IAAM,KAAM,KAAK,iBAAsC,UAAU,GAAG;GACvE,IAAM,IAAQ,iBAAiB,CAAE,GAC3B,IACJ,EAAG,eACF,WAAW,EAAM,WAAW,KAAK,MACjC,WAAW,EAAM,YAAY,KAAK;GAIrC,EAAe,IAAI,GAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAY,CAAW,CAAC,CAAC;EACzE;EASF,KAAK,aAAa,aAAa,EAAE;EACjC,IAAI;GAUF,AAAI,KAAK,GAAO,eAAe,QAAM,KAAK,YAAY,KAAK,EAAM;GACjE,IAAM,IAAU,GAAmB,MAAM,KAAK,EAAM,GAC9C,IAAW,KAAK;GAatB,CAXE,MAAa,QACb,EAAS,UAAU,EAAQ,SAC3B,EAAS,WAAW,EAAQ,UAC5B,EAAS,kBAAkB,EAAQ,iBACnC,EAAS,gBAAgB,EAAQ,iBAEjC,KAAK,MAAM,YAAY,WAAW,GAAG,EAAQ,MAAM,GAAG,GACtD,KAAK,MAAM,YAAY,WAAW,GAAG,EAAQ,OAAO,GAAG,GACvD,KAAK,MAAM,YAAY,YAAY,GAAG,EAAQ,cAAc,GAAG,GAC/D,KAAK,MAAM,YAAY,YAAY,GAAG,EAAQ,eAAe,EAAE,GAAG,IAEpE,KAAK,KAAe;GAMpB,IAAM,IAAK,iBAAiB,IAAI,GAC1B,KAAQ,WAAW,EAAG,WAAW,KAAK,MAAM,WAAW,EAAG,YAAY,KAAK,IAC3E,IAAgB,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,cAAc,KAAQ,EAAQ,KAAK,CAAC;GACvF,IAAI,MAAkB,GAAG;GAKzB,IAAM,IAAiB,GAAkB,GACnC,IACJ,GAAc,MAAM,GAAgB,GAAS,CAAc,KAC3D,KAAK,IAAoB,GAAgB,GAAS,CAAc,GAG5D,EAAE,cAAW,GAAW,GAAa,CAAa;GAexD,AAVA,GAAO,CAAW,GAClB,KAAK,KAAe,GAAwB,CAAW,GACvD,KAAK,GAAmB,GAAS,CAAW,GAO5C,KAAK,KAAa,CAAC,GAAU,GAAa,KAAK,IAAO,KAAK,IAAiB,CAAC,GAC7E,KAAK,KAAc;GAInB,IAAM,IAAY,GAAG,EAAY,UAAU,QAAQ,EAAQ,MAAM,KAC3D,IAAa,GAAG,EAAY,UAAU,SAAS,EAAQ,OAAO;GAEpE,AADI,KAAK,GAAM,MAAM,UAAU,MAAW,KAAK,GAAM,MAAM,QAAQ,IAC/D,KAAK,GAAM,MAAM,WAAW,MAAY,KAAK,GAAM,MAAM,SAAS;GAKtE,IAAM,IACJ,EAAG,cAAc,gBACZ,WAAW,EAAG,UAAU,KAAK,MAC7B,WAAW,EAAG,aAAa,KAAK,MAChC,WAAW,EAAG,cAAc,KAAK,MACjC,WAAW,EAAG,iBAAiB,KAAK,KACrC,GACA,IAAa,GAAG,IAAS,EAAQ,SAAS,EAAO;GACvD,AAAI,KAAK,MAAM,WAAW,MAAY,KAAK,MAAM,SAAS;GAG1D,IAAM,IACJ,EAAG,cAAc,eACb,KAAQ,WAAW,EAAG,eAAe,KAAK,MAAM,WAAW,EAAG,gBAAgB,KAAK,KACnF,GACA,IAAY,GAAG,IAAgB,EAAQ,QAAQ,EAAQ;GAM7D,AALI,KAAK,MAAM,iBAAiB,aAAa,MAAM,KACjD,KAAK,MAAM,YAAY,eAAe,CAAS,GAI5C,KAAK,aAAa,eAAe,KAAG,KAAK,aAAa,iBAAiB,EAAE;EAChF,UAAU;GAwCR,AA/BA,KAAK,aAAa,YAAY,EAAE,GAChC,KAAK,gBAAgB,WAAW,GAChC,iBAAsB,IAAI,CAAC,CAAC,oBAC5B,KAAK,gBAAgB,UAAU,GAM/B,KAAK,GAAwB,CAAW,GAIxC,KAAK,IAAmB,YAAY,GAMhC,EAA0B,IAAI,MAC5B,EAA0B,KAC5B,KAAK,MAAqB,YAAY,IAAI,GAC1C,KAAK,IAAmB,KAExB,KAAK,IAAgB,IAMzB,KAAK,GAAqB,GAC1B,KAAK,KAAkB,CAAC;GACxB,IAAM,IAAY,SAAS,oBAAoB,SAAS;GACxD,KAAK,IAAI,IAAK,KAAK,eAAe,GAAI,IAAK,EAAG,eAC5C,CAAI,MAAO,KAAa,cAAc,KAAK,iBAAiB,CAAE,CAAC,CAAC,QAAQ,MACtE,KAAK,GAAgB,KAAK,CAAE;GAOhC,AADA,KAAK,KAAc,MACf,KAAK,MAAc,KAAK,IAAqB;EACnD;CACF;AACF;AAIA,SAAgB,KAAuB;CACjC,OAAO,iBAAmB,OAC1B,eAAe,IAAI,WAAW,KAClC,eAAe,OAAO,aAAa,EAAe;AACpD;AAwCA,SAAS,GACP,GACA,GACA,GACA,GACA,GACQ;CAIR,OAAO,GAHI,MAAS,MAAM,EAAG,YAAY,EAAG,YAE1C,MAAS,MAAM,EAAG,eAAe,EAAG,eAAe,EAAG,cAAc,EAAG,aACtC,GAAU,GAAK,CAAI;AACxD;AAYA,SAAgB,GACd,GACA,GACA,GACA,GACA,GACQ;CACR,IAAI,IAAM,KAAK,IAAK,KAAK,KAAM,IAAU,GAAG,OAAO;CACnD,IAAM,IAAQ,IAAK,IAAW,GACxB,IACJ,KAAK,IAAI,CAAK,KAAK,KAAM,IAAO,IAAO,KAAK,KAAK,CAAK,IAAI,KAAK,MAAM,KAAK,IAAI,CAAK,CAAC;CACtF,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,CAAK,GAAG,CAAG;AACzC;AAMA,SAAS,GAAkB,GAAuB;CAChD,OACE,aAAiB,gBAAgB,EAAM,gBAAgB,WAAW,EAAM,SAAS;AAErF;AAIA,SAAS,GAAY,GAAiC;CACpD,OAAO,MAAS,QAAQ,EAAE,aAAgB,WAAW,EAAK;AAC5D;AAGA,SAAS,GAAU,GAA6B;CAC9C,OAAO;EAAE,OAAO;EAAO,KAAK;CAAM;AACpC;AAEA,SAAS,GAAc,GAAsB,GAAa,GAAqB;CAC7E,EAAU,iBAAiB,EAAK,MAAM,EAAK,QAAQ,EAAO,MAAM,EAAO,MAAM;AAC/E;AAEA,SAAS,GAAS,GAAkB,GAA2B;CAC7D,OACE,EAAE,MAAM,SAAS,EAAE,MAAM,QACzB,EAAE,MAAM,WAAW,EAAE,MAAM,UAC3B,EAAE,IAAI,SAAS,EAAE,IAAI,QACrB,EAAE,IAAI,WAAW,EAAE,IAAI;AAE3B;AAEA,SAAS,GAAwB,GAAgC;CAC/D,IAAM,IAAoB,CAAC,GACrB,KAAS,MAA2B;EACxC,AAAI,EAAK,eAAa,EAAI,KAAK,CAAI;EACnC,KAAK,IAAM,KAAS,EAAK,UAAU,EAAM,CAAK;CAChD;CAEA,OADA,EAAM,CAAI,GACH;AACT"}
|