Index: /trunk/src/wp-includes/block-supports/states.php
===================================================================
--- /trunk/src/wp-includes/block-supports/states.php	(revision 62513)
+++ /trunk/src/wp-includes/block-supports/states.php	(revision 62514)
@@ -297,4 +297,89 @@
 
 /**
+ * Generates all element selectors for a block root selector.
+ *
+ * @since 7.1.0
+ *
+ * @param string $root_selector The block root CSS selector.
+ * @return string[] Element selectors keyed by element name.
+ */
+function wp_get_block_state_element_selectors( $root_selector ) {
+	if ( ! is_string( $root_selector ) || '' === trim( $root_selector ) ) {
+		return array();
+	}
+
+	$block_selectors   = wp_split_selector_list( $root_selector );
+	$element_selectors = array();
+
+	foreach ( WP_Theme_JSON::ELEMENTS as $element_name => $element_selector ) {
+		$selectors = array();
+
+		foreach ( $block_selectors as $block_selector ) {
+			$block_selector = trim( $block_selector );
+			if ( '' === $block_selector ) {
+				continue;
+			}
+
+			if ( $block_selector === $element_selector ) {
+				$selectors = array( $element_selector );
+				break;
+			}
+
+			$selector_prefix = "$block_selector ";
+			if ( ! str_contains( $element_selector, ',' ) ) {
+				$selectors[] = $selector_prefix . $element_selector;
+				continue;
+			}
+
+			$prepended_selectors = array();
+			foreach ( wp_split_selector_list( $element_selector ) as $selector ) {
+				$prepended_selectors[] = $selector_prefix . $selector;
+			}
+			$selectors[] = implode( ',', $prepended_selectors );
+		}
+
+		if ( ! empty( $selectors ) ) {
+			$element_selectors[ $element_name ] = implode( ',', $selectors );
+		}
+	}
+
+	return $element_selectors;
+}
+
+/**
+ * Adds a compiled state style rule to a rule list.
+ *
+ * @since 7.1.0
+ *
+ * @param array       $css_rules   Style rules.
+ * @param string      $state       Pseudo-state selector.
+ * @param string|null $selector    Block, feature, or element selector.
+ * @param array       $style       Style object.
+ * @param string|null $rules_group Optional CSS grouping rule, e.g. a media query.
+ */
+function wp_add_block_state_style_rule( &$css_rules, $state, $selector, $style, $rules_group = null ) {
+	if ( empty( $style ) || ! is_array( $style ) ) {
+		return;
+	}
+
+	$compiled = wp_style_engine_get_styles(
+		wp_normalize_state_style_for_css_output( $style )
+	);
+
+	if ( empty( $compiled['declarations'] ) ) {
+		return;
+	}
+
+	$css_rules[] = array(
+		'state'        => $state,
+		'selector'     => $selector,
+		'declarations' => $compiled['declarations'],
+	);
+	if ( ! empty( $rules_group ) ) {
+		$css_rules[ count( $css_rules ) - 1 ]['rules_group'] = $rules_group;
+	}
+}
+
+/**
  * Builds compiled state style rules, preserving the selector each rule targets.
  *
@@ -318,19 +403,11 @@
 
 		foreach ( wp_get_state_style_groups( $state_style, $block_selectors ) as $group ) {
-			$style    = wp_get_state_style_with_fallback_dimension_styles( $group['style'] );
-			$compiled = wp_style_engine_get_styles(
-				wp_normalize_state_style_for_css_output( $style )
+			wp_add_block_state_style_rule(
+				$css_rules,
+				$state,
+				$group['selector'],
+				$group['style'],
+				$rules_group
 			);
-
-			if ( ! empty( $compiled['declarations'] ) ) {
-				$css_rules[] = array(
-					'state'        => $state,
-					'selector'     => $group['selector'],
-					'declarations' => $compiled['declarations'],
-				);
-				if ( ! empty( $rules_group ) ) {
-					$css_rules[ count( $css_rules ) - 1 ]['rules_group'] = $rules_group;
-				}
-			}
 		}
 	}
@@ -502,4 +579,55 @@
 				)
 			);
+		}
+
+		if (
+			! empty( $style[ $breakpoint ]['elements'] ) &&
+			is_array( $style[ $breakpoint ]['elements'] )
+		) {
+			$element_selectors = wp_get_block_state_element_selectors(
+				wp_get_block_css_selector( $block_type )
+			);
+
+			foreach ( $style[ $breakpoint ]['elements'] as $element_name => $element_style ) {
+				if (
+					empty( $element_style ) ||
+					! is_array( $element_style ) ||
+					empty( $element_selectors[ $element_name ] )
+				) {
+					continue;
+				}
+
+				$element_pseudo_states = WP_Theme_JSON::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ]
+					?? array();
+				$root_element_style    = wp_get_root_state_style(
+					$element_style,
+					$element_pseudo_states
+				);
+
+				wp_add_block_state_style_rule(
+					$css_rules,
+					'',
+					$element_selectors[ $element_name ],
+					$root_element_style,
+					$media_query
+				);
+
+				foreach ( $element_pseudo_states as $pseudo_state ) {
+					if (
+						empty( $element_style[ $pseudo_state ] ) ||
+						! is_array( $element_style[ $pseudo_state ] )
+					) {
+						continue;
+					}
+
+					wp_add_block_state_style_rule(
+						$css_rules,
+						$pseudo_state,
+						$element_selectors[ $element_name ],
+						$element_style[ $pseudo_state ],
+						$media_query
+					);
+				}
+			}
 		}
 
Index: /trunk/tests/phpunit/tests/block-supports/states.php
===================================================================
--- /trunk/tests/phpunit/tests/block-supports/states.php	(revision 62513)
+++ /trunk/tests/phpunit/tests/block-supports/states.php	(revision 62514)
@@ -961,4 +961,47 @@
 		$this->assertStringContainsString(
 			'@media (width <= 480px){.' . $matches[0] . '{color:#ff0000 !important;}}',
+			$actual_stylesheet
+		);
+	}
+
+	/**
+	 * Tests that a responsive element color generates media-query scoped CSS.
+	 *
+	 * @covers ::wp_render_block_states_support
+	 *
+	 * @ticket 65164
+	 */
+	public function test_responsive_element_color_generates_media_query_scoped_css() {
+		$this->ensure_block_registered( 'core/group' );
+
+		$block_content = '<div class="wp-block-group"><p><a href="#">Link</a></p></div>';
+		$block         = array(
+			'blockName' => 'core/group',
+			'attrs'     => array(
+				'style' => array(
+					'mobile' => array(
+						'elements' => array(
+							'link' => array(
+								'color' => array(
+									'text' => '#00ff00',
+								),
+							),
+						),
+					),
+				),
+			),
+		);
+
+		$actual = wp_render_block_states_support( $block_content, $block );
+
+		$this->assertMatchesRegularExpression(
+			'/^<div class="wp-block-group (wp-states-[a-f0-9]{8})"><p><a href="#">Link<\/a><\/p><\/div>$/',
+			$actual
+		);
+		preg_match( '/wp-states-[a-f0-9]{8}/', $actual, $matches );
+		$actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) );
+
+		$this->assertStringContainsString(
+			'@media (width <= 480px){.' . $matches[0] . ' a:where(:not(.wp-element-button)){color:#00ff00 !important;}}',
 			$actual_stylesheet
 		);
