diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
index f905f75..5bfc6b3 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
@@ -153,8 +153,22 @@ protected function compileString(\Twig_NodeInterface $body) {
             $args = $args->getNode('node');
           }
           if ($args instanceof \Twig_Node_Expression_GetAttr) {
-            $argName = $args->getNode('attribute')->getAttribute('value');
-            $expr = $n;
+            $argName = array();
+            // Reuse the incoming expression.
+            $expr = $args;
+            // Assemble a valid argument name by walking through the expression.
+            $argName[] = $args->getNode('attribute')->getAttribute('value');
+            while ($args->hasNode('node')) {
+              $args = $args->getNode('node');
+              if ($args instanceof \Twig_Node_Expression_Name) {
+                $argName[] = $args->getAttribute('name');
+              }
+              else {
+                $argName[] = $args->getNode('attribute')->getAttribute('value');
+              }
+            }
+            $argName = array_reverse($argName);
+            $argName = implode('.', $argName);
           }
           else {
             $argName = $n->getAttribute('name');
diff --git a/core/modules/field/src/Entity/FieldInstanceConfig.php b/core/modules/field/src/Entity/FieldInstanceConfig.php
index ab7dd47..0292ec9 100644
--- a/core/modules/field/src/Entity/FieldInstanceConfig.php
+++ b/core/modules/field/src/Entity/FieldInstanceConfig.php
@@ -7,12 +7,14 @@
 
 namespace Drupal\field\Entity;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Field\TypedData\FieldItemDataDefinition;
 use Drupal\field\FieldException;
+use Drupal\field\FieldConfigInterface;
 use Drupal\field\FieldInstanceConfigInterface;
 
 /**
@@ -202,7 +204,7 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
   /**
    * The data definition of a field item.
    *
-   * @var \Drupal\Core\TypedData\FieldItemDataDefinition
+   * @var \Drupal\Core\Field\TypedData\FieldItemDataDefinition
    */
   protected $itemDefinition;
 
@@ -218,7 +220,8 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
    *   - field_name: The name of the field this is an instance of. This only
    *     supports non-deleted fields.
    *   - field_uuid: (optional) The uuid of the field this is an instance of.
-   *     If present, this has priority over the 'field_name' value.
+   *     If present and the instance is marked as 'deleted', this has priority
+   *     over the 'field_name' value for retrieving the related field.
    *   - entity_type: required.
    *   - bundle: required.
    *
@@ -231,47 +234,21 @@ class FieldInstanceConfig extends ConfigEntityBase implements FieldInstanceConfi
    * @ingroup field_crud
    */
   public function __construct(array $values, $entity_type = 'field_instance_config') {
-    // Load the corresponding field. In case the instance was deleted, load the
-    // field based on the UUID, otherwise use the field name.
-    if (!empty($values['deleted'])) {
-      if ($fields = entity_load_multiple_by_properties('field_config', array('uuid' => $values['field_uuid'], 'include_deleted' => TRUE))) {
-        $field = current($fields);
-      }
-      else {
-        throw new FieldException(format_string('Attempt to create an instance of field @field_name that does not exist on entity type @entity_type.', array('@field_name' => $values['field_name'], '@entity_type' => $values['entity_type'])));
-      }
+    // Check required properties.
+    if (empty($values['field_name'])) {
+      throw new FieldException('Attempt to create an instance of a field without a field_name.');
     }
-    elseif (isset($values['field_name']) && isset($values['entity_type'])) {
-      $field = FieldConfig::loadByName($values['entity_type'], $values['field_name']);
-      if (empty($field)) {
-        throw new FieldException(format_string('Attempt to create an instance of field @field_name that does not exist on entity type @entity_type.', array('@field_name' => $values['field_name'], '@entity_type' => $values['entity_type'])));
-      }
-      $values['field_uuid'] = $field->uuid();
+    if (empty($values['entity_type'])) {
+      throw new FieldException(String::format('Attempt to create an instance of field @field_name without an entity_type.', array('@field_name' => $values['field_name'])));
     }
-    else {
-      throw new FieldException('Attempt to create an instance of an unspecified field.');
+    if (empty($values['bundle'])) {
+      throw new FieldException(String::format('Attempt to create an instance of field @field_name without a bundle.', array('@field_name' => $values['field_name'])));
     }
 
-    // At this point, we have a Field we can assign.
-    $this->field = $field;
-
     // Discard the 'field_type' entry that is added in config records to ease
     // schema generation. See self::toArray().
     unset($values['field_type']);
 
-    // Check required properties.
-    if (empty($values['entity_type'])) {
-      throw new FieldException(format_string('Attempt to create an instance of field @field_name without an entity_type.', array('@field_name' => $this->field->name)));
-    }
-    if (empty($values['bundle'])) {
-      throw new FieldException(format_string('Attempt to create an instance of field @field_name without a bundle.', array('@field_name' => $this->field->name)));
-    }
-
-    // 'Label' defaults to the field name (mostly useful for field instances
-    // created in tests).
-    $values += array(
-      'label' => $this->field->name,
-    );
     parent::__construct($values, $entity_type);
   }
 
@@ -319,6 +296,24 @@ public function toArray() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function postCreate(EntityStorageInterface $storage) {
+    // Validate that we have a valid field for this instance. This throws an
+    // exception if the field is invalid.
+    $field = $this->getField();
+
+    // Make sure the field_uuid is populated.
+    $this->field_uuid = $field->uuid();
+
+    // 'Label' defaults to the field name (mostly useful for field instances
+    // created in tests).
+    if (empty($this->label)) {
+      $this->label = $this->field->name;
+    }
+  }
+
+  /**
    * Overrides \Drupal\Core\Entity\Entity::preSave().
    *
    * @throws \Drupal\field\FieldException
@@ -330,9 +325,11 @@ public function preSave(EntityStorageInterface $storage) {
     $entity_manager = \Drupal::entityManager();
     $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
 
+    $field = $this->getField();
+
     if ($this->isNew()) {
       // Set the default instance settings.
-      $this->settings += $field_type_manager->getDefaultInstanceSettings($this->field->type);
+      $this->settings += $field_type_manager->getDefaultInstanceSettings($field->type);
       // Notify the entity storage.
       $entity_manager->getStorage($this->entity_type)->onInstanceCreate($this);
     }
@@ -348,7 +345,7 @@ public function preSave(EntityStorageInterface $storage) {
         throw new FieldException("Cannot change an existing instance's field.");
       }
       // Set the default instance settings.
-      $this->settings += $field_type_manager->getDefaultInstanceSettings($this->field->type);
+      $this->settings += $field_type_manager->getDefaultInstanceSettings($field->type);
       // Notify the entity storage.
       $entity_manager->getStorage($this->entity_type)->onInstanceUpdate($this);
     }
@@ -364,7 +361,7 @@ public function preSave(EntityStorageInterface $storage) {
   public function calculateDependencies() {
     parent::calculateDependencies();
     // Manage dependencies.
-    $this->addDependency('entity', $this->field->getConfigDependencyName());
+    $this->addDependency('entity', $this->getField()->getConfigDependencyName());
     $bundle_entity_type_id = \Drupal::entityManager()->getDefinition($this->entity_type)->getBundleEntityType();
     if ($bundle_entity_type_id != 'bundle') {
       // If the target entity type uses entities to manage its bundles then
@@ -473,6 +470,34 @@ public static function postDelete(EntityStorageInterface $storage, array $instan
    * {@inheritdoc}
    */
   public function getField() {
+    if (!$this->field) {
+      // Load the corresponding field.
+      // - If the instance is deleted (case of field purge), load the field
+      //   based on the UUID.
+      // - Otherwise (regular case), fetch the field from the EntityManager
+      //   registry.
+      if (!empty($this->deleted)) {
+        if ($fields = entity_load_multiple_by_properties('field_config', array('uuid' => $this->field_uuid, 'include_deleted' => TRUE))) {
+          $field = current($fields);
+        }
+        else {
+          throw new FieldException(String::format('Attempt to create an instance of field @field_name that does not exist on entity type @entity_type.', array('@field_name' => $this->field_name, '@entity_type' => $this->entity_type)));
+        }
+      }
+      else {
+        $fields = \Drupal::entityManager()->getFieldStorageDefinitions($this->entity_type);
+        if (!isset($fields[$this->field_name])) {
+          throw new FieldException(String::format('Attempt to create an instance of field @field_name that does not exist on entity type @entity_type.', array('@field_name' => $this->field_name, '@entity_type' => $this->entity_type)));
+        }
+        if (!$fields[$this->field_name] instanceof FieldConfigInterface) {
+          throw new FieldException(String::format('Attempt to create a configurable instance of non-configurable field @field_name.', array('@field_name' => $this->field_name, '@entity_type' => $this->entity_type)));
+        }
+        $field = $fields[$this->field_name];
+      }
+
+      $this->field = $field;
+    }
+
     return $this->field;
   }
 
@@ -480,21 +505,21 @@ public function getField() {
    * {@inheritdoc}
    */
   public function getName() {
-    return $this->field->name;
+    return $this->field_name;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getType() {
-    return $this->field->type;
+    return $this->getField()->type;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getSettings() {
-    return $this->settings + $this->field->getSettings();
+    return $this->settings + $this->getField()->getSettings();
   }
 
   /**
@@ -505,7 +530,7 @@ public function getSetting($setting_name) {
       return $this->settings[$setting_name];
     }
     else {
-      return $this->field->getSetting($setting_name);
+      return $this->getField()->getSetting($setting_name);
     }
   }
 
@@ -513,21 +538,21 @@ public function getSetting($setting_name) {
    * {@inheritdoc}
    */
   public function getProvider() {
-    return $this->field->getProvider();
+    return $this->getField()->getProvider();
   }
 
   /**
    * {@inheritdoc}
    */
   public function isTranslatable() {
-    return $this->field->translatable;
+    return $this->getField()->translatable;
   }
 
   /**
    * {@inheritdoc}
    */
   public function isRevisionable() {
-    return $this->field->isRevisionable();
+    return $this->getField()->isRevisionable();
   }
 
   /**
@@ -575,7 +600,7 @@ public function getDescription() {
    * {@inheritdoc}
    */
   public function getCardinality() {
-    return $this->field->cardinality;
+    return $this->getField()->cardinality;
   }
 
   /**
@@ -589,7 +614,7 @@ public function isRequired() {
    * {@inheritdoc}
    */
   public function isMultiple() {
-    return $this->field->isMultiple();
+    return $this->getField()->isMultiple();
   }
 
   /**
@@ -752,49 +777,49 @@ public function getItemDefinition() {
    * {@inheritdoc}
    */
   public function getPropertyDefinition($name) {
-    return $this->field->getPropertyDefinition($name);
+    return $this->getField()->getPropertyDefinition($name);
   }
 
   /**
    * {@inheritdoc}
    */
   public function getPropertyDefinitions() {
-    return $this->field->getPropertyDefinitions();
+    return $this->getField()->getPropertyDefinitions();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getPropertyNames() {
-    return $this->field->getPropertyNames();
+    return $this->getField()->getPropertyNames();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getMainPropertyName() {
-    return $this->field->getMainPropertyName();
+    return $this->getField()->getMainPropertyName();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getSchema() {
-    return $this->field->getSchema();
+    return $this->getField()->getSchema();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getColumns() {
-    return $this->field->getColumns();
+    return $this->getField()->getColumns();
   }
 
   /**
    * {@inheritdoc}
    */
   public function hasCustomStorage() {
-    return $this->field->hasCustomStorage();
+    return $this->getField()->hasCustomStorage();
   }
 
   /**
diff --git a/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php b/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php
index 7ab37dc..2b18307 100644
--- a/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php
+++ b/core/modules/field/tests/src/FieldInstanceConfigEntityUnitTest.php
@@ -87,12 +87,12 @@ public function testCalculateDependencies() {
       ->method('getConfigDependencyName')
       ->will($this->returnValue('field.field.test_entity_type.test_field'));
 
-    $field_storage = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityStorageInterface');
-    $field_storage
-      ->expects($this->any())
-      ->method('load')
-      ->with('test_entity_type.test_field')
-      ->will($this->returnValue($field));
+    $this->entityManager->expects($this->any())
+      ->method('getFieldStorageDefinitions')
+      ->with('test_entity_type')
+      ->will($this->returnValue(array(
+        $field->name => $field,
+      )));
 
     // Mock the interfaces necessary to create a dependency on a bundle entity.
     $bundle_entity = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityInterface');
@@ -109,10 +109,8 @@ public function testCalculateDependencies() {
 
     $this->entityManager->expects($this->any())
       ->method('getStorage')
-      ->will($this->returnValueMap(array(
-        array('field_config', $field_storage),
-        array('bundle_entity_type', $storage),
-      )));
+      ->with('bundle_entity_type')
+      ->will($this->returnValue($storage));
 
     $target_entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
     $target_entity_type->expects($this->any())
diff --git a/core/modules/locale/src/Tests/LocaleContentTest.php b/core/modules/locale/src/Tests/LocaleContentTest.php
index 093da50..7c80148 100644
--- a/core/modules/locale/src/Tests/LocaleContentTest.php
+++ b/core/modules/locale/src/Tests/LocaleContentTest.php
@@ -182,25 +182,25 @@ function testContentTypeDirLang() {
 
     // Check if English node does not have lang tag.
     $this->drupalGet('node/' . $nodes['en']->id());
-    $pattern = '|id="node-' . $nodes['en']->id() . '"[^<>]*lang="en"|';
+    $pattern = '|class="[^"]*node[^"]*"[^<>]*lang="en"|';
     $this->assertNoPattern($pattern, 'The lang tag has not been assigned to the English node.');
 
     // Check if English node does not have dir tag.
-    $pattern = '|id="node-' . $nodes['en']->id() . '"[^<>]*dir="ltr"|';
+    $pattern = '|class="[^"]*node[^"]*"[^<>]*dir="ltr"|';
     $this->assertNoPattern($pattern, 'The dir tag has not been assigned to the English node.');
 
     // Check if Arabic node has lang="ar" & dir="rtl" tags.
     $this->drupalGet('node/' . $nodes['ar']->id());
-    $pattern = '|id="node-' . $nodes['ar']->id() . '"[^<>]*lang="ar" dir="rtl"|';
+    $pattern = '|class="[^"]*node[^"]*"[^<>]*lang="ar" dir="rtl"|';
     $this->assertPattern($pattern, 'The lang and dir tags have been assigned correctly to the Arabic node.');
 
     // Check if Spanish node has lang="es" tag.
     $this->drupalGet('node/' . $nodes['es']->id());
-    $pattern = '|id="node-' . $nodes['es']->id() . '"[^<>]*lang="es"|';
+    $pattern = '|class="[^"]*node[^"]*"[^<>]*lang="es"|';
     $this->assertPattern($pattern, 'The lang tag has been assigned correctly to the Spanish node.');
 
     // Check if Spanish node does not have dir="ltr" tag.
-    $pattern = '|id="node-' . $nodes['es']->id() . '"[^<>]*lang="es" dir="ltr"|';
+    $pattern = '|class="[^"]*node[^"]*"[^<>]*lang="es" dir="ltr"|';
     $this->assertNoPattern($pattern, 'The dir tag has not been assigned to the Spanish node.');
   }
 
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 38e047b..32d3295 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -579,7 +579,7 @@ function node_is_page(NodeInterface $node) {
 function node_preprocess_html(&$variables) {
   // If on an individual node page, add the node type to body classes.
   if (($node = \Drupal::request()->attributes->get('node')) && $node instanceof NodeInterface) {
-    $variables['attributes']['class'][] = drupal_html_class('node-type-' . $node->getType());
+    $variables['attributes']['class'][] = drupal_html_class('node--type-' . $node->getType());
   }
 }
 
@@ -642,9 +642,9 @@ function template_preprocess_node(&$variables) {
     '#account' => $node->getOwner(),
     '#link_options' => array('attributes' => array('rel' => 'author')),
   );
-  $variables['name'] = drupal_render($username);
+  $variables['author_name'] = drupal_render($username);
 
-  $variables['node_url'] = $node->url('canonical', array(
+  $variables['url'] = $node->url('canonical', array(
     'language' => $node->language(),
   ));
   $variables['label'] = $variables['elements']['title'];
@@ -660,23 +660,17 @@ function template_preprocess_node(&$variables) {
   // Display post information only on certain node types.
   // Avoid loading the entire node type config entity here that may not exist.
   $node_type_config = \Drupal::config('node.type.' . $node->bundle());
+  // Used by RDF to add attributes around the author and date submitted.
+  $variables['author_attributes'] = new Attribute();
   // Display submitted by default.
   $variables['display_submitted'] = $node_type_config->isNew() || $node_type_config->get('settings.node.submitted');
   if ($variables['display_submitted']) {
-    $variables['submitted'] = t('Submitted by !username on !datetime', array('!username' => $variables['name'], '!datetime' => $variables['date']));
     if (theme_get_setting('features.node_user_picture')) {
       // To change user picture settings (e.g. image style), edit the 'compact'
       // view mode on the User entity. Note that the 'compact' view mode might
       // not be configured, so remember to always check the theme setting first.
-      $variables['user_picture'] = user_view($node->getOwner(), 'compact');
+      $variables['author_picture'] = user_view($node->getOwner(), 'compact');
     }
-    else {
-      $variables['user_picture'] = array();
-    }
-  }
-  else {
-    $variables['submitted'] = '';
-    $variables['user_picture'] = '';
   }
 
   // Add article ARIA role.
@@ -684,23 +678,22 @@ function template_preprocess_node(&$variables) {
 
   // Gather node classes.
   $variables['attributes']['class'][] = 'node';
-  $variables['attributes']['class'][] = drupal_html_class('node-' . $node->bundle());
+  $variables['attributes']['class'][] = drupal_html_class('node--type-' . $node->bundle());
   if ($node->isPromoted()) {
-    $variables['attributes']['class'][] = 'promoted';
+    $variables['attributes']['class'][] = 'node--promoted';
   }
   if ($node->isSticky()) {
-    $variables['attributes']['class'][] = 'sticky';
+    $variables['attributes']['class'][] = 'node--sticky';
   }
   if (!$node->isPublished()) {
-    $variables['attributes']['class'][] = 'unpublished';
+    $variables['attributes']['class'][] = 'node--unpublished';
   }
   if ($variables['view_mode']) {
-    $variables['attributes']['class'][] = drupal_html_class('view-mode-' . $variables['view_mode']);
+    $variables['attributes']['class'][] = drupal_html_class('node--view-mode-' . $variables['view_mode']);
   }
   if (isset($variables['preview'])) {
-    $variables['attributes']['class'][] = 'preview';
+    $variables['attributes']['class'][] = 'node--preview';
   }
-  $variables['content_attributes']['class'][] = 'content';
 }
 
 /**
@@ -1213,9 +1206,9 @@ function node_form_system_themes_admin_form_submit($form, &$form_state) {
  *
  * Next, all implementations of hook_node_access() will be called. Each
  * implementation may explicitly allow, explicitly deny, or ignore the access
- * request. If at least one module says to deny the request, it will be rejected.
- * If no modules deny the request and at least one says to allow it, the request
- * will be permitted.
+ * request. If at least one module says to deny the request, it will be
+ * rejected. If no modules deny the request and at least one says to allow it,
+ * the request will be permitted.
  *
  * If all modules ignore the access request, then the node_access table is used
  * to determine access. All node access modules are queried using
@@ -1550,7 +1543,8 @@ function node_access_rebuild($batch_mode = FALSE) {
       // Try to allocate enough time to rebuild node grants
       drupal_set_time_limit(240);
 
-      // Rebuild newest nodes first so that recent content becomes available quickly.
+      // Rebuild newest nodes first so that recent content becomes available
+      // quickly.
       $entity_query = \Drupal::entityQuery('node');
       $entity_query->sort('nid', 'DESC');
       $nids = $entity_query->execute();
diff --git a/core/modules/node/src/Tests/NodeFieldMultilingualTestCase.php b/core/modules/node/src/Tests/NodeFieldMultilingualTestCase.php
index fd83b93..42dfafb 100644
--- a/core/modules/node/src/Tests/NodeFieldMultilingualTestCase.php
+++ b/core/modules/node/src/Tests/NodeFieldMultilingualTestCase.php
@@ -133,9 +133,9 @@ function testMultilingualDisplaySettings() {
 
     // Check if node body is showed.
     $this->drupalGet('node/' . $node->id());
-    $body = $this->xpath('//article[@id=:id]//div[@class=:class]/descendant::p', array(
-      ':id' => 'node-' . $node->id(),
-      ':class' => 'content',
+     $body = $this->xpath('//article[contains(concat(" ", normalize-space(@class), " "), :node-class)]//div[contains(concat(" ", normalize-space(@class), " "), :content-class)]/descendant::p', array(
+      ':node-class' => ' node ',
+      ':content-class' => 'node__content',
     ));
     $this->assertEqual(current($body), $node->body->value, 'Node body found.');
   }
diff --git a/core/modules/node/src/Tests/NodePostSettingsTest.php b/core/modules/node/src/Tests/NodePostSettingsTest.php
index a7478a8..7cfaa7e 100644
--- a/core/modules/node/src/Tests/NodePostSettingsTest.php
+++ b/core/modules/node/src/Tests/NodePostSettingsTest.php
@@ -45,7 +45,7 @@ function testPagePostInfo() {
 
     // Check that the post information is displayed.
     $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
-    $elements = $this->xpath('//*[contains(@class,:class)]', array(':class' => 'submitted'));
+    $elements = $this->xpath('//div[contains(@class, :class)]', array(':class' => 'node__submitted'));
     $this->assertEqual(count($elements), 1, 'Post information is displayed.');
     $node->delete();
 
@@ -61,7 +61,7 @@ function testPagePostInfo() {
     $this->drupalPostForm('node/add/page', $edit, t('Save'));
 
     // Check that the post information is displayed.
-    $elements = $this->xpath('//*[contains(@class,:class)]', array(':class' => 'submitted'));
+    $elements = $this->xpath('//div[contains(@class, :class)]', array(':class' => 'node__submitted'));
     $this->assertEqual(count($elements), 0, 'Post information is not displayed.');
   }
 }
diff --git a/core/modules/node/src/Tests/NodeTitleTest.php b/core/modules/node/src/Tests/NodeTitleTest.php
index 9b503ff..784125c 100644
--- a/core/modules/node/src/Tests/NodeTitleTest.php
+++ b/core/modules/node/src/Tests/NodeTitleTest.php
@@ -42,7 +42,8 @@ function setUp() {
    */
   function testNodeTitle() {
     // Create "Basic page" content with title.
-    // Add the node to the frontpage so we can test if teaser links are clickable.
+    // Add the node to the frontpage so we can test if teaser links are
+    // clickable.
     $settings = array(
       'title' => $this->randomName(8),
       'promote' => 1,
@@ -60,7 +61,7 @@ function testNodeTitle() {
     $this->assertEqual(current($this->xpath($xpath)), $node->label(), 'Node breadcrumb is equal to node title.', 'Node');
 
     // Test node title in comment preview.
-    $this->assertEqual(current($this->xpath('//article[@id=:id]/h2/a/span', array(':id' => 'node-' . $node->id()))), $node->label(), 'Node preview title is equal to node title.', 'Node');
+    $this->assertEqual(current($this->xpath('//article[contains(concat(" ", normalize-space(@class), " "), :node-class)]/h2/a/span', array(':node-class' => ' node--type-' . $node->bundle() . ' '))), $node->label(), 'Node preview title is equal to node title.', 'Node');
 
     // Test node title is clickable on teaser list (/node).
     $this->drupalGet('node');
diff --git a/core/modules/node/templates/node.html.twig b/core/modules/node/templates/node.html.twig
index c1ac815..c80eecb 100644
--- a/core/modules/node/templates/node.html.twig
+++ b/core/modules/node/templates/node.html.twig
@@ -5,11 +5,11 @@
  *
  * Available variables:
  * - node: Full node entity.
- *   - id: The node ID
+ *   - id: The node ID.
  *   - bundle: The type of the node, for example, "page" or "article".
  *   - authorid: The user ID of the node author.
- *   - createdtime: Formatted creation date. Preprocess functions can reformat it by
- *     calling format_date() with the desired parameters on
+ *   - createdtime: Formatted creation date. Preprocess functions can
+ *     reformat it by calling format_date() with the desired parameters on
  *     $variables['node']->getCreatedTime().
  *   - promoted: Whether the node is promoted to the front page.
  *   - sticky: Whether the node is 'sticky'. Sticky nodes are ordered above
@@ -20,31 +20,32 @@
  *   or print a subset such as {{ content.field_example }}. Use
  *   {{ content|without('field_example') %} to temporarily suppress the printing
  *   of a given child element.
- * - user_picture: The node author's information as loaded from the 'compact'
- *   view mode for the user entity.
+ * - author_picture: The node author user entity, rendered using the "compact"
+ *   view mode.
+ * - metadata: Metadata for this node.
  * - date: Formatted creation date. Preprocess functions can reformat it by
  *   calling format_date() with the desired parameters on
  *   $variables['created'].
- * - name: Themed username of node author output from theme_username().
- * - node_url: Direct URL of the current node.
+ * - author_name: Themed username of node author output from theme_username().
+ * - url: Direct URL of the current node.
  * - display_submitted: Whether submission information should be displayed.
- * - submitted: Submission information created from name and date during
- *   template_preprocess_node().
  * - attributes: HTML attributes for the containing element.
  *   The attributes.class element may contain one or more of the following
  *   classes:
  *   - node: The current template type (also known as a "theming hook").
- *   - node-[type]: The current node type. For example, if the node is a
- *     "Article" it would result in "node-article". Note that the machine
+ *   - node--[type]: The current node type. For example, if the node is a
+ *     "Article" it would result in "node--article". Note that the machine
  *     name will often be in a short form of the human readable label.
- *   - view-mode-[view_mode]: The View Mode of the node; for example, a teaser
- *     would result in: "view-mode-teaser", and full: "view-mode-full".
- *   - preview: Whether a node is in preview mode.
+ *   - node--view-mode-[view_mode]: The View Mode of the node; for example, a
+ *     teaser would result in: "node--view-mode-teaser", and
+ *     full: "node--view-mode-full".
+ *   - node--preview: Whether a node is in preview mode.
  *   The following are controlled through the node publishing options.
- *   - promoted: Appears on nodes promoted to the front page.
- *   - sticky: Appears on nodes ordered above other non-sticky nodes in teaser
- *     listings.
- *   - unpublished: Appears on unpublished nodes visible only to site admins.
+ *   - node--promoted: Appears on nodes promoted to the front page.
+ *   - node--sticky: Appears on nodes ordered above other non-sticky nodes in
+ *     teaser listings.
+ *   - node--unpublished: Appears on unpublished nodes visible only to site
+ *     admins.
  * - title_prefix: Additional output populated by modules, intended to be
  *   displayed in front of the main title tag that appears in the template.
  * - title_suffix: Additional output populated by modules, intended to be
@@ -76,27 +77,34 @@
  * @ingroup themeable
  */
 #}
-<article id="node-{{ node.id }}" class="{{ attributes.class }} clearfix"{{ attributes|without('id', 'class') }}>
+<article{{ attributes }}>
 
   {{ title_prefix }}
   {% if not page %}
     <h2{{ title_attributes }}>
-      <a href="{{ node_url }}" rel="bookmark">{{ label }}</a>
+      <a href="{{ url }}" rel="bookmark">{{ label }}</a>
     </h2>
   {% endif %}
   {{ title_suffix }}
 
   {% if display_submitted %}
-    <footer>
-      {{ user_picture }}
-      <p class="submitted">{{ submitted }}</p>
+    <footer class="node__meta">
+      {{ author_picture }}
+      <div class="node__submitted {{ author_attributes.class }}"{{ author_attributes|without('class') }}>
+        {% trans %}Submitted by {{ author_name|passthrough }} on {{ date }}{% endtrans %}
+        {{ metadata }}
+      </div>
     </footer>
   {% endif %}
 
-  <div{{ content_attributes }}>
+  <div class="node__content {{ content_attributes.class }}"{{ content_attributes|without('class') }}>
     {{ content|without('links') }}
   </div>
 
-  {{ content.links }}
+  {% if content.links %}
+    <div class="node__links">
+      {{ content.links }}
+    </div>
+  {% endif %}
 
 </article>
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 8ea735b..dc97773 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -279,7 +279,7 @@ function rdf_preprocess_node(&$variables) {
   $bundle = $variables['node']->bundle();
   $mapping = rdf_get_mapping('node', $bundle);
   $bundle_mapping = $mapping->getPreparedBundleMapping('node', $bundle);
-  $variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
+  $variables['attributes']['about'] = empty($variables['url']) ? NULL: $variables['url'];
   $variables['attributes']['typeof'] = empty($bundle_mapping['types']) ? NULL : $bundle_mapping['types'];
 
   // Adds RDFa markup for the node title as metadata because wrapping the title
@@ -297,20 +297,19 @@ function rdf_preprocess_node(&$variables) {
 
   // Adds RDFa markup for the relation between the node and its author.
   $author_mapping = $mapping->getPreparedFieldMapping('uid');
-  if (!empty($author_mapping['properties']) && $variables['submitted']) {
-    $author_attributes = array('rel' => $author_mapping['properties']);
-    $variables['submitted'] = '<span ' . new Attribute($author_attributes) . '>' . $variables['submitted'] . '</span>';
+  if (!empty($author_mapping['properties']) && $variables['display_submitted']) {
+    $variables['author_attributes']['rel'] = $author_mapping['properties'];
   }
 
   // Adds RDFa markup for the date.
   $created_mapping = $mapping->getPreparedFieldMapping('created');
-  if (!empty($created_mapping) && $variables['submitted']) {
+  if (!empty($created_mapping) && $variables['display_submitted']) {
     $date_attributes = rdf_rdfa_attributes($created_mapping, $variables['node']->getCreatedTime());
     $rdf_metadata = array(
       '#theme' => 'rdf_metadata',
       '#metadata' => array($date_attributes),
     );
-    $variables['submitted'] .= drupal_render($rdf_metadata);
+    $variables['metadata'] = drupal_render($rdf_metadata);
   }
 
   // Adds RDFa markup annotating the number of comments a node has.
@@ -323,7 +322,8 @@ function rdf_preprocess_node(&$variables) {
       $count = 0;
       foreach ($valid_fields as $field_name) {
         $count += $variables['node']->get($field_name)->comment_count;
-        // Adds RDFa markup for the comment count near the node title as metadata
+        // Adds RDFa markup for the comment count near the node title as
+        // metadata.
         $comment_count_attributes = rdf_rdfa_attributes($comment_count_mapping, $variables['node']->get($field_name)->comment_count);
         $variables['title_suffix']['rdf_meta_comment_count'] = array(
           '#theme' => 'rdf_metadata',
diff --git a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
index 1537393..34d78f1 100644
--- a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
+++ b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
@@ -30,6 +30,15 @@ public static function getInfo() {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $original_container = \Drupal::getContainer();
+    parent::setUp();
+    $this->assertNotIdentical(\Drupal::getContainer(), $original_container, 'KernelTestBase test creates a new container.');
+  }
+
+  /**
    * Tests expected behavior of setUp().
    */
   function testSetUp() {
diff --git a/core/modules/simpletest/src/Tests/SimpleTestTest.php b/core/modules/simpletest/src/Tests/SimpleTestTest.php
index a0e5738..b2fffb3 100755
--- a/core/modules/simpletest/src/Tests/SimpleTestTest.php
+++ b/core/modules/simpletest/src/Tests/SimpleTestTest.php
@@ -74,7 +74,9 @@ class: Drupal\Core\Cache\MemoryBackendFactory
 EOD;
       file_put_contents($this->siteDirectory . '/testing.services.yml', $yaml);
 
+      $original_container = \Drupal::getContainer();
       parent::setUp();
+      $this->assertNotIdentical(\Drupal::getContainer(), $original_container, 'WebTestBase test creates a new container.');
       // Create and log in an admin user.
       $this->drupalLogin($this->drupalCreateUser(array('administer unit tests')));
     }
diff --git a/core/modules/system/core.api.php b/core/modules/system/core.api.php
index 6637657..8cd29df 100644
--- a/core/modules/system/core.api.php
+++ b/core/modules/system/core.api.php
@@ -41,6 +41,7 @@
  *
  * @section other_essentials Other essential APIs
  *
+ * - @link plugins Plugin system @endlink
  * - @link i18n Internationalization @endlink
  * - @link cache Caching @endlink
  * - @link utility Utility classes and functions @endlink
@@ -735,7 +736,37 @@
  * @{
  * Overview of the Plugin API
  *
- * @todo write this
+ * Plugins is an overloaded term in Content Management Systems. In Drupal a plugin is used to extend the system by providing
+ * additional implementations of configurable objects.  Out of the box, Drupal provides many different kinds of plugins:
+ *
+ * - Action:
+ * - Archiver:
+ * - Condition:
+ * - Contextual link:
+ * - Blocks:
+ * - Field Formatter:
+ * - Field Type:
+ * - Field Widget:
+ * ...
+ * - TypedConfig:
+ *
+ * Creating a simple plugin
+ * Walkthrough creating a block
+ *
+ * What is a derivative?
+ *
+ * What is a plugin discovery?
+ *
+ * What is a plugin discovery decorator?
+ *
+ * What is a plugin factory?
+ *
+ * What is a plugin mapper?
+ *
+ * What is a plugin manager?
+ *
+ * Creating a plugin manager
+ * @todo finish writing this
  *
  * Additional documentation paragraphs need to be written, and functions,
  * classes, and interfaces need to be added to this topic.
diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css
index c8908b5..48623fd 100644
--- a/core/modules/system/css/system.theme.css
+++ b/core/modules/system/css/system.theme.css
@@ -6,10 +6,10 @@
 /**
  * Publishing status.
  */
-.unpublished {
+.node--unpublished {
   background-color: #fff4f4;
 }
-.preview {
+.node--preview {
   background-color: #ffffea;
 }
 
diff --git a/core/modules/system/src/DateFormatListBuilder.php b/core/modules/system/src/DateFormatListBuilder.php
index 53b31a5..02e268f 100644
--- a/core/modules/system/src/DateFormatListBuilder.php
+++ b/core/modules/system/src/DateFormatListBuilder.php
@@ -58,15 +58,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
   /**
    * {@inheritdoc}
    */
-  public function load() {
-    return array_filter(parent::load(), function ($entity) {
-      return !$entity->isLocked();
-    });
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function buildHeader() {
     $header['id'] = t('Machine name');
     $header['label'] = t('Name');
@@ -78,7 +69,12 @@ public function buildHeader() {
    * {@inheritdoc}
    */
   public function buildRow(EntityInterface $entity) {
-    $row['id'] = $entity->id();
+    if ($entity->isLocked()) {
+      $row['id'] =  $this->t('@entity_id (locked)', array('@entity_id' => $entity->id()));
+    }
+    else {
+      $row['id'] = $entity->id();
+    }
     $row['label'] = $this->getLabel($entity);
     $row['pattern'] = $this->dateService->format(REQUEST_TIME, $entity->id());
     return $row + parent::buildRow($entity);
diff --git a/core/modules/system/src/Entity/DateFormat.php b/core/modules/system/src/Entity/DateFormat.php
index 360c6b5..1016fbc 100644
--- a/core/modules/system/src/Entity/DateFormat.php
+++ b/core/modules/system/src/Entity/DateFormat.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
 use Drupal\system\DateFormatInterface;
 
 /**
@@ -104,4 +105,16 @@ public function isLocked() {
     return (bool) $this->locked;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
+    if ($a->isLocked() == $b->isLocked()) {
+      $a_label = $a->label();
+      $b_label = $b->label();
+      return strnatcasecmp($a_label, $b_label);
+    }
+    return $a->isLocked() ? 1 : -1;
+  }
+
 }
diff --git a/core/modules/system/src/Tests/System/DateFormatsLockedTest.php b/core/modules/system/src/Tests/System/DateFormatsLockedTest.php
index e10f106..a7415e1 100644
--- a/core/modules/system/src/Tests/System/DateFormatsLockedTest.php
+++ b/core/modules/system/src/Tests/System/DateFormatsLockedTest.php
@@ -31,10 +31,14 @@ public static function getInfo() {
   public function testDateLocking() {
     $this->drupalLogin($this->root_user);
 
-    // Locked date formats do not show on the listing page.
+    // Locked date formats are not linked on the listing page, locked date
+    // formats are clearly marked as such; unlocked formats are not marked as
+    // "locked".
     $this->drupalGet('admin/config/regional/date-time');
     $this->assertLinkByHref('admin/config/regional/date-time/formats/manage/short');
     $this->assertNoLinkByHref('admin/config/regional/date-time/formats/manage/html_date');
+    $this->assertText('fallback (locked)');
+    $this->assertNoText('short (locked)');
 
     // Locked date formats are not editable.
     $this->drupalGet('admin/config/regional/date-time/formats/manage/short');
diff --git a/core/modules/system/src/Tests/Theme/TwigTransTest.php b/core/modules/system/src/Tests/Theme/TwigTransTest.php
index 47d4557..9b6fd00 100644
--- a/core/modules/system/src/Tests/Theme/TwigTransTest.php
+++ b/core/modules/system/src/Tests/Theme/TwigTransTest.php
@@ -203,7 +203,7 @@ protected function checkForDebugMarkup($visible) {
       '{{ token }}' => '<!-- TRANSLATION: "Escaped: @string" -->',
       '{{ token|passthrough }}' => '<!-- TRANSLATION: "Pass-through: !string" -->',
       '{{ token|placeholder }}' => '<!-- TRANSLATION: "Placeholder: %string" -->',
-      '{{ complex.tokens }}' => '<!-- TRANSLATION: "This @name has a length of: @count. It contains: %numbers and @bad_text. Lets pass the bad text through: !bad_text." -->',
+      '{{ complex.tokens }}' => '<!-- TRANSLATION: "This @token.name has a length of: @count. It contains: %token.numbers and @token.bad_text. Lets pass the bad text through: !token.bad_text." -->',
       '{% trans with {"context": "Lolspeak"} %}I have context.{% endtrans %}' => '<!-- TRANSLATION: "I have context.", CONTEXT: "Lolspeak" -->',
       '{% trans with {"langcode": "zz"} %}Hello new text.{% endtrans %}' => '<!-- TRANSLATION: "Hello new text.", LANGCODE: "zz" -->',
       '{% trans with {"context": "Lolspeak", "langcode": "zz"} %}Hello new text.{% endtrans %}' => '<!-- TRANSLATION: "Hello new text.", CONTEXT: "Lolspeak", LANGCODE: "zz" -->',
@@ -300,8 +300,8 @@ protected function poFileContents($langcode) {
 msgid "Placeholder: %string"
 msgstr "PLAYSHOLDR: %string"
 
-msgid "This @name has a length of: @count. It contains: %numbers and @bad_text. Lets pass the bad text through: !bad_text."
-msgstr "DIS @name HAZ LENGTH OV: @count. IT CONTAYNZ: %numbers AN @bad_text. LETS PAS TEH BAD TEXT THRU: !bad_text."
+msgid "This @token.name has a length of: @count. It contains: %token.numbers and @token.bad_text. Lets pass the bad text through: !token.bad_text."
+msgstr "DIS @token.name HAZ LENGTH OV: @count. IT CONTAYNZ: %token.numbers AN @token.bad_text. LETS PAS TEH BAD TEXT THRU: !token.bad_text."
 
 msgctxt "Lolspeak"
 msgid "I have context."
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index cec48e4..eec64f3 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1283,7 +1283,7 @@ function hook_mail($key, &$message, $params) {
     $node = $params['node'];
     $variables += array(
       '%uid' => $node->getOwnerId(),
-      '%node_url' => url('node/' . $node->id(), array('absolute' => TRUE)),
+      '%url' => url('node/' . $node->id(), array('absolute' => TRUE)),
       '%node_type' => node_get_type_label($node),
       '%title' => $node->getTitle(),
       '%teaser' => $node->teaser,
diff --git a/core/themes/bartik/css/style.css b/core/themes/bartik/css/style.css
index c221415..6cb3831 100644
--- a/core/themes/bartik/css/style.css
+++ b/core/themes/bartik/css/style.css
@@ -132,7 +132,7 @@ ul.primary,
 .item-list .pager,
 div.field-type-taxonomy-term-reference,
 div.messages,
-div.meta,
+.node__meta,
 p.comment-time,
 table,
 .breadcrumb,
@@ -665,7 +665,8 @@ h1.site-name {
 
 /* ----------------- Content ------------------ */
 
-.content {
+.content,
+.node__content {
   margin-top: 10px;
 }
 h1#page-title {
@@ -677,44 +678,44 @@ h1#page-title {
   font-size: 1.429em;
   line-height: 1.4;
 }
-.node .content {
+.node__content {
   font-size: 1.071em;
 }
-.view-mode-teaser .content {
+.node--view-mode-teaser .node__content {
   font-size: 1em;
 }
-.view-mode-teaser h2 {
+.node--view-mode-teaser h2 {
   margin-top: 0;
   padding-top: 0.5em;
 }
-.view-mode-teaser h2 a {
+.node--view-mode-teaser h2 a {
   color: #181818;
 }
-.view-mode-teaser {
+.node--view-mode-teaser {
   border-bottom: 1px solid #d3d7d9;
   margin-bottom: 30px;
   padding-bottom: 15px;
 }
-.view-mode-teaser.sticky {
+.node--view-mode-teaser.node--sticky {
   background: #f9f9f9;
   background: rgba(0, 0, 0, 0.024);
   border: 1px solid #d3d7d9;
   padding: 0 15px 15px;
 }
-.view-mode-teaser .content {
+.node--view-mode-teaser .node__content {
   clear: none;
   line-height: 1.6;
 }
-.meta {
+.node__meta {
   font-size: 0.857em;
   color: #68696b;
   margin-bottom: -5px;
 }
-.submitted .field-name-field-user-picture img {
+.node__meta .field-name-field-user-picture img {
   float: left; /* LTR */
   margin: 1px 20px 0 0; /* LTR */
 }
-[dir="rtl"] .submitted .field-name-field-user-picture img {
+[dir="rtl"] .node__meta .field-name-field-user-picture img {
   float: right;
   margin-left: 20px;
   margin-right: 0;
@@ -735,8 +736,8 @@ h1#page-title {
 .field-type-taxonomy-term-reference ul.links {
   font-size: 0.8em;
 }
-.view-mode-teaser .field-type-taxonomy-term-reference .field-label,
-.view-mode-teaser .field-type-taxonomy-term-reference ul.links {
+.node--view-mode-teaser .field-type-taxonomy-term-reference .field-label,
+.node--view-mode-teaser .field-type-taxonomy-term-reference ul.links {
   font-size: 0.821em;
 }
 .field-type-taxonomy-term-reference ul.links {
@@ -753,10 +754,10 @@ h1#page-title {
   padding: 0 0 0 1em;
   float: right;
 }
-.link-wrapper {
+.node__links {
   text-align: right;
 }
-[dir="rtl"] .link-wrapper {
+[dir="rtl"] .node__links {
   text-align: left;
   margin-right: 236px;
   margin-left: 0;
@@ -769,10 +770,12 @@ ul.links {
   color: #68696b;
   font-size: 0.821em;
 }
+.node--unpublished,
 .unpublished {
   margin: -20px -15px 0;
   padding: 20px 15px 0;
 }
+.node--unpublished .comment-text .comment-arrow,
 .unpublished .comment-text .comment-arrow {
   border-left: 1px solid #fff4f4;
   border-right: 1px solid #fff4f4;
diff --git a/core/themes/bartik/templates/node.html.twig b/core/themes/bartik/templates/node.html.twig
index 4c75e2f..d45b0f0 100644
--- a/core/themes/bartik/templates/node.html.twig
+++ b/core/themes/bartik/templates/node.html.twig
@@ -5,11 +5,11 @@
  *
  * Available variables:
  * - node: Full node entity.
- *   - id: The node ID
+ *   - id: The node ID.
  *   - bundle: The type of the node, for example, "page" or "article".
  *   - authorid: The user ID of the node author.
- *   - createdtime: Formatted creation date. Preprocess functions can reformat
-       it by calling format_date() with the desired parameters on
+ *   - createdtime: Formatted creation date. Preprocess functions can
+ *     reformat it by calling format_date() with the desired parameters on
  *     $variables['node']->getCreatedTime().
  *   - promoted: Whether the node is promoted to the front page.
  *   - sticky: Whether the node is 'sticky'. Sticky nodes are ordered above
@@ -20,31 +20,32 @@
  *   or print a subset such as {{ content.field_example }}. Use
  *   {{ content|without('field_example') }} to exclude the printing of a
  *   given child element.
- * - user_picture: The node author's information as loaded from the 'compact'
- *   view mode for the user entity.
+ * - author_picture: The node author user entity, rendered using the "compact"
+ *   view mode.
+ * - metadata: Metadata for this node.
  * - date: Formatted creation date. Preprocess functions can reformat it by
  *   calling format_date() with the desired parameters on
  *   $variables['created'].
- * - name: Themed username of node author output from theme_username().
- * - node_url: Direct URL of the current node.
+ * - author_name: Themed username of node author output from theme_username().
+ * - url: Direct URL of the current node.
  * - display_submitted: Whether submission information should be displayed.
- * - submitted: Submission information created from name and date during
- *   template_preprocess_node().
  * - attributes: HTML attributes for the containing element.
  *   The attributes.class element may contain one or more of the following
  *   classes:
  *   - node: The current template type (also known as a "theming hook").
- *   - node-[type]: The current node type. For example, if the node is a
- *     "Article" it would result in "node-article". Note that the machine
+ *   - node--[type]: The current node type. For example, if the node is a
+ *     "Article" it would result in "node--article". Note that the machine
  *     name will often be in a short form of the human readable label.
- *   - view-mode-[view_mode]: The View Mode of the node; for example, a teaser
- *     would result in: "view-mode-teaser", and full: "view-mode-full".
- *   - preview: Whether a node is in preview mode.
+ *   - node--view-mode-[view_mode]: The View Mode of the node; for example, a
+ *     teaser would result in: "node--view-mode-teaser",
+ *     and full: "node--view-mode-full".
+ *   - is-preview: Whether a node is in preview mode.
  *   The following are controlled through the node publishing options.
- *   - promoted: Appears on nodes promoted to the front page.
- *   - sticky: Appears on nodes ordered above other non-sticky nodes in teaser
- *     listings.
- *   - unpublished: Appears on unpublished nodes visible only to site admins.
+ *   - node--promoted: Appears on nodes promoted to the front page.
+ *   - node--sticky: Appears on nodes ordered above other non-sticky nodes in
+ *     teaser listings.
+ *   - node--unpublished: Appears on unpublished nodes visible only to site
+ *     admins.
  * - title_prefix: Additional output populated by modules, intended to be
  *   displayed in front of the main title tag that appears in the template.
  * - title_suffix: Additional output populated by modules, intended to be
@@ -70,33 +71,38 @@
  * @see template_preprocess_node()
  */
 #}
-<article id="node-{{ node.id }}" class="{{ attributes.class }} clearfix" role="article"{{ attributes|without('id', 'class', 'role') }}>
+<article class="{{ attributes.class }} clearfix"{{ attributes|without('class') }}>
 
   <header>
     {{ title_prefix }}
     {% if not page %}
-      <h2{{ title_attributes }}>
-        <a href="{{ node_url }}">{{ label }}</a>
+      <h2 class="node__title {{ title_attributes.class }}"{{ title_attributes|without('class') }}>
+        <a href="{{ url }}" rel="bookmark">{{ label }}</a>
       </h2>
     {% endif %}
     {{ title_suffix }}
 
     {% if display_submitted %}
-      <div class="meta submitted">
-        {{ user_picture }}
-        {{ submitted }}
+      <div class="node__meta">
+        {{ author_picture }}
+        <span{{ author_attributes }}>
+          {% trans %}Submitted by {{ author_name|passthrough }} on {{ date }}{% endtrans %}
+        </span>
+        {{ metadata }}
       </div>
     {% endif %}
   </header>
 
-  <div class="content clearfix"{{ content_attributes }}>
-    {{ content|without('links') }}
+  <div class="node__content clearfix {{ content_attributes.class }}"{{ content_attributes|without('class') }}>
+    {{ content|without('comment', 'links') }}
   </div>
 
   {% if content.links %}
-    <footer class="link-wrapper">
+    <div class="node__links">
       {{ content.links }}
-    </footer>
+    </div>
   {% endif %}
 
+  {{ content.comment }}
+
 </article>
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index f1cb442..8b58258 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -518,6 +518,9 @@ ul.admin-list {
 div.submitted {
   color: #898989;
 }
+.node__submitted {
+  margin: 1em 0;
+}
 
 /**
  * Pagination.
