<?php
/**
 * Keep site-chrome CSS out of the block editor canvas.
 *
 * WordPress core deliberately injects the Customizer's "Additional CSS" into
 * the block editor so the preview matches the front end (see
 * wp-includes/block-editor.php: "Get any additional css from the customizer").
 * That is usually helpful — content styles (galleries, buttons, captions, font
 * sizes, form styling) then look right while editing.
 *
 * The problem: this site's Customizer sheet is site-wide, so it also contains
 * layout rules for the theme's page CHROME — `.entry-content-wrap{padding:0}`,
 * `.site-container, …, .entry-hero-layout-contained{padding:0}`,
 * `body.page .content-bg{box-shadow:…}`, header/nav rules. The block editor
 * renders its own wrappers using several of those same class names, so the
 * rules landed on the editor UI and visibly broke it — most obviously the post
 * title stretching edge-to-edge with almost no padding.
 *
 * Fix: filter core's injected copy, dropping only rules whose selectors target
 * site chrome. Everything content-level is kept, so the editor preview stays
 * faithful. The front end is untouched — core still outputs the full sheet
 * there; this only rewrites the editor's in-memory copy.
 *
 * @package Kadence-Child
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Selectors that belong to the site's chrome (header, nav, hero, page
 * containers) rather than to post content. Rules matching any of these are
 * dropped from the editor canvas.
 */
function bw_editor_chrome_selector_pattern() {
	return '/'
		. 'entry-content-wrap|site-container|site-header-row|site-footer-row|entry-hero'
		. '|content-bg|content-style-unboxed|content-title-style'
		. '|masthead|transparent-header|main-navigation|header-navigation'
		. '|nav--toggle-sub|nav-drop-title-wrap|mobile-toggle'
		. '|bw_login_link|bw_apply_menu_mobile|bw-apply-menu'
		. '|single-entry|article\.entry|bw-phero'
		. '/i';
}

/**
 * Strip site-chrome rules from a stylesheet, keeping everything else.
 *
 * Handles one level of nesting so rules inside an @media block are filtered
 * individually (and the at-rule is dropped entirely if nothing survives).
 *
 * @param string $css Stylesheet source.
 * @return string
 */
function bw_editor_strip_chrome_rules( $css ) {
	$css = (string) $css;
	if ( '' === trim( $css ) ) {
		return $css;
	}

	$chrome = bw_editor_chrome_selector_pattern();
	$out    = '';

	if ( ! preg_match_all( '/([^{}]+)\{((?:[^{}]|\{[^{}]*\})*)\}/s', $css, $blocks, PREG_SET_ORDER ) ) {
		return $css;
	}

	foreach ( $blocks as $block ) {
		$prelude = trim( $block[1] );
		$body    = $block[2];

		if ( '' === $prelude ) {
			continue;
		}

		// At-rule (@media/@supports): filter the rules nested inside it.
		if ( '@' === $prelude[0] ) {
			$inner = '';
			if ( preg_match_all( '/([^{}]+)\{([^}]*)\}/s', $body, $rules, PREG_SET_ORDER ) ) {
				foreach ( $rules as $rule ) {
					if ( ! preg_match( $chrome, $rule[1] ) ) {
						$inner .= trim( $rule[1] ) . '{' . trim( $rule[2] ) . '}';
					}
				}
			}
			if ( '' !== $inner ) {
				$out .= $prelude . '{' . $inner . '}';
			}
			continue;
		}

		if ( ! preg_match( $chrome, $prelude ) ) {
			$out .= $prelude . '{' . trim( $body ) . '}';
		}
	}

	return $out;
}

/**
 * Align the block editor's post title with the content column.
 *
 * Kadence paints the page's background behind
 * `.edit-post-visual-editor__post-title-wrapper` so the editor previews the
 * real page background. That wrapper spans the whole canvas and has no
 * horizontal padding, and the title itself sits inside a plugin-injected
 * `.ai-title-toolbar-wrapper` that is width-limited but NOT centred. The result:
 * the title rendered hard against the left edge of a full-width tinted band
 * while every content block below was centred — which is what read as "broken".
 *
 * Centring the inner wrapper and giving the outer one the theme's content edge
 * padding lines the title up with the content column. Verified in the live
 * editor: title, its wrapper and the first content block all land on the same
 * left edge and width.
 *
 * !important is needed because Kadence's own rule uses a higher-specificity
 * `.admin-color-… …:not(.specificity)` selector.
 */
add_filter(
	'block_editor_settings_all',
	function ( $settings ) {
		$settings['styles'][] = array(
			'css' => '
.edit-post-visual-editor__post-title-wrapper,
.editor-visual-editor__post-title-wrapper {
	padding-left: var(--global-content-edge-padding, 1.5rem) !important;
	padding-right: var(--global-content-edge-padding, 1.5rem) !important;
}
.ai-title-toolbar-wrapper {
	margin-left: auto !important;
	margin-right: auto !important;
}',
		);
		return $settings;
	},
	9999
);

/**
 * Rewrite core's Customizer-CSS entry in the editor settings.
 *
 * Runs very late so it sees the entry core added. Matches on content (the entry
 * whose css is exactly wp_get_custom_css()) rather than on array position,
 * which is not guaranteed.
 */
add_filter(
	'block_editor_settings_all',
	function ( $settings ) {
		if ( empty( $settings['styles'] ) || ! is_array( $settings['styles'] ) ) {
			return $settings;
		}

		$custom = (string) wp_get_custom_css();
		if ( '' === trim( $custom ) ) {
			return $settings;
		}

		foreach ( $settings['styles'] as $i => $style ) {
			if ( ! isset( $style['css'] ) || (string) $style['css'] !== $custom ) {
				continue;
			}
			$settings['styles'][ $i ]['css'] = bw_editor_strip_chrome_rules( $custom );
		}

		return $settings;
	},
	9999
);
