diff --git a/admin_menu.js b/admin_menu.js
index 93238c8..c53b82b 100644
--- a/admin_menu.js
+++ b/admin_menu.js
@@ -35,7 +35,12 @@ Drupal.behaviors.adminMenu = {
     if (!$adminMenu.length && settings.admin_menu.hash) {
       Drupal.admin.getCache(settings.admin_menu.hash, function (response) {
           if (typeof response == 'string' && response.length > 0) {
-            $('body', context).prepend(response);
+            // Insert this in the same location and with the same markup that
+            // it would have had if it had been placed on the page by the
+            // server-side code.
+            // @todo: Ideally the wrapping markup should be returned as part of
+            //   the AJAX response.
+            $('body', context).append('<div class="region region-page-bottom">' + response + '</div>');
           }
           var $adminMenu = $('#admin-menu:not(.admin-menu-processed)', context);
           // Apply our behaviors.
diff --git a/admin_menu.module b/admin_menu.module
index 9ae9251..af96f1b 100644
--- a/admin_menu.module
+++ b/admin_menu.module
@@ -110,12 +110,38 @@ function admin_menu_menu_alter(&$items) {
 }
 
 /**
+ * Implements hook_menu_link_insert().
+ */
+function admin_menu_menu_link_insert($link) {
+  // Flush all of our caches to pick up the link.
+  admin_menu_flush_caches();
+}
+
+/**
+ * Implements hook_menu_link_update().
+ */
+function admin_menu_menu_link_update($link) {
+  // Flush all of our caches to pick up the link.
+  admin_menu_flush_caches();
+}
+
+/**
+ * Implements hook_menu_link_delete().
+ */
+function admin_menu_menu_link_delete($link) {
+  // Flush all of our caches to pick up the link.
+  admin_menu_flush_caches();
+}
+
+/**
  * Implements hook_init().
  *
  * We can't move this into admin_menu_footer(), because PHP-only based themes
  * like chameleon load and output scripts and stylesheets in front of
  * theme_closure(), so we ensure Admin menu's styles and scripts are loaded on
  * all pages via hook_init().
+ *
+ * @see admin_menu_page_build()
  */
 function admin_menu_init() {
   if (!user_access('access administration menu') || admin_menu_suppress(FALSE)) {
@@ -207,12 +233,37 @@ function admin_menu_suppress($set = TRUE) {
 }
 
 /**
- * Implements hook_page_alter().
+ * Implements hook_page_build().
  */
-function admin_menu_page_alter(&$page) {
+function admin_menu_page_build(&$page) {
   $page['page_bottom']['admin_menu'] = array(
     '#markup' => admin_menu_output(),
   );
+
+  // Attach the administration menu JavaScript to the same part of the $page
+  // array as the menu itself. This ensures that when this region of the page
+  // is not intended to be rendered (for example, inside the Overlay), the
+  // JavaScript won't be added either. (If the JavaScript were added, the
+  // client-side code would add the menu to the page even when it isn't
+  // supposed to be there.)
+  // @todo Should all the JavaScript added in admin_menu_init() move here too,
+  //   rather than just this file?
+  if (user_access('access administration menu') && !admin_menu_suppress(FALSE)) {
+    $page['page_bottom']['admin_menu']['#attached']['js'][] = drupal_get_path('module', 'admin_menu') . '/admin_menu.js';
+  }
+}
+
+/**
+ * Implements hook_system_info_alter().
+ *
+ * Indicate that the 'page_bottom' region (in which the administration menu
+ * is displayed) is an overlay supplemental region that should be refreshed
+ * whenever its content is updated.
+ */
+function admin_menu_system_info_alter(&$info, $file, $type) {
+  if ($type == 'theme') {
+    $info['overlay_supplemental_regions'][] = 'page_bottom';
+  }
 }
 
 /**
@@ -241,7 +292,7 @@ function admin_menu_js() {
  *   The cache ID of the data to retrieve.
  */
 function admin_menu_cache_get($cid) {
-  static $cache = array();
+  $cache = &drupal_static(__FUNCTION__, array());
 
   if (!variable_get('admin_menu_cache_client', TRUE)) {
     return FALSE;
@@ -380,12 +431,13 @@ function admin_menu_output() {
   $cid = 'admin_menu:' . session_id() . ':' . $language->language;
 
   // Do nothing at all here if the client supports client-side caching, the user
-  // has a hash, and is NOT requesting the cache update path. Consult the hash
-  // cache last, since it requires a DB request.
+  // has a hash, and is NOT requesting either the cache update path or Overlay
+  // module's AJAX update path. Consult the hash cache last, since it requires a
+  // DB request.
   // @todo Implement a sanity-check to prevent permanent double requests; i.e.
   //   what if the client-side cache fails for any reason and performs a second
   //   request on every page?
-  if (!empty($_COOKIE['has_js']) && strpos($_GET['q'], 'js/admin_menu/cache') !== 0) {
+  if (!empty($_COOKIE['has_js']) && strpos($_GET['q'], 'js/admin_menu/cache') !== 0 && strpos($_GET['q'], 'overlay-ajax/') !== 0) {
     if (admin_menu_cache_get($cid)) {
       return;
     }
@@ -549,7 +601,7 @@ function theme_admin_menu_links($variables) {
       '#options' => array(),
     );
     // Render children to determine whether this link is expandable.
-    if (isset($elements[$path]['#type']) || isset($elements[$path]['#theme'])) {
+    if (isset($elements[$path]['#type']) || isset($elements[$path]['#theme']) || isset($elements[$path]['#pre_render'])) {
       $elements[$path]['#admin_menu_depth'] = $depth_child;
       $elements[$path]['#children'] = drupal_render($elements[$path]);
     }
@@ -664,6 +716,7 @@ function admin_menu_flush_caches() {
   // Flush cached output of admin_menu.
   cache_clear_all('admin_menu:', 'cache_menu', TRUE);
   // Flush client-side cache hashes.
+  drupal_static_reset('admin_menu_cache_get');
   // db_table_exists() required for SimpleTest.
   if (db_table_exists('cache_admin_menu')) {
     cache_clear_all('*', 'cache_admin_menu', TRUE);
diff --git a/admin_menu_toolbar/admin_menu_toolbar.css b/admin_menu_toolbar/admin_menu_toolbar.css
index 8aeb5f2..9cf9333 100644
--- a/admin_menu_toolbar/admin_menu_toolbar.css
+++ b/admin_menu_toolbar/admin_menu_toolbar.css
@@ -13,6 +13,9 @@
 html body.admin-menu {
   margin-top: 29px !important;
 }
+html body.admin-menu-with-shortcuts {
+  margin-top: 62px !important;
+}
 body div#toolbar {
   top: 30px;
 }
@@ -118,17 +121,16 @@ body div#toolbar {
 /**
  * Shortcuts widget.
  */
+/* Reset admin_menu styles for the widget and all shortcuts in it. */
+#admin-menu li.admin-menu-shortcuts-inactive ul {
+  display: none !important;
+  left: -999em !important;
+}
 #admin-menu li.admin-menu-shortcuts-active ul {
   display: block !important;
   left: 20px !important;
-  right: 20px;
-  width: auto;
 }
 #admin-menu li.admin-menu-shortcuts ul {
-  background-color: #666;
-  left: 20px !important;
-  padding: 5px 10px;
-  right: 20px;
   width: auto;
 }
 #admin-menu li.admin-menu-shortcuts ul li {
@@ -137,17 +139,26 @@ body div#toolbar {
   width: auto;
 }
 #admin-menu li.admin-menu-shortcuts ul li a {
-  border-radius: 5px;
-  -moz-border-radius: 5px;
-  -webkit-border-radius: 5px;
   border-top: 0;
-  padding: 5px 10px 5px 5px;
-  margin-right: 5px;
 }
-#admin-menu li.admin-menu-shortcuts ul li a:hover {
-  background: #555;
+
+/* Wrapper list excluding shortcuts themselves. */
+#admin-menu li.admin-menu-shortcuts > ul {
+  background-color: #666;
+  padding: 5px 10px;
+  right: 20px;
+}
+#admin-menu li.admin-menu-shortcuts > ul > li {
+  width: 100%;
 }
-#admin-menu li.admin-menu-shortcuts ul li a.active:hover,
-#admin-menu li.admin-menu-shortcuts ul li a.active {
-  background: url(toolbar.png) 0 -20px repeat-x;
+
+/* Drop shadow. */
+html body.admin-menu-with-shortcuts #admin-menu li.admin-menu-shortcuts > ul {
+  -moz-box-shadow: 0 3px 20px #000;
+  -webkit-box-shadow: 0 3px 20px #000;
+  box-shadow: 0 3px 20px #000;
+  filter: progid:DXImageTransform.Microsoft.Shadow(color=#000000, direction='180', strength='10');
+  -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(color=#000000, direction='180', strength='10')";
+  z-index: -1;
 }
+
diff --git a/admin_menu_toolbar/admin_menu_toolbar.js b/admin_menu_toolbar/admin_menu_toolbar.js
index 28f8448..c4c09a7 100644
--- a/admin_menu_toolbar/admin_menu_toolbar.js
+++ b/admin_menu_toolbar/admin_menu_toolbar.js
@@ -4,6 +4,19 @@ Drupal.admin = Drupal.admin || {};
 Drupal.admin.behaviors = Drupal.admin.behaviors || {};
 
 /**
+ * Apply margin to page, taking into account the shortcuts.
+ *
+ * @see Drupal.behaviors.adminMenuMarginTop()
+ */
+Drupal.behaviors.adminMenuMarginTopShortcuts = {
+  attach: function (context, settings) {
+    if (!settings.admin_menu.suppress && settings.admin_menu.toolbar.margin_top_shortcuts) {
+      $('body:not(.admin-menu-with-shortcuts)', context).addClass('admin-menu-with-shortcuts');
+    }
+  }
+};
+
+/**
  * @ingroup admin_behaviors
  * @{
  */
@@ -20,6 +33,27 @@ Drupal.admin.behaviors.toolbarActiveTrail = function (context, settings, $adminM
 };
 
 /**
+ * Toggle the shortcut drawer.
+ */
+Drupal.admin.behaviors.toggleShortcutDrawer = function (context, settings, $adminMenu) {
+  var $body = $('body', context);
+  var $shortcuts = $('li.admin-menu-shortcuts', $adminMenu);
+  var $toggle = $('.toggle', $shortcuts);
+  $toggle.toggle(
+    function () {
+      $shortcuts.addClass('admin-menu-shortcuts-inactive').removeClass('admin-menu-shortcuts-active');
+      $body.removeClass('admin-menu-with-shortcuts');
+      return false;
+    },
+    function () {
+      $shortcuts.addClass('admin-menu-shortcuts-active').removeClass('admin-menu-shortcuts-inactive');
+      $body.addClass('admin-menu-with-shortcuts');
+      return false;
+    }
+  );
+};
+
+/**
  * @} End of "defgroup admin_behaviors".
  */
 
diff --git a/admin_menu_toolbar/admin_menu_toolbar.module b/admin_menu_toolbar/admin_menu_toolbar.module
index 9c04b26..c60e80e 100644
--- a/admin_menu_toolbar/admin_menu_toolbar.module
+++ b/admin_menu_toolbar/admin_menu_toolbar.module
@@ -35,6 +35,12 @@ function admin_menu_toolbar_init() {
   elseif (drupal_is_front_page()) {
     $settings['activeTrail'] = url('<front>');
   }
+
+  // Adjust top margin for the shortcut bar.
+  if (module_exists('shortcut') && ($setting = variable_get('admin_menu_margin_top', 1))) {
+    $settings['margin_top_shortcuts'] = $setting;
+  }
+
   drupal_add_js(array('admin_menu' => array('toolbar' => $settings)), 'setting');
 }
 
@@ -44,27 +50,22 @@ function admin_menu_toolbar_init() {
 function admin_menu_toolbar_admin_menu_output_build(&$content) {
   // Add shortcuts menu.
   $content['shortcuts'] = array(
+    '#access' => module_exists('shortcut'),
     '#theme' => 'admin_menu_links',
     '#weight' => -200,
   );
   $content['shortcuts']['shortcuts'] = array(
     '#title' => t('Show shortcuts'),
     // @todo How do we want to trigger/store state?
-    '#attributes' => array('class' => array('admin-menu-shortcuts')),
-    //'#attributes' => array('class' => array('admin-menu-shortcuts', 'admin-menu-shortcuts-active')),
+    '#attributes' => array('class' => array('admin-menu-shortcuts', 'admin-menu-shortcuts-active')),
     '#options' => array(
       'attributes' => array('class' => 'toggle'),
     ),
   );
-  // @todo Copy this from $content['menu'] instead.
-  $content['shortcuts']['shortcuts']['node-add'] = array(
-    '#title' => t('Add content'),
-    '#href' => 'node/add',
-  );
-  $content['shortcuts']['shortcuts']['admin-content-node'] = array(
-    '#title' => t('Find content'),
-    '#href' => 'admin/content/node',
-    '#access' => user_access('administer nodes'),
+  $content['shortcuts']['shortcuts']['shortcuts'] = array(
+    '#prefix' => '<div id="toolbar">',
+    '#suffix' => '</div>',
+    '#pre_render' => array('shortcut_toolbar_pre_render'),
   );
 }
 
