diff --git a/include/ajax.admin.php b/include/ajax.admin.php
index b1f910c2a08d7464a4c3b47c391a884664206789..6869eaad000070c8bb1c2569f7d51a6daa77ff4a 100644
--- a/include/ajax.admin.php
+++ b/include/ajax.admin.php
@@ -199,7 +199,7 @@ class AdminAjaxAPI extends AjaxController {
         if (!$thisstaff->isAdmin())
             Http::response(403, 'Access denied');
 
-        $column = QueueColumn::create();
+        $column = new QueueColumn();
         if ($_POST) {
             $data_form = $column->getDataConfigForm($_POST);
             if ($data_form->isValid()) {
diff --git a/include/class.queue.php b/include/class.queue.php
index 09ece8de077efa43383262fce5582111d1431f31..7213d67ce692739f66fade1e8904779827b1a38a 100644
--- a/include/class.queue.php
+++ b/include/class.queue.php
@@ -116,10 +116,14 @@ class CustomQueue extends VerySimpleModel {
         $criteria = $criteria ?: $this->getCriteria(true);
         foreach ($criteria as $C) {
             list($path, $method, $value) = $C;
+            if ($path === ':keywords') {
+                $items[] = Format::htmlchars("\"{$value}\"");
+                continue;
+            }
             if (!isset($all[$path]))
                 continue;
-             list($label, $field) = $all[$path];
-             $items[] = $field->describeSearch($method, $value, $label);
+            list($label, $field) = $all[$path];
+            $items[] = $field->describeSearch($method, $value, $label);
         }
         return implode("\nAND ", $items);
     }
diff --git a/include/staff/templates/queue-savedsearches-nav.tmpl.php b/include/staff/templates/queue-savedsearches-nav.tmpl.php
index 3425ac4a563117c8d0ec4805a046848d0459c60d..7bc616a5fa1fb96ab42dca36dd849a89f5a47534 100644
--- a/include/staff/templates/queue-savedsearches-nav.tmpl.php
+++ b/include/staff/templates/queue-savedsearches-nav.tmpl.php
@@ -5,7 +5,7 @@
 // $child_selected - <bool> true if the selected queue is a descendent
 // $adhoc - not FALSE if an adhoc advanced search exists
 ?>
-<li class="primary-only item <?php if ($child_selected) echo ''; ?>">
+<li class="primary-only item <?php if ($child_selected) echo 'active'; ?>">
 <?php
   $href = 'href="tickets.php?queue=adhoc"';
   if (!isset($_SESSION['advsearch']))
diff --git a/scp/tickets.php b/scp/tickets.php
index aaaf653d01a33837d769d3c1ea43ce60eba70d3b..f1b6f48b191dd96b173f66e554c5a7ad10893bd4 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -38,49 +38,88 @@ if($_REQUEST['id'] || $_REQUEST['number']) {
     }
 }
 
-if ($_REQUEST['uid']) {
-    $user = User::lookup($_REQUEST['uid']);
-}
 if (!$ticket) {
+    // Display a ticket queue. Decide the contents
+    $queue_id = null;
+
+    // Search for user
+    if (isset($_GET['uid'])
+        && ($user = User::lookup($_GET['uid']))
+    ) {
+        $criteria = [
+            ['user__name', 'equal', $user->name],
+            ['user_id', 'equal', $user->id],
+        ];
+        if ($S = $_GET['status'])
+            // The actual state is tracked by the key
+            $criteria[] = ['status__state', 'includes', [$S => $S]];
+        $_SESSION['advsearch']['uid'] = $criteria;
+        $queue_id = "adhoc,uid";
+    }
+    // Search for organization tickets
+    elseif (isset($_GET['orgid'])
+        && ($org = Organization::lookup($_GET['orgid']))
+    ) {
+        $criteria = [
+            ['user__org__name', 'equal', $org->name],
+            ['user__org_id', 'equal', $org->id],
+        ];
+        if ($S = $_GET['status'])
+            $criteria[] = ['status__state', 'includes', [$S => $S]];
+        $_SESSION['advsearch']['orgid'] = $criteria;
+        $queue_id = "adhoc,orgid";
+    }
+    // Basic search (click on 🔍 )
+    elseif (isset($_GET['a']) && $_GET['a'] === 'search'
+        && ($_GET['query'])
+    ) {
+        $key = substr(md5($_GET['query']), -10);
+        if ($_GET['search-type'] == 'typeahead') {
+            // Use a faster index
+            $criteria = ['user__emails__address', 'equal', $_GET['query']];
+        }
+        else {
+            $criteria = [':keywords', null, $_GET['query']];
+        }
+        $_SESSION['advsearch'][$key] = [$criteria];
+        $queue_id = "adhoc,{$key}";
+    }
+
     $queue_key = sprintf('::Q:%s', ObjectModel::OBJECT_TYPE_TICKET);
-    $queue_name = strtolower($_GET['a'] ?: $_GET['status']); //Status is overloaded
-    if (!$queue_name && isset($_SESSION[$queue_key]))
-        $queue_name = $_SESSION[$queue_key];
-
-    // Stash current queue view
-    $_SESSION[$queue_key] = $queue_name;
-
-    // Set queue as status
-    if (@!isset($_REQUEST['advanced'])
-            && @$_REQUEST['a'] != 'search'
-            && !isset($_GET['status'])
-            && $queue_name)
-        $_GET['status'] = $_REQUEST['status'] = $queue_name;
-}
+    $queue_id = $queue_id ?: @$_GET['queue'] ?: $_SESSION[$queue_key]
+        ?: $cfg->getDefaultTicketQueueId();
+
+    // Recover advanced search, if requested
+    if (isset($_SESSION['advsearch'])
+        && strpos($queue_id, 'adhoc') === 0
+    ) {
+        list(,$key) = explode(',', $queue_id, 2);
+        // XXX: De-duplicate and simplify this code
+        $queue = new AdhocSearch(array(
+            'id' => $queue_id,
+            'root' => 'T',
+        ));
+        // For queue=queue, use the most recent search
+        if (!$key) {
+            reset($_SESSION['advsearch']);
+            $key = key($_SESSION['advsearch']);
+        }
+        $queue->config = $_SESSION['advsearch'][$key];
+    }
 
-$queue_id = @$_REQUEST['queue'] ?: $cfg->getDefaultTicketQueueId();
-if ((int) $queue_id) {
-    $queue = CustomQueue::lookup($queue_id);
-}
-elseif (isset($_SESSION['advsearch'])
-    && strpos($queue_id, 'adhoc') === 0
-) {
-    list(,$key) = explode(',', $queue_id, 2);
-    // XXX: De-duplicate and simplify this code
-    $queue = AdhocSearch::create(array(
-        'id' => $queue_id,
-        'root' => 'T',
-    ));
-    // For queue=queue, use the most recent search
-    if (!$key) {
-        reset($_SESSION['advsearch']);
-        $key = key($_SESSION['advsearch']);
+    // Make the current queue sticky
+    $_SESSION[$queue_key] = $queue_id;
+
+    if ((int) $queue_id && !$queue) {
+        $queue = CustomQueue::lookup($queue_id);
+    }
+    if (!$queue) {
+        $queue = CustomQueue::lookup($cfg->getDefaultTicketQueueId());
     }
-    $queue->config = $_SESSION['advsearch'][$key];
-    // Slight hack here to make the `adhoc` queue be selected
-    $_REQUEST['queue'] = 'adhoc,'.$key;
-}
 
+    // Set the queue_id for navigation to turn a top-level item bold
+    $_REQUEST['queue'] = $queue->getId();
+}
 
 // Configure form for file uploads
 $response_form = new SimpleForm(array(
@@ -411,17 +450,13 @@ as $q) {
 }
 
 // Add my advanced searches
-$nav->addSubMenu(function() use ($queue, $adhoc) {
+$nav->addSubMenu(function() use ($queue) {
     global $thisstaff;
     // A queue is selected if it is the one being displayed. It is
     // "child" selected if its ID is in the path of the one selected
-    $child_selected = $queue && !$queue->isAQueue();
+    $child_selected = $queue instanceof SavedSearch;
     $searches = SavedSearch::forStaff($thisstaff)->all();
 
-    if (isset($adhoc)) {
-        // TODO: Add "Ad Hoc Search" to the personal children
-    }
-
     include STAFFINC_DIR . 'templates/queue-savedsearches-nav.tmpl.php';
 });