diff --git a/php-transformer/src/HtmlToBlocks/HtmlCompilation.php b/php-transformer/src/HtmlToBlocks/HtmlCompilation.php
index b7a537f5..4e7d6e14 100644
--- a/php-transformer/src/HtmlToBlocks/HtmlCompilation.php
+++ b/php-transformer/src/HtmlToBlocks/HtmlCompilation.php
@@ -2954,6 +2954,12 @@ private function convertElement(DOMElement $element, array &$fallbacks, bool $ca
return null;
}
+ // Empty, visually clipped live regions are runtime accessibility
+ // scaffolding with no editable static content to retain.
+ if ( $this->isInertLiveRegionScaffolding($element) ) {
+ return null;
+ }
+
// A direct phrasing child participates in its parent's flex or grid
// layout. Preserve that source element as the editable leaf rather
// than introducing a paragraph wrapper with core paragraph margins.
@@ -3441,6 +3447,56 @@ private function isInertRuntimeMediaPlaceholder(DOMElement $element): bool
return true;
}
+ private function isInertLiveRegionScaffolding(DOMElement $element): bool
+ {
+ if ( ! str_contains(strtolower($element->tagName), '-')
+ || '' !== trim($element->textContent ?? '')
+ || ! $this->isSafeTransparentCustomElement($element)
+ || 0 !== $element->attributes->length ) {
+ return false;
+ }
+
+ $liveRegion = $this->soleElementChild($element);
+ if ( ! $liveRegion instanceof DOMElement
+ || 0 !== $this->childElementCount($liveRegion)
+ || ! in_array(strtolower($liveRegion->tagName), array( 'div', 'p', 'span' ), true)
+ || ! in_array(strtolower(trim($this->attr($liveRegion, 'role'))), array( 'alert', 'log', 'status' ), true)
+ || ! in_array(strtolower(trim($this->attr($liveRegion, 'aria-live'))), array( 'assertive', 'polite' ), true)
+ || ! $this->isVisuallyClippedLiveRegion($liveRegion)
+ || array() !== $this->safeDataAttributes($liveRegion) ) {
+ return false;
+ }
+
+ $allowedAttributes = array( 'aria-atomic', 'aria-live', 'class', 'id', 'role', 'style' );
+ foreach ( $liveRegion->attributes as $attribute ) {
+ if ( ! in_array(strtolower($attribute->name), $allowedAttributes, true) ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private function isVisuallyClippedLiveRegion(DOMElement $element): bool
+ {
+ $declarations = $this->styleResolver->structuralPresentationDeclarations($element);
+ $width = trim((string) ($declarations['width'] ?? ''));
+ $height = trim((string) ($declarations['height'] ?? ''));
+ $clip = strtolower(trim((string) ($declarations['clip'] ?? '')));
+ $clipPath = strtolower(trim((string) ($declarations['clip-path'] ?? '')));
+
+ return 'absolute' === strtolower(trim((string) ($declarations['position'] ?? '')))
+ && 'hidden' === strtolower(trim((string) ($declarations['overflow'] ?? '')))
+ && $this->isAtMostOnePixelLength($width)
+ && $this->isAtMostOnePixelLength($height)
+ && (str_starts_with($clip, 'rect(') || str_starts_with($clipPath, 'inset('));
+ }
+
+ private function isAtMostOnePixelLength(string $value): bool
+ {
+ return 1 === preg_match('/^(?:0|1)px$/i', $value);
+ }
+
/**
* @return array|null
*/
diff --git a/php-transformer/tests/unit/inert-capture-scaffolding.php b/php-transformer/tests/unit/inert-capture-scaffolding.php
index 03a91421..024cd2f8 100644
--- a/php-transformer/tests/unit/inert-capture-scaffolding.php
+++ b/php-transformer/tests/unit/inert-capture-scaffolding.php
@@ -20,6 +20,19 @@
$assert(array() === ($inertIframe['source_reports']['runtime_islands'] ?? array()), 'hidden sourceless iframe emits no runtime island');
$assert(str_contains((string) ($inertIframe['serialized_blocks'] ?? ''), 'Visible copy') && ! str_contains((string) ($inertIframe['serialized_blocks'] ?? ''), 'archetype'), 'hidden sourceless iframe emits no block');
+$inertLiveRegions = $transform('Visible heading
');
+$assert(array() === ($inertLiveRegions['fallbacks'] ?? array()), 'empty visually clipped custom-element live regions emit no fallback regardless of wrapper name');
+$assert(str_contains((string) ($inertLiveRegions['serialized_blocks'] ?? ''), 'Visible heading') && ! str_contains((string) ($inertLiveRegions['serialized_blocks'] ?? ''), 'capture-shell') && ! str_contains((string) ($inertLiveRegions['serialized_blocks'] ?? ''), 'next-route-announcer'), 'inert live-region scaffolding emits no editable block');
+
+$liveRegionWithContent = $transform('Page changed
');
+$assert(str_contains((string) ($liveRegionWithContent['serialized_blocks'] ?? ''), 'Page changed'), 'live regions with captured content remain editable');
+
+$namedWrapper = $transform('');
+$assert('capture-shell' === ($namedWrapper['fallbacks'][0]['tag'] ?? ''), 'semantically named custom wrappers remain explicit fallbacks');
+
+$customElement = $transform('');
+$assert('custom-widget' === ($customElement['fallbacks'][0]['tag'] ?? ''), 'unrelated custom elements remain explicit fallbacks');
+
$unreferencedStore = $transform('Visible copy
');
$assert(array() === ($unreferencedStore['fallbacks'] ?? array()), 'hidden unreferenced SVG store emits no fallback');
$assert(! str_contains((string) ($unreferencedStore['serialized_blocks'] ?? ''), 'unused'), 'hidden unreferenced SVG store emits no raw HTML');