<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[54162] trunk: Editor: Backport foundation for Layout block support refactor (part 1).</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/54162">54162</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/54162","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>hellofromTonya</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-09-14 18:42:04 +0000 (Wed, 14 Sep 2022)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Editor: Backport foundation for Layout block support refactor (part 1).

Backports the following changes from the Gutenberg repository:

* [WordPress/gutenberg/40875 gutenberg/40875] Layout: Use semantic classnames, centralize layout definitions, reduce duplication, and fix blockGap in theme.json
* [WordPress/gutenberg/42544 gutenberg/42544] Layout: Add a disable-layout-styles theme supports flag to opt out of all layout styles gutenberg/42544
* [WordPress/gutenberg/42087 gutenberg/42087] Theme.json: Add block support feature level selectors for blocks gutenberg/42087
* [WordPress/gutenberg/43792 gutenberg/43792] Global Styles: Split root layout rules into a different function gutenberg/43792
* [WordPress/gutenberg/42544 gutenberg/42544] Layout: Add a disable-layout-styles theme supports flag to opt out of all layout styles gutenberg/42544
* [WordPress/gutenberg/42665 gutenberg/42665] Layout: Reduce specificity of fallback blockGap styles gutenberg/42665
* [WordPress/gutenberg/42085 gutenberg/42085] Core CSS support for root padding and alignfull blocks gutenberg/42085

Notes:
* It doesn't entirely port over PR 40875 - the remaining PHP changes for that PR will be explored in a separate PR targeting `layout.php`.
* <a href="https://core.trac.wordpress.org/changeset/54159">[54159]</a> was reverted in <a href="https://core.trac.wordpress.org/changeset/54160">[54160]</a> due to PHPUnit test failures for tests added by the commit. Later, tests passed when applied on top of `trunk`. There were various outages today of upstream `wp-env` dependencies, which likely were the root cause of the earlier failures. For historical tracking and to make sure, recommitting <a href="https://core.trac.wordpress.org/changeset/54159">[54159]</a> but instead on top of current `trunk`. See PR 3205 for more details.
* Giving additional props for those who did a deep dive investigation into the failed tests.

Follow-up to <a href="https://core.trac.wordpress.org/changeset/54160">[54160]</a>, <a href="https://core.trac.wordpress.org/changeset/54159">[54159]</a>.

Props andrewserong, aaronrobertshaw, isabel_brison, bernhard-reiter, hellofromTonya.
See <a href="https://core.trac.wordpress.org/ticket/56467">#56467</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesblockeditorphp">trunk/src/wp-includes/block-editor.php</a></li>
<li><a href="#trunksrcwpincludesclasswpthemejsonresolverphp">trunk/src/wp-includes/class-wp-theme-json-resolver.php</a></li>
<li><a href="#trunksrcwpincludesclasswpthemejsonphp">trunk/src/wp-includes/class-wp-theme-json.php</a></li>
<li><a href="#trunksrcwpincludesglobalstylesandsettingsphp">trunk/src/wp-includes/global-styles-and-settings.php</a></li>
<li><a href="#trunksrcwpincludesthemejson">trunk/src/wp-includes/theme.json</a></li>
<li><a href="#trunksrcwpincludesthemephp">trunk/src/wp-includes/theme.php</a></li>
<li><a href="#trunktestsphpunittestsblockseditorphp">trunk/tests/phpunit/tests/blocks/editor.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestthemescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php</a></li>
<li><a href="#trunktestsphpunitteststhemewpThemeJsonphp">trunk/tests/phpunit/tests/theme/wpThemeJson.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesblockeditorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/block-editor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/block-editor.php    2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/block-editor.php      2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -209,6 +209,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                'disableCustomColors'              => get_theme_support( 'disable-custom-colors' ),
</span><span class="cx" style="display: block; padding: 0 10px">                'disableCustomFontSizes'           => get_theme_support( 'disable-custom-font-sizes' ),
</span><span class="cx" style="display: block; padding: 0 10px">                'disableCustomGradients'           => get_theme_support( 'disable-custom-gradients' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                'disableLayoutStyles'              => get_theme_support( 'disable-layout-styles' ),
</ins><span class="cx" style="display: block; padding: 0 10px">                 'enableCustomLineHeight'           => get_theme_support( 'custom-line-height' ),
</span><span class="cx" style="display: block; padding: 0 10px">                'enableCustomSpacing'              => get_theme_support( 'custom-spacing' ),
</span><span class="cx" style="display: block; padding: 0 10px">                'enableCustomUnits'                => get_theme_support( 'custom-units' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -417,6 +418,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $block_classes['css'] = $actual_css;
</span><span class="cx" style="display: block; padding: 0 10px">                        $global_styles[]      = $block_classes;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        } else {
+               // If there is no `theme.json` file, ensure base layout styles are still available.
+               $block_classes = array(
+                       'css'            => 'base-layout-styles',
+                       '__unstableType' => 'base-layout',
+                       'isGlobalStyles' => true,
+               );
+               $actual_css    = wp_get_global_stylesheet( array( $block_classes['css'] ) );
+               if ( '' !== $actual_css ) {
+                       $block_classes['css'] = $actual_css;
+                       $global_styles[]  = $block_classes;
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $editor_settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -474,9 +487,24 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $editor_settings['enableCustomSpacing'] = $editor_settings['__experimentalFeatures']['spacing']['padding'];
</span><span class="cx" style="display: block; padding: 0 10px">                unset( $editor_settings['__experimentalFeatures']['spacing']['padding'] );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( isset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] ) ) {
+               $editor_settings['disableCustomSpacingSizes'] = ! $editor_ettings['__experimentalFeatures']['spacing']['customSpacingSize'];
+               unset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( isset( $editor_settings['__experimentalFeatures']['spacing']['spacingSizes'] ) ) {
+               $spacing_sizes_by_origin  = $editor_settings['__experimentalFeatures']['spacing']['spacingSizes'];
+               $editor_settings['spacingSizes'] = isset( $spacing_sizes_by_origin['custom'] ) ?
+                       $spacing_sizes_by_origin['custom'] : (
+                               isset( $spacing_sizes_by_origin['theme'] ) ?
+                                       $spacing_sizes_by_origin['theme'] :
+                                       $spacing_sizes_by_origin['default']
+                       );
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         $editor_settings['__unstableResolvedAssets']         = _wp_get_iframed_editor_assets();
</span><span class="cx" style="display: block; padding: 0 10px">        $editor_settings['localAutosaveInterval']            = 15;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $editor_settings['disableLayoutStyles']              = current_theme_supports( 'disable-layout-styles' );
</ins><span class="cx" style="display: block; padding: 0 10px">         $editor_settings['__experimentalDiscussionSettings'] = array(
</span><span class="cx" style="display: block; padding: 0 10px">                'commentOrder'         => get_option( 'comment_order' ),
</span><span class="cx" style="display: block; padding: 0 10px">                'commentsPerPage'      => get_option( 'comments_per_page' ),
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpthemejsonresolverphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-theme-json-resolver.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-theme-json-resolver.php    2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/class-wp-theme-json-resolver.php      2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -233,6 +233,54 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Gets the styles for blocks from the block.json file.
+        *
+        * @since 6.1.0
+        *
+        * @return WP_Theme_JSON
+        */
+       public static function get_block_data() {
+               $registry = WP_Block_Type_Registry::get_instance();
+               $blocks   = $registry->get_all_registered();
+               $config   = array( 'version' => 1 );
+               foreach ( $blocks as $block_name => $block_type ) {
+                       if ( isset( $block_type->supports['__experimentalStyle'] ) ) {
+                               $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] );
+                       }
+
+                       if (
+                               isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] ) &&
+                               null === _wp_array_get( $config, array( 'styles', 'blocks', $block_name, 'spacing', 'blockGap' ), null )
+                       ) {
+                               // Ensure an empty placeholder value exists for the block, if it provides a default blockGap value.
+                               // The real blockGap value to be used will be determined when the styles are rendered for output.
+                               $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] = null;
+                       }
+               }
+
+               // Core here means it's the lower level part of the styles chain.
+               // It can be a core or a third-party block.
+               return new WP_Theme_JSON( $config, 'core' );
+       }
+
+       /**
+        * When given an array, this will remove any keys with the name `//`.
+        *
+        * @param array $array The array to filter.
+        * @return array The filtered array.
+        */
+       private static function remove_json_comments( $array ) {
+               unset( $array['//'] );
+               foreach ( $array as $k => $v ) {
+                       if ( is_array( $v ) ) {
+                               $array[ $k ] = static::remove_json_comments( $v );
+                       }
+               }
+
+               return $array;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Returns the custom post type that contains the user's origin config
</span><span class="cx" style="display: block; padding: 0 10px">         * for the active theme or a void array if none are found.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -370,6 +418,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.9.0 Added user data, removed the `$settings` parameter,
</span><span class="cx" style="display: block; padding: 0 10px">         *              added the `$origin` parameter.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 6.1.0 Added block data.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param string $origin Optional. To what level should we merge data.
</span><span class="cx" style="display: block; padding: 0 10px">         *                       Valid values are 'theme' or 'custom'. Default 'custom'.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -382,6 +431,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $result = new WP_Theme_JSON();
</span><span class="cx" style="display: block; padding: 0 10px">                $result->merge( static::get_core_data() );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $result->merge( static::get_block_data() );
</ins><span class="cx" style="display: block; padding: 0 10px">                 $result->merge( static::get_theme_data() );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'custom' === $origin ) {
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpthemejsonphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-theme-json.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-theme-json.php     2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/class-wp-theme-json.php       2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -177,40 +177,60 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *              `letter-spacing`, `margin-*`, `padding-*`, `--wp--style--block-gap`,
</span><span class="cx" style="display: block; padding: 0 10px">         *              `text-decoration`, `text-transform`, and `filter` properties,
</span><span class="cx" style="display: block; padding: 0 10px">         *              simplified the metadata structure.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 6.1.0 Added the `border-*-color`, `border-*-width`, `border-*-style`,
+        *              `--wp--style--root--padding-*`, and `box-shadow` properties,
+        *              removed the `--wp--style--block-gap` property.
</ins><span class="cx" style="display: block; padding: 0 10px">          * @var array
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        const PROPERTIES_METADATA = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'background'                 => array( 'color', 'gradient' ),
-               'background-color'           => array( 'color', 'background' ),
-               'border-radius'              => array( 'border', 'radius' ),
-               'border-top-left-radius'     => array( 'border', 'radius', 'topLeft' ),
-               'border-top-right-radius'    => array( 'border', 'radius', 'topRight' ),
-               'border-bottom-left-radius'  => array( 'border', 'radius', 'bottomLeft' ),
-               'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ),
-               'border-color'               => array( 'border', 'color' ),
-               'border-width'               => array( 'border', 'width' ),
-               'border-style'               => array( 'border', 'style' ),
-               'color'                      => array( 'color', 'text' ),
-               'font-family'                => array( 'typography', 'fontFamily' ),
-               'font-size'                  => array( 'typography', 'fontSize' ),
-               'font-style'                 => array( 'typography', 'fontStyle' ),
-               'font-weight'                => array( 'typography', 'fontWeight' ),
-               'letter-spacing'             => array( 'typography', 'letterSpacing' ),
-               'line-height'                => array( 'typography', 'lineHeight' ),
-               'margin'                     => array( 'spacing', 'margin' ),
-               'margin-top'                 => array( 'spacing', 'margin', 'top' ),
-               'margin-right'               => array( 'spacing', 'margin', 'right' ),
-               'margin-bottom'              => array( 'spacing', 'margin', 'bottom' ),
-               'margin-left'                => array( 'spacing', 'margin', 'left' ),
-               'padding'                    => array( 'spacing', 'padding' ),
-               'padding-top'                => array( 'spacing', 'padding', 'top' ),
-               'padding-right'              => array( 'spacing', 'padding', 'right' ),
-               'padding-bottom'             => array( 'spacing', 'padding', 'bottom' ),
-               'padding-left'               => array( 'spacing', 'padding', 'left' ),
-               '--wp--style--block-gap'     => array( 'spacing', 'blockGap' ),
-               'text-decoration'            => array( 'typography', 'textDecoration' ),
-               'text-transform'             => array( 'typography', 'textTransform' ),
-               'filter'                     => array( 'filter', 'duotone' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'background'                        => array( 'color', 'gradient' ),
+               'background-color'                  => array( 'color', 'background' ),
+               'border-radius'                     => array( 'border', 'radius' ),
+               'border-top-left-radius'            => array( 'border', 'radius', 'topLeft' ),
+               'border-top-right-radius'           => array( 'border', 'radius', 'topRight' ),
+               'border-bottom-left-radius'         => array( 'border', 'radius', 'bottomLeft' ),
+               'border-bottom-right-radius'        => array( 'border', 'radius', 'bottomRight' ),
+               'border-color'                      => array( 'border', 'color' ),
+               'border-width'                      => array( 'border', 'width' ),
+               'border-style'                      => array( 'border', 'style' ),
+               'border-top-color'                  => array( 'border', 'top', 'color' ),
+               'border-top-width'                  => array( 'border', 'top', 'width' ),
+               'border-top-style'                  => array( 'border', 'top', 'style' ),
+               'border-right-color'                => array( 'border', 'right', 'color' ),
+               'border-right-width'                => array( 'border', 'right', 'width' ),
+               'border-right-style'                => array( 'border', 'right', 'style' ),
+               'border-bottom-color'               => array( 'border', 'bottom', 'color' ),
+               'border-bottom-width'               => array( 'border', 'bottom', 'width' ),
+               'border-bottom-style'               => array( 'border', 'bottom', 'style' ),
+               'border-left-color'                 => array( 'border', 'left', 'color' ),
+               'border-left-width'                 => array( 'border', 'left', 'width' ),
+               'border-left-style'                 => array( 'border', 'left', 'style' ),
+               'color'                             => array( 'color', 'text' ),
+               'font-family'                       => array( 'typography', 'fontFamily' ),
+               'font-size'                         => array( 'typography', 'fontSize' ),
+               'font-style'                        => array( 'typography', 'fontStyle' ),
+               'font-weight'                       => array( 'typography', 'fontWeight' ),
+               'letter-spacing'                    => array( 'typography', 'letterSpacing' ),
+               'line-height'                       => array( 'typography', 'lineHeight' ),
+               'margin'                            => array( 'spacing', 'margin' ),
+               'margin-top'                        => array( 'spacing', 'margin', 'top' ),
+               'margin-right'                      => array( 'spacing', 'margin', 'right' ),
+               'margin-bottom'                     => array( 'spacing', 'margin', 'bottom' ),
+               'margin-left'                       => array( 'spacing', 'margin', 'left' ),
+               'padding'                           => array( 'spacing', 'padding' ),
+               'padding-top'                       => array( 'spacing', 'padding', 'top' ),
+               'padding-right'                     => array( 'spacing', 'padding', 'right' ),
+               'padding-bottom'                    => array( 'spacing', 'padding', 'bottom' ),
+               'padding-left'                      => array( 'spacing', 'padding', 'left' ),
+               '--wp--style--root--padding'        => array( 'spacing', 'padding' ),
+               '--wp--style--root--padding-top'    => array( 'spacing', 'padding', 'top' ),
+               '--wp--style--root--padding-right'  => array( 'spacing', 'padding', 'right' ),
+               '--wp--style--root--padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
+               '--wp--style--root--padding-left'   => array( 'spacing', 'padding', 'left' ),
+               'text-decoration'                   => array( 'typography', 'textDecoration' ),
+               'text-transform'                    => array( 'typography', 'textTransform' ),
+               'filter'                            => array( 'filter', 'duotone' ),
+               'box-shadow'                        => array( 'shadow' ),
</ins><span class="cx" style="display: block; padding: 0 10px">         );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -254,17 +274,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *              added new properties for `border`, `color`, `spacing`,
</span><span class="cx" style="display: block; padding: 0 10px">         *              and `typography`, and renamed others according to the new schema.
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 6.0.0 Added `color.defaultDuotone`.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 6.1.0 Added `layout.definitions` and `useRootPaddingAwareAlignments`.
</ins><span class="cx" style="display: block; padding: 0 10px">          * @var array
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        const VALID_SETTINGS = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'appearanceTools' => null,
-               'border'          => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'appearanceTools'               => null,
+               'useRootPaddingAwareAlignments' => null,
+               'border'                        => array(
</ins><span class="cx" style="display: block; padding: 0 10px">                         'color'  => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'radius' => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'style'  => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'width'  => null,
</span><span class="cx" style="display: block; padding: 0 10px">                ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'color'           => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'color'                         => array(
</ins><span class="cx" style="display: block; padding: 0 10px">                         'background'       => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'custom'           => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'customDuotone'    => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -278,18 +300,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'palette'          => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'text'             => null,
</span><span class="cx" style="display: block; padding: 0 10px">                ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'custom'          => null,
-               'layout'          => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'custom'                        => null,
+               'layout'                        => array(
</ins><span class="cx" style="display: block; padding: 0 10px">                         'contentSize' => null,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        'definitions' => null,
</ins><span class="cx" style="display: block; padding: 0 10px">                         'wideSize'    => null,
</span><span class="cx" style="display: block; padding: 0 10px">                ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'spacing'         => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'spacing'                       => array(
</ins><span class="cx" style="display: block; padding: 0 10px">                         'blockGap' => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'margin'   => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'padding'  => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'units'    => null,
</span><span class="cx" style="display: block; padding: 0 10px">                ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'typography'      => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'typography'                    => array(
</ins><span class="cx" style="display: block; padding: 0 10px">                         'customFontSize' => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'dropCap'        => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'fontFamilies'   => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -310,6 +333,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.9.0 Renamed from `ALLOWED_STYLES` to `VALID_STYLES`,
</span><span class="cx" style="display: block; padding: 0 10px">         *              added new properties for `border`, `filter`, `spacing`,
</span><span class="cx" style="display: block; padding: 0 10px">         *              and `typography`.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 6.1.0 Added new side properties for `border`,
+        *              updated `blockGap` to be allowed at any level.
</ins><span class="cx" style="display: block; padding: 0 10px">          * @var array
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        const VALID_STYLES = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -318,6 +343,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'radius' => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'style'  => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'width'  => null,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        'top'    => null,
+                       'right'  => null,
+                       'bottom' => null,
+                       'left'   => null,
</ins><span class="cx" style="display: block; padding: 0 10px">                 ),
</span><span class="cx" style="display: block; padding: 0 10px">                'color'      => array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'background' => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -330,7 +359,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                'spacing'    => array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'margin'   => null,
</span><span class="cx" style="display: block; padding: 0 10px">                        'padding'  => null,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'blockGap' => 'top',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'blockGap' => null,
</ins><span class="cx" style="display: block; padding: 0 10px">                 ),
</span><span class="cx" style="display: block; padding: 0 10px">                'typography' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'fontFamily'     => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -384,6 +413,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">        );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * List of block support features that can have their related styles
+        * generated under their own feature level selector rather than the block's.
+        *
+        * @since 6.1.0
+        * @var string[]
+        */
+       const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = array(
+               '__experimentalBorder' => 'border',
+               'color'                => 'color',
+               'spacing'              => 'spacing',
+               'typography'           => 'typography',
+       );
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Returns a class name by an element name.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 6.1.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -656,6 +699,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.9.0 Added `duotone` key with CSS selector.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 6.1.0 Added `features` key with block support feature level selectors.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @return array Block metadata.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -685,6 +729,25 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                static::$blocks_metadata[ $block_name ]['duotone'] = $block_type->supports['color']['__experimentalDuotone'];
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        // Generate block support feature level selectors if opted into
+                       // for the current block.
+                       $features = array();
+                       foreach ( static::BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS as $key => $feature ) {
+                               if (
+                                       isset( $block_type->supports[ $key ]['__experimentalSelector'] ) &&
+                                       $block_type->supports[ $key ]['__experimentalSelector']
+                               ) {
+                                       $features[ $feature ] = static::scope_selector(
+                                               static::$blocks_metadata[ $block_name ]['selector'],
+                                               $block_type->supports[ $key ]['__experimentalSelector']
+                                       );
+                               }
+                       }
+
+                       if ( ! empty( $features ) ) {
+                               static::$blocks_metadata[ $block_name ]['features'] = $features;
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         // Assign defaults, then overwrite those that the block sets by itself.
</span><span class="cx" style="display: block; padding: 0 10px">                        // If the block selector is compounded, will append the element to each
</span><span class="cx" style="display: block; padding: 0 10px">                        // individual block selector.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -810,7 +873,30 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( in_array( 'styles', $types, true ) ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $root_block_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $style_nodes, 'selector' ), true );
+
+                       if ( false !== $root_block_key ) {
+                               $stylesheet .= $this->get_root_layout_rules( static::ROOT_BLOCK_SELECTOR, $style_nodes[ $root_block_key ] );
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                         $stylesheet .= $this->get_block_classes( $style_nodes );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                } elseif ( in_array( 'base-layout-styles', $types, true ) ) {
+                       // Base layout styles are provided as part of `styles`, so only output separately if explicitly requested.
+                       // For backwards compatibility, the Columns block is explicitly included, to support a different default gap value.
+                       $base_styles_nodes = array(
+                               array(
+                                       'path'     => array( 'styles' ),
+                                       'selector' => static::ROOT_BLOCK_SELECTOR,
+                               ),
+                               array(
+                                       'path'     => array( 'styles', 'blocks', 'core/columns' ),
+                                       'selector' => '.wp-block-columns',
+                                       'name'     => 'core/columns',
+                               ),
+                       );
+
+                       foreach ( $base_styles_nodes as $base_style_node ) {
+                               $stylesheet .= $this->get_layout_styles( $base_style_node );
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( in_array( 'presets', $types, true ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -884,6 +970,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.9.0 Renamed from `get_block_styles()` to `get_block_classes()`
</span><span class="cx" style="display: block; padding: 0 10px">         *              and no longer returns preset classes.
</span><span class="cx" style="display: block; padding: 0 10px">         *              Removed the `$setting_nodes` parameter.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 6.1.0 Moved most internal logic to `get_styles_for_block()`.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param array $style_nodes Nodes with styles.
</span><span class="cx" style="display: block; padding: 0 10px">         * @return string The new stylesheet.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -902,6 +989,190 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Get the CSS layout rules for a particular block from theme.json layout definitions.
+        *
+        * @since 6.1.0
+        *
+        * @param array $block_metadata Metadata about the block to get styles for.
+        *
+        * @return string Layout styles for the block.
+        */
+       protected function get_layout_styles( $block_metadata ) {
+               $block_rules = '';
+               $block_type  = null;
+
+               // Skip outputting layout styles if explicitly disabled.
+               if ( current_theme_supports( 'disable-layout-styles' ) ) {
+                       return $block_rules;
+               }
+
+               if ( isset( $block_metadata['name'] ) ) {
+                       $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_metadata['name'] );
+                       if ( ! block_has_support( $block_type, array( '__experimentalLayout' ), false ) ) {
+                               return $block_rules;
+                       }
+               }
+
+               $selector                 = isset( $block_metadata['selector'] ) ? $block_metadata['selector'] : '';
+               $has_block_gap_support    = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
+               $has_fallback_gap_support = ! $has_block_gap_support; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback gap styles support.
+               $node                     = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
+               $layout_definitions       = _wp_array_get( $this->theme_json, array( 'settings', 'layout', 'definitions' ), array() );
+               $layout_selector_pattern  = '/^[a-zA-Z0-9\-\.\ *+>:\(\)]*$/'; // Allow alphanumeric classnames, spaces, wildcard, sibling, child combinator and pseudo class selectors.
+
+               // Gap styles will only be output if the theme has block gap support, or supports a fallback gap.
+               // Default layout gap styles will be skipped for themes that do not explicitly opt-in to blockGap with a `true` or `false` value.
+               if ( $has_block_gap_support || $has_fallback_gap_support ) {
+                       $block_gap_value = null;
+                       // Use a fallback gap value if block gap support is not available.
+                       if ( ! $has_block_gap_support ) {
+                               $block_gap_value = static::ROOT_BLOCK_SELECTOR === $selector ? '0.5em' : null;
+                               if ( ! empty( $block_type ) ) {
+                                       $block_gap_value = _wp_array_get( $block_type->supports, array( 'spacing', 'blockGap', '__experimentalDefault' ), null );
+                               }
+                       } else {
+                               $block_gap_value = static::get_property_value( $node, array( 'spacing', 'blockGap' ) );
+                       }
+
+                       // Support split row / column values and concatenate to a shorthand value.
+                       if ( is_array( $block_gap_value ) ) {
+                               if ( isset( $block_gap_value['top'] ) && isset( $block_gap_value['left'] ) ) {
+                                       $gap_row         = static::get_property_value( $node, array( 'spacing', 'blockGap', 'top' ) );
+                                       $gap_column      = static::get_property_value( $node, array( 'spacing', 'blockGap', 'left' ) );
+                                       $block_gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column;
+                               } else {
+                                       // Skip outputting gap value if not all sides are provided.
+                                       $block_gap_value = null;
+                               }
+                       }
+
+                       // If the block should have custom gap, add the gap styles.
+                       if ( null !== $block_gap_value && false !== $block_gap_value && '' !== $block_gap_value ) {
+                               foreach ( $layout_definitions as $layout_definition_key => $layout_definition ) {
+                                       // Allow outputting fallback gap styles for flex layout type when block gap support isn't available.
+                                       if ( ! $has_block_gap_support && 'flex' !== $layout_definition_key ) {
+                                               continue;
+                                       }
+
+                                       $class_name    = sanitize_title( _wp_array_get( $layout_definition, array( 'className' ), false ) );
+                                       $spacing_rules = _wp_array_get( $layout_definition, array( 'spacingStyles' ), array() );
+
+                                       if (
+                                               ! empty( $class_name ) &&
+                                               ! empty( $spacing_rules )
+                                       ) {
+                                               foreach ( $spacing_rules as $spacing_rule ) {
+                                                       $declarations = array();
+                                                       if (
+                                                               isset( $spacing_rule['selector'] ) &&
+                                                               preg_match( $layout_selector_pattern, $spacing_rule['selector'] ) &&
+                                                               ! empty( $spacing_rule['rules'] )
+                                                       ) {
+                                                               // Iterate over each of the styling rules and substitute non-string values such as `null` with the real `blockGap` value.
+                                                               foreach ( $spacing_rule['rules'] as $css_property => $css_value ) {
+                                                                       $current_css_value = is_string( $css_value ) ? $css_value : $block_gap_value;
+                                                                       if ( static::is_safe_css_declaration( $css_property, $current_css_value ) ) {
+                                                                               $declarations[] = array(
+                                                                                       'name'  => $css_property,
+                                                                                       'value' => $current_css_value,
+                                                                               );
+                                                                       }
+                                                               }
+
+                                                               if ( ! $has_block_gap_support ) {
+                                                                       // For fallback gap styles, use lower specificity, to ensure styles do not unintentionally override theme styles.
+                                                                       $format          = static::ROOT_BLOCK_SELECTOR === $selector ? ':where(.%2$s%3$s)' : ':where(%1$s.%2$s%3$s)';
+                                                                       $layout_selector = sprintf(
+                                                                               $format,
+                                                                               $selector,
+                                                                               $class_name,
+                                                                               $spacing_rule['selector']
+                                                                       );
+                                                               } else {
+                                                                       $format          = static::ROOT_BLOCK_SELECTOR === $selector ? '%s .%s%s' : '%s.%s%s';
+                                                                       $layout_selector = sprintf(
+                                                                               $format,
+                                                                               $selector,
+                                                                               $class_name,
+                                                                               $spacing_rule['selector']
+                                                                       );
+                                                               }
+                                                               $block_rules .= static::to_ruleset( $layout_selector, $declarations );
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               // Output base styles.
+               if (
+                       static::ROOT_BLOCK_SELECTOR === $selector
+               ) {
+                       $valid_display_modes = array( 'block', 'flex', 'grid' );
+                       foreach ( $layout_definitions as $layout_definition ) {
+                               $class_name       = sanitize_title( _wp_array_get( $layout_definition, array( 'className' ), false ) );
+                               $base_style_rules = _wp_array_get( $layout_definition, array( 'baseStyles' ), array() );
+
+                               if (
+                                       ! empty( $class_name ) &&
+                                       ! empty( $base_style_rules )
+                               ) {
+                                       // Output display mode. This requires special handling as `display` is not exposed in `safe_style_css_filter`.
+                                       if (
+                                               ! empty( $layout_definition['displayMode'] ) &&
+                                               is_string( $layout_definition['displayMode'] ) &&
+                                               in_array( $layout_definition['displayMode'], $valid_display_modes, true )
+                                       ) {
+                                               $layout_selector = sprintf(
+                                                       '%s .%s',
+                                                       $selector,
+                                                       $class_name
+                                               );
+                                               $block_rules    .= static::to_ruleset(
+                                                       $layout_selector,
+                                                       array(
+                                                               array(
+                                                                       'name'  => 'display',
+                                                                       'value' => $layout_definition['displayMode'],
+                                                               ),
+                                                       )
+                                               );
+                                       }
+
+                                       foreach ( $base_style_rules as $base_style_rule ) {
+                                               $declarations = array();
+
+                                               if (
+                                                       isset( $base_style_rule['selector'] ) &&
+                                                       preg_match( $layout_selector_pattern, $base_style_rule['selector'] ) &&
+                                                       ! empty( $base_style_rule['rules'] )
+                                               ) {
+                                                       foreach ( $base_style_rule['rules'] as $css_property => $css_value ) {
+                                                               if ( static::is_safe_css_declaration( $css_property, $css_value ) ) {
+                                                                       $declarations[] = array(
+                                                                               'name'  => $css_property,
+                                                                               'value' => $css_value,
+                                                                       );
+                                                               }
+                                                       }
+
+                                                       $layout_selector = sprintf(
+                                                               '%s .%s%s',
+                                                               $selector,
+                                                               $class_name,
+                                                               $base_style_rule['selector']
+                                                       );
+                                                       $block_rules    .= static::to_ruleset( $layout_selector, $declarations );
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return $block_rules;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Creates new rulesets as classes for each preset value such as:
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         *   .has-value-color {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1327,15 +1598,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 5.9.0 Added the `$settings` and `$properties` parameters.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @since 6.1.0 Added the `$theme_json` parameter.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @since 6.1.0 Added `$theme_json`, `$selector`, and `$use_root_padding` parameters.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @param array $styles    Styles to process.
-        * @param array $settings  Theme settings.
-        * @param array $properties Properties metadata.
-        * @param array $theme_json Theme JSON array.
-        * @return array Returns the modified $declarations.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @param array   $styles Styles to process.
+        * @param array   $settings Theme settings.
+        * @param array   $properties Properties metadata.
+        * @param array   $theme_json Theme JSON array.
+        * @param string  $selector The style block selector.
+        * @param boolean $use_root_padding Whether to add custom properties at root level.
+        * @return array  Returns the modified $declarations.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null, $selector = null, $use_root_padding = null ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( null === $properties ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $properties = static::PROPERTIES_METADATA;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1345,9 +1618,24 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return $declarations;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $root_variable_duplicates = array();
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 foreach ( $properties as $css_property => $value_path ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $value = static::get_property_value( $styles, $value_path, $theme_json );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        if ( str_starts_with( $css_property, '--wp--style--root--' ) && ( static::ROOT_BLOCK_SELECTOR !== $selector || ! $use_root_padding ) ) {
+                               continue;
+                       }
+                       // Root-level padding styles don't currently support strings with CSS shorthand values.
+                       // This may change: https://github.com/WordPress/gutenberg/issues/40132.
+                       if ( '--wp--style--root--padding' === $css_property && is_string( $value ) ) {
+                               continue;
+                       }
+
+                       if ( str_starts_with( $css_property, '--wp--style--root--' ) && $use_root_padding ) {
+                               $root_variable_duplicates[] = substr( $css_property, strlen( '--wp--style--root--' ) );
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         // Look up protected properties, keyed by value path.
</span><span class="cx" style="display: block; padding: 0 10px">                        // Skip protected properties that are explicitly set to `null`.
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( is_array( $value_path ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1372,6 +1660,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // If a variable value is added to the root, the corresponding property should be removed.
+               foreach ( $root_variable_duplicates as $duplicate ) {
+                       $discard = array_search( $duplicate, array_column( $declarations, 'name' ), true );
+                       if ( is_numeric( $discard ) ) {
+                               array_splice( $declarations, $discard, 1 );
+                       }
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 return $declarations;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1396,7 +1692,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return string|array Style property value.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        protected static function get_property_value( $styles, $path, $theme_json = null ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $value = _wp_array_get( $styles, $path, '' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $value = _wp_array_get( $styles, $path );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /*
</span><span class="cx" style="display: block; padding: 0 10px">                 * This converts references to a path to the value at that path
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1429,7 +1725,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( '' === $value || is_array( $value ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( is_array( $value ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         return $value;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1622,11 +1918,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $duotone_selector = $selectors[ $name ]['duotone'];
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $feature_selectors = null;
+                       if ( isset( $selectors[ $name ]['features'] ) ) {
+                               $feature_selectors = $selectors[ $name ]['features'];
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         $nodes[] = array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'name'     => $name,
</span><span class="cx" style="display: block; padding: 0 10px">                                'path'     => array( 'styles', 'blocks', $name ),
</span><span class="cx" style="display: block; padding: 0 10px">                                'selector' => $selector,
</span><span class="cx" style="display: block; padding: 0 10px">                                'duotone'  => $duotone_selector,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                'features' => $feature_selectors,
</ins><span class="cx" style="display: block; padding: 0 10px">                         );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1659,16 +1961,49 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 6.1.0
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @param array $block_metadata Meta data about the block to get styles for.
-        * @return array Styles for the block.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @param array $block_metadata Metadata about the block to get styles for.
+        *
+        * @return string Styles for the block.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><span class="cx" style="display: block; padding: 0 10px">        public function get_styles_for_block( $block_metadata ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $node             = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
+               $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments'];
+               $selector         = $block_metadata['selector'];
+               $settings         = _wp_array_get( $this->theme_json, array( 'settings' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         /*
+                * Process style declarations for block support features the current
+                * block contains selectors for. Values for a feature with a custom
+                * selector are filtered from the theme.json node before it is
+                * processed as normal.
+               */
+               $feature_declarations = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $selector = $block_metadata['selector'];
-               $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( ! empty( $block_metadata['features'] ) ) {
+                       foreach ( $block_metadata['features'] as $feature_name => $feature_selector ) {
+                               if ( ! empty( $node[ $feature_name ] ) ) {
+                                       // Create temporary node containing only the feature data
+                                       // to leverage existing `compute_style_properties` function.
+                                       $feature = array( $feature_name => $node[ $feature_name ] );
+                                       // Generate the feature's declarations only.
+                                       $new_feature_declarations = static::compute_style_properties( $feature, $settings, null, $this->theme_json );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        // Merge new declarations with any that already exist for
+                                       // the feature selector. This may occur when multiple block
+                                       // support features use the same custom selector.
+                                       if ( isset( $feature_declarations[ $feature_selector ] ) ) {
+                                               $feature_declarations[ $feature_selector ] = array_merge( $feature_declarations[ $feature_selector ], $new_feature_declarations );
+                                       } else {
+                                               $feature_declarations[ $feature_selector ] = $new_feature_declarations;
+                                       }
+
+                                       // Remove the feature from the block's node now the
+                                       // styles will be included under the feature level selector.
+                                       unset( $node[ $feature_name ] );
+                               }
+                       }
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 /*
</span><span class="cx" style="display: block; padding: 0 10px">                 * Get a reference to element name from path.
</span><span class="cx" style="display: block; padding: 0 10px">                 * $block_metadata['path'] = array( 'styles','elements','link' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1709,9 +2044,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        array_key_exists( $current_element, static::VALID_ELEMENT_PSEUDO_SELECTORS )
</span><span class="cx" style="display: block; padding: 0 10px">                        && in_array( $pseudo_selector, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ], true )
</span><span class="cx" style="display: block; padding: 0 10px">                ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json, $selector, $use_root_padding );
</ins><span class="cx" style="display: block; padding: 0 10px">                 } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json, $selector, $use_root_padding );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $block_rules = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1728,18 +2063,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                /*
-                * Reset default browser margin on the root body element.
-                * This is set on the root selector **before** generating the ruleset
-                * from the `theme.json`. This is to ensure that if the `theme.json` declares
-                * `margin` in its `spacing` declaration for the `body` element then these
-                * user-generated values take precedence in the CSS cascade.
-                * @link https://github.com/WordPress/gutenberg/issues/36147.
-                */
-               if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
-                       $block_rules .= 'body { margin: 0; }';
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 // 2. Generate and append the rules that use the general selector.
</span><span class="cx" style="display: block; padding: 0 10px">                $block_rules .= static::to_ruleset( $selector, $declarations );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1749,16 +2072,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $block_rules     .= static::to_ruleset( $selector_duotone, $declarations_duotone );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
-                       $block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
-                       $block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
-                       $block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // 4. Generate Layout block gap styles.
+               if (
+                       static::ROOT_BLOCK_SELECTOR !== $selector &&
+                       ! empty( $block_metadata['name'] )
+               ) {
+                       $block_rules .= $this->get_layout_styles( $block_metadata );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
-                       if ( $has_block_gap_support ) {
-                               $block_rules .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
-                               $block_rules .= '.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // 5. Generate and append the feature level rulesets.
+               foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) {
+                       $block_rules .= static::to_ruleset( $feature_selector, $individual_feature_declarations );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return $block_rules;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1765,6 +2089,81 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Outputs the CSS for layout rules on the root.
+        *
+        * @since 6.1.0
+        *
+        * @param string $selector The root node selector.
+        * @param array  $block_metadata The metadata for the root block.
+        * @return string The additional root rules CSS.
+        */
+       public function get_root_layout_rules( $selector, $block_metadata ) {
+               $css              = '';
+               $settings         = _wp_array_get( $this->theme_json, array( 'settings' ) );
+               $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments'];
+
+               /*
+               * Reset default browser margin on the root body element.
+               * This is set on the root selector **before** generating the ruleset
+               * from the `theme.json`. This is to ensure that if the `theme.json` declares
+               * `margin` in its `spacing` declaration for the `body` element then these
+               * user-generated values take precedence in the CSS cascade.
+               * @link https://github.com/WordPress/gutenberg/issues/36147.
+               */
+               $css .= 'body { margin: 0;';
+
+               /*
+               * If there are content and wide widths in theme.json, output them
+               * as custom properties on the body element so all blocks can use them.
+               */
+               if ( isset( $settings['layout']['contentSize'] ) || isset( $settings['layout']['wideSize'] ) ) {
+                       $content_size = isset( $settings['layout']['contentSize'] ) ? $settings['layout']['contentSize'] : $settings['layout']['wideSize'];
+                       $content_size = static::is_safe_css_declaration( 'max-width', $content_size ) ? $content_size : 'initial';
+                       $wide_size    = isset( $settings['layout']['wideSize'] ) ? $settings['layout']['wideSize'] : $settings['layout']['contentSize'];
+                       $wide_size    = static::is_safe_css_declaration( 'max-width', $wide_size ) ? $wide_size : 'initial';
+                       $css         .= '--wp--style--global--content-size: ' . $content_size . ';';
+                       $css         .= '--wp--style--global--wide-size: ' . $wide_size . ';';
+               }
+
+               $css .= ' }';
+
+               if ( $use_root_padding ) {
+                       // Top and bottom padding are applied to the outer block container.
+                       $css .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }';
+                       // Right and left padding are applied to the first container with `.has-global-padding` class.
+                       $css .= '.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
+                       // Nested containers with `.has-global-padding` class do not get padding.
+                       $css .= '.has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }';
+                       // Alignfull children of the container with left and right padding have negative margins so they can still be full width.
+                       $css .= '.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }';
+                       // The above rule is negated for alignfull children of nested containers.
+                       $css .= '.has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }';
+                       // Some of the children of alignfull blocks without content width should also get padding: text blocks and non-alignfull container blocks.
+                       $css .= '.has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
+                       // The above rule also has to be negated for blocks inside nested `.has-global-padding` blocks.
+                       $css .= '.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }';
+               }
+
+               $css .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
+               $css .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
+               $css .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
+
+               $block_gap_value       = _wp_array_get( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ), '0.5em' );
+               $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
+               if ( $has_block_gap_support ) {
+                       $block_gap_value = static::get_property_value( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ) );
+                       $css            .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
+                       $css            .= ".wp-site-blocks > * + * { margin-block-start: $block_gap_value; }";
+
+                       // For backwards compatibility, ensure the legacy block gap CSS variable is still available.
+                       $css .= "$selector { --wp--style--block-gap: $block_gap_value; }";
+               }
+               $css .= $this->get_layout_styles( $block_metadata );
+
+               return $css;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * For metadata values that can either be booleans or paths to booleans, gets the value.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * ```php
</span></span></pre></div>
<a id="trunksrcwpincludesglobalstylesandsettingsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/global-styles-and-settings.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/global-styles-and-settings.php      2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/global-styles-and-settings.php        2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -107,7 +107,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();
</span><span class="cx" style="display: block; padding: 0 10px">        if ( empty( $types ) && ! $supports_theme_json ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $types = array( 'variables', 'presets' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $types = array( 'variables', 'presets', 'base-layout-styles' );
</ins><span class="cx" style="display: block; padding: 0 10px">         } elseif ( empty( $types ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $types = array( 'variables', 'styles', 'presets' );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span></span></pre></div>
<a id="trunksrcwpincludesthemejson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/theme.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/theme.json  2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/theme.json    2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,6 +2,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        "version": 2,
</span><span class="cx" style="display: block; padding: 0 10px">        "settings": {
</span><span class="cx" style="display: block; padding: 0 10px">                "appearanceTools": false,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                "useRootPaddingAwareAlignments": false,
</ins><span class="cx" style="display: block; padding: 0 10px">                 "border": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "color": false,
</span><span class="cx" style="display: block; padding: 0 10px">                        "radius": false,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -12,8 +13,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        "background": true,
</span><span class="cx" style="display: block; padding: 0 10px">                        "custom": true,
</span><span class="cx" style="display: block; padding: 0 10px">                        "customDuotone": true,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        "customGradient": true,
-                       "defaultDuotone": true,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 "customGradient": true,
+                       "defaultDuotone": true,
</ins><span class="cx" style="display: block; padding: 0 10px">                         "defaultGradients": true,
</span><span class="cx" style="display: block; padding: 0 10px">                        "defaultPalette": true,
</span><span class="cx" style="display: block; padding: 0 10px">                        "duotone": [
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -185,11 +186,158 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        ],
</span><span class="cx" style="display: block; padding: 0 10px">                        "text": true
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                "layout": {
+                       "definitions": {
+                               "default": {
+                                       "name": "default",
+                                       "slug": "flow",
+                                       "className": "is-layout-flow",
+                                       "baseStyles": [
+                                               {
+                                                       "selector": " > .alignleft",
+                                                       "rules": {
+                                                               "float": "left",
+                                                               "margin-inline-start": "0",
+                                                               "margin-inline-end": "2em"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > .alignright",
+                                                       "rules": {
+                                                               "float": "right",
+                                                               "margin-inline-start": "2em",
+                                                               "margin-inline-end": "0"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > .aligncenter",
+                                                       "rules": {
+                                                               "margin-left": "auto !important",
+                                                               "margin-right": "auto !important"
+                                                       }
+                                               }
+                                       ],
+                                       "spacingStyles": [
+                                               {
+                                                       "selector": " > *",
+                                                       "rules": {
+                                                               "margin-block-start": "0",
+                                                               "margin-block-end": "0"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > * + *",
+                                                       "rules": {
+                                                               "margin-block-start": null,
+                                                               "margin-block-end": "0"
+                                                       }
+                                               }
+                                       ]
+                               },
+                               "constrained": {
+                                       "name": "constrained",
+                                       "slug": "constrained",
+                                       "className": "is-layout-constrained",
+                                       "baseStyles": [
+                                               {
+                                                       "selector": " > .alignleft",
+                                                       "rules": {
+                                                               "float": "left",
+                                                               "margin-inline-start": "0",
+                                                               "margin-inline-end": "2em"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > .alignright",
+                                                       "rules": {
+                                                               "float": "right",
+                                                               "margin-inline-start": "2em",
+                                                               "margin-inline-end": "0"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > .aligncenter",
+                                                       "rules": {
+                                                               "margin-left": "auto !important",
+                                                               "margin-right": "auto !important"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
+                                                       "rules": {
+                                                               "max-width": "var(--wp--style--global--content-size)",
+                                                               "margin-left": "auto !important",
+                                                               "margin-right": "auto !important"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > .alignwide",
+                                                       "rules": {
+                                                               "max-width": "var(--wp--style--global--wide-size)"
+                                                       }
+                                               }
+                                       ],
+                                       "spacingStyles": [
+                                               {
+                                                       "selector": " > *",
+                                                       "rules": {
+                                                               "margin-block-start": "0",
+                                                               "margin-block-end": "0"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > * + *",
+                                                       "rules": {
+                                                               "margin-block-start": null,
+                                                               "margin-block-end": "0"
+                                                       }
+                                               }
+                                       ]
+                               },
+                               "flex": {
+                                       "name": "flex",
+                                       "slug": "flex",
+                                       "className": "is-layout-flex",
+                                       "displayMode": "flex",
+                                       "baseStyles": [
+                                               {
+                                                       "selector": "",
+                                                       "rules": {
+                                                               "flex-wrap": "wrap",
+                                                               "align-items": "center"
+                                                       }
+                                               },
+                                               {
+                                                       "selector": " > *",
+                                                       "rules": {
+                                                               "margin": "0"
+                                                       }
+                                               }
+                                       ],
+                                       "spacingStyles": [
+                                               {
+                                                       "selector": "",
+                                                       "rules": {
+                                                               "gap": null
+                                                       }
+                                               }
+                                       ]
+                               }
+                       }
+               },
</ins><span class="cx" style="display: block; padding: 0 10px">                 "spacing": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "blockGap": null,
</span><span class="cx" style="display: block; padding: 0 10px">                        "margin": false,
</span><span class="cx" style="display: block; padding: 0 10px">                        "padding": false,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        "units": [ "px", "em", "rem", "vh", "vw", "%" ]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 "customSpacingSize": true,
+                       "units": [ "px", "em", "rem", "vh", "vw", "%" ],
+                       "spacingScale": {
+                               "operator": "*",
+                               "increment": 1.5,
+                               "steps": 7,
+                               "mediumStep": 1.5,
+                               "unit": "rem"
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 },
</span><span class="cx" style="display: block; padding: 0 10px">                "typography": {
</span><span class="cx" style="display: block; padding: 0 10px">                        "customFontSize": true,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -240,6 +388,39 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        },
</span><span class="cx" style="display: block; padding: 0 10px">        "styles": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                "spacing": { "blockGap": "24px" }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         "elements": {
+                       "button": {
+                               "color": {
+                                       "text": "#fff",
+                                       "background": "#32373c"
+                               },
+                               "spacing": {
+                                       "padding": "calc(0.667em + 2px) calc(1.333em + 2px)"
+                               },
+                               "typography": {
+                                       "fontSize": "inherit",
+                                       "fontFamily": "inherit",
+                                       "lineHeight": "inherit",
+                                       "textDecoration": "none"
+                               },
+                               "border": {
+                                       "width": "0"
+                               }
+                       },
+                       "link": {
+                               "typography": {
+                                       "textDecoration": "underline"
+                               }
+                       }
+               },
+               "spacing": {
+                       "blockGap": "24px",
+                       "padding": {
+                               "top": "0px",
+                               "right": "0px",
+                               "bottom": "0px",
+                               "left": "0px"
+                       }
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludesthemephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/theme.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/theme.php   2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/theme.php     2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4027,6 +4027,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                )
</span><span class="cx" style="display: block; padding: 0 10px">        );
</span><span class="cx" style="display: block; padding: 0 10px">        register_theme_feature(
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                'disable-layout-styles',
+               array(
+                       'description'  => __( 'Whether the theme disables generated layout styles.' ),
+                       'show_in_rest' => true,
+               )
+       );
+       register_theme_feature(
</ins><span class="cx" style="display: block; padding: 0 10px">                 'editor-color-palette',
</span><span class="cx" style="display: block; padding: 0 10px">                array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'type'         => 'array',
</span></span></pre></div>
<a id="trunktestsphpunittestsblockseditorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/blocks/editor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/blocks/editor.php       2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/tests/phpunit/tests/blocks/editor.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -202,7 +202,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        public function test_get_default_block_editor_settings() {
</span><span class="cx" style="display: block; padding: 0 10px">                $settings = get_default_block_editor_settings();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertCount( 18, $settings );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertCount( 19, $settings );
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertFalse( $settings['alignWide'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertIsArray( $settings['allowedMimeTypes'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertTrue( $settings['allowedBlockTypes'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -249,6 +249,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( $settings['disableCustomColors'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( $settings['disableCustomFontSizes'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( $settings['disableCustomGradients'] );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertFalse( $settings['disableLayoutStyles'] );
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertFalse( $settings['enableCustomLineHeight'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( $settings['enableCustomSpacing'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( $settings['enableCustomUnits'] );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestthemescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php     2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php       2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -396,6 +396,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'dark-editor-style', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'disable-custom-font-sizes', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'disable-custom-gradients', $theme_supports );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $this->assertArrayHasKey( 'disable-layout-styles', $theme_supports );
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertArrayHasKey( 'editor-color-palette', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'editor-font-sizes', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'editor-gradient-presets', $theme_supports );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -406,7 +407,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'responsive-embeds', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'title-tag', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'wp-block-styles', $theme_supports );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertCount( 21, $theme_supports );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertCount( 22, $theme_supports );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="trunktestsphpunitteststhemewpThemeJsonphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/theme/wpThemeJson.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/theme/wpThemeJson.php   2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/tests/phpunit/tests/theme/wpThemeJson.php     2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -423,7 +423,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $expected = 'body { margin: 0; }body{--wp--style--block-gap: 1em;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1em; }body { --wp--style--block-gap: 1em; }';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -544,6 +544,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><span class="cx" style="display: block; padding: 0 10px">                                        ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        'spacing'  => array(
+                                               'blockGap' => '24px',
+                                       ),
</ins><span class="cx" style="display: block; padding: 0 10px">                                 ),
</span><span class="cx" style="display: block; padding: 0 10px">                                'misc'     => 'value',
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -550,7 +553,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $variables = 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $styles    = 'body { margin: 0; }body{color: var(--wp--preset--color--grey);}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }a:where(:not(.wp-element-button)){background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a:where(:not(.wp-element-button)){color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button)){background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a:where(:not(.wp-element-button)){bac
 kground-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $styles    = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{color: var(--wp--preset--color--grey);}a:where(:not(.wp-element-button)){background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a:where(:not(.wp-element-button)){color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button)){background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a:where(:not(.wp-element-button)){back
 ground-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $presets   = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-small-font-family{font-family: var(--wp--preset--font-family--small) !important;}.has-big-font-family{font-family: var(--wp--preset--font-family--big) !important;}';
</span><span class="cx" style="display: block; padding: 0 10px">                $all       = $variables . $styles . $presets;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $all, $theme_json->get_stylesheet() );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2675,8 +2678,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        'blocks'  => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                'core/group' => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'spacing' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                'margin'   => 'valid value',
-                                                               'blockGap' => 'invalid value',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         'margin'  => 'valid value',
+                                                               'display' => 'none',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><span class="cx" style="display: block; padding: 0 10px">                                        ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2989,7 +2992,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $expected = 'body { margin: 0; }body{background-color: #ffffff;color: #000000;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-element-button, .wp-block-button__link{background-color: #000000;color: #ffffff;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;color: #000000;}.wp-element-button, .wp-block-button__link{background-color: #000000;color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3021,7 +3024,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $expected = 'body { margin: 0; }body{background-color: #ffffff;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;}.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3053,7 +3056,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $expected = 'body { margin: 0; }body{background-color: #ffffff;color: #ffffff;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;color: #ffffff;}.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3077,8 +3080,417 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $expected = 'body { margin: 0; }body{background-color: #ffffff;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @dataProvider data_get_layout_definitions
+        *
+        * @ticket 56467
+        *
+        * @param array $layout_definitions Layout definitions as stored in core theme.json.
+        */
+       public function test_get_stylesheet_generates_layout_styles( $layout_definitions ) {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => WP_Theme_JSON::LATEST_SCHEMA,
+                               'settings' => array(
+                                       'layout'  => array(
+                                               'definitions' => $layout_definitions,
+                                       ),
+                                       'spacing' => array(
+                                               'blockGap' => true,
+                                       ),
+                               ),
+                               'styles'   => array(
+                                       'spacing' => array(
+                                               'blockGap' => '1em',
+                                       ),
+                               ),
+                       ),
+                       'default'
+               );
+
+               // Results also include root site blocks styles.
+               $this->assertSame(
+                       'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1em; }body { --wp--style--block-gap: 1em; }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: 1em;margin-block-end: 0;}body .is-layout-flex{gap: 1em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}',
+                       $theme_json->get_stylesheet( array( 'styles' ) )
+               );
+       }
+
+       /**
+        * @dataProvider data_get_layout_definitions
+        *
+        * @ticket 56467
+        *
+        * @param array $layout_definitions Layout definitions as stored in core theme.json.
+        */
+       public function test_get_stylesheet_generates_layout_styles_with_spacing_presets( $layout_definitions ) {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => WP_Theme_JSON::LATEST_SCHEMA,
+                               'settings' => array(
+                                       'layout'  => array(
+                                               'definitions' => $layout_definitions,
+                                       ),
+                                       'spacing' => array(
+                                               'blockGap' => true,
+                                       ),
+                               ),
+                               'styles'   => array(
+                                       'spacing' => array(
+                                               'blockGap' => 'var:preset|spacing|60',
+                                       ),
+                               ),
+                       ),
+                       'default'
+               );
+
+               // Results also include root site blocks styles.
+               $this->assertSame(
+                       'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var(--wp--preset--spacing--60); }body { --wp--style--block-gap: var(--wp--preset--spacing--60); }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}body .is-layout-flex{gap: var(--wp--preset--spacing--60);}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !importa
 nt;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}',
+                       $theme_json->get_stylesheet( array( 'styles' ) )
+               );
+       }
+
+       /**
+        * @dataProvider data_get_layout_definitions
+        *
+        * @ticket 56467
+        *
+        * @param array $layout_definitions Layout definitions as stored in core theme.json.
+        */
+       public function test_get_stylesheet_generates_fallback_gap_layout_styles( $layout_definitions ) {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => WP_Theme_JSON::LATEST_SCHEMA,
+                               'settings' => array(
+                                       'layout'  => array(
+                                               'definitions' => $layout_definitions,
+                                       ),
+                                       'spacing' => array(
+                                               'blockGap' => null,
+                                       ),
+                               ),
+                               'styles'   => array(
+                                       'spacing' => array(
+                                               'blockGap' => '1em',
+                                       ),
+                               ),
+                       ),
+                       'default'
+               );
+               $stylesheet = $theme_json->get_stylesheet( array( 'styles' ) );
+
+               // Results also include root site blocks styles.
+               $this->assertSame(
+                       'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}',
+                       $stylesheet
+               );
+       }
+
+       /**
+        * @dataProvider data_get_layout_definitions
+        *
+        * @ticket 56467
+        *
+        * @param array $layout_definitions Layout definitions as stored in core theme.json.
+        */
+       public function test_get_stylesheet_generates_base_fallback_gap_layout_styles( $layout_definitions ) {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => WP_Theme_JSON::LATEST_SCHEMA,
+                               'settings' => array(
+                                       'layout'  => array(
+                                               'definitions' => $layout_definitions,
+                                       ),
+                                       'spacing' => array(
+                                               'blockGap' => null,
+                                       ),
+                               ),
+                       ),
+                       'default'
+               );
+               $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) );
+
+               // Note the `base-layout-styles` includes a fallback gap for the Columns block for backwards compatibility.
+               $this->assertSame(
+                       ':where(.is-layout-flex){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}',
+                       $stylesheet
+               );
+       }
+
+       /**
+        * @dataProvider data_get_layout_definitions
+        *
+        * @ticket 56467
+        *
+        * @param array $layout_definitions Layout definitions as stored in core theme.json.
+        */
+       public function test_get_stylesheet_skips_layout_styles( $layout_definitions ) {
+               add_theme_support( 'disable-layout-styles' );
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => WP_Theme_JSON::LATEST_SCHEMA,
+                               'settings' => array(
+                                       'layout'  => array(
+                                               'definitions' => $layout_definitions,
+                                       ),
+                                       'spacing' => array(
+                                               'blockGap' => null,
+                                       ),
+                               ),
+                       ),
+                       'default'
+               );
+               $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) );
+               remove_theme_support( 'disable-layout-styles' );
+
+               // All Layout styles should be skipped.
+               $this->assertSame(
+                       '',
+                       $stylesheet
+               );
+       }
+
+       /**
+        * @dataProvider data_get_layout_definitions
+        *
+        * @ticket 56467
+        *
+        * @param array $layout_definitions Layout definitions as stored in core theme.json.
+        */
+       public function test_get_stylesheet_generates_valid_block_gap_values_and_skips_null_or_false_values( $layout_definitions ) {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => WP_Theme_JSON::LATEST_SCHEMA,
+                               'settings' => array(
+                                       'layout'  => array(
+                                               'definitions' => $layout_definitions,
+                                       ),
+                                       'spacing' => array(
+                                               'blockGap' => true,
+                                       ),
+                               ),
+                               'styles'   => array(
+                                       'spacing' => array(
+                                               'blockGap' => '1rem',
+                                       ),
+                                       'blocks'  => array(
+                                               'core/post-content' => array(
+                                                       'color' => array(
+                                                               'text' => 'gray', // This value should not render block layout styles.
+                                                       ),
+                                               ),
+                                               'core/social-links' => array(
+                                                       'spacing' => array(
+                                                               'blockGap' => '0', // This value should render block layout gap as zero.
+                                                       ),
+                                               ),
+                                               'core/buttons'      => array(
+                                                       'spacing' => array(
+                                                               'blockGap' => 0, // This value should render block layout gap as zero.
+                                                       ),
+                                               ),
+                                               'core/columns'      => array(
+                                                       'spacing' => array(
+                                                               'blockGap' => false, // This value should be ignored. The block will use the global layout value.
+                                                       ),
+                                               ),
+                                       ),
+                               ),
+                       ),
+                       'default'
+               );
+
+               $this->assertEquals(
+                       'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1rem; }body { --wp--style--block-gap: 1rem; }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: 1rem;margin-block-end: 0;}body .is-layout-flex{gap: 1rem;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}.wp-bl
 ock-post-content{color: gray;}.wp-block-social-links.is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links.is-layout-flow > * + *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links.is-layout-flex{gap: 0;}.wp-block-buttons.is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons.is-layout-flow > * + *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons.is-layout-flex{gap: 0;}',
+                       $theme_json->get_stylesheet()
+               );
+       }
+
+       /**
+        * Data provider for layout tests.
+        *
+        * @ticket 56467
+        *
+        * @return array
+        */
+       public function data_get_layout_definitions() {
+               return array(
+                       'layout definitions' => array(
+                               array(
+                                       'default' => array(
+                                               'name'          => 'default',
+                                               'slug'          => 'flow',
+                                               'className'     => 'is-layout-flow',
+                                               'baseStyles'    => array(
+                                                       array(
+                                                               'selector' => ' > .alignleft',
+                                                               'rules'    => array(
+                                                                       'float'               => 'left',
+                                                                       'margin-inline-start' => '0',
+                                                                       'margin-inline-end'   => '2em',
+                                                               ),
+                                                       ),
+                                                       array(
+                                                               'selector' => ' > .alignright',
+                                                               'rules'    => array(
+                                                                       'float'               => 'right',
+                                                                       'margin-inline-start' => '2em',
+                                                                       'margin-inline-end'   => '0',
+                                                               ),
+                                                       ),
+                                                       array(
+                                                               'selector' => ' > .aligncenter',
+                                                               'rules'    => array(
+                                                                       'margin-left'  => 'auto !important',
+                                                                       'margin-right' => 'auto !important',
+                                                               ),
+                                                       ),
+                                               ),
+                                               'spacingStyles' => array(
+                                                       array(
+                                                               'selector' => ' > *',
+                                                               'rules'    => array(
+                                                                       'margin-block-start' => '0',
+                                                                       'margin-block-end'   => '0',
+                                                               ),
+                                                       ),
+                                                       array(
+                                                               'selector' => ' > * + *',
+                                                               'rules'    => array(
+                                                                       'margin-block-start' => null,
+                                                                       'margin-block-end'   => '0',
+                                                               ),
+                                                       ),
+                                               ),
+                                       ),
+                                       'flex'    => array(
+                                               'name'          => 'flex',
+                                               'slug'          => 'flex',
+                                               'className'     => 'is-layout-flex',
+                                               'displayMode'   => 'flex',
+                                               'baseStyles'    => array(
+                                                       array(
+                                                               'selector' => '',
+                                                               'rules'    => array(
+                                                                       'flex-wrap'   => 'wrap',
+                                                                       'align-items' => 'center',
+                                                               ),
+                                                       ),
+                                               ),
+                                               'spacingStyles' => array(
+                                                       array(
+                                                               'selector' => '',
+                                                               'rules'    => array(
+                                                                       'gap' => null,
+                                                               ),
+                                                       ),
+                                               ),
+                                       ),
+                               ),
+                       ),
+               );
+       }
+
+       /**
+        * @ticket 56467
+        */
+       function test_get_styles_for_block_with_padding_aware_alignments() {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => 2,
+                               'styles'   => array(
+                                       'spacing' => array(
+                                               'padding' => array(
+                                                       'top'    => '10px',
+                                                       'right'  => '12px',
+                                                       'bottom' => '10px',
+                                                       'left'   => '12px',
+                                               ),
+                                       ),
+                               ),
+                               'settings' => array(
+                                       'useRootPaddingAwareAlignments' => true,
+                               ),
+                       )
+               );
+
+               $metadata = array(
+                       'path'     => array(
+                               '0' => 'styles',
+                       ),
+                       'selector' => 'body',
+               );
+
+               $expected    = 'body { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }.has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) > .alignful
 l:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}';
+               $root_rules  = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata );
+               $style_rules = $theme_json->get_styles_for_block( $metadata );
+               $this->assertSame( $expected, $root_rules . $style_rules );
+       }
+
+       /**
+        * @ticket 56467
+        */
+       function test_get_styles_for_block_without_padding_aware_alignments() {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version' => 2,
+                               'styles'  => array(
+                                       'spacing' => array(
+                                               'padding' => array(
+                                                       'top'    => '10px',
+                                                       'right'  => '12px',
+                                                       'bottom' => '10px',
+                                                       'left'   => '12px',
+                                               ),
+                                       ),
+                               ),
+                       )
+               );
+
+               $metadata = array(
+                       'path'     => array(
+                               '0' => 'styles',
+                       ),
+                       'selector' => 'body',
+               );
+
+               $expected    = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}';
+               $root_rules  = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata );
+               $style_rules = $theme_json->get_styles_for_block( $metadata );
+               $this->assertSame( $expected, $root_rules . $style_rules );
+       }
+
+       /**
+        * @ticket 56467
+        */
+       function test_get_styles_for_block_with_content_width() {
+               $theme_json = new WP_Theme_JSON(
+                       array(
+                               'version'  => 2,
+                               'settings' => array(
+                                       'layout' => array(
+                                               'contentSize' => '800px',
+                                               'wideSize'    => '1000px',
+                                       ),
+                               ),
+                       )
+               );
+
+               $metadata = array(
+                       'path'     => array(
+                               '0' => 'settings',
+                       ),
+                       'selector' => 'body',
+               );
+
+               $expected    = 'body { margin: 0;--wp--style--global--content-size: 800px;--wp--style--global--wide-size: 1000px; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
+               $root_rules  = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata );
+               $style_rules = $theme_json->get_styles_for_block( $metadata );
+               $this->assertSame( $expected, $root_rules . $style_rules );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>

</body>
</html>