diff --git a/README.md b/README.md index 3f63c7ff4..89eba2a82 100644 --- a/README.md +++ b/README.md @@ -260,3 +260,10 @@ safe renderer for arbitrary untrusted websites or scripts. The repository uses the terms in [LICENSE](LICENSE), including its Restricted Party Clause. Describe it as a custom source-available license, not unqualified MIT or an OSI-approved open-source license. + +## Native Web: compiled HTML/CSS and C++ + +The [Native Web sample](samples/NativeWeb/README.md) compiles HTML/CSS into C++ and +runs C++ application logic on WebScene's native DOM/layout with Foco's Cocoa/Metal +host, without deploying V8 or runtime UI parsers. This is an initial, explicitly +bounded compiler profile. See the [architecture and future binding note](docs/design/native-web.md). diff --git a/docs/architecture/adr/0014-mixed-language-compiled-applications.md b/docs/architecture/adr/0014-mixed-language-compiled-applications.md new file mode 100644 index 000000000..d1571bad3 --- /dev/null +++ b/docs/architecture/adr/0014-mixed-language-compiled-applications.md @@ -0,0 +1,58 @@ +# ADR 0014: Mixed-language application logic over compiled views + +Status: Accepted design; mixed-language implementation is subsequent work. +Date: 2026-09-10 + +## Decision + +Compiled HTML/CSS does not prescribe the language of application logic. WebScene +must support C++ and optional JavaScript/TypeScript logic together on the same +native document. Developers can migrate an existing application incrementally, +component by component, while retaining its compiled views and templates. +TypeScript is compiled to JavaScript by application tooling; it is not a separate +runtime or an automatic TypeScript-to-C++ conversion path. + +Use WebScene's annotation-driven interop generator for typed calls, callbacks and +native object access in both directions. Both language paths must operate on the +same document, node identities, events, CSS/layout engine and Canvas/WebGPU +resources. Adding JavaScript must not create a parallel DOM, duplicate scene, +second renderer or require runtime HTML/CSS parsing of compiled views. + +Application state remains outside generated views. Each state object has an +explicit owner; generated bridges expose access and change notifications rather +than silently copying authoritative state between languages. This also leaves a +seam for future typed C++ view models and HTML bindings. + +## Required integration contracts + +- Preserve node identity through native handles and JavaScript wrappers. +- Define ownership, weak references, callback disposal and runtime shutdown so + neither language can retain usable references to disposed native objects. +- Respect document thread affinity; cross-thread calls require explicit dispatch. +- Define error propagation and reentrancy for native-to-JS and JS-to-native calls. +- Keep document mutation, event ordering and rendering behavior consistent across + languages. Native Canvas/WebGPU objects must be exposed through the same backend. +- Generated view APIs use C++20 modules; interop remains a language-neutral seam + and does not require other languages to consume C++ module binaries. + +## Deployment and migration + +Pure-native applications continue to require no JavaScript runtime, V8 linkage, +initialization or deployed runtime assets. The mixed-language profile opts into +those dependencies explicitly. Interop wrappers are optional dependencies of the +native document engine, not prerequisites for compiled view construction. + +A migration can retain existing JS/TS controllers, use compiled templates for +view creation, and replace individual controllers/services with C++ behind typed +interop contracts. Converting application logic must not require replacing the +view or changing its document identity. Arbitrary runtime HTML construction is +outside the compiled-view contract; dynamic native UI uses predefined templates. + +## Scope and verification + +This decision expands the platform design, not the current Kestrel acceptance +criteria. Kestrel remains an HTML/CSS/C++ application with no JavaScript runtime +and no runtime HTML parsing. Mixed-language support must later be verified with +bidirectional calls, shared-node mutations, events, lifetime/cleanup tests and a +real incremental migration example. This ADR does not claim those tests or the +complete integration exist today. diff --git a/docs/design/evidence/hybrid-kestrel/pan.json b/docs/design/evidence/hybrid-kestrel/pan.json new file mode 100644 index 000000000..f435a5e6d --- /dev/null +++ b/docs/design/evidence/hybrid-kestrel/pan.json @@ -0,0 +1,11 @@ +{ + "actual_presentations": 719, + "pan_seconds": 11.999957999985781, + "presentation_hz": 59.91625597367178, + "median_interval_ms": 16.66675000160467, + "p95_interval_ms": 16.66683300572913, + "max_interval_ms": 33.33350000320934, + "submit_to_present_median_ms": 47.388667007908225, + "rss_after_pan_kib": 297872, + "note": "Submit-to-present is not input-to-photon latency. RSS sampled after benchmark, not peak." +} \ No newline at end of file diff --git a/docs/design/evidence/hybrid-kestrel/parity.json b/docs/design/evidence/hybrid-kestrel/parity.json new file mode 100644 index 000000000..d28ede31b --- /dev/null +++ b/docs/design/evidence/hybrid-kestrel/parity.json @@ -0,0 +1,29 @@ +[ + { + "width": 1280, + "height": 800, + "theme": "dark", + "tab": "Home", + "parsed_nodes": 376, + "compiled_nodes": 376, + "differences": [] + }, + { + "width": 980, + "height": 620, + "theme": "dark", + "tab": "Text", + "parsed_nodes": 298, + "compiled_nodes": 298, + "differences": [] + }, + { + "width": 1440, + "height": 900, + "theme": "light", + "tab": "Drafting", + "parsed_nodes": 311, + "compiled_nodes": 311, + "differences": [] + } +] diff --git a/docs/design/evidence/hybrid-kestrel/smoke.json b/docs/design/evidence/hybrid-kestrel/smoke.json new file mode 100644 index 000000000..0ce72e706 --- /dev/null +++ b/docs/design/evidence/hybrid-kestrel/smoke.json @@ -0,0 +1,183 @@ +{ + "checks": [ + { + "ribbon": "Home", + "buttons": 30 + }, + { + "ribbon": "Insert", + "buttons": 17 + }, + { + "ribbon": "Annotate", + "buttons": 18 + }, + { + "ribbon": "Model", + "buttons": 27 + }, + { + "ribbon": "View", + "buttons": 25 + }, + { + "ribbon": "Manage", + "buttons": 19 + }, + { + "ribbon": "Drafting", + "buttons": 22 + }, + { + "ribbon": "Solids", + "buttons": 30 + }, + { + "ribbon": "Parametric", + "buttons": 17 + }, + { + "ribbon": "Assembly", + "buttons": 10 + }, + { + "ribbon": "Blocks", + "buttons": 11 + }, + { + "ribbon": "Text", + "buttons": 19 + }, + { + "ribbon": "Exchange", + "buttons": 10 + }, + { + "ribbon": "Productivity", + "buttons": 10 + }, + { + "command": "layers", + "ok": true, + "title": "Layer manager" + }, + { + "command": "new-layer", + "ok": true, + "title": "Create layer" + }, + { + "command": "units", + "ok": true, + "title": "Drawing units & precision" + }, + { + "command": "help", + "ok": true, + "title": "Welcome to Kestrel CAD" + }, + { + "command": "diagnostics", + "ok": true, + "title": "Renderer diagnostics" + }, + { + "command": "palette", + "ok": true, + "title": "Renderer diagnostics" + }, + { + "command": "group", + "ok": false, + "error": "Error: Select at least 2 editable objects first." + }, + { + "command": "text", + "ok": true, + "title": "Create text" + }, + { + "command": "dimension", + "ok": true, + "title": "Create text" + }, + { + "command": "hatch", + "ok": true, + "title": "Create text" + }, + { + "command": "array", + "ok": false, + "error": "Error: Select an editable object first." + }, + { + "command": "transform3d", + "ok": false, + "error": "Error: Select an editable object first." + }, + { + "command": "dwg-setup", + "ok": true, + "title": "DWG codec status" + }, + { + "command": "mtext", + "ok": true, + "title": "Create rich MTEXT" + }, + { + "command": "dimstyles", + "ok": true, + "title": "Dimension styles" + }, + { + "command": "leader", + "ok": true, + "title": "Create leader" + }, + { + "command": "table", + "ok": true, + "title": "Create table" + }, + { + "command": "stretch", + "ok": true, + "title": "Stretch crossing vertices" + }, + { + "command": "layout-manager", + "ok": true, + "title": "Scaled paper layouts" + }, + { + "command": "ucs-manager", + "ok": true, + "title": "User coordinate system" + } + ], + "startup": { + "entities": 265, + "nodes": 781, + "backend": "Canvas 2D \u00b7 Compatibility" + }, + "strict": true, + "mtext_preview": { + "nodes": 4, + "report": "2 lines, 120.00 \u00d7 16.67 mm. " + }, + "history": { + "n": 265, + "added": 266, + "undone": 265, + "redone": 266 + }, + "worker_available": true, + "dxf_export": { + "length": 53542, + "eof": true + }, + "caught_failures": [], + "errors": [] +} diff --git a/docs/design/hybrid-kestrel-epic.md b/docs/design/hybrid-kestrel-epic.md new file mode 100644 index 000000000..699c463ae --- /dev/null +++ b/docs/design/hybrid-kestrel-epic.md @@ -0,0 +1,126 @@ +# Hybrid Kestrel delivery epic + +## Decision and ownership + +Deliver the complete existing JavaScript CAD application on Foco's established +WebScene VSync/WebGPU host, with compiled original HTML/CSS and native template +construction. JavaScript owns CAD state, commands, selection, history and renderer +state. Do not run the separate native CAD controller alongside it. General CAD +ports to C++ are paused. The independent native-only sample remains supported. + +Hybrid execution is optional. A pure C++ application must build, run and package +without V8 linkage, initialization or deployed JavaScript assets. Compiler output +and the native document library must not acquire a dependency on the optional V8 +adapter. Retain separate native-only package audits and runtime tests. + +WebScene owns compilation, DOM, CSS, layout and optional scripting. Foco supplies +platform services, composition and rendering. Both authoring languages operate on +one engine-owned document on its owner thread. Generated views do not own CAD +state. C++ modules remain the generated authoring format. Preserve named refs and +source metadata for later hot design; implement no reload machinery here. + +## One delivery, ordered implementation + +1. **Shared runtime:** native factories return normal DOM nodes; compiled roots + enter the existing navigation lifecycle before scripts. Preserve focus, + listeners, node identity, stylesheet ownership, base URLs and readiness events. +2. **Compiler/package integration:** emit engine-compatible constructors and + prepared stylesheet data from unchanged upstream markup. Add a versioned + language-neutral host entry point, copied package descriptors and explicit + worker-thread construction/disposal. Package resources and scripts locally. +3. **Kestrel templates throughout:** audit producers as well as HTML API consumers. + Convert dynamic ribbon, explorer, properties, menus, dialogs, extension UI, + icons and print/export UI into compiled templates with structured data and + normal JS event callbacks. Preserve original HTML/CSS. Retain the complete + original CAD script set and its ordering. Do not treat the 27 API sites as a + complete producer count. +4. **Foco hybrid application:** use the existing WebScene integration and renderer. + Wire one model and renderer, resource loading, file operations and truthful + optional-service availability. Keep browser-compatible source authoring. +5. **Acceptance:** verify commands and extension dialogs, visual parity at multiple + sizes/themes, offline relocated bundle, shutdown and input ownership. Measure + presented-frame panning and actual OS resize, startup, memory, package size, + build cost and interaction latency. Run native-only and existing-host regressions. + +These are internal checkpoints of one epic, not separate accepted deliveries. + +## Runtime HTML compatibility + +The framework hybrid profile permits runtime HTML by default: existing JavaScript +can use `innerHTML`, `insertAdjacentHTML`, DOMParser and contextual fragments while +migrating gradually. Those nodes use the same DOM as native templates. + +Kestrel selects a strict compiled-template profile. Nonempty HTML parser requests +must fail with actionable errors before destroying existing content. Empty clears +and text/DOM operations remain usable. Block indirect frame/document parsing too; +no silent parsed-shell or template fallback. This restriction belongs to the +application profile, not all WebScene embedders. A pure C++ package does not include +the runtime parser or V8 at all. + +## Implementation and validation (2026-09-11) + +Implemented the optional compiled engine package, versioned host ABI, Foco hybrid +sample/packager and Kestrel-specific migration frontend. The unchanged root HTML +and CSS produce a C++ module; 238 templates cover dynamic markup producers, +including native SVG variants for rich text and print/export content. All 37 +application scripts retain CAD behavior. Packaged Blob workers now capture their +same-origin source before entering the worker isolate, preserving original async IO. + +The bundle starts with 265 entities and 781 DOM elements. Runtime tests cover +shared node identity, listener cleanup, focus, compiled lifecycle and strict versus +compatible HTML policies. Compiler regression covers deterministic module output, +inert template CSS/scripts, raw-text slots, namespaces and dependencies. Replacing +children now flattens fragments and applies structural selectors after all siblings +are attached. This fixes missing nested controls and the one-pixel ribbon-border +parity defect. + +Evidence: + +- Native-only suite: 22/22 passed; rebuilt FocoKestrelPreview dependency/symbol/asset + audit passes with no V8 or HTML parser symbols. +- Foco WebScene regressions: 4/4 passed (Graphite, modules, adapter, native storage). +- Hybrid runtime and compiler tests pass. +- Compiled/parsed parity: zero differences in the selected ribbon/explorer/inspector + nodes at 1280×800 dark/Home (376 nodes), 980×620 dark/Text (298), and 1440×900 + light/Drafting (311). This is targeted DOM/style/layout parity, not exhaustive + browser pixel equivalence. +- Expanded ABI smoke: all ribbon tabs, 20 command/dialog paths, MTEXT native SVG, + strict rejection, undo/redo and 53,542-byte DXF worker export pass. Original CAD + code owns the state throughout. +- Packaged window visually verified with WebGPU, 4× MSAA and the original layout; + real macOS drag-resize reflows the UI. Bundle dependency/signature audit passes; + copied bundle launches from a temporary directory without loose source assets. +- Initial 12-second GPU pan trace: 720 actual presentations, 59.9997 Hz; median + 16.66675 ms and p95 16.66679 ms intervals. Median submit-to-present is 63.22 ms; + that is not input-to-photon latency. No equivalent old-host latency baseline was + established by this run. Rebuild/package takes about 22–28 seconds on the warm + configured trees; package size is approximately 103 MB. These are development + builds, not stripped release-size or cold-build claims. +- Final relocated build with the IO worker active: 719 actual presentations in + 12 seconds (59.916 Hz), one 33.33 ms interval; median submit-to-present 47.39 ms. + RSS after the pan was 297,872 KiB (291 MiB). First host presentation was observed + at about 0.88 seconds; this includes an initial frame and is not CAD-ready time. + The final warm packaging run took 17.13 seconds. Raw test summaries are in + `evidence/hybrid-kestrel/`; use `tests/NativeWeb/analyze_hybrid_pan.py` with the + benchmark log and `FOCO_PRESENT_TRACE_JSONL` output to repeat frame analysis. + +## Remaining acceptance and existing platform limits + +The hybrid implementation is running end to end; **the complete acceptance matrix +is not closed**. WebScene's existing `window.open` only supports external URL +handoff. Kestrel's blank-window print preview and browser printing therefore remain +unsupported, even though their markup and SVG producers now compile. Adding native +print/multiwindow support is still required for that part of original behavior. +Do not call compilation of those paths proof that printing works. + +The sample packages its required assets offline (system fonts/inline SVG for the +base UI, embedded scripts/worker, local runtime dependencies). A general resource +compiler for arbitrary additional image/font URLs is still broader work. The +optional DWG/OpenCascade bridges remain governed by upstream availability checks. +True input-to-photon latency, exhaustive CAD command coverage and full browser +pixel conformance are not established by the targeted acceptance tests. + +Keep these limitations distinct from hybrid optionality: the V8-free C++ profile +remains buildable and tested. Future C++ viewmodels/DataContext and `{Binding}` in +HTML, compiled SVG path data, broader SDK packaging and hot design remain separate +design work; hybrid execution does not make any of them prerequisites. diff --git a/docs/design/native-web-compiler-audit.md b/docs/design/native-web-compiler-audit.md new file mode 100644 index 000000000..5769f8912 --- /dev/null +++ b/docs/design/native-web-compiler-audit.md @@ -0,0 +1,1844 @@ +# Native Web compiler support audit + +Status: open. Compiler audit and gap closure take priority over further Kestrel +application porting. Preserve original inputs; preview omission is not support. + +Baseline regenerated on 2026-09-10 at revision 4883452c: the reference stylesheet +contains 397 rules and 1475 declarations, with 80 distinct unsupported constructs. +This corpus is a compatibility input, not the complete compiler specification. +Audit supported features too: accepting syntax does not prove correct semantics. + +## Current compatibility checkpoint + +At implementation revision `6702b62e`, the unchanged reference stylesheet reports +**55 distinct unsupported constructs** across **397 rules / 1475 declarations**, +compared with the historical 80-construct baseline above. This is a diagnostic +inventory count, not percentage compatibility or visual parity. No Kestrel launch +or new application porting was performed for this checkpoint. + +Reference SHA-256: `4a6ce8c12c047367e92424a545e7b6142a1a3d19a576896d53644e17e2d85492`. +Command: `artifacts/native-web-modules/webscene-uic --check-css samples/NativeKestrel/reference/src/style.css`. +Full output: [compatibility checkpoint](native-web-css-checkpoint.txt). + +Remaining groups include pseudo-elements/generated content, conditional rules and +animation, gradients/two-color mixing/shadows, grid placement, overflow typography, +and platform/control presentation. Continue independent compiler audit fixtures; +this corpus does not change the work order below. + +The user has now requested one integrated implementation pass for all 55 remaining +constructs. The complete per-construct ledger, dependency order and acceptance gates +are in [the remaining-55 plan](native-web-remaining-55-plan.md). That plan controls +this batch; it does not replace the broader compiler and Kestrel acceptance gates. + +## Work order and closure gates + +| Order | Feature family | Required closure evidence | Status | +| --- | --- | --- | --- | +| 1 | Lexing, numeric grammar, declaration extraction and diagnostics | Valid CSS numeric forms; nested functions; invalid-source diagnostics with locations; inspect apparent truncated `color:var(` before assigning blame | Open | +| 2 | HTML semantics, attributes and compiled templates | Inventory elements/attributes; native form/control behavior; preserved template structure, references and disposal; no runtime HTML parsing | Open | +| 3 | Cascade, selectors, variables and conditional rules | Initial/inherited/unset behavior, specificity, pseudo-elements, media conditions, dynamic mutations; parsed/compiled differential tests | Open | +| 4 | Layout and typography | Insets, calc, grid placement, wrapping, ellipsis, font behavior; resize and mutation comparisons | Open | +| 5 | Paint and SVG | Gradients, color mixing, borders/outlines, shadows, transforms, filters, SVG stroke/text; rendered comparisons | Open | +| 6 | Input and native control presentation | Cursor, selection, touch action, scrollbars, resizing and form colors; interaction tests | Open | +| 7 | Animation and resource pipeline | Keyframes/transitions/reduced motion; embedded images/fonts; packaged offline verification | Open | +| 8 | Strict compilation and regression closure | Original inputs compile without preview omissions; full tests and rendered/interactive comparisons; remaining exclusions explicitly resolved | Open | + +For each gap, record the source construct, responsible layer (compiler, native +engine, host or resource pipeline), implementation commit, regression fixture and +validation result. Group related grammar/semantic changes rather than adding +isolated sample-specific exceptions. Do not mark a group complete from a lower +warning count alone. Deliberately unsupported browser-only behavior needs an +explicit semantic decision, not a silent no-op. + +## Reproduction + +Run `webscene-uic --check-css samples/NativeKestrel/reference/src/style.css`. +For structural diagnostics, compile the original index with `--preview` into a +temporary module and inspect all warnings. Preview is an inventory aid only. +Extend this audit to template files, inline styles and independent feature fixtures. +The HTML inventory below is provisional; warning coverage itself must be checked. + +## Execution discipline + +Complete this audit before resuming Kestrel-driven feature porting. Work through +feature families in the order above, using independent HTML/CSS fixtures first; +Kestrel remains an unchanged compatibility corpus. Within each family: + +1. Inventory accepted and rejected syntax, including inline styles and templates. +2. Separate missing compiler lowering from missing engine or host semantics. +3. Implement coherent grammar/behavior groups and test invalid inputs as well as + successful compilation, mutation, layout and paint where applicable. +4. Record remaining exclusions and evidence here. A family remains open until its + closure gate is met; fewer preview warnings alone do not close it. + +Next audit work should return to the earliest open gates: source locations and +numeric/function grammar, followed by the HTML element/attribute/template +inventory. Paint investigations below identify later engine work rather than +changing this order. Browser differential and packaged-resource verification +remain required before overall closure. + +## CSS baseline diagnostics + +```text +samples/NativeKestrel/reference/src/style.css: error: #command-input::placeholder: unsupported selector: #command-input::placeholder +samples/NativeKestrel/reference/src/style.css: error: #ribbon-tab-list button.active:after: unsupported selector: #ribbon-tab-list button.active::after +samples/NativeKestrel/reference/src/style.css: error: -webkit-font-smoothing:antialiased: unsupported Native Web CSS property: -webkit-font-smoothing +samples/NativeKestrel/reference/src/style.css: error: .document-tab.active:after: unsupported selector: .document-tab.active::after +samples/NativeKestrel/reference/src/style.css: error: .panel-tabs button.active:after: unsupported selector: .panel-tabs button.active::after +samples/NativeKestrel/reference/src/style.css: error: .progress-line:after: unsupported selector: .progress-line::after +samples/NativeKestrel/reference/src/style.css: error: .property-section-title:before: unsupported selector: .property-section-title::before +samples/NativeKestrel/reference/src/style.css: error: @keyframes progress: unsupported at-rule or condition +samples/NativeKestrel/reference/src/style.css: error: @keyframes toast-in: unsupported at-rule or condition +samples/NativeKestrel/reference/src/style.css: error: @media (prefers-reduced-motion:reduce): unsupported at-rule or condition +samples/NativeKestrel/reference/src/style.css: error: @media print: unsupported at-rule or condition +samples/NativeKestrel/reference/src/style.css: error: accent-color:var(--accent): compiled var() not supported for property: accent-color +samples/NativeKestrel/reference/src/style.css: error: animation:none: unsupported Native Web CSS property: animation +samples/NativeKestrel/reference/src/style.css: error: animation:progress 1.2s infinite ease-in-out: unsupported Native Web CSS property: animation +samples/NativeKestrel/reference/src/style.css: error: animation:toast-in .15s ease-out: unsupported Native Web CSS property: animation +samples/NativeKestrel/reference/src/style.css: error: backdrop-filter:blur(3px): unsupported Native Web CSS property: backdrop-filter +samples/NativeKestrel/reference/src/style.css: error: backdrop-filter:blur(9px): unsupported Native Web CSS property: backdrop-filter +samples/NativeKestrel/reference/src/style.css: error: background:color-mix(in srgb,var(--active) 63%,var(--panel)): compiled color-mix currently supports an sRGB color percentage mixed with transparent +samples/NativeKestrel/reference/src/style.css: error: background:linear-gradient(125deg,var(--panel2),var(--panel)): unsupported custom-value token: linear-gradient(125deg,var(--panel2),var(--panel)) +samples/NativeKestrel/reference/src/style.css: error: background:linear-gradient(145deg,var(--panel2),var(--panel)): unsupported custom-value token: linear-gradient(145deg,var(--panel2),var(--panel)) +samples/NativeKestrel/reference/src/style.css: error: background:none: color profile requires #rgb, #rgba, #rrggbb, #rrggbbaa, black, white or transparent +samples/NativeKestrel/reference/src/style.css: error: border-collapse:collapse: unsupported Native Web CSS property: border-collapse +samples/NativeKestrel/reference/src/style.css: error: border:1px dashed #65c5a4: border shorthand currently requires width solid color, 0 or none +samples/NativeKestrel/reference/src/style.css: error: border:2px dashed var(--accent): border shorthand currently requires width solid color, 0 or none +samples/NativeKestrel/reference/src/style.css: error: bottom:calc(var(--command-height) + 74px): unsupported custom-value token: calc(var(--command-height) +samples/NativeKestrel/reference/src/style.css: error: box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 25%,transparent): unsupported custom-value token: color-mix(in +samples/NativeKestrel/reference/src/style.css: error: box-shadow:inset 0 -2px 0 var(--accent): native compiled inset shadows are not supported yet +samples/NativeKestrel/reference/src/style.css: error: box-shadow:inset 0 0 0 1px var(--accent-dim): native compiled inset shadows are not supported yet +samples/NativeKestrel/reference/src/style.css: error: box-shadow:inset 2px 0 0 var(--accent): native compiled inset shadows are not supported yet +samples/NativeKestrel/reference/src/style.css: error: color-scheme:dark: unsupported Native Web CSS property: color-scheme +samples/NativeKestrel/reference/src/style.css: error: color-scheme:light: unsupported Native Web CSS property: color-scheme +samples/NativeKestrel/reference/src/style.css: error: color:var(: unclosed variable reference +samples/NativeKestrel/reference/src/style.css: error: content:"": unsupported Native Web CSS property: content +samples/NativeKestrel/reference/src/style.css: error: content:"⌄": unsupported Native Web CSS property: content +samples/NativeKestrel/reference/src/style.css: error: cursor:col-resize: unsupported Native Web CSS property: cursor +samples/NativeKestrel/reference/src/style.css: error: cursor:crosshair: unsupported Native Web CSS property: cursor +samples/NativeKestrel/reference/src/style.css: error: cursor:grabbing: unsupported Native Web CSS property: cursor +samples/NativeKestrel/reference/src/style.css: error: cursor:move: unsupported Native Web CSS property: cursor +samples/NativeKestrel/reference/src/style.css: error: cursor:not-allowed: unsupported Native Web CSS property: cursor +samples/NativeKestrel/reference/src/style.css: error: cursor:pointer: unsupported Native Web CSS property: cursor +samples/NativeKestrel/reference/src/style.css: error: cursor:row-resize: unsupported Native Web CSS property: cursor +samples/NativeKestrel/reference/src/style.css: error: dialog::backdrop: unsupported selector: dialog::backdrop +samples/NativeKestrel/reference/src/style.css: error: filter:brightness(1.1): unsupported Native Web CSS property: filter +samples/NativeKestrel/reference/src/style.css: error: font-synthesis:none: unsupported Native Web CSS property: font-synthesis +samples/NativeKestrel/reference/src/style.css: error: grid-column:1/-1: unsupported Native Web CSS property: grid-column +samples/NativeKestrel/reference/src/style.css: error: inset:0: unsupported Native Web CSS property: inset +samples/NativeKestrel/reference/src/style.css: error: inset:15px: unsupported Native Web CSS property: inset +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:-.4px: unsupported length: -.4px +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:.1px: unsupported length: .1px +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:.25px: unsupported length: .25px +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:.2px: unsupported length: .2px +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:.35px: unsupported length: .35px +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:.5px: unsupported length: .5px +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:.6px: unsupported length: .6px +samples/NativeKestrel/reference/src/style.css: error: letter-spacing:.7px: unsupported length: .7px +samples/NativeKestrel/reference/src/style.css: error: opacity:.34: invalid numeric value +samples/NativeKestrel/reference/src/style.css: error: opacity:.45: invalid numeric value +samples/NativeKestrel/reference/src/style.css: error: opacity:.8: invalid numeric value +samples/NativeKestrel/reference/src/style.css: error: outline-offset:-2px: unsupported Native Web CSS property: outline-offset +samples/NativeKestrel/reference/src/style.css: error: outline:2px solid var(--accent): compiled var() not supported for property: outline +samples/NativeKestrel/reference/src/style.css: error: outline:none: unsupported Native Web CSS property: outline +samples/NativeKestrel/reference/src/style.css: error: overflow-wrap:anywhere: unsupported Native Web CSS property: overflow-wrap +samples/NativeKestrel/reference/src/style.css: error: resize:vertical: unsupported Native Web CSS property: resize +samples/NativeKestrel/reference/src/style.css: error: right:calc(var(--right-width) + 16px): unsupported custom-value token: calc(var(--right-width) +samples/NativeKestrel/reference/src/style.css: error: scrollbar-color:var(--line) transparent: compiled var() not supported for property: scrollbar-color +samples/NativeKestrel/reference/src/style.css: error: scrollbar-width:none: unsupported Native Web CSS property: scrollbar-width +samples/NativeKestrel/reference/src/style.css: error: scrollbar-width:thin: unsupported Native Web CSS property: scrollbar-width +samples/NativeKestrel/reference/src/style.css: error: stroke-width:.8: unsupported Native Web CSS property: stroke-width +samples/NativeKestrel/reference/src/style.css: error: stroke-width:1.25: unsupported Native Web CSS property: stroke-width +samples/NativeKestrel/reference/src/style.css: error: stroke-width:1.4: unsupported Native Web CSS property: stroke-width +samples/NativeKestrel/reference/src/style.css: error: text-anchor:middle: unsupported Native Web CSS property: text-anchor +samples/NativeKestrel/reference/src/style.css: error: text-overflow:ellipsis: unsupported Native Web CSS property: text-overflow +samples/NativeKestrel/reference/src/style.css: error: touch-action:none: unsupported Native Web CSS property: touch-action +samples/NativeKestrel/reference/src/style.css: error: transform:none: unsupported Native Web CSS property: transform +samples/NativeKestrel/reference/src/style.css: error: transform:translateX(-50%): unsupported Native Web CSS property: transform +samples/NativeKestrel/reference/src/style.css: error: transform:translateY(7px): unsupported Native Web CSS property: transform +samples/NativeKestrel/reference/src/style.css: error: transition:fill .15s: unsupported Native Web CSS property: transition +samples/NativeKestrel/reference/src/style.css: error: transition:none: unsupported Native Web CSS property: transition +samples/NativeKestrel/reference/src/style.css: error: user-select:none: unsupported Native Web CSS property: user-select +samples/NativeKestrel/reference/src/style.css: error: user-select:text: unsupported Native Web CSS property: user-select +397 rules, 1475 declarations, 80 distinct unsupported constructs +``` + +## HTML structural baseline diagnostics + +```text +generic native attribute: accept +generic native attribute: autocapitalize +generic native attribute: autocomplete +generic native attribute: hidden +generic native attribute: href +generic native attribute: placeholder +generic native attribute: spellcheck +generic native attribute: title +generic native attribute: transform +generic native attribute: value +generic native element: a +generic native element: aside +generic native element: dd +generic native element: dialog +generic native element: dl +generic native element: dt +generic native element: form +generic native element: i +generic native element: input +generic native element: kbd +generic native element: option +generic native element: select +generic native element: strong +generic native element: text +skipped noscript +skipped script +``` + +## Closure log + +### Numeric grammar: leading decimals (2026-09-10) + +Implemented signed leading-decimal lengths (`.5px`, `+.5px`, `-.25px`) and +leading-decimal scalar values (`opacity:.8`). Length token recognition in compiled +custom-property expressions uses the same expanded grammar. Regression fixture: +`tests/NativeWeb/Contracts.html` (`numeric-length`); native contract assertions +verify generated dimensions. Compiler and native contract suites pass. + +Fresh corpus result: 397 rules, 1475 declarations, **69 distinct unsupported +constructs**, down from the preserved 80-construct baseline. Numeric grammar is +not closed: exponent notation and property-specific range/normalization behavior +still require review. The `color:var(` diagnostic also remains open; a scan of the +original source found no unclosed `color:var(...)` declaration, so declaration +extraction/serialization needs investigation before classifying it as bad input. + +### Nested function followed by !important (2026-09-10) + +Resolved the apparent `color:var(` truncation in the shared Rust CSS declaration +parser. Reproduced with `.history-error{color:var(--danger)!important}` and two +other original declarations. cssparser deferred skipping the function body until +its next token read, but the declaration reader saved the end-state beforehand. +It consequently sliced the value at the opening function rather than before `!`. +The reader now consumes nested blocks before recording the next token state. + +Regression: the compiled SVG fixture now uses nested variable fallbacks directly +adjacent to `!important`; existing scene assertions verify both initial paint and +native theme mutation. Compiler and native contract tests pass. Fresh corpus: +397 rules, 1475 declarations, **68 distinct unsupported constructs**. This closes +this extraction defect only; the grammar/diagnostic audit remains open. + +### Numeric grammar: exponent notation (2026-09-10) + +Added exponent forms to direct lengths, typed custom-property length tokens and +scalar numeric properties. Build-time length conversion separates the numeric +prefix from the unit before producing the native length, avoiding confusion +between an exponent's `e` and a CSS unit. Non-finite length results are rejected. +The native fixture verifies `+.5e1px` becomes 5px and `7.5e-1px` becomes .75px; +`opacity:8e-1` compiles. Compiler and native contract tests pass. Numeric grammar +remains open for property-specific ranges and other numeric consumers such as +fractional grid tracks, shorthand parsers and function arguments. + +### Numeric ranges: opacity and flex (2026-09-10) + +Opacity now accepts signed finite numbers and clamps generated values to [0,1]. +Negative flex-grow/flex-shrink values remain errors; line-height retains its +nonnegative constraint. Compiler regressions cover negative and over-one opacity, +exponent notation, negative flex factors and negative line height. All 37 compiler +tests pass. Percentage opacity, fractional font weights and range behavior in +other property families still require review; this does not close numeric ranges. + +### Numeric ranges: percentage opacity (2026-09-10) + +Direct opacity percentages now normalize at build time and clamp to [0,1], +including signed and exponent forms. Regression cases cover 50%, -20%, +2e2%, +and malformed percentage tokens. All 37 compiler tests pass. This closes direct +percentage literals only; variable-based opacity and CSS-wide keyword semantics +remain part of the cascade/value audit. + +### Numeric consumers: fractional grid tracks (2026-09-10) + +Fractional tracks now accept leading decimals, explicit plus signs and exponent +notation, both directly and as a minmax maximum. Tests cover `.5fr`, `5e-1fr`, +`+1fr`, `1E+0fr`, and `minmax(0px,.5fr)`, and reject negative/malformed fractions. +All 38 compiler tests pass. This closes these literal grammar cases, not grid +layout semantics or variable substitution within minmax. + +### Layout shorthand: inset literals (2026-09-10) + +Implemented one-to-four-value inset expansion into supported native top/right/ +bottom/left setters. Regression cases cover every expansion arity, auto, negative +lengths, percentages and rejection of five values. All 39 compiler tests pass. +Variable-bearing inset and calc expressions remain open; literal support does not +close the positioning/layout family. + +### Layout shorthand: variable inset and native geometry (2026-09-10) + +Inset now evaluates compiled variable token lists and expands one-to-four typed +length/auto values at runtime without CSS parsing. Invalid computed lists reset +the four sides to auto. Native layout checks verify a four-value fallback places +and sizes the child correctly, then a theme change to a single 5px inset produces +190×90 content inside a 200×100 parent. Compiler and native contract suites pass. +Calc expressions and explicit CSS-wide keywords remain open. + +### Invalid computed inset regression (2026-09-10) + +Native layout regression switches a valid four-sided inset to a variable containing +an invalid identifier, verifies old offsets are cleared while independent width/ +height survive, and restores the valid cascade before the theme-update checks. +The native contract suite passes. This validates the invalid-computed-value path +for this case; explicit inherit/revert semantics are still open. + +### SVG paint: stroke-width literals (2026-09-10) + +Fresh pre-change baseline was 66 unsupported constructs. Added nonnegative SVG +stroke-width literals (unitless, px and percentage, including decimal/exponent +forms). The compiler validates them and the native SVG serializer projects the +cascaded value as a presentation attribute, overriding an authored attribute when +CSS specifies the property. The existing SVG serialization contract now checks +`.8` stroke width. Compiler and native contract suites pass. Variable values, +CSS-wide keywords and broader SVG unit coverage remain open; SVG path compilation +remains the separately documented future optimization. + +### SVG text: text-anchor and text elements (2026-09-10) + +Strict compilation now accepts SVG text/tspan elements and the start/middle/end +text-anchor keywords. The public style writer uses the native engine's existing +SVG text-anchor field and serializer. A compiled text element regression verifies +that middle alignment reaches serialized SVG. Compiler and native contract tests +pass. Full SVG text layout, additional positioning attributes, variable values +and CSS-wide keywords remain open; this is not a general SVG conformance claim. + +### Background reset (2026-09-10) + +Fresh baseline after SVG additions: 62 unsupported constructs. `background:none` +now generates a native reset of background color and background-image state, +while `background-color:none` remains invalid. Compiler regression covers the +shorthand distinction. All 40 compiler tests and the native contract suite pass. +Gradient/image authoring and other background shorthand combinations remain open. + +### Typography dependency review and font smoothing (2026-09-10) + +`text-overflow:ellipsis` is an engine gap, not merely a missing compiler setter: +no native text-overflow field or ellipsis implementation was found, and text is +emitted through both inline-fragment and direct-text paths. Correct implementation +must cover both paths and clipping/line direction before compiler acceptance. + +The existing native font-smoothing field and serialized text metadata are now +exposed to compiled `-webkit-font-smoothing` declarations (auto, none, antialiased, +subpixel-antialiased, inherit/unset). A native contract verifies inherited +antialiased metadata reaches text output. Compiler and native contract suites pass. +This verifies propagation, not identical glyph rasterization across platforms. + +## Current grouped CSS backlog (2026-09-10) + +Regenerated after 5b14f19a: **60 distinct unsupported constructs**, 397 rules, +1475 declarations. The original 80-item baseline above remains historical. +These counts describe this stylesheet only; no feature family is closed by them. + +| Family | Distinct diagnostics | +| --- | ---: | +| Generated content and pseudo-elements | 9 | +| Animation and conditional rules | 9 | +| Input and native control presentation | 17 | +| Paint, effects and transforms | 18 | +| Layout and compiled expressions | 4 | +| Text layout and font behavior | 3 | + +Next dependency to resolve: compiled expressions used by layout and paint. +Variable evaluation currently handles typed token lists, but nested calc and +color functions need typed expression evaluation rather than runtime parsing. +Pseudo-element support also requires generated-content lifecycle and scene +semantics, not selector acceptance alone. Input/control presentation requires +engine/host review; text ellipsis is a confirmed engine gap. Ownership of the +remaining items is provisional until their native paths are inspected. + +### Generated content and pseudo-elements + +```text +#command-input::placeholder: unsupported selector: #command-input::placeholder +#ribbon-tab-list button.active:after: unsupported selector: #ribbon-tab-list button.active::after +.document-tab.active:after: unsupported selector: .document-tab.active::after +.panel-tabs button.active:after: unsupported selector: .panel-tabs button.active::after +.progress-line:after: unsupported selector: .progress-line::after +.property-section-title:before: unsupported selector: .property-section-title::before +content:"": unsupported Native Web CSS property: content +content:"⌄": unsupported Native Web CSS property: content +dialog::backdrop: unsupported selector: dialog::backdrop +``` + +### Animation and conditional rules + +```text +@keyframes progress: unsupported at-rule or condition +@keyframes toast-in: unsupported at-rule or condition +@media (prefers-reduced-motion:reduce): unsupported at-rule or condition +@media print: unsupported at-rule or condition +animation:none: unsupported Native Web CSS property: animation +animation:progress 1.2s infinite ease-in-out: unsupported Native Web CSS property: animation +animation:toast-in .15s ease-out: unsupported Native Web CSS property: animation +transition:fill .15s: unsupported Native Web CSS property: transition +transition:none: unsupported Native Web CSS property: transition +``` + +### Input and native control presentation + +```text +accent-color:var(--accent): compiled var() not supported for property: accent-color +color-scheme:dark: unsupported Native Web CSS property: color-scheme +color-scheme:light: unsupported Native Web CSS property: color-scheme +cursor:col-resize: unsupported Native Web CSS property: cursor +cursor:crosshair: unsupported Native Web CSS property: cursor +cursor:grabbing: unsupported Native Web CSS property: cursor +cursor:move: unsupported Native Web CSS property: cursor +cursor:not-allowed: unsupported Native Web CSS property: cursor +cursor:pointer: unsupported Native Web CSS property: cursor +cursor:row-resize: unsupported Native Web CSS property: cursor +resize:vertical: unsupported Native Web CSS property: resize +scrollbar-color:var(--line) transparent: compiled var() not supported for property: scrollbar-color +scrollbar-width:none: unsupported Native Web CSS property: scrollbar-width +scrollbar-width:thin: unsupported Native Web CSS property: scrollbar-width +touch-action:none: unsupported Native Web CSS property: touch-action +user-select:none: unsupported Native Web CSS property: user-select +user-select:text: unsupported Native Web CSS property: user-select +``` + +### Paint, effects and transforms + +```text +backdrop-filter:blur(3px): unsupported Native Web CSS property: backdrop-filter +backdrop-filter:blur(9px): unsupported Native Web CSS property: backdrop-filter +background:color-mix(in srgb,var(--active) 63%,var(--panel)): compiled color-mix currently supports an sRGB color percentage mixed with transparent +background:linear-gradient(125deg,var(--panel2),var(--panel)): unsupported custom-value token: linear-gradient(125deg,var(--panel2),var(--panel)) +background:linear-gradient(145deg,var(--panel2),var(--panel)): unsupported custom-value token: linear-gradient(145deg,var(--panel2),var(--panel)) +border:1px dashed #65c5a4: border shorthand currently requires width solid color, 0 or none +border:2px dashed var(--accent): border shorthand currently requires width solid color, 0 or none +box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 25%,transparent): unsupported custom-value token: color-mix(in +box-shadow:inset 0 -2px 0 var(--accent): native compiled inset shadows are not supported yet +box-shadow:inset 0 0 0 1px var(--accent-dim): native compiled inset shadows are not supported yet +box-shadow:inset 2px 0 0 var(--accent): native compiled inset shadows are not supported yet +filter:brightness(1.1): unsupported Native Web CSS property: filter +outline-offset:-2px: unsupported Native Web CSS property: outline-offset +outline:2px solid var(--accent): compiled var() not supported for property: outline +outline:none: unsupported Native Web CSS property: outline +transform:none: unsupported Native Web CSS property: transform +transform:translateX(-50%): unsupported Native Web CSS property: transform +transform:translateY(7px): unsupported Native Web CSS property: transform +``` + +### Layout and compiled expressions + +```text +border-collapse:collapse: unsupported Native Web CSS property: border-collapse +bottom:calc(var(--command-height) + 74px): unsupported custom-value token: calc(var(--command-height) +grid-column:1/-1: unsupported Native Web CSS property: grid-column +right:calc(var(--right-width) + 16px): unsupported custom-value token: calc(var(--right-width) +``` + +### Text layout and font behavior + +```text +font-synthesis:none: unsupported Native Web CSS property: font-synthesis +overflow-wrap:anywhere: unsupported Native Web CSS property: overflow-wrap +text-overflow:ellipsis: unsupported Native Web CSS property: text-overflow +``` + +### Compiled expression foundation: length arithmetic (2026-09-10) + +Added typed addition/subtraction for the native relative-term-plus-pixel-offset +representation. Tests verify percentage minus pixels, reversed subtraction, +rejection of auto and rejection of mixed relative units that cannot be represented. +Native contract tests pass. No CSS text is parsed by this helper. This is the +runtime arithmetic foundation only: the compiler does not yet lower calc into it. +General mixed-unit expressions require a richer representation and remain open. + +### Positional calc lowering (2026-09-10) + +The compiler now lowers additive/subtractive calc expressions for left/right/top/ +bottom into typed native arithmetic, including variable operands and fallbacks. +Native layout tests verify `calc(50% - 20px)` in a 200px containing block and +`calc(var(--missing-offset, 5px) + 10px)`. Compiler and native contract suites pass. +Fresh corpus count: **58 distinct unsupported constructs** (397 rules, 1475 + declarations). No runtime CSS parsing is introduced. + +This is partial calc support: multiplication/division, ordinary grouped arithmetic, +additional consuming properties and expressions mixing two relative units remain +open. Unrepresentable evaluated sums currently become auto through the positional +consumer; strict compilation must eventually diagnose statically unsupported unit +combinations rather than treating them as implemented CSS. Do not close the +expression family based on the two removed corpus diagnostics. + +### Grouped additive calc (2026-09-10) + +The compiler now strips only parentheses enclosing the entire operand, accepts +ordinary nested arithmetic groups, and retains left associativity for chained +addition/subtraction. Native geometry tests use `calc(50% - (15px + 5px))` and +`calc(var(--missing-offset, 5px) + 20px - 10px)`; expected positions remain 80px +and 15px. Compiler and native contract tests pass. Product/division and richer +mixed-unit representation remain open. + +### Scalar products in positional calc (2026-09-10) + +Added typed length scaling and compiler lowering for multiplication by literal +scalars (either side) and division by literal scalars. Operator precedence and +chained product evaluation are exercised by native geometry fixtures that mix +percentages, pixel offsets, groups and variable length operands. Compiler tests +reject division by zero, length×length and scalar÷length. All 41 compiler tests +and native contracts pass. Scalar variables/expressions, general dimensional +algebra and additional calc-consuming properties remain open. + +### Calc resize semantics (2026-09-10) + +The calc layout fixture now uses a 25vw parent and checks two viewport widths. +The parent grows from 200px to 300px, and its child's percentage-minus-pixel offset +changes from 80px to 130px without rebuilding the generated document. The native +contract suite passes. This verifies dynamic percentage resolution, not host +window-resize frame pacing. + +### Function-preserving box shorthand splitting (2026-09-10) + +Box shorthand splitting now preserves parenthesized function values rather than +splitting their internal whitespace. Inset can therefore contain multiple literal +calc functions alongside auto values. Generated positional calc locals are scoped +per assignment so shorthand expansion compiles without duplicate declarations. +The native geometry fixture exercises this combination; compiler and native +contract suites pass. This splitter is for the supported length shorthand grammar, +not a general CSS string/token parser. Variable-containing calc inside an inset +still requires integration with the variable-shorthand evaluator. + +### Combined inset variables and calc (2026-09-10) + +Variable-bearing inset now gathers complete shorthand components before expansion. +Calc components produce typed lengths, while variable components may expand into +multiple typed tokens; the final list receives one arity/type validation before +all four sides are assigned. The native fixture combines variable fallback inside +calc, a two-value auto fallback, and percentage arithmetic. Existing resize, +invalid-value and theme checks pass, along with the compiler suite. This closes +the previously noted combination gap for the supported expression grammar, not +all custom-property function values or CSS-wide keywords. + +### Zero token normalization through variables (2026-09-10) + +Custom-property tokens now recognize signed, decimal and exponent spellings of +unitless zero as typed zero lengths, matching direct length consumption rather +than recognizing only the exact string `0`. A native regression verifies +`--zero:+0e0; width:var(--zero)` produces zero width. Compiler and native contract +suites pass. Nonzero unitless numbers remain distinct from lengths. + +### Audit diagnostic ownership (2026-09-10) + +CSS audit errors now list the rule owning each unsupported declaration, while +preserving deduplication and the distinct-construct count. Repeated constructs +can report multiple owners without inflating the baseline count. The compiler +audit regression verifies owner output; all 41 compiler tests pass. Exact source +line/column ranges and nested conditional ancestry remain diagnostic gaps. + +### Conditional ancestry in diagnostics (2026-09-10) + +Declaration ownership now includes the parent-rule chain, distinguishing e.g. +`@media (max-width:400px) > div` from unconditional `div`. A regression verifies +both contexts still deduplicate to one unsupported construct. All 41 compiler +tests pass. Exact line/column source spans remain open. + +### Border shorthand family and engine ownership (2026-09-10) + +Compiler lowering now expands one-to-four `border-width` and `border-style` +values into the existing side setters. Pixel widths accept signed zero, leading +fractional digits and exponent notation in both side declarations and the +supported width/solid/color shorthand. Negative widths, nonzero unitless widths, +percentages, excess components and unsupported styles remain errors. + +All 42 compiler tests and native contracts pass. The native fixture uses the new +width/style shorthands and retains its verified 14px border-inclusive height. +This verifies lowering and geometry, not a complete rendered border comparison. + +Dashed borders are an engine/API gap: the compiled style facade exposes only a +boolean solid/hidden distinction, with no dash pattern state. Do not lower dashed +to solid. Outline fields and scene drawing exist internally but still need a +semantic/API audit before compiler exposure. Relative/keyword widths, arbitrary +border shorthand ordering, variable-bearing width/style shorthands, CSS-wide +keywords and the remaining border styles are still open. + +### Declaration source locations (2026-09-10) + +The Rust CSS parser now carries each declaration's one-based line and column +through its native callback and collected syntax model. The C++ streaming sink +has a default located-declaration adapter so existing sink implementations retain +their behavior. The internal Rust/C callback signature changes together and must +be rebuilt together. + +CSS audit declaration errors retain each source occurrence alongside conditional +ancestry while still counting distinct unsupported constructs only once. A +multiline nested-media regression verifies two identical declarations report +lines 4 and 5, column 5, with one distinct gap. All 42 compiler tests and native +contracts pass after rebuilding the parser and compiler. Rule/selector locations, +syntax-error locations and mapping inline-style offsets into the owning HTML +source remain open; this does not close the diagnostic gate. + +### Rule source locations (2026-09-10) + +CSS syntax rules now retain parser-provided one-based line/column locations for +qualified rules and at-rules, including rules without blocks. Unsupported selector +and at-rule audit diagnostics report those locations. Streaming sinks use a +default adapter, and the internal Rust/C callback signatures are updated together. +A multiline regression checks a media rule at 2:1, a nested pseudo-element rule +at 3:3 and an import rule at 5:1. All 42 compiler tests and native contracts pass. +Syntax-error locations and mapping embedded CSS back into HTML remain open. + +### Syntax-error locations and ABI guard (2026-09-10) + +CSS streaming results preserve the first parser error location alongside the total +error count. `--check-css` reports that location rather than an empty generic +stylesheet error. A two-error declaration fixture verifies the first location +(2:9) and count (2). All 43 compiler tests and native contracts pass. + +The internal CSS streaming ABI is now version 2, covering the located callbacks +and extended result structure; the C++ wrapper rejects stale version-1 libraries. +This reports parser-detected syntax errors only. Full error lists, semantic source +locations during normal compilation, and inline CSS-to-HTML mapping remain open. + +### Linked stylesheet build diagnostics (2026-09-10) + +Normal compilation now uses parser line/column locations for linked stylesheet +rules, declarations and syntax errors. This replaces the first-substring search +for external CSS diagnostics; locations point into the actual linked file. +A build-path regression covers an unsupported declaration, pseudo-element selector +and malformed declaration. All 44 compiler tests and native contracts pass. +Embedded style blocks and style attributes retain their previous approximate +mapping and require HTML parser source spans before claiming exact locations. + +### HTML whitespace preservation (2026-09-10) + +The compiler previously discarded every whitespace-only text node, losing the +separator between adjacent inline elements and whitespace-only preformatted +content. It now emits all nonempty parsed text nodes; CSS whitespace processing +remains the native engine's responsibility. This also preserves content for later +white-space style changes rather than baking the initial style into construction. + +An independent compiler fixture verifies emitted separator and two-space nodes. +Native contracts verify `text_content` is `A B` for adjacent spans and retains +both spaces in a preformatted element. All 45 compiler tests and native contracts +pass. These checks prove DOM preservation, not full inline shaping or rendered +whitespace parity; those remain part of layout differential coverage. + +### Native attribute removal (2026-09-10) + +HTML boolean attributes correctly use presence, including `disabled="false"`, +but C++ authoring lacked removal. Added `document::remove_attribute`, clearing +special id/class storage and invalidating native styles after removal. Missing +attributes are a no-op. No parsing or node reconstruction is involved. + +Native contracts verify disabled presence prevents focus, removal restores focus +eligibility and removes the disabled selector's width, and removing id clears +lookup state. All 45 compiler tests and native contracts pass. General HTML form +semantics, tabindex ordering and focus cleanup on disabling an already-focused +control still require audit; this closes only the missing mutation operation. + +### Native tabindex ordering (2026-09-10) + +Sequential focus previously excluded only the literal `-1` and ignored positive +priorities. Native focus now parses signed HTML integer prefixes, excludes all +negative values from sequential navigation, and stably orders positive values +before zero/default values. Invalid tabindex does not make a generic element +focusable. Large numeric values saturate safely to the native integer range. + +Native regressions verify priority ordering, document-order ties, reverse wrap, +programmatic negative focus, invalid input and dynamic tabindex removal. All 45 +compiler tests and native contracts pass. Shadow-tree focus scopes, full form +control coverage, hidden-ancestor programmatic focus and focused-control disabling +remain open; this is not complete browser focus parity. + +### Mixed template root ownership (2026-09-10) + +Template root whitespace was emitted without inclusion in the instance root list, +so removing an instance could leave text behind. The compiler now records every +nonempty root text node in that list and permits mixed text/element template +content without introducing wrapper elements. This remains predefined generated +construction with no runtime parsing. + +Both generated-header and C++ module template tests instantiate a whitespace, +element and text sequence, verify its text and three roots, then remove every +root and verify no text remains. Both template suites, native contracts and all +45 compiler tests pass. Nested template support and transactional construction +failure cleanup remain open. + +### Hidden ancestor focus eligibility (2026-09-10) + +Programmatic focus previously checked only the target's display mode. It now +rejects targets with any `display:none` ancestor. A native regression hides a +container through a class rule, verifies focus is rejected, removes the class, +recomputes layout and verifies focus succeeds. All 45 compiler tests and native +contracts pass. This uses computed style; style flushing before focus and clearing +existing focus when an ancestor becomes hidden remain open. + +Inspection also confirmed subtree removal already removes inline-target rules +and listeners belonging to removed nodes; no duplicate cleanup mechanism added. + +### Compiled hidden attribute (2026-09-10) + +Strict compilation now permits ordinary HTML hidden state, reusing the native +engine's existing default-display behavior. The `until-found` keyword is rejected +explicitly because native find/reveal semantics are not implemented. Other values, +including `false`, preserve HTML hidden-state behavior. + +Compiler tests cover accepted values and case-insensitive until-found rejection. +Native contracts verify the compiled element has no layout height, removing the +attribute restores its 17px height, and reapplying hidden suppresses it again. +All 46 compiler tests and native contracts pass. Find/reveal and focus cleanup +on hidden-state changes remain open. + +### Compiled explicit line breaks (2026-09-10) + +Strict HTML compilation now accepts `br`, constructing the existing native element +without translating it to another layout primitive. A compiled fixture verifies +that a break separates adjacent spans vertically and native removal restores a +shared line. All 46 compiler tests and native contracts pass. Consecutive/trailing +breaks, mixed font baselines and browser-rendered comparisons remain part of the +broader inline formatting audit. + +### Layout keyword casing (2026-09-10) + +Enum lowering now performs ASCII case-insensitive lookup for display, +flex-direction, align-items, justify-content, position and box-sizing keywords. +Previously valid uppercase spellings were rejected. Independent compiler tests +verify uppercase property/value forms generate identical rule code to lowercase +forms across all six families. All 47 compiler tests and native contracts pass. +This normalization is confined to keyword lookup; custom-property names and +case-sensitive strings are untouched. Other property grammars, function names, +units and escaped keyword identifiers still need case-handling coverage. + +### Common length unit casing (2026-09-10) + +The shared compiler length parser normalizes ASCII case in numeric dimensions, +and custom-property token lowering recognizes the same unit variants while +preserving custom-property names. Tests cover PX/EM/REM/VW/VH/DVW/DVH in direct +widths and variable dimensions, plus overflow and malformed unit rejection. +The native numeric fixture now uses uppercase PX and retains its geometry check. +All 48 compiler tests and native contracts pass. Property-specific prevalidators +(e.g. border widths and spacing), escaped units and keyword casing outside the +previously audited enum families remain open. + +### Shared pixel-property validation (2026-09-10) + +Border side widths, font size, pixel line height and letter/word spacing now share +one finite pixel-value validator. It accepts case-insensitive units, exponent and +fractional numbers and signed zero, with nonnegative constraints for widths/font +size/line height and signed spacing. Font-size emission uses the validated numeric +value instead of reparsing through a separate native utility. + +Regression coverage exercises each property with valid numeric forms, overflow, +unsupported relative units and separated units; font-size output is checked for +its exact 5px value. All 49 compiler tests and native contracts pass. Relative +units for these property profiles and broader keyword/function grammar remain open. + +### Literal length range validation (2026-09-10) + +Common literal length lowering now rejects negative dimensions, padding, gaps, +flex basis and corner radii, and rejects auto for padding/gaps/radii. Shorthand +expansion shares these checks. Signed zero remains valid; negative margins and +positional offsets remain supported. Previously these invalid declarations could +be accepted and delegated to engine clamping or auto behavior. + +Independent compiler regressions exercise pixels, percentages, uppercase relative +units, signed zero, invalid auto and valid signed offsets. All 50 compiler tests +and native contracts pass. Computed-value range semantics through variables/calc +and browser-style invalid-declaration recovery remain separate open audit items. + +### Typed variable padding shorthand (2026-09-10) + +Padding now accepts variable-token shorthand values, validates one-to-four +nonnegative typed lengths, and expands sides only after whole-value validation. +Invalid computed values reset all four sides to initial zero rather than keeping +partially valid sides. Evaluation uses typed native tokens, not runtime CSS parsing. + +Native geometry checks verify two-axis padding, a class mutation introducing a +negative component, all-side reset, and recovery after class removal. All 50 +compiler tests and native contracts pass. Padding longhand variables, calc values +and remaining box shorthand families still require coverage. + +### Variable padding longhands (2026-09-10) + +All four padding longhands now lower variable expressions into one nonnegative +typed length, resetting to initial zero for missing, multi-token or invalid +values. A native regression verifies fallback overrides an earlier shorthand, +a negative custom-property mutation resets only that side (rather than restoring +the earlier declaration), and removing the mutation restores the fallback. +All 50 compiler tests and native contracts pass. Calc, CSS-wide keywords and +broader computed-value range handling remain open. + +### Typed variable gaps (2026-09-10) + +Gap shorthand now evaluates one or two nonnegative typed lengths and validates +both before assignment. Invalid values reset both axes to zero for the current +flex/grid profile. Row-gap and column-gap reuse typed single-value lowering. +A compiled fixed-track grid regression verifies distinct row/column spacing and +whole-shorthand reset after a negative custom-property mutation. All 50 compiler +tests and native contracts pass. Longhand interaction coverage, normal keyword, +calc and multicolumn initial-gap semantics remain open. + +### Gap longhand cascade regression (2026-09-10) + +Extended native grid coverage verifies column-gap variable fallback overrides only +its shorthand axis. Existing multi-token and negative variable values reset the +column gap to zero while retaining the row gap, without incorrectly selecting the +var fallback. Removing the longhand's class restores shorthand spacing. The native +contract suite passes. This closes the previously missing longhand interaction +regression for typed length gaps; normal/calc/multicolumn semantics remain open. + +### Variable margin lowering (2026-09-10) + +Margin shorthand and longhands now evaluate typed lengths or auto, accepting +negative lengths and updating both side values and native auto flags. Invalid +computed values reset affected sides to zero and clear auto flags. Shorthand +validation covers the whole one-to-four-token value before expansion. + +Native regression verifies block centering via variable auto margins, transition +to a negative left margin without stale auto state, and invalid-value reset. +All 50 compiler tests and native contracts pass. Margin longhand cascade tests, +case-insensitive variable auto, calc and collapsing-margin parity remain open. + +### Margin longhand cascade coverage (2026-09-10) + +Native contracts now verify a variable margin-left overrides one auto shorthand +side, a multi-token invalid value resets that side without selecting fallback, +a subsequent auto value restores centering, and class removal retains shorthand +auto behavior. The native contract suite passes without a lowering change. This +closes the missing longhand interaction regression for the supported token +profile; collapsing margins and broader keyword/expression support remain open. + +### Variable auto keyword casing (2026-09-10) + +Typed variable tokens now expose ASCII case-insensitive keyword comparison without +normalizing stored text or custom-property names. Margin, inset and variable grid +track auto consumers use it. Existing margin centering/cascade regressions now +exercise uppercase AUTO and mixed-case AuTo. All 50 compiler tests and native +contracts pass. Escaped identifiers and other keyword consumers remain open; +this helper compares already compiled tokens and does not parse CSS at runtime. + +### Literal auto case handling (2026-09-10) + +Supported length-property consumers normalize the auto keyword before lowering, +so margin auto flags agree with the emitted lengths for mixed-case spellings. +Shorthands inherit this through side expansion. Tests cover dimensions, offsets, +margin/inset/flex basis, continued rejection for padding/gaps/radii, and preservation +of an unrelated font-family value named AUTO. All 51 compiler tests and native +contracts pass. This is scoped keyword normalization, not general CSS token +normalization; other keyword families and escaped forms remain open. + +### Font weight absolute keywords (2026-09-10) + +Font-weight normal/bold now lower to native weights 400/700. Keyword matching is +ASCII case-insensitive, including existing inherit/unset handling. Compiler +regressions verify exact generated weights and rejection of invalid values. +All 52 compiler tests and native contracts pass. Relative bolder/lighter, +fractional native weight representation, variable values and font selection +parity remain open. Numeric line-height overflow was inspected: stof rejects +out-of-range inputs before C++ emission; no change was required there. + +### Native translation transform lowering (2026-09-10) + +Refreshed the unchanged reference corpus: 397 rules, 1475 declarations and 58 +unsupported constructs before this change. Added a native typed translation +setter and compiler lowering for translateX/translateY lengths or percentages +and transform:none. The setter resets scale/rotation and records authored +transform versus stacking-context state separately. No runtime CSS parsing added. + +Native geometry verifies percentage translation resolves against the element's +own width and class-applied none resets it. All 52 compiler tests and native +contracts pass. Transform lists, variables, rotation/scale lowering, transformed +hit testing and rendered stacking comparisons remain open; this is not full +transform-family closure. + +### Translation input and grammar regression (2026-09-10) + +The compiled translation fixture now verifies pointer targeting at its displaced +right edge and absence of targeting at its original left edge. Native contracts +pass. Compiler tests cover signed percentages/pixels, case variants and rejection +of auto, nonzero unitless values, unsupported transform lists and excess arguments; +all 53 compiler tests pass. This verifies simple translated hit geometry, not +nested transforms, clipping or rendered stacking-context parity. + +### Two-axis translate function (2026-09-10) + +Compiler transform lowering now accepts translate(x) and translate(x,y), with the +one-argument form supplying zero Y. Native regression checks percentages resolve +against each axis of the element's own box; compiler tests reject excess arguments, +missing commas and auto. All 53 compiler tests and native contracts pass. Function +lists, calc/variables and broader transform composition remain open. + +### Translation resize semantics (2026-09-10) + +The compiled translation fixture now has viewport-relative width. Native contracts +verify widening the viewport doubles its width and percentage X offset while Y +retains its own-height basis, pointer targeting follows the resized geometry, +and shrinking restores the original offset without accumulation. Native contracts +pass. This proves dynamic geometry/input only, not compositor presentation timing, +60fps resize or absence of host image stretching; those goal requirements remain +unverified and unchanged. + +### Translation flow isolation (2026-09-10) + +Added a following block sibling to the compiled transform fixture. Native +contracts verify its normal-flow position is unchanged when a vertical translation +is applied and cleared. Also corrected transform:none keyword case handling; +compiler coverage now includes NONE. Native contracts and all 53 compiler tests +pass. Overflow/clipping, nested transforms and rendered stacking remain open. + +### Nested translation geometry and targeting (2026-09-10) + +Extended the compiled translation fixture with a child carrying its own X +translation. Native contracts verify combined parent/child offsets, pointer +targeting of the descendant, and descendant Y movement when the parent gains a +vertical transform. Native contracts pass without engine changes. This covers +nested translations only; clipping, stacking paint and rotation/scale composition +remain open. + +### Native overflow derived state (2026-09-10) + +A translated-child clipping regression initially failed: native cascade stored +axis overflow values but omitted the derived clipping/scroll flags populated by +the JS-backed path. Native cascade now derives those flags after declarations, +including cross-axis visible/clip normalization for that calculation. + +The regression now passes: visible translated content is targetable, content +outside overflow:hidden is excluded, and changing overflow to visible restores +outside targeting. Native contracts pass. Rendered clipping parity, mixed-axis +clipping and actual scroll interaction remain open and require further coverage. + +### Overflow scene clip coverage (2026-09-10) + +The compiled overflow fixture now paints its translated child. Native contracts +verify clip begin/end commands bracket that child's paint and use the ancestor's +20x10 viewport. Changing overflow to visible removes both ancestor clip commands. +Native contracts pass. This verifies scene ordering and metadata, not final +rasterized pixels; renderer differential and mixed-axis clipping remain open. + +### Empty overflow viewport regression (2026-09-10) + +Native compiled overflow coverage now includes a class-driven zero-height +viewport. The scene retains a zero-height clip, descendant geometry remains +allocated, outside pointer targeting is suppressed, and restoring the height +restores targeting. Native contracts pass. This checks retained-scene/input +behavior, not renderer pixel output or animated height transitions. + +### Computed overflow axes (2026-09-10) + +Native cascade now stores normalized overflow axis values as well as deriving +clipping/scroll flags, so downstream layout/scene consumers see computed values. +A mixed visible/hidden compiled fixture verifies outside targeting is excluded +and scene clipping remains present. Native contracts pass. The visible/clip +combination requires genuinely axis-specific clipping rather than the current +single clip flag and remains an engine/scene audit gap. + +### Native programmatic scrolling (2026-09-10) + +Added scroll_to and scroll_offset APIs for C++ document authoring. Scroll requests +use the latest rendered layout, reject non-finite inputs, clamp to content extent, +permit hidden/auto/scroll containers and invalidate layout when offsets change. +Compiled fixture regressions verify child movement and upper/lower clamping; +native contracts pass. Calls before initial layout do not flush layout. Default +wheel scrolling, scroll events, smooth scrolling, RTL offsets and host interaction +coverage remain open. + +### Native vertical wheel default action (2026-09-10) + +Wheel dispatch now performs default vertical scrolling after listeners unless +preventDefault or document disposal cancels it. The nearest surviving ancestor +that can move handles the delta; hidden-only containers are not wheel-scrollable. +Ancestor IDs are captured before dispatch and revalidated to tolerate removal. +Native contracts verify scrolling, cancellation and resumption after listener +disposal. Contracts pass. Horizontal/delta-mode support, scroll events, overscroll +policy, gesture momentum and host frame pacing remain open; current API deltas +are treated as pixel distances. + +### Scroll modes and wheel removal safety (2026-09-10) + +Native regressions verify overflow:hidden accepts programmatic scrolling but +suppresses wheel default, overflow:clip rejects a programmatic scroll request, +and a wheel handler can remove its scroll subtree without the default action +accessing deleted nodes. Native contracts pass. Automatic offset reset solely +from overflow changes, queued scroll events and nested scroll chaining remain +open; the clip test explicitly calls scroll_to after changing mode. + +### Overflow mode changes reset scrolling (2026-09-10) + +After computing overflow axes, native cascade now clears retained scroll offsets +on visible/clip axes. Hidden/auto/scroll offsets remain eligible for layout +clamping. Native regressions switch a previously scrolled compiled container to +clip and visible and verify both offset and child geometry reset without an +explicit scroll request. Native contracts pass. Root viewport scrolling, RTL and +scroll-event scheduling remain open. + +### Scroll extent mutation regression (2026-09-10) + +Compiled class mutations now exercise shrinking scrolled content and enlarging +its viewport. Native contracts verify the offset clamps to the new content extent +and child geometry agrees in the same render, then resets to zero when content +fits. Contracts pass without engine changes. This is layout correctness coverage, +not asynchronous scroll-event or frame-presentation timing verification. + +### Nested wheel container regression (2026-09-10) + +A compiled nested-scroller fixture verifies inner-container preference, ancestor +scrolling when the inner container is already at its boundary, and return to inner +scrolling when direction reverses. Native contracts pass. This tests discrete +pixel wheel events; residual deltas within one event, overscroll-behavior, gesture +latching and momentum remain open and must not be inferred from this regression. + +### Overflow and text keyword casing (2026-09-10) + +Overflow axis lookup and text-align/white-space/text-transform lowering now use +ASCII case-insensitive keyword matching. Overflow shorthand inherits this through +axis expansion. Independent tests compare uppercase/lowercase generated rules +across these families. All 54 compiler tests and native contracts pass. Variable +keyword values and escaped identifiers remain separate gaps. + +### Variable text keyword lowering (2026-09-10) + +Text-align, white-space and text-transform now evaluate compiled variable tokens, +match supported keywords case-insensitively, and reset invalid computed values to +inheritance. Variable names retain case; normalization occurs only at keyword +consumption. Native geometry verifies uppercase alignment fallback and inherited +right alignment after an invalid custom-property mutation. All 54 compiler tests +and native contracts pass. Whitespace/transformation variable rendering coverage, +CSS-wide custom-property keywords and escaped identifiers remain open. + +### Variable text transformation and discovered newline gap (2026-09-10) + +Native scene regressions verify uppercase transformation through variable fallback, +invalid-value inheritance to lowercase, recovery after mutation, and unchanged +DOM text. Native contracts pass. + +A separate attempted preformatted-newline regression failed: with font-size 10px, +line-height 20px and white-space:var(--White, PRE), A/newline/B measured 20px high +instead of the expected 40px. Retained standalone reproduction in +`tests/NativeWeb/audit/Whitespace.html`; it is not registered as a passing test. +Next investigate literal-versus-variable behavior and native text measurement; +do not claim whitespace variable rendering closure from successful compilation. + +### Preformatted newline layout fix (2026-09-10) + +The preserved newline reproduction is now covered by passing native contracts: +A/newline/B under variable PRE measures 40px with 20px line height; invalidating +the variable restores normal whitespace and 20px height. Two native paths were +collapsing preformatted text: wrap_text_lines and flattened inline fragment layout. +Both now preserve preformatted line segments and explicit newlines. Contracts pass. +Pre-wrap/pre-line/break-spaces, tabs, trailing-newline edge cases, mixed inline +styles and pixel comparisons still need coverage; this closes the recorded +preformatted two-line failure, not the whole whitespace family. + +### Preformatted blank lines and spaces (2026-09-10) + +Extended native contracts after the preformatted fix: A/newline/newline/B occupies +three 20px lines, and native text mutation preserves leading/trailing spaces in +scene text. Restoring the original text also renders successfully. Contracts pass. +Whitespace-only content, tab expansion, trailing newline boundaries and the other +preserving whitespace modes remain open. + +### Preformatted whitespace boundaries (2026-09-10) + +Native contracts now cover whitespace-only spaces, a leading newline and a +trailing newline after text. The cases produce one line, two lines and one line +respectively at the fixture's 20px line height. Contracts pass without further +layout changes. Tab stops, cross-element whitespace boundaries, pre-wrap, +pre-line and break-spaces remain open. + +### Pre-line explicit newlines (2026-09-10) + +Native text wrapping and flattened inline layout now preserve explicit newline +boundaries for pre-line while collapsing spaces within each line. Compiled +variable-style regression verifies three lines including an internal blank line +and absence of repeated spaces in paint text. Native contracts pass. Soft-wrap +boundaries, mixed inline styles, tabs and renderer pixel comparisons remain open. + +### Pre-line soft wrapping and width mutation (2026-09-10) + +An independent native contract combines two words and an explicit newline under +compiled `white-space:var(--White, pre-line)`. At 15px width it occupies three +20px lines; restoring 100px width removes the soft wrap and retains the explicit +newline, producing two lines. Both native contracts and the compiler suite pass. +This is geometry evidence only, not pixel parity or whitespace-family closure. +The current whitespace regression is complete; resume the earliest open audit +gate (source diagnostics and numeric/function grammar) before further layout or +Kestrel work. + +### Flex shorthand numeric grammar (2026-09-10) + +The numeric-grammar audit reproduced a compiler-only inconsistency: `flex:.5 +2 +10px` failed although its equivalent longhands compiled. Shorthand factor +classification and numeric longhand validation now share the CSS number grammar, +including signs, leading decimals and exponents. Range validation remains in the +longhand lowering. Removed the shorthand's textual negative-basis check so valid +negative zero is accepted while negative nonzero bases still fail validation. + +The independent compiler regression compares generated grow/shrink/basis setters +against equivalent longhands, covers single-factor forms and negative zero, and +rejects negative factors/bases, malformed numbers, excess components and overflow. +The regression failed before the fix; all 55 compiler tests and native contracts +pass afterward. This closes this shorthand grammar inconsistency only; broader +function grammar and source-location gates remain open. + +### Shared media-condition numeric validation (2026-09-10) + +Compiler lowering and `--check-css` previously duplicated an integer-only media +condition regex; the audit path also omitted numeric conversion/range checks. +Both now use one min/max width/height condition parser and the validated pixel +length grammar. Supported values include signs, decimals, exponents, unitless +zero, case-insensitive keywords/units and surrounding whitespace. Negative bounds +are retained so their comparisons have their natural always/never-match result +for nonnegative viewport dimensions. + +Independent tests verify audit/compiler agreement for accepted and rejected +values and inspect generated axis/bound values. Overflow, malformed numbers, +nonzero unitless values and unsupported units fail both paths. All 56 compiler +tests and native contracts passed; the additional generated-bound assertions pass +in the focused regression. General media expressions, relative media lengths and +browser differential coverage remain open; this is numeric validation closure +for the existing pixel min/max condition subset only. + +### Preview diagnostic locations and HTML mapping gap (2026-09-10) + +Preview warnings now retain the compiler's current source line and column instead +of printing only a filename. A linked-stylesheet regression verifies the at-rule +location and two separate repeated-property locations in generated-module preview +mode. All 57 compiler tests and native contracts pass. + +HTML diagnostics remain approximate: dom_node and the HTML parser bridge expose +no authored source spans, and compiler::locate searches the first matching text. +Repeated tags/properties, decoded attribute entities and reordered HTML tree nodes +therefore cannot be mapped reliably with that mechanism. Closing this gate needs +parser-provided source provenance (including attribute-value mapping) propagated +into compiler diagnostics and generated source mappings; do not replace it with +another substring-search heuristic or claim inline location accuracy. Linked CSS +locations are parser-derived and are covered by the regression above. + +### Parser-derived element line mappings (2026-09-10) + +The HTML tree sink now captures html5ever's current-line callback and passes the +creation line through the native bridge into dom_node. Generated element #line +mappings use this provenance instead of the first matching tag substring. An +independent fixture verifies distinct mappings for repeated div elements and a +nested section. All 58 compiler tests and rebuilt native contracts pass. + +The HTML bridge ABI is version 2 because create_element now receives a line +argument. CSS and selector ABI versions are unchanged. Parser lines describe the +tree-builder position at creation, not exact opening-token spans: multiline tags, +implicit/reconstructed elements, attribute columns, entity decoding and inline +CSS offsets still require richer provenance. This is a foundation for source +mapping, not closure of the precise HTML diagnostics gate. + +### Element validation diagnostic provenance (2026-09-10) + +Compiler traversal now selects the current node's parser line before validating +it, including the metadata pass. Previously unsupported elements could report a +previous sibling's location, while scripts/templates/links rejected in the +metadata pass could retain unrelated locations. One regression checks all four +rejection paths after repeated valid siblings and verifies no output is emitted. +All 59 compiler tests and native contracts pass. The column remains an element +line anchor; exact authored spans and attribute diagnostics remain open. + +### Inline declaration owner anchoring (2026-09-10) + +Inline declaration lowering now receives its owning node and retains that node's +parser-line anchor for errors and preview warnings. It no longer searches the +whole HTML source for the first matching property name. A repeated-width fixture +checks strict failure on the second element and the same location in preview. +All 60 compiler tests and native contracts pass. This provides an owner location, +not the exact attribute/property span; multiline attributes and decoded source +mapping remain part of the open diagnostics gate. + +### Font shorthand numeric forms (2026-09-10) + +The existing size/line-height/family font shorthand now accepts signed numeric +forms, leading decimals, exponents, unitless zero and case-insensitive px/normal. +Family spelling is preserved. Longhand lowering validates size and line-height +ranges; unitless line-height uses the shared CSS number grammar, including +negative zero as a factor rather than accidentally treating it as a pixel value. +Tests cover valid forms, retained family case, invalid negative/overflow values +and zero-factor representation. All 61 compiler tests and native contracts pass. +Optional font style/variant/weight/stretch fields, relative sizes, percentages and +full shorthand reset semantics remain open; this closes numeric consistency for +the existing shorthand subset only. + +### SVG stroke-width numeric validation (2026-09-10) + +Stroke-width now uses the shared CSS number grammar and explicit nonnegative +range validation, accepts negative zero and case-insensitive PX, and normalizes +unit spelling before passing it to the existing native API. Independent tests +cover signed/exponent forms, percentages, negative ranges, malformed units and +overflow. All 62 compiler tests and native contracts pass. + +The current SVG style API still stores stroke width as text. Numeric acceptance +is not evidence of a fully preprocessed SVG pipeline: typed SVG lengths, compiled +path data, inherited percentage resolution and rendered parity remain open under +the paint/SVG gate. This work changes compiler validation only. + +### Calc function-name casing (2026-09-10) + +Inset longhands, nested compiled length expressions and variable inset shorthands +now recognize calc function names case-insensitively. Only the function prefix +is compared in normalized form; custom-property names retain their authored case. +Independent regressions cover uppercase/mixed-case calc, nesting and --Offset +preservation in both longhand and shorthand output. All 63 compiler tests and +native contracts pass. Escaped function identifiers and general component-value +lexing remain open; this does not extend calc to unsupported properties. + +### Var function-name casing across lowering paths (2026-09-10) + +Variable-expression parsing and property dispatch now recognize var names +case-insensitively, including nested fallbacks, grid tracks and calc operands. +Comparison uses normalized temporary strings; emitted custom-property names and +fallback tokens retain their original case. An independent matrix compares +uppercase/mixed-case generated rules with lowercase-function equivalents for +width, margin, padding, gap, alignment, calc, grid and nested color fallbacks. +All 64 compiler tests and native contracts pass. Escaped identifiers, richer +custom-value token forms and CSS-wide custom-property semantics remain open. + +### Custom-value keyword classification (2026-09-10) + +Custom-value token classification now compares keywords case-insensitively while +preserving token text. Uppercase/mixed-case CSS-wide keywords no longer bypass the +existing unsupported diagnostic. Supported named colors (black, white, +transparent) now acquire typed color data regardless of capitalization, fixing +uppercase variable fallbacks that previously lacked color metadata. Independent +regressions verify both rejection and emitted typed color values. All 65 compiler +tests and native contracts pass. Full CSS-wide custom-property semantics, broader +named colors and context-sensitive fallback handling remain open. + +### Literal grid function casing and repeat integers (2026-09-10) + +Literal grid track lowering now accepts case-insensitive repeat/minmax names, +track keywords and dimension units. Repeat counts accept an explicit positive +sign while retaining integer-only syntax and the existing 1..1024 bound. +Independent regressions compare uppercase and lowercase generated track rules, +and reject zero, decimal/exponent integer spellings and duplicate signs. All 66 +compiler tests and native contracts pass. This does not add named grid lines, +auto-repeat, additional intrinsic sizing or escaped identifiers. + +### Grid numeric range validation (2026-09-10) + +Grid fixed/minmax length bounds now validate numeric sign instead of rejecting +any leading minus character, so negative zero is accepted. Fractional tracks and +minmax fractional maxima use shared CSS number grammar with finite, nonnegative +range checks. Regressions cover zero across units, negative values, overflow and +invalid fractional minima. All 67 compiler tests and native contracts pass. +These checks validate compiler input and typed output construction, not complete +grid layout parity; intrinsic track sizing and browser comparisons remain open. + +### Grid function argument rejection coverage (2026-09-10) + +Audited empty/missing/excess repeat and minmax arguments, including malformed +minmax nested in repeat. Existing guards reject all nine cases; no engine or +compiler change was necessary. The new regression verifies both strict compiler +failure without an output artifact and --check-css rejection. All 68 compiler +tests pass. This records verified existing behavior rather than new support. +Variable grid tracks still accept only typed lengths and auto: fractional values +in custom properties remain an identified lowering gap requiring typed metadata, +not runtime string parsing. + +### Typed fractional grid variables (2026-09-10) + +Variable expressions/tokens now carry optional fractional-track metadata compiled +from fr dimensions. Both variable evaluation paths preserve it, equality includes +it, and grid lowering consumes nonnegative fractions directly without parsing +runtime strings. A native fixture verifies var fallback 1FR/2fr divides a 300px +grid into 100px/200px tracks. All 68 compiler tests and rebuilt native contracts +pass. Dynamic invalidation/recovery and minmax expressions inside variable token +sequences still need coverage/support; this closes simple fractional tokens only. + +### Fractional grid variable mutation and recovery (2026-09-10) + +Native contracts now change the fractional track custom property from fallback +1fr/2fr to 2fr/1fr and verify the widths reverse. A negative fraction invalidates +the complete declaration: both children use the implicit full-width column. +Removing the class restores the original fallback ratio with no stale tracks. +Rebuilt native contracts pass. This adds dynamic geometry evidence; nested +minmax token expressions, raster parity and broader grid behavior remain open. + +### Inherited fractional references (2026-09-10) + +Native geometry now verifies a child custom property referencing inherited +3fr/1fr tokens produces 225px/75px columns in a 300px grid. Removing the ancestor +attribute removes that declaration and activates the nested 1fr/1fr fallback, +producing 150px/150px columns. Rebuilt contracts pass, confirming fractional +metadata survives reference evaluation, inheritance and ancestor mutation. +Full variable token grammar and browser differential closure remain open. + +### Dependency output failure reporting (2026-09-10) + +Compiler dependency-file creation and final flush are now checked. Previously a +failed depfile write could report success, undermining subsequent rebuilds. A +regression makes the dependency path a directory, verifies failure with its path, +then removes the obstruction and verifies successful retry and source dependency. +All 69 compiler tests pass. Generated source may already exist when depfile output +fails; callers must honor the nonzero exit. Atomic source/depfile publication is +not established by this change. + +### HTML root attribute bypass (2026-09-10) + +The html root previously copied every attribute directly, bypassing both script +attribute rejection and inline CSS compilation. Root event attributes now fail +strict compilation and are omitted with a preview warning. Root inline styles +now use typed declaration lowering targeted at d.root(), including diagnostics. +Compiler regressions verify typed width output, root targeting and event rejection +/preview omission. All 70 compiler tests pass. Other root attributes still retain +the existing generic-copy behavior; the complete root attribute inventory, named +root references and native geometry coverage remain open. + +### Root IDs and named references (2026-09-10) + +HTML root IDs now enter the generated view's named references and the shared +ID uniqueness set. Previously the attribute existed on the native root but its +reference was missing and duplicates on body/descendants escaped validation. +Native contracts verify named("html-root") equals d.root(); compiler tests reject +both body and descendant duplicates. All 71 compiler tests and rebuilt native +contracts pass. Broader root attribute semantics remain open. + +### Root inline custom-property cascade (2026-09-10) + +Native contracts verify a compiled root inline custom property inherits into a +child's width and outranks a normal ID-selector declaration (23px versus 41px). +A class-selected important declaration overrides it to 37px; removing the class +restores 23px. Rebuilt contracts pass. This provides native cascade/inheritance +and mutation evidence for the root inline lowering; exact source spans and the +remaining root attribute inventory are still open. + +### Semantic block containers (2026-09-10) + +Strict HTML compilation now permits article, aside, hgroup and search. The shared +native UA display defaults already classify all four as blocks. A compiled native +fixture verifies full containing width, explicit heights and vertical source-order +stacking. All 71 compiler tests and rebuilt native contracts pass. This closes +construction/basic layout for these containers only; accessibility landmarks, +complete UA styles and full HTML coverage are not established by these checks. + +### HTML stylesheet media attributes (2026-09-10) + +Style/link media attributes now seed compiled rule bounds using the existing +pixel min/max width/height condition parser. Empty/all media remains unrestricted; +unsupported media fails strict compilation and omits the whole stylesheet with a +preview warning. Previously media was ignored and styles became unconditional. +Compiler fixtures cover both embedded/linked styles and unsupported print media. +All 72 compiler tests pass. Native resize validation, general media expressions, +type/disabled/alternate stylesheet behavior remain open. + +### HTML media resize and nested-condition evidence (2026-09-10) + +A compiled embedded stylesheet with min-width:500px and nested max-width:700px +now has native geometry coverage. Viewports 400, 500, 700, 701 and 400px verify +base style, inclusive boundaries, intersection and restoration on shrinking. +Rebuilt contracts pass. These are layout checks for the supported conditions; +they do not establish presentation frame rate or general media-query coverage. + +### Static stylesheet activation (2026-09-10) + +Non-CSS style/link types and disabled stylesheet links no longer contribute +compiled rules. Disabled uses attribute presence, including disabled="false"; +empty type and case-insensitive text/css remain active. Tests verify inactive +content is not parsed/read and active CSS still lowers. All 73 compiler tests +pass. This implements initial compiled activation only: runtime stylesheet +activation, alternate stylesheet sets and stylesheet DOM objects remain open. + +### Stylesheet relationship token grammar (2026-09-10) + +Link rel recognition now handles case-insensitive whitespace-separated stylesheet +tokens, including duplicates. Unsupported relationship tokens receive a specific +diagnostic rather than being treated as active stylesheet semantics. Tests cover +case, spaces/tabs/newlines, duplicates and explicit alternate rejection. All 74 +compiler tests pass. Alternate stylesheet selection and other link relationships +remain unsupported; this closes token grammar for ordinary stylesheet links. + +### Input file diagnostics (2026-09-10) + +The shared compiler input reader now requires a regular file, reads binary bytes, +and reports stream failures with the source path. Regression coverage checks a +directory supplied as HTML, as linked CSS and to --check-css; each fails without +output. All 75 compiler tests pass. This verifies directory rejection; simulated +mid-read I/O faults and atomic artifact publication remain untested. + +### Generated module/template integration checkpoint (2026-09-10) + +Rebuilt native_web_smoke, native_web_templates, native_web_module_templates and +native_web_contracts against current compiler/HTML ABI/variable metadata changes. +All four executables and the 75-test compiler suite pass. Template checks exercise +instance-local references, native events, independent-instance survival after +removal, mixed text roots and cleanup. This confirms current generated headers +and C++ modules integrate with the native API; it is not SDK packaging, V8 linkage, +GPU presentation or browser parity evidence. The unbuilt native_web_gpu target +observed in the test inventory remains outside this compiler checkpoint. + +### HTML table construction (2026-09-10) + +Strict compilation now admits the native table element family and cell-specific +colspan/rowspan attributes. Existing native defaults/layout provide table roles +and span processing. A compiled fixture verifies two separate columns and a +following colspan=2 cell covering their combined width. All 75 compiler tests +and rebuilt native contracts pass. Rowspan edge cases, caption/column behavior, +cell header accessibility, border models and browser differential table coverage +remain open; admission of these elements does not establish full table parity. + +### Compiled table colspan mutation (2026-09-10) + +Native contracts change the compiled table cell from colspan=2 to colspan=1, +verify it adopts the first column's width, then restore colspan=2 and verify the +original width returns. Rebuilt contracts pass. This establishes live span +mutation for the simple fixture only; complex spans, row groups and browser +parity remain open. + +### Table-layout property lowering (2026-09-10) + +Added a supported native style writer for the existing fixed-table-layout flag +and compiler lowering for table-layout:auto/fixed with case-insensitive keywords. +Compiler regressions verify both generated values and invalid keyword rejection. +All 76 compiler tests and rebuilt native contracts pass. Fixed-layout geometry, +first-row sizing and overflow comparisons remain necessary; existing table +contracts exercise auto layout and do not prove those behaviors. + +### Fixed table first-row sizing defect (2026-09-10) + +A native fixture failed when a fixed 200px table's first cell requested 50px and +a later-row cell requested 150px: the later row expanded the column. Fixed mode +now considers only first-row cell sizing and ignores intrinsic text sizing in +that pass; auto mode retains its existing behavior. The regression now passes +with the first cell at 50px, alongside native contracts. Column-element priority, +auto-width tables, span distribution and browser differential tests remain open. +The fix is in the shared native layout engine and may affect other hosts using it. + +### Fixed table auto-width qualification (2026-09-10) + +The fixed column-sizing path now requires a specified table width. With width:auto, +the existing intrinsic sizing path remains active despite table-layout:fixed. +Native contracts switch the fixture to auto width, verify later-row content can +expand the first column, then restore specified width and verify the 50px fixed +column returns. Rebuilt contracts pass. Percentage definiteness and column-element +precedence remain open table sizing cases. + +### Fixed table column precedence (2026-09-10) + +A regression reproduced a first-row 120px cell overriding an authored 60px col. +The layout pass now records specified column widths independently from numeric +width (so zero is distinguishable from auto), protects them from single-column +cell sizing, and excludes them from unspecified-track excess distribution. +The 60px regression and native contracts pass. Spanning cells crossing authored +columns, percentage-column distribution and column-group widths remain open. + +### Explicit zero-width column mutation (2026-09-10) + +Native contracts mutate the authored priority column from 60px to 0 with an +important class rule and verify the cell remains zero-width despite its own +120px declaration. Removing the class restores 60px. Rebuilt contracts pass, +confirming explicit zero is preserved independently of automatic sizing. +Spanning-cell and percentage-column interactions remain open. + +### Column span input handling (2026-09-10) + +Compiled col elements now accept span. Native column collection replaces unchecked +float-to-size conversion with bounded integer-prefix parsing: invalid/zero values +default to one, positive values clamp to 1000 and an optional plus is accepted. +Contracts cover compiled +1 and dynamic negative/zero/nonnumeric defaults without +altering the 60px column. All 76 compiler tests and rebuilt contracts pass. +Large-span geometry, colgroup span behavior and full table reflection remain open. + +### Column span overflow regression and shared parsing (2026-09-10) + +An oversized dynamic span exposed two additional unchecked column-span conversions +in intrinsic sizing and column geometry, throwing vector length_error despite the +previous allocation guard. All three column paths now share bounded integer +parsing. Contracts verify +2suffix repeats the 60px width, a very large integer +renders without failure, and restoring +1 recovers the automatic second column. +Rebuilt contracts pass. This supersedes the prior partial column-span guard; +cell-span reflection and colgroup semantics remain separate audit items. + +### Cell span bounded parsing (2026-09-10) + +Cell placement and intrinsic column counting now use the shared bounded table-span +parser instead of unchecked float conversions. Colspan clamps to 1000; positive +rowspan clamps to 65534. Contracts cover invalid/zero colspan defaults, an oversized +colspan render and restoration to the original width. Rebuilt contracts pass. +Rowspan=0 still follows the old one-row fallback rather than spanning the remaining +row group; that semantic gap and dedicated rowspan geometry tests remain open. + +### Rowspan zero and row-group limits (2026-09-10) + +Table row collection now records each row's group. Rowspan parsing preserves zero +and resolves it to the remaining rows in that group; positive spans are capped at +the same boundary. The native fixture verifies a zero-span cell covers both rows +and reserves its column beside the second-row cell. Rebuilt contracts pass. +Multiple-group transitions, dynamic row insertion and comprehensive rowspan +geometry still require dedicated coverage. + +### Rowspan group boundary and native row mutation (2026-09-10) + +Contracts verify the next tbody begins in the first column after a zero rowspan +in the preceding group. Inserting a row through native construction expands the +zero-span cell and reserves its column; removing that row restores its original +height. Rebuilt native contracts pass. No runtime HTML parsing is used. Complex +span overlaps, row-group reordering and browser differential coverage remain open. + +### CSS table display roles (2026-09-10) + +Compiler display lowering now exposes table, inline-table and the eight internal +table roles already represented by native display_mode. Independent compiler +coverage verifies case-insensitive syntax and each emitted enum. All 77 compiler +tests pass. CSS-generated table structure, anonymous table boxes and dynamic role +changes still need native geometry coverage; this records lowering support only. + +### CSS table roles and dynamic display (2026-09-10) + +A compiled div/table-row/table-cell fixture verifies side-by-side native cell +placement. Class mutation switches all roles to block layout and stacks the cells; +removing the class restores the original table geometry. Rebuilt contracts pass. +This covers explicit CSS table structure; anonymous wrappers, inline-table baseline +behavior and browser differential comparisons remain open. + +### Display contents lowering (2026-09-10) + +Compiler display lowering now admits contents through the existing native enum. +A compiled wrapper fixture verifies its two children participate directly in the +parent flex row, followed by an outside sibling at the expected position. All 77 +compiler tests and rebuilt contracts pass. Box suppression in paint/hit testing, +inheritance, dynamic role changes and accessibility remain separate coverage gaps. + +### Display contents pointer propagation (2026-09-10) + +Native contracts hit a visible child of the compiled display:contents wrapper +using pointer coordinates and verify both child targeting and bubbling through +the DOM wrapper. Rebuilt contracts pass. This verifies event ancestry survives +layout flattening; wrapper paint suppression and accessibility remain open. + +### Display contents box paint evidence (2026-09-10) + +The contents fixture now authors a colored background and border on its wrapper. +Native scene commands contain no wrapper paint with that color, while the existing +child layout and pointer propagation checks still pass. Rebuilt contracts pass. +This verifies background/border suppression in scene output, not raster pixels or +all effects such as shadows, transforms and filters. Accessibility remains open. + +### Contents-to-block mutation (2026-09-10) + +Contracts switch the compiled contents wrapper to block via an important class +rule. Its background/border paint returns and its children resume vertical block +flow. Removing the class restores direct child participation in the outer flex +row. Rebuilt contracts pass. This adds live role-change evidence; effects, +accessibility and browser pixel comparisons remain open. + +### Align-self compiler/native bridge (2026-09-10) + +Added align-self lowering through a supported native writer, including auto's +unspecified state and native start/end/center/stretch/baseline modes. A native flex +fixture verifies center overrides parent start alignment and changing to auto +restores parent alignment. All 77 compiler tests and rebuilt contracts pass. +Baseline, stretch, grid alignment, logical directions and CSS-wide values still +need dedicated semantic coverage; this closes the basic flex override path. + +### Align-self stretch/end mutation (2026-09-10) + +Native contracts switch the flex child to stretch with auto height and verify +it fills the 40px cross axis. Switching to end restores its explicit 10px height +and positions it 30px from the parent's top. Rebuilt contracts pass. Baseline, +column-direction and grid alignment remain separate coverage gaps. + +### Flex space-around and space-evenly lowering (2026-09-10) + +Compiler justify-content now exposes the native space-around and space-evenly +modes. A 100px flex fixture containing two 20px items verifies offsets 15/65px +for around and 20/60px for evenly after class mutation. All 77 compiler tests +and rebuilt contracts pass. Wrapped lines, overflow and logical-direction cases +remain outside this evidence. + +### Flex distribution with explicit gap (2026-09-10) + +The compiled distribution fixture now applies a 12px gap. Native contracts verify +space-evenly offsets of 16/64px and space-around offsets of 12/68px in the 100px +container, accounting for the explicit gap before distributing remaining space. +Rebuilt contracts pass. Negative free space and wrapped-line distribution remain +open cases. + +### Normal gap in flex/grid profile (2026-09-10) + +Literal row-gap/column-gap normal now lower to zero for supported flex/grid +layouts, including mixed shorthand values and case-insensitive spelling. Compiler +coverage checks these forms; native flex geometry verifies switching from an +explicit gap to normal restores zero-gap distribution. All 78 compiler tests and +rebuilt contracts pass. Multicol's different normal-gap semantics require a distinct +representation when that layout is supported; variable normal tokens remain open. + +### Normal tokens in variable gap shorthand (2026-09-10) + +Compiled variable gap shorthand now accepts normal tokens as zero without +invalidating the other axis. A native fixture verifies var(--MixedGap, NORMAL +12px) preserves the 12px column gap, yielding the expected flex distribution. +All 78 compiler tests and rebuilt contracts pass. This targets supported flex/grid +semantics; multicol normal-gap behavior remains outside the profile. + +### Column-flex self alignment (2026-09-10) + +An independent compiled column-flex fixture verifies align-self:center places a +20px child 40px from the left of a 100px container despite parent start alignment. +Rebuilt contracts pass. This covers the horizontal cross-axis path; baseline, +logical writing directions and grid self alignment remain open. + +### Grid self-alignment arrange defect (2026-09-10) + +A compiled 40px grid-row fixture with a 10px align-self:center child failed because +the grid arrange pass ignored alignment. The pass now selects self/parent alignment, +uses intrinsic height for nonstretched auto-height items, and applies center/end +block-axis offsets. The 15px centering regression and native contracts pass. +Auto margins, post-constraint offsets, baseline groups and alternate grid paths +remain open; this fixes the exercised explicit-track arrange path only. + +### Grid vertical auto-margin precedence (2026-09-10) + +A native regression showed margin-top:auto failing to override align-self:center. +Explicit-track grid arrangement now distributes positive remaining block space +to auto margins before alignment and avoids stretching auto-height items with +vertical auto margins. The 10px child now sits at offset 30px in its 40px track; +rebuilt contracts pass. Horizontal auto margins, min/max constraints and other +grid arrange paths remain open. + +### Grid horizontal auto margins (2026-09-10) + +Explicit-track grid arrangement now allocates positive horizontal free space to +auto margins and uses intrinsic width instead of stretch for auto-width items +with horizontal auto margins. A native fixture verifies a 20px item with auto left +margin moves to x+80 in its 100px track. Rebuilt contracts pass. Both-auto margins, +intrinsic shrink-to-fit details and min/max constraints remain open coverage gaps. + +### Grid alignment after size constraints (2026-09-10) + +Work order reaffirmed: complete the structured HTML/CSS compiler audit before +resuming Kestrel-driven implementation. Use independent fixtures to establish +support, record unsupported behavior explicitly, and close gaps with regression +coverage rather than treating preview output as parity. + +A new compiled fixture reproduced incorrect centering and auto-margin placement +when min-width/min-height enlarged an explicitly sized grid item. Explicit-track +arrangement now applies min/max constraints before calculating alignment offsets, +including content-box padding/borders and minimum-over-maximum precedence. +The regression verifies a 40x20 constrained item at offset (60,10) in a 100x40 +track. It failed before the change and passes afterward; compiler and native +contract suites pass. Maximum-size, percentage and box-sizing combinations still +need dedicated coverage. Alternate grid paths and broader layout parity remain +open; this does not close the layout audit family. + +### Final height constraints and grid box sizing (2026-09-10) + +Independent compiled grid fixtures now exercise both auto margins, maximum sizes, +content-box padding/borders, border-box constraints, and minimum/maximum conflicts. +The conflict fixture failed: arrangement selected the correct 26px outer height, +but layout_child's final max-height clamp reduced it to 6px. That shared clamp now +accounts for content-box edges and lets minimum height win over maximum height. +The cases pass with expected sizes/offsets after the fix. Rebuilt smoke, templates, +C++ module templates, contracts and compiler suites all pass (five CTest entries). +This shared engine change has not been verified across V8 hosts or against browser +screenshots. Percentage containing blocks and automatic minimum sizes remain open. +After closing this discovered regression, resume the earliest open audit gates +listed above rather than extending grid coverage indefinitely. + +### Embedded stylesheet declaration locations (2026-09-10) + +Returned to the first audit family. Embedded style blocks now translate CSS parser +line/column locations to document positions when their raw text can be matched in +the source. Successive blocks advance a cursor, so identical declarations in +repeated style blocks no longer all report the first property occurrence. This +also maps selector and CSS syntax diagnostics through the same location helper. +An independent preview fixture checks two identical one-line blocks and a +multiline block; the strict unsupported-property fixture now requires column 26 +rather than the old column 1. All 79 compiler tests pass. + +This is still a source-text matching bridge, not complete HTML token spans: text +normalization (such as CRLF), matching text in other HTML contexts, inline attribute +entities and multiline start tags require parser-origin offsets. When an embedded +block cannot be matched, the existing approximate location fallback remains. +The source-location closure gate stays open pending those cases. + +### HTML newline normalization for diagnostics (2026-09-10) + +A regression with CRLF embedded CSS reproduced fallback to column 1 instead of +column 3. The compiler now normalizes CRLF and lone CR to LF before HTML parsing +and diagnostic lookup, matching HTML input preprocessing without changing source +files. Both newline forms report the tested declaration at line 4, column 3. +All 80 compiler tests pass. This closes the newline mismatch for the exercised +embedded block; source-text ambiguity and token-origin spans remain open. + +### Embedded CSS lookup bounded by owner line (2026-09-10) + +An independent fixture reproduced a diagnostic pointing into an earlier HTML +comment containing identical CSS. Lookup now starts no earlier than the parser's +style-element creation line and the preceding matched block's end. The regression +reports the actual style declaration at line 3, column 14 rather than the comment +at line 2, column 12. All 81 compiler tests pass. Same-line comment/attribute +ambiguity is explicitly unresolved; full token-origin offsets remain the required +closure mechanism, not additional substring heuristics. + +### Nested literal calc shorthand audit (2026-09-10) + +Verified existing inset lowering independently of variable-containing expressions. +New compiler coverage accepts nested groups/functions, mixed-case CALC, literal +scalar multiplication/division and four-component calc shorthands; dimensional +products and division by zero are rejected. Generated output contains typed +add_compiled_lengths operations. Native class mutation checks top=14px and +left=(50%-20px)/2: the left offset changes from 40px to 65px as the containing +width changes from 200px to 300px, then removing the override restores the prior +variable expression. Compiler (82 tests) and native contracts pass. No production +change was needed. This establishes the exercised nested extraction/precedence +cases; general custom-value function trees and nonliteral scalar expressions +remain open and are not implied supported by this result. + +### ASCII custom-property name grammar (2026-09-10) + +The variable-reference regex incorrectly required a letter or underscore after +`--`, rejecting valid dashed identifiers such as `--1` and `---`. Updated the +reference and supported color-mix paths to accept nonempty ASCII name suffixes +including digits and hyphens. The reserved `--` and malformed references remain +rejected. The grammar decision follows CSS Variables Level 1: +https://www.w3.org/TR/css-variables-1/ . + +A compiler regression failed on `--1` before the change. All 83 compiler tests now +pass, as do native contracts covering an inherited `---:var(--1)` reference and +class removal restoring the original inset. Escaped and non-ASCII identifiers +remain open; this is not a claim of complete CSS identifier support. + +### Tokenizer-backed custom-property references (2026-09-10) + +Replaced var()'s ASCII identifier regex with validation/decoding through the +existing build-time CSS declaration tokenizer. A single synthetic declaration +must parse without errors and retain the expected sentinel value and a nonempty +dashed name. This aligns reference identity with parsed definitions and rejects +malformed names or additional declarations. No parser is added to generated apps. + +All 84 compiler tests pass, including Unicode and escaped names and malformed +reference cases. Native contracts verify an inherited Unicode reference chain +ending in an escaped spelling of café resolves to the expected 34px inset. +The specialized color-mix regex still has its narrower ASCII input grammar; +escaped punctuation inside var() scanning and broader custom-value token trees +remain open. Identifier support outside this var() path is not implied complete. + +### Escaped delimiters in variable references (2026-09-10) + +The var() boundary scanner incorrectly treated escaped commas/parentheses in +custom-property names as syntax. A new regression failed on an escaped comma +before the change. Scanning now skips escaped punctuation before counting groups +or finding the fallback separator; the build-time tokenizer still decodes and +validates the name. Compiler coverage exercises escaped comma, both parentheses +and backslash. Native contracts verify an inherited chain using comma and closing +parenthesis names selects 38px rather than the 9px fallback. All 85 compiler tests +and native contracts pass. This fixes var() framing only: shared component-value +scanners and specialized color-mix parsing still need the same token-aware audit. + +### Escaped identifiers through shorthand component scanning (2026-09-10) + +The shared component scanner still counted escaped parentheses in var() names, +rejecting a valid inset shorthand as an unbalanced function. It now skips escaped +characters before tracking nesting or whitespace boundaries. A regression matrix +covers escaped parentheses/comma references in inset, padding, margin and gap; +it failed before the fix. Native coverage now uses escaped names in a four-sided +inset shorthand and verifies both offsets equal 38px. All 86 compiler tests and +native contracts pass. This covers escaped punctuation inside variable functions; +quoted token sequences and complete CSS component-token handling remain open. + +### Escaped references within calc expressions (2026-09-10) + +Calc's enclosing-group and reverse operator scans still counted escaped identifier +punctuation, rejecting valid variable expressions. The forward scan now skips +escapes and the reverse scans check backslash parity before interpreting syntax. +Regression coverage for escaped parentheses, multiplication and division symbols +failed before the fix. All 87 compiler tests pass; native contracts verify an +inherited escaped name inside a calc shorthand resolves 38px + 2px to 40px. +General token-tree lowering remains open; this repairs the existing typed calc +path without adding runtime parsing or claiming unrestricted CSS math support. + +### Color-mix component grammar (2026-09-10) + +Replaced the specialized ASCII-name regex with nested component splitting for the +existing sRGB color-percentage-to-transparent profile. It now accepts nested var +fallbacks, Unicode/escaped names, case-insensitive function/keywords, and signed, +decimal or exponent percentage forms. Empty comma arguments, invalid literal +colors and out-of-range/nonfinite percentages fail compilation. Variable colors +retain existing computed-time validity handling. All 89 compiler tests pass; +rebuilt native contracts passed after component lowering changes. New grammar +cases do not yet have dedicated rendered comparisons. General two-color mixing, +other color spaces and complete color syntax remain open. + +### Color-mix native paint and interpolation whitespace (2026-09-10) + +Native scene-command checks now cover nested fallback resolution, a Unicode +custom-property override with existing alpha, and restoration after class removal. +Expected background RGBA values are 12345680, abcdef40, then 12345680; rebuilt +contracts pass. These inspect submitted paint colors, not browser pixel parity. +Interpolation keywords now split on CSS whitespace and accept intervening comments +in the supported `in srgb` prelude. All 90 compiler tests pass. General comment +handling across component scans and rendered differential comparisons remain open. + +### Shared component scanner comments and strings (2026-09-10) + +Replaced substring-only splitting with a component accumulator that tracks quotes, +escapes, nesting and comments. Comment punctuation no longer changes grouping or +comma separation, and quoted text remains intact. Removed the interpolation-only +comment regex. A regression with commas and parentheses inside comments failed +before the fix; coverage includes color-mix and inset components. The native mix +fixture now includes those comments and retains its expected paint/mutation results. +All 91 compiler tests pass, as do rebuilt smoke, template, module-template and +native contract suites. This improves callers of component_values; direct var/calc +scanners and other ad hoc grammars still require comment/token-tree auditing. + +### Shared comment scanning for direct variables and calc (2026-09-10) + +Added a no-split mode to the shared component scanner and used it before direct +variable/custom-value and calc lowering. Comments containing delimiters no longer +corrupt those paths. A compiler regression failed on a comment after a variable +name before the fix. All 92 compiler tests pass; native contracts retain the +expected 40px calc inset with comments inside the escaped-name reference and +arithmetic expression. Token-boundary subtleties (including comments adjacent to +operators without authored whitespace) and full component-token semantics remain +open; this does not close the grammar family. + +### Shared supported named-color lowering (2026-09-10) + +The native color parser already handles 20 basic named colors plus transparent; +compiler literals and variable metadata previously admitted only black/white/ +transparent. Added one shared validator for the engine's existing named set and +hex forms. Names are matched case-insensitively without changing variable names. +Compiler coverage compares literal and fallback RGBA across foreground, +background and borders. All 93 compiler tests pass. Native contracts verify +ORANGE in a custom property produces ffa50080 through the compiled 50% mix and +restores the fallback after mutation. The complete CSS named-color set and +functional color grammar remain open; this does not claim full color support. + +### Complete named-color table shared with native parsing (2026-09-10) + +Added all 148 named-color entries from CSS Color 4 section 6.1 to one internal +native table. Both native parse_color and compiler literal/custom-value validation +use it; transparent remains a separate keyword. Source: +https://www.w3.org/TR/css-color-4/#named-colors (retrieved 2026-09-10). +The checked-in named-colors.json fixture records the corresponding specification +values for offline compiler tests. All names compile in uppercase literal form +and lowercase variable fallback form, with expected RGBA constants (94 compiler +tests pass). Native paint/mutation coverage now exercises REBECCAPURPLE through +the 50% mix, expecting 66339980. Rebuilt smoke, templates, module templates and +contracts pass. Functional colors, system colors, currentcolor semantics and +browser rendering comparisons remain open; only the named-color inventory is +completed here. The shared parser change has not been tested in V8 hosts. + +### Typed RGB/RGBA literal lowering (2026-09-10) + +Added strict build-time lowering of numeric rgb()/rgba() values: legacy comma +channels (uniform number or percentage units), modern space channels with optional +slash alpha, numeric/percentage alpha, case-insensitive names, signed/exponent +numbers and range clamping. Constants are emitted directly for foreground, +background and borders; custom properties/fallbacks retain typed color metadata. +Component extraction now retains whole literal functions in custom-value lists. + +All 95 compiler tests pass, including malformed channel counts, mixed legacy +units, invalid units, missing alpha and nonfinite numbers. Native paint/mutation +coverage verifies rgb(10 20 30 / 50%) through a 50% mix emits 0a141e40. +Rebuilt smoke, template, module-template and contract suites pass. Relative colors, +none channels, channel variables/math, HSL/HWB and other color spaces remain open. +This is literal RGB lowering, not completion of functional-color semantics or +browser differential validation. No runtime CSS parser is introduced. + +### At-rule diagnostic classification (2026-09-10) + +The compatibility checkpoint exposed misleading keyframes errors describing media +conditions. Non-media at-rules now report their actual unsupported rule kind; +media failures retain the condition diagnostic. All 96 compiler tests pass, +including keyframes, supports and print-media classification. No at-rule support +is claimed by this diagnostic change. diff --git a/docs/design/native-web-css-checkpoint.txt b/docs/design/native-web-css-checkpoint.txt new file mode 100644 index 000000000..b417a152b --- /dev/null +++ b/docs/design/native-web-css-checkpoint.txt @@ -0,0 +1,134 @@ +samples/NativeKestrel/reference/src/style.css: error: #command-input::placeholder: unsupported selector: #command-input::placeholder + in rule: samples/NativeKestrel/reference/src/style.css:11:1429 +samples/NativeKestrel/reference/src/style.css: error: #ribbon-tab-list button.active:after: unsupported selector: #ribbon-tab-list button.active::after + in rule: samples/NativeKestrel/reference/src/style.css:5:428 +samples/NativeKestrel/reference/src/style.css: error: .document-tab.active:after: unsupported selector: .document-tab.active::after + in rule: samples/NativeKestrel/reference/src/style.css:7:561 +samples/NativeKestrel/reference/src/style.css: error: .panel-tabs button.active:after: unsupported selector: .panel-tabs button.active::after + in rule: samples/NativeKestrel/reference/src/style.css:8:1190 +samples/NativeKestrel/reference/src/style.css: error: .progress-line:after: unsupported selector: .progress-line::after + in rule: samples/NativeKestrel/reference/src/style.css:14:4419 +samples/NativeKestrel/reference/src/style.css: error: .property-section-title:before: unsupported selector: .property-section-title::before + in rule: samples/NativeKestrel/reference/src/style.css:10:609 +samples/NativeKestrel/reference/src/style.css: error: @keyframes progress: unsupported at-rule: @keyframes + in rule: samples/NativeKestrel/reference/src/style.css:14:4561 +samples/NativeKestrel/reference/src/style.css: error: @keyframes toast-in: unsupported at-rule: @keyframes + in rule: samples/NativeKestrel/reference/src/style.css:13:1263 +samples/NativeKestrel/reference/src/style.css: error: @media (prefers-reduced-motion:reduce): only min/max width or height media conditions in px are supported + in rule: samples/NativeKestrel/reference/src/style.css:19:1 +samples/NativeKestrel/reference/src/style.css: error: @media print: only min/max width or height media conditions in px are supported + in rule: samples/NativeKestrel/reference/src/style.css:20:1 +samples/NativeKestrel/reference/src/style.css: error: accent-color:var(--accent): compiled var() not supported for property: accent-color + in rule: input[type=checkbox] at samples/NativeKestrel/reference/src/style.css:3:841 +samples/NativeKestrel/reference/src/style.css: error: animation:none: unsupported Native Web CSS property: animation + in rule: @media (prefers-reduced-motion:reduce) > * at samples/NativeKestrel/reference/src/style.css:19:41 +samples/NativeKestrel/reference/src/style.css: error: animation:progress 1.2s infinite ease-in-out: unsupported Native Web CSS property: animation + in rule: .progress-line:after at samples/NativeKestrel/reference/src/style.css:14:4516 +samples/NativeKestrel/reference/src/style.css: error: animation:toast-in .15s ease-out: unsupported Native Web CSS property: animation + in rule: .toast at samples/NativeKestrel/reference/src/style.css:13:1079 +samples/NativeKestrel/reference/src/style.css: error: backdrop-filter:blur(3px): unsupported Native Web CSS property: backdrop-filter + in rule: dialog::backdrop at samples/NativeKestrel/reference/src/style.css:14:207 +samples/NativeKestrel/reference/src/style.css: error: backdrop-filter:blur(9px): unsupported Native Web CSS property: backdrop-filter + in rule: .floating-toolbar at samples/NativeKestrel/reference/src/style.css:9:2004 +samples/NativeKestrel/reference/src/style.css: error: background:color-mix(in srgb,var(--active) 63%,var(--panel)): compiled color-mix currently supports an sRGB color percentage mixed with transparent + in rule: .layer-row.current at samples/NativeKestrel/reference/src/style.css:8:2369 +samples/NativeKestrel/reference/src/style.css: error: background:linear-gradient(125deg,var(--panel2),var(--panel)): unsupported custom-value token: linear-gradient(125deg,var(--panel2),var(--panel)) + in rule: .modal-header at samples/NativeKestrel/reference/src/style.css:14:494 +samples/NativeKestrel/reference/src/style.css: error: background:linear-gradient(145deg,var(--panel2),var(--panel)): unsupported custom-value token: linear-gradient(145deg,var(--panel2),var(--panel)) + in rule: .explorer-summary at samples/NativeKestrel/reference/src/style.css:8:3644 +samples/NativeKestrel/reference/src/style.css: error: border-collapse:collapse: unsupported Native Web CSS property: border-collapse + in rule: .report-table at samples/NativeKestrel/reference/src/style.css:14:2805 +samples/NativeKestrel/reference/src/style.css: error: border:1px dashed #65c5a4: border shorthand currently requires width solid color, 0 or none + in rule: #selection-window.crossing at samples/NativeKestrel/reference/src/style.css:9:4061 +samples/NativeKestrel/reference/src/style.css: error: border:2px dashed var(--accent): border shorthand currently requires width solid color, 0 or none + in rule: #drop-zone at samples/NativeKestrel/reference/src/style.css:9:4148 +samples/NativeKestrel/reference/src/style.css: error: box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 25%,transparent): unsupported custom-value token: color-mix(in srgb,var(--accent) 25%,transparent) + in rule: input:focus,select:focus,textarea:focus at samples/NativeKestrel/reference/src/style.css:3:597 +samples/NativeKestrel/reference/src/style.css: error: box-shadow:inset 0 -2px 0 var(--accent): native compiled inset shadows are not supported yet + in rule: #layout-tabs button.active at samples/NativeKestrel/reference/src/style.css:12:431 +samples/NativeKestrel/reference/src/style.css: error: box-shadow:inset 0 0 0 1px var(--accent-dim): native compiled inset shadows are not supported yet + in rule: .ribbon-large.active,.ribbon-small.active at samples/NativeKestrel/reference/src/style.css:6:1213 +samples/NativeKestrel/reference/src/style.css: error: box-shadow:inset 2px 0 0 var(--accent): native compiled inset shadows are not supported yet + in rule: .layer-row.current at samples/NativeKestrel/reference/src/style.css:8:2430 +samples/NativeKestrel/reference/src/style.css: error: color-scheme:dark: unsupported Native Web CSS property: color-scheme + in rule: :root at samples/NativeKestrel/reference/src/style.css:1:7 +samples/NativeKestrel/reference/src/style.css: error: color-scheme:light: unsupported Native Web CSS property: color-scheme + in rule: :root[data-theme=light] at samples/NativeKestrel/reference/src/style.css:2:25 +samples/NativeKestrel/reference/src/style.css: error: content:"": unsupported Native Web CSS property: content + in rule: #ribbon-tab-list button.active:after at samples/NativeKestrel/reference/src/style.css:5:465 + in rule: .document-tab.active:after at samples/NativeKestrel/reference/src/style.css:7:588 + in rule: .panel-tabs button.active:after at samples/NativeKestrel/reference/src/style.css:8:1222 + in rule: .progress-line:after at samples/NativeKestrel/reference/src/style.css:14:4440 +samples/NativeKestrel/reference/src/style.css: error: content:"⌄": unsupported Native Web CSS property: content + in rule: .property-section-title:before at samples/NativeKestrel/reference/src/style.css:10:640 +samples/NativeKestrel/reference/src/style.css: error: cursor:col-resize: unsupported Native Web CSS property: cursor + in rule: .panel-resizer at samples/NativeKestrel/reference/src/style.css:8:4385 +samples/NativeKestrel/reference/src/style.css: error: cursor:crosshair: unsupported Native Web CSS property: cursor + in rule: #viewport at samples/NativeKestrel/reference/src/style.css:9:101 +samples/NativeKestrel/reference/src/style.css: error: cursor:grabbing: unsupported Native Web CSS property: cursor + in rule: #viewport.panning at samples/NativeKestrel/reference/src/style.css:9:148 +samples/NativeKestrel/reference/src/style.css: error: cursor:move: unsupported Native Web CSS property: cursor + in rule: #viewport.orbiting at samples/NativeKestrel/reference/src/style.css:9:183 +samples/NativeKestrel/reference/src/style.css: error: cursor:not-allowed: unsupported Native Web CSS property: cursor + in rule: button:disabled at samples/NativeKestrel/reference/src/style.css:3:387 +samples/NativeKestrel/reference/src/style.css: error: cursor:pointer: unsupported Native Web CSS property: cursor + in rule: #viewcube svg g at samples/NativeKestrel/reference/src/style.css:9:972 + in rule: .layer-row at samples/NativeKestrel/reference/src/style.css:8:2335 + in rule: .object-row at samples/NativeKestrel/reference/src/style.css:8:3090 + in rule: .suggestion at samples/NativeKestrel/reference/src/style.css:11:1871 + in rule: button at samples/NativeKestrel/reference/src/style.css:3:250 + in rule: input[type=color] at samples/NativeKestrel/reference/src/style.css:3:805 +samples/NativeKestrel/reference/src/style.css: error: cursor:row-resize: unsupported Native Web CSS property: cursor + in rule: #command-resizer at samples/NativeKestrel/reference/src/style.css:11:280 +samples/NativeKestrel/reference/src/style.css: error: dialog::backdrop: unsupported selector: dialog::backdrop + in rule: samples/NativeKestrel/reference/src/style.css:14:169 +samples/NativeKestrel/reference/src/style.css: error: filter:brightness(1.1): unsupported Native Web CSS property: filter + in rule: .button.primary:hover at samples/NativeKestrel/reference/src/style.css:14:1334 +samples/NativeKestrel/reference/src/style.css: error: font-synthesis:none: unsupported Native Web CSS property: font-synthesis + in rule: :root at samples/NativeKestrel/reference/src/style.css:1:520 +samples/NativeKestrel/reference/src/style.css: error: grid-column:1/-1: unsupported Native Web CSS property: grid-column + in rule: .form-divider at samples/NativeKestrel/reference/src/style.css:14:2101 + in rule: .form-field.full at samples/NativeKestrel/reference/src/style.css:14:1738 +samples/NativeKestrel/reference/src/style.css: error: outline-offset:-2px: unsupported Native Web CSS property: outline-offset + in rule: button:focus-visible,a:focus-visible,[tabindex]:focus-visible at samples/NativeKestrel/reference/src/style.css:3:962 +samples/NativeKestrel/reference/src/style.css: error: outline:2px solid var(--accent): compiled var() not supported for property: outline + in rule: button:focus-visible,a:focus-visible,[tabindex]:focus-visible at samples/NativeKestrel/reference/src/style.css:3:930 +samples/NativeKestrel/reference/src/style.css: error: outline:none: unsupported Native Web CSS property: outline + in rule: #viewport at samples/NativeKestrel/reference/src/style.css:9:70 + in rule: input,select,textarea at samples/NativeKestrel/reference/src/style.css:3:517 +samples/NativeKestrel/reference/src/style.css: error: overflow-wrap:anywhere: unsupported Native Web CSS property: overflow-wrap + in rule: #command-history>div at samples/NativeKestrel/reference/src/style.css:11:629 +samples/NativeKestrel/reference/src/style.css: error: resize:vertical: unsupported Native Web CSS property: resize + in rule: .form-field textarea at samples/NativeKestrel/reference/src/style.css:14:2002 +samples/NativeKestrel/reference/src/style.css: error: scrollbar-color:var(--line) transparent: compiled var() not supported for property: scrollbar-color + in rule: #command-history at samples/NativeKestrel/reference/src/style.css:11:508 + in rule: .panel-scroll at samples/NativeKestrel/reference/src/style.css:8:2104 +samples/NativeKestrel/reference/src/style.css: error: scrollbar-width:none: unsupported Native Web CSS property: scrollbar-width + in rule: #document-tabs at samples/NativeKestrel/reference/src/style.css:7:228 +samples/NativeKestrel/reference/src/style.css: error: scrollbar-width:thin: unsupported Native Web CSS property: scrollbar-width + in rule: #command-history at samples/NativeKestrel/reference/src/style.css:11:487 + in rule: #modal-body at samples/NativeKestrel/reference/src/style.css:14:730 + in rule: #palette-results at samples/NativeKestrel/reference/src/style.css:15:399 + in rule: #ribbon at samples/NativeKestrel/reference/src/style.css:6:193 + in rule: .panel-scroll at samples/NativeKestrel/reference/src/style.css:8:2083 +samples/NativeKestrel/reference/src/style.css: error: text-overflow:ellipsis: unsupported Native Web CSS property: text-overflow + in rule: #command-prefix at samples/NativeKestrel/reference/src/style.css:11:1245 + in rule: .layer-row .layer-name at samples/NativeKestrel/reference/src/style.css:8:2591 + in rule: .property-row>span at samples/NativeKestrel/reference/src/style.css:10:1284 + in rule: .title-document #title-name at samples/NativeKestrel/reference/src/style.css:4:1028 +samples/NativeKestrel/reference/src/style.css: error: touch-action:none: unsupported Native Web CSS property: touch-action + in rule: #viewport at samples/NativeKestrel/reference/src/style.css:9:83 +samples/NativeKestrel/reference/src/style.css: error: transition:fill .15s: unsupported Native Web CSS property: transition + in rule: #viewcube polygon at samples/NativeKestrel/reference/src/style.css:9:1060 +samples/NativeKestrel/reference/src/style.css: error: transition:none: unsupported Native Web CSS property: transition + in rule: @media (prefers-reduced-motion:reduce) > * at samples/NativeKestrel/reference/src/style.css:19:66 +samples/NativeKestrel/reference/src/style.css: error: user-select:none: unsupported Native Web CSS property: user-select + in rule: #documentbar at samples/NativeKestrel/reference/src/style.css:7:147 + in rule: #ribbon at samples/NativeKestrel/reference/src/style.css:6:214 + in rule: #ribbon-tabs at samples/NativeKestrel/reference/src/style.css:5:150 + in rule: #statusbar at samples/NativeKestrel/reference/src/style.css:12:141 + in rule: #titlebar at samples/NativeKestrel/reference/src/style.css:4:232 + in rule: #viewcube at samples/NativeKestrel/reference/src/style.css:9:831 +samples/NativeKestrel/reference/src/style.css: error: user-select:text: unsupported Native Web CSS property: user-select + in rule: #command-history at samples/NativeKestrel/reference/src/style.css:11:548 +397 rules, 1475 declarations, 55 distinct unsupported constructs diff --git a/docs/design/native-web-os-resize-evidence.json b/docs/design/native-web-os-resize-evidence.json new file mode 100644 index 000000000..b5f3b237c --- /dev/null +++ b/docs/design/native-web-os-resize-evidence.json @@ -0,0 +1,45 @@ +{ + "test": "OS CGEvent corner drag, 300x180 points inward and back, 360 steps", + "start": 63910.721123, + "end": 63917.818877, + "duration_seconds": 7.097753999994893, + "layer_size_events": 358, + "submissions": 426, + "valid_presented_timestamps": 1, + "retained_submissions": 51, + "conclusion": "Native live resize exercised; physical presentation rate and visual stretching remain unproven.", + "context_trace_followup": [ + { + "transaction": false, + "retained": false, + "callbacks": 3, + "valid_presentation_timestamps": 1, + "distinct_dimensions": 1 + }, + { + "transaction": true, + "retained": true, + "callbacks": 58, + "valid_presentation_timestamps": 0, + "distinct_dimensions": 57 + }, + { + "transaction": true, + "retained": false, + "callbacks": 381, + "valid_presentation_timestamps": 1, + "distinct_dimensions": 181 + } + ], + "midpoint_capture": { + "path": "/tmp/kestrel-live-resize-midpoint.png", + "method": "macOS screencapture of target CGWindow during held corner drag after 180 of 360 steps", + "pause_seconds": 0.2, + "observations": [ + "Original narrow-window layout hides Properties panel", + "Ribbon becomes horizontally scrollable", + "Drawing is clipped to resized viewport; no obvious stretching in sampled frame" + ], + "limitations": "Paused sample cannot prove continuous no-stretch motion or displayed 60fps." + } +} diff --git a/docs/design/native-web-remaining-55-plan.md b/docs/design/native-web-remaining-55-plan.md new file mode 100644 index 000000000..d8988170d --- /dev/null +++ b/docs/design/native-web-remaining-55-plan.md @@ -0,0 +1,2496 @@ +# Remaining 55 CSS constructs: integrated implementation plan + +Status: active. Requested as one integrated implementation pass, without stopping +for approval or treating individual commits as completion. Preserve original +Kestrel HTML/CSS and use independent fixtures to develop each feature family. +Baseline: native-web-css-checkpoint.txt, 397 rules / 1475 declarations, 55 distinct +unsupported constructs. These are distinct source usages, not 55 separate engines. + +## Architecture and boundaries + +Group/picking integration verified: the native picking fixture now creates its +group through group_entities instead of manually assigning metadata. It verifies +ordinary group selection, individual selection with ignore-group, Ungroup from +one member, single-object picking after ungroup and restored group picking after +exact undo. The existing pick implementation already matches the original app's +visible-peer selection and modifiers; no new selection algorithm was needed. +The native layer suite passes. + +V8 backdrop scene verification: new modal-backdrop runtime test opens a JavaScript +dialog, acquires emitted scene records, requires one viewport-sized authored +backdrop, toggles a transparent class off/on and closes the dialog. It requires +new scene revisions for each state and acknowledges/releases acquired scenes. +The rebuilt V8 engine test passes. This is reference-path verification only; +native Kestrel still uses compiled templates with no JS or runtime HTML parsing. +Pixel equivalence, blur and broader backdrop syntax remain unverified. + +Backdrop cascade convergence: extracted solid backdrop application into the +shared pseudo-declaration helper, using the existing CSS color-token validator. +Both native cascade and the two V8 cascade paths now call it, resetting backdrop +color before each matched pseudo pass. This also prevents V8 from treating the +new backdrop pseudo kind as ::after. Native shared-style tests pass; V8 engine +and tests build, and fixed-auto-height-dialog regression passes. Direct V8 +backdrop scene/pixel parity and blur remain unverified. + +Shared native backdrop color: ::backdrop now has a recognized pseudo kind, native +dialog color storage, shared cascade handling for solid background/background-color +with important precedence, and viewport-sized foreground paint immediately before +each modal. Tests cover closed/open/resize, transparent overrides, priority and +parsed/generated stylesheet equivalence. The hosted original Group capture +/tmp/kestrel-group-backdrop.png visibly dims the UI and WebGPU canvas behind the +dialog. No app HTML/CSS was rewritten. Backdrop blur, broader background syntax, +currentColor and the legacy V8 cascade path remain outside this implementation; +unsupported declarations continue to be reported. + +Native label activation: pointer activation now resolves explicit for/id targets +and implicit wrapped controls, focuses and activates the associated control after +an uncancelled label click, and avoids reactivation from direct control clicks. +Disabled/inert targets are excluded and callback removal/disposal is rechecked. +Native input tests cover Group-style explicit labels, preventDefault, disabled +inputs and wrapping checkbox labels without double toggles; the suite passes. +This closes the basic native label behavior gap, not all HTML activation edge +cases or accessibility/browser parity. + +Group Unicode trim parity: group creation now trims the 25 ECMAScript whitespace +code points using UTF-8 boundaries, preserving accented/astral name content and +falling back to Group for all-whitespace names. A development Node reference +enumeration confirms the whitespace set and expected nonbreaking/ideographic/BOM +fixtures. Native tests verify the names and exact undo; the drawing suite passes. +No JavaScript dependency is added to the application. + +Hosted Group interaction verified: --exercise-group-dialog opens the compiled +original dialog, sends Foco text input into its focused name field, presses/releases +the rendered Create group button, requires applied names and closed modal, then +sends platform-Z and compares the complete drawing to its original snapshot. +The rebuilt app passes and captures /tmp/kestrel-group-submit.png (exit 0, +GPU serial 2). Input is injected through host methods; this is not physical OS +mouse/keyboard latency evidence. Backdrop visuals and broader dialog parity remain +open. + +Modal layout correction: runtime diagnostics located the original Group dialog +at (0,800), 510x278.4, below the viewport. Shared native layout now takes +default-positioned registered modals out of flow, sizes them against the viewport +and centers their subtree; explicitly positioned dialogs keep the CSS path. +Native tests verify centering at two viewport sizes and retain focus/isolation +checks. The hosted capture /tmp/kestrel-group-centered.png now visibly shows the +centered original Group form and focused input. Original HTML/CSS is unchanged. +Backdrop paint/blur, authored static-position distinctions, oversized-dialog +behavior and full modal browser parity still need coverage. + +Compiled Group dialog integration in progress: original body/field markup is a +predefined template; native handlers populate the name/count, submit captured +entities, cancel/Escape, restore focus and display validation errors. The existing +Group ribbon action is connected. Compiler templates now preserve authored IDs +(with named references), required by the original label/input association. Native +dialog creation/cancel/validation/focus tests and all 114 compiler tests pass. +The hosted build and --show-group-dialog capture run succeed, but the captured +original app does NOT visibly show the modal. Native modal registration and +top-layer painting exist; UA modal positioning/layout needs investigation before +this UI is usable. Do not count Group as complete. Unicode trim parity, label +activation and browser-equivalent form validation remain open as well. + +Native modal scope API: document::set_modal connects a native HTML dialog to the +existing engine modal stack and open attribute. It clears focus when blocked or +closed; the caller owns initial/restored focus and cancel/submit behavior. Native +tests cover background focus rejection, Tab wrap, nested modal precedence, +close/removal cleanup, non-dialog rejection and disposal during blur. The native +text/input suite passes. This is a structural native seam, not a complete browser +showModal implementation; the compiled Group dialog still needs connection. + +Modal prerequisite: native document focus and Tab candidate collection now consult +the existing engine is_inert check, which covers explicit inert ancestors and +registered modal scopes. Tests verify direct focus rejection, forward/reverse Tab +skipping (including positive tabindex), direct inert attributes and restoring +eligibility after removing inert. The native text/input suite passes. Public +show/close modal APIs, focus restoration, Escape cancellation and the compiled +Group dialog still need implementation; this is not complete dialog support. + +Group model foundation: group_entities accepts the dialog's captured entity IDs, +requires at least two distinct editable members, generates a shared group ID/name, +and commits one Create group undo transaction. Tests verify captured versus live +selection, regrouping without altering old peers, duplicate/missing/noneditable +members, ASCII whitespace trimming, blank-name fallback and exact undo. The +native drawing suite passes. This operation is not yet connected to the original +Group dialog; compiled dialog markup, modal focus/submit/cancel behavior, default +name/count, maxlength validation and Unicode trim parity remain open. + +Native Ungroup action: the existing compiled ribbon action now calls the native +model, collecting groups from editable selected entities and removing group and +groupName from all editable members of those groups, matching the original +app.js action. Model tests verify unselected peers, unrelated groups, locked and +hidden members, exact undo and empty selection. The native drawing suite and +hosted app build pass. Browser-style empty-selection feedback, interactive ribbon +verification and the separate Group dialog remain open. + +Compiled color-scheme coverage: SharedStyles.css now includes a dark media rule; +the parsed/generated integration sequence switches light/dark/light and requires +80/95/80px widths plus identical serialized scenes for both stylesheet producers. +The regenerated C++ CSS module builds and the shared-style suite passes. This +closes the generated-data verification gap from the previous runtime-only fixture, +without claiming OS preference notifications or broader browser parity. + +Color-scheme environment gap fixed: shared_css previously hardcoded the light +media environment. Native documents now expose set_dark_color_scheme, invalidate +styles when it changes, and pass it to the existing shared media evaluator. Foco's +view supplies its effective theme and requests a refresh when that preference +changes. A native shared-CSS test verifies light/dark/light widths and unchanged +preference layout stability. The hosted app builds and its existing theme/capture +exercise passes; that exercise changes Kestrel's data-theme and is not an OS theme +notification test. Typed-backend color-scheme lowering and OS theme transitions +remain outside this verification. + +Shared CSS parity check strengthened: shared_styles now records serialized scene +bytes at every render checkpoint and requires identical sequences for runtime +stylesheet preparation and compiler-generated stylesheet data on compiled HTML. +This includes hover/focus, class/text changes, viewport and reduced-motion changes, +template insertion/removal, scrollbar styling, SVG paint and stylesheet replacement. +The strengthened test passes. The compiler, shared document, native contract and +text/input suites also pass after rebuilding their targets. This compares fixture +scene serialization, not browser pixels or complete CSS/Kestrel coverage. + +Bundle symbol isolation: a broader audit found html5ever code linked into the +preview from the shared Rust archive despite no HTML entry-point call in native +authoring. Native macOS app targets now dead-strip unused code. The executable +shrinks from 18,120,944 to 14,353,808 bytes; Dawn remains 9,222,256 bytes. The new +tests/NativeWeb/audit_macos_bundle.py flags the old bundle's html5ever symbols and +passes the new bundle's source-asset, dependency/rpath, symbol-family and local +signature checks. The rebuilt app also passes the routed spectrum/undo capture +exercise (exit 0, GPU serial 3). This is structural evidence, not proof of every +runtime path or complete application parity; shared CSS interpretation remains. + +Native app relocation fix: FocoKestrel and FocoKestrelPreview now bundle Dawn in +Contents/Frameworks, use @executable_path/../Frameworks instead of an absolute +external SDK rpath, and receive local ad-hoc signatures after copying the library. +The rebuilt preview copied to /tmp/KestrelRelocatedNative.app passes strict/deep +signature verification and its routed spectrum drag/undo/capture exercise (exit +0, GPU serial 3). DYLD_PRINT_LIBRARIES confirms Dawn loads from that copied bundle. +Dawn's inspected dependencies are system libraries/frameworks. This establishes +local relocation for the preview; release identity signing/notarization, resource +coverage and complete application acceptance remain open. + +Startup-gap repeatability check: three consecutive fresh process launches of the +same Courtyard benchmark produce approximately 59.9998fps with no positive +presentation interval above 16.667ms. Raw traces and revision/hash metadata live +in performance/native-kestrel-pan-repeat-summary.json. The earlier 50ms startup +gap did not recur; preserve its trace and leave startup variability unresolved. +No renderer scheduling change is justified from these observations alone. These +synthetic pan runs do not prove live-resize cadence or physical pointer latency. + +Post-inspector hosted performance check: latest NativeKestrel builds and runs the +Courtyard pan benchmark. Evidence in performance/native-kestrel-pan-post-inspector.json +and its raw trace records 360 callbacks, 358 positive presentation timestamps, +59.665fps average, 16.667ms p95 and one 50ms interval between the first two positive +timestamps. No other interval exceeds 25ms. Geometry rebuilds remain zero and +the compositor reports zero skips. Preserve this startup gap as a remaining issue; +do not replace it with the earlier clean trace or claim uninterrupted 60fps. +Live window-resize presentation and full browser parity remain unproven. + +MTEXT paragraph information: native inspector now emits the original Paragraphs +readonly row through the compiled template. A boundary scanner follows pinned +Kestrel src/mtext.js handling for CR/LF, paragraph/column controls, escaped slashes, +literal fields and semicolon-terminated formatting arguments (including escaped +stack arguments). Six fixtures produce 1/6/1/2/2/1 in both the original JS parser +executed as a development reference and the native tests; the layer suite passes. +The shipped native app adds no JS. This scanner only counts boundaries: formatting +validation, warnings, resource limits, rich-text composition and layout still need +the full native MTEXT implementation. + +MTEXT inspector scalar editing: compiled coordinate templates now expose Position +XYZ, Text height and Paragraph width for native multiline-text entities. Width +accepts zero and rejects negative/nonfinite values; height remains positive. +The native inspector test enters each field through text input and Enter, checks +invalid width rejection and exact undo restoration while preserving rich-text +source. The native layer suite passes. Original HTML/CSS remains unchanged and +no runtime HTML parsing is introduced. Paragraph counting and the original rich +text composition action/dialog remain unimplemented; this is partial MTEXT +inspector coverage, not multiline layout/rendering parity. + +Spectrum routed-input verification: --exercise-color-picker now waits for popup +layout, locates its native spectrum, verifies window hit testing at two positions, +and raises pressed/moved/released routed pointer events on the hit control. Both +press and drag must change document color while keeping the picker open; the +selected entity color must match the spectrum and two undos restore exact states. +The hosted run passes and captures `/tmp/kestrel-picker-pointer.png` (exit 0, +GPU serial 3). This replaces direct set_color calls in the exercise. It verifies +native hit testing/control event routing, not OS event ingestion, out-of-bounds +pointer capture or physical interaction latency. + +Picker editing lifetime: the NativeKestrel host no longer closes the flyout from +its color-change callback, allowing successive edits in one open session. A +selection mismatch closes it without applying the stale edit. The hosted exercise +now applies two colors, requires the picker to remain open after both, dismisses +it and verifies exact intermediate and original document states through two undo +operations. Build and capture `/tmp/kestrel-picker-continuous.png` pass (exit 0). +These remain API-driven changes, not physical pointer-routing evidence. Each +change currently creates an undo entry; drag-session undo coalescing and native +mouse interaction remain to be reviewed against browser behavior. + +Picker background follow-up: the Foco editor panel now resolves Fluent.Surface +as its background. NativeKestrel rebuilt and the open-picker GPU capture +(`/tmp/kestrel-picker-background.png`, exit 0) shows an opaque panel with readable +RGB/hex fields. At 1280x800 it fits flush against the bottom/right window edges. +Small-window overflow and actual pointer selection remain unverified; no original +HTML/CSS changed. + +Foco spectrum box correction: retained rendering now uses the selected hue with +white-to-hue saturation and a vertical value shade, matching the control's native +pointer coordinates. Its selection marker follows saturation/value instead of +remaining at the center. The rebuilt NativeKestrel open-picker capture +(`/tmp/kestrel-spectrum-selection.png`) verifies the gradient and marker for the +selected color. Ring marker behavior, flyout placement/background and actual +pointer-driven selection still need work; this does not establish picker parity. + +Foco picker retained-rendering correction: color_spectrum now publishes reusable +gradient paint resources and complete retained commands for its existing box/ring +visuals. Basic headerless sliders without ticks/tooltips now emit retained tracks +and thumbs; unsupported slider variants remain explicitly incomplete. The open +Kestrel picker capture now succeeds and shows the spectrum/RGB controls, and the +open/commit/undo exercise passes again with a GPU capture. The flyout's chrome, +placement, spectrum selection marker and actual pointer color selection still +need review; this is not full picker appearance/interaction parity or 60fps resize +evidence. Foco owns these rendering fixes; WebScene remains unchanged by them. + +Color-picker integration work in progress: selected swatches now anchor Foco's +existing compact color_picker flyout; native color changes apply to the captured +selection only and refresh the model/DOM. --exercise-color-picker opens the flyout, +sets a color through the picker API and verifies exact undo; that path passes. +However --show-color-picker --capture fails while the flyout remains open: +Graphite reports an incomplete semantic record for color_spectrum (kind 15, +geometry box). The legacy Graphite node painter supports color_spectrum, but +scene-storage.cpp does not emit its retained semantic drawing record. This is a +rendering gap to fix before considering the picker usable; no visual success is +claimed. The selection guard and first-color close behavior also need interactive +review after rendering works. No source HTML/CSS changes or JS were introduced. + +Selected Color row restored in its original position before Linetype. Native color +updates validate hex/bylayer values; ByLayer changes editable selections with the +original undo label and refreshes the swatch. A native button-keyboard test checks +model state, inherited layer-color display and exact undo. Native color-picker +dialog activation, persisted/default color behavior and hosted verification remain +open; the swatch alone is not a complete color editor. + +Spline optional-property correction: adding degree to an ordered-json entity +could invalidate the referenced point-array entry before knot generation. The +editor now captures count and prepares knots before mutation. Native inspector +tests cover both points and controlPoints entities with omitted degree/knots, +enter degree through the compiled control and require exact undo. This removes a +native imported-entity lifetime hazard; full import/application parity remains open. + +Mesh/dimension native-control verification: a reusable compiled-inspector fixture +now enters Mesh Center X and dimension Precision, Text override and Offset using +text input plus Enter. Tests retain geometry/volume preservation, measurement +text, clamping and exact undo checks. The native inspector suite passes. Hosted +mesh/dimension interaction and remaining application parity remain open. + +Mesh inspector: compiled Center fields translate through the existing native +geometry transform; Width/Depth/Height, Vertices/Faces and Signed volume readouts +are populated. A model test verifies center translation, unchanged dimensions and +volume, and exact undo. Count formatting currently uses plain decimal rather than +locale grouping. Native-control/host mesh inspector verification and full parity +remain open. + +Dimension inspector: compiled Measurement, Offset, Text height, Text override and +Precision fields now bind to native edits. Precision rounds/clamps to 0..6; text +height must be positive. Model tests verify precision clamping, signed offset, +override text, validation and exact undo. The absent precision display uses the +original initial default 2; persisted application defaults and hosted dimension +control verification remain open. + +TEXT native control verification: the inspector test now types multiline content +into the compiled textarea, confirms Enter does not commit it, and commits on +focus departure. Rotation and height are entered through numeric controls and +committed with Enter. Direction removal, stored values and exact undo pass without +manually dispatching change. Hosted text editing, IME and full parity remain open. + +TEXT inspector: original Position, Text height, Rotation and textarea content now +use compiled rows and native change handlers. Rotation converts degrees to radians +and removes explicit direction as the original app does. Model tests cover content, +height validation, direction removal and exact undo. Native document/host tests +for the new text inspector and rich MTEXT editing remain open. + +Hatch control verification: tests now type Spacing and commit with Enter, select +Pattern using ArrowDown and verify model values and exact undo. Removed the added +wrapper around hatch rows so each original property-row is directly in its section; +the test checks this parent structure. Spacing display now trims trailing decimal +zeros. Native inspector regressions pass; hosted hatch interaction remains open. + +Hatch inspector: HATCH now shares Vertices/Length/Plan area measurements and exposes +compiled Spacing and Pattern controls. Native edits validate positive finite +spacing and supported pattern names and use undo transactions. Model tests cover +edits, invalid input and exact undo. Native document/host interaction verification +for these new controls remains open, as does complete application parity. + +Spline inspector: compiled Degree field and shared Vertices/Length/Plan area +readouts now cover SPLINE alongside polyline metrics. Native degree edits round +as in the original app, clamp to 1..min(10, point count - 1), regenerate uniform +knots and record undo. Model tests verify rounding, clamping, knot values and exact +undo. Hosted spline interaction and remaining application behavior remain open. + +Checkbox paint correction: the shared native scene builder now draws a check +indicator from live checkedness (falling back to the checked attribute), and does +not paint a checkbox's submitted value as text. Native scene tests verify checked, +unchecked and attribute/property precedence. Rebuilt Foco and repeated hosted +polyline click/undo: the capture now visibly shows the restored check mark and +the app exits successfully. This is a basic native indicator, not complete themed +form-control appearance or browser pixel parity. + +Hosted Closed checkbox verification: the Courtyard inspector exercise now finds +the compiled checkbox's rendered bounds, sends Foco pointer press/release at its +center, verifies the selected polyline's closed flag changed, and invokes platform +undo with exact drawing restoration. The run passed with GPU capture and clean +exit. This exercises host hit testing/activation, not physical mouse latency or +full application parity. + +Polyline geometry inspector: original Vertices, Closed, Length and conditional +Plan area rows instantiate through compiled templates. Closed binds native checked +state to an editable-selection undo transaction; length/area use the native path +and polygon calculations. A native keyboard test closes a 3–4–5 path, checks length +7 to 12 and area 6, then requires exact undo. Hosted pointer checkbox verification +and other remaining application behavior are still open. + +Native checkbox prerequisite: added checked/set_checked and checkbox focusability. +Pointer click activation and Space toggle checkedness before click listeners, roll +back when canceled, then emit input/change with removal/disposal guards. Tests +cover Space, cancellation, programmatic state, disabled controls and disposal in +input. Radio groups, labels, OS pointer verification and the polyline Closed +binding remain open; this is not complete form-control parity. + +Ellipse Major/Minor radius now use compiled coordinate fields and the existing +native conic-axis calculation. Editing normalizes/scales the selected axis while +preserving the other axis and writes both explicit axes, matching the original +application approach. Native inspector tests type a minor radius for a tilted +ellipse, verify axis direction/other-axis preservation and exact undo. Full hosted +conic interaction, other entity inspectors and application parity remain open. + +Post-inspector panning check: the current original Courtyard benchmark ran 360 +ticks with 265 entities and 30 text records, no geometry rebuilds and no compositor +skips. Of 361 Metal callbacks, 359 had positive presentation timestamps: 59.999700 +FPS, p95 16.666833 ms, maximum 16.666875 ms, no intervals over 25 ms. Two invalid +timestamps are excluded rather than inferred. Raw trace, source revisions and +summary are retained in performance/native-kestrel-pan-current.{json,jsonl}. +This is evidence for synthetic panning only, not physical input latency, continuous +OS resize performance or full browser parity. + +Arc Start/End angle rows now use compiled numeric fields with native degree/radian +conversion and undo. Circle Area uses the original radius-based formula and +three-decimal squared-unit display. Tests type 270 degrees into End angle, verify +the stored radians and exact undo, and verify radius-5 area text. Ellipse radii, +remaining inspector sections and hosted conic interaction verification remain open. + +Circle/arc Radius now uses the compiled coordinate row and native change handler. +The model requires a positive finite radius and editable single selection, derives +the previous conic X-axis magnitude, and scales explicit axes as the original app +does. Model tests cover rotated explicit axes, zero rejection and exact undo for +both entity types; native inspector regressions pass. Ellipse radii, arc angles, +area display and hosted radius interaction verification remain open. + +Conic center inspector: CIRCLE, ARC and ELLIPSE expose original Center X/Y/Z +fields through the shared compiled coordinate template. Native center edits +require finite values and an editable single selection. Tests instantiate each +entity's inspector, type Center X through text input, commit via Enter and require +exact undo restoration. Radius, axes, angles and area fields remain to be ported; +this does not complete conic inspector parity. + +Point geometry inspector: POINT Position X/Y/Z now reuse the compiled coordinate +template used by lines. Native position editing checks finite values and editable +single selection, and records undo transactions. A native document test types a +negative Z coordinate, commits through Enter and verifies exact undo restoration. +The complete native layer/inspector regression target passes. Other entity editors, +full application behavior and physical resize performance remain open. + +Hosted line edit: `--exercise-line-edit --capture` selects an original Courtyard +LINE through pointer events, enters an End X change through Foco text/Enter events, +checks native geometry, waits for a subsequent GPU image publication, and invokes +platform undo with exact drawing restoration. The run passed and captured GPU +serial 3 with exit status zero. Publication is not a pixel comparison or physical +presentation timestamp, so browser visual parity and 60fps gates remain open. + +Line geometry inspector: compiled section/coordinate templates now expose the +original six Start/End coordinates and calculated Length for a single LINE. +Native finite endpoint edits respect editable selection and use undo transactions. +The native document test types End X, commits with Enter, verifies changed geometry +and displayed length, and requires exact undo restoration. Missing endpoint arrays +are guarded; absent Z components display zero. Other entity geometry editors and +full browser interaction parity remain open. + +Inspector information: single selections now show the original Layer state row +(locked, visible/editable or hidden) and optional Group row, using a predefined +compiled read-only property template. Group names fall back to group IDs. +Lineweight display uses four decimal places with trailing zeros removed instead +of std::to_string's six fixed decimals. Native tests verify the visible and locked +labels, group display, zero formatting and the existing editing/undo behavior. + +Hosted text-commit verification: the inspector exercise now sends Foco +text_input_event for Lineweight and Name, commits each through Foco's Enter key +event, checks the selected entity's property, then sends platform-Z and requires +exact drawing JSON restoration. It passed in FocoKestrelPreview with a delivered +GPU frame and exit status zero. This covers host event forwarding; text selection +is set through the native API, so OS text selection and IME remain unverified. + +Native text commit correction: inspector number/name tests previously dispatched +change explicitly, masking that real text entry only emitted input. Native text +controls now track user edits and emit change on focus departure; single-line +inputs also commit on Enter. Unchanged edits and programmatic set_value do not +create a commit, and pending records are cleared on removal/disposal. Tests cover +deletion, textarea blur, repeated commits, and change handlers that remove the +control or dispose the document. Inspector tests now type through text_input and +commit via Enter/focus, then verify model updates and exact undo. Full input +validation, IME and original application parity remain separate open work. + +Inspector continuation: original Linetype and Lineweight rows and the single-object +Name row now instantiate from predefined compiled templates. Native edits apply +only to editable selected entities and create undo transactions. Native document +tests exercise keyboard selection of Center linetype, weight and name changes, +exact undo restoration, invalid values and locked-layer rejection. Color controls, +geometry fields, validation feedback and complete control behavior remain open; +this is not full inspector parity. + +Latest hosted verification: `--exercise-layer-edit --capture` selected Courtyard +geometry through the viewport, changed the selected object's layer using the +inspector select's Home key, and sent the platform undo shortcut through Foco. +The drawing JSON was restored exactly and the rebuilt inspector displayed the +original layer. The application captured a GPU frame and exited successfully. +Shared stylesheet, shared document and native layer regression tests also pass. +This verifies that interaction path only; remaining inspector fields, application +commands, full browser parity and continuous displayed resize cadence are open. + +### CSS architecture review + +Delivery decision: prioritize compiled HTML and predefined templates with +build-time CSS preparation and the existing native CSS runtime. The original-HTML +FocoKestrelPreview now defaults NATIVE_WEB_PREVIEW_SHARED_CSS to ON; existing CMake +caches retain their explicit selection. The typed backend remains available for +comparison and incremental optimization. This changes the preview delivery path, +not the claim of full Kestrel parity or CSS compliance. Runtime value/inline-style +interpretation remains and must be distinguished from stylesheet syntax parsing +at build time. No JavaScript or runtime HTML parsing is introduced. + +Audit remaining gaps as compiler handoff, shared CSS semantics, or host behavior. +Prioritize missing engine behavior and original application functionality before +eliminating textual CSS value interpretation. Fully typed CSS lowering is a +subsequent optimization; the earlier parser-free CSS gates below describe that +stricter backend, not a prerequisite for testing the shared-runtime application. + +The compiler audit currently reports 30 distinct unsupported source constructs, +not 30 isolated parser changes or a percentage of browser compatibility. Continue +using the original stylesheet as evidence, but separate compiler emission gaps +from missing native layout, paint and interaction behavior. + +The preferred direction is to reuse WebScene's existing Rust CSS parser and native +cascade for both parsed and compiled documents. Build-time preparation should +emit stylesheet data into generated C++ modules, consumed by the same native +engine. Do not expand a second implementation of CSS semantics as the long-term +architecture. The extracted prepared_stylesheet, stylesheet_owner and +native_style_session now connect to native_web through an explicitly selected +stylesheet resolver (see the integration checkpoint below). The default application +still uses typed rules; the shared adapter does not prove parser-free execution. Declaration values, +media conditions and functional selector arguments still contain text interpreted +by the shared machinery; emitting these records alone would not satisfy the +no-runtime-CSS-parsing requirement of the stricter typed backend. + +An embedded-CSS runtime-parser route is a proposed intermediate comparison mode, +not a change to the final acceptance contract. It can establish which original UI +features the shared engine actually renders before completing build-time lowering. +Keep HTML construction and dynamic templates compiled in every mode. The original +preview now selects prepared shared CSS by default; the separate typed sample +remains available. + +Next integration gates: + +1. Define the prepared-style handoff and connect native document mutation, focus, + hover, preferences, viewport changes and disposal to the shared style session. +2. Compare parsed preparation and generated preparation on identical native trees, + including dynamic updates; retain unsupported-feature diagnostics. +3. Complete typed value/selector/media preparation wherever shared execution still + reparses text, then verify the packaged binary's parser dependencies. +4. Address actual engine gaps once for both authoring paths, and test original + Kestrel behavior and presented frame performance separately from syntax coverage. + +WebScene owns compiler lowering, native style/cascade/layout/paint, animation and +DOM APIs. Foco supplies cursor/window/input, preference projection, compositor and +frame scheduling. Reuse native engine behavior where verified; accepted syntax +without observable behavior does not count as support. Emit typed expressions, +tracks, keyframes and paint records; no runtime CSS or HTML parsing. Keep generated +C++ modules and compiled template APIs. Native C++ remains the application model. + +## Dependency-ordered implementation batches + +1. **Typed values and paint data (P).** Extend the existing expression evaluator + to two-color sRGB mixing and color-valued functions in shadows/gradients. Compile + gradient stops and angles, preserving variable dependency recomputation. + Add dashed borders, inset shadows, outline and outline-offset to native style + writers and paint geometry. Define clipping, spread, negative offsets and + currentColor behavior; keep outlines outside layout sizing. Add brightness and + backdrop blur using existing renderer effects if available, otherwise extend + native scene/compositor effect records. Validate paint order, clipping, opacity + and resource disposal. Do not substitute solid fills or ignore effects. +2. **Selectors and generated boxes (S).** Extend compiled selectors to target + before/after/placeholder/backdrop style records. Compile content string values + (including empty strings), maintain originating-element specificity/inheritance + and pseudo-state updates. Generate before/after boxes through native engine + layout and paint, placeholder through native editable-control rendering, and + backdrop through dialog top-layer ownership. Check empty generated boxes, + positioning, hit testing, modal lifecycle and removal. +3. **Layout and text (L).** Add typed grid line/span placement including negative + end lines; resolve 1/-1 against explicit track count rather than hardcoded spans. + Bridge collapsed table borders and verify shared edge conflict resolution. + Implement anywhere wrapping and ellipsis in native shaping/layout/paint, covering + intrinsic widths, clipping, Unicode, resize and mutation. Implement font-synthesis + policy in shaping/font selection; none must disable synthetic faces. +4. **Interaction and control presentation (I).** Compile cursor keywords and expose + inherited resolved cursor to Foco pointer hit testing. Add selection policies, + touch-action gesture policy, vertical resize handles, scrollbar width/color, + accent-color and color-scheme. Implement or connect native control rendering and + event paths, keyboard accessibility, disabled states, pointer capture and cleanup. + Expose host preference/theme data without JS. Verify real host interaction as well + as native event contracts; storing unused style fields is insufficient. +5. **Conditions and animation (A).** Compile media conditions as typed predicates: + screen/print and prefers-reduced-motion. Screen is the normal window medium; + expose print context explicitly rather than deleting print rules. Compile + keyframes, shorthand timing/duration/iteration/fill and animation:none. Implement + transitions for fill and none with native frame-clock interpolation, variable + changes, cancellation and reduced-motion updates. Schedule via existing Foco + display driver; no independent timer. Inspect keyframe declarations and any + newly exposed unsupported contents recursively. +6. **Integrated verification (V).** Re-run the complete original stylesheet in + strict mode: zero omissions, no preview flag, and every listed construct below + has behavior evidence. Compile the original document and all predefined UI + templates; resolve additional diagnostics rather than hiding them. Rebuild + no-JS macOS application, verify linkage/assets, run original-browser versus + native layout and image comparisons at multiple window sizes, light/dark modes, + hover/focus/selection/dialog states and reduced-motion settings. Inspect real + cursor, wheel, resize and shutdown behavior. Keep performance measurements + separate from visual correctness and inspect frame presentation rather than + submission timing alone. + +## Per-construct ledger + +Every row starts open. Closure requires the batch implementation plus its concrete +regression and integrated evidence; update this ledger with evidence as work lands. + +| ID | Construct | Batch | Status | +|---|---|---|---| +| 01 | `#command-input::placeholder` | S | Open | +| 02 | `#ribbon-tab-list button.active:after` | S | Open | +| 03 | `.document-tab.active:after` | S | Open | +| 04 | `.panel-tabs button.active:after` | S | Open | +| 05 | `.progress-line:after` | S | Open | +| 06 | `.property-section-title:before` | S | Open | +| 07 | `@keyframes progress` | A | Open | +| 08 | `@keyframes toast-in` | A | Open | +| 09 | `@media (prefers-reduced-motion:reduce)` | A | Open | +| 10 | `@media print` | A | Open | +| 11 | `accent-color:var(--accent)` | I | Open | +| 12 | `animation:none` | A | Open | +| 13 | `animation:progress 1.2s infinite ease-in-out` | A | Open | +| 14 | `animation:toast-in .15s ease-out` | A | Open | +| 15 | `backdrop-filter:blur(3px)` | P | Open | +| 16 | `backdrop-filter:blur(9px)` | P | Open | +| 17 | `background:color-mix(in srgb,var(--active) 63%,var(--panel))` | P | Implemented; native paint checks pass; integrated comparison pending | +| 18 | `background:linear-gradient(125deg,var(--panel2),var(--panel))` | P | Implemented for source form; compiler/native/Foco tests pass; integration pending | +| 19 | `background:linear-gradient(145deg,var(--panel2),var(--panel))` | P | Implemented for source form; compiler/native/Foco tests pass; integration pending | +| 20 | `border-collapse:collapse` | L | Open | +| 21 | `border:1px dashed #65c5a4` | P | Implemented; compiler/native/Foco raster tests pass; integration pending | +| 22 | `border:2px dashed var(--accent)` | P | Implemented; compiler/native/Foco raster tests pass; integration pending | +| 23 | `box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 25%,transparent)` | P | Implemented; compiler/native paint tests pass; integration pending | +| 24 | `box-shadow:inset 0 -2px 0 var(--accent)` | P | Implemented; native command and Foco raster checks pass; integration pending | +| 25 | `box-shadow:inset 0 0 0 1px var(--accent-dim)` | P | Implemented; native command and Foco raster checks pass; integration pending | +| 26 | `box-shadow:inset 2px 0 0 var(--accent)` | P | Implemented; native command and Foco raster checks pass; integration pending | +| 27 | `color-scheme:dark` | I | Open | +| 28 | `color-scheme:light` | I | Open | +| 29 | `content:""` | S | Open | +| 30 | `content:"⌄"` | S | Open | +| 31 | `cursor:col-resize` | I | Open | +| 32 | `cursor:crosshair` | I | Open | +| 33 | `cursor:grabbing` | I | Open | +| 34 | `cursor:move` | I | Open | +| 35 | `cursor:not-allowed` | I | Open | +| 36 | `cursor:pointer` | I | Open | +| 37 | `cursor:row-resize` | I | Open | +| 38 | `dialog::backdrop` | S | Open | +| 39 | `filter:brightness(1.1)` | P | Open | +| 40 | `font-synthesis:none` | L | Open | +| 41 | `grid-column:1/-1` | L | Open | +| 42 | `outline-offset:-2px` | P | Implemented for source form; native geometry tests pass; full semantics/integration pending | +| 43 | `outline:2px solid var(--accent)` | P | Implemented for source form; native geometry tests pass; full semantics/integration pending | +| 44 | `outline:none` | P | Implemented for source form; native geometry tests pass; full semantics/integration pending | +| 45 | `overflow-wrap:anywhere` | L | Open | +| 46 | `resize:vertical` | I | Open | +| 47 | `scrollbar-color:var(--line) transparent` | I | Open | +| 48 | `scrollbar-width:none` | I | Open | +| 49 | `scrollbar-width:thin` | I | Open | +| 50 | `text-overflow:ellipsis` | L | Open | +| 51 | `touch-action:none` | I | Open | +| 52 | `transition:fill .15s` | A | Open | +| 53 | `transition:none` | A | Open | +| 54 | `user-select:none` | I | Open | +| 55 | `user-select:text` | I | Open | + +## Completion gates beyond this CSS batch + +Finishing these 55 usages does not itself finish the thread goal. After compiler +coverage and browser comparisons, complete Kestrel command/state/geometry/viewmodel +logic in C++, use compiled templates for all dynamic UI, embed resources, and prove +native WebGPU initialization without V8. Benchmark panning and live window resizing +at 60fps with presentation traces and no stretched stale-frame elastic effect. +Keep Foco's optimized display scheduling and GPU surface integration. Do not claim +full Kestrel parity from this CSS inventory or a static diagnostic preview. + +## Implementation evidence + +- Initial paint batch: native premultiplied-alpha sRGB mixing with typed variable + colors, default/complementary weights, normalization and alpha scaling when + weights sum below 100%. Compiler tests cover two variable colors and weight + grammar; native scene checks cover red/blue 25/75 and 25/25 mixtures, with class + removal restoring earlier paint. Zero-total weights are rejected. Nested + color-valued expression trees for gradients/shadows remain pending. +- Literal HSL/HSLA support was completed alongside the initial batch: hue units, + wrapping, percentage saturation/lightness, alpha and clamping, with native + paint coverage. This improves the shared color prerequisites but is not counted + as closure of additional baseline rows. +- The complete 55-row batch is not finished. Keep all subsequent batch gates + active; do not present these first changes as completion of the request. + +- Outline batch: supported source forms lower to typed native outline style; + signed offsets adjust painted bounds without changing layout. Native contracts + verify outside/inset geometry, none, and restoration. Rounded outline radii + incorporate signed offset; rounded pixel comparison, currentColor/default width, + broader shorthand ordering and pseudo-element outline propagation remain pending. +- Outline follow-through: typed shorthand evaluation now supports component + reordering, omitted color/width, thin/medium/thick and whole-value variables. + Duplicate literal components fail compilation; invalid substituted components + suppress the outline. Native currentColor resolves from the live foreground at + paint time. Compiler and native contracts pass, including mutation from explicit + color to default currentColor. Other outline styles, longhands and pseudo boxes + remain pending; original source-form rows retain their integration gate. +- Shadow host prerequisite: Foco's DOM packet renderer ignored existing kinds + 17/18 (outer shadows). Added ordered/background/foreground handling and Skia mask + blur. Raster tests verify both variants paint opaque centers and blurred exterior + alpha. The Native Web Foco configuration now builds/runs that host paint suite + as native_web_foco_paint; it passes. This fixes existing outer-shadow delivery; + inset shadow geometry/commands are still pending. A stale standalone Foco build + was not used for validation; tests ran against current Native Web dependencies. + +- Inset shadows: typed inset flag, padding-box clipping and inverse rounded-hole + shadow commands now connect to Foco's blur renderer. All three baseline inset + forms compile. Native contracts check background/clip/shadow/restore order; + Foco raster tests check hard inset edges, a transparent center, soft inward blur + and no paint outside the clip. Shadow command kinds 17/18 reserve flags bit 0 + for this inverse path; non-Foco consumers need equivalent support before claiming + embedding parity. Multiple shadows, arbitrary component ordering, elliptical + corner/border details and browser comparisons remain open integration work. +- Shadow shorthand follow-through: color and inset can precede or follow the + contiguous length group; omitted color and explicit currentColor resolve from + the live foreground. Duplicate colors/inset and interrupted length groups are + rejected, including after typed variable substitution. Compiler and native + mutation contracts pass; a reordered inset shadow paints blue after a foreground + change. Multiple shadows and non-pixel shadow lengths remain pending. + +- Dashed borders: typed per-side dash state, rounded uniform perimeter and mixed + straight-edge stroke commands connect to Foco dash path effects. Both baseline + dashed declarations compile; native mutation checks verify solid resets dash + state. Foco raster tests cover visible dash/gap runs for background/foreground + rounded and line commands. DOM kinds 40–43 are documented separately from canvas + opcodes. Compiler (103 tests), native contracts and Foco paint tests pass. + Mixed-width rounded corners, elliptical metadata, exact browser dash distribution + and non-Foco consumer support remain pending; no broad border parity claim. + +- Color-valued shadow expressions now reuse shared compiled color-mix lowering. + Generated code evaluates typed color variables and appends the resulting RGBA + token to the shadow operands; no CSS string reaches a runtime parser. The exact + baseline mix-shadow form and an inset two-color variant compile. Native mutation + coverage verifies a 25% variable red mix emits ff000040 in an inset shadow. + Compiler (104 tests) and native contracts pass. Nested custom-property function + trees beyond this direct shadow component remain pending. + +- Typed linear-gradient source forms now emit angle and RGBA stop records rather + than CSS strings. Native contracts verify angle, stop count and live custom-color + mutation; Foco raster tests verify direction, bounds and malformed-payload safety. + Compiler (105 tests), native contracts and Foco paint tests pass. Current lowering + supports equally spaced colors and degree angles; explicit stop positions, + side/corner directions and broader gradient syntax remain pending. This is not + full gradient parity or closure of the integrated comparison gate. + +## Parser reuse decision (user clarification) + +The compiler already links the existing Rust cssparser and selectors library +through the shared parser bridge. The Rust DeclarationParser adapter currently +returns declaration value strings, not a complete typed property-value model. +The 55 diagnostics must not be described as 55 missing Rust parser features. + +Before adding further property-specific compiler parsing, classify each gap as +compiler exposure, shared value interpretation, or native/host behavior. Extract +existing runtime property interpretation into a V8-independent shared layer where +possible; have the compiler serialize typed values/expressions from that layer. +Ordinary parsed WebScene content should use the same interpretation and native +style APIs. Keep parser code in build tools for native-only applications. + +Existing gradient handling illustrates the boundary: runtime cascade retains the +CSS image string and Foco's draw_dom_gradient interprets that string at paint time. +Reusing Rust syntax parsing alone cannot turn that path into parser-free compiled +paint. Move interpretation ahead of rendering and converge both producers on typed +paint records. Avoid growing a second independently maintained property grammar +in tooling/webscene-uic/main.cpp. Variable-dependent values must retain typed +expression structure, rather than freezing theme-dependent computed styles at build +time. Tests must compare parsed and compiled paths as well as native rendering. + +- Reuse audit: collapsed table borders currently suppress spacing in native layout, + but no shared-edge border conflict resolver was found in the native layout/scene + implementation. Row 20 remains open; exposing border_collapsed alone would not + satisfy its behavior gate. +- Shared shadow interpretation: extracted typed component validation and native + style application into webscene_shadow_value.h. Both compiled variable evaluation + and runtime CSS shadow tokenization now use that builder. This removes duplicate + ordering/default-color logic and gives runtime content the same inset/currentColor + semantics as compiled content. The runtime tokenizer remains separate; shared + typed property parsing is not complete. Multiple shadows remain unsupported. +- Updated original-stylesheet audit after typed gradients: 397 rules, 1475 + declarations, 43 distinct unsupported constructs (baseline 55). This measures + compiler acceptance only, not integrated visual parity or feature completion. + +## Delivery alternative under consideration + +Recommendation following the user's CSS-runtime question: retain compiled HTML +and predefined templates, C++ application code and embedded resources, but extract +and reuse WebScene's CSS runtime as the first delivery path. Parse bundled original +CSS at startup; do not add runtime HTML parsing or require V8. This deliberately +relaxes the original no-runtime-CSS-parser requirement and is a proposed change, +not a claim that the existing acceptance gate has already been met. + +First prove a V8-free CSS service against the same native document used by compiled +HTML. Preserve selectors, cascade, variables, media predicates, pseudo styles, +invalidation and animation scheduling. The existing cascade is largely native C++ +but lives as methods of the V8 runtime implementation and depends on its state. +Extraction is real engineering work; adding the Rust parser library alone is not +sufficient. Validate original Kestrel CSS without omission before extending the +application port. Shared native/Foco rendering gaps still require implementation. + +Later optimize by serializing the shared parser's stylesheet representation at +build time, retaining runtime cascade and dynamic values. This avoids maintaining +an independent CSS implementation and can ultimately remove startup parsing. +Full standards-compliant CSS compilation is not close merely because the +Kestrel-specific unsupported-construct count is falling. + +Shared-shadow validation: compiler/native contracts and the focused V8 runtime +scene test pass. The runtime test verifies both existing outer shadow geometry +and inset/currentColor paint. Its standalone harness needed an execute bootstrap +because evaluate alone does not activate native scene publication. Inline recascade +now preserves inset/currentColor flags, and shadow resets clear all shared fields. +The runtime test build used Inspector enabled; the Inspector-disabled build exposed +an existing unguarded call to cancel_detached_frame_context_tasks, still unresolved. + +- Reference-runtime build repair: navigation task cancellation is now compiled + regardless of Inspector support; only its Inspector notification is conditional. + The Inspector-disabled runtime and test executable build successfully. Focused + shared-shadow-values and iframe-replacement-layout tests both pass. This resolves + the build failure noted above and preserves a usable ordinary-runtime reference + for shared CSS extraction. It does not change the delivery profile decision. + +- CSS service extraction: stylesheet declarations, compiled selector structures, + immutable rule payloads, keyframe storage and movable cascade state now live in + webscene_css_state.h, independent of V8. The existing runtime uses aliases to + those shared types; its payload cache retains its existing ownership. The + compiler build includes the header to verify the V8-free tool boundary. This + does not yet switch compiler lowering to runtime cascade execution. Both builds, + compiler/native contracts, shared-shadow-values and iframe-dynamic-recascade + tests pass. Next extraction boundaries are selector matching, property application + and cascade/invalidation services, followed by a native-document integration test. + +- CSS service extraction: webscene_css_declarations.h now owns the Rust-backed + declaration parser and runtime declaration normalization. The V8 adapter calls + this service, retaining the legacy parser fallback. A separate native_web_css_service + executable links the Rust parser without V8 or the runtime engine and passes + custom-property case/empty values, escapes, important, nested functions, quoted + delimiters and malformed-declaration recovery checks. Its link dependencies and + undefined symbols contain no V8/runtime-engine dependency. Runtime shadow and + iframe dynamic-recascade checks pass after the extraction. This establishes a + reusable parser service, not yet a standalone cascade or a working Kestrel CSS + runtime; selector evaluation and cascade execution remain the next boundary. + +- Selector preparation extraction: webscene_css_selectors.h now owns the existing + identifier/escape handling, compound preparation and Servo-backed selector/list + preparation. The runtime delegates to it; its legacy selector fallback remains. + The V8-free CSS service test now links the selector bridge and verifies combinators, + pseudo-element metadata, escaped identifiers and malformed-selector rejection. + Runtime positional-selector-siblings, iframe-dynamic-recascade and shared-shadow-values + tests pass. This moves preparation, not DOM-dependent matching or cascade execution; + supported selector semantics are unchanged by this extraction. + +- Native selector matching extraction: attribute and nth-expression matching now + live in webscene_css_matching.h and are used by the existing runtime. V8-free + tests exercise attribute word/language matching, empty substring rejection, + mutation, signed An+B expressions and malformed expressions. Nth arithmetic uses + a 64-bit difference to avoid overflow for valid extreme offsets. Service tests + and runtime positional-selector-siblings/iframe-dynamic-recascade tests pass. + Full compound matching, document state, combinators and cascade execution still + require extraction; this does not claim new overall selector compliance. + +- Disabled-state selector extraction: the shared matcher now accepts a native + document to resolve disabled form controls through parent relationships. The + ordinary runtime delegates to the same function. V8-free service tests use native + DOM construction to check direct attributes, fieldset inheritance, first-legend + exemption, attribute removal and select/option inheritance. The service links + the native DOM library without V8. Service and runtime positional/iframe cascade + regressions pass. This preserves existing disabled semantics; full compound + matching and interaction-state dependencies are still not extracted. + +- Interaction selector boundary: hover/focus/focus-visible/focus-within now use a + native interaction_state record and shared document-aware matching. The runtime + passes its existing hovered/focused nodes and focus modality; no JS handle crosses + the matching interface. Native tests cover ancestor hover/focus-within, direct + focus, modality changes, text-control focus visibility and hover removal. Service + and runtime host-pointer-exit/positional/iframe cascade regressions pass. This + establishes an input-state boundary but does not yet provide full standalone + compound matching, a CSS cascade, or native-app interaction integration. + +- Inherited selector state: language/direction matching now uses shared native + document helpers. V8-free tests cover inherited language, case folding, nearer + overrides, explicit empty language, direction inheritance and default direction. + The runtime delegates to these helpers; service and runtime positional/iframe + cascade regressions pass. Existing behavior is preserved; broader language-range + support and automatic direction detection are not added by this extraction. + Full compound matching and cascade execution remain open. + +- Form/URL selector boundary: selected-option resolution and its traversal helpers + now live in webscene_native_form_state.h and serve both DOM properties and CSS. + Shared checked matching consumes live native checkbox/option state. Target + matching consumes a plain hash string; the V8 adapter still obtains the current + context's hash. Native service tests cover default/authored option selection, + live state overriding attributes, checkbox state and empty/matching URL targets. + Service and runtime pointer/positional/iframe cascade regressions pass. Compound + matching still contains recursive selector/cache dependencies and is not yet a + standalone service; no additional browser-compliance claim is made. + +- Combinator traversal extraction: native selector traversal now owns child, + descendant, adjacent-sibling and general-sibling walking. A compound predicate + is supplied explicitly; the runtime supplies its existing compound matcher. + Native service tests isolate traversal with a tag predicate, verifying positive + and negative relationships. Service and runtime positional/iframe/pointer tests + pass. These tests do not imply the standalone service can evaluate all compound + selectors yet; that predicate and cascade execution remain open. + +- Compound matcher extraction: webscene_css_compound.h now contains the existing + compound evaluation logic without V8 types. A host contract supplies document, + input state, target hash, class lookup, text-control classification and recursive + queries; the runtime delegates while keeping its current caches/query behavior. + Sibling benchmark counters retain their export access through shared storage. + A V8-free test host verifies combined class/combinator/focus/hover selectors, + disabled/target selectors and nested not/is/has cases. Service and runtime + positional/iframe/pointer/shadow checks pass. This preserves existing selector + limitations and is not full standards compliance. A production native query host + and cascade execution are still required before styling the compiled application. + +- Native query host: webscene_css_query.h supplies the shared compound/traversal + engine with native DOM, input IDs, URL hash and class lookup. It preserves query + scope through descendant traversal and caches prepared syntax, not match results. + Shared ownership pins syntax during recursive matching even if bounded-cache + eviction occurs. The service test now uses this host instead of its test adapter, + including a one-entry cache, scoped queries and class/focus mutation checks. + Text-control classification is shared with the runtime form helpers. Service and + runtime pointer/positional/iframe regressions pass. The host borrows its document + and is intended for its owning thread; its state must be updated by the app/host. + Stylesheet cascade/style application and app integration remain unfinished. + +- Cascade primitives: specificity/source-order sorting and root custom-property + rebuilding now use shared functions in webscene_css_rule_operations.h. The + runtime delegates without changing its root-variable policy. Native tests cover + specificity, source ties, important overrides, media exclusion and shadow scope. + Service and runtime iframe/shadow/positional regressions pass. Per-element + inheritance, substitution, declaration application and invalidation are still + required; these primitives do not constitute a standalone cascade. + +- Parsed CSS variable resolver extraction: webscene_css_variables.h now provides + the existing runtime substitution path to native callers. The runtime delegates + to it; compiled-only styles retain their typed evaluator. Native tests verify + ancestor/root lookup, nested fallback, repeated references and mutation; runtime + dimension-variable-compatibility, dimension-inheritance and iframe cascade tests + pass. This is behavior-preserving reuse, not full variable compliance: cycle + semantics, quote/token awareness and the fixed expansion bound remain limitations + of this existing resolver. Declaration application/cascade integration remains open. + +- Custom-property declaration application: inline seeding and stylesheet application + now share native helpers, preserving the runtime's existing inline/important + precedence. Native tests verify normal stylesheet declarations cannot replace + inline values, stylesheet important can replace normal inline, inline important + remains protected, and removing inline state allows later stylesheet values. + Service and runtime dimension-variable/inheritance/iframe regressions pass. + Ordinary style properties, whole-document cascade and app integration remain open. + +- Box-property application extraction: canonical property naming, existing value + component splitting, margin/padding application and per-side margin precedence + now live in webscene_css_box_values.h. All existing runtime callers delegate to + the shared implementation. Native tests cover shorthand expansion, automatic + margin flags, inline-side protection and important-side protection. Service and + runtime dimension-variable/inheritance/iframe regressions pass. This preserves + current parser/length/logical-side limitations; it does not claim full box-property + compliance. Other property families and full cascade orchestration remain open. + +- Inset/border application extraction: existing inset shorthand, reset-value + handling, border width/color/shorthand application and explicit-color recognition + now live in the shared box-value helpers. Native tests verify inset expansion, + automatic sides, border widths/colors, currentColor flags and removal. Service + and runtime tradingview-opacity-border, active-chart-pseudo-border and + logical-inset-transition tests pass. Existing border-style/logical-direction and + parsing limitations remain; this is shared behavior, not full border compliance. + Full declaration dispatch and cascade orchestration are still unfinished. + +- Corner-radius extraction: shared box-value helpers now apply circular and + elliptical radii to ordinary styles and pseudo styles. Native tests cover + horizontal/vertical shorthand expansion, individual corners and clearing a + pseudo's elliptical state. Service and runtime elliptical-corner-radii and + active-chart-pseudo-border tests pass. Parsing/logical-corner limitations are + unchanged; full declaration dispatch and cascade orchestration remain open. + +- Transition configuration extraction: component-list splitting, time conversion, + timing curves, property-list configuration and transition shorthand now use shared + native helpers. Runtime adapters delegate without changing frame scheduling. + Native tests cover property lists, durations, positive/negative delays, linear + timing and none resets. Service and runtime logical-inset-transition, + dimension-variable-compatibility and iframe cascade tests pass. Existing timing + grammar/property-coverage limitations remain; no standalone animation scheduler + or application cascade integration has been added. + +- Grid/animation value extraction: grid placement application and animation + shorthand now use shared native helpers. Tests preserve area/line metadata and + reset behavior; this does not fix the runtime's general grid placement limits. + A new progress-animation test exposed the old time detector accepting any token + ending in s. Shared time parsing now requires a finite numeric value and complete + s/ms unit, so progress remains an animation name. Tests cover signed/fractional/ + exponent times and malformed tokens. Native service and runtime compact grid, + symbol-search grid and logical-inset-transition tests pass. Full animation + playback and grid layout parity in the standalone app remain unverified. + +- Keyframe configuration extraction: runtime CSS now delegates opacity/rotation + stop selection, timing and animation signatures to the shared native helper. + The V8-free service test exercises actual native-document interpolation at + 500ms and cancellation after animation:none. The focused host-clock-keyframes + runtime regression passes, covering transitions, staggered opacity animation, + continuous rotation and offscreen frame-demand suppression. Its prerequisite + transition tests are retained because the existing tests share a clock timeline. + This preserves existing first-animation/property coverage limits; it does not + establish full animation compliance or Kestrel application parity. + +- Pseudo-element value extraction: generated content decoding and the existing + pseudo-element property dispatcher now live in webscene_css_pseudo_values.h. + Runtime cascade retains variable resolution and diagnostic reporting, while + native callers can apply resolved values without V8. Native tests cover escaped + content, display, padding, currentColor borders, elliptical radii, resets and + unsupported/partial diagnostics. Runtime active-chart-pseudo-border and + elliptical-corner-radii regressions pass. Existing content grammar, logical + direction, paint and typography limits remain; pseudo rule orchestration and + compiled application integration are not yet complete. + +- Stylesheet ingestion extraction: the existing Rust parser event adapter now + lives in webscene_css_stylesheet_sink.h, parameterized by native storage, + capability-inventory and diagnostic callbacks. Runtime parsing uses this same + adapter. The V8-free service test verifies ordinary rules, nested media ancestry, + important declarations, supported supports conditions, exclusion of container + rules, keyframe routing and source addresses. Runtime media-query-list, + host-clock-keyframes and iframe-dynamic-recascade regressions pass. Existing + at-rule limitations are deliberately retained; this adapter does not implement + cascade layers, container conditions or a complete native stylesheet owner. + +- Keyframe ingestion now calls shared native stop parsing and normalization + directly, removing another runtime-host dependency from the stylesheet adapter. + The V8-free service test parses a CSS keyframe block, stores its definition, + configures a native document and verifies opacity at a host-clock timestamp. + It also verifies turn-to-degree rotation and implicit initial rotation handling. + Existing first-declaration, name normalization and restricted property/grammar + behavior remain; this is reuse of current semantics, not complete CSS animations. + +- Rule payload preparation/storage extraction: runtime and native callers can now + share immutable selector/declaration/media payload construction and weak-cache + interning through webscene_css_rule_payload.h. The native service test checks + selector preparation, specificity, identity reuse, declaration isolation and + releasing/recreating unused payloads. Cache ownership and rule indexing remain + with their host; this does not yet supply the complete native stylesheet owner. + +- Resource resolution extraction: shared native URL and CSS url() rewriting + helpers now serve the existing runtime as well as native callers. Native tests + cover stylesheet-relative package-style URLs, root-relative resources, fragments, + data URLs and malformed input preservation. The runtime relative-stylesheet-resource + regression passes. This preserves existing URL/tokenization limitations and + supplies resolution only; embedding bytes, loading fonts/images, and complete + native stylesheet integration still require their own implementation/validation. + +- Rule preparation integration: the Servo runtime path and native stylesheet + ingestion test now share declaration URL resolution and selector-list expansion + through webscene_css_rule_preparation.h. Hosts retain diagnostics, resource + prefetch and rule ownership. Tests cover nested selector-list commas, resolved + URLs and invalid combinator rejection; parser error recovery remains intact. + Native service and runtime relative-resource, iframe cascade and positional + selector regressions pass. Whole-document native cascade remains unfinished. + +- Owned stylesheet preparation: webscene_css_stylesheet.h now assembles shared + parsing, rule preparation, immutable payloads and keyframes into an owned native + result with diagnostics. Media conditions remain attached for later live + matching; the caller supplies capability inventory. Native ownership and + diagnostics tests pass. Running native_web_css_service with the original + samples/NativeKestrel/reference/src/style.css prepares 407 selector-expanded + rules and 1520 declarations, with one retained keyframe definition. Its seven + diagnostics comprise five media conditions (the diagnostic command deliberately + supplies no media capabilities) and two partially supported keyframe blocks. + These syntax/preparation counts are not compiler support or visual-parity counts. + Unsupported animation properties, font registration, property application and + complete native document cascade remain open. This does not change the + compiled application's runtime parsing dependencies. + +- Media evaluation extraction: shared native environment-based media matching and + capability inventory now serve the runtime and native preparation diagnostic + command. Tests verify inclusive Kestrel width/height breakpoints, color scheme, + screen/print and comma alternatives; runtime media-query-list, reentrant query + and iframe cascade regressions pass. Original Kestrel CSS still prepares 407 + rules/1520 declarations; all five media conditions are recognized, leaving two + partial keyframe diagnostics in this preparation stage. Existing numeric-unit, + grammar and hard-coded input/reduced-motion preference limits are unchanged. + Prepared rules still need document ownership and resize-triggered cascade. + +- Prepared selector consumption: native document queries can match the immutable + selectors already stored in a prepared stylesheet, avoiding outer-selector + reparsing. The shared query implementation delegates to this path. Native tests + exercise authored stylesheet selectors against live class and hover changes and + verify pseudo-element rules do not accidentally match their originating DOM box. + The service test passes. Candidate indexing, pseudo rule routing and complete + document cascade application remain separate unfinished work. + +- Declaration precedence metadata extraction: the existing property bit groups + and alias/shorthand mapping now live in webscene_css_property_mask.h and all + runtime callers use that shared definition. Native tests cover combined groups, + aliases, custom-property exclusion and high-bit storage; runtime dimension, + inheritance, animation and iframe cascade regressions pass. Grouped-field + precedence limitations remain unchanged. This is a dependency for sharing the + full declaration dispatcher, not new property coverage or completed cascade. + +- Reset application extraction: existing non-important all:unset behavior now + lives in webscene_css_reset.h, including native defaults and preservation of + modeled inline/important values, custom properties and pseudo-element state. + Native tests verify protected width/color and custom/pseudo data survive while + ordinary height/opacity reset. The focused runtime all-unset regression passes. + Existing grouped-property/reset coverage limits remain; other reset keywords, + full declaration dispatch and application cascade integration are still open. + +- Box declaration application extraction: resolved dimension, inset, padding, + margin and gap application now uses webscene_css_box_application.h with an + owner-supplied precedence predicate. Native tests check inherited dimensions, + protected inline values, shorthand sides/gaps and reset behavior. Native service + and runtime dimension inheritance/variables, inset transition and iframe cascade + regressions pass. Existing parsing, logical-direction and grouped precedence + limitations are unchanged. Other declaration families and full cascade remain open. + +- Grid/flex application extraction: shared layout helpers now prepare the existing + grid tracks and apply grid/flex declarations, alignment and box sizing with the + owner-provided precedence predicate. Native layout tests verify fixed-plus-flexible + columns respond to 500px/700px viewports for both grid and flex. This preserves + existing repeat/named-line/dense-layout and shorthand limitations; it does not + claim complete grid/flex compatibility or presented-frame performance. Full + declaration dispatch and document cascade remain unfinished. + Runtime compact-go-to-grid, tradingview-symbol-search-grid, + dynamic-percentage-flex-list and dimension-inheritance regressions pass. + +- Structural declaration extraction: display parsing and display, table spacing/ + collapse/layout, positioning, float and z-index application now use shared native + helpers. Native layout tests verify display:none releases flex space, inherited + position/z-index values and table style metadata. Runtime property-table spacing, + compact table, fixed dialog and dimension-inheritance regressions pass. Existing + keyword/float/table coverage limitations remain; full cascade and application + integration are not complete. + +- Paint application extraction: shadow parsing and background color/image/position/ + size/repeat mutation now use shared native helpers. SVG loading remains a host + callback. Native tests cover inset/currentColor shadows, resource loading/failure, + gradient replacement and size resets. They exposed stale background-size second + components; clearing both components before parsing fixes updates from two values + to contain or one length. Native service and runtime shadow, relative resource, + SVG checker and active-chart pseudo-border regressions pass. Existing image, + gradient, shadow and tokenization limits remain; full cascade is unfinished. + +- Visibility/overflow extraction: native helpers now apply overflow, containment, + visibility, pointer-events and opacity, including computed overflow-axis coupling. + Native hit tests verify hidden/noninteractive elements are excluded; style tests + cover clipping/scroll flags and opacity clamping. Native service and runtime + overflow navigation, virtual-row scroll and pointer-exit regressions pass. + Existing inheritance/keyword coverage remains; this does not establish complete + scrolling behavior or presented-frame performance for Native Kestrel. + +- Typography extraction: font resolution/shorthand and text, SVG paint, cursor and + list-style application now use shared native helpers. Native tests verify + inherited percentage sizing, em spacing and unitless line-height preservation. + A numeric-weight shorthand test exposed 700 being read as font-size; the parser + now recognizes modeled 100–900 weights before locating size. Native service and + runtime dimension/font-relative, SVG typography and reset regressions pass. + Variable weights, additional font axes, shaping and other existing grammar limits + remain; this does not establish font-resource packaging or full app parity. + +- Unified resolved declaration application: borders/outlines, transforms and + animation declarations are shared, and webscene_css_application.h now composes + the native property handlers behind one resolved-declaration entry point used + by the runtime. A V8-free integration test prepares CSS, matches its selectors + against a C++-constructed document, applies declarations and verifies flex layout. + Native decoration/reset tests and runtime keyframes, border, dimension and iframe + cascade regressions pass. Variable substitution, rule ordering, invalidation, + pseudo routing and resource ownership remain the caller's responsibility; the + complete native document cascade and Kestrel integration are not finished. + +- Native declaration entry point now combines alias normalization, live custom + property application/substitution, invalid-variable rejection and resolved style + application. Runtime application delegates to it while retaining telemetry and + resource callbacks. Native tests verify variable updates, fallbacks, aliases, + important protection and resulting geometry. Runtime variable/inheritance, + iframe cascade and keyframe regressions pass. The ordinary path borrows authored + declarations; only aliases allocate normalized copies. Existing substitution and + precedence limitations remain; rule ordering/invalidation are not yet integrated. + +- Cascade reset extraction: runtime and native callers now share clearing of + previous stylesheet state through webscene_css_cascade_reset.h. Native tests + verify stale dimensions, visibility, custom/pseudo values and important flags + clear while an inline width survives and determines layout. Runtime dynamic + iframe cascade, active-class pseudo border, variable dimensions and all-unset + regressions pass. This preserves existing reset behavior/limitations; candidate + selection, ordering and the document cascade lifecycle are still unfinished. + +- Matched declaration ordering extraction: shared cascade application performs + custom-property passes before dependent values, then replays dependent inline + values and restores inline transitions with existing important guards. Native + tests verify a later matched rule supplies an earlier rule's variable and an + initially unresolved inline height updates, retaining its inline mask. Runtime + variable/inheritance, transition/keyframe and iframe cascade regressions pass. + Candidate selection, final font metrics, pseudo routing and document invalidation + still need integration; this is not a complete native stylesheet lifecycle. + +- Pseudo application extraction: pseudo selector suffix routing, variable-aware + pseudo property application and scrollbar declarations now use native helpers. + Tests cover generated text/color from custom properties and important scrollbar + visibility without hiding the originating element. Native service and runtime + active pseudo border, scrollbar drag/style and overflow navigation regressions + pass. Existing suffix grammar, unsupported scrollbar-corner behavior and pseudo + cascade limitations remain; native document lifecycle integration is unfinished. + +- Candidate matching extraction: shared matching now filters ordered candidate + indices by media and existing shadow-scope policy and separates ordinary/pseudo + rule targets. Native tests cover specificity ordering, media deactivation and + live class changes; runtime pseudo border, media, iframe cascade and positional + selector regressions pass. Results borrow their rule storage until application + completes. Candidate index construction, font finalization and invalidation still + need integration into a complete native document stylesheet owner. + +- Cascade finalization extraction: native callers and the existing runtime now + share relative line-height finalization against the winning font size and + computed layout-style comparison. A regression exposed missing pseudo padding + in the comparison; all four padding edges now participate so those changes + invalidate geometry while background-color-only changes remain paint-only. + Native CSS service tests and runtime paint-only cascade, variable dimensions, + dimension inheritance and active pseudo-border regressions pass. Both builds + are current. This does not change compiler support counts or introduce runtime + CSS parsing into compiled applications. Native stylesheet ownership, candidate + indexing and invalidation integration remain unfinished; full original Kestrel + parity and presented 60fps panning/resize remain unverified. + +- Selector index extraction: shared native index_selector now selects subject + ID/class/tag/attribute keys, focus/root buckets and fallback rules, and records + ancestor attribute dependencies. The ordinary runtime delegates this portion of + index construction to it. Native tests cover all buckets and distinguish ancestor + attributes from subject attributes; runtime positional selector, pseudo border, + iframe recascade and media-query regressions pass after rebuilding. Existing + selector scanning limitations are preserved. Hover/variable dependency indexing, + candidate collection and native document invalidation remain to be integrated; + this does not increase audited compiler coverage or prove Kestrel parity. + +- Candidate collection extraction: shared native collect_candidates now combines + fallback, tag, root alias, ID, attribute, focus and class rule buckets. Runtime + class lookup allocation policy and benchmark counters remain in its callback; + sorting/deduplication and full matching remain separate. Native service tests + cover combined buckets and repeated whitespace-separated classes. Rebuilt runtime + positional selector, active pseudo border, iframe recascade and media-query + regressions pass. This preserves existing selection policy; native stylesheet + ownership/invalidation and full Kestrel parity/performance remain unfinished. + +- Native prepared stylesheet ownership: stylesheet_owner now attaches/replaces + prepared author sheets in stable source order, removes them with index rebuild, + merges keyframe definitions, collects sorted unique candidates, and refreshes + media activation from an explicit environment. Prepared data types are separated + from the parser entry point; the owner performs no CSS text parsing. Native + tests pass for replacement order, removal/index compaction, repeated class keys, + viewport activation and unchanged activation. Original Kestrel preparation still + reports 407 selector-expanded rules, 1520 declarations and two partial keyframe + diagnostics; these are syntax counts, not visual parity. The owner is not yet + wired to a native document host. Recascade scheduling, interaction dependencies, + scoped sheets, resource registration and app integration remain outstanding. + +- Native per-node cascade integration: apply_native_cascade combines the prepared + stylesheet owner, indexed matching, reset, ordinary/inline declarations, font + finalization, pseudo/scrollbar rules, keyframe configuration and layout-versus- + paint invalidation. Callers provide root variables, interaction-aware query state, + resource loading and diagnostics, and must process parents before children. + Native service tests pass for sheet replacement changing width and removing + generated content, and removal clearing the previous stylesheet width. No V8 or + runtime HTML parsing is used. Automatic tree scheduling, root variable refresh, + scoped sheets, interaction invalidation and application hosting remain unfinished; + this test proves computed-style updates, not browser parity or frame performance. + +- Native document cascade pass: explicit full-document refresh rebuilds active root + variables and traverses the light DOM parent-before-child using an iterative + stack. Native tests pass for inherited variable updates, removed variables falling + back, and media activation changing computed width after a viewport update. + This is a correctness refresh path for host-scheduled changes, not a per-frame + operation. Automatic mutation hooks, selective invalidation, shadow scopes, + parser-free prepared pseudo matching, native app integration and presented-frame + performance remain open. No original Kestrel parity claim is made. + +- Prepared pseudo origin selectors: immutable rule payload preparation now compiles + the originating selector for pseudo-element rules. Native cascade matching uses + that representation directly instead of submitting the origin string to the + query parser. Existing runtime matching callbacks retain their host behavior. + Native cascade/pseudo tests and rebuilt runtime pseudo border, iframe recascade + and positional selector regressions pass. Nested functional selector queries + and generated stylesheet serialization still require work before claiming a + fully parser-free native CSS application. Full Kestrel parity remains unproven. + +- Native style session: a document-borrowing session now owns prepared sheets and + query state, coalesces explicit invalidations, and refreshes before host layout. + Sheet replacement/removal, viewport changes, focus/hover and target changes + schedule refresh; unchanged interaction/viewport inputs do not. DOM mutators + still must explicitly invalidate. Native tests pass for focus styling, class + mutation, repeated invalidation coalescing, no-op flush and removal cleanup. + This is not yet wired to the Foco sample or native DOM mutation hooks, and full + document refresh is not a suitable unconditional animation-frame operation. + Resource callbacks, selective invalidation, original Kestrel parity and 60fps + panning/resize verification remain outstanding. + +- Compiled Native Web host invalidation: inspection found every dirty canvas update + reran the entire compiled declaration cascade. document_state now separately + tracks style invalidation; canvas-only changes retain computed styles, while DOM, + attributes, rules, interaction and viewport changes still recascade. Layout and + scene construction remain unchanged. A declaration-count contract proves canvas + paint skips the cascade and attribute/resize updates execute it. Compiler and + contract suites pass. This applies to the current app host but does not yet wire + the prepared stylesheet session into it or prove 60fps presented performance. + +- Native canvas layout reuse: canvas drawing/clearing/external composition now + marks scene generation rather than global layout dirtiness. The compiled host + checks both scene generation and layout state, rebuilding display data while + retaining geometry for canvas-only changes. Style/viewport changes still mark + layout dirty. A public layout-pass counter supports performance diagnostics; + contracts verify paint/clear skip layout, paint produces a new scene revision, + and mutations/resize still run layout. Compiler and contract tests pass. This + removes measured unnecessary passes but does not establish presented 60fps or + complete original Kestrel behavior; Foco app-level profiling remains required. + +- Foco app validation after canvas reuse changes: rebuilt FocoKestrel in + artifacts/native-web-foco and ran --exercise-commands --capture. Process exited + zero after hosted line creation, undo and redo checks, with GPU serial=2. Viewed + /tmp/kestrel-canvas-reuse.png: native grid, box and created line are visible in + the simplified POC interface. This is not the original Kestrel UI and serial=2 + is not an FPS measurement. otool lists Dawn and system frameworks, no V8 dylib; + undefined-symbol scan found no V8/HTML/CSS parser matches (not a complete static + dependency audit). Full original UI, behavior, packaging and presented 60fps + panning/resize acceptance remain outstanding. + +- Compiler scrollbar-width support: auto/thin/none now emit typed native style + calls. Native overlay widths are 6px for auto and 4px for thin; none suppresses + rails while preserving scrolling. Compiler tests reject lengths/unknown/multiple + keywords, and contracts verify emitted rail geometry and hidden-bar scrolling. + Compiler and contract suites pass. Fresh original Kestrel audit: 397 rules, + 1475 declarations, **41 distinct unsupported constructs**, down from 43. + Inherited scrollbar-width, scrollbar-color, original app parity and performance + remain unfinished; this is not a full CSS Scrollbars conformance claim. + +- Compiler scrollbar-color support: two typed colors (including compiled var() + expressions), auto/initial and inherit/unset now emit native color updates. + Parent color inheritance is preserved without allocating auxiliary style storage + for unchanged defaults; invalid computed pairs restore inherited colors. + Compiler tests cover Kestrel's var(--line) transparent form and reject malformed + literal pairs; native paint contracts verify custom rail colors. Compiler and + contract suites pass. Fresh original audit: 397 rules, 1475 declarations, + **40 distinct unsupported constructs**. currentColor/color-mix forms, forced-color + handling and browser differential validation remain incomplete. No app parity + or presented-frame performance claim follows from the audit count. + +- Compiler full grid column span: grid-column:1/-1 and auto now emit a typed flag; + used and intrinsic grid layout consume it without parsing a placement string. + Contracts verify spanning three tracks and resetting to one track; compiler + tests cover whitespace and invalid line zero. Compiler/contracts and rebuilt + runtime compact-go-to/symbol-search grid regressions pass. Fresh original Kestrel + audit: 397 rules, 1475 declarations, **39 distinct unsupported constructs**. + General numeric/named grid lines and spans remain unsupported in this compiler + path. Full original app parity and 60fps acceptance remain unfinished. + +- Basic native cursors: compiler supports auto/default, pointer, text, crosshair + and horizontal/vertical resize keywords with inherit/unset. Native hit-based + cursor lookup walks ancestors; the Foco view maps supported keywords to host + cursor types on pointer input and scene refresh. Document inheritance/override + contracts, 109 compiler tests and FocoKestrel build pass. Diagnostic fixtures now + use unsupported grabbing instead of newly supported pointer. Fresh original CSS + audit: **35 distinct unsupported constructs**. Live OS cursor transitions after + deferred style changes remain to be verified; grabbing/move/not-allowed, custom + cursor images, full browser parity and performance remain open. Border-collapse + was rechecked and remains open because shared-edge conflict resolution is absent. + +- Cocoa interaction cursors: Foco bf7b065a adds grab/grabbing/not_allowed enum + values and native open-hand/closed-hand/operation-not-allowed NSCursor mappings. + Other platform backends explicitly retain arrow fallback. Native Web maps compiled + grab/grabbing/not-allowed keywords to those values; the FocoKestrel macOS build, + compiler suite and contracts pass. Diagnostic fixtures now use unsupported zoom-in. + Fresh original CSS audit: **33 distinct unsupported constructs**. These shapes + have not been visually verified. Cocoa currently applies cursor selection before + deferred host-frame style updates, so style-driven cursor changes can lag until + subsequent input; that ordering remains open along with move/custom-image cursors, + original Kestrel parity and measured 60fps panning/resize. + +- Cocoa deferred cursor ordering: Foco 0a4be755 separates cursor refresh from input + dispatch and refreshes again after host-frame callbacks/layout in both Cocoa + presentation paths. Post-frame refresh is restricted to the key window and + avoids redundant NSCursor updates when the effective kind is unchanged. + FocoKestrel rebuild and hosted line/undo/redo capture pass (exit zero, serial=2). + This smoke test does not observe OS cursor state; stationary-pointer visual + validation remains required. Compiler audit remains 33, and full original + Kestrel parity and presented 60fps panning/resize remain incomplete. + +- Text overflow prerequisite audit: native DOM emits text fragments with spacing + metadata, but Foco draw_dom_text ignored both spacing fields. Foco 636d421d now + applies finite letter/word spacing while preserving the existing unspaced font + run path. Raster tests pass for exact ASCII letter-gap and space advances. + This matches the native fallback scalar-spacing policy, not full grapheme-aware + shaping. Ellipsis and anywhere wrapping remain open: both fragment and fallback + text paint paths require coordinated overflow geometry, and the Foco renderer + still uses simple text runs rather than a shared full shaper. Compiler audit + remains 33; original app parity and 60fps acceptance remain unfinished. + +- Screen-target media types: the compiler now accepts screen/all/not print as + active and print/not screen/not all as inactive for the current native screen + application target. Inactive nested rules retain an impossible media interval; + nested screen rules cannot reactivate a print subtree. Compiler suite passes, + with diagnostic fixtures using unsupported speech instead of print. Fresh + original CSS audit: **32 distinct unsupported constructs**. This is not print + output support or general media-query grammar; print rendering would require + a distinct target/runtime mode. Reduced-motion preference and animations remain + open, as do original Kestrel parity and presented 60fps panning/resize. + +- Reduced-motion media conditions: generated rules now carry an optional boolean + preference, and document.set_reduced_motion schedules recascade when it changes. + Compiler supports reduce/no-preference in at-rules and stylesheet media attributes; + nested contradictory conditions remain inactive. Compiler and contract suites + pass for emitted conditions and runtime activation/deactivation. Fresh original + CSS audit: **31 distinct unsupported constructs**. Host OS preference propagation, + preference-change notification and compiled animation/transition behavior remain + open; accepting the condition does not implement the declarations inside it. + Original Kestrel parity and presented 60fps acceptance remain incomplete. + +- Foco reduced-motion propagation: native views read the attached visual-animation + service preference and refresh compiled styles when it changes. Foco 1519b2e0 + wakes host frames from scene_publisher::set_reduced_motion only on a changed + value; Cocoa's existing OS-settings subscriptions feed that service. New hosted + native_web_foco_motion test passes for wake-up, style activation/deactivation + and no-op repeated values. This verifies the service-to-view path without + changing the machine's accessibility settings. Compiled animations/transitions, + original Kestrel parity and presented 60fps validation remain unfinished; audit + remains 31 distinct unsupported constructs. + +- Native animation clock integration: compiled document cascades now notify the + existing native animation machines, and document.advance_animations feeds their + monotonic host clock. Native transition events dispatch with property/elapsed + metadata. Foco views request host frames while animations remain active and + stop afterward. Native C++ style authoring exposes a linear opacity transition; + document tests verify start/midpoint/completion and transitionend, while hosted + tests verify frame demand ends at completion. Compiler suite also passes. + Compiler transition/keyframe syntax, richer timings, cancellation/disposal edge + cases and visual animation parity remain open. Audit stays at 31; this is clock + plumbing, not proof of Kestrel animation or presented 60fps behavior. + +- Compiled opacity transitions: shorthand supports opacity, validated duration and + optional delay, named easing and none, emitted as typed C++ timing data. A new + generated C++ module test verifies delayed start, completion and cancellation. + Native opacity transitions now cancel on transition-property:none even when the + target is unchanged. Queued events retain frame demand after cancellation; + hosted tests verify delivery and return to idle. Compiler/contracts/generated + transition tests, runtime host-clock regression and hosted motion tests pass. + Fresh original CSS audit: **30 distinct unsupported constructs**. Multiple + properties, fill transitions, cubic/steps timing, compiled keyframes and broader + cancellation semantics remain unfinished. No full parity or 60fps claim. + +- Animation callback disposal: native documents expose disposal state and clear + queued transition events and scene output during disposal. Foco drops retained + composition packets and GPU ownership, avoids advancing disposed documents and + returns to idle. Generated transition tests verify target removal suppresses + later queued events; hosted motion tests dispose from transitionend and verify + no retained stream or frame demand. Native contracts, compiler, transitions and + hosted motion tests pass. This does not establish general callback-disposal + safety for every input path, original Kestrel parity or presented 60fps. + +- Shared stylesheet document handoff: added an owned stylesheet_resolver seam and + separate opt-in webscene_native_web_shared_css target. The adapter accepts + prepared_stylesheet records, projects viewport/hover/focus/reduced-motion state + and runs the existing native cascade on document invalidation. It retains + preparation/application diagnostics and is destroyed before native tree cleanup. + Mixing this backend with typed generated rules throws rather than silently + discarding one source of styling. Replacing the resolver invalidates styles. + A generated C++ HTML module and predefined row template now exercise this path: + initial layout, hover, class/text updates, focus, responsive media, reduced + motion, insertion/removal, replacement and disposal pass. Canvas-only drawing + retains the layout-pass count. Six tests pass: shared styles, native CSS service, + module smoke, transitions, contracts and compiler. This comparison test prepares + CSS at runtime; it never parses HTML at runtime. The default app remains on the + typed backend. Shared-engine SVG resource loading, color preference projection, + remaining interaction states, typed prepared values and actual Kestrel/Foco + integration remain unfinished. No original-app parity or 60fps claim. + +- Build-time shared CSS preparation: webscene-uic --prepare-css input.css + output.cppm --module module.name now emits a C++ module whose compiled_css::build + returns prepared_stylesheet data. It uses the existing Rust parser and emits + prepared selector compounds/pseudo origins, declarations, media conditions, + keyframes and diagnostics. Output preserves rule order and sorts keyframe names + for deterministic generation. CMake exposes webscene_prepare_css_module. + Parsed and generated preparation run through identical compiled-HTML mutation, + focus/hover, resizing, preference and template tests. Round-trip assertions cover + selector fields, escaping, declarations, keyframes and diagnostics; compiler + tests cover deterministic output, invalid module names and input overwrite + rejection. Shared style, CSS service and compiler suites pass. The unchanged + original Kestrel stylesheet produces a 348,956-byte module that Clang successfully + precompiles; its two partial-keyframe diagnostics remain visible. This emission + does not validate every property's rendering semantics. Textual values, media + and functional selector arguments still require shared-engine interpretation, + so this is build-time stylesheet parsing, not the final parser-free backend. + The packaged Kestrel app has not switched to this path; parity, resources and + presented 60fps remain unfinished. + +- HTML compiler shared-backend selection: --css-backend shared now prepares linked + and embedded stylesheets into the generated HTML module, preserving stylesheet + order, source addresses, link dependencies and media attributes. Generated build + installs the optional shared resolver and accepts a diagnostic report. Inline + styles on the document root, body, elements and predefined templates are kept + as authored attributes in this transitional backend. The shared native cascade + now has an opt-in attribute synchronization path, including inline custom values, + priority and style removal; the existing V8-style path remains the default for + other session callers. Typed documents continue to reject textual style writes. + Tests verify linked/embedded/inline interaction, responsive template dimensions, + inherited custom-value updates, attribute removal and important precedence. + Shared document/style, CSS service, contracts and compiler suites pass, including + backend validation and linked dependency emission. Kestrel's original index.html + generates and Clang-precompiles with --css-backend shared --preview; preview HTML + warnings and script omission remain, so this is not a complete original app. + No default application backend changed. Runtime inline/value interpretation, + resource integration, actual Foco/Kestrel integration, parity and presented 60fps + remain unfinished. + +- Foco shared-CSS preview integration: NATIVE_WEB_PREVIEW_SHARED_CSS (default OFF) + selects generated shared styles for the original Kestrel document and ribbon + templates, links the separate shared adapter and reports native CSS limitations. + Canvas percentage sizing remains native application logic. Added --capture for + the GPU preview, requiring a delivered GPU image and shutting down after capture. + Built the opt-in FocoKestrelPreview and ran it successfully: compositor capture + /tmp/kestrel-shared-css-preview.png, GPU serial 1, clean exit. Inspected the image: + original shell, ribbon icons, sidebars, command dock and GPU grid/demo box render. + Layer/property populations and app behavior are still incomplete. Layout dump + at 1280x800 and 1280x1000 shows the workbench growing from 463 to 663 pixels while + fixed top/bottom regions retain size; this is layout evidence, not smooth live + resize evidence. Input-coalescing check passes. Runtime diagnostics still include + unsupported backdrop-filter, overflow-wrap, scrollbar-color/width, stroke-width, + text-overflow, touch-action and user-select, plus partial features. No stylesheet + source modifications or runtime HTML parsing were introduced. The production + sample remains typed and this preview still uses shared value interpretation. + Full Kestrel logic, resources, browser parity and presented 60fps remain open. + +- Shared CSS standard scrollbars: connected scrollbar-width auto/thin/none and + scrollbar-color explicit color pairs/auto/inheritance to existing native overlay + geometry. Added independent priority masks and parent color inheritance during + cascade reset. Values validate before updating priority state. Parsed and + generated stylesheet integration tests verify four-pixel blue rails inherited + from a parent, author-important versus inline-normal width, hidden rails with + retained scrolling, default colors, inline-important six-pixel rails, and style + removal restoring stylesheet values. Shared style/document, CSS service and + compiler suites pass; rebuilt reference runtime and scrollbar-style-drag passes. + This addresses two diagnostics from the shared preview; the packaged preview + has not been rebuilt for this checkpoint. CurrentColor/extended color functions, + forced-color behavior and full interaction with vendor scrollbar pseudo styling + are not established by these tests. Original-app parity and presented 60fps + remain unfinished. + +- Shared CSS SVG stroke width: connected stroke-width to the existing SVG + serialization field, with its own precedence mask and reset on recascade. + Nonnegative numbers, px and percentage tokens are accepted; initial and explicit + inheritance resolve before projection. Validation precedes priority updates so + invalid important widths cannot block valid inline values. Parsed/generated + stylesheet tests verify an authored presentation width is overridden by CSS, + class removal restores it, explicit inheritance uses the ancestor width, and an + invalid important declaration leaves a valid inline width effective. Shared + style/document, CSS service and compiler suites pass. Evidence covers emitted + SVG data; no new Foco pixel comparison or packaged preview capture was made. + Font-relative units, full SVG styling parity, full Kestrel behavior and presented + 60fps remain unverified or unfinished. + +- SVG paint recascade: reproduced stale fill/stroke after removing an icon class + in both parsed/generated shared stylesheet tests. Cascade reset now clears + non-inline SVG paint overrides so authored presentation attributes become + effective again. Tests cover class removal, inline paint taking precedence, + inline paint surviving class changes, and removing the inline attribute. + Shared style/document, CSS service and compiler suites pass. Rebuilt reference + runtime; tradingview-svg-checker and canvas-svg-image regressions pass. This is + live scene-data update evidence, not a new Foco pixel comparison. Full original + Kestrel behavior and presented 60fps remain unfinished. + +- Native original layer panel: added four predefined layer-row templates from + pinned upstream app.js and UI.icon geometry (visible/hidden, locked/unlocked), + retaining original structure/classes and adding data-ref binding metadata. + New C++ module kestrel.layer_panel binds the native drawing's layers, colors, + entity counts, current selection, visibility/lock icons and accessible labels. + It handles current-layer clicks, transactional visibility/locking, row cleanup, + explorer badges and summary fields. The shared/GPU preview mounts it and marks + GPU content dirty after changes. Native layer tests pass for toggles without + accidental row selection, current-layer changes, lock undo, repeated refresh and + obsolete-node removal. Rebuilt and captured Foco preview successfully at + /tmp/kestrel-native-layers.png (GPU serial 1, clean exit), then inspected the image: + populated original layer rows, current highlight, icons, counts and summary are + visible alongside the GPU demo. No runtime HTML parsing or JavaScript was added. + Filtering, Shift-click selection, ribbon synchronization, object/property panels, + complete app behavior and presented 60fps remain unfinished. The demo geometry + is still a box, not the original full browser demonstration document. + +- Native modifier propagation and layer selection: native events now carry Shift, + Control, Alt and Meta state; Foco pointer/wheel routing preserves the host flags, + including the synthesized click on release. Shift-clicking an original layer row + replaces selection with visible entities on that layer without changing the + current layer, matching the pinned upstream explorer handler. Tests cover hidden + entities/layers, selection replacement and current-layer preservation. Hosted + motion/input tests verify all four flags on pointerdown, click and wheel; layer, + native contract, transition and compiler suites pass. This verifies injected Foco + input events, not a physical keyboard session. Keyboard-generated click modifier + coverage and broader keyboard input remain separate work; full app parity and + presented 60fps remain unfinished. + +- Keyboard modifier consistency: added a modifier-aware native key overload while + retaining the existing bool-Shift API. Foco forwards all four modifiers for + Enter/Space activation, and synthesized clicks carry them to native handlers. + Hosted tests verify modifier-preserving activation and document disposal from a + focus callback during Tab navigation. The host now checks disposal before + querying final focus. Native contracts, transitions, layer selection and compiler + suites pass alongside hosted motion/input tests. This does not implement general + text editing, shortcuts or IME; full app parity and presented 60fps remain open. + +- Native committed text: reused form-control value/selection/caret storage and + extracted authored-value initialization for both the existing runtime and native + documents. Added live value/set_value APIs, focus for text controls, committed + text insertion with beforeinput cancellation and input data/type metadata, and + Foco text_input_event forwarding. Read-only controls reject edits; hidden inputs + do not become focusable via tabindex. Untouched defaults follow value attributes + and textarea child updates, while dirty live values remain independent. Tests + cover Unicode text, cancellation, read-only state, default/live value separation, + textarea newline defaults, removal/disposal during beforeinput and hosted text + delivery. Native text/contracts/shared-document/compiler and hosted input tests + pass; rebuilt runtime native-text-input and textarea-value-lifecycle regressions + pass. No runtime HTML parsing was added. This is committed-text groundwork: + deletion/navigation, selection APIs, clipboard, input-type sanitization, caret + blinking and IME composition remain incomplete, as do full Kestrel and 60fps. + +- Native text deletion and selection: shared UTF-8 boundary helpers now serve the + existing runtime and native Backspace/Delete path. Added explicit selection + get/set APIs using UTF-8 byte offsets, rejecting offsets inside a scalar. + Deletion emits cancellable beforeinput and input metadata, rechecks target + lifetime/read-only/inert state after callbacks, and updates the live caret. + Foco forwards Backspace/Delete. Tests verify emoji/accent deletion, forward and + selected-range deletion, no-op boundaries, invalid offsets, cancellation, + read-only controls, replacement of selected text, and hosted keyboard delivery. + Native text/contracts/compiler and hosted input tests pass; rebuilt runtime + native-text-input regression passes. This is scalar-safe, not full grapheme or + word editing. Modifier-based deletion, caret navigation, clipboard, IME, full + application parity and presented 60fps remain unfinished. + +- Native layer filtering: the original explorer-search input now filters native + rows through input events. A persistent filter subscription survives row refresh; + the original empty-state markup is a predefined compiled template. macOS uses + CoreFoundation Unicode lowercase; the additional-platform fallback is explicitly + ASCII-only. Tests pass for matching, empty-state scene text, restored lists, + accented names on macOS, retained focus and no drawing/GPU change notification. + Built and ran --exercise-layer-filter --capture successfully; inspected + /tmp/kestrel-native-filter.png, showing a-wall in the native field and only A-WALL + in the original panel (GPU serial 1, clean exit). This uses injected Foco committed + text, not a physical keyboard session. The capture also exposes a form-rendering + gap after value initialization: input[type=color] paints its hex value as text. + Correct non-text control rendering next; this is not a full app-parity result. + Ribbon/object/property integration, broader text editing and presented 60fps + remain unfinished. + +- Native color-input painting: the shared native scene now paints input[type=color] + as an inset swatch instead of exposing the live hexadecimal value as text. Native + set_value updates repaint the swatch; malformed simple color values paint black. + The native text-input test checks authored mixed-case hex, value changes, fallback, + swatch dimensions and absence of text/caret commands. Rebuilt native_web_text and + its CTest passes. This is painting support only: picker activation, full input-type + value sanitization and browser-specific color-control appearance remain unfinished. + +- Original Objects explorer: extended the native explorer module with tab handlers, + original object-row templates and all twelve original entity icon variants copied + from the pinned UI source. C++ now supplies names/type labels, layer names, ID + suffixes, selected classes, the original combined search fields and a 500-row cap. + Click replaces selection; Shift-click toggles membership. Template construction + performs no runtime HTML parsing; model text is assigned through native APIs. + Native explorer tests pass for switching tabs, selection toggles, layer-name + filtering, empty matches and the cap message. Large-number locale formatting, + inspector/ribbon synchronization and full original model/application integration + remain unfinished; these tests do not establish visual parity or presented FPS. + The FocoKestrelPreview application also rebuilds and links successfully with the + updated templates and native explorer module; interactive capture is pending. + +- Hosted object-selection capture: added --exercise-objects to the diagnostic + Foco preview. It activates the original Objects tab, selects the generated row + through native dispatch and asserts the drawing selection and active row class. + Rebuilt and ran with --capture /tmp/kestrel-native-objects.png; clean exit and + GPU serial 1. Inspected capture: Box icon/name/A-WALL/suffix, active Objects tab, + highlighted row, summary selected=1 and highlighted GPU box are present. The + prior color swatch fix is visible too. This uses synthetic document events, + not a physical pointer test or presented-frame benchmark. Empty search input + still omits placeholder painting, the inspector is empty and renderer status + remains the original startup text; broader application parity is unfinished. + +- Native placeholder painting: eligible empty input/textarea controls now emit + their authored placeholder through the native text scene, while keeping the + live value and caret calculations independent. Rebuilt native_web_text; CTest + passes focused/unfocused display, typing suppression, clearing restoration, + attribute replacement/removal and exclusion for range controls. This closes the + missing text seen in the explorer capture, but does not implement ::placeholder + styling, placeholder-specific line handling, or case-insensitive input types; + current painting inherits the field text style. Visual recapture remains pending. + +- Hosted panning publication probe: FocoKestrelPreview --benchmark-pan drives + camera motion for 360 host ticks and reports publication count, elapsed time, + CPU tick cost and native geometry rebuild count. Rebuilt app and ran successfully: + 360 images / 5.98349 seconds = 60.1655 images/second; mean tick 0.495921 ms, + maximum 0.770667 ms, zero scene rebuilds during motion. Log: + /tmp/kestrel-pan-pipeline.log. This is a single small demo-box run with synthetic + camera movement, not physical pointer latency, display presentation timestamps, + full Kestrel model throughput or live-resize validation. It establishes that + this preview's single-pending-snapshot pipeline can sustain 60Hz publication. + +- Larger hosted panning workload: --benchmark-pan-large populates 1,000 native + mesh entities, then runs the same 360-tick camera/publication probe. Rebuilt + FocoKestrelPreview and ran successfully: 360 images in 5.9784 seconds (60.2168/s), + mean CPU tick 0.386052 ms, maximum 0.779708 ms and zero geometry rebuilds. + /tmp/kestrel-pan-large.log contains the result. This supports cached-scene + panning scalability for this synthetic workload, not full original Kestrel + geometry coverage or display-presented FPS. Single-run timing differences + from the one-box run are not evidence of a performance improvement. + +- Compositor counter probe: panning benchmarks now sample the view publisher's + compositor diagnostics before/after motion, printing successful backend + presentations, skipped attempts and occlusion separately from GPU publications. + Source inspection shows presented_frame_count increments after backend success + in compositor-tick.cpp, not on physical display timestamps. Rebuilt and ran + --benchmark-pan-large: 360 publications / 5.97845 seconds, mean CPU tick + 0.506081 ms, maximum 0.844125 ms, zero scene rebuilds. Diagnostics report available + but presented=0, skipped=0, occluded=0. Log /tmp/kestrel-pan-compositor.log. + This is an unresolved diagnostic-path mismatch, NOT evidence of zero displayed + frames or proof of 60 displayed FPS. Trace the active platform presentation path + and counter ownership before relying on these diagnostics for acceptance. + +- Direct Metal presentation evidence: discovered existing Cocoa Graphite host + trace_metal_presentation, enabled by FOCO_PRESENT_TRACE_JSONL. It attaches an + addPresentedHandler to CAMetalDrawable and records presentedTime. Ran the + 1,000-entity pan probe with trace /tmp/kestrel-metal-present.jsonl and log + /tmp/kestrel-metal-pan.log. GPU publication remained 360 / 5.97837 seconds, but + trace contains exactly one callback with presentedTime=0 (no valid display + timestamps). Consequently no displayed FPS can be calculated. Next investigate + active Cocoa host presentation scheduling/invalidation and drawable delivery; + do not infer successful on-screen animation from GPU publications or forced + compositor captures. Existing generic presentation counters also stayed zero. + +- Host callback change reporting fix: preview_window::advance_host_frame no longer + unconditionally returns false after invoking the native GPU callback; it reports + has_pending_scene_changes(), allowing Foco's host_changed commit path to publish + the updated subtree. Rebuilt and repeated the traced 1,000-entity benchmark. + GPU publications: 360 / 5.98299 seconds (60.1706/s); compositor successful + presentations: 179 (~29.9181/s). Metal trace has 180 callbacks, 177 valid positive + presentedTime values; valid interval FPS 29.99985, median 33.33350 ms, + p95 33.333583 ms, maximum 33.333625 ms. Logs: + /tmp/kestrel-host-change.log and /tmp/kestrel-host-change-present.jsonl. + This fixes missing presentation caused by false host-change reporting and exposes + a real half-rate presentation issue. Actual 60fps acceptance still FAILS; + investigate scheduling/commit-to-display latency rather than claiming publication + throughput as displayed FPS. No debugger tools were available; used controlled + before/after runtime traces instead. + +- Half-rate localization: pan probes now also sample scene_publisher commit, + publication and no-op counters. Rebuilt and ran the traced 1,000-entity workload: + 359 GPU images / 5.98297 seconds, 358 scene commits and 358 publications, + zero no-op commits, but only 178 compositor presentations. Logs: + /tmp/kestrel-scene-publish.log and /tmp/kestrel-scene-publish-present.jsonl. + This localizes the half-rate loss AFTER native/Foco scene publication. Next + inspect compositor scheduling and drawable presentation, rather than changing + native geometry caching or assuming document invalidation still loses half + the updates. Actual displayed 60fps remains unachieved. + +- Half-rate CPU timing investigation: temporary timing around the active Cocoa + presentation worker's compositor_->tick localized an over-budget render call. + 1,000-entity run: 180 successful ticks, median 20.1494 ms, p95 21.1624 ms, + max 59.1078 ms (includes startup); 181 non-rendering ticks, median 2.6968 ms, + p95 3.3933 ms. GPU publications 360, scene publications 359, compositor + presentations 179. Log /tmp/present-cpu.log. Temporary host instrumentation + removed after measurement (built executable still includes the probe until + next rebuild). Next profile phases inside render: drawable acquisition, + painter, GPU waits/submission. Do not assume this is an explicit 30Hz throttle; + successful calls exceed the 16.7ms frame budget. + +- Render-phase and backing investigation: existing FOCO_RESIZE_TRACE_JSON spans + show median ensure-backing 16.502 ms, paint-scene 2.297 ms, snap-recording + 2.016 ms; drawable acquisition effectively zero. Log + /tmp/kestrel-render-phases.log. Temporary backing-allocation logging then found + 180 allocations, ALL starting with no texture, dimensions 0x0 and scale 0, + allocating the same 2560x1600 backing at scale 2. Log + /tmp/kestrel-backing-probe.log. Thus stable-window panning is repeatedly losing + the retained backing, not resizing between different dimensions. Trace reset/ + recovery paths (including renderer status handling) next. Temporary logging + removed from Foco source; last-built binary retains it until rebuild. This is + stronger evidence than the earlier scheduler hypothesis; do not change frame + cadence to hide backing recreation. Displayed 60fps remains unmet. + +- Recovery trigger found: logs contain semantic replay skipped: Graphite semantic + image resource is unavailable. Cocoa mapped ALL non-presented painter statuses + to device_lost, forcing recovery/backing destruction. A working-tree diagnostic + change in Foco cocoa_graphite_host.mm preserves render_status. Rebuilt/run: + 359 GPU images, 358 scene publications, ZERO presentations and 358 skipped + attempts. /tmp/kestrel-preserve-skip.log. Thus device recovery masked a persistent + semantic image resolution failure; preserving status alone is not a working + fix. Foco change intentionally uncommitted pending resource-resolution fix. + Next inspect skia_graphite_renderer::draw_image images_ and command-surface + fallback, which return unavailable for the updated native GPU packet resource. + +- Semantic resource narrowing: temporary logging in update_command_surface finds + packet compilation failures (40,449-byte packets, zero GPU images), not failed + Metal imports. There are 64,261 such attempts in /tmp/kestrel-resource-probe.log + during one 360-tick run, suggesting repeated scans of accumulated resources. + Do not assume attachment loss is proven: failing packets may include stale + resources, and current draw_image's failing ID must be correlated with its + resource attachment/generation. Next inspect scene resource attachment retention + and cache population. Temporary renderer logging removed; Foco's uncommitted + render-status preservation experiment remains. Rendering still incomplete. + +- Root cause fixed in Foco: single-leaf publication append_resource copied bytes + but omitted resource_attachments, unlike the general publication paths. It now + retains attachment ID/generation/value. Cocoa also preserves painter skipped + status instead of falsely triggering device recovery. Rebuilt/reran the traced + 1,000-entity native pan benchmark: 360 GPU publications, 359 scene publications, + 359 compositor presentations, zero skips. Metal trace contains 357 positive + presentation timestamps: 59.999762 FPS, median 16.666750 ms, p95 16.666792 ms, + max 16.666875 ms. /tmp/kestrel-leaf-fixed.log and + /tmp/kestrel-leaf-fixed.jsonl. This is actual presentation evidence for the + synthetic panning workload; physical input latency, live resize, original model + and full Kestrel parity remain incomplete. Add focused leaf-attachment lifetime + regression coverage next, beyond this successful hosted reproduction. + +- Native/Foco attachment regression: native_web_foco_motion now publishes four + successive GPU attachment generations through a native document canvas. It + verifies the single-leaf fast path (publisher_visit_count==1) after initial + publication, applies each mailbox diff to a retained scene, acknowledges and + releases the lease, then verifies exact attachment identity and continued + ownership. Rebuilt target and CTest passes. This guards the actual attachment + omission behind the panning failure; it does not exercise Metal imports or + substitute for the separately recorded 60fps presentation trace. + +- Native GPU resize validity: view packet generation now suppresses the GPU draw + command when the image's logical allocation dimensions differ from the current + canvas dimensions (using the host's integer sizing convention). Previously it + stretched the old image into the new bounds. Matching content restores drawing. + Native Foco regression verifies matching image -> resize suppression -> new + matching image; rebuilt native_web_foco_motion and CTest passes. This is a + correctness guard, not smooth-resize completion: DOM/background can remain + briefly visible without GPU content while replacement is pending. Next ensure + correctly sized content arrives on resize presentation deadlines; live 60fps + resize and no blank intervals still require measurement/integration work. + +- Same-tick resize submission investigation: WebScene snapshots already expose + resolve_with_gpu_waits, but native Foco make_gpu_image explicitly rejects + requires_producer_wait and omits dependency_count/get_metal_event callbacks. + Experiment using immediate GPU-wait resolution aborts with Native frame + requires a completed GPU image (/tmp/kestrel-gpu-waits.log). Reverted viewport/ + preview experiment, retaining completed-image behavior in source. Last-built + preview binary contains the experiment and must be rebuilt before running. + Next extend the native adapter's consumer lifetime and dependency callbacks + using existing lease ABI, then retry same-tick publication with synchronization. + Do not remove the rejection alone: that would permit unfinished GPU sampling. + +- Native GPU fence handoff: make_gpu_image now validates producer dependencies, + retains them in consumers, and exposes dependency_count/get_metal_event to Foco. + Required waits without valid dependencies are rejected. Viewport poll has an + explicit GPU-wait option (completed-only remains default); preview uses it and + publishes again immediately after submit so resized frames need not wait an + extra host tick. Rebuilt and ran 1,000-entity pan: 360 image publications, 359 + compositor presentations, zero skipped; 358 valid Metal timestamps, aggregate + 59.8321 FPS, p95 16.666833 ms, maximum 33.333542 ms (one doubled interval). + /tmp/kestrel-native-fences.log and /tmp/kestrel-native-fences.jsonl. This verifies + actual hosted fence import without the earlier adapter rejection; focused + dependency lifetime tests and live-resize deadlines remain to be verified. + +- Native Foco fence regression: new native_web_foco_gpu_dependencies test covers + pending-image dependency acceptance, count/event callbacks, invalid index/null + arguments and rejection of required waits without dependencies. It drops frame, + lease and producer references while retaining a consumer, verifies its dependency + still exists, then verifies destruction on consumer completion. Uses a fake + fence pointer only for callback/lifetime checks, never GPU submission. Rebuilt + target and CTest passes; actual Metal synchronization is covered separately by + the hosted probe. Live resize acceptance remains unfinished. + +- Hosted canvas-resize workload: --benchmark-canvas-resize drives three 120-tick + shrink/grow cycles via native inline dimensions while panning 1,000 meshes. + Rebuilt/reran with Metal trace: 360 image publications, 359 scene publications, + 359 compositor presentations, zero skipped, zero geometry rebuilds. 359 valid + presentedTime timestamps give 59.999605 FPS, p95 16.666875 ms and maximum + 16.666917 ms. Logs /tmp/kestrel-canvas-resize.log and + /tmp/kestrel-canvas-resize.jsonl. This is canvas resizing within a fixed window, + not AppKit live window dragging; visual verification of per-frame matching + content and native window resize acceptance remain unfinished. + +- Resize workload validity checks: preview now validates every published lease's + actual dimensions against current canvas dimensions. Canvas-resize benchmark + counts real viewport dimension changes and host ticks ending without a matching + image, failing if fewer than 300 changes occur or any matching image is missing. + Rebuilt/reran: 359 dimension changes, zero ticks without matching content, + 360 image publications, 360 compositor presentations, zero skips over 5.98677s. + /tmp/kestrel-resize-validation.log and accompanying .jsonl Metal trace. This + strengthens canvas-resize evidence without substituting it for AppKit window + dragging or visual stale-frame inspection, which remain unfinished. + +- Shrunk-canvas visual check: resize benchmark capture now triggers at tick 61, + the first minimum-size point, instead of near the restored size. Rebuilt and + captured /tmp/kestrel-resize-minimum.png (clean exit). Inspected: native mesh grid + and primary box remain visible within reduced canvas, with right/bottom unused + space rather than an image stretched to the original viewport. Search/command + placeholders are now visible too. This single forced capture is visual evidence + at one point; it does not prove all transition frames or AppKit live resizing. + +- Original Courtyard drawing fixture: generated the pinned upstream examples.js + courtyard through its original math/geometry/model implementation offline, and + embedded the resulting project JSON in kestrel.examples C++ module. Native + load_courtyard applies it through the native drawing validator: 265 entities, + nine layers, original project name; all entity layers resolve. Rebuilt + kestrel_native_layers and CTest passes. Offline JavaScript generation is not + deployed or run by the app; runtime parsing is drawing JSON, never HTML. + Preview still uses its diagnostic box until this fixture is connected with + camera fitting and original render-style selection. Full drawing render parity + and application behavior remain unverified. + +- Courtyard connected to hosted preview: ordinary launch now loads the original + embedded 265-entity fixture, selects wireframe and fits visible geometry. Existing + synthetic benchmarks and interaction probes retain their deterministic box + fixtures. Rebuilt/captured /tmp/kestrel-native-courtyard.png with clean exit. + Inspected walls, openings/door arcs, furniture, hatches and dimension lines; + explorer shows nine layers and 265 objects with native summary title. Drawing + labels and dimension text are absent: native render_data collects text, but + hosted text drawing requires investigation. Full visual parity remains unmet. + +- Native Canvas text API: added fill_text using existing shared display-list + commands for paint/font/alignment/baseline/text. This supplies the missing native + entry point needed by Courtyard's text overlay without V8 or HTML parsing. + Rebuilt native_web_text and CTest passes Unicode content/coordinates, clear and + no layout-pass increase for drawing-only updates. Native render_data already + collects drawing labels; projecting and painting those onto the preview overlay + is next. This API addition alone does not restore visible Courtyard labels. + +- Courtyard native text overlay: exposes cached viewport text records and projects + their axes using original renderer.js visibility, scale, orientation and + dimension-flip rules. Native Canvas fill_text supports a scoped affine transform; + preview paints aligned multiline text onto the original overlay canvas with + matching bitmap dimensions when publishing GPU frames. Rebuilt and captured + /tmp/kestrel-courtyard-text.png, clean exit; inspected room labels, dimension + numbers, north label, drawing title and scale annotations now visible. Rebuilt + native_web_text and CTest passes. Dimension background masks, formatted MText, + custom font handling, complete original renderer overlays and performance with + text are still unverified/incomplete; this is not full browser parity. + +- Original drawing panning workload: --benchmark-courtyard fits the original + drawing and pans back/forth through 360 ticks, keeping labels within view. + Rebuilt/reran: 265 entities, 30 text records, 360 GPU publications, zero geometry + rebuilds, mean CPU tick 3.49867 ms, max 4.33971 ms. Scene publications 359; + compositor presentations 358 and one skipped attempt. 356 valid Metal times + yield 59.999662 FPS, p95 16.666833 ms, max 16.666917 ms. Logs + /tmp/kestrel-courtyard-pan.log and /tmp/kestrel-courtyard-pan.jsonl. The positive + timestamp series sustains 60fps with the current text overlay, but the isolated + skipped attempt is not characterized, and this does not prove physical input + latency, live window resize or complete original app functionality. + +- Original view action wiring: Zoom Extents data-action=fit now calls shared + native fit_drawing logic (also used at Courtyard startup), fitting visible + geometry. Zoom In/Out now use original app.js factors 1.35 and 1/1.35 instead + of the diagnostic 1.25/0.8 values. FocoKestrelPreview rebuilds successfully. + Physical action clicks and wider command/ribbon synchronization remain to be + verified; this change does not establish full UI behavior parity. + +- Original selection actions: native drawing now exposes select_all_editable, + replacing selection with visible entities on unlocked layers as original app.js + does. Preview wires selectall and clear-selection data-actions, refreshes explorer + selection/summary state and invalidates GPU content. Regression verifies prior + selection replacement, hidden entity exclusion and locked layer exclusion; + rebuilt kestrel_native_layers CTest passes and FocoKestrelPreview builds. + Clear-selection's original tool-cancellation behavior and inspector updates + remain pending with the broader native application controller port. + +- Native existing-selection erase/history actions: drawing.erase_selected filters + through selected(true), removes editable IDs in one named transaction and skips + empty selection. Preview routes original erase/undo/redo actions into native + history, refreshes explorer and invalidates GPU content. Courtyard regression + verifies erase count, exact data restoration by Undo, Redo removal and empty + no-op. Rebuilt native layer test passes and FocoKestrelPreview builds. Original + interactive erase tool on empty selection, command history messages, cancellation + and inspector synchronization remain incomplete. + +- Original active-document tab view: added predefined clean/dirty tab templates + copied from original refreshTabs markup/icon, with native named references. + Native panel refresh supplies active document name, ID, close accessible label + and dirty marker from drawing state. Tests with document-tabs verify initial + name and dirty marker after a transaction; rebuilt native layer CTest passes. + This is the single active document view only: switching/closing and multi-document + lifecycle still require application controller work. No runtime HTML parsing. + +- Native document status bindings: title-name, selection-status and units-status + now follow the native drawing during explorer refresh. The renderer badge + changes to WebGPU only after the first native GPU image arrives. The native + layer test checks initial title/status and selection updates and passes. + Rebuilt FocoKestrelPreview and captured /tmp/kestrel-status-current.png with + clean exit; inspected Courtyard title, active document tab, units and renderer + badge. This does not establish full command parity or OS live-resize timing. + +- Native orbit navigation: Shift+middle-drag now selects orbit at pointer-down, + using the original app.js yaw/pitch sensitivity and pole clamps. Ordinary + middle-drag still pans. Orbit updates the original view selector to iso. + Native camera tests verify direction, sensitivity, fixed target, revision and + both pitch limits; existing browser camera-reference comparisons pass. + This does not yet port the browser workspace/navigation class updates or prove + physical pointer capture outside the window. + +- Hosted navigation exercise: --exercise-navigation injects Foco pointer events + into the mounted original UI and checks orbit/pan mode remains determined by + pointer-down modifiers, release and cancellation stop navigation, and a new + GPU image is published. It exposed set_value rejecting the original select; + native value/set_value now supports selects using live option selectedness, + normalized fallback text and explicit empty selection for unmatched values. + Native text tests pass, including programmatic change-event suppression. + Rebuilt/reran hosted exercise: success marker and GPU serial 2 capture at + /tmp/kestrel-native-orbit.png; inspected rotated Courtyard and SE isometric + selector. Physical pointer capture, full select interaction and window resize + performance remain unproven. Failure shutdown currently returned process zero + in the initial failed exercise; inspect explicit success markers until the + preview exit-code propagation is corrected. + +- Original view/style dropdown change handlers now update the native camera and + renderer. Hosted navigation exercises front/iso and shaded-edges changes and + requires a subsequent GPU image; success marker confirmed after rebuild in + /tmp/kestrel-dropdown-final.log. Inspected /tmp/kestrel-dropdown-current.png. + Native popup/keyboard select interaction and workspace side effects still need + implementation. Added --exercise-failure to reproduce failure-exit handling. + Foco Cocoa terminate exits zero before returning the lifetime result. Replacing + terminate with stop plus a wake event exposed exit 139 on both success/failure; + that host change was reverted, Foco worktree is clean, and final hosted exercise + succeeds again. Teardown requires dedicated debugging; exit codes alone remain + insufficient evidence for preview validation. + +- Cocoa shutdown root cause verified from macOS crash report: the active display + callback continued after application host-frame shutdown cleared renderer and + display-link resources. Foco now checks callback lifetime after reentrant input, + layout and host-frame work. Cocoa shutdown stops/wakes the AppKit loop instead + of terminating the process, allowing its requested exit code to return. Rebuilt + preview: --exercise-failure returns 5; --exercise-navigation returns 0 with its + success marker. Courtyard pan also exits 0 after 360 frames, 359 compositor + presentations, zero skips in 5.98628 s, zero geometry rebuilds. These are backend + counts, not physical display timestamp measurements or OS resize evidence. + +- Native single-select keyboard navigation: selects are focusable; Up/Down and + Home/End change live selection, skip disabled options/optgroups, stop at list + boundaries, and emit input followed by change only for an actual change. + Disposal from input prevents the subsequent change dispatch. Native text tests + cover these behaviors and pass. Foco forwards the four navigation keys. + Multiple selection, native popup interaction and typeahead remain unfinished. + +- Hosted select keyboard verification: navigation exercise now uses Foco key + events (Home, Down, Up) for original view/style controls instead of setting + values and dispatching change manually. It asserts focus, handled events, front + camera orientation, iso selection and shaded-edges renderer state, followed by + a new GPU image. Rebuilt preview exits 0 with success marker and GPU serial 2; + inspected /tmp/kestrel-keyboard-select.png including focused control styling. + This verifies injected host events, not physical keyboard or popup operation. + +- Native panel actions now toggle the original workbench hide-explorer and + hide-properties classes, preserving unrelated classes and unchanged CSS. Hosted + navigation injects temporary native action buttons, verifies each hide expands + canvas width and restoring both recovers the initial width; run exits 0 with + success marker. The original painted-button lookup failed, so this is action/ + layout validation only, not proof original icon buttons are visible/clickable. + Original shell data-icon hydration remains an interaction/visual gap. This + same-tick layout check does not measure intermediate GPU sizes or resize FPS. + +- Original shell icon hydration: extracted the 17 data-icon names used in the + pinned index.html and expanded original UI.icon definitions into predefined + SVG templates in LayerRows.html. Native construction traverses child snapshots + and instantiates icons into authored placeholders; panel disposal removes owned + icon roots. Added native document children snapshots. No runtime HTML parser + or JS is used; original index.html/style.css are unchanged. Layer tests verify + SVG construction and disposal and pass. Rebuilt preview exits 0 and capture + /tmp/kestrel-shell-icons.png visibly includes search/settings/panel arrows and + other previously missing shell icons. Icon visibility is proven; individual + commands still require their own port/interaction verification. + +- Original panel pointer verification replaces temporary test buttons: locate + authored viewport-controls/statusbar actions, require nonzero hit areas, then + inject Foco primary pointer press/release at their centers. The hosted exercise + verifies both hide actions expand canvas width and both show actions restore it; + original controls remain reachable with panels hidden. Rebuilt run exits 0 with + success marker in /tmp/kestrel-original-panel-pointer.log. This closes the + original-control hit-routing gap for these two actions, not OS event delivery + or intermediate resize presentation timing. + +- Actual macOS window resize exercised using CGEvent corner drag: 360 steps + shrink 300x180 points and restore. Native trace reports 361 resize events, + 357 content frames, zero deadline misses, selected/native cadence 60 Hz. + Presentation timestamps are almost entirely zero, so displayed FPS cannot be + established from this run. See native-web-os-resize-evidence.json for isolated + gesture counts. No claim of visual no-stretch or displayed 60fps. Raw logs are + /tmp/kestrel-window-resize-current.log and matching .jsonl; app remains running + under exec session 91177 for further investigation. + +- Live-resize presentation trace now records transaction mode, drawable ID and + dimensions plus callback arrival separately from presentedTime. Repeated real + OS drag: 381 transaction content callbacks had one valid presentation timestamp; + 58 retained transaction callbacks had none. Content used 181 distinct sizes. + Callback arrival must not be substituted for display timing. Results added to + native-web-os-resize-evidence.json; no displayed-FPS conclusion. Current app + remains running under exec session 56253, PID 16828. + +- Actual window midpoint capture during held OS resize: screencapture targets the + Kestrel CGWindow, pauses 0.2 s at the inward endpoint, then restores the window. + /tmp/kestrel-live-resize-midpoint.png shows narrow-window media layout hiding + Properties, horizontal ribbon overflow, and clipped drawing without obvious + stretching in that frame. This is sampled visual evidence, not continuous + motion or 60fps proof; midpoint capture metadata added to resize evidence. + +- Native theme action now updates authored root data-theme, GPU light-theme + options and original sun/moon SVG path. Hosted light-theme capture initially + exposed :root failing for native parentless html nodes: shared compound matcher + recognized wrapper-based roots only. Added parentless html recognition and a + shared CSS regression proving root-attribute custom-variable recascade dark to + light and back. Rebuilt shared-style suite passes. Hosted capture exits 0; + /tmp/kestrel-native-light-fixed.png confirms light shell, grid, geometry, text + overlay and moon icon. Original stylesheet remains unchanged. Preferences and + sheet-specific theme policy remain unported. + +- Native Show all layers action: original all-layers-on command invokes an + undoable Show all layers transaction, refreshing explorer and GPU state. Tests + verify visibility restoration, preserved locks, no redundant history entry, + exact undo restoration and redo; layer suite passes. Preview rebuilt. Also + rebuilt/reran shared generated-document CSS suite after parentless :root fix; + linked/embedded/inline CSS test passes. Physical command interaction and full + layer manager remain separate gaps. + +- Native viewport click selection: added screen-space segment distance/depth + picking, basic multiline text bounds and shaded mesh-face depth, with browser + distance thresholds/tie-breaking. Selection handles visible groups, modifier + toggling, Ctrl/Meta group bypass and empty-click clearing. Native tests cover + lines, tolerance, visibility, groups and empty clicks and pass. Primary pointer + clicks invoke picking; movement over four pixels cancels click selection. + Hosted test exposed original canvas pointer-events:none, so viewport itself + is accepted as the authored click target. Rebuilt hosted --exercise-picking + exits 0 and capture /tmp/kestrel-native-picked.png shows selected count 1 and + updated drawing. Spatial indexing, rich/composed text hit bounds, dedicated + mesh/text picking tests, drag-box selection, grips and hover remain incomplete. + +- Picking validation expanded: native tests now cover mesh interior exclusion in + wireframe, face picking in shaded mode, nearer overlapping face depth, hidden + mesh exclusion, and centered multiline text hit/miss bounds. Rebuilt layer/ + picking test passes. This closes the dedicated basic mesh/text test gap from + aa2ce684; composed text, spatial indexing and comprehensive browser differential + picking coverage remain open. + +- Native keyboard event seam: document.key now dispatches bubbling keydown with + explicit key and modifiers before built-in keyboard defaults. prevent_default + suppresses default editing; disposal from the listener stops processing safely. + Native text suite rebuilt/passes, including root bubbling, modifier preservation, + cancelled deletion, ordinary deletion and disposal. Kestrel shortcut routing + and full host key coverage still need implementation; this is their native API + prerequisite, not a claim that erase/undo shortcuts are working yet. + +- Native editing shortcuts: Foco forwards A/Z/Y, Escape and F7 in addition to + existing delete keys. Root keydown handles select-all, erase, undo/redo, Escape + selection/navigation cancellation and grid toggle, while input/textarea/select + and contenteditable ancestors retain editing behavior. Open modal/palette guards + prevent underlying shortcuts. Added native tag_name introspection. Hosted + --exercise-shortcuts verifies select-all/erase, Ctrl and platform-modifier undo, + redo, exact document restoration, Backspace text isolation, Escape and grid. + Rebuilt run exits 0 with success marker and GPU serial 2 capture. Full tool + cancellation, remaining shortcut commands and physical-key delivery remain open. + +- Native window/crossing selection: added containment and crossing tests using + projected entity bounds, segment intersections, basic text overlap and shaded + face containment. Editable group expansion and additive selection follow the + original selectWindow model. Native tests prove crossing can select a segment + with both endpoints outside, containment rejects partial entities, full bounds + selects and locked layers are excluded. Suite passes. Preview primary drags + update original selection-window style/class, select on release, and hide on + release/cancel/Escape; preview builds. Hosted drag/capture verification remains + required, along with broader mesh/text/group differential coverage. + +- Hosted drag selection verification: --exercise-drag-selection injects primary + press/move/release into the original viewport, checks visible crossing rectangle + geometry/class, verifies multiple selected entities and hidden rectangle after + release, then cancels another drag and checks unchanged selection/cleanup. + Rebuilt run exits 0, selects 257 Courtyard entities and captures GPU serial 2 at + /tmp/kestrel-drag-selected.png; inspected cyan geometry/text highlights and + selected count. Physical pointer capture outside the window and full browser + differential rectangle selection remain open. + +- Inspector no-selection state: compiled original inspector header/general/option + templates, populated current layer, color swatch, units and visual-style summary + through native APIs. Current-layer select change updates the drawing and panel. + Native layer tests verify populated no-selection content and disposal; pass. + Rebuilt preview exits 0 and /tmp/kestrel-inspector-empty.png shows original + Properties layout. Selected-object inspector, color/default editing, ByLayer + action and workspace-dependent summary refresh remain incomplete. The temporary + workspace label is still 2D drafting until native workspace state is ported. + +- Native view-state synchronization: named view changes now follow original + 2D/3D workspace policy and enable shaded edges for wireframe mesh drawings + entering non-top/bottom views. Orbit enters modeling state. Style/workspace + selectors, model-space label and inspector summary update together, guarded by + actual state changes to avoid per-orbit-frame inspector rebuilds. Rebuilt + --exercise-navigation exits 0; /tmp/kestrel-view-state.png confirms iso, shaded + edges and consistent 3D modeling labels. Full workspace-switch defaults, ribbon + changes and selected-object inspector remain unported. + +- Selected-object inspector layer editing: compiled original type-header variants + and Layer row, with multi-selection placeholder and native option population. + Change applies Edit layer transaction to the precomputed editable selection; + invalid target and fully locked selection make no change. Tests verify layer + changes, destination lock behavior and exact undo restoration; layer suite + passes. Rebuilt hosted picking capture exits 0 and shows Polyline/A-WALL in + /tmp/kestrel-inspector-selected.png. Remaining general/geometry property rows, + locked-edit error feedback and hosted layer-change interaction remain open. + +### Native continuous Line command state + +Ported the original app's continuous Line point/segment state into the exported +C++ drawing module. Each nonduplicate segment uses a Line transaction and current +layer, color and lineweight; command Undo removes the last segment/point, and +cancel clears pending points without deleting committed geometry. Locked-layer +failure preserves both document and pending endpoint. The native drawing suite +passes, covering chained segments, 1e-8 duplicate tolerance, defaults, Undo, +locked-layer rejection and cancellation. This is command state only: connecting +the original ribbon, viewport coordinates, snapping, rubber-band preview, numeric +input and command prompts remains necessary before claiming Line tool parity. + +### Original ribbon and viewport Line wiring + +The original compiled ribbon Line action now starts native line_command; primary +viewport pointer input unprojects onto the XY plane and commits connected +segments, bypassing selection while the command is active. Near-edge-on views +switch to top, Escape cancels, and the original banner/prefix display prompts or +locked-layer errors. Existing middle-button navigation is retained. Foco preview +build and startup/capture smoke pass (GPU serial 1, clean exit). This smoke does +not verify physical Line pointer interaction. Rubber-band preview, snapping, +command-line Undo/numeric entry, drawing-default UI synchronization and complete +application tool transitions remain unfinished; do not claim Line parity yet. + +### Hosted original Line interaction evidence + +Added --exercise-line-draw to the Foco preview. The check locates the original +compiled ribbon button, sends press/release events through the Foco WebScene +view, then clicks two viewport positions. It verifies the first point leaves the +model unchanged and the second creates one LINE with endpoints matching camera +unprojection. Native Escape cancels pending state; platform Undo restores the +exact document snapshot. The rebuilt hosted run passed and captured with GPU +serial 2, exiting 0. This exercises synthetic Foco view input, not physical OS +mouse ingestion, snapping, rubber-band feedback, or a pixel check of the new line. + +### Line command-field options + +The existing compiled command input handles Line U/UNDO and empty Enter/ENTER +finish, plus ESC/CANCEL aliases. Recognized options clear the input, update the +original prompt and refresh native model/viewport state. The hosted Line check +now types lowercase u through Foco text input, presses Enter through Foco key +input, verifies exact drawing restoration with the previous endpoint retained, +and creates another segment by pointer before Escape/global Undo. Build and +hosted check pass (GPU serial 2, exit 0). Numeric coordinates, semicolon command +sequences, history/suggestions and general command dispatch remain unported; +finish aliases have not yet received a dedicated hosted assertion. + +### Native drafting coordinate parser + +Added parse_drafting_point in the exported drawing module for absolute XY/XYZ, +relative @ coordinates and distance