Windows daily driver (nishi.exe) vs the Chrome and Edge oracles, measured by the standing top-20 census (OCR reading-recall, permille vs Chrome=1000). Everything below is measured, gated, and reproducible; images are the actual renders.
Two resolver keystones closed the day. (1) Percentage heights resolve to auto against indefinite parents (CSS 2.1 §10.5) — html,body{height:100%} had been resolving against the viewport WIDTH, manufacturing ~1,050px phantom containers: the CSS-on first-screen void, and google's blank first screen (its CSS is inline, so this bit even with CSS off). Google went 0 → 387‰ CONTENT-OK — the synthesized "Google Search / I'm Feeling Lucky" button labels now sit in the first viewport. (2) One shared font-size value resolver for measure and paint: px/%/em/rem/fractions, with calc() and keywords dropped like CSS drops unevaluable declarations. The kill: font-size:0.875rem had digit-scanned to ZERO — wikipedia sizes everything in rem, so styled runs measured at width 0 (the 1-char columns) and the vector-measure page collapsed to 37% height. After: 94–101% of Chrome's height.
One more universal defect fell out of the same x-ray: the absolute CSS units were unhandled. font-size:10pt resolved to 10px instead of 13.3px — and news.ycombinator.com sizes its entire page in pt, so with author CSS on every run dropped under the OCR legibility cliff (its measured 438→0). Added pt/pc/in/cm/mm per CSS Values §5 (1in = 96px = 72pt = 6pc = 2.54cm), with the existing 13.5px→13 truncation contract preserved and verified by a 6-row unit ladder. With sizes correct, hackernews' remaining gap is now cleanly isolated as table column-width layout — its cells scatter while the page height proves the content is there. Named, filed, and probe-ready rather than guessed at.
Census pair verdict (the standing gate): OFF 414‰ vs ON ~242 on shared rows — CSS stays off for now; the styled-collapse blockers are named exactly (x 878→151, linkedin 843→159, hackernews 438→0) plus the OCR ruler's sub-14px cliff under-crediting styled text. Day arc: 300 → 414‰ (+38%), every step through probes, 20-tooth gates, and the 7-gate sweep. New standing tools: the layout x-ray (@region/@textsweep/@decls), the census-pair decision instrument, and the bitmap/vector A/B flag.
The deepest find of the day: the tokenizer's raw-text consumer leaves the cursor AT the close tag ("the next token IS the END_TAG") — but the tree builder ALSO popped eagerly after consuming, so the arriving END_TAG popped an ANCESTOR. Every <script>/<style>/<title> amputated one tree level on every page: body hung off the root, a script inside body re-parented all following content (probe: x=44→0), and script-bearing containers lost their spines — which WAS the "flattening" rock AND the catastrophic CSS sliver. The element extractor had the mirror bug: it tokenized script BODIES, so tag-like text in JS strings minted phantom elements that skewed every later element's identity. Both walkers fixed; probes + 20-tooth gate + 7-gate sweep GREEN.
Also from the same fix: netflix height 386%→152% (now CONTENT-OK), ebay 18.7k→8.9k px, shared-row census mean 344→365‰. Plus <input value=...> labels are now synthesized as text boxes — "Google Search" / "I'm Feeling Lucky" render as real buttons' text (google's remaining gap: its form sits ~3,300px down in source-order flow until CSS centering lands). Board: seq1132 + seq1137 EATEN; residual CSS-on defects filed precisely as seq1150.
build_nishiexe.sh wrote /tmp/nxwin.s while the PE wrapper nx_pe_compile_win_gui reads _offc/nishi_gui.s — so every rebuild re-wrapped 12-day-old assembly. Timestamp fresh, code old. The whole "CSS makes it worse" era and the 6,598-vs-18,500px GUI/shot paradox (seq1110) were this one build-lane bug. Proof: identical bytes through the fixed lane — GUI page_h 19,263 → 6,615 (Chrome ~7,000), box count exactly matching the reference renderer (2077). The GUI now writes an instrument line (boxes/vw/plen/bytesum) into its shot metadata so a stale binary can never hide again.
The first honest build exposed black "blobs" down the left edge of real pages. Zoomed 4x, the blobs are readable: Do/na/te … cc/ou/nt — wikipedia's hidden header links. Text under a display:none element was never laid out (kept x=0,y=0,w=0,h=0) but the painter drew it anyway, char-wrapped at zero width, every hidden run overprinting at the origin.
Fix (3 guards at the shared core): the paint passes skip never-laid text boxes (h==0), the image blit skips never-laid boxes, and the inline flow now applies display:none like the block path — hidden inline spans finally hide. Regression-proofed: the bg gate grew 17 → 20 teeth (visible-control, hidden-block, hidden-inline); the 7-gate sweep stayed GREEN.
With the rail gone, wikipedia's first screen was still TOC-first (article below the fold). The UA sheet now hides the .vector-toc* chrome (same policy as the existing wiki-nav hides) — the first screen is now the title, lead and hatnote, like Chrome's. Height ratio 99% of the Chrome oracle.
Found on the way: the box tree flattens deep nesting (descendants become siblings), so hiding only the TOC container could not hide its items — filed as seq1137, the next structural rock.
Through honest binaries, author CSS wins on stackoverflow (232 vs 170‰, page_h 6,615 vs Chrome ~7,000; 281‰ vs the Edge oracle) — but the full census pair says OFF: mean 348‰ CSS-off vs 148‰ CSS-on. Author CSS currently collapses x (878→0), duckduckgo (833→0) and wikipedia into unreadable slivers. CSS_ENABLED stays 0; the sliver (seq1132) is the named gate to flipping it.
Rows were flex containers, so every table cell got an equal share of the width regardless of content — a table-built site like hackernews scattered its columns. Implemented the CSS 2.1 auto table algorithm: column width = max-content across all rows, shared down the column, with nested tables saving and restoring their own column context (hackernews nests them). Tables are recognised through a table{display:table} UA rule, the same trick already used for flex and grid, since the box tree carries no tag names. Result on table-built sites: hackernews 438 → 471‰, ebay 178 → 229, yahoo 125 → 163.
The aggregate first read as a regression (414 → 396) because google scored 161. It was not a regression: the same binary renders both the saved page and a fresh fetch at 714px with the button correctly placed — google simply serves a different homepage variant per request. Excluding it, the census is flat (415 vs 416). That near-miss produced the fix: a deterministic saved-page A/B harness, so a layout change is judged on identical bytes and the live census measures the network-facing product separately. Live-page variance had already contaminated one earlier read; it will not contaminate a third.
colspan now works end to end: the tree builder stashes the span on the cell box (clamped against hostile values), column resolution spreads a spanning cell's content width ACROSS its span, and the row path gives it the sum of its columns. The hackernews-shaped control probe is pixel-correct — rank / vote / title columns aligned across rows, the colspan=2 subtext starting at the vote column directly under its story, exactly Chrome's arrangement. The deterministic A/B confirms zero blast radius: every corpus page byte-identical except hackernews itself.
The real hackernews page still misplaces its subtext — and three x-ray commands localized why: on the live page the inner table box is 19px tall and the story rows attach to the containing cell as its siblings, outside the table, so they consume the outer table's columns. Two minimal reproducers (bare nested tables; nested tables with HN's exact attribute shapes) both refused to fail — the nesting break needs the real page's full context. Next step is a mechanical prefix-bisect of the saved 42KB page; the finding stays filed as open (seq1159) because the acceptance number is not met. The board reflects reality, not effort.
HTML5-lite end-tag matching — the sibling of the raw-text double-pop. Inside hackernews' vote cell, <center><a><div> made the block-resync pop the open anchor, then its </a> popped <center>, </center> popped the cell, and every element after it escaped the table. End tags now match the nearest open element by name (pop through on a deeper match, ignore when the element was already resync-popped). Effect: hackernews 471 → 695‰ at 92% of Chrome's height, wikipedia CSS-on to 99% height, and the sixth census record of the day: 432‰ (the arc: 300 → 348 → 350 → 384 → 414 → 432).
The styled-page UA correction. A theory that Chrome indents wikipedia died on one pixel probe — Chrome's first ink is at x=24; its sidebar grid needs a 1120px viewport. The offender was ours: our UA sheet's 44px body padding (a readability choice for unstyled pages) survived under author CSS, pushing every styled page right of Chrome. Now a Chrome-parity body{padding:8px} is injected between our UA sheet and the page's own CSS. Structural matching on styled wikipedia went 807 → 846‰ deep-page and 538 → 692‰ on the first screen. Landed alongside: max-width, auto-margin centering, the grid-template shorthand, and rem/fraction grid tracks.
JavaScript, phase 1 of a frontier-driven plan: generators (function*, yield, yield*) and object getters/setters now parse, with execution honestly stubbed where full semantics are a separate rung. Netflix's parse frontier nearly doubled — 860,389 → 1,631,853 bytes of its 4.1MB bundle; conformance held at 92/92 and the 7-gate sweep stayed green throughout. The next construct is already named by the same instrument: object spread.
Three-browser parity is live. One command now captures Chrome and Waterfox and grades both: wikipedia at 96% of oracle height, 896‰ against Chrome and 897‰ against Waterfox — two independent engine families agreeing on our render to within one permille. (A first run scored a meaningless 70‰ because Waterfox ignored a lone window-size flag and shot at 1366px; verifying capture dimensions caught it. An oracle at a different viewport is not an oracle.)
Author CSS on, rendered by the Nishi engine. These are the sites that collapsed into unreadable slivers a day earlier.
LinkedIn's styled first screen across three consecutive fixes — 229 → 583 → 688 → 750‰:
| site | class | ratio% | recall ‰ | note |
|---|---|---|---|---|
| duckduckgo | CONTENT-OK | 10 | 904 | site RECORD |
| x | SPARSE-NISHI | 6 | 878 | record band |
| example | CONTENT-OK | 12 | 842 | |
| SPARSE-NISHI | 79 | 833 | was rail-corrupted: +71 from fix | |
| wikipedia | CONTENT-OK | 99 | 444 | 61 before this session |
| hackernews | CONTENT-OK | 135 | 444 | |
| bbc | SPARSE-NISHI | 113 | 292 | |
| github | CANVAS-OFF | 93 | 276 | |
| stackoverflow | SPARSE-NISHI | 112 | 167 | 233 with CSS on |
| ebay | STRIP-COLLAPSE | 5296 | 120 | height blowup rock |
| yahoo | CONTENT-OK | 41 | 142 | |
| netflix | CANVAS-OFF | 386 | 30 | SPA + height rock |
| BLANK-NISHI | 69 | 0 | renders 5506px, OCRs 0: invisible-ink class | |
| STRIP-COLLAPSE | 3 | 0 | SPA shell |
Mean 384‰ over 14 measured rows; FETCH-EMPTY: youtube, reddit, instagram, craigslist; CHROME-BLOCKED (no oracle): amazon, bing. Sweep 7/7 GREEN after every change.
Eaten today: seq1110 (stale-lane paradox), seq1130 (hidden ink), seq1131 (wiki viewport). Filed: seq1129 (15 PE wrappers still read /tmp — the same stale trap armed), seq1132 (CSS-on sliver — the gate to author CSS), seq1137 (box-tree flattening breaks hide-subtree + hit-test). Next by evidence: google invisible-ink 0‰ · CSS-off height inflation (netflix/ebay/stackoverflow) · seq1132 · seq1137 · the 4 FETCH-EMPTY sites.
evidence id: census-record-384 · generated 2026-07-28 · instruments: nx_top20_parity + nx_visual_diff + Windows.Media.Ocr · gates: browser_regress_all 7/7, bg gate 20/20