Loading…
Loading…
Dataset 20260827-2142-2f1b575 · measured 2026-08-27 21:42 UTC
Conformance · root causes
Behind the failures are a much smaller number of causes: one missing rule in the fragmentation algorithm can account for a dozen tests across three suites. These are the ones that have been diagnosed — with what was actually found, not a label.
Nested fragmentation (columns inside paged FC) missing: test renders only ONE page with both 2in-tall columns fully green (6in of content packed into page-1 columns, remainder lost), while the ref correctly renders 2 pages. Expected: page 1 = div1 sliced (col1 2in + col2 1in), div2 pushed whole to page 2 and sliced there. The multicol container never resumes in the next page fragmentainer.
css-break parallel flows (the test's help link) are not implemented: the overflowing children of the height:50px block (70px green + 90px spacer + 40px green) are laid out serially with the following siblings instead of in a parallel flow. Rects: sibling 2 (50px) is moved WHOLE to column 2 y=0..50 ('re f 37.5 374.7 37.5 37.5') leaving column 1 y=70..100 red (blocks are never sliced mid-box at a column boundary, block.rs:1263), sibling 3 at col2 y=50..90, and the overflow 40px green lands at col2 y=90..130, overflowing below the container. Needs both parallel-flow placement and mid-box block slicing.
New bucket: forced break propagation from edge descendants is missing. Render shows NO column break at all: both 100px green blocks stacked in col1 (0-200css), col2 empty, parent red visible at x50-100. Probe confirmed break-before:column WORKS on a direct multicol child (renders perfect 100x100 green). Here the break-before:column sits on the first child of an empty wrapper div and must propagate to the break between wrapper and previous sibling (css-break break-propagation).
page_geometry() (flexpdf/src/lib.rs:1288) folds ALL @page rules into one global Page, so '@page :first { size:100px }' overwrites the base 320x200px for every page: pdfinfo shows all 3 pages 75x75pt. Correct output needs page 1 at 100px and later pages 320x200px - per-page fragmentainer sizes that change per-page available width (50% divs), i.e. per-page layout.
Runner: 'matches its rel=mismatch reference', diff=0. PDF stream proves it: page 1 clip is '0 -7.5 150 232.5' and the cyan strip is '0 1 1 rg 0 -7.5 150 7.5 re f' - off the 225pt media box. The paginator's advance-through-void step (flexpdf-paginate/src/lib.rs ~360, 'Advance a natural break through the void to the next block/atom top') moves the natural break from 225pt past div2's 10px top border to its first line top (232.5pt), because tops/atoms hold content tops, not border-box tops. The box's top border (the ONLY differing pixels, cyan vs black) is stranded in the previous page's clipped zone in both test and notref, so the two render identically and the mismatch test fails. page-orientation itself is also unparsed but irrelevant to this comparison.
writing-mode is entirely unsupported: no writing_mode/vertical-rl in flexpdf-css/src/style.rs computed style and zero hits in flexpdf-layout. Render shows 'TEXT' horizontal in a wide lime block inside the yellow multicol (24480 diff px) instead of rotated 90° clockwise in a narrow vertical column honoring the vertical block's min-content inline size. Needs orthogonal-flow layout (vertical writing mode inline direction = vertical, multicol sizing against it) — a cross-cutting subsystem.
Test renders '123'/'456'/'7' on three lines; ref (same content but no <div> inside the span) renders '123 456'/'7'. The engine promotes the whole inline span with a block child to block level instead of splitting the inline around the block (anonymous block-in-inline), forcing a break before '456'. The abspos <abs> boxes (inline containing block) are not rendered at all, but they are equally missing in the ref render so they cancel; the pixel diff that fails the reftest is the extra line break.
Core named-page semantics: nested divs with page:a/page:b must force breaks whenever the current page name changes. Engine has no 'page' property (flexpdf-css/src/properties.rs maps only page-break-*), so no breaks are inserted. Confirmed by render: test produces 1 page, ref produces 8 pages.
The inline-table itself renders correctly (green box bbox identical to ref and to a plain-div control: 100x100 at ref position, incl. 25px padding). Failure is only the red div with position:absolute (auto offsets) + z-index:-1: engine places it at page origin (0,0) instead of its hypothetical static position and paints it on top of all content (negative z-index ignored), leaving red visible.
column-fill:auto with unconstrained height must fill ONE unbounded column (everything stays in col1, where the position:relative green covers the flex item's red overflow). Engine balances instead (explicit NB comment in layout_multicol, block.rs ~1355: single-column fill 'tried 2026-07-09, broke multicol-nested-0xx'), moving the relative green div into column 2 and leaving red visible at col1 y50-100 (render: red 100x50 CSS at y50-100).
Render: green is 100x200 CSS px instead of 100x100 (diff exactly 10000 px). The cell child div{height:100%; min-height:100px; overflow-y:scroll} with a 200px-tall child resolves height:100% to auto/content height (200) instead of re-resolving against the final cell block-size (100, set by min-height). Ref clamps at 100 and scroll-clips the content.
New bucket: widows/orphans not implemented for unforced breaks between line boxes during fragmentainer fill. Engine renders #test (widows:2) as 1-4 | 5-8 | 9 — a single widow line in column 3 — instead of pulling one line back: 1-4 | 5-7 | 8-9 (the #reference div with widows:1 + extra <br> renders that distribution correctly). Column capacity (4 lines at 26px in 104px columns) is computed correctly; the only missing piece is the widows adjustment when choosing the class-B break point.
column-span:all is parsed (flexpdf-css/src/cascade.rs:555 sets column_span_all) but zero references in flexpdf-layout — spanners are laid out as ordinary column content. Here the 2em empty spanner and the 'SS' spanner get balanced into separate columns, so 'SS' renders at the multicol top (ink rows 53-63) and 'PA' baseline-aligns to it at the top, while the ref has PASS 2em lower (rows 86-96); 552 diff px. Requires real spanner support: interrupt column rows, lay the spanner full-width, resume columns below, and export baselines accordingly.
The abspos green square (containing block = ICB, static position inside a flex container fragmented across 2 columns) is painted at page origin (0,0), covering the <p> text; red multicol shows through at y100-150css. Expected: abspos placed at its static position = top-left of the flex container's first fragment ≈ (8, 51)css, exactly covering the 100x100 red multicol. Static position of OOF elements is lost when the ancestor chain is inside a fragmentation context.
Diff vs ref-filled-green-100px-square is exactly 37 px, all in one image row (row 37, x38-74 at 72dpi): the fragment resumed in column 2 is painted starting 1pt (1.33 CSS px) above the column's block-start (pure green at row 37 where ref has pure white; both agree from row 38 down). Everything else in the test (margin-bottom of last flex item accounted at the break) already works. Same off-by-1pt consumed-block-size/offset rounding as -001/-002/-003/-004/-006/-010; one fix covers all seven.
Layout is correct (display:none children removed, outer red div is 600x0). But the painter emits a degenerate rect to the PDF: content stream contains '1 0 0 rg 0 412.2012 600 0 re f'. Poppler antialiases the zero-height fill into a faint pink hairline (255,223,223) across the page, failing the pixel diff vs the blank ref. Fix: skip background/border fills with width<=0 or height<=0 in the PDF emitter.
Engine columns measured 100/200/100 instead of spec 130/140/130: fixed layout under border-collapse adds the cell's FULL borders (120+0) to its specified width (80) when sizing the column, instead of half per side; cell content then paints 140px (80+60 half-borders) instead of 80px — blue stripe 140px wide vs 80px in ref, first cell 40px vs 70px.
Render is pure red (diff 10000): both grid items paint as 0x0 rects ('0 0.502 0 rg 0 412.2 0 0 re f' and at x=37.5). The anonymous grid-item wrapper consumes the child's fixed height (box_tree.rs wrap_in_item, /var/www/reflowpdf/flexpdf/rust/flexpdf-layout/src/box_tree.rs:717-726 resets child height to Auto) but the wrapper layout never re-applies it, so the 50px/150px items and their auto row collapse to 0; auto column track also collapses to width 0 (no free-space stretch). Note: item 2 IS relocated to column x=37.5, so multicol item distribution works; after the sizing fix the test will still need in-row slicing of the 150px row across the two 100px columns.
Conflict color resolution is correct (no red anywhere), but geometry is wrong: render shows 5 separate green bars with white gaps. Measured green runs at y=38-52, 67-81, 95-109... (72dpi): border starts are 40 CSS px apart, i.e. layout reserves BOTH adjacent cells' 20px borders (20+20) instead of merging them into one 20px collapsed border, then paints only the winner's 20px slot, leaving a 20px white gap. Table is 180px tall instead of 100px.
Test side renders correctly: box pushed whole to column 2 with intact 10px hotpink borders, x matches ref exactly (image x 83-157 both). Only diff is a 16css-px vertical offset: ref box at y=34.7css, test at 50.7css. Probe confirmed: an in-flow block after <p> is placed at y=50.7 but a float at y=34.7 — float placement omits the preceding sibling's collapsed 16px bottom margin, so the float-based REF renders too high. Fix float hypothetical position to include preceding collapsed margins.
Rendered col1 = 150css green (squares 1-3), col2 = 50css (square 4): engine breaks at the 3/4 boundary that break-before:avoid on square 4 forbids; it should backtrack to the 2/3 boundary giving 100x100. Note break-inside:avoid IS honored (square 4 moved whole, not sliced at y=160), so what's missing is avoid-between-siblings with last-good-breakpoint backtracking.
The 200px item paints as one unsliced fragment h=150pt at column 1 extending 100px below the container bottom ('0 0.502 0 rg 0 262.2 0 150 re f', container bottom y=337.2) instead of splitting 100px into column 2; block.rs:1263 documents that a whole child box is never split between columns, and grid slicing only happens at row boundaries (unit test multicol_splits_grid_rows_across_columns) — a single row taller than the fragmentainer is monolithic. Compounding: 'grid-template-columns: auto auto' tracks collapse to width 0 (no auto-track stretch), so the fragment is invisible (w=0).
Line distribution is CORRECT per orphans/widows (4 lines per column: 10,10,40,40 | 40,40,10,10 — cut-blockers at block.rs:1643-1657 work), but line-height:0 is ignored when sizing line boxes: measured line advances are 18.43 CSS px for 10px-tall inline-block lines (= normal strut 14.56 ascent + 3.87 descent) and 43.87 for 40px ones (item + normal descent), instead of exactly the inline-block heights. Columns become ~118px instead of 100 and the red container background shows through 3-8px gaps between lines (2300 diff px @96dpi). parse_line_height handles Number(0) fine (cascade.rs:1096) — the line-box construction uses font 'normal' metrics for the strut regardless of specified line-height.
Two independent gaps: (1) page_geometry (flexpdf/src/lib.rs:1288) merges every @page rule into one global geometry - later '@page { margin:0 }' overwrites ':first { margin:1cm }' for all pages, no per-page :first selection; (2) named pages unimplemented, so no break at a->b name change. Verified render: 1 page, margin 0, both bordered boxes stacked at top-left; ref is 2 pages (diff=u64::MAX).
A ~1em+borders red box (diff bbox 0,38-20,57 at 72dpi, 380 red px) is painted for the display:table-column div misparented inside a table-row. Per table fixup a table-column outside table/column-group context must be treated as display:none (its bg/border never paints directly); engine instead lays it out and paints it as a normal box. Contrast: misparented table-row (test 011) is correctly suppressed.
New bucket: floats inside fragmented flex containers are mislaid and never sliced. Test render: the 500px-tall yellow float escapes its flex-item/multicol containment — rendered as one unfragmented monolith at body origin (y 7-510css), the pink multicol box (a BFC) is displaced sideways to x≈113-302css avoiding its own descendant float, and the cyan float stacks below at y≈510. Ref (cyan as block) renders differently (pink box at origin, cyan on top), so test/ref mismatch. Expected: float fragments into ≤160px slices across the 100px-wide columns inside the pink border.
Undecorated wrapped flex is split into flex_bands Groups (block.rs ~1976), and Groups are never render-time banded (frag_child only matches MulticolItem::Child), so each 250px-tall row bounces whole into one column: render shows band1 in col1 + band2 in col2 (green 40x250, overflowing 150px below the 100px columns), columns 3-5 empty red. Expected: rows sliced at 100px column height filling all 5 columns (green 100x100).
The 100px row-gap is geometrically sliced instead of truncated at the break: vs the engine-rendered ref (identical markup minus the gap) 8201 px differ in columns 2-3 — col2's lower quarter shows yellow gap area instead of item content and item2 lands lower/in the overflow column painted at full multicol width (300px cyan, x252-476 raster). Banding slices the pre-laid strip so content after the gap can't be pulled up.
New bucket: a block whose only inline content is <br> must produce one line box of strut height (line-height), but engine yields height 0. Minimal repro confirmed: <div style="line-height:60px"><br></div> renders as a 0-height rect. In the test both floats (line-height:100px/60px with <br>) collapse to 40x0 and 10x0, so nothing needs pushing and the clear:left block lands at col2 top (40px tall), giving an L-shape instead of the 100px green square. Rebuilt the same test with explicit float heights: engine correctly pushes the tall float to column 2 and applies clearance (orange at y60-100 in col2) — the fragmentation/float logic is fine; only the <br> line box is dropped.
The <button> renders as a native blue pill with all children flattened into one inline run 'block1block2 spanner block3block4' — column-count:3, column-rule and the column-span:all h3 are ignored inside button. The ref gets identically flattened, so the reftest only fails on residual word-spacing diff (diff bbox 73,10-252,18), but the root cause is that button content bypasses normal CSS block/multicol layout entirely.
New bucket: engine breaks exactly at the fragmentainer edge regardless of legal class A/B breakpoints. Measured: col1 = exactly 100css green (sliced mid-line-2), col2 = 56.7css green (line remainder + 50px trailing padding) + 43css red. Expected: break at class-B point between the two lines (break between last line and container end padding is illegal), first fragment's background extends to column bottom, col2 = line2+padding = 100css green.
New bucket: overflow columns not implemented. Fieldset fragmentation itself works (col1 = blocks 1-2, col2 = blocks 3-4, break-inside:avoid honored), but the 5th (red) block is placed in col2 at y=100-150 and clipped at the 140px container edge by overflow:hidden — measured red at col2 y100-140css. Expected: content past the last column goes to an inline-direction overflow column at x=100-150, fully clipped by overflow:hidden, leaving no red.
New bucket: flex item cross-axis stretch sizing ignored — item auto-grows to content height. Probe outside any fragmentation: flexbox 70px tall with flex:1 item containing a 140px grandchild renders the item 160css tall (teal border spans y10-170) instead of the stretched 50px. In the multicol this 160px item fragments into col2 (teal side borders measured at x160-170 and 260-270css where the ref, whose item has explicit block-size:50, has only orange) and produces a stray third fragment: a 110css-wide teal strip painted outside the multicol at x≈300-410css.
Rows themselves land correctly (green 100x100 present), but item1's overflowing 100px red child is left painted at its strip position below column 1 (render: red 50x100 CSS at y100-200, under the multicol box). Per spec the overflow continues into the next fragmentainer where item2's later-painted green covers it, so no red is visible. Band-move scheme produces no continuation fragments for content overflowing a flex item.
break-before:page on flex item '5' must propagate to its flex line / nested container edge: expected 2 pages (Before+items1-4 | items5-8+After). Engine renders 3 pages: page1 completely BLANK (spurious page from the mishandled forced break), page2 has items 1-4 AND row 5-6 together (forced break not honored at the line edge), page3 has 7-8.
Render: flex item painted 25 CSS px wide x ~155 tall (green x0-25, y51-207), red exposed x25-100 — the item's auto main size (flex-basis:auto content size) was resolved to min-content (25px, the widest single inline-block) instead of max-content (25+25=50), so the two inline-blocks stacked vertically. Reproduced without any fragmentation in /tmp/claude-1000/wf-cls-7/iso007.html (container width 50, item still 25 wide). Secondary: the resulting 150px box also paints straight across the column boundary without fragmenting, and the 'item grows due to fragmentation' behavior the test targets is absent — but the first-order failure is the intrinsic main-size computation.
NEW BUCKET: multicol container's first-baseline export to flex baseline alignment is off by a sub-pixel. Test vs ref differ ONLY by the whole word PASS sitting 0.75 CSS px too high (ink rows 53-63 vs 54-64 @96dpi, 336 diff px; identical at 72/144dpi). Isolation: flex + plain block item matches ref exactly; swapping the item for columns:3 reproduces the exact 1px@96dpi shift with no spanner involved — so the (unsupported) column-span:all is NOT the operative failure here; the exported baseline of the multicol flex item is what is wrong.
NEW BUCKET: layout/paint geometry is exactly right — content stream shows red bg '0 337.2012 75 75 re f' identical to ref, 3.75x75pt rules in every gap, and each column slice as the full 600pt child rect offset by N*75pt — but slices are painted under per-column clip rects ('q -100000 337.2012 200000 75 re W n') at fractional page coords (container top 37.8pt), and poppler rasterizes clip edges differently (rounds out) than the ref's plain fill edge: 1px green bleed above the container at 72dpi and pure-green bottom row 150 at 96dpi (57 diff px vs ref's anti-aliased edge). Fix: snap/inset slice clip rects to the fill edge or emit pre-clipped rects in the slice painter.
The fieldset multicol lands correctly in outer column 2 (x0-100), but its 200px green child stays monolithic in inner column 1 (green 50x200 overflowing to y250) while inner column 2 stays empty (fieldset red bg x51-100 visible). Probe4 reproduces with a plain non-nested div multicol: block-level boxes are never fragmented across column boundaries (only line boxes distribute) — not fieldset-specific.
Pages 1-2 mismatch: test pages show yellow only behind body's single line box, ref pages are fully yellow (ref's 283px divs fill the page content box so body bg covers it). The engine does not propagate the body background to the page canvas as CSS requires (Chrome paints both test and ref pages fully yellow). Secondary: same trailing-forced-break bug as 001 — 3 pages vs ref 2 (blank last page from break-after:page on body/last div).
@page size 300x50px is honored (both PDFs 225x37.5pt, 3 pages). Failure is snap_forced_breaks (flexpdf-paginate/src/lib.rs:191): forced breaks are floor-snapped to the CSS-px grid while box y stays exact, so content lands 0.3pt lower per break (test baselines 26.44/26.14/25.84pt vs ref 26.44 on every page) - a 1px text shift at the runner's 96dpi (365+379 differing px on pages 2-3).
Row-origin borders are entirely absent from collapsed-border conflict resolution: the 5px solid blue/green/red border-bottom rules on tr paint nowhere — render shows only 1px black td borders. Ref differs only by an explicit td-level red border-bottom (which the engine honors), producing the 5px strip diff at the table bottom (bbox (0,209,207,214), 1045 px). Fix needs tr/tbody borders added as conflict sources, plus per-segment attribution so the rowspan cell's bottom edge takes the LAST spanned row's border (the actual assert).
New bucket: margin/border/padding on table-internal boxes is applied instead of ignored. Isolated repro: td with margin:7px+dashed border in a separate-borders table shifts the cells so their dashed borders paint OUTSIDE the table's 3px solid border box; a tbody with border/padding/margin inherited down to tr/td collapses the table into a narrow vertical stack. Test/ref diverge from the .inherited/.bc region on (diff bbox y218-451, 2956 px). Fix: zero mbp on row/row-group/cell-margin boxes at box construction.
New bucket: conflict WINNER is resolved correctly even at subpixel widths (4.95px red cell loses to 5px green table border — no red pixels), but table/column sizing uses the cell's own specified border width instead of the resolved winning width: test table border-box is 72px wide vs ref 64px (delta 8 = 2x(4.95-1)); spec-wise both must be identical since the winning 5px table border is the same. 600 diff px = vertical strip at the right/bottom edges.
Colspan/gutter width distribution is actually CORRECT: green div measures exactly 100 CSS px (300 dev px at 288dpi). Failure is a 1 CSS px red fringe on all four sides: cell is 102x102 with the green div inset 1px — UA default td{padding:1px} is applied but the cellpadding="0" presentational attribute is not mapped to padding:0. Fix: map cellpadding/cellspacing HTML attributes to style.
Render shows white cells surrounded by wide red gutters: the parser accepted the invalid 'border-spacing: 20%' declaration (border-spacing takes only lengths) instead of dropping it and keeping the earlier 'border-spacing: 0px'. Fix: reject percentage values when parsing border-spacing so the invalid declaration is ignored per CSS error handling.
#test is a valid, genuinely empty table-cell with empty-cells:hide, yet its red background and 5px red border are painted (red box at top-left, 420 red px). The engine does not implement empty-cells:hide (skip painting background+border of empty cells in the separated borders model).
display:inherit should compute to the parent .tr's table-row; test 011 with explicit display:table-row in the identical structure renders NO red, but 017 paints a 1em red box (same as a plain block/cell would). So the CSS-wide 'inherit' keyword is not resolved for display — #test falls back to a normal box. Fix in cascade: resolve inherit to the parent's computed value for non-inherited properties like display.
Test table renders 600 CSS px wide vs ref 500: engine treats the HTML table's width:500px as content-box and adds table padding (33+39) and borders (11+17) on top (+100 exactly); per CSS2 17.6.1 table width is the border-edge distance. Secondary: height 118.7 vs 100 from an empty-cell line strut (see 004e).
Black and blue stripes match ref in width/x exactly (96px at x=185); mismatch is vertical: the empty table-cell with height:1em(16px) renders 18.67px tall — engine imposes a line-height:normal strut as minimum height on empty cells (verified in isolation: empty cell height:16px renders 18.67px; with line-height:1 it renders 16px), shifting the relative blue stripe down ~3px.
In border-collapse:collapse the table padding must be ignored, but the engine applies it: aqua table renders 114.7 CSS tall (ref 104; delta = exactly the 3px+8px vertical table padding) and ~301 wide (ref 292). Secondary: the two background-image tables additionally paint the image only over the padding box (see bs-cell-001 bug), compounding the mismatch.
The background-color cell table matches ref pixel-exactly, but background-image cells paint only the padding box: image area 42x12 dev vs ref 45x16 (shrunk by the cell's 3+1/2+4 borders and shifted by border widths). Reproduced on a plain div with transparent border: bg-color fills the border box, bg-image is clipped to the padding box — engine-wide painting-area bug, not table-specific.
Aqua table background renders 313.3 CSS wide vs ref 325.3 — short exactly the 6x2px horizontal border-spacing; height (145.3, incl. 6x3px vertical spacing) matches ref, and cells sit at correct spacing-included x positions (verified via bs-cell-001 geometry), so the table box/background is computed without horizontal spacing while cells overflow past its padding edge. Secondary: imagetl/imagebr tables also hit the bg-image padding-box clipping bug.
Not a fragmentation bug: reproduced standalone without multicol. In a column-wrap flex, a stretch item with auto cross size is measured at the CONTAINER cross size (block.rs:6327-6328), so line1 becomes 100 wide and line2 is placed at cross-offset 100: item2's green renders at x100-150 (outside the 100px square), leaving red at x50-100,y0-25. Spec: multi-line lines size to items' hypothetical (fit-content=50) cross sizes.
Layout is essentially correct: pixel diff vs the engine-rendered ref is only 56 px, all on one raster row (y=37, x19-74) — the ColFragment slices in columns 2-4 paint 1 raster px (~1.3 CSS px) ABOVE the square's top edge, while column 1 starts at the correct y38. Rounding of the fragment translation/clip in the render-time fragment plan.
The flex/break-inside:avoid part works (col2 is fully green: item1 bounced whole, item2 follows). Failure: the auto-offset position:absolute 50x70 green resolves to the containing block's TOP (y0-70) instead of its static position after the 30px sibling (y30-100), leaving red at col1 y70-100. Reproduced in a plain block without multicol — engine has no static-position tracking for abs boxes (no such concept in block.rs).
Render: item1 (10px, definite basis) correct in col1 top, but col1 shows red below y=10 and item2 (50x190) is painted entirely in col2, unfragmented, overflowing 90px below the 100px multicol (green strip to CSS y~240). Isolated repro /tmp/claude-1000/wf-cls-7/iso051a.html (item1 without overflowing children) shows the same: engine refuses to split a flex item that starts mid-fragmentainer, prefers a break between items and then never slices the pushed item either. Expected: item2 splits 90/100 across the two columns. New bucket: engine can't break inside a flex item at an arbitrary mid-column position (only slices boxes that start at the fragmentainer top, cf. -001 which fragments fine).
Render: column 1 is green 100px, column 2 fully red (2775 red px) — only 100px of content exists. The height:100% div inside the flex:none item resolved to 0 (percentage against non-definite item treated as auto) instead of resolving against the item's used main size after flexing (flexbox spec 9.8: post-flex main size is definite). Correct resolution gives 100%->100px + contain-size 100px = 200px of green fragmenting into column 2 (overflow-content fragmentation itself works, cf. row-002 which nearly passes).
Render: the top 100x100 matches ref (0 red px), but the stretched flex item's green background continues ~55 CSS px below the multicol (diff bbox img x0-37, y113-154). In a height:100px flex container the auto-height item should be stretched (clamped) to exactly 100px with content overflowing invisibly; the engine gives the item its content height (150px from the stacked inline-blocks). Reproduced with no fragmentation at all in /tmp/claude-1000/wf-cls-7/iso008.html (item bg 156px tall inside a height:100 flex) — general flex cross-size stretch implemented as grow-only, missing the clamp to the container's definite size.
Render: column 1 fully green (outer flexbox bg 100px), column 2 green only y51-107 with red x51-100 y107-151 (1221 red px). The outer auto-height flexbox's fragment in column 2 is sized to just its actual content there (~50px, the second fragment of the inner item) instead of expanding its intrinsic block-size due to the flex item fragmenting (per css-flexbox pagination, expected total 200px so the background fills both 100px columns). Missing 'container/item grows by space consumed by fragmentation' logic in flex fragmentation.
Render: break-before of the flex row works (the 100x100 flex item correctly starts at the top of column 2, no red anywhere), but the item's box paints 50 CSS px past the multicol's right edge — diff bbox img x75-112 (CSS x100-150), y38-112. Per css-multicol, column content extending into the gap/past the column box must be clipped (gap=0 here, so at the column edge x=50/x=100); the first 100px-wide div's overflow into column 2's area happens to be green so only the rightmost overhang differs from ref. Missing inline-direction clipping of fragmentainer content at paint time.
Layout is CORRECT — the 450px block slices 300+150 across the columns and the abspos fragment fills column 2 y=150..300; every painted edge coincides with the ref's green square (0,187.2,225,225). The 112-pixel diff is one row (y=37px, x=113..224): the column-2 slice is emitted as an oversized rect ('re f 112.5 299.7 112.5 337.5') clipped by 'q ... re W n' at y=412.2012, and poppler rasterizes that clip edge one pixel taller/harder than the ref's plain fill edge at the same coordinate, leaving a 1px green line above the square. Fix: intersect emitted fragment fill rects with the fragment clip box instead of relying on the clip.
NEW BUCKET: engine layout is correct (empty column-fill:auto multicol gets exactly height 0), but the PDF writer emits degenerate zero-height fill rects — content stream contains '1 0 0 rg 0 841.89 595.276 0 re f' — which poppler/pdftoppm rasterizes as a faint red hairline (255,223,223) across page-top row 0 at the left/right 10px border zones (22 diff px, max_delta 32). Reproduced with a plain empty div with background:red (same 0-height 're f' painted as hairline). Fix: skip zero-area fills in fill_rect/draw_borders in /var/www/reflowpdf/flexpdf/rust/flexpdf-pdf/src/lib.rs.
NEW BUCKET: fully transparent text color is painted opaque. The two inline-block parts align and size correctly (solid 100x100 green footprint matches ref edges); the ONLY diff (826 px, max_delta 128 = G-channel of black-on-rgb(0,128,0)) is the 'line1/line2' glyphs painted black despite color:transparent. 'transparent' parses to Color::TRANSPARENT (flexpdf-css/src/value.rs:824), but the text paint path in /var/www/reflowpdf/flexpdf/rust/flexpdf-pdf/src/lib.rs:1552-1556 only builds alpha ExtGStates for 1e-6 < a < 0.999 and draws a==0 runs fully opaque instead of skipping them.
Ref is nothing.html but render shows a faint red hairline (rgb 255,223,223 row at y=37) below the text: the empty nested multicol with background:red gets an epsilon (<1px) block-size and paints its background. Probe shows the same hairline for a NON-nested empty multicol (probe1.html rows 75/90), so nesting is incidental — empty multicol containers should resolve to height 0 and paint nothing.
The green 5em column-rule is drawn with correct geometry (5850 green px covering the red reference div — the multicol/rule part passes). Failure: 2700 black pixels in exactly the column areas (40x100 CSS blocks) — the Ahem text with color:transparent is painted opaque black. The engine ignores/mis-parses 'transparent' for the color property (or paints glyphs ignoring alpha).
Same geometry as multicol-rule-samelength-001 but the 5850-px square renders RED instead of green: at least one of the 12 invalid column-rule re-declarations (containing 'normal' or duplicate colors, e.g. 'column-rule: red 5em solid red') is accepted instead of being dropped as a parse error, replacing/killing the valid 'green solid 5em' rule. (Secondary: same color:transparent-text-painted-black issue as samelength-001.)
Render is a pure red 100x100 square with zero green pixels: <canvas> is not treated as a replaced element — flexpdf-layout/src/box_tree.rs:372 only recognizes img|svg — so the canvas becomes an empty 0-height block and its green background never paints. New bucket because missing spanner alone cannot explain 'no green at all' (other spanner tests still paint green in columns). Secondary dependency: column-span:all is also unimplemented (column_span_all parsed at flexpdf-css/src/style.rs:1235, zero refs in flexpdf-layout), which the test's spanner auto-width geometry ultimately needs.
Two co-causes. Test side: multicol layout is gated on kind==BoxKind::Block (flexpdf-layout/src/block.rs:401 'is_multicol(&style) && kind == BoxKind::Block'), so column-count:3 on the display:table-cell div is ignored — render shows A/S/S stacked vertically in the cell instead of one per column. Ref side: float-layout bug — float:left + overflow:hidden drops all floats after the first (minimal repro: 4 floats with overflow:hidden render only 'P'; removing overflow:hidden renders 'P A S S'), so the ref shows only 'P'. Both must be fixed for the reftest to match.
Test renders 2 pages vs ref 1; page 1 is pixel-identical to the ref (yellow strip + 'Page'). break-after:page on the document's last element spawns a trailing blank page, whereas per css-break a forced break after the last box must not create an extra fragmentainer. Fix is a local suppression rule in flexpdf-paginate (ignore forced break at/after the last content bottom).
1 page vs ref 3: body{height:250vh} paints nothing, and flexpdf-paginate's visual-bottom heuristic deliberately refuses to open pages for non-painting height (flexpdf-paginate/src/lib.rs:661-663 'a trailing empty/margin-only box pushes content_bottom but must not open a fresh page') — WPT/Chrome expects 3 pages from bare height. Secondary mismatch on page 1: width:max-content is not parsed (no MaxContent variant in flexpdf-css), so the abspos inside the fixed shrinks to ~min-content and the link wraps one word per line ('This/should/be on/...') vs the ref's two full lines. The fixed box itself does repeat (but there is only 1 page).
New bucket: root element with display:table mis-sized. Measured at 96dpi: green border box (0,0)-(219,599) — inline-size 220 = min-content (widest inline-block 200 + 2x10 border) so the 80px inline-block wraps to a second row; block-size stretched to fill the 600px viewport (the assert explicitly forbids this); margin:auto not applied (x=0, ref centers a 300px-wide box at x=250 with height 320). Three root-element-specific sizing defects, diff=100480.
New bucket: position:relative on a table-row does not act as containing block — the abspos div.abspos descendants of the cells are dropped from the render entirely (no green pixels anywhere; only the red static divs paint as a 100x100 block where ref has green; diff=10001). Contrast with children-003..006 where ICB-parented abspos boxes do render (at origin): OOFs whose containing block is a table-internal box are lost during table layout.