diff --git src/wp-admin/css/customize-controls.css src/wp-admin/css/customize-controls.css
index c76a6e5..3bd297f 100644
--- src/wp-admin/css/customize-controls.css
+++ src/wp-admin/css/customize-controls.css
@@ -455,6 +455,161 @@ body {
 	-webkit-overflow-scrolling: touch;
 }
 
+/** Header control **/
+
+#customize-control-header_image .current {
+	margin-bottom: 8px;
+}
+
+#customize-control-header_image .uploaded {
+	margin-bottom: 18px;
+}
+
+/* Header control: current image container */
+
+#customize-control-header_image .current .container {
+	overflow: hidden;
+	border-radius: 2px;
+}
+
+#customize-control-header_image .placeholder {
+	width: 100%;
+	position: relative;
+	background: #262626;
+	text-align: center;
+	cursor: default;
+}
+
+#customize-control-header_image .inner {
+	display: none;
+	position: absolute;
+	width: 100%;
+	height: 18px;
+	margin-top: -9px;
+	top: 50%;
+}
+
+body:not(.blue) #customize-control-header_image .inner {
+	color: #eee;
+}
+
+/* Header control: overlay "close" button */
+
+#customize-control-header_image .header-view {
+	position: relative;
+}
+
+#customize-control-header_image .uploaded .header-view .close {
+	visibility: hidden;
+	position: absolute;
+	top: 10px;
+	right: 10px;
+	z-index: 1;
+	width: 20px;
+	height: 20px;
+	background: url('../images/close-button.light.png');
+	background-size: 20px 20px;
+	text-indent: -999px;
+}
+
+#customize-control-header_image .header-view:hover .close {
+	visibility: visible;
+}
+
+/* Header control: randomiz(s)er */
+
+#customize-control-header_image .random.placeholder {
+	cursor: pointer;
+	border-radius: 2px;
+	height: 40px;
+}
+
+#customize-control-header_image .random .inner {
+	display: block;
+}
+
+#customize-control-header_image .dice {
+	font-size: 16px;
+	vertical-align: -1px;
+}
+
+#customize-control-header_image .placeholder:hover .dice {
+	-webkit-animation: dice-color-change 3s infinite;
+	-moz-animation: dice-color-change 3s infinite;
+	-ms-animation: dice-color-change 3s infinite;
+	animation: dice-color-change 3s infinite;
+}
+
+@-webkit-keyframes dice-color-change {
+	0% { color: #d4b146; }
+	50% { color: #ef54b0; }
+	75% { color: #7190d3; }
+	100% { color: #d4b146; }
+}
+
+@-moz-keyframes dice-color-change {
+	0% { color: #d4b146; }
+	50% { color: #ef54b0; }
+	75% { color: #7190d3; }
+	100% { color: #d4b146; }
+}
+
+@-ms-keyframes dice-color-change {
+	0% { color: #d4b146; }
+	50% { color: #ef54b0; }
+	75% { color: #7190d3; }
+	100% { color: #d4b146; }
+}
+
+@keyframes dice-color-change {
+	0% { color: #d4b146; }
+	50% { color: #ef54b0; }
+	75% { color: #7190d3; }
+	100% { color: #d4b146; }
+}
+
+/* Header control: actions and choices */
+
+#customize-control-header_image .actions {
+	margin-bottom: 32px;
+}
+
+#customize-control-header_image .choice {
+	position: relative;
+	display: block;
+	margin-bottom: 9px;
+}
+
+#customize-control-header_image .choice.random:before {
+	position: absolute;
+	content: attr(data-label);
+	left: 0;
+	top: 0;
+}
+
+#customize-control-header_image .uploaded div:last-child > .choice {
+	margin-bottom: 0;
+}
+
+#customize-control-header_image .choices hr {
+	visibility: hidden;
+}
+
+#customize-control-header_image img {
+	width: 100%;
+	border-radius: 2px;
+}
+
+#customize-control-header_image .remove {
+	float: left;
+	margin-right: 3px;
+}
+
+#customize-control-header_image .new {
+	float: right;
+}
+
+
 /** Handle cheaters. */
 body.cheatin {
 	min-width: 0;
diff --git src/wp-admin/custom-header.php src/wp-admin/custom-header.php
index 633dc65..1c6ee7e 100644
--- src/wp-admin/custom-header.php
+++ src/wp-admin/custom-header.php
@@ -43,7 +43,7 @@ class Custom_Image_Header {
 	var $default_headers = array();
 
 	/**
-	 * Holds custom headers uploaded by the user
+	 * Holds custom headers uploaded by the user.
 	 *
 	 * @var array
 	 * @since 3.2.0
@@ -61,6 +61,14 @@ class Custom_Image_Header {
 	var $page = '';
 
 	/**
+	 * ID of the attachment image from which we are cropping a new one.
+	 *
+	 * @var int
+	 * @since 3.9.0
+	 */
+	public $parent_attachment_id;
+
+	/**
 	 * Constructor - Register administration header callback.
 	 *
 	 * @since 2.1.0
@@ -72,6 +80,15 @@ class Custom_Image_Header {
 		$this->admin_header_callback = $admin_header_callback;
 		$this->admin_image_div_callback = $admin_image_div_callback;
 
+		if ( current_theme_supports( 'custom-header' ) ) {
+			add_action( 'customize_save_after', array( $this, 'set_last_used' ) );
+			add_action( 'wp_ajax_header_crop', array( $this, 'ajax_header_crop' ) );
+			add_action( 'wp_ajax_header_add', array( $this, 'ajax_header_add' ) );
+			add_action( 'wp_ajax_header_remove', array( __CLASS__, 'ajax_header_remove' ) );
+			add_filter( 'wp_prepare_attachment_for_js', array( $this, 'add_parent_attachment_js' ) , 11, 3);
+			add_filter( 'wp_header_image_attachment_metadata', array( $this, 'add_parent_attachment_id' ) , 11, 1);
+		}
+
 		add_action( 'admin_menu', array( $this, 'init' ) );
 	}
 
@@ -93,6 +110,7 @@ class Custom_Image_Header {
 		add_action("admin_head-$page", array($this, 'js'), 50);
 		if ( $this->admin_header_callback )
 			add_action("admin_head-$page", $this->admin_header_callback, 51);
+
 	}
 
 	/**
@@ -819,29 +837,10 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
 		$attachment_id = absint( $_POST['attachment_id'] );
 		$original = get_attached_file($attachment_id);
 
-
-		$max_width = 0;
-		// For flex, limit size of image displayed to 1500px unless theme says otherwise
-		if ( current_theme_supports( 'custom-header', 'flex-width' ) )
-			$max_width = 1500;
-
-		if ( current_theme_supports( 'custom-header', 'max-width' ) )
-			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
-		$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );
-
-		if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width )
-			$dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) );
-		elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) )
-			$dst_height = absint( $_POST['height'] );
-		else
-			$dst_height = get_theme_support( 'custom-header', 'height' );
-
-		if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width )
-			$dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) );
-		elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) )
-			$dst_width = absint( $_POST['width'] );
-		else
-			$dst_width = get_theme_support( 'custom-header', 'width' );
+		extract( $this->get_header_dimensions( array(
+			'width' => $_POST['width'],
+			'height' => $_POST['height'],
+		) ) );
 
 		if ( empty( $_POST['skip-cropping'] ) )
 			$cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height );
@@ -856,31 +855,17 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
 		/** This filter is documented in wp-admin/custom-header.php */
 		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
 
-		$parent = get_post($attachment_id);
-		$parent_url = $parent->guid;
-		$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
-
-		$size = @getimagesize( $cropped );
-		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
+		$object = $this->create_attachment_object( $cropped, $attachment_id );
 
-		// Construct the object array
-		$object = array(
-			'ID' => $attachment_id,
-			'post_title' => basename($cropped),
-			'post_content' => $url,
-			'post_mime_type' => $image_type,
-			'guid' => $url,
-			'context' => 'custom-header'
-		);
 		if ( ! empty( $_POST['create-new-attachment'] ) )
 			unset( $object['ID'] );
 
 		// Update the attachment
-		$attachment_id = wp_insert_attachment( $object, $cropped );
-		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $cropped ) );
+		$attachment_id = $this->insert_attachment( $object, $cropped );
 
 		$width = $dst_width;
 		$height = $dst_height;
+		$url = $object['guid'];
 		$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );
 
 		// cleanup
@@ -1041,4 +1026,208 @@ wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' ); ?>
 		set_theme_mod( 'header_image', $default );
 		set_theme_mod( 'header_image_data', (object) $default_data );
 	}
+
+	/**
+	 * Calculate dst_width and dst_height based on what the currently selected theme supports.
+	 *
+	 * @return array dst_height and dst_width of header image.
+	 */
+	final public function get_header_dimensions( $dimensions ) {
+		$max_width = 0;
+		$width = absint( $dimensions['width'] );
+		$height = absint( $dimensions['height'] );
+		$theme_height = get_theme_support( 'custom-header', 'height' );
+		$theme_width = get_theme_support( 'custom-header', 'width' );
+		$has_flex_width = current_theme_supports( 'custom-header', 'flex-width' );
+		$has_flex_height = current_theme_supports( 'custom-header', 'flex-height' );
+		$has_max_width = current_theme_supports( 'custom-header', 'max-width' ) ;
+		$dst = array();
+
+		// For flex, limit size of image displayed to 1500px unless theme says otherwise
+		if ( $has_flex_width )
+			$max_width = 1500;
+
+		if ( $has_max_width )
+			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
+		$max_width = max( $max_width, $theme_width );
+
+		if ( $has_flex_height && ( ! $has_flex_width || $width > $max_width ) )
+			$dst['dst_height'] = absint( $height * ( $max_width / $width ) );
+		elseif ( $has_flex_height && $has_flex_width )
+			$dst['dst_height'] = $height;
+		else
+			$dst['dst_height'] = $theme_height;
+
+		if ( $has_flex_width && ( ! $has_flex_height || $width > $max_width ) )
+			$dst['dst_width'] = absint( $width * ( $max_width / $width ) );
+		elseif ( $has_flex_width && $has_flex_height )
+			$dst['dst_width'] = $width;
+		else
+			$dst['dst_width'] = $theme_width;
+
+		return $dst;
+	}
+
+	/**
+	 * Create an attachment 'object'.
+	 *
+	 * @param string $cropped Cropped image URL.
+	 * @param int $parent_attachment_id Attachment ID of parent image.
+	 *
+	 * @return array Attachment object.
+	 */
+	final public function create_attachment_object( $cropped, $parent_attachment_id ) {
+		$parent = get_post( $parent_attachment_id );
+		$parent_url = $parent->guid;
+		$url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url );
+
+		$size = @getimagesize( $cropped );
+		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';
+
+		$object = array(
+			'ID' => $parent_attachment_id,
+			'post_title' => basename($cropped),
+			'post_content' => $url,
+			'post_mime_type' => $image_type,
+			'guid' => $url,
+			'context' => 'custom-header'
+		);
+
+		return $object;
+	}
+
+	/**
+	 * Insert an attachment & its metadata.
+	 *
+	 * @param array $object Attachment object.
+	 * @param string $cropped Cropped image URL.
+	 *
+	 * @return int Attachment ID.
+	 */
+	final public function insert_attachment( $object, $cropped ) {
+		$attachment_id = wp_insert_attachment( $object, $cropped );
+		$metadata = wp_generate_attachment_metadata( $attachment_id, $cropped );
+		/**
+		 * Allows us to insert custom meta data for an attachment.
+		 *
+		 */
+		$metadata = apply_filters( 'wp_header_image_attachment_metadata', $metadata );
+		wp_update_attachment_metadata( $attachment_id, $metadata );
+		return $attachment_id;
+	}
+
+	function ajax_check_nonce( $nonce, $attachment_id = null ) {
+		if ( ! isset( $nonce ) || ! wp_verify_nonce( $nonce,  'crop-image_' . $attachment_id ) ) {
+			wp_die( __( 'Cheatin&#8217; uh?' ) );
+		}
+	}
+
+	/**
+	 * Gets attachment uploaded by Media Manager, crops it, then saves it as a
+	 * new object. Returns JSON-encoded object details.
+	 */
+	function ajax_header_crop() {
+		$data = $_POST['data'];
+		$this->ajax_check_nonce( $data['nonces']['crop'], $data['id'] );
+		if ( ! current_theme_supports( 'custom-header', 'uploads' ) )
+			wp_die( __( 'Cheatin&#8217; uh?' ) );
+
+		if ( ! empty( $data['skip-cropping'] ) && ! ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) )
+			wp_die( __( 'Cheatin&#8217; uh?' ) );
+
+		$crop_details = $data['cropDetails'];
+
+		$dimensions = $this->get_header_dimensions( array(
+			'width' => $crop_details['width'],
+			'height' => $crop_details['height'],
+		) );
+
+		$attachment_id = absint( $data['id'] );
+
+		$cropped = wp_crop_image( $attachment_id, (int) $crop_details['x1'], (int) $crop_details['y1'], (int) $crop_details['width'], (int) $crop_details['height'], (int) $dimensions['dst_width'], (int) $dimensions['dst_height'] );
+
+		if ( ! $cropped || is_wp_error( $cropped ) )
+			wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
+
+		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication
+
+		$object = $this->create_attachment_object( $cropped, $attachment_id );
+
+		unset( $object['ID'] );
+
+		$this->parent_attachment_id = $attachment_id;
+		$new_attachment_id = $this->insert_attachment( $object, $cropped );
+
+		$object['attachment_id'] = $new_attachment_id;
+		$object['width']         = $dimensions['dst_width'];
+		$object['height']        = $dimensions['dst_height'];
+
+		echo json_encode($object);
+		die();
+	}
+
+	/**
+	 * Given an attachment ID for a header image, updates its "last used"
+	 * timestamp to now.
+	 *
+	 * Triggered when the user tries adds a new header image from the
+	 * Media Manager, even if s/he doesn't save that change.
+	 */
+	function ajax_header_add() {
+		$data = $_POST['data'];
+		check_ajax_referer( 'header-add', 'nonce' );
+
+		$attachment_id = absint( $data['attachment_id'] );
+		if ( $attachment_id < 1 )
+			return;
+
+		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
+		update_post_meta( $attachment_id, $key, time() );
+		update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
+
+		die();
+	}
+
+	/**
+	 * Given an attachment ID for a header image, unsets it as a user-uploaded
+	 * header image for the current theme.
+	 *
+	 * Triggered when the user clicks the overlay "X" button next to each image
+	 * choice in the Customizer's Header tool.
+	 */
+	function ajax_header_remove() {
+		$data = $_POST['data'];
+		check_ajax_referer( 'header-remove', 'nonce' );
+
+		$attachment_id = absint( $data['attachment_id'] );
+		if ( $attachment_id < 1 )
+			return;
+
+		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
+		delete_post_meta( $attachment_id, $key );
+		delete_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
+
+		die();
+	}
+
+	function set_last_used( $manager ) {
+		$data = $manager->get_setting( 'header_image_data' )->post_value();
+
+		if ( !isset( $data['attachment_id'] ) )
+			return;
+
+		$attachment_id = $data['attachment_id'];
+		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
+		update_post_meta( $attachment_id, $key, time() );
+	}
+
+	function add_parent_attachment_id( $metadata ) {
+		$metadata['parent_attachment_id'] = $this->parent_attachment_id;
+		return $metadata;
+	}
+
+	function add_parent_attachment_js($response, $attachment, $meta ){
+		$response['parentAttachmentId'] = isset( $meta['parent_attachment_id'] ) ? $meta['parent_attachment_id'] : 0;
+		return $response;
+	}
 }
diff --git src/wp-admin/images/close-button.light.png src/wp-admin/images/close-button.light.png
new file mode 100644
index 0000000..5da989b
Binary files /dev/null and src/wp-admin/images/close-button.light.png differ
diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
index 3a05ad4..d16a94b 100644
--- src/wp-admin/js/customize-controls.js
+++ src/wp-admin/js/customize-controls.js
@@ -306,6 +306,216 @@
 		}
 	});
 
+	api.HeaderControl = api.Control.extend({
+		ready: function() {
+			this.btnRemove        = $('.actions .remove');
+			this.btnNew           = $('.actions .new');
+
+			_.bindAll(this, 'openMM', 'removeImage');
+
+			this.btnNew.on( 'click', this.openMM );
+			this.btnRemove.on( 'click', this.removeImage );
+
+			api.HeaderTool.currentHeader = new api.HeaderTool.ImageModel();
+
+			new api.HeaderTool.CurrentView({
+				model: api.HeaderTool.currentHeader,
+				el: '.current .container'
+			});
+
+			new api.HeaderTool.ChoiceListView({
+				collection: api.HeaderTool.UploadsList = new api.HeaderTool.ChoiceList(),
+				el: '.choices .uploaded .list'
+			});
+
+			new api.HeaderTool.ChoiceListView({
+				collection: api.HeaderTool.DefaultsList = new api.HeaderTool.DefaultsList(),
+				el: '.choices .default .list'
+			});
+
+			api.HeaderTool.combinedList = api.HeaderTool.CombinedList = new api.HeaderTool.CombinedList([
+				api.HeaderTool.UploadsList,
+				api.HeaderTool.DefaultsList
+			]);
+		},
+
+		/**
+		 * Returns a set of options, computed from the attached image data and
+		 * theme-specific data, to be fed to the imgAreaSelect plugin in
+		 * wp.media.view.Cropper.
+		 *
+		 * @param {wp.media.model.Attachment} attachment
+		 * @param {wp.media.controller.Cropper} controller
+		 * @returns {Object} Options
+		 */
+		calculateImageSelectOptions: function(attachment, controller) {
+			var xInit = parseInt(_wpCustomizeHeader.data.width, 10),
+				yInit = parseInt(_wpCustomizeHeader.data.height, 10),
+				flexWidth = !! parseInt(_wpCustomizeHeader.data['flex-width'], 10),
+				flexHeight = !! parseInt(_wpCustomizeHeader.data['flex-height'], 10),
+				ratio, xImg, yImg, realHeight, realWidth,
+				imgSelectOptions;
+
+			realWidth = attachment.get('width');
+			realHeight = attachment.get('height');
+
+			this.headerImage = new api.HeaderTool.ImageModel();
+			this.headerImage.set({
+				themeWidth: xInit,
+				themeHeight: yInit,
+				themeFlexWidth: flexWidth,
+				themeFlexHeight: flexHeight,
+				imageWidth: realWidth,
+				imageHeight: realHeight
+			});
+
+			controller.set( 'canSkipCrop', ! this.headerImage.shouldBeCropped() );
+
+			ratio = xInit / yInit;
+			xImg = realWidth;
+			yImg = realHeight;
+
+			if ( xImg / yImg > ratio ) {
+				yInit = yImg;
+				xInit = yInit * ratio;
+			} else {
+				xInit = xImg;
+				yInit = xInit / ratio;
+			}
+
+			imgSelectOptions = {
+				handles: true,
+				keys: true,
+				instance: true,
+				persistent: true,
+				parent: this.$el,
+				imageWidth: realWidth,
+				imageHeight: realHeight,
+				x1: 0,
+				y1: 0,
+				x2: xInit,
+				y2: yInit
+			};
+
+			if (flexHeight === false && flexWidth === false) {
+				imgSelectOptions.aspectRatio = xInit + ':' + yInit;
+			}
+			if (flexHeight === false ) {
+				imgSelectOptions.maxHeight = yInit;
+			}
+			if (flexWidth === false ) {
+				imgSelectOptions.maxWidth = xInit;
+			}
+
+			return imgSelectOptions;
+		},
+
+		/**
+		 * Sets up and opens the Media Manager in order to select an image.
+		 * Depending on both the size of the image and the properties of the
+		 * current theme, a cropping step after selection may be required or
+		 * skippable.
+		 *
+		 * @param {event} event
+		 */
+		openMM: function(event) {
+			var title, suggestedWidth, suggestedHeight,
+				l10n = _wpMediaViewsL10n;
+
+			event.preventDefault();
+
+			suggestedWidth = l10n.suggestedWidth.replace('%d', _wpCustomizeHeader.data.width);
+			suggestedHeight = l10n.suggestedHeight.replace('%d', _wpCustomizeHeader.data.height);
+
+			title = {
+				html: l10n.chooseImage + ' <span class="suggested-dimensions">' +
+							suggestedWidth + ' ' + suggestedHeight +'</span>',
+				text: l10n.chooseImage
+			};
+
+			frame = wp.media({
+				title: title,
+				library: {
+					type: 'image'
+				},
+				button: {
+					text: l10n.selectAndCrop,
+					close: false
+				},
+				multiple: false,
+				imgSelectOptions: this.calculateImageSelectOptions
+			});
+
+			frame.states.add([new wp.media.controller.Cropper()]);
+
+			frame.on('select', function() {
+				frame.setState('cropper');
+			});
+
+			frame.on('cropped', function(croppedImage) {
+				var url = croppedImage.post_content,
+					attachmentId = croppedImage.attachment_id,
+					w = croppedImage.width,
+					h = croppedImage.height;
+				this.setImageFromURL(url, attachmentId, w, h);
+			}, this);
+
+			frame.on('skippedcrop', function(selection) {
+				var url = selection.get('url'),
+					w = selection.get('width'),
+					h = selection.get('height');
+				this.setImageFromURL(url, selection.id, w, h);
+			}, this);
+
+			frame.open();
+		},
+
+		/**
+		 * Creates a new wp.customize.HeaderTool.ImageModel from provided
+		 * header image data and inserts it into the user-uploaded headers
+		 * collection.
+		 *
+		 * @param {String} url
+		 * @param {Number} attachmentId
+		 * @param {Number} width
+		 * @param {Number} height
+		 */
+		setImageFromURL: function(url, attachmentId, width, height) {
+			var choice, data = {};
+
+			data.url = url;
+			data.thumbnail_url = url;
+
+			if (attachmentId)
+				data.attachment_id = attachmentId;
+
+			if (width)
+				data.width = width;
+
+			if (height)
+				data.height = height;
+
+			choice = new api.HeaderTool.ImageModel({
+				header: data,
+				choice: url.split('/').pop()
+			});
+			api.HeaderTool.UploadsList.add(choice);
+			api.HeaderTool.currentHeader.set(choice.toJSON());
+			choice.save();
+			choice.importImage();
+		},
+
+		/**
+		 * Triggers the necessary events to deselect an image which was set as
+		 * the currently selected one.
+		 */
+		removeImage: function() {
+			api.HeaderTool.currentHeader.trigger('hide');
+			api.HeaderTool.CombinedList.trigger('control:removeImage');
+		}
+
+	});
+
 	// Change objects contained within the main customize object to Settings.
 	api.defaultConstructor = api.Setting;
 
@@ -686,7 +896,8 @@
 	api.controlConstructor = {
 		color:  api.ColorControl,
 		upload: api.UploadControl,
-		image:  api.ImageControl
+		image:  api.ImageControl,
+		header: api.HeaderControl
 	};
 
 	$( function() {
@@ -961,35 +1172,6 @@
 			});
 		});
 
-		// Handle header image data
-		api.control( 'header_image', function( control ) {
-			control.setting.bind( function( to ) {
-				if ( to === control.params.removed )
-					control.settings.data.set( false );
-			});
-
-			control.library.on( 'click', 'a', function() {
-				control.settings.data.set( $(this).data('customizeHeaderImageData') );
-			});
-
-			control.uploader.success = function( attachment ) {
-				var data;
-
-				api.ImageControl.prototype.success.call( control, attachment );
-
-				data = {
-					attachment_id: attachment.get('id'),
-					url:           attachment.get('url'),
-					thumbnail_url: attachment.get('url'),
-					height:        attachment.get('height'),
-					width:         attachment.get('width')
-				};
-
-				attachment.element.data( 'customizeHeaderImageData', data );
-				control.settings.data.set( data );
-			};
-		});
-
 		api.trigger( 'ready' );
 
 		// Make sure left column gets focus
diff --git src/wp-admin/js/header-models.js src/wp-admin/js/header-models.js
new file mode 100644
index 0000000..945bc23
--- /dev/null
+++ src/wp-admin/js/header-models.js
@@ -0,0 +1,246 @@
+/* globals jQuery, _wpCustomizeHeader */
+;( function( $, wp ) {
+	var api = wp.customize;
+	api.HeaderTool = {};
+
+
+	/**
+	 * wp.customize.HeaderTool.ImageModel
+	 *
+	 * A header image. This is where saves via the Customizer API are
+	 * abstracted away, plus our own AJAX calls to add images to and remove
+	 * images from the user's recently uploaded images setting on the server.
+	 * These calls are made regardless of whether the user actually saves new
+	 * Customizer settings.
+	 *
+	 * @constructor
+	 * @augments Backbone.Model
+	 */
+	api.HeaderTool.ImageModel = Backbone.Model.extend({
+		defaults: function() {
+			return {
+				header: {
+					attachment_id: 0,
+					url: '',
+					timestamp: Date.now(),
+					thumbnail_url: ''
+				},
+				choice: '',
+				hidden: false,
+				random: false
+			};
+		},
+
+		initialize: function() {
+			this.on('hide', this.hide, this);
+		},
+
+		hide: function() {
+			this.set('choice', '');
+			api('header_image').set('remove-header');
+			api('header_image_data').set('remove-header');
+		},
+
+		destroy: function() {
+			var data = this.get('header'),
+				curr = api.HeaderTool.currentHeader.get('header').attachment_id;
+
+			// If the image we're removing is also the current header, unset
+			// the latter
+			if (curr && data.attachment_id == curr)
+				api.HeaderTool.currentHeader.trigger('hide');
+
+			$.post(_wpCustomizeSettings.url.ajax, {
+				wp_customize: 'on',
+				theme: api.settings.theme.stylesheet,
+				dataType: 'json',
+				action: 'header_remove',
+				nonce: _wpCustomizeHeader.nonces.remove,
+				data: data
+			});
+
+			this.trigger('destroy', this, this.collection);
+		},
+
+		save: function() {
+			if (this.get('random')) {
+				api('header_image').set(this.get('header').random);
+				api('header_image_data').set(this.get('header').random);
+			} else {
+				if (this.get('header').defaultName) {
+					api('header_image').set(this.get('header').url);
+					api('header_image_data').set(this.get('header').defaultName);
+				} else {
+					api('header_image').set(this.get('header').url);
+					api('header_image_data').set(this.get('header'));
+				}
+			}
+
+			api.HeaderTool.combinedList.trigger('control:setImage', this);
+		},
+
+		importImage: function() {
+			var data = this.get('header');
+			if (data.attachment_id === undefined)
+				return;
+
+			$.post(_wpCustomizeSettings.url.ajax, {
+				wp_customize: 'on',
+				theme: api.settings.theme.stylesheet,
+				dataType: 'json',
+				action: 'header_add',
+				nonce: _wpCustomizeHeader.nonces.add,
+				data: data
+			});
+		},
+
+		shouldBeCropped: function() {
+			if (this.get('themeFlexWidth') === true &&
+						this.get('themeFlexHeight') === true) {
+				return false;
+			}
+
+			if (this.get('themeFlexWidth') === true &&
+					 this.get('themeHeight') === this.get('imageHeight')) {
+				return false;
+			}
+
+			if (this.get('themeFlexHeight') === true &&
+					 this.get('themeWidth') === this.get('imageWidth')) {
+				return false;
+			}
+
+			if (this.get('themeWidth') === this.get('imageWidth') &&
+					 this.get('themeHeight') === this.get('imageHeight')) {
+				return false;
+			}
+
+			return true;
+		}
+	});
+
+
+	/**
+	 * wp.customize.HeaderTool.ChoiceList
+	 *
+	 * @constructor
+	 * @augments Backbone.Collection
+	 */
+	api.HeaderTool.ChoiceList = Backbone.Collection.extend({
+		model: api.HeaderTool.ImageModel,
+
+		// Ordered from most recently used to least
+		comparator: function(model) {
+			return -model.get('header').timestamp;
+		},
+
+		initialize: function() {
+			var current = api.HeaderTool.currentHeader.get('choice').replace(/^https?:\/\//, ''),
+				isRandom = this.isRandomChoice(api.get().header_image);
+
+			// Overridable by an extending class
+			if (!this.type)
+				this.type = 'uploaded';
+
+			// Overridable by an extending class
+			if (!this.data)
+				this.data = _wpCustomizeHeader.uploads;
+
+			if (isRandom) {
+				// So that when adding data we don't hide regular images
+				current = api.get().header_image;
+			}
+
+			this.on('control:setImage', this.setImage, this);
+			this.on('control:removeImage', this.removeImage, this);
+			this.on('add', this.maybeAddRandomChoice, this);
+
+			_.each(this.data, function(elt, index) {
+				if (!elt.attachment_id)
+					elt.defaultName = index;
+
+				this.add({
+					header: elt,
+					choice: elt.url.split('/').pop(),
+					hidden: current == elt.url.replace(/^https?:\/\//, '')
+				}, { silent: true });
+			}, this);
+
+			if (this.size() > 0)
+				this.addRandomChoice(current);
+		},
+
+		maybeAddRandomChoice: function() {
+			if (this.size() === 1)
+				this.addRandomChoice();
+		},
+
+		addRandomChoice: function(initialChoice) {
+			var isRandomSameType = RegExp(this.type).test(initialChoice),
+				randomChoice = 'random-' + this.type + '-image';
+
+			this.add({
+				header: {
+					timestamp: 0,
+					random: randomChoice,
+					width: 245,
+					height: 41
+				},
+				choice: randomChoice,
+				random: true,
+				hidden: isRandomSameType
+			});
+		},
+
+		isRandomChoice: function(choice) {
+			return /^random-(uploaded|default)-image$/.test(choice);
+		},
+
+		shouldHideTitle: function() {
+			return _.every(this.pluck('hidden'));
+		},
+
+		setImage: function(model) {
+			this.each(function(m) {
+				m.set('hidden', false);
+			});
+
+			if (model) {
+				model.set('hidden', true);
+				// Bump images to top except for special "Randomize" images
+				if (!model.get('random')) {
+					model.get('header').timestamp = Date.now();
+					this.sort();
+				}
+			}
+		},
+
+		removeImage: function() {
+			this.each(function(m) {
+				m.set('hidden', false);
+			});
+		},
+
+		shown: function() {
+			var filtered = this.where({ hidden: false });
+			return new api.HeaderTool.ChoiceList( filtered );
+		}
+	});
+
+
+	/**
+	 * wp.customize.HeaderTool.DefaultsList
+	 *
+	 * @constructor
+	 * @augments wp.customize.HeaderTool.ChoiceList
+	 * @augments Backbone.Collection
+	 */
+	api.HeaderTool.DefaultsList = api.HeaderTool.ChoiceList.extend({
+		initialize: function() {
+			this.type = 'default';
+			this.data = _wpCustomizeHeader.defaults;
+			api.HeaderTool.ChoiceList.prototype.initialize.apply(this);
+		}
+	});
+
+})( jQuery, this.wp );
diff --git src/wp-admin/js/header-views.js src/wp-admin/js/header-views.js
new file mode 100644
index 0000000..a9957b5
--- /dev/null
+++ src/wp-admin/js/header-views.js
@@ -0,0 +1,254 @@
+/* globals jQuery, _, Backbone, _wpMediaViewsL10n, _wpCustomizeHeader */
+;( function( $, wp, _ ) {
+	if ( ! wp || ! wp.customize ) { return; }
+	var api = wp.customize, frame, CombinedList, UploadsList, DefaultsList;
+
+
+	/**
+	 * wp.customize.HeaderTool.CurrentView
+	 *
+	 * Displays the currently selected header image, or a placeholder in lack
+	 * thereof.
+	 *
+	 * Instantiate with model wp.customize.HeaderTool.currentHeader.
+	 *
+	 * @constructor
+	 * @augments Backbone.View
+	 */
+	api.HeaderTool.CurrentView = Backbone.View.extend({
+		template: _.template($('#tmpl-header-current').html()),
+
+		initialize: function() {
+			this.listenTo(this.model, 'change', this.render);
+			this.render();
+		},
+
+		render: function() {
+			this.$el.html(this.template(this.model.toJSON()));
+			this.setPlaceholder();
+			this.setButtons();
+			return this;
+		},
+
+		getHeight: function() {
+			var image = this.$el.find('img'),
+				saved = this.model.get('savedHeight'),
+				height = image.height() || saved;
+
+			if (image.length) {
+				this.$el.find('.inner').hide();
+			} else {
+				this.$el.find('.inner').show();
+			}
+
+			// happens at ready
+			if (!height) {
+				var d = api.get().header_image_data;
+
+				if (d && d.width && d.height) {
+					var w = d.width,
+						h = d.height;
+					// hardcoded container width
+					height = 260 / w * h;
+				}
+				// fallback for when no image is set
+				else height = 40;
+			}
+
+			return height;
+		},
+
+		setPlaceholder: function(_height) {
+			var height = _height || this.getHeight();
+			this.model.set('savedHeight', height);
+			this.$el
+				.add(this.$el.find('.placeholder'))
+				.height(height);
+		},
+
+		setButtons: function() {
+			var elements = $('.actions .remove');
+			if (this.model.get('choice'))
+				elements.show();
+			else
+				elements.hide();
+		}
+	});
+
+
+	/**
+	 * wp.customize.HeaderTool.ChoiceView
+	 *
+	 * Represents a choosable header image, be it user-uploaded,
+	 * theme-suggested or a special Randomize choice.
+	 *
+	 * Takes a wp.customize.HeaderTool.ImageModel.
+	 *
+	 * Manually changes model wp.customize.HeaderTool.currentHeader via the
+	 * `select` method.
+	 *
+	 * @constructor
+	 * @augments Backbone.View
+	 */
+	(function () { // closures FTW
+	var lastHeight = 0;
+	api.HeaderTool.ChoiceView = Backbone.View.extend({
+		template: _.template($('#tmpl-header-choice').html()),
+
+		className: 'header-view',
+
+		events: {
+			'click .choice,.random': 'select',
+			'click .close': 'removeImage'
+		},
+
+		initialize: function() {
+			var properties = [
+				this.model.get('header').url,
+				this.model.get('choice')
+			];
+
+			this.listenTo(this.model, 'change', this.render);
+			if (_.contains(properties, api.get().header_image))
+				api.HeaderTool.currentHeader.set(this.extendedModel());
+		},
+
+		render: function() {
+			var model = this.model;
+
+			this.$el.html(this.template(this.extendedModel()));
+
+			if (model.get('random'))
+				this.setPlaceholder(40);
+			else
+				lastHeight = this.getHeight();
+
+			this.$el.toggleClass('hidden', model.get('hidden'));
+			return this;
+		},
+
+		extendedModel: function() {
+			var c = this.model.get('collection'),
+				t = _wpCustomizeHeader.l10n[c.type] || '';
+
+			return _.extend(this.model.toJSON(), {
+				// -1 to exclude the randomize button
+				nImages: c.size() - 1,
+				type: t
+			});
+		},
+
+		getHeight: api.HeaderTool.CurrentView.prototype.getHeight,
+
+		setPlaceholder: api.HeaderTool.CurrentView.prototype.setPlaceholder,
+
+		select: function() {
+			this.model.save();
+			api.HeaderTool.currentHeader.set(this.extendedModel());
+		},
+
+		removeImage: function(e) {
+			e.stopPropagation();
+			this.model.destroy();
+			this.remove();
+		}
+	});
+	})();
+
+
+	/**
+	 * wp.customize.HeaderTool.ChoiceListView
+	 *
+	 * A container for ChoiceViews. These choices should be of one same type:
+	 * user-uploaded headers or theme-defined ones.
+	 *
+	 * Takes a wp.customize.HeaderTool.ChoiceList.
+	 *
+	 * @constructor
+	 * @augments Backbone.View
+	 */
+	api.HeaderTool.ChoiceListView = Backbone.View.extend({
+		slimScrollOptions: {
+			disableFadeOut: true,
+			allowPageScroll: true,
+			height: 'auto'
+		},
+
+		initialize: function() {
+			this.listenTo(this.collection, 'add', this.addOne);
+			this.listenTo(this.collection, 'remove', this.render);
+			this.listenTo(this.collection, 'sort', this.render);
+			this.listenTo(this.collection, 'change:hidden', this.toggleTitle);
+			this.listenTo(this.collection, 'change:hidden', this.setMaxListHeight);
+			this.render();
+		},
+
+		render: function() {
+			this.$el.empty();
+			this.collection.each(this.addOne, this);
+			this.toggleTitle();
+			if (this.$el.parents().hasClass('uploaded')) {
+				this.setMaxListHeight();
+			}
+		},
+
+		setMaxListHeight: function() {
+			if (this.$el.parents().hasClass('uploaded')) {
+				var uploaded = this.$el.parents('.uploaded'),
+					height   = this.maxListHeight();
+
+				uploaded.height(height);
+				this.$el.slimScroll(this.slimScrollOptions);
+			}
+		},
+
+		maxListHeight: function() {
+			var shown = this.collection.shown(),
+				imgsHeight = shown.reduce( function(memo, img, index) {
+					var imgMargin = (shown.length - 1)  === index ? 0 : 9,
+						height = (260 / img.get('header').width) * img.get('header').height;
+
+					return memo + height + 5 + imgMargin;
+				}, 0);
+			return Math.min( Math.ceil(imgsHeight), 180 );
+		},
+
+		addOne: function(choice) {
+			var view;
+			choice.set({ collection: this.collection });
+			view = new api.HeaderTool.ChoiceView({ model: choice });
+			this.$el.append(view.render().el);
+		},
+
+		toggleTitle: function() {
+			var title = this.$el.parents().prev('.customize-control-title');
+			if (this.collection.shouldHideTitle())
+				title.hide();
+			else
+				title.show();
+		}
+	});
+
+
+	/**
+	 * wp.customize.HeaderTool.CombinedList
+	 *
+	 * Aggregates wp.customize.HeaderTool.ChoiceList collections (or any
+	 * Backbone object, really) and acts as a bus to feed them events.
+	 *
+	 * @constructor
+	 * @augments Backbone.View
+	 */
+	api.HeaderTool.CombinedList = Backbone.View.extend({
+		initialize: function(collections) {
+			this.collections = collections;
+			this.on('all', this.propagate, this);
+		},
+		propagate: function(event, arg) {
+			_.each(this.collections, function(collection) {
+				collection.trigger(event, arg);
+			});
+		},
+	});
+
+})( jQuery, this.wp, _ );
diff --git src/wp-includes/class-wp-customize-control.php src/wp-includes/class-wp-customize-control.php
index fde8561..5529513 100644
--- src/wp-includes/class-wp-customize-control.php
+++ src/wp-includes/class-wp-customize-control.php
@@ -691,37 +691,9 @@ class WP_Customize_Background_Image_Control extends WP_Customize_Image_Control {
 	}
 }
 
-/**
- * Customize Header Image Control Class
- *
- * @package WordPress
- * @subpackage Customize
- * @since 3.4.0
- */
-class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control {
-	/**
-	 * The processed default headers.
-	 * @since 3.4.2
-	 * @var array
-	 */
-	protected $default_headers;
-
-	/**
-	 * The uploaded headers.
-	 * @since 3.4.2
-	 * @var array
-	 */
-	protected $uploaded_headers;
+class WP_Customize_Header_Image_Control extends WP_Customize_Control {
+	public $type = 'header';
 
-	/**
-	 * Constructor.
-	 *
-	 * @since 3.4.0
-	 * @uses WP_Customize_Image_Control::__construct()
-	 * @uses WP_Customize_Image_Control::add_tab()
-	 *
-	 * @param WP_Customize_Manager $manager
-	 */
 	public function __construct( $manager ) {
 		parent::__construct( $manager, 'header_image', array(
 			'label'    => __( 'Header Image' ),
@@ -733,85 +705,293 @@ class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control {
 			'context'  => 'custom-header',
 			'removed'  => 'remove-header',
 			'get_url'  => 'get_header_image',
-			'statuses' => array(
-				''                      => __('Default'),
-				'remove-header'         => __('No Image'),
-				'random-default-image'  => __('Random Default Image'),
-				'random-uploaded-image' => __('Random Uploaded Image'),
+		) );
+
+	}
+
+	public function to_json() {
+		parent::to_json();
+	}
+
+	public function enqueue() {
+		wp_enqueue_media();
+		wp_enqueue_script( 'customize-header-views' );
+
+		$this->prepare_control();
+
+		wp_localize_script( 'customize-header-views', '_wpCustomizeHeader', array(
+			'data' => array(
+				'width' => absint( get_theme_support( 'custom-header', 'width' ) ),
+				'height' => absint( get_theme_support( 'custom-header', 'height' ) ),
+				'flex-width' => absint( get_theme_support( 'custom-header', 'flex-width' ) ),
+				'flex-height' => absint( get_theme_support( 'custom-header', 'flex-height' ) ),
+				'currentImgSrc' => $this->get_current_image_src(),
+			),
+			'nonces' => array(
+				'add' => wp_create_nonce( 'header-add' ),
+				'remove' => wp_create_nonce( 'header-remove' ),
+			),
+			'l10n' => array(
+				/* translators: header images uploaded by user */
+				'uploaded' => __( 'uploaded' ),
+				/* translators: header images suggested by the current theme */
+				'default' => __( 'suggested' )
+			),
+			'uploads' => $this->uploaded_headers,
+			'defaults' => $this->default_headers
+		) );
+
+		parent::enqueue();
+	}
+
+	public function get_default_header_images() {
+		global $custom_image_header;
+
+		// Get *the* default image if there is one
+		$default = get_theme_support( 'custom-header', 'default-image' );
+
+		if ( ! $default ) // If not,
+			return $custom_image_header->default_headers; // easy peasy.
+
+		$default = sprintf( $default,
+			get_template_directory_uri(),
+			get_stylesheet_directory_uri() );
+
+		$header_images = array();
+		$already_has_default = false;
+
+		// Get the whole set of default images
+		$default_header_images = $custom_image_header->default_headers;
+		foreach ( $default_header_images as $k => $h ) {
+			if ( $h['url'] == $default ) {
+				$already_has_default = true;
+				break;
+			}
+		}
+
+		// If *the one true image* isn't included in the default set, add it in
+		// first position
+		if ( ! $already_has_default ) {
+			$header_images['default'] = array(
+				'url' => $default,
+				'thumbnail_url' => $default,
+				'description' => 'Default'
+			);
+		}
+
+		// The rest of the set comes after
+		$header_images = array_merge( $header_images, $default_header_images );
+
+		return $header_images;
+	}
+
+	public function get_uploaded_header_images() {
+		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
+		$header_images = array();
+
+		$headers_not_dated = get_posts( array(
+			'post_type' => 'attachment',
+			'meta_key' => '_wp_attachment_is_custom_header',
+			'meta_value' => get_option('stylesheet'),
+			'orderby' => 'none',
+			'nopaging' => true,
+			'meta_query' => array(
+				array(
+					'key' => '_wp_attachment_is_custom_header',
+					'value' => get_option( 'stylesheet' ),
+					'compare' => 'LIKE'
+				),
+				array(
+					'key' => $key,
+					'value' => 'this string must not be empty',
+					'compare' => 'NOT EXISTS'
+				),
 			)
 		) );
 
-		// Remove the upload tab.
-		$this->remove_tab( 'upload-new' );
+		$headers_dated = get_posts( array(
+			'post_type' => 'attachment',
+			'meta_key' => $key,
+			'orderby' => 'meta_value_num',
+			'order' => 'DESC',
+			'nopaging' => true,
+			'meta_query' => array(
+				array(
+					'key' => '_wp_attachment_is_custom_header',
+					'value' => get_option( 'stylesheet' ),
+					'compare' => 'LIKE'
+				),
+			),
+		) );
+
+		$limit = apply_filters( 'custom_header_uploaded_limit', 15 );
+		$headers = array_merge( $headers_dated, $headers_not_dated );
+		$headers = array_slice( $headers, 0, $limit );
+
+		foreach ( (array) $headers as $header ) {
+			$url = esc_url_raw( $header->guid );
+			$header_data = wp_get_attachment_metadata( $header->ID );
+			$timestamp = get_post_meta( $header->ID,
+				'_wp_attachment_custom_header_last_used_' . get_stylesheet(),
+				true );
+
+			$h = array(
+				'attachment_id' => $header->ID,
+				'url'           => $url,
+				'thumbnail_url' => $url,
+				'timestamp'     => $timestamp ? $timestamp : 0,
+			);
+
+			if ( isset( $header_data['width'] ) )
+				$h['width'] = $header_data['width'];
+			if ( isset( $header_data['height'] ) )
+				$h['height'] = $header_data['height'];
+
+			$header_images[] = $h;
+		}
+
+		return $header_images;
 	}
 
-	/**
-	 * Prepares the control.
-	 *
-	 * If no tabs exist, removes the control from the manager.
-	 *
-	 * @since 3.4.2
-	 */
 	public function prepare_control() {
 		global $custom_image_header;
 		if ( empty( $custom_image_header ) )
-			return parent::prepare_control();
+			return;
 
 		// Process default headers and uploaded headers.
 		$custom_image_header->process_default_headers();
-		$this->default_headers = $custom_image_header->default_headers;
-		$this->uploaded_headers = get_uploaded_header_images();
+		$this->default_headers = $this->get_default_header_images();
+		$this->uploaded_headers = $this->get_uploaded_header_images();
+	}
 
-		if ( $this->default_headers )
-			$this->add_tab( 'default',  __('Default'),  array( $this, 'tab_default_headers' ) );
+	function print_header_image_template() {
+		?>
+		<script type="text/template" id="tmpl-header-choice">
+			<% if (random) { %>
+
+			<div class="placeholder random">
+				<div class="inner">
+					<span><span class="dice">&#9860;</span>
+						<?php /* translators: "nImages" is a number, "type" is either "uploaded" or "suggested" */ ?>
+						<?php _e( 'Randomize <%- nImages %> <%- type %> headers' ); ?>
+					</span>
+				</div>
+			</div>
 
-		if ( ! $this->uploaded_headers )
-			$this->remove_tab( 'uploaded' );
+			<% } else { %>
 
-		return parent::prepare_control();
-	}
+			<% if (type == 'uploaded') { %>
+			<a href="#" class="close">X</a>
+			<% } %>
 
-	/**
-	 * @since 3.4.0
-	 *
-	 * @param mixed $choice Which header image to select. (@see Custom_Image_Header::get_header_image() )
-	 * @param array $header
-	 */
-	public function print_header_image( $choice, $header ) {
-		$header['url']           = set_url_scheme( $header['url'] );
-		$header['thumbnail_url'] = set_url_scheme( $header['thumbnail_url'] );
+			<a href="#" class="choice thumbnail %>"
+				data-customize-image-value="<%- header.url %>"
+				data-customize-header-image-data="<%- JSON.stringify(header) %>">
+				<img src="<%- header.thumbnail_url %>">
+			</a>
 
-		$header_image_data = array( 'choice' => $choice );
-		foreach ( array( 'attachment_id', 'width', 'height', 'url', 'thumbnail_url' ) as $key ) {
-			if ( isset( $header[ $key ] ) )
-				$header_image_data[ $key ] = $header[ $key ];
-		}
+			<% } %>
+		</script>
 
+		<script type="text/template" id="tmpl-header-current">
+			<% if (choice) { %>
+				<% if (random) { %>
 
-		?>
-		<a href="#" class="thumbnail"
-			data-customize-image-value="<?php echo esc_url( $header['url'] ); ?>"
-			data-customize-header-image-data="<?php echo esc_attr( json_encode( $header_image_data ) ); ?>">
-			<img src="<?php echo esc_url( $header['thumbnail_url'] ); ?>" />
-		</a>
+			<div class="placeholder">
+				<div class="inner">
+					<span><span class="dice">&#9860;</span>
+						<?php /* translators: "nImages" is a number, "type" is either "uploaded" or "suggested" */ ?>
+						<?php _e( 'Randomizing <%- nImages %> <%- type %> headers' ); ?>
+					</span>
+				</div>
+			</div>
+
+				<% } else { %>
+
+			<img src="<%- header.thumbnail_url %>" />
+
+				<% } %>
+			<% } else { %>
+
+			<div class="placeholder">
+				<div class="inner">
+					<span>
+						No image set.
+					</span>
+				</div>
+			</div>
+
+			<% } %>
+		</script>
 		<?php
 	}
 
-	/**
-	 * @since 3.4.0
-	 */
-	public function tab_uploaded() {
-		?><div class="uploaded-target"></div><?php
-
-		foreach ( $this->uploaded_headers as $choice => $header )
-			$this->print_header_image( $choice, $header );
+	public function get_current_image_src() {
+		$src = $this->value();
+		if ( isset( $this->get_url ) ) {
+			$src = call_user_func( $this->get_url, $src );
+			return $src;
+		}
+		return null;
 	}
 
-	/**
-	 * @since 3.4.0
-	 */
-	public function tab_default_headers() {
-		foreach ( $this->default_headers as $choice => $header )
-			$this->print_header_image( $choice, $header );
+	public function render_content() {
+		$this->print_header_image_template();
+		$visibility = $this->get_current_image_src() ? '' : ' style="display:none" ';
+		$width = absint( get_theme_support( 'custom-header', 'width' ) );
+		$height = absint( get_theme_support( 'custom-header', 'height' ) );
+		?>
+
+
+		<div class="customize-control-content">
+			<p class="customizer-section-intro">
+				<?php _e( 'Personalize your blog with your own header image.' ); ?>
+				<?php
+				if ( $width && $height ) {
+					printf( __( 'While you can crop images to your liking after clicking <strong>%s</strong>, your theme recommends a header size of <strong>%dx%d</strong> pixels.' ),
+						_x( 'Add new', 'new image', 'custom-header' ), $width, $height );
+				} else {
+					if ( $width )
+						printf( __( 'While you can crop images to your liking after clicking <strong>%s</strong>, your theme recommends a header width of <strong>%d</strong> pixels.' ),
+							_x( 'Add new', 'new image', 'custom-header' ), $width );
+					if ( $height )
+						printf( __( 'While you can crop images to your liking after clicking <strong>%s</strong>, your theme recommends a header height of <strong>%d</strong> pixels.' ),
+							_x( 'Add new', 'new image', 'custom-header' ), $height );
+				}
+				?>
+			</p>
+			<div class="current">
+				<span class="customize-control-title">
+					<?php _e( 'Current header', 'custom-header' ); ?>
+				</span>
+				<div class="container">
+				</div>
+			</div>
+			<div class="actions">
+				<?php /* translators: Hide as in hide header image via the Customizer */ ?>
+				<a href="#" <?php echo $visibility ?> class="button remove"><?php _e( 'Hide', 'custom-header' ); ?></a>
+				<?php /* translators: New as in add new header image via the Customizer */ ?>
+				<a href="#" class="button new"><?php _ex( 'Add new', 'new image', 'custom-header' ); ?></a>
+				<div style="clear:both"></div>
+			</div>
+			<div class="choices">
+				<span class="customize-control-title header-previously-uploaded">
+					<?php _e( 'Previously uploaded', 'custom-header' ); ?>
+				</span>
+				<div class="uploaded">
+					<div class="list">
+					</div>
+				</div>
+				<span class="customize-control-title header-default">
+					<?php _e( 'Suggested', 'custom-header' ); ?>
+				</span>
+				<div class="default">
+					<div class="list">
+					</div>
+				</div>
+			</div>
+		</div>
+		<?php
 	}
-}
\ No newline at end of file
+
+}
diff --git src/wp-includes/js/jquery/jquery.slimscroll.js src/wp-includes/js/jquery/jquery.slimscroll.js
new file mode 100644
index 0000000..8f813ee
--- /dev/null
+++ src/wp-includes/js/jquery/jquery.slimscroll.js
@@ -0,0 +1,463 @@
+/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * Version: 1.3.2
+ *
+ */
+(function($) {
+
+  jQuery.fn.extend({
+    slimScroll: function(options) {
+
+      var defaults = {
+
+        // width in pixels of the visible scroll area
+        width : 'auto',
+
+        // height in pixels of the visible scroll area
+        height : '250px',
+
+        // width in pixels of the scrollbar and rail
+        size : '7px',
+
+        // scrollbar color, accepts any hex/color value
+        color: '#000',
+
+        // scrollbar position - left/right
+        position : 'right',
+
+        // distance in pixels between the side edge and the scrollbar
+        distance : '1px',
+
+        // default scroll position on load - top / bottom / $('selector')
+        start : 'top',
+
+        // sets scrollbar opacity
+        opacity : .4,
+
+        // enables always-on mode for the scrollbar
+        alwaysVisible : false,
+
+        // check if we should hide the scrollbar when user is hovering over
+        disableFadeOut : false,
+
+        // sets visibility of the rail
+        railVisible : false,
+
+        // sets rail color
+        railColor : '#333',
+
+        // sets rail opacity
+        railOpacity : .2,
+
+        // whether  we should use jQuery UI Draggable to enable bar dragging
+        railDraggable : true,
+
+        // defautlt CSS class of the slimscroll rail
+        railClass : 'slimScrollRail',
+
+        // defautlt CSS class of the slimscroll bar
+        barClass : 'slimScrollBar',
+
+        // defautlt CSS class of the slimscroll wrapper
+        wrapperClass : 'slimScrollDiv',
+
+        // check if mousewheel should scroll the window if we reach top/bottom
+        allowPageScroll : false,
+
+        // scroll amount applied to each mouse wheel step
+        wheelStep : 20,
+
+        // scroll amount applied when user is using gestures
+        touchScrollStep : 200,
+
+        // sets border radius
+        borderRadius: '7px',
+
+        // sets border radius of the rail
+        railBorderRadius : '7px'
+      };
+
+      var o = $.extend(defaults, options);
+
+      // do it for every element that matches selector
+      this.each(function(){
+
+      var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
+        barHeight, percentScroll, lastScroll,
+        divS = '<div></div>',
+        minBarHeight = 30,
+        releaseScroll = false;
+
+        // used in event handlers and for better minification
+        var me = $(this);
+
+        // ensure we are not binding it again
+        if (me.parent().hasClass(o.wrapperClass))
+        {
+            // start from last bar position
+            var offset = me.scrollTop();
+
+            // find bar and rail
+            bar = me.parent().find('.' + o.barClass);
+            rail = me.parent().find('.' + o.railClass);
+
+            getBarHeight();
+
+            // check if we should scroll existing instance
+            if ($.isPlainObject(options))
+            {
+              // Pass height: auto to an existing slimscroll object to force a resize after contents have changed
+              if ( 'height' in options && options.height == 'auto' ) {
+                me.parent().css('height', 'auto');
+                me.css('height', 'auto');
+                var height = me.parent().parent().height();
+                me.parent().css('height', height);
+                me.css('height', height);
+              }
+
+              if ('scrollTo' in options)
+              {
+                // jump to a static point
+                offset = parseInt(o.scrollTo);
+              }
+              else if ('scrollBy' in options)
+              {
+                // jump by value pixels
+                offset += parseInt(o.scrollBy);
+              }
+              else if ('destroy' in options)
+              {
+                // remove slimscroll elements
+                bar.remove();
+                rail.remove();
+                me.unwrap();
+                return;
+              }
+
+              // scroll content by the given offset
+              scrollContent(offset, false, true);
+            }
+
+            return;
+        }
+
+        // optionally set height to the parent's height
+        o.height = (options.height == 'auto') ? me.parent().height() : options.height;
+
+        // wrap content
+        var wrapper = $(divS)
+          .addClass(o.wrapperClass)
+          .css({
+            position: 'relative',
+            overflow: 'hidden',
+            width: o.width,
+            height: o.height
+          });
+
+        // update style for the div
+        me.css({
+          overflow: 'hidden',
+          width: o.width,
+          height: o.height
+        });
+
+        // create scrollbar rail
+        var rail = $(divS)
+          .addClass(o.railClass)
+          .css({
+            width: o.size,
+            height: '100%',
+            position: 'absolute',
+            top: 0,
+            display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
+            'border-radius': o.railBorderRadius,
+            background: o.railColor,
+            opacity: o.railOpacity,
+            zIndex: 90
+          });
+
+        // create scrollbar
+        var bar = $(divS)
+          .addClass(o.barClass)
+          .css({
+            background: o.color,
+            width: o.size,
+            position: 'absolute',
+            top: 0,
+            opacity: o.opacity,
+            display: o.alwaysVisible ? 'block' : 'none',
+            'border-radius' : o.borderRadius,
+            BorderRadius: o.borderRadius,
+            MozBorderRadius: o.borderRadius,
+            WebkitBorderRadius: o.borderRadius,
+            zIndex: 99
+          });
+
+        // set position
+        var posCss = (o.position == 'right') ? { right: o.distance } : { left: o.distance };
+        rail.css(posCss);
+        bar.css(posCss);
+
+        // wrap it
+        me.wrap(wrapper);
+
+        // append to parent div
+        me.parent().append(bar);
+        me.parent().append(rail);
+
+        // make it draggable and no longer dependent on the jqueryUI
+        if (o.railDraggable){
+          bar.bind("mousedown", function(e) {
+            var $doc = $(document);
+            isDragg = true;
+            t = parseFloat(bar.css('top'));
+            pageY = e.pageY;
+
+            $doc.bind("mousemove.slimscroll", function(e){
+              currTop = t + e.pageY - pageY;
+              bar.css('top', currTop);
+              scrollContent(0, bar.position().top, false);// scroll content
+            });
+
+            $doc.bind("mouseup.slimscroll", function(e) {
+              isDragg = false;hideBar();
+              $doc.unbind('.slimscroll');
+            });
+            return false;
+          }).bind("selectstart.slimscroll", function(e){
+            e.stopPropagation();
+            e.preventDefault();
+            return false;
+          });
+        }
+
+        // on rail over
+        rail.hover(function(){
+          showBar();
+        }, function(){
+          hideBar();
+        });
+
+        // on bar over
+        bar.hover(function(){
+          isOverBar = true;
+        }, function(){
+          isOverBar = false;
+        });
+
+        // show on parent mouseover
+        me.hover(function(){
+          isOverPanel = true;
+          showBar();
+          hideBar();
+        }, function(){
+          isOverPanel = false;
+          hideBar();
+        });
+
+        // support for mobile
+        me.bind('touchstart', function(e,b){
+          if (e.originalEvent.touches.length)
+          {
+            // record where touch started
+            touchDif = e.originalEvent.touches[0].pageY;
+          }
+        });
+
+        me.bind('touchmove', function(e){
+          // prevent scrolling the page if necessary
+          if(!releaseScroll)
+          {
+  		      e.originalEvent.preventDefault();
+		      }
+          if (e.originalEvent.touches.length)
+          {
+            // see how far user swiped
+            var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
+            // scroll content
+            scrollContent(diff, true);
+            touchDif = e.originalEvent.touches[0].pageY;
+          }
+        });
+
+        // set up initial height
+        getBarHeight();
+
+        // check start position
+        if (o.start === 'bottom')
+        {
+          // scroll content to bottom
+          bar.css({ top: me.outerHeight() - bar.outerHeight() });
+          scrollContent(0, true);
+        }
+        else if (o.start !== 'top')
+        {
+          // assume jQuery selector
+          scrollContent($(o.start).position().top, null, true);
+
+          // make sure bar stays hidden
+          if (!o.alwaysVisible) { bar.hide(); }
+        }
+
+        // attach scroll events
+        attachWheel();
+
+        function _onWheel(e)
+        {
+          // use mouse wheel only when mouse is over
+          if (!isOverPanel) { return; }
+
+          var e = e || window.event;
+
+          var delta = 0;
+          if (e.wheelDelta) { delta = -e.wheelDelta/120; }
+          if (e.detail) { delta = e.detail / 3; }
+
+          var target = e.target || e.srcTarget || e.srcElement;
+          if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
+            // scroll content
+            scrollContent(delta, true);
+          }
+
+          // stop window scroll
+          if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
+          if (!releaseScroll) { e.returnValue = false; }
+        }
+
+        function scrollContent(y, isWheel, isJump)
+        {
+          releaseScroll = false;
+          var delta = y;
+          var maxTop = me.outerHeight() - bar.outerHeight();
+
+          if (isWheel)
+          {
+            // move bar with mouse wheel
+            delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
+
+            // move bar, make sure it doesn't go out
+            delta = Math.min(Math.max(delta, 0), maxTop);
+
+            // if scrolling down, make sure a fractional change to the
+            // scroll position isn't rounded away when the scrollbar's CSS is set
+            // this flooring of delta would happened automatically when
+            // bar.css is set below, but we floor here for clarity
+            delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
+
+            // scroll the scrollbar
+            bar.css({ top: delta + 'px' });
+          }
+
+          // calculate actual scroll amount
+          percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight());
+          delta = percentScroll * (me[0].scrollHeight - me.outerHeight());
+
+          if (isJump)
+          {
+            delta = y;
+            var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
+            offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
+            bar.css({ top: offsetTop + 'px' });
+          }
+
+          // scroll content
+          me.scrollTop(delta);
+
+          // fire scrolling event
+          me.trigger('slimscrolling', ~~delta);
+
+          // ensure bar is visible
+          showBar();
+
+          // trigger hide when scroll is stopped
+          hideBar();
+        }
+
+        function attachWheel()
+        {
+          if (window.addEventListener)
+          {
+            this.addEventListener('DOMMouseScroll', _onWheel, false );
+            this.addEventListener('mousewheel', _onWheel, false );
+          }
+          else
+          {
+            document.attachEvent("onmousewheel", _onWheel)
+          }
+        }
+
+        function getBarHeight()
+        {
+          // calculate scrollbar height and make sure it is not too small
+          barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
+          bar.css({ height: barHeight + 'px' });
+
+          // hide scrollbar if content is not long enough
+          var display = barHeight == me.outerHeight() ? 'none' : 'block';
+          bar.css({ display: display });
+        }
+
+        function showBar()
+        {
+          // recalculate bar height
+          getBarHeight();
+          clearTimeout(queueHide);
+
+          // when bar reached top or bottom
+          if (percentScroll == ~~percentScroll)
+          {
+            //release wheel
+            releaseScroll = o.allowPageScroll;
+
+            // publish approporiate event
+            if (lastScroll != percentScroll)
+            {
+                var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
+                me.trigger('slimscroll', msg);
+            }
+          }
+          else
+          {
+            releaseScroll = false;
+          }
+          lastScroll = percentScroll;
+
+          // show only when required
+          if(barHeight >= me.outerHeight()) {
+            //allow window scroll
+            releaseScroll = true;
+            return;
+          }
+          bar.stop(true,true).fadeIn('fast');
+          if (o.railVisible) { rail.stop(true,true).fadeIn('fast'); }
+        }
+
+        function hideBar()
+        {
+          // only hide when options allow it
+          if (!o.alwaysVisible)
+          {
+            queueHide = setTimeout(function(){
+              if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg)
+              {
+                bar.fadeOut('slow');
+                rail.fadeOut('slow');
+              }
+            }, 1000);
+          }
+        }
+
+      });
+
+      // maintain chainability
+      return this;
+    }
+  });
+
+  jQuery.fn.extend({
+    slimscroll: jQuery.fn.slimScroll
+  });
+
+})(jQuery);
diff --git src/wp-includes/js/jquery/jquery.slimscroll.min.js src/wp-includes/js/jquery/jquery.slimscroll.min.js
new file mode 100644
index 0000000..09785e7
--- /dev/null
+++ src/wp-includes/js/jquery/jquery.slimscroll.min.js
@@ -0,0 +1,16 @@
+/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * Version: 1.3.2
+ *
+ */
+(function(f){jQuery.fn.extend({slimScroll:function(g){var a=f.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:0.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},g);this.each(function(){function u(d){if(r){d=d||
+window.event;var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);f(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&m(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function m(d,f,g){k=!1;var e=d,h=b.outerHeight()-c.outerHeight();f&&(e=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),e=Math.min(Math.max(e,0),h),e=0<d?Math.ceil(e):Math.floor(e),c.css({top:e+"px"}));l=parseInt(c.css("top"))/(b.outerHeight()-c.outerHeight());
+e=l*(b[0].scrollHeight-b.outerHeight());g&&(e=d,d=e/b[0].scrollHeight*b.outerHeight(),d=Math.min(Math.max(d,0),h),c.css({top:d+"px"}));b.scrollTop(e);b.trigger("slimscrolling",~~e);v();p()}function C(){window.addEventListener?(this.addEventListener("DOMMouseScroll",u,!1),this.addEventListener("mousewheel",u,!1)):document.attachEvent("onmousewheel",u)}function w(){s=Math.max(b.outerHeight()/b[0].scrollHeight*b.outerHeight(),D);c.css({height:s+"px"});var a=s==b.outerHeight()?"none":"block";c.css({display:a})}
+function v(){w();clearTimeout(A);l==~~l?(k=a.allowPageScroll,B!=l&&b.trigger("slimscroll",0==~~l?"top":"bottom")):k=!1;B=l;s>=b.outerHeight()?k=!0:(c.stop(!0,!0).fadeIn("fast"),a.railVisible&&h.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(A=setTimeout(function(){a.disableFadeOut&&r||x||y||(c.fadeOut("slow"),h.fadeOut("slow"))},1E3))}var r,x,y,A,z,s,l,B,D=30,k=!1,b=f(this);if(b.parent().hasClass(a.wrapperClass)){var n=b.scrollTop(),c=b.parent().find("."+a.barClass),h=b.parent().find("."+
+a.railClass);w();if(f.isPlainObject(g)){if("height"in g&&"auto"==g.height){b.parent().css("height","auto");b.css("height","auto");var q=b.parent().parent().height();b.parent().css("height",q);b.css("height",q)}if("scrollTo"in g)n=parseInt(a.scrollTo);else if("scrollBy"in g)n+=parseInt(a.scrollBy);else if("destroy"in g){c.remove();h.remove();b.unwrap();return}m(n,!1,!0)}}else{a.height="auto"==g.height?b.parent().height():g.height;n=f("<div></div>").addClass(a.wrapperClass).css({position:"relative",
+overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden",width:a.width,height:a.height});var h=f("<div></div>").addClass(a.railClass).css({width:a.size,height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=f("<div></div>").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?
+"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius,WebkitBorderRadius:a.borderRadius,zIndex:99}),q="right"==a.position?{right:a.distance}:{left:a.distance};h.css(q);c.css(q);b.wrap(n);b.parent().append(c);b.parent().append(h);a.railDraggable&&c.bind("mousedown",function(a){var b=f(document);y=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);m(0,c.position().top,!1)});
+b.bind("mouseup.slimscroll",function(a){y=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll",function(a){a.stopPropagation();a.preventDefault();return!1});h.hover(function(){v()},function(){p()});c.hover(function(){x=!0},function(){x=!1});b.hover(function(){r=!0;v();p()},function(){r=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(z=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&
+(m((z-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),z=b.originalEvent.touches[0].pageY)});w();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),m(0,!0)):"top"!==a.start&&(m(f(a.start).position().top,null,!0),a.alwaysVisible||c.hide());C()}});return this}});jQuery.fn.extend({slimscroll:jQuery.fn.slimScroll})})(jQuery);
diff --git src/wp-includes/script-loader.php src/wp-includes/script-loader.php
index 98e4a87..945f192 100644
--- src/wp-includes/script-loader.php
+++ src/wp-includes/script-loader.php
@@ -198,6 +198,7 @@ function wp_default_scripts( &$scripts ) {
 	$scripts->add( 'jquery-table-hotkeys', "/wp-includes/js/jquery/jquery.table-hotkeys$suffix.js", array('jquery', 'jquery-hotkeys'), false, 1 );
 	$scripts->add( 'jquery-touch-punch', "/wp-includes/js/jquery/jquery.ui.touch-punch.js", array('jquery-ui-widget', 'jquery-ui-mouse'), '0.2.2', 1 );
 	$scripts->add( 'jquery-masonry', "/wp-includes/js/jquery/jquery.masonry.min.js", array('jquery'), '2.1.05', 1 );
+	$scripts->add( 'jquery-slimscroll', "/wp-includes/js/jquery/jquery.slimscroll$suffix.js", array( 'jquery' ), '1.3.2', 1 );
 
 	$scripts->add( 'thickbox', "/wp-includes/js/thickbox/thickbox.js", array('jquery'), '3.1-20121105', 1 );
 	did_action( 'init' ) && $scripts->localize( 'thickbox', 'thickboxL10n', array(
@@ -375,6 +376,9 @@ function wp_default_scripts( &$scripts ) {
 		'allowedFiles' => __( 'Allowed Files' ),
 	) );
 
+	$scripts->add( 'customize-header-models',  "/wp-admin/js/header-models.js",  array( 'underscore', 'backbone' ), false, 1 );
+	$scripts->add( 'customize-header-views',  "/wp-admin/js/header-views.js",  array( 'jquery', 'underscore', 'jquery-slimscroll', 'imgareaselect', 'customize-header-models' ), false, 1 );
+
 	$scripts->add( 'accordion', "/wp-admin/js/accordion$suffix.js", array( 'jquery' ), false, 1 );
 
 	$scripts->add( 'shortcode', "/wp-includes/js/shortcode$suffix.js", array( 'underscore' ), false, 1 );
@@ -594,7 +598,7 @@ function wp_default_styles( &$styles ) {
 	$styles->add( 'login',              "/wp-admin/css/login$suffix.css", array( 'buttons', 'open-sans', 'dashicons' ) );
 	$styles->add( 'install',            "/wp-admin/css/install$suffix.css", array( 'buttons', 'open-sans' ) );
 	$styles->add( 'wp-color-picker',    "/wp-admin/css/color-picker$suffix.css" );
-	$styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie' ) );
+	$styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie', 'imgareaselect' ) );
 	$styles->add( 'ie',                 "/wp-admin/css/ie$suffix.css" );
 
 	$styles->add_data( 'ie', 'conditional', 'lte IE 7' );
