Index: admin/blog_pref.php
===================================================================
--- admin/blog_pref.php	(revision 3731)
+++ admin/blog_pref.php	(revision 3851)
@@ -345,5 +345,5 @@
     echo
     '<div class="multi-part" id="params" title="' . __('Parameters') . '">' .
-    '<h3 class="out-of-screen-if-js">' . __('Parameters') . '</h3>' .
+    '<div id="standard-pref"><h3>' . __('Blog parameters') . '</h3>' .
         '<form action="' . $action . '" method="post" id="blog-form">';
 
@@ -615,4 +615,5 @@
     '<br class="clear" />' . //Opera sucks
 
+    '</div>' .
     '</div>';
 
Index: admin/blog_theme.php
===================================================================
--- admin/blog_theme.php	(revision 3731)
+++ admin/blog_theme.php	(revision 3812)
@@ -20,5 +20,6 @@
     $core->themes,
     $core->blog->themes_path,
-    $core->blog->settings->system->store_theme_url
+    $core->blog->settings->system->store_theme_url,
+    !empty($_GET['nocache'])
 );
 adminThemesList::$distributed_modules = explode(',', DC_DISTRIB_THEMES);
@@ -105,4 +106,10 @@
 # -- Display modules lists --
 if ($core->auth->isSuperAdmin()) {
+
+    if (!$core->error->flag()) {
+        if (!empty($_GET['nocache'])) {
+            dcPage::success(__('Manual checking of themes update done successfully.'));
+        }
+    }
 
     # Updated modules from repo
@@ -134,4 +141,10 @@
 
             '</div>';
+    } else {
+        echo
+        '<form action="' . $list->getURL('', false) . '" method="get">' .
+        '<p><input type="hidden" name="nocache" value="1" />' .
+        '<input type="submit" value="' . __('Force checking update of themes') . '" /></p>' .
+            '</form>';
     }
 }
Index: admin/index.php
===================================================================
--- admin/index.php	(revision 3781)
+++ admin/index.php	(revision 3833)
@@ -115,5 +115,5 @@
 if ($core->auth->user_prefs->dashboard->doclinks) {
     if (!empty($__resources['doc'])) {
-        $doc_links = '<div class="box small dc-box"><h3>' . __('Documentation and support') . '</h3><ul>';
+        $doc_links = '<div class="box small dc-box" id="doc-and-support"><h3>' . __('Documentation and support') . '</h3><ul>';
 
         foreach ($__resources['doc'] as $k => $v) {
@@ -150,4 +150,6 @@
 -------------------------------------------------------- */
 dcPage::open(__('Dashboard'),
+    dcPage::jsLoad('js/jquery/jquery-ui.custom.js') .
+    dcPage::jsLoad('js/jquery/jquery.ui.touch-punch.js') .
     dcPage::jsLoad('js/_index.js') .
     $admin_post_behavior .
@@ -244,32 +246,100 @@
 }
 
-# Dashboard items and contents (processed first, as we need to know the result before displaying the icons.)
-$dashboardItems = '';
-foreach ($__dashboard_items as $i) {
-    foreach ($i as $v) {
-        $dashboardItems .= $v;
-    }
-}
-$dashboardContents = '';
-foreach ($__dashboard_contents as $i) {
-    foreach ($i as $v) {
-        $dashboardContents .= $v;
-    }
-}
-
-# Dashboard elements: icons then boxes (items then contents)
-echo '<div id="dashboard-main">';
-
+# Get current main orders
+$main_order = $core->auth->user_prefs->dashboard->main_order;
+$main_order = ($main_order != '' ? explode(',', $main_order) : array());
+
+# Get current boxes orders
+$boxes_order = $core->auth->user_prefs->dashboard->boxes_order;
+$boxes_order = ($boxes_order != '' ? explode(',', $boxes_order) : array());
+
+# Get current boxes items orders
+$boxes_items_order = $core->auth->user_prefs->dashboard->boxes_items_order;
+$boxes_items_order = ($boxes_items_order != '' ? explode(',', $boxes_items_order) : array());
+
+# Get current boxes contents orders
+$boxes_contents_order = $core->auth->user_prefs->dashboard->boxes_contents_order;
+$boxes_contents_order = ($boxes_contents_order != '' ? explode(',', $boxes_contents_order) : array());
+
+$composeItems = function ($list, $blocks, $flat = false) {
+
+    $ret   = array();
+    $items = array();
+
+    if ($flat) {
+        $items = $blocks;
+    } else {
+        foreach ($blocks as $i) {
+            foreach ($i as $v) {
+                $items[] = $v;
+            }
+        }
+    }
+
+    # First loop to find ordered indexes
+    $order = array();
+    $index = 0;
+    foreach ($items as $v) {
+        if (preg_match('/<div.*?id="([^"].*?)".*?>/ms', $v, $match)) {
+            $id       = $match[1];
+            $position = array_search($id, $list, true);
+            if ($position !== false) {
+                $order[$position] = $index;
+            }
+        }
+        $index++;
+    }
+
+    # Second loop to combine ordered items
+    $index = 0;
+    foreach ($items as $v) {
+        $position = array_search($index, $order, true);
+        if ($position !== false) {
+            $ret[$position] = $v;
+        }
+        $index++;
+    }
+    # Reorder items on their position (key)
+    ksort($ret);
+
+    # Third loop to combine unordered items
+    $index = 0;
+    foreach ($items as $v) {
+        $position = array_search($index, $order, true);
+        if ($position === false) {
+            $ret[count($ret)] = $v;
+        }
+        $index++;
+    }
+
+    return join('', $ret);
+};
+
+# Compose dashboard items (doc, …)
+$dashboardItems = $composeItems($boxes_items_order, $__dashboard_items);
+# Compose dashboard contents (plugin's modules)
+$dashboardContents = $composeItems($boxes_contents_order, $__dashboard_contents);
+
+$__dashboard_boxes = array();
+if ($dashboardItems != '') {
+    $__dashboard_boxes[] = '<div class="db-items" id="db-items">' . $dashboardItems . '</div>';
+}
+if ($dashboardContents != '') {
+    $__dashboard_boxes[] = '<div class="db-contents" id="db-contents">' . $dashboardContents . '</div>';
+}
+$dashboardBoxes = $composeItems($boxes_order, $__dashboard_boxes, true);
+
+# Compose main area
+$__dashboard_main = array();
 if (!$core->auth->user_prefs->dashboard->nofavicons) {
     # Dashboard icons
-    echo '<div id="icons">';
+    $dashboardIcons = '<div id="icons">';
     foreach ($__dashboard_icons as $i) {
-        echo
-        '<p><a href="' . $i[1] . '"><img src="' . dc_admin_icon_url($i[2]) . '" alt="" />' .
+        $dashboardIcons .= '<p><a href="' . $i[1] . '"><img src="' . dc_admin_icon_url($i[2]) . '" alt="" />' .
             '<br /><span class="db-icon-title">' . $i[0] . '</span></a></p>';
     }
-    echo '</div>';
-}
-
+    $dashboardIcons .= '</div>';
+    $__dashboard_main[] = $dashboardIcons;
+}
 if ($core->auth->user_prefs->dashboard->quickentry) {
     if ($core->auth->check('usage,contentadmin', $core->blog->id)) {
@@ -279,5 +349,5 @@
         );
 
-        echo
+        $dashboardQuickEntry =
         '<div id="quick">' .
         '<h3>' . __('Quick entry') . sprintf(' &rsaquo; %s', $core->auth->getOption('post_format')) . '</h3>' .
@@ -320,16 +390,15 @@
             '</form>' .
             '</div>';
-    }
-}
-
-if ($dashboardContents != '' || $dashboardItems != '') {
-    echo
-        '<div id="dashboard-boxes">' .
-        ($dashboardItems != '' ? '<div class="db-items">' . $dashboardItems . '</div>' : '') .
-        ($dashboardContents != '' ? '<div class="db-contents">' . $dashboardContents . '</div>' : '') .
-        '</div>';
-}
-
-echo '</div>'; #end dashboard-main
+        $__dashboard_main[] = $dashboardQuickEntry;
+    }
+}
+if ($dashboardBoxes != '') {
+    $__dashboard_main[] = '<div id="dashboard-boxes">' . $dashboardBoxes . '</div>';
+}
+$dashboardMain = $composeItems($main_order, $__dashboard_main, true);
+
+# Dashboard elements
+echo '<div id="dashboard-main">' . $dashboardMain . '</div>';
+
 dcPage::helpBlock('core_dashboard');
 dcPage::close();
Index: admin/js/_auth.js
===================================================================
--- admin/js/_auth.js	(revision 3725)
+++ admin/js/_auth.js	(revision 3851)
@@ -3,6 +3,6 @@
 
 $(window).load(function() {
-  var uid = $('input[name=user_id]');
-  var upw = $('input[name=user_pwd]');
+  let uid = $('input[name=user_id]');
+  let upw = $('input[name=user_pwd]');
   uid.focus();
 
@@ -10,8 +10,5 @@
     return;
   }
-
-  uid.keypress(processKey);
-
-  function processKey(evt) {
+  uid.keypress(evt => {
     if (evt.which == 13 && upw.val() == '') {
       upw.focus();
@@ -19,5 +16,6 @@
     }
     return true;
-  }
+  });
+
   $.cookie('dc_admin_test_cookie', true);
   if ($.cookie('dc_admin_test_cookie')) {
Index: admin/js/_blog_pref.js
===================================================================
--- admin/js/_blog_pref.js	(revision 3706)
+++ admin/js/_blog_pref.js	(revision 3851)
@@ -1,53 +1,56 @@
 /*global $, dotclear, jsToolBar */
 'use strict';
-function checkQueryString() {
-	var blogUrl = $('#blog_url')[0].value;
-	var urlScan = $('#url_scan')[0].value;
-	var errorMsg = '';
-	if (/.*[^\/]$/.exec(blogUrl) && urlScan=='path_info') {
-		errorMsg = dotclear.msg.warning_path_info;
-	} else if (/.*[^\?]$/.exec(blogUrl) && urlScan=='query_string') {
-		errorMsg = dotclear.msg.warning_query_string;
-	}
-	$('p#urlwarning').remove();
-	if (errorMsg != '') {
-		$('#blog_url').parents('p').after('<p id="urlwarning" class="warning">'+errorMsg+'</p>');
-	}
-}
-
 
 $(function() {
-	var blog_url = $('#blog_url');
-	if (blog_url.length > 0 && !blog_url.is(':hidden')) {
-		checkQueryString();
-		$('#blog_url').focusout(checkQueryString);
-		$('body').on('change','#url_scan',checkQueryString);
-	}
+  var blog_url = $('#blog_url');
+  if (blog_url.length > 0 && !blog_url.is(':hidden')) {
+    var checkQueryString = function() {
+      const url = $('#blog_url')[0].value;
+      const scan = $('#url_scan')[0].value;
+      let msg = '';
+      if (/.*[^\/]$/.exec(url) && scan == 'path_info') {
+        msg = dotclear.msg.warning_path_info;
+      } else if (/.*[^\?]$/.exec(url) && scan == 'query_string') {
+        msg = dotclear.msg.warning_query_string;
+      }
+      $('p#urlwarning').remove();
+      if (msg != '') {
+        $('#blog_url').parents('p').after(`<p id="urlwarning" class="warning">${msg}</p>`);
+      }
+    };
+    checkQueryString();
+    $('#blog_url').focusout(checkQueryString);
+    $('body').on('change', '#url_scan', checkQueryString);
+  }
 
-	$('#date_format_select,#time_format_select').change(function() {
-		if ($(this).prop('value') == '') {
-			return;
-		}
-		$('#'+$(this).attr('id').replace('_select','')).prop('value', $(this).prop('value'));
-		$(this).parent().next('.chosen').html($(this).find(':selected').prop('label'));
-	});
+  $('#date_format_select,#time_format_select').change(function() {
+    if ($(this).prop('value') == '') {
+      return;
+    }
+    $('#' + $(this).attr('id').replace('_select', '')).prop('value', $(this).prop('value'));
+    $(this).parent().next('.chosen').html($(this).find(':selected').prop('label'));
+  });
 
-	// HTML text editor
-	if ($.isFunction(jsToolBar)) {
-		$('#blog_desc').each(function() {
-			var tbWidgetText = new jsToolBar(this);
-			tbWidgetText.context = 'blog_desc';
-			tbWidgetText.draw('xhtml');
-		});
-	}
+  // HTML text editor
+  if ($.isFunction(jsToolBar)) {
+    $('#blog_desc').each(function() {
+      let tbWidgetText = new jsToolBar(this);
+      tbWidgetText.context = 'blog_desc';
+      tbWidgetText.draw('xhtml');
+    });
+  }
 
-	// Hide advanced and plugins prefs sections
-	$('#advanced-pref h3').toggleWithLegend($('#advanced-pref').children().not('h3'),{
-		legend_click: true,
-		user_pref: 'dcx_blog_pref_adv'
-	});
-	$('#plugins-pref h3').toggleWithLegend($('#plugins-pref').children().not('h3'),{
-		legend_click: true,
-		user_pref: 'dcx_blog_pref_plg'
-	});
+  // Hide advanced and plugins prefs sections
+  $('#standard-pref h3').toggleWithLegend($('#standard-pref').children().not('h3'), {
+    legend_click: true,
+    hide: false
+  });
+  $('#advanced-pref h3').toggleWithLegend($('#advanced-pref').children().not('h3'), {
+    legend_click: true,
+    user_pref: 'dcx_blog_pref_adv',
+  });
+  $('#plugins-pref h3').toggleWithLegend($('#plugins-pref').children().not('h3'), {
+    legend_click: true,
+    user_pref: 'dcx_blog_pref_plg',
+  });
 });
Index: admin/js/_index.js
===================================================================
--- admin/js/_index.js	(revision 3781)
+++ admin/js/_index.js	(revision 3839)
@@ -155,4 +155,6 @@
         var xml = $('rsp>update', data).attr('ret');
         $('#content h2').after(xml);
+        // manage outgoing links
+        dotclear.outgoingLinks('#ajax-update a');
       }
     }
@@ -180,4 +182,6 @@
         }
         $('#dashboard-boxes div.db-items').prepend(xml);
+        // manage outgoing links
+        dotclear.outgoingLinks('#ajax-news a');
       }
     }
@@ -195,6 +199,6 @@
   }
   // Posts
-  var icon_com = $('#dashboard-main #icons p a[href="posts.php"]');
-  if (icon_com.length) {
+  var icon_post = $('#dashboard-main #icons p a[href="posts.php"]');
+  if (icon_post.length) {
     // Icon exists on dashboard
     // First pass
@@ -203,3 +207,40 @@
     dotclear.dbPostsCount_Timer = setInterval(dotclear.dbCommentsPost, 600 * 1000);
   }
+
+  // Dashboard boxes and their children are sortable
+  var set_positions = function(sel, id) {
+    var list = $(sel).sortable("toArray").join();
+    // Save positions (via services) for id
+    var params = {
+      f: 'setDashboardPositions',
+      xd_check: dotclear.nonce,
+      id: id,
+      list: list
+    };
+    $.post('services.php', params, function() {});
+  };
+  var init_positions = function(sel, id) {
+    $(sel).sortable({
+      cursor: 'move',
+      opacity: 0.5,
+      tolerance: "pointer",
+      update: function() {
+        set_positions(sel, id);
+      },
+      start: function() {
+        $(sel).addClass('sortable-area');
+      },
+      stop: function() {
+        $(sel).removeClass('sortable-area');
+      }
+    });
+  };
+  // Wait 5 seconds before activating ordering capabilities on dashboard
+  setTimeout(function() {
+    init_positions('#dashboard-main', 'main_order');
+    init_positions('#dashboard-boxes', 'boxes_order');
+    init_positions('#db-items', 'boxes_items_order');
+    init_positions('#db-contents', 'boxes_contents_order');
+  }, 5000);
+
 });
Index: admin/js/common.js
===================================================================
--- admin/js/common.js	(revision 3843)
+++ admin/js/common.js	(revision 3858)
@@ -140,19 +140,10 @@
     $(ctarget).click(function(e) {
       if (p.user_pref && set_user_pref) {
-        if (p.hide ^ p.reverse_user_pref) {
-          jQuery.post('services.php', {
-            'f': 'setSectionFold',
-            'section': p.user_pref,
-            'value': 1,
-            xd_check: dotclear.nonce
-          }, function() {});
-        } else {
-          jQuery.post('services.php', {
-            'f': 'setSectionFold',
-            'section': p.user_pref,
-            'value': 0,
-            xd_check: dotclear.nonce
-          }, function() {});
-        }
+        jQuery.post('services.php', {
+          'f': 'setSectionFold',
+          'section': p.user_pref,
+          'value': (p.hide ^ p.reverse_user_pref ? 1 : 0),
+          xd_check: dotclear.nonce
+        }, function() {});
         jQuery.cookie(p.user_pref, '', {
           expires: -1
@@ -169,30 +160,27 @@
 (function($) {
   $.expandContent = function(opts) {
-    var defaults = {};
-    $.expandContent.options = $.extend({}, defaults, opts);
     if (opts == undefined || opts.callback == undefined || !$.isFunction(opts.callback)) {
       return;
     }
     if (opts.line != undefined) {
-      multipleExpander(opts.line, opts.lines);
+      multipleExpander(opts.line, opts.lines, opts.callback);
     }
     opts.lines.each(function() {
-      singleExpander(this);
-    });
-  };
-  var singleExpander = function singleExpander(line) {
+      singleExpander(this, opts.callback);
+    });
+  };
+  var singleExpander = function singleExpander(line, callback) {
     $('<button type="button" class="details-cmd" aria-label="' + dotclear.img_plus_alt + '">' + dotclear.img_plus_txt + '</button>').click(function (e) {
       toggleArrow(this);
-      $.expandContent.options.callback.call(this, line);
+      callback(line);
       e.preventDefault();
     }).prependTo($(line).children().get(0)); // first td
   };
-  var multipleExpander = function multipleExpander(line, lines) {
+  var multipleExpander = function multipleExpander(line, lines, callback) {
     $('<button type="button" class="details-cmd" aria-label="' + dotclear.img_plus_alt + '">' + dotclear.img_plus_txt + '</button>').click(function (e) {
-      var that = this;
       var action = toggleArrow(this);
       lines.each(function() {
         toggleArrow(this.firstChild.firstChild, action);
-        $.expandContent.options.callback.call(that, this, action);
+        callback(this, action);
       });
       e.preventDefault();
@@ -311,5 +299,5 @@
   enterKeyInForm: function(frm_id, ok_id, cancel_id) {
     $(frm_id + ':not(' + cancel_id + ')').keyup(function(e) {
-      if (e.key == 'Enter') {
+      if ((e.key == 'Enter') && ($(ok_id).prop('disabled') !== true)) {
         e.preventDefault();
         e.stopPropagation();
@@ -445,4 +433,17 @@
       return true;
     });
+  },
+  outgoingLinks: function(target) {
+    $(target).filter(function() {
+      return ((this.hostname && this.hostname != location.hostname && !$(this).hasClass('modal') && !$(this).hasClass('modal-image')) || $(this).hasClass('outgoing'));
+    }).each(function() {
+      $(this).prop('title', $(this).prop('title') + ' (' + dotclear.msg.new_window + ')');
+      if (!$(this).hasClass('outgoing')) {
+        $(this).append('&nbsp;<img class="outgoing-js" src="images/outgoing-link.svg" alt=""/>');
+      }
+    }).click(function(e) {
+      e.preventDefault();
+      window.open($(this).attr('href'));
+    });
   }
 };
@@ -460,15 +461,5 @@
   });
   // manage outgoing links
-  $('a').filter(function() {
-    return ((this.hostname && this.hostname != location.hostname && !$(this).hasClass('modal') && !$(this).hasClass('modal-image')) || $(this).hasClass('outgoing'));
-  }).each(function() {
-    $(this).prop('title', $(this).prop('title') + ' (' + dotclear.msg.new_window + ')');
-    if (!$(this).hasClass('outgoing')) {
-      $(this).append('&nbsp;<img class="outgoing-js" src="images/outgoing-link.svg" alt=""/>');
-    }
-  }).click(function(e) {
-    e.preventDefault();
-    window.open($(this).attr('href'));
-  });
+  dotclear.outgoingLinks('a');
   // Popups: dealing with Escape key fired
   $('#dotclear-admin.popup').keyup(function(e) {
Index: admin/plugins.php
===================================================================
--- admin/plugins.php	(revision 3731)
+++ admin/plugins.php	(revision 3812)
@@ -16,5 +16,6 @@
     $core->plugins,
     DC_PLUGINS_ROOT,
-    $core->blog->settings->system->store_plugin_url
+    $core->blog->settings->system->store_plugin_url,
+    !empty($_GET['nocache'])
 );
 
@@ -115,4 +116,10 @@
 # -- Display modules lists --
 if ($core->auth->isSuperAdmin()) {
+
+    if (!$core->error->flag()) {
+        if (!empty($_GET['nocache'])) {
+            dcPage::success(__('Manual checking of plugins update done successfully.'));
+        }
+    }
 
     # Updated modules from repo
@@ -144,4 +151,10 @@
 
             '</div>';
+    } else {
+        echo
+        '<form action="' . $list->getURL('', false) . '" method="get">' .
+        '<p><input type="hidden" name="nocache" value="1" />' .
+        '<input type="submit" value="' . __('Force checking update of plugins') . '" /></p>' .
+            '</form>';
     }
 }
Index: admin/preferences.php
===================================================================
--- admin/preferences.php	(revision 3800)
+++ admin/preferences.php	(revision 3836)
@@ -60,5 +60,5 @@
 if (!empty($_GET['append']) || !empty($_GET['removed']) || !empty($_GET['neworder']) ||
     !empty($_GET['replaced']) || !empty($_POST['appendaction']) || !empty($_POST['removeaction']) ||
-    !empty($_GET['db-updated'])) {
+    !empty($_GET['db-updated']) || !empty($_POST['resetorder'])) {
     $default_tab = 'user-favorites';
 } elseif (!empty($_GET['updated'])) {
@@ -401,4 +401,17 @@
 }
 
+# Reset dashboard items order
+if (!empty($_POST['resetorder'])) {
+    $core->auth->user_prefs->dashboard->drop('main_order');
+    $core->auth->user_prefs->dashboard->drop('boxes_order');
+    $core->auth->user_prefs->dashboard->drop('boxes_items_order');
+    $core->auth->user_prefs->dashboard->drop('boxes_contents_order');
+
+    if (!$core->error->flag()) {
+        dcPage::addSuccessNotice(__('Dashboard items order have been successfully reset.'));
+        $core->adminurl->redirect("admin.user.preferences", array(), '#user-favorites');
+    }
+}
+
 /* DISPLAY
 -------------------------------------------------------- */
@@ -669,4 +682,5 @@
 echo '<h3>' . __('My dashboard') . '</h3>';
 
+# Favorites
 echo '<form action="' . $core->adminurl->get("admin.user.preferences") . '" method="post" id="favs-form" class="two-boxes odd">';
 
@@ -774,4 +788,5 @@
 echo '</form>';
 
+# Dashboard items
 echo
 '<form action="' . $core->adminurl->get("admin.user.preferences") . '" method="post" id="db-forms" class="two-boxes even">' .
@@ -835,4 +850,14 @@
     '</form>';
 
+# Dashboard items order (reset)
+echo '<form action="' . $core->adminurl->get("admin.user.preferences") . '" method="post" id="order-reset" class="two-boxes even">';
+echo '<div class="fieldset"><h4>' . __('Dashboard items order') . '</h4>';
+echo
+'<p>' .
+$core->formNonce() .
+'<input type="submit" name="resetorder" value="' . __('Reset dashboard items order') . '" /></p>';
+echo '</div>';
+echo '</form>';
+
 echo '</div>'; # /multipart-user-favorites
 
Index: admin/services.php
===================================================================
--- admin/services.php	(revision 3781)
+++ admin/services.php	(revision 3833)
@@ -25,4 +25,5 @@
 $core->rest->addFunction('setSectionFold', array('dcRestMethods', 'setSectionFold'));
 $core->rest->addFunction('getModuleById', array('dcRestMethods', 'getModuleById'));
+$core->rest->addFunction('setDashboardPositions', array('dcRestMethods', 'setDashboardPositions'));
 
 $core->rest->serve();
@@ -86,5 +87,5 @@
                 $feed = $feed_reader->parse($GLOBALS['__resources']['rss_news']);
                 if ($feed) {
-                    $ret = '<div class="box medium dc-box"><h3>' . __('Dotclear news') . '</h3><dl id="news">';
+                    $ret = '<div class="box medium dc-box" id="ajax-news"><h3>' . __('Dotclear news') . '</h3><dl id="news">';
                     $i   = 1;
                     foreach ($feed->items as $item) {
@@ -132,5 +133,5 @@
                 if (version_compare(phpversion(), $updater->getPHPVersion()) >= 0) {
                     $ret =
-                    '<div class="dc-update"><h3>' . sprintf(__('Dotclear %s is available!'), $new_v) . '</h3> ' .
+                    '<div class="dc-update" id="ajax-update"><h3>' . sprintf(__('Dotclear %s is available!'), $new_v) . '</h3> ' .
                     '<p><a class="button submit" href="' . $core->adminurl->get("admin.update") . '">' . sprintf(__('Upgrade now'), $new_v) . '</a> ' .
                     '<a class="button" href="' . $core->adminurl->get("admin.update", array('hide_msg' => 1)) . '">' . __('Remind me later') . '</a>' .
@@ -566,4 +567,24 @@
     }
 
+    public static function setDashboardPositions($core, $get, $post)
+    {
+        if (empty($post['id'])) {
+            throw new Exception('No zone name');
+        }
+        if (empty($post['list'])) {
+            throw new Exception('No sorted list of id');
+        }
+
+        if ($core->auth->user_prefs->dashboard === null) {
+            $core->auth->user_prefs->addWorkspace('dashboard');
+        }
+
+        $zone  = $post['id'];
+        $order = $post['list'];
+
+        $core->auth->user_prefs->dashboard->put($zone, $order);
+        return true;
+    }
+
     public static function getModuleById($core, $get, $post)
     {
Index: admin/style/default-dark.css
===================================================================
--- admin/style/default-dark.css	(revision 3853)
+++ admin/style/default-dark.css	(revision 3858)
@@ -229,5 +229,7 @@
 /* Typographie */
 :root {
-  --html-font-size: 62.5%; }
+  --html-font-size: 62.5%;
+  --body-color: #dcdee0;
+  --body-background: #272b30; }
 
 html {
@@ -1081,4 +1083,8 @@
   margin-bottom: .3em; }
 
+input[type=color] {
+  width: 4em;
+  height: 3em; }
+
 optgroup {
   font-weight: bold;
@@ -1583,10 +1589,6 @@
   padding: 0;
   overflow: hidden;
-  position: absolute;
-  top: 3em;
-  left: 0;
   background: #a2cbe9;
-  width: 100%;
-  z-index: 100; }
+  width: 100%; }
   #prelude li {
     list-style-type: none;
@@ -2111,7 +2113,10 @@
 #dashboard-main {
   text-align: center; }
+  #dashboard-main > *:last-child {
+    margin-bottom: 1em; }
 
 /* raccourcis */
 #icons {
+  margin: 1em auto 2em;
   display: flex;
   flex-wrap: wrap;
@@ -2150,7 +2155,7 @@
 /* billet rapide */
 #quick {
+  max-width: 72em;
+  margin: 1em auto 2em;
   padding: 1em;
-  max-width: 72em;
-  margin: 0 auto;
   background: #323334;
   border: 1px solid #dbdcdd;
@@ -2165,7 +2170,5 @@
     padding: .2em 1em .1em 24px;
     color: #323334; }
-  #quick #new_cat,
-  #quick .q-cat,
-  #quick .q-cat label {
+  #quick #new_cat, #quick .q-cat, #quick .q-cat label {
     display: inline-block;
     vertical-align: top;
@@ -2179,6 +2182,5 @@
 /* modules additionnels */
 #dashboard-boxes {
-  margin: 1em auto 1em;
-  padding-top: 2em;
+  margin: 1em auto 2em;
   display: flex;
   flex-wrap: wrap;
@@ -2192,20 +2194,16 @@
     text-align: left; }
 
-.db-items,
-.db-contents {
+.db-items, .db-contents {
   display: flex;
   flex-wrap: wrap;
   justify-content: center;
   flex: 1 1 auto; }
-  .db-items img,
-  .db-contents img {
+  .db-items img, .db-contents img {
     vertical-align: middle; }
-  .db-items ul,
-  .db-contents ul {
+  .db-items ul, .db-contents ul {
     display: block;
     padding-left: 1.5em;
     list-style: square; }
-  .db-items li,
-  .db-contents li {
+  .db-items li, .db-contents li {
     margin: 0.25em 0 0 0; }
 
@@ -3164,5 +3162,6 @@
 
 .offline {
-  color: #86888c; }
+  color: #86888c;
+  background: #323334; }
 
 /* caché pour tout le monde */
@@ -3193,4 +3192,10 @@
 
 /* ---------------------------------------------- Couleurs ajoutées via javascript
+
+/* Sortable (jQuery UI) */
+.sortable-area {
+  border: 1px dashed currentColor;
+  background-color: #4c4d4f; }
+
 /* color-picker.js */
 .color-color-picker {
Index: admin/style/default.css
===================================================================
--- admin/style/default.css	(revision 3853)
+++ admin/style/default.css	(revision 3858)
@@ -229,5 +229,7 @@
 /* Typographie */
 :root {
-  --html-font-size: 62.5%; }
+  --html-font-size: 62.5%;
+  --body-color: #323232;
+  --body-background: #fff; }
 
 html {
@@ -1081,4 +1083,8 @@
   margin-bottom: .3em; }
 
+input[type=color] {
+  width: 4em;
+  height: 3em; }
+
 optgroup {
   font-weight: bold;
@@ -1583,10 +1589,6 @@
   padding: 0;
   overflow: hidden;
-  position: absolute;
-  top: 3em;
-  left: 0;
   background: #a2cbe9;
-  width: 100%;
-  z-index: 100; }
+  width: 100%; }
   #prelude li {
     list-style-type: none;
@@ -2111,7 +2113,10 @@
 #dashboard-main {
   text-align: center; }
+  #dashboard-main > *:last-child {
+    margin-bottom: 1em; }
 
 /* raccourcis */
 #icons {
+  margin: 1em auto 2em;
   display: flex;
   flex-wrap: wrap;
@@ -2150,7 +2155,7 @@
 /* billet rapide */
 #quick {
+  max-width: 72em;
+  margin: 1em auto 2em;
   padding: 1em;
-  max-width: 72em;
-  margin: 0 auto;
   background: #f3f3f3;
   border: 1px solid #dbdbdb;
@@ -2165,7 +2170,5 @@
     padding: .2em 1em .1em 24px;
     color: #323232; }
-  #quick #new_cat,
-  #quick .q-cat,
-  #quick .q-cat label {
+  #quick #new_cat, #quick .q-cat, #quick .q-cat label {
     display: inline-block;
     vertical-align: top;
@@ -2179,6 +2182,5 @@
 /* modules additionnels */
 #dashboard-boxes {
-  margin: 1em auto 1em;
-  padding-top: 2em;
+  margin: 1em auto 2em;
   display: flex;
   flex-wrap: wrap;
@@ -2192,20 +2194,16 @@
     text-align: left; }
 
-.db-items,
-.db-contents {
+.db-items, .db-contents {
   display: flex;
   flex-wrap: wrap;
   justify-content: center;
   flex: 1 1 auto; }
-  .db-items img,
-  .db-contents img {
+  .db-items img, .db-contents img {
     vertical-align: middle; }
-  .db-items ul,
-  .db-contents ul {
+  .db-items ul, .db-contents ul {
     display: block;
     padding-left: 1.5em;
     list-style: square; }
-  .db-items li,
-  .db-contents li {
+  .db-items li, .db-contents li {
     margin: 0.25em 0 0 0; }
 
@@ -3164,5 +3162,6 @@
 
 .offline {
-  color: #676e78; }
+  color: #676e78;
+  background: #f3f3f3; }
 
 /* caché pour tout le monde */
@@ -3193,4 +3192,10 @@
 
 /* ---------------------------------------------- Couleurs ajoutées via javascript
+
+/* Sortable (jQuery UI) */
+.sortable-area {
+  border: 1px dashed currentColor;
+  background-color: #f3f3f3; }
+
 /* color-picker.js */
 .color-color-picker {
Index: admin/style/scss/partials/_classes.scss
===================================================================
--- admin/style/scss/partials/_classes.scss	(revision 3774)
+++ admin/style/scss/partials/_classes.scss	(revision 3811)
@@ -333,4 +333,5 @@
 .offline {
 	color: $offline;
+  background: $offline-background;
 }
 
Index: admin/style/scss/partials/_common.scss
===================================================================
--- admin/style/scss/partials/_common.scss	(revision 3763)
+++ admin/style/scss/partials/_common.scss	(revision 3828)
@@ -4,4 +4,7 @@
 	// May be superseed by user pref (typically from 50% to 75%, default 62.5%)
 	--html-font-size: #{$html-font-size};
+  // Main colors
+  --body-color: #{$body-color};
+  --body-background: #{$body-background};
 }
 
Index: admin/style/scss/partials/_forms.scss
===================================================================
--- admin/style/scss/partials/_forms.scss	(revision 3780)
+++ admin/style/scss/partials/_forms.scss	(revision 3823)
@@ -180,4 +180,8 @@
   margin-bottom: .3em;
 }
+input[type=color] {
+  width: 4em;
+  height: 3em;
+}
 optgroup {
   font-weight: bold;
Index: admin/style/scss/partials/_header.scss
===================================================================
--- admin/style/scss/partials/_header.scss	(revision 3763)
+++ admin/style/scss/partials/_header.scss	(revision 3822)
@@ -6,10 +6,6 @@
 	padding: 0;
 	overflow: hidden;
-	position: absolute;
-	top: 3em;
-	left: 0;
 	background: $prelude-background;
 	width: 100%;
-	z-index: 100;
 	li {
 		list-style-type: none;
Index: admin/style/scss/partials/_index.scss
===================================================================
--- admin/style/scss/partials/_index.scss	(revision 3787)
+++ admin/style/scss/partials/_index.scss	(revision 3839)
@@ -1,157 +1,142 @@
 #dashboard-main {
-	text-align: center;
+  text-align: center;
+  & > *:last-child {
+    margin-bottom: 1em;
+  }
 }
-
-
 /* raccourcis */
 
 #icons {
-	display: flex;
-	flex-wrap: wrap;
-	justify-content: center;
-	p {
-		width: 13em;
-		margin: 1em 0 2em;
+  margin: 1em auto 2em;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  p {
+    width: 13em;
+    margin: 1em 0 2em;
     display: flex;
     flex-direction: column;
     justify-content: flex-start;
     align-items: center;
-	}
-	a {
-		&,
-		&:link,
-		&:visited,
-		&:hover,
-		&:focus {
-			border-bottom-width: 0;
-			text-decoration: none;
-		}
-		span {
+  }
+  a {
+    &, &:link, &:visited, &:hover, &:focus {
+      border-bottom-width: 0;
+      text-decoration: none;
+    }
+    span {
       color: $index-link-color;
-			border-bottom: 1px dotted $index-link-border;
-		}
-		img {
-			padding: 1.5em;
-			background-color: $index-icon-background;
-			border-radius: 8px;
-			border: 1px solid $index-icon-border;
-			display: inline-block;
+      border-bottom: 1px dotted $index-link-border;
+    }
+    img {
+      padding: 1.5em;
+      background-color: $index-icon-background;
+      border-radius: 8px;
+      border: 1px solid $index-icon-border;
+      display: inline-block;
       filter: contrast($index-icon-contrast);
-		}
-		&:focus {
-			outline: 0;
-			span {
-				border: 2px solid $index-icon-outline;
-			}
-		}
-		&:focus,
-		&:hover {
-			img {
-				background: $index-icon-outline;
-				outline: 0;
-				border-color: $index-icon-border;
-			}
-			span {
-				border-bottom-style: solid;
-			}
-		}
-	}
+    }
+    &:focus {
+      outline: 0;
+      span {
+        border: 2px solid $index-icon-outline;
+      }
+    }
+    &:focus, &:hover {
+      img {
+        background: $index-icon-outline;
+        outline: 0;
+        border-color: $index-icon-border;
+      }
+      span {
+        border-bottom-style: solid;
+      }
+    }
+  }
 }
-
-
 /* billet rapide */
 
 #quick {
-	padding: 1em;
-	max-width: 72em;
-	margin: 0 auto;
-	background: $quick-background;
+  max-width: 72em;
+  margin: 1em auto 2em;
+  padding: 1em;
+  background: $quick-background;
   border: 1px solid $quick-border;
-	text-align: left;
-	h3 {
-		margin-bottom: 0.2em;
-		font-size: 1.2em;
-	}
-	p.qinfo {
-		margin: -.7em -1em 1em;
-		background: $quick-info-background url(msg-info.png) no-repeat .2em .2em;
-		border: 1px solid $quick-info-border;
-		padding: .2em 1em .1em 24px;
-		color: $quick-info-color;
-	}
-	#new_cat,
-	.q-cat,
-	.q-cat label {
-		display: inline-block;
-		vertical-align: top;
-		margin-right: 1em;
-		margin-top: 0;
-	}
-	.q-cat label {
-		margin-right: .3em;
-	}
-	#new_cat {
-		margin-bottom: 2em;
-	}
+  text-align: left;
+  h3 {
+    margin-bottom: 0.2em;
+    font-size: 1.2em;
+  }
+  p.qinfo {
+    margin: -.7em -1em 1em;
+    background: $quick-info-background url(msg-info.png) no-repeat .2em .2em;
+    border: 1px solid $quick-info-border;
+    padding: .2em 1em .1em 24px;
+    color: $quick-info-color;
+  }
+  #new_cat, .q-cat, .q-cat label {
+    display: inline-block;
+    vertical-align: top;
+    margin-right: 1em;
+    margin-top: 0;
+  }
+  .q-cat label {
+    margin-right: .3em;
+  }
+  #new_cat {
+    margin-bottom: 2em;
+  }
 }
-
-
 /* modules additionnels */
 
 #dashboard-boxes {
-	margin: 1em auto 1em;
-	padding-top: 2em;
-	display: flex;
-	flex-wrap: wrap;
-	justify-content: center;
-	.box {
-		padding: 10px;
-		border: 1px solid $index-box-border;
-		border-radius: 3px;
-		min-height: 200px;
-		margin: 10px;
-		text-align: left;
-	}
+  margin: 1em auto 2em;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  .box {
+    padding: 10px;
+    border: 1px solid $index-box-border;
+    border-radius: 3px;
+    min-height: 200px;
+    margin: 10px;
+    text-align: left;
+  }
 }
-
-.db-items,
-.db-contents {
-	//	display: inline-block;
-	//	text-align: center;
-	display: flex;
-	flex-wrap: wrap;
-	justify-content: center;
-	flex: 1 1 auto;
-	img {
-		vertical-align: middle;
-	}
-	ul {
-		display: block;
-		padding-left: 1.5em;
-		list-style: square;
-	}
-	li {
-		margin: 0.25em 0 0 0;
-	}
+.db-items, .db-contents {
+  //  display: inline-block;
+  //  text-align: center;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  flex: 1 1 auto;
+  img {
+    vertical-align: middle;
+  }
+  ul {
+    display: block;
+    padding-left: 1.5em;
+    list-style: square;
+  }
+  li {
+    margin: 0.25em 0 0 0;
+  }
 }
-
 .no-js .outgoing img {
-	display: none;
+  display: none;
 }
-
 .dc-box {
-	background: transparent url(dc_logos/sq-logo-32.png) no-repeat top right;
+  background: transparent url(dc_logos/sq-logo-32.png) no-repeat top right;
 }
-
 #news {
-	dt {
-		font-weight: bold;
-		margin: 0 0 0.4em 0;
-	}
-	dd {
-		margin: 0 0 1em 0;
-		p {
-			margin: 0.2em 0 0 0;
-		}
-	}
+  dt {
+    font-weight: bold;
+    margin: 0 0 0.4em 0;
+  }
+  dd {
+    margin: 0 0 1em 0;
+    p {
+      margin: 0.2em 0 0 0;
+    }
+  }
 }
Index: admin/style/scss/partials/_utils.scss
===================================================================
--- admin/style/scss/partials/_utils.scss	(revision 3763)
+++ admin/style/scss/partials/_utils.scss	(revision 3839)
@@ -1,3 +1,11 @@
 /* ---------------------------------------------- Couleurs ajoutées via javascript
+
+/* Sortable (jQuery UI) */
+
+.sortable-area {
+  border: 1px dashed currentColor;
+  background-color: $main-menu-background;
+}
+
 /* color-picker.js */
 
Index: admin/style/scss/themes/_dark.scss
===================================================================
--- admin/style/scss/themes/_dark.scss	(revision 3780)
+++ admin/style/scss/themes/_dark.scss	(revision 3811)
@@ -420,4 +420,5 @@
 
 $offline:                         $gray-semi-dark;
+$offline-background:              $gray-very-dark;
 
 $mark-attach-img:                 url('../images/attach.svg');
Index: admin/style/scss/themes/_light.scss
===================================================================
--- admin/style/scss/themes/_light.scss	(revision 3780)
+++ admin/style/scss/themes/_light.scss	(revision 3811)
@@ -419,4 +419,5 @@
 
 $offline:                         $gray-dark;                         // #676e78
+$offline-background:              $gray-very-light;                   // #f3f3f3
 
 $mark-attach-img:                 url('../images/attach.svg');
