diff --git a/core/includes/form.inc b/core/includes/form.inc
index 06ee164..518fc63 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -9,6 +9,7 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Url;
+use Drupal\Component\Utility\Xss;
 use Drupal\Core\Form\FormInterface;
 use Drupal\Core\Form\BaseFormIdInterface;
 use Drupal\Core\Database\Database;
@@ -2694,7 +2695,7 @@ function _form_options_flatten($array) {
 }
 
 /**
- * Processes a select list form element.
+ * Processes a select list element.
  *
  * This process callback is mandatory for select fields, since all user agents
  * automatically preselect the first available option of single (non-multiple)
@@ -2762,26 +2763,27 @@ function form_process_select($element) {
 }
 
 /**
- * Returns HTML for a select form element.
+ * Prepares variables for select element templates.
+ *
+ * Default template: select.html.twig.
  *
  * It is possible to group options together; to do this, change the format of
  * $options to an associative array in which the keys are group labels, and the
  * values are associative arrays in the normal $options format.
  *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #title, #value, #options, #description, #extra,
  *     #multiple, #required, #name, #attributes, #size.
- *
- * @ingroup themeable
  */
-function theme_select($variables) {
+function template_preprocess_select(&$variables) {
   $element = $variables['element'];
   element_set_attributes($element, array('id', 'name', 'size'));
   _form_set_attributes($element, array('form-select'));
 
-  return '<select' . new Attribute($element['#attributes']) . '>' . form_select_options($element) . '</select>';
+  $variables['options'] = form_select_options($element);
+  $variables['attributes'] = $element['#attributes'];
 }
 
 /**
@@ -2883,94 +2885,79 @@ function form_get_options($element, $key) {
 }
 
 /**
- * Returns HTML for a fieldset form element and its children.
+ * Prepares variables for fieldset element templates.
  *
- * @param $variables
+ * Default template: fieldset.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #attributes, #children, #collapsed, #description, #id,
  *     #title, #value.
- *
- * @ingroup themeable
  */
-function theme_fieldset($variables) {
+function template_preprocess_fieldset(&$variables) {
   $element = $variables['element'];
   element_set_attributes($element, array('id'));
   _form_set_attributes($element, array('form-wrapper'));
 
-  if (!empty($element['#description'])) {
-    $description_id = $element['#attributes']['id'] . '--description';
-    $element['#attributes']['aria-describedby'] = $description_id;
-  }
-
-  $legend_attributes = array();
-  if (isset($element['#title_display']) && $element['#title_display'] == 'invisible') {
-    $legend_attributes['class'][] = 'visually-hidden';
-  }
+  $variables['attributes'] = $element['#attributes'];
 
-  $output = '<fieldset' . new Attribute($element['#attributes']) . '>';
   if (!empty($element['#title'])) {
-    // Always wrap fieldset legends in a SPAN for CSS positioning.
-    $output .= '<legend' . new Attribute($legend_attributes) . '><span class="fieldset-legend">' . $element['#title'] . '</span></legend>';
+    $variables['title'] = $element['#title'];
+    if (isset($element['#title_display']) && $element['#title_display'] == 'invisible') {
+      $variables['title_attributes']['class'] = array('visually-hidden');
+    }
   }
-  $output .= '<div class="fieldset-wrapper">';
-  if (!empty($element['#description'])) {
-    $attributes = array('class' => 'fieldset-description', 'id' => $description_id);
-    $output .= '<div' . new Attribute($attributes) . '>' . $element['#description'] . '</div>';
 
+  if (!empty($element['#description'])) {
+    $variables['description'] = $element['#description'];
+    $description_id = $element['#attributes']['id'] . '--description';
+    $variables['description_attributes'] = new Attribute(array(
+      'id' => $description_id,
+      'class' => array('fieldset-description'),
+      'aria-describedby' => $description_id,
+    ));
   }
-  $output .= $element['#children'];
-  if (isset($element['#value'])) {
-    $output .= $element['#value'];
-  }
-  $output .= '</div>';
-  $output .= "</fieldset>\n";
-  return $output;
+
+  $variables['children'] = $element['#children'];
+  $variables['value'] = (isset($element['#value'])) ? $element['#value'] : NULL;
 }
 
 /**
- * Returns HTML for a details form element and its children.
+ * Prepares variables for details element templates.
  *
- * @param $variables
+ * Default template: details.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
- *     Properties used: #attributes, #children, #collapsed, #description, #id,
- *     #title, #value.
+ *     Properties used: #attributes, #children, #collapsed, #collapsible,
+ *     #description, #id, #title, #value.
  *
  * @ingroup themeable
  */
-function theme_details($variables) {
+function template_preprocess_details(&$variables) {
   $element = $variables['element'];
-  element_set_attributes($element, array('id'));
-  _form_set_attributes($element, array('form-wrapper'));
 
-  $output = '<details' . new Attribute($element['#attributes']) . '>';
+  $variables['attributes'] = $element['#attributes'];
+  $variables['summary_attributes'] = new Attribute(array());
   if (!empty($element['#title'])) {
-    $summary_attributes = new Attribute(array(
-      'role' => 'button',
-    ));
+    $variables['summary_attributes']['role'] = 'button';
     if (!empty($element['#attributes']['id'])) {
-      $summary_attributes['aria-controls'] = $element['#attributes']['id'];
+      $variables['summary_attributes']['aria-controls'] = $element['#attributes']['id'];
     }
-    $summary_attributes['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE;
-    $summary_attributes['aria-pressed'] = $summary_attributes['aria-expanded'];
-    $output .= '<summary' . $summary_attributes . '>' . $element['#title'] . '</summary>';
-  }
-  $output .= '<div class="details-wrapper">';
-  if (!empty($element['#description'])) {
-    $output .= '<div class="details-description">' . $element['#description'] . '</div>';
-  }
-  $output .= $element['#children'];
-  if (isset($element['#value'])) {
-    $output .= $element['#value'];
+    $variables['summary_attributes']['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE;
+    $variables['summary_attributes']['aria-pressed'] = $variables['summary_attributes']['aria-expanded'];
   }
-  $output .= '</div>';
-  $output .= "</details>\n";
-  return $output;
+
+  $variables['title'] = (!empty($element['#title'])) ? $element['#title'] : '';
+  $variables['description'] = (!empty($element['#description'])) ? $element['#description'] : '';
+  $variables['children'] = (isset($element['#children'])) ? $element['#children'] : '';
+  $variables['value'] = (isset($element['#value'])) ? $element['#value'] : '';
 }
 
 /**
- * Prepares a #type 'radio' render element for theme_input().
+ * Adds form-specific attributes to a 'radio' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -2982,7 +2969,7 @@ function theme_details($variables) {
  *       all the attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__radio'.
  */
 function form_pre_render_radio($element) {
   $element['#attributes']['type'] = 'radio';
@@ -2997,34 +2984,34 @@ function form_pre_render_radio($element) {
 }
 
 /**
- * Returns HTML for a set of radio button form elements.
+ * Prepares variables for radios templates.
  *
- * @param $variables
+ * Default template: radios.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
- *     Properties used: #title, #value, #options, #description, #required,
- *     #attributes, #children.
- *
- * @ingroup themeable
+ *     Properties used: #attributes, #id, #children.
  */
-function theme_radios($variables) {
+function template_preprocess_radios(&$variables) {
   $element = $variables['element'];
-  $attributes = array();
   if (isset($element['#id'])) {
-    $attributes['id'] = $element['#id'];
-  }
-  $attributes['class'] = 'form-radios';
-  if (!empty($element['#attributes']['class'])) {
-    $attributes['class'] .= ' ' . implode(' ', $element['#attributes']['class']);
+    $variables['attributes']['id'] = $element['#id'];
   }
+  $variables['attributes']['class'] = (!empty($element['#attributes']['class'])) ? $element['#attributes']['class'] : array();
+  $variables['attributes']['class'][] = 'form-radios';
   if (isset($element['#attributes']['title'])) {
-    $attributes['title'] = $element['#attributes']['title'];
+    $variables['attributes']['title'] = $element['#attributes']['title'];
   }
-  return '<div' . new Attribute($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>';
+
+  $variables['children'] = !empty($element['#children']) ? $element['#children'] : '';
+
+  // Remove the disabled attribute on the wrapper.
+  unset($variables['attributes']['disabled']);
 }
 
 /**
- * Expand a password_confirm field into two text boxes.
+ * Expands a password_confirm field into two text boxes.
  */
 function form_process_password_confirm($element) {
   $element['pass1'] =  array(
@@ -3077,29 +3064,30 @@ function password_confirm_validate($element, &$element_state) {
 }
 
 /**
- * Returns HTML for an #date form element.
+ * Adds form-specific attributes to a 'date' #type element.
  *
  * Supports HTML5 types of 'date', 'datetime', 'datetime-local', and 'time'.
  * Falls back to a plain textfield. Used as a sub-element by the datetime
  * element type.
  *
- * @param array $variables
- *   An associative array containing:
- *   - element: An associative array containing the properties of the element.
- *     Properties used: #title, #value, #options, #description, #required,
- *     #attributes, #id, #name, #type, #min, #max, #step, #value, #size.
+ * @param array $element
+ *   An associative array containing the properties of the element.
+ *   Properties used: #title, #value, #options, #description, #required,
+ *   #attributes, #id, #name, #type, #min, #max, #step, #value, #size.
  *
- * @ingroup themeable
+ * Note: The input "name" attribute needs to be sanitized before output, which
+ *       is currently done by initializing Drupal\Core\Template\Attribute with
+ *       all the attributes.
+ *
+ * @return array
+ *   The $element with prepared variables ready for #theme 'input__date'.
  */
-function theme_date($variables) {
-  $element = $variables['element'];
-  if (empty($element['attribute']['type'])) {
-    $element['attribute']['type'] = 'date';
-  }
-  element_set_attributes($element, array('id', 'name', 'type', 'min', 'max', 'step', 'value', 'size'));
-  _form_set_attributes($element, array('form-' . $element['attribute']['type']));
+function form_pre_render_date($element) {
+  $element['#attributes']['type'] = 'date';
+  element_set_attributes($element, array('id', 'name', 'min', 'max', 'step', 'value', 'size'));
+  _form_set_attributes($element, array('form-date'));
 
-  return '<input' . new Attribute($element['#attributes']) . ' />';
+  return $element;
 }
 
 /**
@@ -3115,7 +3103,7 @@ function weight_value(&$form) {
 }
 
 /**
- * Expands a radios element into individual radio elements.
+ * Expands a #type 'radios' element into individual radio elements.
  */
 function form_process_radios($element) {
   if (count($element['#options']) > 0) {
@@ -3151,7 +3139,7 @@ function form_process_radios($element) {
 }
 
 /**
- * Prepares a #type 'checkbox' render element for theme_input().
+ * Adds form-specific attributes to a 'checkbox' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -3159,7 +3147,7 @@ function form_process_radios($element) {
  *   #attributes, #checked.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__checkbox'.
  */
 function form_pre_render_checkbox($element) {
   $element['#attributes']['type'] = 'checkbox';
@@ -3175,33 +3163,44 @@ function form_pre_render_checkbox($element) {
 }
 
 /**
- * Returns HTML for a set of checkbox form elements.
+ * Prepares variables for checkboxes templates.
  *
- * @param $variables
+ * Default template: checkboxes.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #children, #attributes.
- *
- * @ingroup themeable
  */
-function theme_checkboxes($variables) {
+function template_preprocess_checkboxes(&$variables) {
   $element = $variables['element'];
-  $attributes = array();
+
   if (isset($element['#id'])) {
-    $attributes['id'] = $element['#id'];
+    $variables['attributes']['id'] = $element['#id'];
   }
-  $attributes['class'][] = 'form-checkboxes';
+  $variables['attributes']['class'] = array();
+  $variables['attributes']['class'][] = 'form-checkboxes';
   if (!empty($element['#attributes']['class'])) {
-    $attributes['class'] = array_merge($attributes['class'], $element['#attributes']['class']);
+    if (is_array($element['#attributes']['class'])) {
+      foreach ($element['#attributes']['class'] as $class) {
+        $variables['attributes']['class'][] = $class;
+      }
+    }
+    else {
+      $variables['attributes']['class'][] = $element['#attributes']['class'];
+    }
   }
   if (isset($element['#attributes']['title'])) {
-    $attributes['title'] = $element['#attributes']['title'];
+    $variables['attributes']['title'] = $element['#attributes']['title'];
   }
-  return '<div' . new Attribute($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>';
+  $variables['children'] = (!empty($element['#children'])) ? $element['#children'] : '';
+
+  // Remove the disabled attribute on the wrapper.
+  unset($variables['attributes']['disabled']);
 }
 
 /**
- * Adds form element theming to an element if its title or description is set.
+ * Adds form element themeing to an element if its title or description is set.
  *
  * This is used as a pre render function for checkboxes and radios.
  */
@@ -3434,7 +3433,9 @@ function form_process_container($element, &$form_state) {
 }
 
 /**
- * Returns HTML for a table with radio buttons or checkboxes.
+ * Prepares a 'tableselect' #type element for rendering.
+ *
+ * Adds a column of radio buttons or checkboxes for each row of a table.
  *
  * @param $variables
  *   An associative array containing:
@@ -3472,11 +3473,8 @@ function form_process_container($element, &$form_state) {
  *       '#empty' => t('No content available.'),
  *     );
  *     @endcode
- *
- * @ingroup themeable
  */
-function theme_tableselect($variables) {
-  $element = $variables['element'];
+function form_pre_render_tableselect(array $element) {
   $rows = array();
   $header = $element['#header'];
   if (!empty($element['#options'])) {
@@ -3516,7 +3514,7 @@ function theme_tableselect($variables) {
     // checkboxes/radios in the first table column.
     if ($element['#js_select']) {
       // Add a "Select all" checkbox.
-      drupal_add_library('system', 'drupal.tableselect');
+      $element['#attached']['library'][] = array('system', 'drupal.tableselect');
       array_unshift($header, array('class' => array('select-all')));
     }
     else {
@@ -3525,7 +3523,10 @@ function theme_tableselect($variables) {
       array_unshift($header, '');
     }
   }
-  return theme('table', array('header' => $header, 'rows' => $rows, 'empty' => $element['#empty'], 'attributes' => $element['#attributes']));
+  $element['#header'] = $header;
+  $element['#rows'] = $rows;
+
+  return $element;
 }
 
 /**
@@ -3617,7 +3618,6 @@ function form_process_tableselect($element) {
  *   The processed element.
  *
  * @see form_process_tableselect()
- * @see theme_tableselect()
  */
 function form_process_table($element, &$form_state) {
   if ($element['#tableselect']) {
@@ -3910,7 +3910,7 @@ function form_process_group(&$element, &$form_state) {
 }
 
 /**
- * Adds form element theming to details.
+ * Adds form-specific attributes to a 'details' #type element.
  *
  * @param $element
  *   An associative array containing the properties and children of the
@@ -3920,11 +3920,13 @@ function form_process_group(&$element, &$form_state) {
  *   The modified element.
  */
 function form_pre_render_details($element) {
-  // The .form-wrapper class is required for #states to treat details like
-  // containers.
+  element_set_attributes($element, array('id'));
   if (!isset($element['#attributes']['class'])) {
     $element['#attributes']['class'] = array();
   }
+  // The .form-wrapper class is required for #states to treat details like
+  // containers.
+  _form_set_attributes($element, array('form-wrapper'));
 
   // Collapsible details.
   $element['#attached']['library'][] = array('system', 'drupal.collapse');
@@ -4058,18 +4060,20 @@ function form_pre_render_vertical_tabs($element) {
 }
 
 /**
- * Returns HTML for an element's children details as vertical tabs.
+ * Prepares an element's children details for vertical tabs templates.
  *
- * @param $variables
+ * Default template: vertical-tabs.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties and children of
  *     the details element. Properties used: #children.
- *
- * @ingroup themeable
  */
-function theme_vertical_tabs($variables) {
-  $element = $variables['element'];
-  return '<div data-vertical-tabs-panes>' . $element['#children'] . '</div>';
+function template_preprocess_vertical_tabs(&$variables) {
+  $variables['attributes'] = array(
+    'data-vertical-tabs-panes' => TRUE,
+  );
+  $variables['children'] = $variables['element']['#children'];
 }
 
 /**
@@ -4137,37 +4141,20 @@ function form_process_autocomplete($element, &$form_state) {
 }
 
 /**
- * Preprocesses variables for theme_input().
+ * Prepares variables for input templates.
  *
- * @param array $variables
- *   An associative array containing:
- *   - element: An associative array containing the properties of the element.
- *
- * @ingroup themeable
- */
-function template_preprocess_input(&$variables) {
-  $element = $variables['element'];
-  $variables['attributes'] = new Attribute($element['#attributes']);
-}
-
-/**
- * Returns HTML for an input form element.
+ * Default template: input.html.twig.
  *
  * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
- *     Properties used: #attributes.
- *
- * @ingroup themeable
  */
-function theme_input($variables) {
-  $element = $variables['element'];
-  $attributes = $variables['attributes'];
-  return '<input' . $attributes . ' />' . drupal_render_children($element);
+function template_preprocess_input(&$variables) {
+  $variables['attributes'] = $variables['element']['#attributes'];
 }
 
 /**
- * Prepares a #type 'button' render element for theme_input().
+ * Adds form-specific attributes to a 'button' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4177,7 +4164,7 @@ function theme_input($variables) {
  * styles the following button_types appropriately: 'primary', 'danger'.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__button'.
  */
 function form_pre_render_button($element) {
   $element['#attributes']['type'] = 'submit';
@@ -4198,7 +4185,7 @@ function form_pre_render_button($element) {
 }
 
 /**
- * Prepares a #type 'image_button' render element for theme_input().
+ * Adds form-specific attributes to an 'image_button' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4208,7 +4195,7 @@ function form_pre_render_button($element) {
  * styles the following button_types appropriately: 'primary', 'danger'.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__image_button'.
  */
 function form_pre_render_image_button($element) {
   $element['#attributes']['type'] = 'image';
@@ -4235,14 +4222,14 @@ function form_pre_render_image_button($element) {
 }
 
 /**
- * Prepares a #type 'hidden' render element for theme_input().
+ * Adds form-specific attributes to a 'hidden' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
  *   Properties used: #name, #value, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__hidden'.
  */
 function form_pre_render_hidden($element) {
   $element['#attributes']['type'] = 'hidden';
@@ -4252,7 +4239,7 @@ function form_pre_render_hidden($element) {
 }
 
 /**
- * Prepares a #type 'textfield' render element for theme_input().
+ * Adds form-specific attributes to a 'textfield' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4260,7 +4247,7 @@ function form_pre_render_hidden($element) {
  *   #placeholder, #required, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__textfield'.
  */
 function form_pre_render_textfield($element) {
   $element['#attributes']['type'] = 'text';
@@ -4271,7 +4258,7 @@ function form_pre_render_textfield($element) {
 }
 
 /**
- * Prepares a #type 'email' render element for theme_input().
+ * Adds form-specific attributes to an 'email' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4279,7 +4266,7 @@ function form_pre_render_textfield($element) {
  *   #placeholder, #required, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__email'.
  */
 function form_pre_render_email($element) {
   $element['#attributes']['type'] = 'email';
@@ -4304,7 +4291,7 @@ function form_validate_email(&$element, &$form_state) {
 }
 
 /**
- * Prepares a #type 'tel' render element for theme_input().
+ * Adds form-specific attributes to a 'tel' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4312,7 +4299,7 @@ function form_validate_email(&$element, &$form_state) {
  *   #placeholder, #required, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__tel'.
  */
 function form_pre_render_tel($element) {
   $element['#attributes']['type'] = 'tel';
@@ -4323,7 +4310,7 @@ function form_pre_render_tel($element) {
 }
 
 /**
- * Prepares a #type 'number' render element for theme_input().
+ * Adds form-specific attributes to a 'number' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4331,7 +4318,7 @@ function form_pre_render_tel($element) {
  *   #required, #attributes, #step, #size.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__number'.
  */
 function form_pre_render_number($element) {
   $element['#attributes']['type'] = 'number';
@@ -4342,7 +4329,7 @@ function form_pre_render_number($element) {
 }
 
 /**
- * Prepares a #type 'range' render element for theme_input().
+ * Adds form-specific attributes to a 'range' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4350,7 +4337,7 @@ function form_pre_render_number($element) {
  *   #step.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__range'.
  */
 function form_pre_render_range($element) {
   $element['#attributes']['type'] = 'range';
@@ -4431,7 +4418,7 @@ function form_type_range_value($element, $input = FALSE) {
 }
 
 /**
- * Prepares a #type 'url' render element for theme_input().
+ * Adds form-specific attributes to a 'url' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4439,7 +4426,7 @@ function form_type_range_value($element, $input = FALSE) {
  *   #placeholder, #required, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__url'.
  */
 function form_pre_render_url($element) {
   $element['#attributes']['type'] = 'url';
@@ -4450,7 +4437,7 @@ function form_pre_render_url($element) {
 }
 
 /**
- * Prepares a #type 'search' render element for theme_input().
+ * Adds form-specific attributes to a 'search' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4458,7 +4445,7 @@ function form_pre_render_url($element) {
  *   #placeholder, #required, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__search'.
  */
 function form_pre_render_search($element) {
   $element['#attributes']['type'] = 'search';
@@ -4505,14 +4492,14 @@ function form_validate_color(&$element, &$form_state) {
 }
 
 /**
- * Prepares a #type 'color' render element for theme_input().
+ * Adds form-specific attriutes to a 'color' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
  *   Properties used: #title, #value, #description, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__color'.
  */
 function form_pre_render_color($element) {
   $element['#attributes']['type'] = 'color';
@@ -4523,61 +4510,59 @@ function form_pre_render_color($element) {
 }
 
 /**
- * Returns HTML for a form.
+ * Prepares variables for form templates.
  *
- * @param $variables
+ * Default template: form.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #action, #method, #attributes, #children
- *
- * @ingroup themeable
  */
-function theme_form($variables) {
+function template_preprocess_form(&$variables) {
   $element = $variables['element'];
+  element_set_attributes($element, array('method', 'id'));
   if (isset($element['#action'])) {
     $element['#attributes']['action'] = Url::stripDangerousProtocols($element['#action']);
   }
-  element_set_attributes($element, array('method', 'id'));
   if (empty($element['#attributes']['accept-charset'])) {
     $element['#attributes']['accept-charset'] = "UTF-8";
   }
-  // Anonymous DIV to satisfy XHTML compliance.
-  return '<form' . new Attribute($element['#attributes']) . '><div>' . $element['#children'] . '</div></form>';
+  $variables['attributes'] = $element['#attributes'];
+  $variables['children'] = $element['#children'];
 }
 
 /**
- * Returns HTML for a textarea form element.
+ * Prepares variables for textarea form element templates.
  *
- * @param $variables
+ * Default template: textarea.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #title, #value, #description, #rows, #cols,
  *     #placeholder, #required, #attributes, #resizable
- *
- * @ingroup themeable
  */
-function theme_textarea($variables) {
+function template_preprocess_textarea(&$variables) {
   $element = $variables['element'];
   element_set_attributes($element, array('id', 'name', 'rows', 'cols', 'placeholder'));
   _form_set_attributes($element, array('form-textarea'));
 
-  $wrapper_attributes = array(
+  $variables['wrapper_attributes'] = new Attribute(array(
     'class' => array('form-textarea-wrapper'),
-  );
+  ));
 
   // Add resizable behavior.
   if (!empty($element['#resizable'])) {
     $element['#attributes']['class'][] = 'resize-' . $element['#resizable'];
   }
 
-  $output = '<div' . new Attribute($wrapper_attributes) . '>';
-  $output .= '<textarea' . new Attribute($element['#attributes']) . '>' . String::checkPlain($element['#value']) . '</textarea>';
-  $output .= '</div>';
-  return $output;
+  $variables['attributes'] = $element['#attributes'];
+  $variables['value'] = String::checkPlain($element['#value']);
 }
 
 /**
- * Prepares a #type 'password' render element for theme_input().
+ * Adds form-specific attributes to a 'password' #type element.
  *
  * @param array $element
  *   An associative array containing the properties of the element.
@@ -4585,7 +4570,7 @@ function theme_textarea($variables) {
  *   #placeholder, #required, #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__password'.
  */
 function form_pre_render_password($element) {
   $element['#attributes']['type'] = 'password';
@@ -4623,7 +4608,7 @@ function form_process_weight($element) {
 }
 
 /**
- * Prepares a #type 'file' render element for theme_input().
+ * Adds form-specific attributes to a 'file' #type element.
  *
  * For assistance with handling the uploaded file correctly, see the API
  * provided by file.inc.
@@ -4634,7 +4619,7 @@ function form_process_weight($element) {
  *   #attributes.
  *
  * @return array
- *   The $element with prepared variables ready for theme_input().
+ *   The $element with variables prepared for #theme 'input__file'.
  */
 function form_pre_render_file($element) {
   $element['#attributes']['type'] = 'file';
@@ -4693,109 +4678,84 @@ function form_process_file($element) {
  * but the parent element should have neither. Use this carefully because a
  * field without an associated label can cause accessibility challenges.
  *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #title, #title_display, #description, #id, #required,
  *     #children, #type, #name.
- *
- * @ingroup themeable
  */
-function theme_form_element($variables) {
-  $element = &$variables['element'];
+function template_preprocess_form_element(&$variables) {
+  $element = $variables['element'];
 
   // This function is invoked as theme wrapper, but the rendered form element
   // may not necessarily have been processed by form_builder().
   $element += array(
     '#title_display' => 'before',
   );
-
+  // If #title is not set, we don't display any label or required marker.
+  if (!isset($element['#title'])) {
+    $element['#title_display'] = 'none';
+  }
+  // We call it a label, though.
+  $variables['label_display'] = $element['#title_display'];
+  // Label returns empty string in some cases.
+  $variables['label'] = array('#theme' => 'form_element_label', '#element' => $element);
   // Take over any #wrapper_attributes defined by the element.
   // @todo Temporary hack for #type 'item'.
   // @see http://drupal.org/node/1829202
-  if (isset($element['#wrapper_attributes'])) {
-    $attributes = $element['#wrapper_attributes'];
-  }
-  // Add element #id for #type 'item'.
-  if (isset($element['#markup']) && !empty($element['#id'])) {
-    $attributes['id'] = $element['#id'];
-  }
+  $variables['attributes'] = (isset($element['#wrapper_attributes']) ? $element['#wrapper_attributes'] : array('class' => array()));
   // Add element's #type and #name as class to aid with JS/CSS selectors.
-  $attributes['class'][] = 'form-item';
+  $variables['attributes']['class'][] = 'form-item';
   if (!empty($element['#type'])) {
-    $attributes['class'][] = 'form-type-' . strtr($element['#type'], '_', '-');
+    $variables['attributes']['class'][] = 'form-type-' . strtr($element['#type'], '_', '-');
   }
   if (!empty($element['#name'])) {
-    $attributes['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
+    $variables['attributes']['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
   }
   // Add a class for disabled elements to facilitate cross-browser styling.
   if (!empty($element['#attributes']['disabled'])) {
-    $attributes['class'][] = 'form-disabled';
-  }
-  $output = '<div' . new Attribute($attributes) . '>' . "\n";
-
-  // If #title is not set, we don't display any label or required marker.
-  if (!isset($element['#title'])) {
-    $element['#title_display'] = 'none';
+    $variables['attributes']['class'][] = 'form-disabled';
   }
-  $prefix = isset($element['#field_prefix']) ? '<span class="field-prefix">' . $element['#field_prefix'] . '</span> ' : '';
-  $suffix = isset($element['#field_suffix']) ? ' <span class="field-suffix">' . $element['#field_suffix'] . '</span>' : '';
-
-  switch ($element['#title_display']) {
-    case 'before':
-    case 'invisible':
-      $output .= ' ' . theme('form_element_label', $variables);
-      $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
-      break;
-
-    case 'after':
-      $output .= ' ' . $prefix . $element['#children'] . $suffix;
-      $output .= ' ' . theme('form_element_label', $variables) . "\n";
-      break;
-
-    case 'none':
-    case 'attribute':
-      // Output no label and no required marker, only the children.
-      $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
-      break;
-  }
-
-  if (!empty($element['#description'])) {
-    $attributes = array('class' => 'description');
+  // Add element #id for #type 'item'.
+  if (isset($element['#markup']) && !empty($element['#id'])) {
+    $variables['attributes']['id'] = $element['#id'];
+  }
+  $variables['prefix'] = isset($element['#field_prefix']) ? $element['#field_prefix'] : '';
+  $variables['suffix'] = isset($element['#field_suffix']) ? $element['#field_suffix'] : '';
+  $variables['children'] = isset($element['#children']) ? $element['#children'] : NULL;
+  $variables['description'] = !empty($element['#description']) ? $element['#description'] : '';
+  if ($variables['description']) {
+    $variables['description_attributes'] = new Attribute(array('class' => 'description'));
     if (!empty($element['#id'])) {
-      $attributes['id'] = $element['#id'] . '--description';
+      $variables['description_attributes']['id'] = $element['#id'] . '--description';
     }
-    $output .= '<div' . new Attribute($attributes) . '>' . $element['#description'] . "</div>\n";
   }
-
-  $output .= "</div>\n";
-
-  return $output;
 }
 
 /**
- * Returns HTML for a marker for required form elements.
+ * Prepares variables for form element required marker templates.
  *
- * @param $variables
+ * Default template: form-element-required.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
- *
- * @ingroup themeable
  */
-function theme_form_required_marker($variables) {
-  $attributes = array(
+function template_preprocess_form_required_marker(&$variables) {
+  $variables['attributes'] = array(
     'class' => 'form-required',
     'title' => t('This field is required.'),
   );
-  return '<abbr' . new Attribute($attributes) . '>*</abbr>';
 }
 
 /**
- * Returns HTML for a form element label and required marker.
+ * Prepares variables for form element label templates.
+ *
+ * Default template: form-element-label.html.twig.
  *
  * Form element labels include the #title and a #required marker. The label is
  * associated with the element itself by the element #id. Labels may appear
- * before or after elements, depending on theme_form_element() and
+ * before or after elements, depending on form_element template and
  * #title_display.
  *
  * This function will not be called for elements with no labels, depending on
@@ -4803,44 +4763,72 @@ function theme_form_required_marker($variables) {
  * this function will output no label (''). For required elements that have an
  * empty #title, this will output the required marker alone within the label.
  * The label will use the #id to associate the marker with the field that is
- * required. That is especially important for screenreader users to know
- * which field is required.
+ * required. That is especially important for screenreader users to know which
+ * field is required.
  *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #required, #title, #id, #value, #description.
- *
- * @ingroup themeable
  */
-function theme_form_element_label($variables) {
-  $element = $variables['element'];
-
-  // If title and required marker are both empty, output no label.
-  if ((!isset($element['#title']) || $element['#title'] === '') && empty($element['#required'])) {
-    return '';
-  }
-
-  // If the element is required, a required marker is appended to the label.
-  $required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : '';
-
-  $title = filter_xss_admin($element['#title']);
+function template_preprocess_form_element_label(&$variables) {
+  // @todo: Figure out how to do this differently (calling from form_element).
+  $element = $variables['element']['#element'];
 
-  $attributes = array();
-  // Style the label as class option to display inline with the element.
-  if ($element['#title_display'] == 'after') {
-    $attributes['class'] = 'option';
+  // If title and required marker are both empty, prepare no label.
+  if (empty($element['#required']) && (!isset($element['#title']) || $element['#title'] === '')) {
+    $variables['label'] = $variables['required'] = $variables['attributes'] = NULL;
   }
-  // Show label only to screen readers to avoid disruption in visual flows.
-  elseif ($element['#title_display'] == 'invisible') {
-    $attributes['class'] = 'visually-hidden';
+  else {
+    // If the element is required, a required marker is appended to the label.
+    $variables['label'] = (isset($element['#title'])) ? Xss::filterAdmin($element['#title']) : NULL;
+    $variables['required'] = (!empty($element['#required'])) ? array('#theme' => 'form_required_marker', '#element' => $element) : '';
+    // Associate the label with the field it is for.
+    if (!empty($element['#id'])) {
+      $variables['attributes']['for'] = $element['#id'];
+    }
+    // Add label positioning classes.
+    if (!empty($element['#title_display'])) {
+      $variables['attributes']['class'] = array();
+      // Style the label as class 'option' to display inline with the element.
+      // @todo: Use a more semantic class name like 'layout-inline-after'?
+      if ($element['#title_display'] == 'after') {
+        $variables['attributes']['class'][] = 'option';
+      }
+      // Show label only to screen readers to avoid disruption in visual flows.
+      elseif ($element['#title_display'] == 'invisible') {
+        $variables['attributes']['class'][] = 'visually-hidden';
+      }
+    }
   }
+}
 
-  if (!empty($element['#id'])) {
-    $attributes['for'] = $element['#id'];
+/**
+ * Prepares variables for exposed filters templates.
+ *
+ * Default template: exposed-filters.html.twig.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - form: An associative array containing the structure of the form.
+ */
+function template_preprocess_exposed_filters(&$variables) {
+  $form = $variables['form'];
+
+  $variables['items'] = array();
+  if (isset($form['current'])) {
+    $items = array();
+    foreach (element_children($form['current']) as $key) {
+      $items[] = $form['current'][$key];
+    }
+    $variables['items'][] = array(
+      '#theme' => 'item_list',
+      '#items' => $items,
+      '#attributes' => array(
+        'class' => array('clearfix', 'current-filters'),
+      ),
+    );
   }
-
-  return '<label' . new Attribute($attributes) . '>' . t('!title!required', array('!title' => $title, '!required' => $required)) . '</label>';
 }
 
 /**
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index e49bb76..0f606e7 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2342,20 +2342,16 @@ function theme_indentation($variables) {
 }
 
 /**
- * Returns HTML to wrap child elements in a container.
+ * Prepares variables for container templates.
  *
- * Used for grouped form items. Can also be used as a #theme_wrapper for any
- * renderable element, to surround it with a <div> and add attributes such as
- * classes or an HTML id.
+ * Default template: container.html.twig.
  *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties of the element.
  *     Properties used: #id, #attributes, #children.
- *
- * @ingroup themeable
  */
-function theme_container($variables) {
+function template_preprocess_container(&$variables) {
   $element = $variables['element'];
   // Ensure #attributes is set.
   $element += array('#attributes' => array());
@@ -2370,7 +2366,8 @@ function theme_container($variables) {
     $element['#attributes']['class'][] = 'form-wrapper';
   }
 
-  return '<div' . new Attribute($element['#attributes']) . '>' . $element['#children'] . '</div>';
+  $variables['children'] = $element['#children'];
+  $variables['attributes'] = $element['#attributes'];
 }
 
 /**
@@ -3117,51 +3114,59 @@ function drupal_common_theme() {
     // From form.inc.
     'input' => array(
       'render element' => 'element',
+      'template' => 'input',
     ),
     'select' => array(
       'render element' => 'element',
+      'template' => 'select',
     ),
     'fieldset' => array(
       'render element' => 'element',
+      'template' => 'fieldset',
     ),
     'details' => array(
       'render element' => 'element',
+      'template' => 'details',
     ),
     'radios' => array(
       'render element' => 'element',
-    ),
-    'date' => array(
-      'render element' => 'element',
+      'template' => 'radios',
     ),
     'exposed_filters' => array(
       'render element' => 'form',
+      'template' => 'exposed-filters',
     ),
     'checkboxes' => array(
       'render element' => 'element',
+      'template' => 'checkboxes',
     ),
     'form' => array(
       'render element' => 'element',
+      'template' => 'form',
     ),
     'textarea' => array(
       'render element' => 'element',
-    ),
-    'tableselect' => array(
-      'render element' => 'element',
+      'template' => 'textarea',
     ),
     'form_element' => array(
       'render element' => 'element',
+      'template' => 'form-element',
     ),
     'form_required_marker' => array(
       'render element' => 'element',
+      'template' => 'form-required-marker',
     ),
     'form_element_label' => array(
       'render element' => 'element',
+      'template' => 'form-element-label',
     ),
     'vertical_tabs' => array(
       'render element' => 'element',
+      'template' => 'vertical-tabs',
     ),
     'container' => array(
       'render element' => 'element',
+      'template' => 'container',
     ),
   );
 }
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
index 3d20f6d..b0be2de 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUpdateTest.php
@@ -167,7 +167,9 @@ function testUpdateImportSourceRemote() {
     $this->drupalGet('admin/reports/translations/check');
 
     // Check the status on the Available translation status page.
-    $this->assertRaw('<label class="visually-hidden" for="edit-langcodes-de">Update German</label>', 'German language found');
+    $elements = $this->xpath('//label[@class="visually-hidden" and @for="edit-langcodes-de" and text()=:value]', array(':value' => 'Update German'));
+    $this->assertTrue(!empty($elements), 'German language found');
+
     $this->assertText('Updates for: Contributed module one, Contributed module two, Custom module one, Locale test', 'Updates found');
     $this->assertText('Contributed module one (' . format_date($this->timestamp_now, 'html_date') . ')', 'Updates for Contrib module one');
     $this->assertText('Contributed module two (' . format_date($this->timestamp_new, 'html_date') . ')', 'Updates for Contrib module two');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
index 9ba4bf4..a618409 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
@@ -50,7 +50,7 @@ function testContainer() {
           '#type' => 'container',
           '#markup' => 'foo',
         ),
-        'expected' => '<div>foo</div>',
+        'expected' => '<div>foo</div>' . "\n",
       ),
       // Container with a class.
       array(
@@ -62,7 +62,7 @@ function testContainer() {
             'class' => 'bar',
           ),
         ),
-        'expected' => '<div class="bar">foo</div>',
+        'expected' => '<div class="bar">foo</div>' . "\n",
       ),
       // Container with children.
       array(
@@ -73,7 +73,7 @@ function testContainer() {
             '#markup' => 'foo',
           ),
         ),
-        'expected' => '<div>foo</div>',
+        'expected' => '<div>foo</div>' . "\n",
       ),
     );
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
index 4aa8eb8..b7a6f18 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -94,7 +94,7 @@ function testRequiredFields() {
     $elements['file']['empty_values'] = $empty_strings;
 
     // Regular expression to find the expected marker on required elements.
-    $required_marker_preg = '@<label.*<abbr class="form-required" title="This field is required\.">\*</abbr></label>@';
+    $required_marker_preg = '@<label.*<abbr class="form-required" title="This field is required\.">\*</abbr>\n</label>@';
 
     // Go through all the elements and all the empty values for them.
     foreach ($elements as $type => $data) {
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index abda14e..2c4ecde 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -235,7 +235,7 @@ function hook_queue_info_alter(&$queues) {
  *  - "#post_render": array of callables taking $children and $element.
  *  - "#submit": array of callback functions taking $form and $form_state.
  *  - "#title_display": optional string indicating if and how #title should be
- *    displayed, see theme_form_element() and theme_form_element_label().
+ *    displayed, see templates for form_element and form_element_label.
  *
  * @see hook_element_info_alter()
  * @see system_element_info()
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 03f9042..a164911 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -297,7 +297,7 @@ function system_element_info() {
     '#limit_validation_errors' => FALSE,
     '#process' => array('form_process_button', 'ajax_process_form'),
     '#pre_render' => array('form_pre_render_button'),
-    '#theme_wrappers' => array('input__submit'),
+    '#theme' => 'input__submit',
   );
   $types['button'] = array(
     '#input' => TRUE,
@@ -307,7 +307,7 @@ function system_element_info() {
     '#limit_validation_errors' => FALSE,
     '#process' => array('form_process_button', 'ajax_process_form'),
     '#pre_render' => array('form_pre_render_button'),
-    '#theme_wrappers' => array('input__button'),
+    '#theme' => 'input__button',
   );
   $types['image_button'] = array(
     '#input' => TRUE,
@@ -319,7 +319,7 @@ function system_element_info() {
     '#has_garbage_value' => TRUE,
     '#src' => NULL,
     '#pre_render' => array('form_pre_render_image_button'),
-    '#theme_wrappers' => array('input__image_button'),
+    '#theme' => 'input__image_button',
   );
   $types['textfield'] = array(
     '#input' => TRUE,
@@ -488,7 +488,8 @@ function system_element_info() {
   );
   $types['date'] = array(
     '#input' => TRUE,
-    '#theme' => 'date',
+    '#theme' => 'input__date',
+    '#pre_render' => array('form_pre_render_date'),
     '#theme_wrappers' => array('form_element'),
   );
   $types['file'] = array(
@@ -504,10 +505,11 @@ function system_element_info() {
     '#input' => TRUE,
     '#js_select' => TRUE,
     '#multiple' => TRUE,
+    '#pre_render' => array('form_pre_render_tableselect'),
     '#process' => array('form_process_tableselect'),
     '#options' => array(),
     '#empty' => '',
-    '#theme' => 'tableselect',
+    '#theme' => 'table__tableselect',
   );
 
   // Form structure.
@@ -3202,40 +3204,6 @@ function theme_system_config_form($variables) {
 }
 
 /**
- * Returns HTML for an exposed filter form.
- *
- * @param $variables
- *   An associative array containing:
- *   - form: An associative array containing the structure of the form.
- *
- * @return
- *   A string containing an HTML-formatted form.
- *
- * @ingroup themeable
- */
-function theme_exposed_filters($variables) {
-  $form = $variables['form'];
-  $output = '';
-
-  if (isset($form['current'])) {
-    $items = array();
-    foreach (element_children($form['current']) as $key) {
-      $items[] = $form['current'][$key];
-    }
-    $item_list = array(
-      '#theme' => 'item_list',
-      '#items' => $items,
-      '#attributes' => array('class' => array('clearfix', 'current-filters')),
-    );
-    $output .= drupal_render($item_list);
-  }
-
-  $output .= drupal_render_children($form);
-
-  return '<div class="exposed-filters">' . $output . '</div>';
-}
-
-/**
  * Implements hook_admin_paths().
  */
 function system_admin_paths() {
diff --git a/core/modules/system/templates/checkboxes.html.twig b/core/modules/system/templates/checkboxes.html.twig
new file mode 100644
index 0000000..00384d3
--- /dev/null
+++ b/core/modules/system/templates/checkboxes.html.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a 'checkboxes' #type form element.
+ *
+ * Available variables
+ * - attributes: A list of HTML attributes for the wrapper element.
+ * - children: The rendered checkboxes.
+ *
+ * @see template_preprocess_checkboxes()
+ *
+ * @ingroup themeable
+ */
+ @todo: remove this file once http://drupal.org/node/1819284 is resolved.
+ This is identical to core/modules/system/templates/container.html.twig
+#}
+<div{{ attributes }}>{{ children }}</div>
diff --git a/core/modules/system/templates/container.html.twig b/core/modules/system/templates/container.html.twig
new file mode 100644
index 0000000..933a201
--- /dev/null
+++ b/core/modules/system/templates/container.html.twig
@@ -0,0 +1,15 @@
+{#
+/**
+ * @file
+ * Default theme implementation of a container used to wrap child elements.
+ *
+ * Available variables:
+ * - attributes: HTML attributes for the containing element.
+ * - children: The rendered child elements of the container.
+ *
+ * @see template_preprocess_container()
+ *
+ * @ingroup themeable
+ */
+#}
+<div{{ attributes }}>{{ children }}</div>
diff --git a/core/modules/system/templates/datetime.html.twig b/core/modules/system/templates/datetime.html.twig
index 25ef788..0af45c3 100644
--- a/core/modules/system/templates/datetime.html.twig
+++ b/core/modules/system/templates/datetime.html.twig
@@ -7,19 +7,20 @@
  * - timestamp: (optional) A UNIX timestamp for the datetime attribute. If the
  *   datetime cannot be represented as a UNIX timestamp, use a valid datetime
  *   attribute value in attributes.datetime.
- * - text: (optional) The content to display within the <time> element. Set
- *   'html' to TRUE if this value is already sanitized for output in HTML.
+ * - text: (optional) The content to display within the <time> element. If this
+ *   value is already sanitized for output in HTML the html flag will be TRUE.
  *   Defaults to a human-readable representation of the timestamp value or the
  *   datetime attribute value using format_date().
  * - attributes: (optional) HTML attributes to apply to the <time> element.
  *   A datetime attribute in 'attributes' overrides the 'timestamp'. To
  *   create a valid datetime attribute value from a UNIX timestamp, use
  *   format_date() with one of the predefined 'html_*' formats.
- * - html: (optional) Whether 'text' is HTML markup (TRUE) or plain-text
- *   (FALSE). Defaults to FALSE. For example, to use a SPAN tag within the
- *   TIME element, this must be set to TRUE, or the SPAN tag will be escaped.
- *   It is the responsibility of the caller to properly sanitize the value
- *   contained in 'text' (or within the SPAN tag in aforementioned example).
+ * - html: (optional) A flag indicating whether 'text' is HTML markup (TRUE) or
+ *   plain-text (FALSE). Defaults to FALSE. For example, to use a SPAN tag
+ *   within the TIME element, this must be set to TRUE, or the SPAN tag will be
+ *   escaped. It is the responsibility of the caller to properly sanitize the
+ *   value contained in 'text' (or within the SPAN tag in aforementioned
+ *   example).
  *
  * @see template_preprocess_datetime()
  * @see http://www.w3.org/TR/html5-author/the-time-element.html#attr-time-datetime
diff --git a/core/modules/system/templates/details.html.twig b/core/modules/system/templates/details.html.twig
new file mode 100644
index 0000000..aef051e
--- /dev/null
+++ b/core/modules/system/templates/details.html.twig
@@ -0,0 +1,33 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a details element.
+ *
+ * Available variables
+ * - attributes: A list of HTML attributes for the details element.
+ * - title: (optional) The title of the element, may not be set.
+ * - description: (optional) The description of the element, may not be set.
+ * - children: (optional) The children of the element, may not be set.
+ * - value: (optional) The value of the element, may not be set.
+ *
+ * @see template_preprocess_details()
+ *
+ * @ingroup themeable
+ */
+#}
+<details{{ attributes }}>
+  {% if title %}
+    <summary{{ summary_attributes }}>{{ title }}</summary>
+  {% endif %}
+  <div class="details-wrapper">
+    {% if description %}
+      <div class="details-description">{{ description }}</div>
+    {% endif %}
+    {% if children %}
+      {{ children }}
+    {% endif %}
+    {% if value %}
+      {{ value }}
+    {% endif %}
+  </div>
+</details>
diff --git a/core/modules/system/templates/exposed-filters.html.twig b/core/modules/system/templates/exposed-filters.html.twig
new file mode 100644
index 0000000..0d8d7a8
--- /dev/null
+++ b/core/modules/system/templates/exposed-filters.html.twig
@@ -0,0 +1,20 @@
+{#
+/**
+ * @file
+ * Default theme implementation of an exposed filter form.
+ *
+ * Available variables:
+ * - form: The rendered exposed filter form.
+ * - items: A list of current filters.
+ *
+ * @see template_preprocess_exposed_filters()
+ *
+ * @ingroup themeable
+ */
+#}
+<div class="exposed-filters">
+  {% if items %}
+    {{ items }}
+  {% endif %}
+  {{ form }}
+</div>
diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig
new file mode 100644
index 0000000..0980057
--- /dev/null
+++ b/core/modules/system/templates/fieldset.html.twig
@@ -0,0 +1,35 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a fieldset element and its children.
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the fieldset element.
+ * - title: Title of the fieldset, intended for use as the text of the legend.
+ * - title_attributes: A list of HTML attributes to apply to the legend.
+ * - description: The description of the fieldset.
+ * - description_attributes: A list of HTML attributes to apply to the
+ *   description container.
+ * - children: The rendered child elements of the fieldset.
+ * - value: The value of the fieldset.
+ *
+ * @see template_preprocess_fieldset()
+ *
+ * @ingroup themeable
+ */
+#}
+<fieldset{{ attributes }}>
+  {% if title is defined %}
+    {# Always wrap fieldset legends in a SPAN for CSS positioning. #}
+    <legend{{ title_attributes }}><span class="fieldset-legend">{{ title }}</span></legend>
+  {% endif %}
+  <div class="fieldset-wrapper">
+    {% if description is defined %}
+      <div{{ description_attributes }}>{{ description }}</div>
+    {% endif %}
+    {{ children }}
+    {% if value %}
+      {{ value }}
+    {% endif %}
+  </div>
+</fieldset>
diff --git a/core/modules/system/templates/form-element-label.html.twig b/core/modules/system/templates/form-element-label.html.twig
new file mode 100644
index 0000000..44caae6
--- /dev/null
+++ b/core/modules/system/templates/form-element-label.html.twig
@@ -0,0 +1,28 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form element label.
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the label.
+ * - label: (optional) The text of the label, may not be set if there is no
+ *   title and the element is not required.
+ * - required: A rendered marker indicating the field is required, or an empty
+ *   string if the field is not required.
+ *
+ * @see template_preprocess_form_label()
+ * @see form-required-marker.html.twig
+ *
+ * @ingroup themeable
+ */
+#}
+{% if (label is not empty) or (required is not empty) %}
+  <label{{ attributes }}>
+    {%- if label is not empty -%}
+      {{ label }}
+    {%- endif -%}
+    {%- if required is not empty -%}
+      {{ required }}
+    {%- endif -%}
+  </label>
+{% endif %}
diff --git a/core/modules/system/templates/form-element.html.twig b/core/modules/system/templates/form-element.html.twig
new file mode 100644
index 0000000..234a387
--- /dev/null
+++ b/core/modules/system/templates/form-element.html.twig
@@ -0,0 +1,57 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form element.
+ *
+ * Available variables:
+ * - attributes: HTML attributes for the containing element.
+ * - prefix: (optional) The form element prefix, may not be set.
+ * - suffix: (optional) The form element suffix, may not be set.
+ * - label: The rendered label. @see form-element-label.html.twig.
+ * - label_display: Label display setting. It can have these values:
+ *   - before: The label is output before the element. This is the default. The
+ *     label includes the #title and the required marker, if #required.
+ *   - after: The label is output after the element. For example, this is used
+ *     for radio and checkbox #type elements as set in system_element_info().
+ *     If the #title is empty but the field is #required, the label will
+ *     contain only the required marker.
+ *   - invisible: Labels are critical for screen readers to enable them to
+ *     properly navigate through forms but can be visually distracting. This
+ *     property hides the label for everyone except screen readers.
+ *   - attribute: Set the title attribute on the element to create a tooltip but
+ *     output no label element. This is supported only for checkboxes and radios
+ *     in form_pre_render_conditional_form_element(). It is used where a visual
+ *     label is not needed, such as a table of checkboxes where the row and
+ *     column provide the context. The tooltip will include the title and
+ *     required marker.
+ * - description: (optional) A description of the form element, may not be set.
+ * - description_attributes: (optional) A list of HTML attributes to apply to
+ *   the wrapper of the description. Will only be set when description is set.
+ *
+ * @see template_preprocess_form_element()
+ *
+ * @ingroup themeable
+ */
+#}
+<div{{ attributes }}>
+  {% if (label is not empty) and (label_display in ['before', 'invisible']) %}
+    {{ label }}
+  {% endif %}
+  {% if prefix is not empty %}
+    <span class="field-prefix">{{ prefix }}</span>
+  {% endif %}
+  {% if children is not empty %}
+    {{ children }}
+  {% endif %}
+  {% if suffix is not empty %}
+    <span class="field-suffix">{{ suffix }}</span>
+  {% endif %}
+  {% if (label is not empty) and (label_display == 'after') %}
+    {{ label }}
+  {% endif %}
+  {% if description is not empty %}
+    <div{{ description_attributes }}>
+      {{ description }}
+    </div>
+  {% endif %}
+</div>
diff --git a/core/modules/system/templates/form-required-marker.html.twig b/core/modules/system/templates/form-required-marker.html.twig
new file mode 100644
index 0000000..711f7d5
--- /dev/null
+++ b/core/modules/system/templates/form-required-marker.html.twig
@@ -0,0 +1,14 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form element required marker.
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the marker.
+ *
+ * @see template_preprocess_form_required_marker()
+ *
+ * @ingroup themeable
+ */
+#}
+<abbr{{ attributes }}>*</abbr>
diff --git a/core/modules/system/templates/form.html.twig b/core/modules/system/templates/form.html.twig
new file mode 100644
index 0000000..f2549a3
--- /dev/null
+++ b/core/modules/system/templates/form.html.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a form.
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the form element.
+ * - children: The rendered child form elements.
+ *
+ * @see template_preprocess_form()
+ *
+ * @ingroup themeable
+ */
+#}
+<form{{ attributes }}>
+  {{ children }}
+</form>
diff --git a/core/modules/system/templates/input.html.twig b/core/modules/system/templates/input.html.twig
new file mode 100644
index 0000000..2d2d41a
--- /dev/null
+++ b/core/modules/system/templates/input.html.twig
@@ -0,0 +1,33 @@
+{#
+/**
+ * @file
+ * Default theme implementation for an input element.
+ *
+ * This covers input types:
+ * - button
+ * - checkbox
+ * - date
+ * - email
+ * - file
+ * - hidden
+ * - image_button
+ * - number
+ * - radio
+ * - range
+ * - password
+ * - tel
+ * - textfield
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the input element.
+ * - element: The rendered child elements.
+ *
+ * @see template_preprocess_input()
+ *
+ * @ingroup themeable
+ */
+#}
+<input{{ attributes }}/>
+{% if element is not empty %}
+  {{ element }}
+{% endif %}
diff --git a/core/modules/system/templates/radios.html.twig b/core/modules/system/templates/radios.html.twig
new file mode 100644
index 0000000..3d995cb
--- /dev/null
+++ b/core/modules/system/templates/radios.html.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a #type 'radios' form element.
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the container element.
+ * - children: The rendered radio elements.
+ *
+ * @see template_preprocess_radios()
+ *
+ * @ingroup themeable
+ */
+ @todo: remove this file once http://drupal.org/node/1819284 is resolved.
+ This is identical to core/modules/system/templates/container.html.twig
+#}
+<div{{ attributes }}>{{ children }}</div>
diff --git a/core/modules/system/templates/select.html.twig b/core/modules/system/templates/select.html.twig
new file mode 100644
index 0000000..2554731
--- /dev/null
+++ b/core/modules/system/templates/select.html.twig
@@ -0,0 +1,15 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a select element.
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the select element.
+ * - options: The rendered select option elements.
+ *
+ * @see template_preprocess_select()
+ *
+ * @ingroup themeable
+ */
+#}
+<select{{ attributes }}>{{ options }}</select>
diff --git a/core/modules/system/templates/textarea.html.twig b/core/modules/system/templates/textarea.html.twig
new file mode 100644
index 0000000..16819e6
--- /dev/null
+++ b/core/modules/system/templates/textarea.html.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a textarea element.
+ *
+ * Available variables:
+ * - attributes: A list of HTML attributes for the textarea element.
+ * - value: Plain text value of the textarea.
+ *
+ * @see template_preprocess_textarea()
+ *
+ * @ingroup themeable
+ */
+#}
+<div{{ wrapper_attributes }}>
+  <textarea{{ attributes }}>{{ value }}</textarea>
+</div>
diff --git a/core/modules/system/templates/vertical-tabs.html.twig b/core/modules/system/templates/vertical-tabs.html.twig
new file mode 100644
index 0000000..aec5da5
--- /dev/null
+++ b/core/modules/system/templates/vertical-tabs.html.twig
@@ -0,0 +1,16 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a set of vertical tabs.
+ *
+ * Available variables
+ * - children: The rendered child fieldset elements.
+ *
+ * @see template_preprocess_vertical_tabs()
+ *
+ * @ingroup themeable
+ */
+ @todo: remove this file once http://drupal.org/node/1819284 is resolved.
+ This is identical to core/modules/system/templates/container.html.twig
+#}
+<div{{ attributes }}>{{ children }}</div>
