diff --git a/commerce_checkout_login.module b/commerce_checkout_login.module
index 63754d7..4696633 100644
--- a/commerce_checkout_login.module
+++ b/commerce_checkout_login.module
@@ -2,193 +2,102 @@
 
 /**
  * @file
- * Adds an inline login form to the Account Information checkout pane.
+ * Adds a new checkout pane to allow users to login, create an account or
+ * checkout anonymously depending on site configuration.
  */
 
-
 /**
  * Implements hook_form_FORM_ID_alter().
- *
- * This module works by altering the checkout form to add an additional bit of
- * AJAX to the Account Information checkout pane via this hook.
  */
-function commerce_checkout_login_form_commerce_checkout_form_alter(&$form, &$form_state) {
-  global $user;
-
-  // If the Account Information pane is on the current checkout page and the
-  // user is not logged in...
-  if (!$user->uid && !empty($form['account'])) {
-    $form['account']['login']['mail'] += array(
-      '#ajax' => array(
-        'callback' => 'commerce_checkout_login_checkout_form_refresh',
-        'wrapper' => 'account-login-container',
-      ),
-    );
-
-    // Immediately validate e-mail addresses if mail confirmation is enabled.
-    if (isset($form['account']['login']['mail_confirm'])) {
-      $form['account']['login']['mail_confirm']['#ajax'] = array(
-        'callback' => 'commerce_checkout_login_checkout_form_refresh',
-        'wrapper' => 'account-login-container',
-      );
-    }
-
-    // Check the form state to see if an e-mail address has been specified.
-    if (!empty($form_state['values']['account']['login'])) {
-      $mail = trim($form_state['values']['account']['login']['mail']);
-
-      // Don't attempt to load the user for an invalid e-mail address.
-      if (_validate_email($mail) && user_load_by_mail($mail)) {
-        // An existing e-mail address has been entered. Add a password field to
-        // allow the customer to login.
-        // @todo: autosubmit by ajax, but only if password was changed to
-        // prevent infinite loops caused by automatically filled forms.
-        $form['account']['login']['password'] = array(
-          '#type' => 'password',
-          '#title' => t('Password'),
-          '#required' => TRUE,
-          '#description' => t('Please enter the password for your account. !forgot', array('!forgot' => l(t('Did you forget your password?'), 'user/password')))
-        );
-
-        // No e-mail confirmation is required to login. So we hide the e-mail
-        // confirmation field if it is set.
-        if (isset($form['account']['login']['mail_confirm'])) {
-          $form['account']['login']['mail_confirm']['#value'] = $mail;
-          $form['account']['login']['mail_confirm']['#access'] = FALSE;
-        }
-      }
+function commerce_checkout_login_form_commerce_checkout_form_account_alter(&$form, &$form_state, $form_id) {
+  if (variable_get('commerce_checkout_login_allow_anonymous_checkout', TRUE)) {
+    // Set the name to guest to differentiate during validation.
+    $form['buttons']['continue']['#name'] = 'guest';
+    // Guest checkout does not need any validation.
+    $form['buttons']['continue']['#limit_validation_errors'] = array();
+    // Change the button label if the register/login form is shown.
+    if ($form_state['account']->uid === 0) {
+      $form['buttons']['continue']['#value'] = t('Checkout as guest');
     }
   }
-}
-
-/**
- * Ajax callback: returns the account information pane to an AJAX request.
- */
-function commerce_checkout_login_checkout_form_refresh($form, $form_state) {
-  $show_conf_mail = variable_get('commerce_order_account_pane_mail_double_entry', FALSE);
-
-  $mail = !empty($form_state['values']['account']['login']['mail']) ? trim($form_state['values']['account']['login']['mail']) : '';
-  _validate_email($mail);
-
-  // Just return the new login form if e-mail confirmation is not required.
-  if (!$show_conf_mail) {
-    return $form['account']['login'];
+  else {
+    $form['buttons']['continue']['#access'] = FALSE;
+    unset($form['buttons']['cancel']['#prefix']);
   }
-
-  // Return AJAX commands to set focus to the mail confirmation field for
-  // improved user experience.
-  $commands = array();
-  $commands[] = ajax_command_replace('#' . $form['account']['login']['mail']['#ajax']['wrapper'], drupal_render($form['account']['login']));
-  $commands[] = ajax_command_invoke('[name="account[login][mail_confirm]"]', 'focus');
-  print ajax_render($commands);
-  exit;
 }
 
 /**
- * Implements hook_commerce_checkout_pane_info_alter().
+ * Implements hook_form_alter().
  */
-function commerce_checkout_login_commerce_checkout_pane_info_alter(&$checkout_panes) {
-  if (isset($checkout_panes['account'])) {
-    $checkout_panes['account']['callbacks']['checkout_form_validate'] = 'commerce_checkout_login_commerce_checkout_pane_validate';
-    $checkout_panes['account']['callbacks']['checkout_form_submit'] = 'commerce_checkout_login_commerce_checkout_pane_submit';
+function commerce_checkout_login_form_commerce_checkout_form_checkout_alter(&$form, &$form_state, $form_id) {
+  // If user registration information has been submitted...
+  if (isset($form_state['order']->data['commerce_checkout_login_register'])) {
+    // And the pane has been configured to display account information...
+    if (variable_get('commerce_order_account_pane_auth_display', FALSE)) {
+      // Remove the 'login' form.
+      unset($form['account']['login']);
+      // Display account information.
+      $form['account'][] = ccl_account_information($form_state['order']);
+    }
+    else {
+      // Remove the account pane, because we already have the information.
+      unset($form['account']);
+    }
   }
 }
 
-
 /**
- * Account checkout pane validation.
+ * Implements hook_form_alter().
  */
-function commerce_checkout_login_commerce_checkout_pane_validate(&$form, &$form_state, $checkout_pane, $order) {
-  $mail = !empty($form_state['values']['account']['login']['mail']) ? trim($form_state['values']['account']['login']['mail']) : $form_state['order']->mail;
-
-  // Bail if the e-mail address is invalid.
-  if (!_validate_email($mail)) {
-    return FALSE;
-  }
-
-  if ($account = user_load_by_mail($mail)) {
-    $validated = _validate_existing_account($form, $form_state, $account);
-  }
-  // A non-existing e-mail address has been entered.
-  else {
-    $validated = TRUE;
-    // Validate e-mail confirmation field if set.
-    if (isset($form['account']['login']['mail_confirm'])) {
-      $mail_confirm = !empty($form_state['values']['account']['login']['mail_confirm']) ? trim($form_state['values']['account']['login']['mail_confirm']) : '';
-      if (empty($mail_confirm) || $mail != $mail_confirm) {
-        form_set_error('account][login][mail_confirm', t('The specified e-mail addresses do not match.'));
-        $validated = FALSE;
-      }
-    }
-
-    if (isset($form['account']['login']['password'])) {
-      // A password field is present. During rebuild of the form, this password
-      // field will be removed because a non-existing email address was entered.
-      // Previous form validation might already have set a password required
-      // message. We need to remove said message.
-      $messages = drupal_get_messages('error');
-      $password_title = $form['account']['login']['password']['#title'];
-      foreach ($messages['error'] as $message) {
-        if ($message != strip_tags(t('The field %field is required.', array('%field' => $password_title)))) {
-          // This message is not the password required message, re-set it.
-          drupal_set_message($message, 'error');
-        }
-      }
+function commerce_checkout_login_form_commerce_checkout_form_review_alter(&$form, &$form_state, $form_id) {
+  // If user registration information has been submitted...
+  if (isset($form_state['order']->data['commerce_checkout_login_register'])) {
+    // If the account review pane is shown.
+    if (isset($form['checkout_review']['review']['#data']['account'])) {
+      $content = ccl_account_information($form_state['order']);
+      $form['checkout_review']['review']['#data']['account']['data'] = render($content);
     }
   }
-
-  return $validated;
 }
 
 /**
- * Account checkout pane submit handler.
+ * Implements hook_commerce_checkout_pane_info().
  */
-function commerce_checkout_login_commerce_checkout_pane_submit(&$form, &$form_state, $checkout_pane, $order) {
+function commerce_checkout_login_commerce_checkout_pane_info() {
   global $user;
 
-  // commerce_checkout_login_uid gets set during _validate_existing_account() if
-  // the account was validated successfully.
-  if (!empty($form_state['commerce_checkout_login_uid'])) {
-    // If the user was logged in during this request, make sure we are using the
-    // full user object.
-    if (!empty($user->uid)) {
-      $user = user_load($user->uid);
-    }
-    else {
-      // Load the validated user into the global $user variable.
-      $user = user_load($form_state['commerce_checkout_login_uid']);
-
-      // "Finalize" the login by triggering the appropriate system messages, IP
-      // address and login timestamp logging, and user login hook.
-      user_login_finalize();
-    }
-
-    // Convert the current order from anonymous to authenticated and clear out
-    // our variable from the form state.
-    $oid = is_object($form_state['order']) ? $form_state['order']->order_id : $form_state['order'];
-    $order = commerce_order_load($oid);
-    if (empty($order->uid)) {
-      commerce_checkout_login_order_convert($order, $user);
-    }
-    unset($form_state['commerce_checkout_login_uid']);
-  }
+  $panes['account_form'] = array(
+    'title' => $user->uid > 0 ? t('Account information') : t('Checkout method'),
+    'name' => t('Account'),
+    'page' => 'account',
+    'file' => 'commerce_checkout_login.panes.inc',
+    'callbacks' => array(
+      'settings_form' => 'commerce_checkout_login_account_settings_form',
+      'checkout_form' => 'commerce_checkout_login_account_form',
+      'checkout_form_validate' => 'commerce_checkout_login_account_form_validate',
+      'checkout_form_submit' => 'commerce_checkout_login_account_form_submit',
+    ),
+  );
+
+  return $panes;
 }
 
 /**
- * Email validation helper
+ * Implements hook_commerce_checkout_page_info().
  */
-function _validate_email($mail) {
-  if ($error = user_validate_mail($mail)) {
-    form_set_error('account][login][mail', $error);
-    return FALSE;
-  }
-  return TRUE;
+function commerce_checkout_login_commerce_checkout_page_info() {
+  $pages['account'] = array(
+    'title' => t('Account'),
+    'weight' => -1,
+  );
+
+  return $pages;
 }
 
 /**
  * Known user validation helper.
  */
-function _validate_existing_account(&$form, &$form_state, &$account) {
+function ccl_validate_existing_account(&$form, &$form_state, &$account) {
   if ($user = user_uid_optional_load()) {
     if ($user->uid === $account->uid) {
       // Nothing to validate, the user is already logged in.
@@ -196,67 +105,81 @@ function _validate_existing_account(&$form, &$form_state, &$account) {
     }
   }
 
-  // If there is no password field present, the customer has not yet been
-  // informed about the the pre-existing account. We therefore have to inform
-  // the customer about this.
-  if (!isset($form['account']['login']['password'])) {
-    $message = t('There is already an account registered to %mail. Please enter your password to continue checkout.', array('%mail' => $account->mail));
-    drupal_set_message($message, 'warning');
-    // By invalidating the form submission we trigger a rebuild which will cause
-    // the password field to be rendered.
-    return FALSE;
+  // user_login_authenticate_validate() does a flood controlled authentication
+  // of the credentials based on a form submission. We therefor simulate a form
+  // submission to make use of existing code.
+  $credentials['values'] = array(
+    'pass' => $form_state['values']['account_form']['select']['login']['password'],
+    'name' => $account->name,
+    'mail' => $account->mail,
+  );
+  user_login_authenticate_validate(array(), $credentials);
+  // The uid is added to the credentials when validation is successful.
+  if (isset($credentials['uid']) && $credentials['uid']) {
+    // Clear past failures for this user so as not to block a user who might
+    // log in and out more than once in an hour.
+    if (isset($credentials['flood_control_user_identifier'])) {
+      flood_clear_event('failed_login_attempt_user', $credentials['flood_control_user_identifier']);
+    }
+    $form_state['commerce_checkout_login_uid'] = $credentials['uid'];
+    return TRUE;
   }
   else {
-    // Display an appropriate error message if the user account is blocked.
-    if (user_is_blocked($account->name)) {
-      form_set_error('account][login][email', t('The username %name has not been activated or is blocked.', array('%name' => $account->name)));
-      return FALSE;
+    // Register events for flood control.
+    // Copied/adjusted from user_login_final_validate().
+
+    // Always register an IP-based failed login event.
+    flood_register_event('failed_login_attempt_ip', variable_get('user_failed_login_ip_window', 3600));
+    // Register a per-user failed login event.
+    if (isset($credentials['flood_control_user_identifier'])) {
+      flood_register_event('failed_login_attempt_user', variable_get('user_failed_login_user_window', 21600), $credentials['flood_control_user_identifier']);
     }
 
-    // user_login_authenticate_validate() does a flood controlled authentication
-    // of the credentials based on a form submission. We therefor simulate a
-    // form submission to make use of existing code.
-    $credentials['values'] = array(
-      'pass' => $form_state['values']['account']['login']['password'],
-      'name' => $account->name,
-    );
-    user_login_authenticate_validate(array(), $credentials);
-    // The uid is added to the credentials when validation is successful.
-    if (isset($credentials['uid']) && $credentials['uid']) {
-      // Clear past failures for this user so as not to block a user who might
-      // log in and out more than once in an hour.
-      if (isset($credentials['flood_control_user_identifier'])) {
-        flood_clear_event('failed_login_attempt_user', $credentials['flood_control_user_identifier']);
+    if (isset($credentials['flood_control_triggered'])) {
+      if ($credentials['flood_control_triggered'] == 'user') {
+        form_set_error('account_form][select][login][name', format_plural(variable_get('user_failed_login_user_limit', 5), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
+      }
+      else {
+        // We did not find a uid, so the limit is IP-based.
+        form_set_error('account_form][select][login][name', t('Sorry, too many failed login attempts from your IP address. This IP address is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
       }
-      $form_state['commerce_checkout_login_uid'] = $credentials['uid'];
-      return TRUE;
     }
     else {
-      // Register events for flood control.
-      // Copied/adjusted from user_login_final_validate().
+      form_set_error('account_form][select][login][name', t('Sorry, unrecognized e-mail address or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password', array('query' => array('name' => $credentials['values']['mail']))))));
+      watchdog('commerce_checkout_login', 'Login attempt failed for %mail.', array('%mail' => $credentials['values']['mail']));
+    }
+  }
 
-      // Always register an IP-based failed login event.
-      flood_register_event('failed_login_attempt_ip', variable_get('user_failed_login_ip_window', 3600));
-      // Register a per-user failed login event.
-      if (isset($credentials['flood_control_user_identifier'])) {
-        flood_register_event('failed_login_attempt_user', variable_get('user_failed_login_user_window', 21600), $credentials['flood_control_user_identifier']);
-      }
+  // Display an appropriate error message if the user account is blocked.
+  if (user_is_blocked($account->name)) {
+    form_set_error('account_form][select][login][email', t('The username %name has not been activated or is blocked.', array('%name' => $account->name)));
+    return FALSE;
+  }
 
-      if (isset($credentials['flood_control_triggered'])) {
-        if ($credentials['flood_control_triggered'] == 'user') {
-          form_set_error('account][login][name', format_plural(variable_get('user_failed_login_user_limit', 5), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
-        }
-        else {
-          // We did not find a uid, so the limit is IP-based.
-          form_set_error('account][login][name', t('Sorry, too many failed login attempts from your IP address. This IP address is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
-        }
-      }
-      else {
-        form_set_error('account][login][name', t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password', array('query' => array('name' => $credentials['values']['name']))))));
-        watchdog('commerce_checkout_login', 'Login attempt failed for %user.', array('%user' => $credentials['values']['name']));
-        return FALSE;
-      }
-    }
+  return FALSE;
+}
+
+/**
+ * Implements hook_commerce_checkout_complete().
+ */
+function commerce_checkout_login_commerce_checkout_complete($order) {
+  if (!empty($order->data['commerce_checkout_login_register'])) {
+    $username = $order->data['commerce_checkout_login_register']['username'];
+    $mail = $order->data['commerce_checkout_login_register']['mail'];
+    // Create account and login.
+    $account = commerce_checkout_create_account($username, $mail, user_password(), TRUE, TRUE);
+
+    $token = drupal_random_key();
+    $_SESSION['pass_reset_' . $account->uid] = $token;
+    $reset_link = l(t('Please set your password'), 'user/' . $account->uid . '/edit', array('query' => array('pass-reset-token' => $token)));
+    drupal_set_message(t('Your account has been created and you have been automatically logged in. !set_pass.', array('!set_pass' => $reset_link)));
+
+    // Send a notification email and inform the user about it.
+    _user_mail_notify('register_no_approval_required', $account);
+    drupal_set_message(t('A welcome message with further instructions has been sent to your e-mail address.'));
+
+    // Convert the order.
+    ccl_login_convert_order($account->uid, $order);
   }
 }
 
@@ -267,12 +190,11 @@ function _validate_existing_account(&$form, &$form_state, &$account) {
  *   The anonymous order to convert to an authenticated order.
  * @param $account
  *   The user account the order will belong to.
- *
- * @return
+ * @return bool|\EntityMetadataWrapper
  *   The updated order's wrapper or FALSE if the order was not converted,
- *     meaning it was not an anonymous cart order to begin with.
+ *   meaning it was not an anonymous cart order to begin with.
  */
-function commerce_checkout_login_order_convert($order, $account) {
+function ccl_order_convert($order, $account) {
   // Only convert orders that are currently anonymous.
   if ($order->uid == 0) {
     // Update the uid and e-mail address to match the current account since
@@ -305,11 +227,59 @@ function commerce_checkout_login_order_convert($order, $account) {
     }
 
     // Allow other modules to operate on the converted order and then save.
-    module_invoke_all('commerce_checkout_login_order_convert', $order_wrapper, $account);
+    module_invoke_all('ccl_order_convert', $order_wrapper, $account);
     $order_wrapper->save();
 
     return $order_wrapper;
   }
 
   return FALSE;
-}
\ No newline at end of file
+}
+
+/**
+ * Login user and convert his/her anonymous order.
+ */
+function ccl_login_convert_order($uid, $order) {
+  global $user;
+  // If the user was logged in during this request, make sure we are using the
+  // full user object.
+  if ($user->uid) {
+    $user = user_load($user->uid);
+  }
+  else {
+    // Load the validated user into the global $user variable.
+    $user = user_load($uid);
+
+    // "Finalize" the login by triggering the appropriate system messages, IP
+    // address and login timestamp logging, and user login hook.
+    user_login_finalize();
+  }
+
+  // Convert the current order from anonymous to authenticated and clear out
+  // our variable from the form state.
+  if (empty($order->uid)) {
+    ccl_order_convert($order, $user);
+  }
+}
+
+/**
+ *
+ */
+function ccl_account_information($order) {
+  $content[] = array(
+    '#type' => 'item',
+    '#markup' => t('%checkout', array('%checkout' => t('Your account will be created after completing checkout.'))),
+  );
+  $content[] = array(
+    '#type' => 'item',
+    '#title' => t('Username'),
+    '#markup' => check_plain($order->data['commerce_checkout_login_register']['username']),
+  );
+  $content[] = array(
+    '#type' => 'item',
+    '#title' => t('E-mail address'),
+    '#markup' => check_plain($order->data['commerce_checkout_login_register']['mail']),
+  );
+
+  return $content;
+}
diff --git a/commerce_checkout_login.panes.inc b/commerce_checkout_login.panes.inc
new file mode 100644
index 0000000..f55c625
--- /dev/null
+++ b/commerce_checkout_login.panes.inc
@@ -0,0 +1,234 @@
+<?php
+
+/**
+ * @file Contains all callbacks for Commerce checkout login's checkout panes.
+ */
+
+/**
+ * Account pane form callback.
+ */
+function commerce_checkout_login_account_form($form, &$form_state, $checkout_pane, $order) {
+  if ($form_state['account']->uid > 0) {
+    // The user is logged in, display account information.
+    module_load_include('inc', 'commerce_order', 'includes/commerce_order.checkout_pane');
+    $form['account_info']['#markup'] = commerce_order_account_pane_review($form, $form_state, $checkout_pane, $order);
+  }
+  else {
+
+    $replacements = array(
+      '%login' => t('Login & checkout'),
+      '%register' => t('Register & checkout'),
+      '%guest' => t('Checkout as guest')
+    );
+    $form['help']['#type'] = 'item';
+
+    if (variable_get('user_register', 0) && variable_get('commerce_checkout_login_allow_anonymous_checkout', TRUE)) {
+      // All forms of checkout are allowed.
+      $form['help']['#markup'] = t('If you have an existing account you can login by entering your login information in the form on the left and clicking the %login button. You can also create a new account by filling the form on the right and clicking the %register button or you can choose to skip account creation and checkout as a guest by clicking the %guest button at the bottom of the form.', $replacements);
+    }
+    elseif (variable_get('user_register', 0)) {
+      // Only login and register are allowed, guest checkout is disallowed.
+      $form['help']['#markup'] = t('If you have an existing account you can login by entering your login information in the form on the left and clicking the %login button or you can create a new account by filling the form on the right and clicking the %register button.', $replacements);
+    }
+    elseif (variable_get('commerce_checkout_login_allow_anonymous_checkout', TRUE)) {
+      // Only guest checkout and login are allowed, registration is disallowed.
+      $form['help']['#markup'] = t('If you have an existing account you can login by entering your login information in the form on the left and clicking the %login button or you can checkout as a guest by clicking the %guest button at the bottom of the form.', $replacements);
+    }
+    else {
+      // Only login is allowed, users are not allowed to perform guest checkout
+      // or create a new account themselves.
+      $form['help']['#markup'] = t('Please login to start the checkout process.', $replacements);
+    }
+
+    $form['select']['#type'] = 'container';
+
+    $form['select']['login'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Login'),
+    );
+
+    $form['select']['login']['mail'] = array(
+      '#type' => 'textfield',
+      '#title' => t('E-mail address'),
+      '#size' => 25,
+      '#required' => TRUE,
+    );
+
+    $form['select']['login']['password'] = array(
+      '#type' => 'password',
+      '#title' => t('Password'),
+      '#size' => 25,
+      '#required' => TRUE,
+    );
+
+    $form['select']['login']['continue'] = array(
+      '#type' => 'submit',
+      '#name' => 'login',
+      '#value' => t('Login & checkout'),
+      '#validate' => array('commerce_checkout_form_validate'),
+      '#limit_validation_errors' => array(
+        array(
+          'account_form',
+          'select',
+          'login'
+        )
+      ),
+      '#submit' => array('commerce_checkout_form_submit'),
+    );
+
+    // Only allow the user to register an account if they are allowed to do so.
+    if (variable_get('user_register', 0)) {
+      drupal_add_css(drupal_get_path('module', 'commerce_checkout_login') . '/css/commerce_checkout_login.admin.css');
+      $form['select']['register'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Register account'),
+      );
+
+      $form['select']['register']['username'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Username'),
+        '#size' => 25,
+        '#required' => TRUE,
+        '#default_value' => isset($order->data['commerce_checkout_login_register']['username']) ? $order->data['commerce_checkout_login_register']['username'] : '',
+        '#maxlength' => USERNAME_MAX_LENGTH,
+        '#description' => t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, apostrophes, and underscores.'),
+      );
+
+      $form['select']['register']['mail'] = array(
+        '#type' => 'textfield',
+        '#title' => t('E-mail address'),
+        '#default_value' => isset($order->data['commerce_checkout_login_register']['mail']) ? $order->data['commerce_checkout_login_register']['mail'] : '',
+        '#size' => 25,
+        '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
+        '#required' => TRUE,
+      );
+
+      if (variable_get('commerce_order_account_pane_mail_double_entry', FALSE)) {
+        $form['select']['register']['mail_confirm'] = array(
+          '#type' => 'textfield',
+          '#title' => t('Confirm e-mail address'),
+          '#default_value' => isset($order->data['commerce_checkout_login_register']['mail']) ? $order->data['commerce_checkout_login_register']['mail'] : '',
+          '#size' => 25,
+          '#description' => t('Provide your e-mail address in both fields.'),
+          '#required' => TRUE,
+        );
+      }
+
+      $form['select']['register']['continue'] = array(
+        '#type' => 'submit',
+        '#name' => 'register',
+        '#value' => t('Register & checkout'),
+        '#validate' => array('commerce_checkout_form_validate'),
+        '#limit_validation_errors' => array(
+          array(
+            'account_form',
+            'select',
+            'register'
+          )
+        ),
+        '#submit' => array('commerce_checkout_form_submit'),
+      );
+    }
+
+  }
+
+  return $form;
+}
+
+/**
+ * Account pane validation handler.
+ */
+function  commerce_checkout_login_account_form_validate($form, &$form_state, $checkout_pane, $order) {
+  switch ($form_state['triggering_element']['#name']) {
+    case 'login':
+      // The login form was submitted.
+      $mail = trim($form_state['values']['account_form']['select']['login']['mail']);
+      if ($error = user_validate_mail($mail)) {
+        // An invalid e-mail address was entered.
+        form_set_error('account_form][select][login][mail', $error);
+      }
+      elseif ($account = user_load_by_mail($mail)) {
+        // A user can be loaded using the supplied email address. validate it.
+        return ccl_validate_existing_account($form, $form_state, $account);
+      }
+      elseif (!empty($form_state['values']['account_form']['select']['login']['password'])) {
+        // Only check non-existing e-mail addresses if a password was entered to
+        // prevent information disclosure.
+        form_set_error('account_form][select][login][mail', t('Sorry, unrecognized e-mail address or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password', array('query' => array('name' => $mail))))));
+      }
+      break;
+
+    case 'register':
+      // The register form was submitted, but we won't even consider validating
+      // the form it if no e-mail address was set.
+      if (isset($form_state['values']['account_form']['select']['register']['mail'])) {
+        $mail = trim($form_state['values']['account_form']['select']['register']['mail']);
+        if ($error = user_validate_mail($mail)) {
+          form_set_error('account_form][select][register][mail', $error);
+        }
+        elseif (isset($form_state['values']['account_form']['select']['register']['mail_confirm'])
+        && $form_state['values']['account_form']['select']['register']['mail_confirm'] !== $mail) {
+          form_set_error('account_form][select][register][mail', t('The specified e-mail addresses do not match.'));
+        }
+        elseif (!empty($form_state['values']['account_form']['select']['register']['username'])
+          && $account = user_load_by_mail($mail)) {
+          // Only validate the e-mail address if a username was supplied to
+          // prevent information disclosure.
+          form_set_error('account_form][select][register][mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $mail, '@password' => url('user/password'))));
+        }
+        elseif ($account = user_load_by_name($form_state['values']['account_form']['select']['register']['username'])) {
+          form_set_error('account_form][select][register][username', t('The name %name is already taken.', array('%name' => $form_state['values']['account_form']['select']['register']['username'])));
+        }
+        else{
+          return TRUE;
+        }
+      }
+      break;
+
+    case 'guest':
+      // Guest checkout does not need any validation.
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+ * Account pane submit handler.
+ */
+function commerce_checkout_login_account_form_submit($form, &$form_state, $checkout_pane, $order) {
+  // commerce_checkout_login_uid gets set during ccl_validate_existing_account() if
+  // the account was validated successfully.
+  if (!empty($form_state['commerce_checkout_login_uid'])) {
+    ccl_login_convert_order($form_state['commerce_checkout_login_uid'], $order);
+    unset($form_state['commerce_checkout_login_uid']);
+  }
+  elseif (!empty($form_state['values']['account_form']['select']['register']['username'])
+    && !empty($form_state['values']['account_form']['select']['register']['mail'])
+  ) {
+    $order->data['commerce_checkout_login_register'] = $form_state['values']['account_form']['select']['register'];
+  }
+}
+
+/**
+ * Account pane settings form callback.
+ */
+function commerce_checkout_login_account_settings_form($checkout_pane) {
+  $form = array();
+
+  $form['commerce_checkout_login_allow_anonymous_checkout'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow anonymous checkout'),
+    '#description' => t('Checking this box allows anonymous users to checkout without creating a new account. Be sure to also disable the account creation rule defined by commerce.'),
+    '#default_value' => variable_get('commerce_checkout_login_allow_anonymous_checkout', TRUE),
+  );
+
+  $form['commerce_order_account_pane_mail_double_entry'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Require double entry of email address.'),
+    '#description' => t('Forces anonymous users to enter their email address in two consecutive fields, which must have identical values.') . '<br>' . t('This field uses the same setting as the account pane provided by Commerce Order'),
+    '#default_value' => variable_get('commerce_order_account_pane_mail_double_entry', FALSE),
+  );
+
+  return $form;
+}
diff --git a/css/commerce_checkout_login.admin.css b/css/commerce_checkout_login.admin.css
new file mode 100644
index 0000000..8e6aa92
--- /dev/null
+++ b/css/commerce_checkout_login.admin.css
@@ -0,0 +1,8 @@
+#edit-account-form-select{
+  display: flex;
+  justify-content: space-between;
+}
+
+#edit-account-form-select > .form-wrapper {
+  flex:0 0 49%;
+}
diff --git a/tests/commerce_checkout_login.test b/tests/commerce_checkout_login.test
index 943ec07..7d6f9e7 100644
--- a/tests/commerce_checkout_login.test
+++ b/tests/commerce_checkout_login.test
@@ -77,6 +77,9 @@ class CommerceCheckoutLoginTestCase extends CommerceBaseTestCase {
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access checkout' => TRUE,
     ));
+    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
+      'access checkout' => TRUE,
+    ));
 
     // Create a dummy product display content type.
     $this->createDummyProductDisplayContentType();
@@ -118,10 +121,21 @@ class CommerceCheckoutLoginTestCase extends CommerceBaseTestCase {
 
     // Start checkout
     $this->drupalPost('cart', array(), t('Checkout'));
+    // Checkout as guest
+    $this->drupalPost(NULL, array(), t('Checkout as guest'));
+
+    // Post address info and e-mail address.
     $edit = $this->generateAddressFormValues();
     $edit['account[login][mail]'] = $this->generateEmail();
-    $this->drupalPost("checkout/{$this->order->order_id}", $edit, t('Continue to next step'));
-    $this->continueCheckout();
+    $this->drupalPost(NULL, $edit, t('Continue to next step'));
+    // Make sure only the e-mail address is displayed.
+    // (default commerce_account behaviour).
+    $this->emailInformationDisplayed( $edit['account[login][mail]']);
+    $this->noUsernameInformationDisplayed();
+
+    // Continue to review.
+    $this->drupalPost(NULL, array(), t('Continue to next step'));
+    $this->assertText(t('Checkout complete'));
     $this->assertEqual($this->last_uid, $this->getLastUid(), 'No new account created');
     $this->assertFalse($this->userLoggedIn(), 'User is still anonymous');
   }
@@ -131,43 +145,144 @@ class CommerceCheckoutLoginTestCase extends CommerceBaseTestCase {
    */
   protected function testCheckoutLogin() {
     $this->prepareAnonymousEnviroment();
-    // Disable the account creation rule, since we want to make sure commerce
-    // checkout login does not create a new user.
-    $this->disableAccountCreationRule();
 
     // Start checkout
     $this->drupalPost('cart', array(), t('Checkout'));
+
+    // Test e-mail address validation.
+    $edit = array(
+      'account_form[select][login][mail]' => 'invalid email',
+      'account_form[select][login][password]' => 'invalidpassword',
+    );
+    $this->drupalPost(NULL, $edit, t('Login & checkout'));
+    $this->assertRaw(t('The e-mail address %mail is not valid.', array('%mail' => 'invalid email')));
+
+    // Test non-existing e-mail address validation.
+    $edit['account_form[select][login][mail]'] = $this->generateEmail();
+    $replacement = array('@password' => url('user/password', array('query' => array('name' => $edit['account_form[select][login][mail]']))));
+    $this->drupalPost(NULL, $edit, t('Login & checkout'));
+    $this->assertRaw(t('Sorry, unrecognized e-mail address or password. <a href="@password">Have you forgotten your password?</a>', $replacement));
+
+    // Test password validation.
+    $edit['account_form[select][login][mail]'] = $this->store_customer->mail;
+    $replacement = array('@password' => url('user/password', array('query' => array('name' => $this->store_customer->mail))));
+    $this->drupalPost(NULL, $edit, t('Login & checkout'));
+    $this->assertRaw(t('Sorry, unrecognized e-mail address or password. <a href="@password">Have you forgotten your password?</a>', $replacement));
+
+    // Test correct credentials.
+    $edit['account_form[select][login][password]'] = $this->store_customer->pass_raw;
+    $this->drupalPost(NULL, $edit, t('Login & checkout'));
+    $this->assertNoText(t('Account information'), 'Account information is not displayed.');
+
+    // Enable display of account information and refresh the page.
+    variable_set('commerce_order_account_pane_auth_display', TRUE);
+    $this->drupalGet($this->getUrl());
+    // Verify the account information is shown.
+    $this->assertText(t('Account information'), 'Account information is displayed.');
+    $this->emailInformationDisplayed($edit['account_form[select][login][mail]']);
+    $this->usernameInformationDisplayed($this->store_customer->name);
+
+    // Continue to review.
     $edit = $this->generateAddressFormValues();
-    $edit['account[login][mail]'] = $this->store_customer->mail;
-    $this->drupalPost("checkout/{$this->order->order_id}", $edit, t('Continue to next step'));
-    $this->assertRaw(t('There is already an account registered to %mail. Please enter your password to continue checkout.', array('%mail' => $this->store_customer->mail)));
-    $this->assertFieldByName('account[login][password]');
-    $this->drupalPost(NULL, array('account[login][password]' => $this->store_customer->pass_raw), t('Continue to next step'));
-    $this->assertTrue($this->userLoggedIn(), 'User is logged in');
-    $this->continueCheckout();
+    $this->drupalPost(NULL, $edit, t('Continue to next step'));
+    // Verify the account information is shown.
+    $this->emailInformationDisplayed($this->store_customer->mail);
+    $this->usernameInformationDisplayed($this->store_customer->name);
+
+    // Complete checkout.
+    $this->drupalPost(NULL, array(), t('Continue to next step'));
+    $this->assertText(t('Checkout complete'));
     $this->assertEqual($this->last_uid, $this->getLastUid(), 'No new account created');
   }
 
   /**
-   * Test AJAX checkout process for user logging in during checkout.
+   * Test checkout process for user logging in during checkout.
    */
-  protected function testAJAXCheckoutLogin() {
+  protected function testCheckoutRegister() {
     $this->prepareAnonymousEnviroment();
-    // Disable the account creation rule, since we want to make sure commerce
-    // checkout login does not create a new user.
-    $this->disableAccountCreationRule();
+    $usertoregister = (object) array(
+      'username' => $this->randomName(),
+      'mail' => $this->generateEmail(),
+    );
 
     // Start checkout
     $this->drupalPost('cart', array(), t('Checkout'));
-    $edit['account[login][mail]'] = $this->store_customer->mail;
-    $this->drupalPostAJAX("checkout/{$this->order->order_id}", $edit, 'account[login][mail]');
-    $this->assertFieldByName('account[login][password]');
+
+    // Test e-mail address validation.
+    $edit = array(
+      'account_form[select][register][username]' => 'admin',
+      'account_form[select][register][mail]' => 'invalid email',
+    );
+    $this->drupalPost(NULL, $edit, t('Register & checkout'));
+    $this->assertRaw(t('The e-mail address %mail is not valid.', array('%mail' => 'invalid email')));
+
+    // Test non-matching e-mail validation.
+    // Enable e-mail confirmation so we can test it.
+    variable_set('commerce_order_account_pane_mail_double_entry', TRUE);
+    $edit = array(
+      'account_form[select][register][username]' => $this->randomName(),
+      'account_form[select][register][mail]' => $this->generateEmail(),
+      'account_form[select][register][mail_confirm]' => $this->generateEmail(),
+    );
+    $this->drupalPost($this->getUrl(), $edit, t('Register & checkout'));
+    $this->assertRaw(t('The specified e-mail addresses do not match.'));
+    variable_set('commerce_order_account_pane_mail_double_entry', FALSE);
+
+    // Test existing username validation.
+    $edit = array(
+      'account_form[select][register][username]' => $this->store_customer->name,
+      'account_form[select][register][mail]' => $this->generateEmail(),
+    );
+    $this->drupalPost($this->getUrl(), $edit, t('Register & checkout'));
+    $this->assertRaw(t('The name %name is already taken.', array('%name' => $this->store_customer->name)));
+
+    // Test existing username validation without e-mail address entered.
+    $this->drupalPost($this->getUrl(), array('account_form[select][register][username]' => 'admin'), t('Register & checkout'));
+    $this->assertNoRaw(t('The name %name is already taken.', array('%name' => $usertoregister->username)));
+
+    // Test existing e-mail validation
+    $edit = array(
+      'account_form[select][register][username]' => $this->randomName(),
+      'account_form[select][register][mail]' => $this->store_customer->mail,
+    );
+    $this->drupalPost($this->getUrl(), $edit, t('Register & checkout'));
+    $this->assertRaw(t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $this->store_customer->mail, '@password' => url('user/password'))));
+
+    // Test existing e-mail validation
+    $this->drupalPost($this->getUrl(), array('account_form[select][register][mail]' => $this->store_customer->mail), t('Register & checkout'));
+    $this->assertNoRaw(t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $this->store_customer->mail, '@password' => url('user/password'))));
+
+    // Test valid new user validation
+    $edit = array(
+      'account_form[select][register][username]' => $usertoregister->username,
+      'account_form[select][register][mail]' => $usertoregister->mail,
+    );
+    $this->drupalPost($this->getUrl(), $edit, t('Register & checkout'));
+    $this->noEmailInformationDisplayed($usertoregister->mail);
+    $this->noUsernameInformationDisplayed($usertoregister->username);
+    $this->assertEqual($this->last_uid, $this->getLastUid(), 'No new account created yet');
+
+    // Enable display of account information and refresh the page.
+    variable_set('commerce_order_account_pane_auth_display', TRUE);
+    $this->drupalGet($this->getUrl());
+    // Verify the account information is shown.
+    $this->assertText(t('Account information'), 'Account information is displayed.');
+    $this->emailInformationDisplayed($usertoregister->mail);
+    $this->usernameInformationDisplayed($usertoregister->username);
+    $this->assertEqual($this->last_uid, $this->getLastUid(), 'No new account created yet');
+
+    // Continue to review.
     $edit = $this->generateAddressFormValues();
-    $edit['account[login][password]'] = $this->store_customer->pass_raw;
     $this->drupalPost(NULL, $edit, t('Continue to next step'));
-    $this->assertTrue($this->userLoggedIn(), 'User is logged in');
-    $this->continueCheckout();
-    $this->assertEqual($this->last_uid, $this->getLastUid(), 'No new account created');
+    // Verify the account information is shown.
+    $this->emailInformationDisplayed($usertoregister->mail);
+    $this->usernameInformationDisplayed($usertoregister->username);
+    $this->assertEqual($this->last_uid, $this->getLastUid(), 'No new account created yet');
+
+    // Complete checkout.
+    $this->drupalPost(NULL, array(), t('Continue to next step'));
+    $this->assertText(t('Checkout complete'));
+    $this->assertNotEqual($this->last_uid, $this->getLastUid(), 'New account created');
   }
 
   /**
@@ -183,14 +298,6 @@ class CommerceCheckoutLoginTestCase extends CommerceBaseTestCase {
   }
 
   /**
-   * Continues checkout after the authentication is done.
-   */
-  protected function continueCheckout() {
-    $this->assertUrl("checkout/{$this->order->order_id}/review", array(), 'Checkout proceeded to the review step');
-    $this->drupalPost(NULL, array(), t('Continue to next step'));
-  }
-
-  /**
    * Generates some default form values for the checkout step.
    * @return array
    */
@@ -228,4 +335,23 @@ class CommerceCheckoutLoginTestCase extends CommerceBaseTestCase {
     return !empty($links);
   }
 
+  protected function usernameInformationDisplayed($username) {
+    $this->assertText(t('Username'), 'Account information shows show the username label');
+    $this->assertText($username, 'Account information shows the username');
+
+  }
+
+  protected function noUsernameInformationDisplayed() {
+    $this->assertText(t('Username'), 'Account information does not show the username label');
+  }
+
+  protected function emailInformationDisplayed($email) {
+    $this->assertText(t('E-mail address'), 'Account information shows the e-mail address label');
+    $this->assertText($email, 'Account information shows the e-mail address');
+  }
+
+  protected function noEmailInformationDisplayed($email) {
+    $this->assertNoText(t('E-mail address'), 'Account information does not show the e-mail address label');
+    $this->assertNoText($email, 'Account information does not show the e-mail address');
+  }
 }
