diff --git a/core/includes/form.inc b/core/includes/form.inc
index 4689711..732b1e9 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -4185,13 +4185,13 @@ function form_pre_render_button($element) {
 
   $element['#attributes']['class'][] = 'button';
   if (!empty($element['#button_type'])) {
-    $element['#attributes']['class'][] = 'button-' . $element['#button_type'];
+    $element['#attributes']['class'][] = 'button--' . $element['#button_type'];
   }
   // @todo Various JavaScript depends on this button class.
   $element['#attributes']['class'][] = 'form-submit';
 
   if (!empty($element['#attributes']['disabled'])) {
-    $element['#attributes']['class'][] = 'form-button-disabled';
+    $element['#attributes']['class'][] = 'is-disabled';
   }
 
   return $element;
@@ -4222,13 +4222,13 @@ function form_pre_render_image_button($element) {
 
   $element['#attributes']['class'][] = 'image-button';
   if (!empty($element['#button_type'])) {
-    $element['#attributes']['class'][] = 'image-button-' . $element['#button_type'];
+    $element['#attributes']['class'][] = 'image-button--' . $element['#button_type'];
   }
   // @todo Various JavaScript depends on this button class.
   $element['#attributes']['class'][] = 'form-submit';
 
   if (!empty($element['#attributes']['disabled'])) {
-    $element['#attributes']['class'][] = 'image-button-disabled';
+    $element['#attributes']['class'][] = 'is-disabled';
   }
 
   return $element;
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php
index e3521cc..783a92f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php
@@ -99,12 +99,12 @@ function testOptions() {
   function testButtonClasses() {
     $this->drupalGet('form-test/button-class');
     // Just contains(@class, "button") won't do because then
-    // "button-foo" would contain "button". Instead, check
+    // "button--foo" would contain "button". Instead, check
     // " button ". Make sure it matches in the beginning and the end too
     // by adding a space before and after.
     $this->assertEqual(2, count($this->xpath('//*[contains(concat(" ", @class, " "), " button ")]')));
-    $this->assertEqual(1, count($this->xpath('//*[contains(concat(" ", @class, " "), " button-foo ")]')));
-    $this->assertEqual(1, count($this->xpath('//*[contains(concat(" ", @class, " "), " button-danger ")]')));
+    $this->assertEqual(1, count($this->xpath('//*[contains(concat(" ", @class, " "), " button--foo ")]')));
+    $this->assertEqual(1, count($this->xpath('//*[contains(concat(" ", @class, " "), " button--danger ")]')));
   }
 
   /**
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 f402395..e37db1d 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -579,11 +579,11 @@ function testDisabledMarkup() {
       // Setup XPath and CSS class depending on #type.
       if (in_array($item['#type'], array('button', 'submit'))) {
         $path = "//!type[contains(@class, :div-class) and @value=:value]";
-        $class = 'form-button-disabled';
+        $class = 'is-disabled';
       }
       elseif (in_array($item['#type'], array('image_button'))) {
         $path = "//!type[contains(@class, :div-class) and @value=:value]";
-        $class = 'image-button-disabled';
+        $class = 'is-disabled';
       }
       else {
         // starts-with() required for checkboxes.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/SystemConfigFormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/SystemConfigFormTest.php
index 56a24c0..a0b45e3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/SystemConfigFormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/SystemConfigFormTest.php
@@ -35,7 +35,7 @@ public static function getInfo() {
    */
   function testSystemConfigForm() {
     $this->drupalGet('form-test/system-config-form');
-    $element = $this->xpath('//div[@id = :id]/input[contains(@class, :class)]', array(':id' => 'edit-actions', ':class' => 'button-primary'));
+    $element = $this->xpath('//div[@id = :id]/input[contains(@class, :class)]', array(':id' => 'edit-actions', ':class' => 'button--primary'));
     $this->assertTrue($element, 'The primary action submit button was found.');
     $this->drupalPost(NULL, array(), t('Save configuration'));
     $this->assertText(t('The configuration options have been saved.'));
diff --git a/core/themes/seven/css/components/buttons.css b/core/themes/seven/css/components/buttons.css
new file mode 100644
index 0000000..1024c51
--- /dev/null
+++ b/core/themes/seven/css/components/buttons.css
@@ -0,0 +1,70 @@
+/**
+ * @file
+ * Structural styles for Seven’s UI buttons
+ *
+ * Apply these classes to any element (<link>, <button>, <input>, etc.) that
+ * should appear as a button.
+ */
+
+/* ====================================
+   Buttons
+   ==================================== */
+
+/**
+ * 1. Enable z-index on buttons.
+ * 2. Normalize 'line-height'; can’t be changed from 'normal' in Firefox 4+.
+ * 3. Allows full range of styling in Webkit and Gecko.
+ *
+ * N.B. Assumes box-sizing: border-box applied globally.
+ */
+.button {
+  /* @TODO Move into base.css under a universal selector (*) */
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  display: inline-block;
+  position: relative;  /* 1 */
+  text-align: center;
+  line-height: normal;  /* 2 */
+  cursor: pointer;
+  -webkit-appearance: none;  /* 3 */
+  -moz-appearance:    none;  /* " */
+}
+
+/* Prevent focus ring being covered by next siblings. */
+.button:focus {
+  z-index: 10;
+}
+
+
+/* ====================================
+   Link actions
+   ==================================== */
+
+.link {
+  display: inline;
+  cursor: pointer;
+  padding: 0;
+  border: 0;
+  background: none;
+  -webkit-appearance: none;
+  -moz-appearance:    none;
+}
+
+/* ====================================
+   Button groups
+   ==================================== */
+
+.button-group {
+  display: inline-block;
+}
+/* Clearfix manually to avoid needing to add a utility class to the markup */
+.button-group:after {
+  content: ' ';
+  display: block;
+  clear: both;
+}
+
+.button-group > .button {
+  float: left;
+}
diff --git a/core/themes/seven/css/components/buttons.theme.css b/core/themes/seven/css/components/buttons.theme.css
new file mode 100644
index 0000000..820b946
--- /dev/null
+++ b/core/themes/seven/css/components/buttons.theme.css
@@ -0,0 +1,244 @@
+/**
+ * @file
+ * Stylistic treatment for Seven’s UI buttons
+ */
+
+/* ====================================
+   Buttons
+   ==================================== */
+
+/**
+ * 1. Use px units to ensure button text is centered vertically.
+ * 2. Prevent fat text in WebKit
+ */
+.button {
+  /* @TODO Removed this before commit - #1986082 */
+  font-family: "Source Sans Pro", "Segoe UI", 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', sans-serif;
+
+  padding: 4px 1.5em;  /* 1 */
+  border: 1px solid #a6a6a6;
+  border-radius: 20em;
+  background-color: #f2f1eb;
+  background-image: -webkit-linear-gradient(top, #f6f6f3, #e7e7df);
+  background-image:    -moz-linear-gradient(top, #f6f6f3, #e7e7df);
+  background-image:      -o-linear-gradient(top, #f6f6f3, #e7e7df);
+  background-image:   linear-gradient(to bottom, #f6f6f3, #e7e7df);
+  color: #333333;
+  text-decoration: none;
+  text-shadow: 0 1px hsla(0, 0%, 100%, 0.6);
+  font-weight: 600;
+  font-size: 15px;
+  /* @TODO uncomment once base typography from the style guide is in - #1986082 */
+  /* font-size: 0.938rem; */
+  -webkit-transition: all 0.1s;
+  -moz-transition:    all 0.1s;
+  -o-transition:      all 0.1s;
+  transition:         all 0.1s;
+  -webkit-font-smoothing: antialiased;  /* 2 */
+}
+.button:focus,
+.button:hover {
+  background-color: #f9f8f6;
+  background-image: -webkit-linear-gradient(top, #fcfcfa, #e9e9dd);
+  background-image:    -moz-linear-gradient(top, #fcfcfa, #e9e9dd);
+  background-image:      -o-linear-gradient(top, #fcfcfa, #e9e9dd);
+  background-image:   linear-gradient(to bottom, #fcfcfa, #e9e9dd);
+  color: #1a1a1a;
+  text-decoration: none;
+}
+.button:hover {
+  box-shadow: 0 1px 2px hsla(0, 0%, 0%, 0.125);
+}
+.button:active {
+  background-color: #dfdfd9;
+  background-image: -webkit-linear-gradient(top, #f6f6f3, #e7e7df);
+  background-image:    -moz-linear-gradient(top, #f6f6f3, #e7e7df);
+  background-image:      -o-linear-gradient(top, #f6f6f3, #e7e7df);
+  background-image:   linear-gradient(to bottom, #f6f6f3, #e7e7df);
+  box-shadow: inset 0 1px 3px hsla(0, 0%, 0%, 0.2);
+  -webkit-transition: none;
+  -moz-transition:    none;
+  -o-transition:      none;
+  transition:         none;
+}
+
+.button--primary {
+  border-color: #1e5c90;
+  background-image: -webkit-linear-gradient(top, #007bc6, #0071b8);
+  background-image:    -moz-linear-gradient(top, #007bc6, #0071b8);
+  background-image:      -o-linear-gradient(top, #007bc6, #0071b8);
+  background-image:   linear-gradient(to bottom, #007bc6, #0071b8);
+  color: #fff;
+  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
+  font-weight: 700;
+  -webkit-font-smoothing: antialiased;
+}
+.button--primary:focus,
+.button--primary:hover {
+  background-color: #2369a6;
+  background-image: -webkit-linear-gradient(top, #0c97ed, #1f86c7);
+  background-image:    -moz-linear-gradient(top, #0c97ed, #1f86c7);
+  background-image:      -o-linear-gradient(top, #0c97ed, #1f86c7);
+  background-image:   linear-gradient(to bottom, #0c97ed, #1f86c7);
+  border-color: #1e5c90;
+  color: #fff;
+}
+.boxshadow .button--primary:focus {
+  border-color: #0087db;
+}
+.button--primary:hover {
+  box-shadow: 0 1px 2px hsla(203, 10%, 10%, 0.25);
+}
+.button--primary:active {
+  background-image: -webkit-linear-gradient(top, #08639b, #0071b8);
+  background-image:    -moz-linear-gradient(top, #08639b, #0071b8);
+  background-image:      -o-linear-gradient(top, #08639b, #0071b8);
+  background-image:   linear-gradient(to bottom, #08639b, #0071b8);
+  border-color: #144b78;
+  box-shadow: inset 0 1px 3px hsla(0, 0%, 0%, 0.2);
+}
+
+/**
+ * Overrides styling from system.theme
+ */
+.button-action:before {
+  margin-left: -0.2em;
+  padding-right: 0.2em;
+  font-size: 14px;
+  line-height: 16px;
+  -webkit-font-smoothing: auto;
+}
+
+/**
+ * 1. Use px units to ensure button text is centered vertically.
+ */
+.no-touch .button--small {
+  font-size: 13px;
+  /* @TODO uncomment once base typography from the style guide is in - #1986082 */
+  /*font-size: 0.813rem;*/
+
+  padding: 2px 1em;  /* 1 */
+}
+
+.button:disabled,
+.button:disabled:active,
+.button.is-disabled,
+.button.is-disabled:active {
+  border-color: #d4d4d4;
+  background: #ededed;
+  box-shadow: none;
+  color: #5c5c5c;
+  font-weight: normal;
+  cursor: default;
+  text-shadow: 0 1px hsla(0, 0%, 100%, 0.6);
+}
+
+/**
+ * Provide a custom focus ring using box-shadow, but *only* when box-shadow is
+ * supported (testing with Modernizr). Otherwise, maintain the default browser
+ * focus style.
+ *
+ * @TODO Themes need a way to require Modernizr tests.
+ */
+/*.boxshadow*/ .button:focus {
+  outline: none;
+  border-color: #40b6ff;
+  box-shadow: 0 0 0.5em 0.1em hsla(203, 100%, 60%, 0.7);
+}
+/*.boxshadow*/ .button:active:focus,
+/*.boxshadow*/ .button.is-active:focus {
+  box-shadow:
+    0 0 0.5em 0.1em hsla(203, 100%, 60%, 0.7),
+    inset 0 1px 3px hsla(0, 0%, 0%, 0.2);
+}
+
+
+/* ====================================
+   Link actions
+   ==================================== */
+
+/**
+ * Style a clickable/tappable element as a link. Duplicates the base style for
+ * the <a> tag, plus a reset for padding, borders and background.
+ */
+.link {
+  color: #0074bd; /* hsl(203, 100%, 37%) */
+  text-decoration: none;
+}
+.link:focus,
+.link:hover {
+  color: #008ee6; /* hsl(203, 100%, 45%) */
+  text-decoration: underline;
+}
+
+/* We've temporaily added the danger button here, bit of a harsh reset but we need it */
+.button--danger {
+  display: inline;
+  cursor: pointer;
+  padding: 0!important;
+  border: 0!important;
+  border-radius: 0;
+  box-shadow: none!important;
+  background: none!important;
+  -webkit-appearance: none;
+  -moz-appearance:    none;
+  color: #c72100;
+  text-decoration: underline;
+}
+.button--danger:focus,
+.button--danger:hover,
+.button--danger:active {
+  color: #ff2a00;
+  text-decoration: underline;
+  text-shadow: none;
+}
+.button--danger:disabled,
+.button--danger.is-disabled {
+ color: #737373;
+ cursor: default;
+ text-decoration: none;
+ -webkit-font-smoothing: antialiased;
+}
+
+
+/* ====================================
+   Button groups
+   ==================================== */
+
+/* Compensate for all buttons pulled left by 1px */
+.button-group {
+  padding-left: 1px;
+}
+
+/**
+ * The child selector is appropriate here because these styles are inherently
+ * tied to the button-group situation and are unlikely to be useful elsewhere.
+ *
+ * 1. Remove any border-radius on all buttons, to be re-added on outer
+ *    buttons only.
+ * 2. Collapse borders on adjacent buttons
+ * 3. Tighten the inner padding. Without border-radius, it’s not needed.
+ */
+.button-group > .button {
+  border-radius: 0;  /* 1 */
+  margin-left: -1px;  /* 2 */
+  padding-left: .75em;  /* 3 */
+  padding-right: .75em; /* " */
+}
+
+/**
+ * Re-apply the normal button border-radius to the outer buttons in the group.
+ *
+ * N.B. These styles don’t need to support IE8, since it doesn’t support
+ * border-radius in the first place.
+ */
+.button-group > .button:first-of-type {
+  border-top-left-radius: 20em;
+  border-bottom-left-radius: 20em;
+  padding-left: 1em;
+}
+.button-group > .button:last-of-type {
+  border-top-right-radius: 20em;
+  border-bottom-right-radius: 20em;
+  padding-right: 1em;
+}
diff --git a/core/themes/seven/seven.info.yml b/core/themes/seven/seven.info.yml
index 13ca85c..9e5892d 100644
--- a/core/themes/seven/seven.info.yml
+++ b/core/themes/seven/seven.info.yml
@@ -7,6 +7,8 @@ core: 8.x
 stylesheets:
   screen:
     - style.css
+    - css/components/buttons.css
+    - css/components/buttons.theme.css
 stylesheets-override:
   - vertical-tabs.css
   - vertical-tabs-rtl.css
diff --git a/core/themes/seven/seven.theme b/core/themes/seven/seven.theme
index 3b11032..a5464ea 100644
--- a/core/themes/seven/seven.theme
+++ b/core/themes/seven/seven.theme
@@ -22,6 +22,9 @@ function seven_preprocess_maintenance_page(&$vars) {
  */
 function seven_preprocess_html(&$vars) {
   drupal_add_library('system', 'normalize');
+  // Temporarily add Source Sans as a webfont from Google Webfonts
+  // @TODO resolve 1986082: Add a webfont version of Source Sans Pro
+  drupal_add_html_head_link(array('rel' => 'stylesheet', 'href' => 'http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,700,400italic'));
 }
 
 /**
@@ -139,6 +142,44 @@ function seven_tablesort_indicator($variables) {
 }
 
 /**
+ * Overrides theme_menu_local_action().
+ */
+function seven_menu_local_action($variables) {
+  $link = $variables['element']['#link'];
+  $link += array(
+    'href' => '',
+    'localized_options' => array(),
+  );
+  // Will be the existing classes array or NULL
+  $classes = &$link['localized_options']['attributes']['class'];
+  $classes = array_merge((array)$classes, array('button', 'button--primary', 'button--small'));
+  // We require modernizr for button styling
+  drupal_add_library('system', 'modernizr');
+
+  // @TODO Replace with a generalized solution for icons.
+  // See http://drupal.org/node/1849712
+  $classes[] = 'button-action';
+
+  $link['localized_options']['html'] = TRUE;
+
+  $output = '<li>';
+  $output .= l($link['title'], $link['href'], $link['localized_options']);
+  $output .= "</li>";
+
+  return $output;
+}
+
+/**
+ * Implements hook_element_info_alter().
+ */
+function seven_element_info_alter(&$types) {
+  // We require modernizr for button styling
+  if (isset($types['button'])) {
+    drupal_add_library('system', 'modernizr');
+  }
+}
+
+/**
  * Implements hook_preprocess_install_page().
  */
 function seven_preprocess_install_page(&$variables) {
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index 86ac064..68b7838 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -604,68 +604,6 @@ body div.form-type-radio div.description,
 body div.form-type-checkbox div.description {
   margin-left: 1.5em; /* LTR */
 }
-.button {
-  cursor: pointer;
-  padding: 4px 17px;
-  color: #5a5a5a;
-  text-align: center;
-  font-weight: normal;
-  font-size: 1.077em;
-  font-family: "Lucida Grande", Verdana, sans-serif;
-  border: 1px solid #e4e4e4;
-  border-bottom: 1px solid #b4b4b4;
-  border-left-color: #d2d2d2;
-  border-right-color: #d2d2d2;
-  background-color: #e4e4e4;
-  border-radius: 20px;
-  text-decoration: none;
-}
-.button:focus,
-.button:hover {
-  background-color: #c0c0c0;
-  border: 1px solid #bebebe;
-  border-left-color: #afafaf;
-  border-right-color: #afafaf;
-  border-bottom-color: #9b9b9b;
-  color: #2e2e2e;
-  text-decoration: none;
-}
-.button:active {
-  background-color: #565656;
-  border: 1px solid #333;
-  border-left-color: #222;
-  border-right-color: #222;
-  border-bottom-color: #111;
-  color: #fff;
-  text-decoration: none;
-  text-shadow: #222 0 -1px 0;
-}
-.button-primary {
-  background-color: #9dcae7;
-  border: 1px solid #8eB7cd;
-  border-bottom-color: #7691a2;
-  color: #133B54;
-}
-.button-primary:focus,
-.button-primary:hover {
-  background-color: #73b3dd;
-  border: 1px solid #6ea3bf;
-  border-bottom-color: #4680a0;
-}
-.button-primary:active {
-  background-color: #3981b1;
-  border: 1px solid #36647c;
-  border-bottom-color: #284657;
-}
-.button-disabled,
-.button-disabled:active,
-.button[disabled],
-.button[disabled]:active {
-  background-color: #eee;
-  border-color: #eee;
-  text-shadow: none;
-  color: #999;
-}
 input.form-autocomplete,
 input.form-text,
 input.form-tel,
@@ -711,42 +649,6 @@ select.form-select:focus {
 .js input.throbbing {
   background-position: 100% -16px;
 }
-.button-action {
-  background: #1078d4;
-  background-image: -webkit-linear-gradient(top, #419ff1, #1076d5);
-  background-image: -moz-linear-gradient(top, #419ff1, #1076d5);
-  background-image: -o-linear-gradient(top, #419ff1, #1076d5);
-  background-image: linear-gradient(to bottom, #419ff1, #1076d5);
-  border: 1px solid #0048c8;
-  border-radius: .4em;
-  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4);
-  color: #fff;
-  font-size: 1em;
-  line-height: normal;
-  margin: 0;
-  padding: 4px 1em;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
-}
-.button-action:focus,
-.button-action:hover {
-  background-color: #419cf1;
-  background-image: -webkit-linear-gradient(top, #59abf3, #2a90ef);
-  background-image: -moz-linear-gradient(top, #59abf3, #2a90ef);
-  background-image: -o-linear-gradient(top, #59abf3, #2a90ef);
-  background-image: linear-gradient(to bottom, #59abf3, #2a90ef);
-  border: 1px solid #0048c8;
-  color: #fff;
-}
-.button-action:active {
-  background-color: #0e69be;
-  background-image: -webkit-linear-gradient(top, #0e69be, #2a93ef);
-  background-image: -moz-linear-gradient(top, #0e69be, #2a93ef);
-  background-image: -o-linear-gradient(top, #0e69be, #2a93ef);
-  background-image: -ms-linear-gradient(top, #0e69be, #2a93ef);
-  background-image: linear-gradient(to bottom, #0e69be, #2a93ef);
-  border: 1px solid #0048c8;
-  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .25);
-}
 
 /**
  * Improve spacing of cancel link.
