Index: src/wp-admin/css/customize-controls.css
===================================================================
--- src/wp-admin/css/customize-controls.css	(revision 29471)
+++ src/wp-admin/css/customize-controls.css	(working copy)
@@ -105,7 +105,7 @@
 #customize-theme-controls .control-section.open .accordion-section-title,
 #customize-theme-controls .control-section .accordion-section-title:focus {
 	color: #222;
-	background: #f5f5f5;
+	background: #eee;
 }
 
 .js .control-section:hover .accordion-section-title,
@@ -112,7 +112,7 @@
 .js .control-section .accordion-section-title:hover,
 .js .control-section.open .accordion-section-title,
 .js .control-section .accordion-section-title:focus {
-	background: #f5f5f5;
+	background: #eee;
 }
 
 #customize-theme-controls .control-section:hover > .accordion-section-title:after,
@@ -132,7 +132,7 @@
 }
 
 #customize-theme-controls .control-section:last-of-type.open,
-#customize-theme-controls .control-section:last-of-type .accordion-section-title {
+#customize-theme-controls .control-section:last-of-type > .accordion-section-title {
 	border-bottom-color: #ddd;
 }
 
@@ -151,7 +151,7 @@
 	color: #555;
 	width: 38px;
 	height: 100%;
-	margin: -11px -10px -11px 0; /* compensate for positioning */
+	margin: -11px -10px -11px 0;
 	line-height: 45px;
 	padding-left: 5px;
 	border-left: 1px solid #eee;
@@ -166,8 +166,9 @@
 #customize-theme-controls .control-section.control-panel > h3.accordion-section-title:hover:after {
 	background: #ddd;
 	color: #000;
-	border: 1px solid #d9d9d9;
-	border-right: none;
+	border-left: 1px solid #d9d9d9;
+	border-top: 1px solid #d9d9d9;
+	border-bottom: 1px solid #d9d9d9;
 	margin-top: -12px;
 	line-height: 44px;
 	z-index: 1;
Index: src/wp-admin/customize.php
===================================================================
--- src/wp-admin/customize.php	(revision 29471)
+++ src/wp-admin/customize.php	(working copy)
@@ -161,12 +161,9 @@
 
 			<div id="customize-theme-controls"><ul>
 				<?php
-				foreach ( $wp_customize->panels() as $panel ) {
-					$panel->maybe_render();
+				foreach ( $wp_customize->containers() as $container ) {
+					$container->maybe_render();
 				}
-				foreach ( $wp_customize->sections() as $section ) {
-					$section->maybe_render();
-				}
 				?>
 			</ul></div>
 		</div>
Index: src/wp-includes/class-wp-customize-container.php
===================================================================
--- src/wp-includes/class-wp-customize-container.php	(revision 0)
+++ src/wp-includes/class-wp-customize-container.php	(working copy)
@@ -0,0 +1,314 @@
+<?php
+/**
+ * Customize Container Class.
+ *
+ * A UI container for Customizer components, managed by the WP_Customize_Manager.
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.0.0
+ */
+abstract class WP_Customize_Container {
+
+	/**
+	 * WP_Customize_Manager instance.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var WP_Customize_Manager
+	 */
+	public $manager;
+
+	/**
+	 * Unique identifier.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var string
+	 */
+	public $id;
+
+	/**
+	 * Priority of the container, which determines display order.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var integer
+	 */
+	public $priority = 160;
+
+	/**
+	 * Capability required for the container.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var string
+	 */
+	public $capability = 'edit_theme_options';
+
+	/**
+	 * Theme feature support requied for the container.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var string|array
+	 */
+	public $theme_supports = '';
+
+	/**
+	 * Title to show in the UI.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var string
+	 */
+	public $title = '';
+
+	/**
+	 * Description to show in the UI.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var string
+	 */
+	public $description = '';
+
+	/**
+	 * Constructor.
+	 *
+	 * Any supplied $args override class property defaults.
+	 *
+	 * @since 4.0.0
+	 *
+	 * @param WP_Customize_Manager $manager Customizer bootstrap instance.
+	 * @param string               $id      An specific ID for the container.
+	 * @param array                $args    Container arguments.
+	 */
+	public function __construct( $manager, $id, $args = array() ) {
+		$keys = array_keys( get_object_vars( $this ) );
+		foreach ( $keys as $key ) {
+			if ( isset( $args[ $key ] ) )
+				$this->$key = $args[ $key ];
+		}
+
+		$this->manager = $manager;
+		$this->id = $id;
+
+		return $this;
+	}
+
+	/**
+	 * Checks required user capabilities and whether the theme has the
+	 * feature support required by the container.
+	 *
+	 * @since 4.0.0
+	 *
+	 * @return bool False if theme doesn't support the container or user doesn't have the capability.
+	 */
+	public final function check_capabilities() {
+		if ( $this->capability && ! call_user_func_array( 'current_user_can', (array) $this->capability ) )
+			return false;
+
+		if ( $this->theme_supports && ! call_user_func_array( 'current_theme_supports', (array) $this->theme_supports ) )
+			return false;
+
+		return true;
+	}
+
+	/**
+	 * Check capabilities and render the container.
+	 *
+	 * @since 4.0.0
+	 */
+	public final function maybe_render() {
+		if ( ! $this->check_capabilities() )
+			return;
+
+		/**
+		 * Fires before rendering a Customizer section (or panel).
+		 *
+		 * @since 3.4.0
+		 *
+		 * @param WP_Customize_Section $this WP_Customize_Section instance.
+		 */
+		do_action( 'customize_render_section', $this );
+
+		/**
+		 * Fires before rendering a specific Customizer section (or panel).
+		 *
+		 * The dynamic portion of the hook name, $this->id, refers to the ID
+		 * of the specific Customizer container to be rendered.
+		 *
+		 * @since 3.4.0
+		 */
+		do_action( "customize_render_section_{$this->id}" );
+
+		$this->render();
+	}
+
+	/**
+	 * Render the container, and the objects that have been added to it.
+	 *
+	 * @since 4.0.0
+	 */
+	abstract protected function render();
+}
+
+
+/**
+ * Customize Panel Class.
+ *
+ * A UI container for sections, managed by the WP_Customize_Manager.
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.0.0
+ */
+class WP_Customize_Panel extends WP_Customize_Container {
+
+	/**
+	 * Customizer sections for this panel.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var array
+	 */
+	public $sections;
+
+	/**
+	 * Constructor.
+	 *
+	 * Any supplied $args override class property defaults.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 *
+	 * @param WP_Customize_Manager $manager Customizer bootstrap instance.
+	 * @param string               $id      An specific ID of the section.
+	 * @param array                $args    Optional. Section arguments. Default empty array.
+	 */
+	public function __construct( $manager, $id, $args = array() ) {
+		parent::__construct( $manager, $id, $args );
+
+		$this->sections = array(); // Users cannot customize the $sections array.
+
+		return $this;
+	}
+
+	/**
+	 * Render the panel, and the sections that have been added to it.
+	 *
+	 * @since 4.0.0
+	 * @access protected
+	 */
+	protected function render() {
+		?>
+		<li id="accordion-panel-<?php echo esc_attr( $this->id ); ?>" class="control-section control-panel accordion-section">
+			<h3 class="accordion-section-title" tabindex="0">
+				<?php echo esc_html( $this->title ); ?>
+				<span class="screen-reader-text"><?php _e( 'Press return or enter to open panel' ); ?></span>
+			</h3>
+			<span class="control-panel-back" tabindex="-1"><span class="screen-reader-text"><?php _e( 'Back' ); ?></span></span>
+			<ul class="accordion-sub-container control-panel-content">
+				<li class="accordion-section control-section<?php if ( empty( $this->description ) ) echo ' cannot-expand'; ?>">
+					<div class="accordion-section-title" tabindex="0">
+						<span class="preview-notice"><?php
+							/* translators: %s is the site/panel title in the Customizer */
+							echo sprintf( __( 'You are customizing %s' ), '<strong class="panel-title">' . esc_html( $this->title ) . '</strong>' );
+						?></span>
+					</div>
+					<?php if ( ! empty( $this->description ) ) : ?>
+						<div class="accordion-section-content description">
+							<?php echo $this->description; ?>
+						</div>
+					<?php endif; ?>
+				</li>
+				<?php
+				foreach ( $this->sections as $section ) {
+					$section->maybe_render();
+				}
+				?>
+			</ul>
+		</li>
+		<?php
+	}
+}
+
+
+/**
+ * Customize Section Class.
+ *
+ * A UI container for controls, managed by the WP_Customize_Manager.
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 3.4.0
+ */
+class WP_Customize_Section extends WP_Customize_Container {
+
+	/**
+	 * Panel in which to show the section, making it a sub-section.
+	 *
+	 * @since 4.0.0
+	 * @access public
+	 * @var string
+	 */
+	public $panel = '';
+
+	/**
+	 * Customizer controls for this section.
+	 *
+	 * @since 3.4.0
+	 * @access public
+	 * @var array
+	 */
+	public $controls;
+
+	/**
+	 * Constructor.
+	 *
+	 * Any supplied $args override class property defaults.
+	 *
+	 * @since 3.4.0
+	 *
+	 * @param WP_Customize_Manager $manager Customizer bootstrap instance.
+	 * @param string               $id      An specific ID of the section.
+	 * @param array                $args    Section arguments.
+	 */
+	public function __construct( $manager, $id, $args = array() ) {
+		parent::__construct( $manager, $id, $args );
+
+		$this->controls = array(); // Users cannot customize the $controls array.
+
+		return $this;
+	}
+
+	/**
+	 * Render the section, and the controls that have been added to it.
+	 *
+	 * @since 3.4.0
+	 */
+	protected function render() {
+		$classes = 'control-section accordion-section';
+		if ( $this->panel ) {
+			$classes .= ' control-subsection';
+		}
+		?>
+		<li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
+			<h3 class="accordion-section-title" tabindex="0">
+				<?php echo esc_html( $this->title ); ?>
+				<span class="screen-reader-text"><?php _e( 'Press return or enter to expand' ); ?></span>
+			</h3>
+			<ul class="accordion-section-content">
+				<?php if ( ! empty( $this->description ) ) : ?>
+				<li><p class="description customize-section-description"><?php echo $this->description; ?></p></li>
+				<?php endif; ?>
+				<?php
+				foreach ( $this->controls as $control )
+					$control->maybe_render();
+				?>
+			</ul>
+		</li>
+		<?php
+	}
+}
Index: src/wp-includes/class-wp-customize-manager.php
===================================================================
--- src/wp-includes/class-wp-customize-manager.php	(revision 29471)
+++ src/wp-includes/class-wp-customize-manager.php	(working copy)
@@ -43,10 +43,11 @@
 	 */
 	public $widgets;
 
-	protected $settings = array();
-	protected $panels   = array();
-	protected $sections = array();
-	protected $controls = array();
+	protected $settings   = array();
+	protected $containers = array();
+	protected $panels     = array();
+	protected $sections   = array();
+	protected $controls   = array();
 
 	protected $nonce_tick;
 
@@ -66,7 +67,7 @@
 	 */
 	public function __construct() {
 		require( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
-		require( ABSPATH . WPINC . '/class-wp-customize-section.php' );
+		require( ABSPATH . WPINC . '/class-wp-customize-container.php' );
 		require( ABSPATH . WPINC . '/class-wp-customize-control.php' );
 		require( ABSPATH . WPINC . '/class-wp-customize-widgets.php' );
 
@@ -305,6 +306,17 @@
 	}
 
 	/**
+	 * Get the registered containers.
+	 *
+	 * @since 4.0.0
+	 *
+	 * @return array
+	 */
+	public function containers() {
+		return $this->containers;
+	}
+
+	/**
 	 * Get the registered sections.
 	 *
 	 * @since 3.4.0
@@ -890,6 +902,10 @@
 			$panels[] = $panel;
 		}
 		$this->panels = $panels;
+
+		// Sort panels and top-level sections together.
+		$this->containers = array_merge( $this->panels, $this->sections );
+		uasort( $this->containers, array( $this, '_cmp_priority' ) );
 	}
 
 	/**
