diff --git a/deploy/csp/index.js b/deploy/csp/index.js
index 1d67da419baa8f3c60bb7e93893ce5939f9d5ee2..e976dd482d2845490dd24bebef212ea1ab0aeb17 100644
--- a/deploy/csp/index.js
+++ b/deploy/csp/index.js
@@ -115,7 +115,7 @@ module.exports = {
           'https://unpkg.com/d3@6.2.0/', // required for preview component
           'https://unpkg.com/mathjax@3.1.2/', // math jax
           'https://unpkg.com/three-surfer@0.0.13/dist/bundle.js', // for threeSurfer (freesurfer support in browser)
-          'https://unpkg.com/ng-layer-tune@0.0.6/dist/ng-layer-tune/', // needed for ng layer control
+          'https://unpkg.com/ng-layer-tune@0.0.12/dist/ng-layer-tune/', // needed for ng layer control
           'https://unpkg.com/hbp-connectivity-component@0.6.6/', // needed for connectivity component
           (req, res) => res.locals.nonce ? `'nonce-${res.locals.nonce}'` : null,
           ...SCRIPT_SRC,
diff --git a/docs/releases/v2.11.1.md b/docs/releases/v2.11.1.md
new file mode 100644
index 0000000000000000000000000000000000000000..3c4b52dceda310dbf1790cef6ff3b245e5875ffa
--- /dev/null
+++ b/docs/releases/v2.11.1.md
@@ -0,0 +1,20 @@
+# v2.11.1
+
+## Feature
+
+- Allow point assignment result to be sorted
+- Allow point assignment result to be downloaded as csv
+- Informs user when atlas download should be occurring, and check popup blocker
+- Restores Julich Brain 2.9 in Colin 27 space full mesh view
+
+## Bugfixes
+
+- Fixed point assignment full table not showing
+- On template/parcellation/atlas change, clear currently selected feature
+
+## Behind the scenes
+
+- Bump siibra-api version dependency. Remove guard for feature type query restrictions
+- Removed unused components
+- Tweaked context menu, showing on hover effects
+- now also attempts to fetch `transform.json` when external layer is populated
diff --git a/mkdocs.yml b/mkdocs.yml
index 0f21368640d98f4d765b121fe151f77a45ad86c5..df2d3dcc9969d727dc219a4a2450f0da70533330 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -33,6 +33,7 @@ nav:
     - Fetching datasets: 'advanced/datasets.md'
     - Display non-atlas volumes: 'advanced/otherVolumes.md'
   - Release notes:
+    - v2.11.1: 'releases/v2.11.1.md'
     - v2.11.0: 'releases/v2.11.0.md'
     - v2.10.3: 'releases/v2.10.3.md'
     - v2.10.2: 'releases/v2.10.2.md'
diff --git a/package.json b/package.json
index 593c06d72221ece38464f61b65e29828639ff594..9719e8ac3d423f69b3e79bc3c266675522175327 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "siibra-explorer",
-  "version": "2.11.0",
+  "version": "2.11.1",
   "description": "siibra-explorer - explore brain atlases. Based on humanbrainproject/nehuba & google/neuroglancer. Built with angular",
   "scripts": {
     "lint": "eslint src --ext .ts",
diff --git a/src/atlas-download/atlas-download.directive.spec.ts b/src/atlas-download/atlas-download.directive.spec.ts
index e81fe2966b376e21eded2b6ec96a79a85faaf616..61c17884a4151cbf5d22cd056e8ca42fc9e242d6 100644
--- a/src/atlas-download/atlas-download.directive.spec.ts
+++ b/src/atlas-download/atlas-download.directive.spec.ts
@@ -3,7 +3,7 @@ import { AtlasDownloadDirective } from './atlas-download.directive';
 
 describe('AtlasDownloadDirective', () => {
   it('should create an instance', () => {
-    const directive = new AtlasDownloadDirective(NEVER as any);
+    const directive = new AtlasDownloadDirective(NEVER as any, null);
     expect(directive).toBeTruthy();
   });
 });
diff --git a/src/atlas-download/atlas-download.directive.ts b/src/atlas-download/atlas-download.directive.ts
index ce873301181fa39c1975848bd4a76de9b09adbf4..9b2ba98268b8f52cebec05803ca637a0d75e2353 100644
--- a/src/atlas-download/atlas-download.directive.ts
+++ b/src/atlas-download/atlas-download.directive.ts
@@ -1,4 +1,5 @@
 import { Directive, HostListener } from '@angular/core';
+import { MatSnackBar } from '@angular/material/snack-bar';
 import { Store, select } from '@ngrx/store';
 import { Subject, concat, of } from 'rxjs';
 import { distinctUntilChanged, shareReplay, take } from 'rxjs/operators';
@@ -70,6 +71,7 @@ export class AtlasDownloadDirective {
        */
       window.open(`${endpoint}/atlas_download/${task_id}/download`, "_blank")
       this.#busy$.next(false)
+      this.snackbar.open(`Download starting. If it has not, please check your browser's popup blocker.`, 'Dismiss')
     } catch (e) {
       this.#busy$.next(false)
       this.#error$.next(e.toString())
@@ -89,6 +91,6 @@ export class AtlasDownloadDirective {
   #error$ = new Subject<string>()
   error$ = this.#error$.pipe()
 
-  constructor(private store: Store<MainState>) { }
+  constructor(private store: Store<MainState>, private snackbar: MatSnackBar) { }
 
 }
diff --git a/src/atlas-download/atlas-download.module.ts b/src/atlas-download/atlas-download.module.ts
index b4181a9cc0526254f2cabd6fbe1aa7b9894acfc8..910154cb4bce732b351da2a27738d85cab6a275a 100644
--- a/src/atlas-download/atlas-download.module.ts
+++ b/src/atlas-download/atlas-download.module.ts
@@ -1,6 +1,7 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { AtlasDownloadDirective } from './atlas-download.directive';
+import { MatSnackBarModule } from '@angular/material/snack-bar';
 
 
 @NgModule({
@@ -9,6 +10,7 @@ import { AtlasDownloadDirective } from './atlas-download.directive';
   ],
   imports: [
     CommonModule,
+    MatSnackBarModule,
   ],
   exports: [
     AtlasDownloadDirective
diff --git a/src/atlasComponents/sapi/sapi.service.ts b/src/atlasComponents/sapi/sapi.service.ts
index faf55163bb5607a3b9214cee6e4b6089e75cfc40..7959d63fbd7715d7be672d626e02ffaa77d68100 100644
--- a/src/atlasComponents/sapi/sapi.service.ts
+++ b/src/atlasComponents/sapi/sapi.service.ts
@@ -22,7 +22,7 @@ export const useViewer = {
 } as const
 
 export const SIIBRA_API_VERSION_HEADER_KEY='x-siibra-api-version'
-export const EXPECTED_SIIBRA_API_VERSION = '0.3.3'
+export const EXPECTED_SIIBRA_API_VERSION = '0.3.4'
 
 let BS_ENDPOINT_CACHED_VALUE: Observable<string> = null
 
@@ -515,11 +515,11 @@ export class SAPI{
     const map = await this.getLabelledMap(parcellation, template)
 
     for (const regionname in map.indices) {
-      if (parcellation.id === IDS.PARCELLATION.CORTICAL_LAYERS) {
-        if (regionname.includes("left") || regionname.includes("right")) {
-          continue
-        }
-      }
+      // if (parcellation.id === IDS.PARCELLATION.CORTICAL_LAYERS) {
+      //   if (regionname.includes("left") || regionname.includes("right")) {
+      //     continue
+      //   }
+      // }
       for (const { volume: volumeIdx, fragment, label } of map.indices[regionname]) {
         const { providedVolumes } = map.volumes[volumeIdx]
         if (!("neuroglancer/precomputed" in providedVolumes)) {
diff --git a/src/atlasComponents/sapi/schemaV3.ts b/src/atlasComponents/sapi/schemaV3.ts
index de27935f67b5a381ef1d04069f41fad1733a6b6e..e73a25736e182902ac13528a75848ee3a6f44e3c 100644
--- a/src/atlasComponents/sapi/schemaV3.ts
+++ b/src/atlasComponents/sapi/schemaV3.ts
@@ -81,6 +81,10 @@ export interface paths {
     /** Get Task Id */
     get: operations["get_task_id_atlas_download__task_id__get"]
   }
+  "/atlas_download/{task_id}/download": {
+    /** Get Task Id */
+    get: operations["get_task_id_atlas_download__task_id__download_get"]
+  }
   "/feature/_types": {
     /** Get All Feature Types */
     get: operations["get_all_feature_types_feature__types_get"]
@@ -441,12 +445,6 @@ export interface components {
        */
       versionIdentifier: string
     }
-    /**
-     * ConnectivityTypes 
-     * @description An enumeration. 
-     * @enum {unknown}
-     */
-    ConnectivityTypes: "FunctionalConnectivity" | "StreamlineCounts" | "StreamlineLengths"
     /** CoordinatePointModel */
     CoordinatePointModel: {
       /** @Type */
@@ -494,20 +492,14 @@ export interface components {
        */
       year: string
     }
-    /**
-     * CorticalProfileTypes 
-     * @description An enumeration. 
-     * @enum {unknown}
-     */
-    CorticalProfileTypes: "ReceptorDensityProfile" | "CellDensityProfile" | "BigBrainIntensityProfile"
     /** DataFrameModel */
     DataFrameModel: {
       /** @Type */
       "@type": string
       /** Index */
-      index: unknown[]
+      index: any[]
       /** Columns */
-      columns: unknown[]
+      columns: any[]
       /** Ndim */
       ndim: number
       /** Data */
@@ -1749,6 +1741,28 @@ export interface operations {
       }
     }
   }
+  get_task_id_atlas_download__task_id__download_get: {
+    /** Get Task Id */
+    parameters: {
+      path: {
+        task_id: string
+      }
+    }
+    responses: {
+      /** @description Successful Response */
+      200: {
+        content: {
+          "application/json": Record<string, never>
+        }
+      }
+      /** @description Validation Error */
+      422: {
+        content: {
+          "application/json": components["schemas"]["HTTPValidationError"]
+        }
+      }
+    }
+  }
   get_all_feature_types_feature__types_get: {
     /** Get All Feature Types */
     parameters?: {
@@ -1777,7 +1791,7 @@ export interface operations {
     parameters: {
       query: {
         parcellation_id: string
-        type?: components["schemas"]["ConnectivityTypes"]
+        type?: string
         page?: number
         size?: number
       }
@@ -1808,7 +1822,7 @@ export interface operations {
       query: {
         parcellation_id: string
         subject?: string
-        type?: components["schemas"]["ConnectivityTypes"]
+        type?: string
       }
       path: {
         feature_id: string
@@ -1835,7 +1849,7 @@ export interface operations {
       query: {
         parcellation_id: string
         region_id: string
-        type?: components["schemas"]["CorticalProfileTypes"]
+        type?: string
         page?: number
         size?: number
       }
@@ -1861,7 +1875,7 @@ export interface operations {
       query: {
         parcellation_id: string
         region_id: string
-        type?: components["schemas"]["CorticalProfileTypes"]
+        type?: string
       }
       path: {
         feature_id: string
diff --git a/src/atlasComponents/sapi/translateV3.ts b/src/atlasComponents/sapi/translateV3.ts
index 79775ba84f4ca64aa8a03169373ed1049a487c92..e92c14d9fe61a46e14b7bb4be99a1541c8e39ec8 100644
--- a/src/atlasComponents/sapi/translateV3.ts
+++ b/src/atlasComponents/sapi/translateV3.ts
@@ -287,17 +287,7 @@ class TranslateV3 {
       segLayerSpec.layer.labelIndicies.push(label)
       segLayerSpec.region.push(region)
     }
-    const { ['@id']: mapId } = map
     for (const regionname in map.indices) {
-      /**
-       * temporary fix
-       * see https://github.com/FZJ-INM1-BDA/siibra-python/issues/317
-       */
-      if (mapId === "siibra-map-v0.0.1_bigbrain-cortical-labelled") {
-        if (regionname.includes("left") || regionname.includes("right")) {
-          continue
-        }
-      }
       for (const index of map.indices[regionname]) {
         const { volume:volumeIdx=0, fragment, label } = index
         if (!label) {
diff --git a/src/atlasComponents/sapiViews/core/space/boundingBox.directive.ts b/src/atlasComponents/sapiViews/core/space/boundingBox.directive.ts
index 72d0e2e66fc7ff0b8da0d520a6ec4438432a88df..ed1aa7731dfeda9b771a64cdadfc82236bf9eec1 100644
--- a/src/atlasComponents/sapiViews/core/space/boundingBox.directive.ts
+++ b/src/atlasComponents/sapiViews/core/space/boundingBox.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, Input, OnChanges } from "@angular/core";
+import { Directive, Input, OnChanges, Output } from "@angular/core";
 import { BehaviorSubject, Observable } from "rxjs";
 import { distinctUntilChanged } from "rxjs/operators";
 import { BoundingBox, SxplrTemplate, SxplrAtlas } from "src/atlasComponents/sapi/sxplrTypes"
@@ -60,6 +60,7 @@ export class SapiViewsCoreSpaceBoundingBox implements OnChanges{
     bbox: null
   })
 
+  @Output('sxplr-sapiviews-core-space-boundingbox-changed')
   public bbox$: Observable<{
     atlas: SxplrAtlas
     space: SxplrTemplate
diff --git a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html
index 8fc0aa7b4411e39a46e1d30f200f45907eb8d1ee..57a9cf3d5031587bc37f7ac36e115319b396f500 100644
--- a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html
+++ b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.html
@@ -1,7 +1,7 @@
 <div class="sxplr-m-2" *ngIf="busy$ | async">
     <spinner-cmp class="sxplr-d-inline-block"></spinner-cmp>
     <span>
-        Loading assignment ...
+        Performing probabilistic assignment ...
     </span>
 </div>
 
@@ -13,9 +13,14 @@
     </button>
 
     <!-- simple table -->
-    <table mat-table [dataSource]="df | dfToDs" class="sxplr-w-100">
+    <table mat-table [dataSource]="df | dfToDs : simpleTblSort"
+        matSort
+        class="sxplr-w-100"
+        #simpleTblSort="matSort"
+        matSortActive="map value"
+        matSortDirection="desc">
         <ng-container matColumnDef="region">
-            <th mat-header-cell *matHeaderCellDef>
+            <th mat-header-cell *matHeaderCellDef mat-sort-header>
                 region
             </th>
             <td mat-cell *matCellDef="let element">
@@ -25,12 +30,12 @@
                 </button>
             </td>
         </ng-container>
-        <ng-container matColumnDef="intersection over union">
-            <th mat-header-cell *matHeaderCellDef>
-                intersection over union
+        <ng-container matColumnDef="map value">
+            <th mat-header-cell *matHeaderCellDef mat-sort-header>
+                map value
             </th>
             <td mat-cell *matCellDef="let element">
-                {{ element['intersection over union'] | prettyPresent }}
+                {{ element['map value'] | prettyPresent }}
             </td>
         </ng-container>
         
@@ -42,10 +47,14 @@
 <ng-template #datatableTmpl>
     <h2 mat-dialog-title>Assignment</h2>
     <mat-dialog-content>
-        <table mat-table [dataSource]="df$ | async | dfToDs">
+        <table mat-table [dataSource]="df$ | async | dfToDs : comphTableSort"
+            matSort
+            #comphTableSort="matSort"
+            matSortActive="map value"
+            matSortDirection="desc">
             <ng-container *ngFor="let column of columns$ | async"
                 [matColumnDef]="column">
-                <th mat-header-cell *matHeaderCellDef>
+                <th mat-header-cell *matHeaderCellDef mat-sort-header>
                     {{ column }}
                 </th>
                 <td mat-cell *matCellDef="let element">
@@ -58,6 +67,14 @@
         </table>
     </mat-dialog-content>
     <mat-dialog-actions align="center">
+        <button mat-raised-button color="primary"
+            [zip-files-output]="zipfileConfig$ | async"
+            zip-files-output-zip-filename="pointassignment.zip">
+            <i class="fas fa-download"></i>
+            <span>
+                Download CSV
+            </span>
+        </button>
         <button mat-button mat-dialog-close>Close</button>
-      </mat-dialog-actions>
+    </mat-dialog-actions>
 </ng-template>
diff --git a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts
index 2bf281e7816015f0607b4f77122373d7097705c5..90cf9b9ed7aaca875eec919e4a718e6a6ef66898 100644
--- a/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts
+++ b/src/atlasComponents/sapiViews/volumes/point-assignment/point-assignment.component.ts
@@ -1,12 +1,14 @@
-import { Component, Input, OnDestroy, Output, TemplateRef, EventEmitter } from '@angular/core';
+import { Component, Input, OnDestroy, Output, TemplateRef, EventEmitter, ViewChild, AfterViewInit } from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
-import { BehaviorSubject, EMPTY, Subscription, combineLatest, concat, of } from 'rxjs';
+import { BehaviorSubject, EMPTY, Observable, Subscription, combineLatest, concat, of } from 'rxjs';
 import { map, shareReplay, switchMap, tap } from 'rxjs/operators';
-import { SAPI } from 'src/atlasComponents/sapi/sapi.service';
+import { SAPI, EXPECTED_SIIBRA_API_VERSION } from 'src/atlasComponents/sapi/sapi.service';
 import { SxplrParcellation, SxplrRegion, SxplrTemplate } from 'src/atlasComponents/sapi/sxplrTypes';
 import { translateV3Entities } from 'src/atlasComponents/sapi/translateV3';
 import { PathReturn } from 'src/atlasComponents/sapi/typeV3';
 import { TSandsPoint } from 'src/util/types';
+import { TZipFileConfig } from "src/zipFilesOutput/type"
+import { environment } from "src/environments/environment"
 
 @Component({
   selector: 'sxplr-point-assignment',
@@ -17,7 +19,7 @@ export class PointAssignmentComponent implements OnDestroy {
 
   SIMPLE_COLUMNS = [
     "region",
-    "intersection over union",
+    "map value",
   ]
   
   #busy$ = new BehaviorSubject(false)
@@ -44,7 +46,7 @@ export class PointAssignmentComponent implements OnDestroy {
   @Output()
   clickOnRegion = new EventEmitter<{ target: SxplrRegion, event: MouseEvent }>()
 
-  df$ = combineLatest([
+  df$: Observable<PathReturn<"/map/assign">> = combineLatest([
     this.#point,
     this.#parcellation,
     this.#template,
@@ -66,15 +68,14 @@ export class PointAssignmentComponent implements OnDestroy {
             parcellation_id: parcellation.id,
             point: point.coordinates.map(v => `${v.value/1e6}mm`).join(','),
             space_id: template.id,
-            sigma_mm: 3.0
+            sigma_mm: 0
           }
         }).pipe(
           tap(() => this.#busy$.next(false)),
         )
-      ).pipe(
-        shareReplay(1),
       )
-    })
+    }),
+    shareReplay(1),
   )
 
   columns$ = this.df$.pipe(
@@ -95,4 +96,76 @@ export class PointAssignmentComponent implements OnDestroy {
     const sxplrReg = await translateV3Entities.translateRegion(region)
     this.clickOnRegion.emit({ target: sxplrReg, event })
   }
+
+  zipfileConfig$: Observable<TZipFileConfig[]> = combineLatest([
+    this.#point,
+    this.#parcellation,
+    this.#template,
+    this.df$
+  ]).pipe(
+    map(([ pt, parc, tmpl, df ]) => {
+      return [{
+        filename: 'README.md',
+        filecontent: generateReadMe(pt, parc, tmpl)
+      }, {
+        filename: 'pointassignment.csv',
+        filecontent: generateCsv(df)
+      }] as TZipFileConfig[]
+    })
+  )
+}
+
+function generateReadMe(pt: TSandsPoint, parc: SxplrParcellation, tmpl: SxplrTemplate){
+  return `# Point assignment exporter
+
+Exported by siibra-explorer verison \`${environment.VERSION}\` hash: \`${environment.GIT_HASH}\`.
+
+On: ${new Date().toString()}
+
+Data retrieved through siibra-api version \`${EXPECTED_SIIBRA_API_VERSION}\`
+
+Retrieval parameters:
+
+Point
+- coord: ${pt.coordinates.map(v => v.value/1e6).join(',')} mm
+
+Parcellation
+- name: ${parc.name || parc.shortName}
+- id: ${parc.id}
+
+Space
+- name: ${tmpl.name || tmpl.shortName}
+- id: ${tmpl.id}
+`
+}
+
+function escapeFactory(chars: string[] = []){
+  const search = new RegExp(`[${chars.join('').replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}]`, 'g')
+  return function escape(s: string) {
+    return s.replace(search, s => `\\${s}`)
+  }
+}
+
+const escapeDoubleQuotes = escapeFactory(['"'])
+
+function processRow(v: unknown[]): string{
+  const returnValue: string[] = []
+  for (const item of v) {
+
+    // region
+    if (typeof item === "object" && item?.['@type'] === "siibra-0.4/region") {
+      returnValue.push(item['name'])
+      continue
+    }
+
+    returnValue.push(JSON.stringify(item))
+  }
+  return returnValue.map(escapeDoubleQuotes).map(v => `"${v}"`).join(",")
+}
+
+function generateCsv(df: PathReturn<"/map/assign">) {
+  return [
+    df.columns.map(escapeDoubleQuotes).map(v => `"${v}"`).join(","),
+    ...df.data.map(processRow)
+  ].join("\n")
 }
diff --git a/src/atlasComponents/sapiViews/volumes/volumes.module.ts b/src/atlasComponents/sapiViews/volumes/volumes.module.ts
index eee2503b61afec1b5533c4d265ce178669ee492c..1a5a32d0f5cf07a536f3e559c29ad835ca1abb6f 100644
--- a/src/atlasComponents/sapiViews/volumes/volumes.module.ts
+++ b/src/atlasComponents/sapiViews/volumes/volumes.module.ts
@@ -6,6 +6,8 @@ import { UtilModule } from 'src/util';
 import { SpinnerModule } from 'src/components/spinner';
 import { MatDialogModule } from '@angular/material/dialog';
 import { MatButtonModule } from '@angular/material/button';
+import { MatSortModule } from '@angular/material/sort';
+import { ZipFilesOutputModule } from 'src/zipFilesOutput/module';
 
 
 
@@ -20,6 +22,8 @@ import { MatButtonModule } from '@angular/material/button';
     SpinnerModule,
     MatDialogModule,
     MatButtonModule,
+    MatSortModule,
+    ZipFilesOutputModule,
   ],
   exports: [
     PointAssignmentComponent
diff --git a/src/features/category-acc.directive.ts b/src/features/category-acc.directive.ts
index cddba9e69912494aa8a156eb802fe2b25f76ad1e..73156e7af17e6cf4e39e97fca101655eb02b07bb 100644
--- a/src/features/category-acc.directive.ts
+++ b/src/features/category-acc.directive.ts
@@ -118,7 +118,8 @@ export class CategoryAccDirective implements AfterContentInit, OnDestroy {
           return this.datasource
         }),
       )
-    })
+    }),
+    shareReplay(1),
   )
 
   constructor(){
diff --git a/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts b/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts
index dbc546a7ead3d44685043b5654767b8499debe28..f4a2c8e6231db8386047195264206516136d8577 100644
--- a/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts
+++ b/src/features/connectivity/connectivityBrowser/connectivityBrowser.component.ts
@@ -156,13 +156,15 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
        * on
        * - accordion update
        * - colormap change
-       * - fetching matrix
+       * - fetching matrix flag is true
        * remove custom layer
        */
       merge(
         this.#accordionExpanded$,
         this.colormap$,
-        this.#fetchingMatrix$,
+        this.#fetchingMatrix$.pipe(
+          filter(flag => !!flag)
+        ),
       ).subscribe(() => {
         this.removeCustomLayer()
       }),
@@ -207,6 +209,7 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
        * on pure connection update, update logchecked box
        */
       this.#pureConnections$.subscribe(v => {
+        if (!v) return
         for (const val of Object.values(v)) {
           if (val > 1) {
             this.displayForm.get("logChecked").enable()
@@ -256,30 +259,32 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
         }
 
         const typedName = getType(selectedType.name)
-        if (!guardType(typedName)) {
-          throw new Error(`type ${typedName} is not in ${validTypes.join(',')}`)
-        }
         const query = {
           parcellation_id: parc.id,
           type: typedName
         }
         this.busy$.next(true)
-        return this.sapi.v3Get(
-          "/feature/RegionalConnectivity",
-          { query }
-        ).pipe(
-          switchMap(resp =>
-            this.sapi.iteratePages(
-              resp,
-              page => this.sapi.v3Get(
-                "/feature/RegionalConnectivity",
-                { query: { ...query, page } }
-              )
-            )
+        return concat(
+          of(
+            [] as PathReturn<"/feature/RegionalConnectivity/{feature_id}">[],
           ),
-          finalize(() => {
-            this.busy$.next(false)
-          })
+          this.sapi.v3Get(
+            "/feature/RegionalConnectivity",
+            { query }
+          ).pipe(
+            switchMap(resp =>
+              this.sapi.iteratePages(
+                resp,
+                page => this.sapi.v3Get(
+                  "/feature/RegionalConnectivity",
+                  { query: { ...query, page } }
+                )
+              )
+            ),
+            finalize(() => {
+              this.busy$.next(false)
+            })
+          )
         )
       })
     )),
@@ -328,7 +333,7 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
   displaySubject$ = this.selectedDataset$.pipe(
     distinctUntilChanged((o, n) => o?.id === n?.id),
     map(ds => {
-      return (idx: number) => ds.subjects[idx]
+      return (idx: number) => ds?.subjects?.[idx]
     })  
   )
 
@@ -336,7 +341,7 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
     map(ds => ds ? ds.datasets : [])
   )
 
-  #fetchingMatrix$ = new BehaviorSubject<boolean>(true)
+  #fetchingMatrix$ = new BehaviorSubject<boolean>(false)
 
   #matrixInput$ = combineLatest([
     this.parcellation$,
@@ -346,7 +351,8 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
     map(([ parcellation, form, dss ]) => {
       const {
         selectedDatasetIndex: dsIdx,
-        selectedSubjectIndex: subIdx
+        selectedSubjectIndex: subIdx,
+        selectedView
       } = form
       const ds = dss[dsIdx]
       if (!ds) {
@@ -360,7 +366,8 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
       return {
         parcellation,
         feature_id: ds.id,
-        subject
+        subject,
+        selectedView
       }
     }),
     shareReplay(1),
@@ -379,26 +386,33 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
         {
           query: {
             parcellation_id: parcellation.id,
-            subject,
+            ...(input.selectedView === "average"
+            ? {}
+            : { subject })
           },
           path: {
             feature_id
           }
         }
+      ).pipe(
+        finalize(() => {
+          this.#fetchingMatrix$.next(false)
+        })
       )
     }),
-    tap(() => this.#fetchingMatrix$.next(false)),
     shareReplay(1),
   )
 
   #pureConnections$ = this.#matrixInput$.pipe(
-    filter(v => !!v),
-    switchMap(({ subject }) =>
+    switchMap(matrixInput =>
       this.#selectedMatrix$.pipe(
-        filter(v => !!v.matrices[subject]),
         withLatestFrom(this.region$),
         map(([ v, region ]) => {
-          const b = v.matrices[subject]
+          const matrixKey = matrixInput?.selectedView === "average" ? "_average" : matrixInput?.subject
+          if (!v || !matrixInput || !v.matrices?.[matrixKey]) {
+            return null
+          }
+          const b = v.matrices[matrixKey]
           const foundIdx = b.columns.findIndex(v => v['name'] === region.name)
           if (typeof foundIdx !== 'number') {
             return null
@@ -429,6 +443,7 @@ export class ConnectivityBrowserComponent implements OnChanges, OnDestroy {
           distinctUntilChanged()
         )
       ]).pipe(
+        filter(conn => !!conn),
         map(([ conn, flag ]) => processProfile(conn, flag))
       )
     ))
@@ -545,12 +560,6 @@ function getType(name: string) {
   return name.split(".").slice(-1)[0]
 }
 
-const validTypes = ["FunctionalConnectivity", "StreamlineCounts", "StreamlineLengths"]
-
-function guardType(name: unknown): name is "FunctionalConnectivity" | "StreamlineCounts" | "StreamlineLengths" {
-  return typeof name === "string" && validTypes.includes(name)
-}
-
 type ConnectedArea = {
     color: {r: number, g: number, b: number}
     name: string
diff --git a/src/features/connectivity/connectivityBrowser/connectivityBrowser.template.html b/src/features/connectivity/connectivityBrowser/connectivityBrowser.template.html
index a7061fe7a83fedfb63c776e39deb613d1c5008dd..416763f02dab74f3dd141ab7d954d7155739a5b7 100644
--- a/src/features/connectivity/connectivityBrowser/connectivityBrowser.template.html
+++ b/src/features/connectivity/connectivityBrowser/connectivityBrowser.template.html
@@ -16,29 +16,37 @@
                     </mat-select>
                 </mat-form-field>
 
-                <mat-form-field *ngIf="!(busy$ | async) && (formValue$ | async | getProperty : 'selectedType')" class="flex-grow-1 flex-shrink-1 w-100">
-                    <mat-label>
-                        Cohort
-                    </mat-label>
-                    <mat-select formControlName="selectedCohort">
-                        <mat-option *ngFor="let cohort of cohorts$ | async"
-                            [value]="cohort">
-                            {{ cohort }}
-                        </mat-option>
-                    </mat-select>
-                </mat-form-field>
-            </div>
-        </ng-template>
+                <ng-template [ngIf]="cohorts$ | async" let-cohorts>
+                    <ng-template [ngIf]="cohorts.length > 0">
 
-        <ng-template [ngIf]="formValue$ | async | getProperty : 'selectedCohort'">
-            <mat-radio-group formControlName="selectedView">
-                <mat-radio-button value="average" class="m-2" color="primary">
-                    Average
-                </mat-radio-button>
-                <mat-radio-button value="subject" class="m-2" color="primary">
-                    Subject
-                </mat-radio-button>
-            </mat-radio-group>
+                        <mat-form-field class="flex-grow-1 flex-shrink-1 w-100">
+                            <mat-label>
+                                Cohort
+                            </mat-label>
+                            <mat-select formControlName="selectedCohort">
+                                <mat-option *ngFor="let cohort of cohorts$ | async"
+                                    [value]="cohort">
+                                    {{ cohort }}
+                                </mat-option>
+                            </mat-select>
+                        </mat-form-field>
+
+                        
+                        <ng-template [ngIf]="formValue$ | async | getProperty : 'selectedCohort'">
+                            <mat-radio-group formControlName="selectedView">
+                                <mat-radio-button value="average" class="m-2" color="primary">
+                                    Average
+                                </mat-radio-button>
+                                <mat-radio-button value="subject" class="m-2" color="primary">
+                                    Subject
+                                </mat-radio-button>
+                            </mat-radio-group>
+                        </ng-template>
+                
+                    </ng-template>
+                </ng-template>
+
+            </div>
         </ng-template>
 
         <ng-template [ngIf]="cohortDatasets$ | async" let-cohortDatasets>
@@ -84,7 +92,7 @@
         <!-- loading spinner -->
         <ng-template [ngIf]="view$ | async | getProperty : 'fetchingMatrix'"
             [ngIfElse]="profileTmpl">
-            <div class="d-flex justify-content-center" id = 'blabla'>
+            <div class="d-flex justify-content-center">
                 <mat-spinner></mat-spinner>
             </div>
         </ng-template>
@@ -92,7 +100,13 @@
         <!-- profile -->
         <!-- <pre>{{ view$ | async | json }}</pre> -->
         <ng-template #profileTmpl>
-            <ng-template [ngIf]="view$ | async | getProperty : 'connections'" let-conn>
+            
+            <ng-template #noConnTmpl>
+                No connectivity Found
+            </ng-template>
+        
+            <ng-template [ngIf]="view$ | async | getProperty : 'connections'" let-conn
+                [ngIfElse]="noConnTmpl">
                 <div class="d-flex align-items-center">
                     <form [formGroup]="displayForm">
                         <mat-checkbox
diff --git a/src/features/entry/entry.component.ts b/src/features/entry/entry.component.ts
index 979fea404ef798b8f0bfc510477bf423782938b0..722fd8e99735fb88a04ab0435c6a0bccaa760306 100644
--- a/src/features/entry/entry.component.ts
+++ b/src/features/entry/entry.component.ts
@@ -1,13 +1,13 @@
 import { AfterViewInit, Component, OnDestroy, QueryList, ViewChildren } from '@angular/core';
 import { select, Store } from '@ngrx/store';
-import { distinctUntilChanged, map, scan, shareReplay, switchMap, tap } from 'rxjs/operators';
+import { debounceTime, distinctUntilChanged, map, scan, shareReplay, switchMap, withLatestFrom } from 'rxjs/operators';
 import { IDS, SAPI } from 'src/atlasComponents/sapi';
 import { Feature } from 'src/atlasComponents/sapi/sxplrTypes';
 import { FeatureBase } from '../base';
 import * as userInteraction from "src/state/userInteraction"
 import { atlasSelection } from 'src/state';
 import { CategoryAccDirective } from "../category-acc.directive"
-import { BehaviorSubject, combineLatest, concat, merge, of, Subscription } from 'rxjs';
+import { combineLatest, concat, forkJoin, merge, of, Subject, Subscription } from 'rxjs';
 import { DsExhausted, IsAlreadyPulling, PulledDataSource } from 'src/util/pullable';
 import { TranslatedFeature } from '../list/list.directive';
 
@@ -33,56 +33,63 @@ const categoryAcc = <T extends Record<string, unknown>>(categories: T[]) => {
 })
 export class EntryComponent extends FeatureBase implements AfterViewInit, OnDestroy {
 
-  private _features$ = new BehaviorSubject<TranslatedFeature[]>([])
-  features$ = this._features$.pipe(
-    shareReplay(1)
-  )
-
   @ViewChildren(CategoryAccDirective)
   catAccDirs: QueryList<CategoryAccDirective>
 
-  public busyTallying$ = new BehaviorSubject<boolean>(false)
-  public totals$ = new BehaviorSubject<number>(null)
-
   constructor(private sapi: SAPI, private store: Store) {
     super()
   }
 
   #subscriptions: Subscription[] = []
+  #catAccDirs = new Subject<CategoryAccDirective[]>()
+  features$ = this.#catAccDirs.pipe(
+    switchMap(dirs => concat(
+      of([] as TranslatedFeature[]),
+      merge(...dirs.map((dir, idx) =>
+        dir.datasource$.pipe(
+          switchMap(ds =>  ds.data$),
+          map(val => ({ val, idx }))
+        ))
+      ).pipe(
+        map(({ idx, val }) => ({ [idx.toString()]: val })),
+        scan((acc, curr) => ({ ...acc, ...curr })),
+        map(record => Object.values(record).flatMap(v => v))
+      )
+    )),
+    shareReplay(1),
+  )
 
-  private _busy$ = new BehaviorSubject<boolean>(false)
-  busy$ = this._busy$.pipe(
+  busy$ = this.#catAccDirs.pipe(
+    switchMap(dirs => combineLatest(
+      dirs.map(dir => dir.isBusy$)
+    )),
+    map(flags => flags.some(flag => flag)),
+    distinctUntilChanged(),
     shareReplay(1)
   )
 
-  ngOnDestroy(): void {
-    while (this.#subscriptions.length > 0) this.#subscriptions.pop().unsubscribe()
-  }
-  ngAfterViewInit(): void {
-    const catAccDirs$ = merge(
-      of(null),
-      this.catAccDirs.changes
-    ).pipe(
-      map(() => Array.from(this.catAccDirs))
-    )
-    this.#subscriptions.push(
-      catAccDirs$.pipe(
-        switchMap(dirs => combineLatest(
-          dirs.map(dir => dir.isBusy$)
-        )),
-        map(flags => flags.some(flag => flag)),
-        distinctUntilChanged(),
-      ).subscribe(value => {
-        this._busy$.next(value)
-      }),
-      catAccDirs$.pipe(
-        tap(() => this.busyTallying$.next(true)),
-        switchMap(catArrDirs => merge(
-          ...catArrDirs.map((dir, idx) => dir.total$.pipe(
-            map(val => ({ idx, val }))
-          ))
-        )),
-        
+  public busyTallying$ = this.#catAccDirs.pipe(
+    switchMap(arr => concat(
+      of(true),
+      forkJoin(
+        arr.map(dir => dir.total$)
+      ).pipe(
+        map(() => false)
+      )
+    )),
+    shareReplay(1)
+  )
+
+  public totals$ = this.#catAccDirs.pipe(
+    switchMap(arr => concat(
+      of(0),
+      merge(
+        ...arr.map((dir, idx) =>
+          dir.total$.pipe(
+            map(val => ({ val, idx }))
+          )
+        )
+      ).pipe(
         map(({ idx, val }) => ({ [idx.toString()]: val })),
         scan((acc, curr) => ({ ...acc, ...curr })),
         map(record => {
@@ -92,11 +99,47 @@ export class EntryComponent extends FeatureBase implements AfterViewInit, OnDest
           }
           return tally
         }),
-        tap(num => {
-          this.busyTallying$.next(false)
-          this.totals$.next(num)
-        }),
-      ).subscribe(),
+      )
+    ))
+  )
+
+  ngOnDestroy(): void {
+    while (this.#subscriptions.length > 0) this.#subscriptions.pop().unsubscribe()
+  }
+  ngAfterViewInit(): void {
+    this.#subscriptions.push(
+      merge(
+        of(null),
+        this.catAccDirs.changes
+      ).pipe(
+        map(() => Array.from(this.catAccDirs))
+      ).subscribe(dirs => this.#catAccDirs.next(dirs)),
+
+      this.#pullAll.pipe(
+        debounceTime(320),
+        withLatestFrom(this.#catAccDirs),
+        switchMap(([_, dirs]) => combineLatest(dirs.map(dir => dir.datasource$))),
+      ).subscribe(async dss => {
+        await Promise.all(
+          dss.map(async ds => {
+            // eslint-disable-next-line no-constant-condition
+            while (true) {
+              try {
+                await ds.pull()
+              } catch (e) {
+                if (e instanceof DsExhausted) {
+                  console.log('exhausted')
+                  break
+                }
+                if (e instanceof IsAlreadyPulling ) {
+                  continue
+                }
+                throw e
+              }
+            }
+          })
+        )
+      })
     )
   }
 
@@ -167,28 +210,8 @@ export class EntryComponent extends FeatureBase implements AfterViewInit, OnDest
     }
   }
 
-  async pullAll(){
-    const dss = Array.from(this.catAccDirs).map(catAcc => catAcc.datasource)
-
-    this._features$.next([])
-    await Promise.all(
-      dss.map(async ds => {
-        // eslint-disable-next-line no-constant-condition
-        while (true) {
-          try {
-            await ds.pull()
-          } catch (e) {
-            if (e instanceof DsExhausted) {
-              break
-            }
-            if (e instanceof IsAlreadyPulling ) {
-              continue
-            }
-            throw e
-          }
-        }
-      })
-    )
-    this._features$.next(dss.flatMap(ds => ds.finalValue))
+  #pullAll = new Subject()
+  pullAll(){
+    this.#pullAll.next(null)
   }
 }
diff --git a/src/features/voi-bbox.directive.ts b/src/features/voi-bbox.directive.ts
index d6ed2e0aac4ca11816b5f214699ed9c07cc8a47d..f150225b9cf66f5ce2f68f26c7a936f1c30f6576 100644
--- a/src/features/voi-bbox.directive.ts
+++ b/src/features/voi-bbox.directive.ts
@@ -47,7 +47,7 @@ export class VoiBboxDirective implements OnDestroy {
   
   @Input()
   set features(feats: Feature[]){
-    this.#voiFeatures = feats.filter(isVoiData)
+    this.#voiFeatures = (feats || []).filter(isVoiData)
     this.#features$.next(this.#voiFeatures)
   }
   get features(): VoiFeature[]{
diff --git a/src/index.html b/src/index.html
index 0f009f4f2d5ab33219754015cfc136a5c8758899..c1cef937495c9ed9218e6ec90326307b07a8816e 100644
--- a/src/index.html
+++ b/src/index.html
@@ -14,7 +14,7 @@
   <script src="extra_js.js"></script>
   <script src="https://unpkg.com/kg-dataset-previewer@1.2.0/dist/kg-dataset-previewer/kg-dataset-previewer.js" defer></script>
   <script src="https://unpkg.com/three-surfer@0.0.13/dist/bundle.js" defer></script>
-  <script type="module" src="https://unpkg.com/ng-layer-tune@0.0.6/dist/ng-layer-tune/ng-layer-tune.esm.js"></script>
+  <script type="module" src="https://unpkg.com/ng-layer-tune@0.0.12/dist/ng-layer-tune/ng-layer-tune.esm.js"></script>
   <script type="module" src="https://unpkg.com/hbp-connectivity-component@0.6.6/dist/connectivity-component/connectivity-component.js" ></script>
   <script defer src="https://unpkg.com/mathjax@3.1.2/es5/tex-svg.js"></script>
   <script defer src="https://unpkg.com/d3@6.2.0/dist/d3.min.js"></script>
diff --git a/src/overwrite.scss b/src/overwrite.scss
index 9fd0bb0b88e2fc3039a03040dfa659a2ec341cf8..5b17076e66aca6d569e24b3e6f5d0b6ab4c65f32 100644
--- a/src/overwrite.scss
+++ b/src/overwrite.scss
@@ -289,3 +289,38 @@ a[mat-raised-button]
 {
   pointer-events: none!important;
 }
+
+// list like button
+$llb: "#{$nsp}-list-like-button";
+button.#{$llb}
+{
+  width: 100%;
+
+  > .mat-button-wrapper
+  {
+    display: flex;
+    
+    > .#{$llb}-icon
+    {
+      width: 2rem;
+      flex: 0 0 auto;
+      margin: auto;
+      font-size: 150%;
+    }
+
+    > .#{$llb}-body
+    {
+      flex: 1 1 0px;
+      display: flex;
+      flex-direction: column;
+      margin:1rem;
+  
+      .#{$llb}-body-line
+      {
+        flex: 0 0 0px;
+        text-align: start;
+        line-height: 1.5rem;
+      }
+    }
+  }
+}
diff --git a/src/state/atlasSelection/util.ts b/src/state/atlasSelection/util.ts
index a76fd1f9f2e8fc45335a5b3695c65bb68322dfef..525df7f1fdc00f7528bdfbbc210a547db3b738ac 100644
--- a/src/state/atlasSelection/util.ts
+++ b/src/state/atlasSelection/util.ts
@@ -1,8 +1,6 @@
 import { createSelector, select } from "@ngrx/store";
-import { forkJoin, of, pipe } from "rxjs";
-import { distinctUntilChanged, map, switchMap } from "rxjs/operators";
-import { SAPI } from "src/atlasComponents/sapi";
-import { translateV3Entities } from "src/atlasComponents/sapi/translateV3"
+import { pipe } from "rxjs";
+import { distinctUntilChanged, map } from "rxjs/operators";
 import { SxplrAtlas, SxplrParcellation, SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes";
 import { jsonEqual } from "src/util/json";
 import * as selectors from "./selectors"
diff --git a/src/state/index.ts b/src/state/index.ts
index 40e84c234c4bca8d7eb7fece2c2c999ab249629f..12adc4b974fb893cef495e9310a5b990966478d4 100644
--- a/src/state/index.ts
+++ b/src/state/index.ts
@@ -71,6 +71,7 @@ export function getStoreEffects() {
     plugins.Effects,
     atlasSelection.Effect,
     userInterface.Effects,
+    userInteraction.Effect,
   ]
 }
 
diff --git a/src/state/userInteraction/effects.ts b/src/state/userInteraction/effects.ts
index 5d4986ad5965117705e6d1aa869407fabdbd8a65..7fd81d8ae1252522deba3c4f589eda32d61513e7 100644
--- a/src/state/userInteraction/effects.ts
+++ b/src/state/userInteraction/effects.ts
@@ -1,17 +1,33 @@
 import { Injectable } from "@angular/core";
 import { Actions, createEffect, ofType } from "@ngrx/effects";
-import * as atlasSelectionActions from "../atlasSelection/actions"
 import * as userInterface from "../userInterface"
-import { mapTo } from "rxjs/operators";
+import * as atlasSelection from "../atlasSelection"
+import * as actions from "./actions"
+import { filter, map, mapTo, skip } from "rxjs/operators";
+import { Store } from "@ngrx/store";
 
 @Injectable()
 export class Effect {
   onStandAloneVolumesExistCloseMatDrawer = createEffect(() => this.action.pipe(
-    ofType(atlasSelectionActions.clearStandAloneVolumes),
+    ofType(atlasSelection.actions.clearStandAloneVolumes),
     mapTo(userInterface.actions.closeSidePanel())
   ))
 
-  constructor(private action: Actions){
+  #distinctATP$ = this.store.pipe(
+    atlasSelection.fromRootStore.distinctATP(),
+  )
+
+  onATPUpdateUnselectFeature = createEffect(() => this.#distinctATP$.pipe(
+    filter(v => !!v.atlas && !!v.parcellation && !!v.template),
+    /**
+     * First non empty emit would be from selecting atlas.
+     * So ignore it.
+     */
+    skip(1),
+    map(() => actions.clearShownFeature())
+  ))
+
+  constructor(private action: Actions, private store: Store){
 
   }
-}
\ No newline at end of file
+}
diff --git a/src/ui/topMenu/topMenuCmp/topMenu.components.ts b/src/ui/topMenu/topMenuCmp/topMenu.components.ts
index cf6922a353a041bd18b136ac7c1876dbc6e74c05..688da21160db6fef1fd93c1e95e17423cb627cbf 100644
--- a/src/ui/topMenu/topMenuCmp/topMenu.components.ts
+++ b/src/ui/topMenu/topMenuCmp/topMenu.components.ts
@@ -3,7 +3,6 @@ import {
   Component,
   Input,
   TemplateRef,
-  ViewChild,
 } from "@angular/core";
 import { Observable } from "rxjs";
 import { map } from "rxjs/operators";
diff --git a/src/ui/topMenu/topMenuCmp/topMenu.template.html b/src/ui/topMenu/topMenuCmp/topMenu.template.html
index a33377a72f41a7126bd272754e3862651fd8b86a..c64c0dcee48ba00781195e882d4ffe17cd84e72d 100644
--- a/src/ui/topMenu/topMenuCmp/topMenu.template.html
+++ b/src/ui/topMenu/topMenuCmp/topMenu.template.html
@@ -22,7 +22,7 @@
 
     <!-- pinned dataset -->
     <div iav-fab-speed-dial-child>
-      <ng-container *ngTemplateOutlet="pinnedDatasetBtnTmpl">
+      <ng-container *ngTemplateOutlet="downloadAllTmpl">
       </ng-container>
     </div>
 
@@ -53,7 +53,7 @@
     </ng-container>
 
     <!-- pinned dataset -->
-    <ng-container *ngTemplateOutlet="pinnedDatasetBtnTmpl">
+    <ng-container *ngTemplateOutlet="downloadAllTmpl">
     </ng-container>
 
     <!-- help one pager -->
@@ -100,7 +100,7 @@
 </ng-template>
 
 <!-- pinned dataset btn -->
-<ng-template #pinnedDatasetBtnTmpl>
+<ng-template #downloadAllTmpl>
   <div class="btnWrapper"
     [matTooltip]="(atlasDlDct.busy$| async) ? busyTxt : idleTxt"
     quick-tour
diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts
index a657e32cc68916a0b63a485f226dbdd7a05e948e..1d9c79d562f70331b06637468450d964b6d733b4 100644
--- a/src/ui/ui.module.ts
+++ b/src/ui/ui.module.ts
@@ -10,7 +10,6 @@ import { DownloadDirective } from "../util/directives/download.directive";
 import { MobileOverlay } from "./nehubaContainer/mobileOverlay/mobileOverlay.component";
 import { HumanReadableFileSizePipe } from "src/util/pipes/humanReadableFileSize.pipe";
 import { ReorderPanelIndexPipe } from "./nehubaContainer/reorderPanelIndex.pipe";
-import { FixedMouseContextualContainerDirective } from "src/util/directives/FixedMouseContextualContainerDirective.directive";
 import { ShareModule } from "src/share";
 import { AuthModule } from "src/auth";
 import { ActionDialog } from "./actionDialog/actionDialog.component";
@@ -41,7 +40,6 @@ import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../screens
     ReorderPanelIndexPipe,
     /* directive */
     DownloadDirective,
-    FixedMouseContextualContainerDirective,
   ],
   providers: [
     {
@@ -104,7 +102,6 @@ import { HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "../screens
     // NehubaContainer,
     MobileOverlay,
     // StatusCardComponent,
-    FixedMouseContextualContainerDirective,
   ]
 })
 
diff --git a/src/util/df-to-ds.pipe.ts b/src/util/df-to-ds.pipe.ts
index 612b8b48220cb6463458d21bd63f5f5c2eb60e7b..f50be028d82a3522df9277be89ef75b59accd33d 100644
--- a/src/util/df-to-ds.pipe.ts
+++ b/src/util/df-to-ds.pipe.ts
@@ -1,5 +1,7 @@
 import { CdkTableDataSourceInput } from '@angular/cdk/table';
 import { Pipe, PipeTransform } from '@angular/core';
+import { MatSort } from '@angular/material/sort';
+import { MatTableDataSource } from '@angular/material/table';
 import { components } from "src/atlasComponents/sapi/schemaV3"
 type DF = components["schemas"]["DataFrameModel"]
 
@@ -19,11 +21,11 @@ function isDf(val: object): val is DF {
 })
 export class DfToDsPipe implements PipeTransform {
 
-  transform(df: object): CdkTableDataSourceInput<unknown> {
+  transform(df: object, sort: MatSort): CdkTableDataSourceInput<unknown> {
     if (!isDf(df)) {
       return null
     }
-    return df.data.map((arr, idx) => {
+    const v = df.data.map((arr, idx) => {
       const val = df.index[idx] as any
       const returnVal: Record<string, string|number|number[]> = {
         index: val,
@@ -37,6 +39,9 @@ export class DfToDsPipe implements PipeTransform {
       })
       return returnVal
     })
+    const ds = new MatTableDataSource(v)
+    ds.sort = sort
+    return ds
   }
 
 }
diff --git a/src/util/directives/FixedMouseContextualContainerDirective.directive.spec.ts b/src/util/directives/FixedMouseContextualContainerDirective.directive.spec.ts
deleted file mode 100644
index 0cf11aeb387d08a01a89f616e7095cc716fb63c5..0000000000000000000000000000000000000000
--- a/src/util/directives/FixedMouseContextualContainerDirective.directive.spec.ts
+++ /dev/null
@@ -1,131 +0,0 @@
-import { Component, ViewChild } from "@angular/core";
-import { TestBed } from "@angular/core/testing";
-import { FixedMouseContextualContainerDirective } from "./FixedMouseContextualContainerDirective.directive";
-import { By } from "@angular/platform-browser";
-
-@Component({
-  template: ''
-})
-
-class TestCmp{
-  @ViewChild(FixedMouseContextualContainerDirective) directive: FixedMouseContextualContainerDirective
-}
-
-describe('FixedMouseContextualContainerDirective', () => {
-  beforeEach(() => {
-    TestBed.configureTestingModule({
-      imports: [
-        
-      ],
-      declarations: [
-        TestCmp,
-        FixedMouseContextualContainerDirective
-      ]
-    })
-  })
-
-  it('> can instantiate directive properly', () => {
-    TestBed.overrideComponent(TestCmp, {
-      set: {
-        template: `
-        <div fixedMouseContextualContainerDirective>
-        </div>
-        `
-      }
-    }).compileComponents()
-
-    const fixture = TestBed.createComponent(TestCmp)
-    fixture.detectChanges()
-    const directive = fixture.debugElement.query( By.directive(FixedMouseContextualContainerDirective) )
-    expect(directive).toBeTruthy()
-
-    expect(fixture.componentInstance.directive).toBeTruthy()
-  })
-
-  describe('> hides if no content', () => {
-    it('> on #show, if content exists, isShown will be true', () => {
-
-      TestBed.overrideComponent(TestCmp, {
-        set: {
-          template: `
-          <div fixedMouseContextualContainerDirective>
-            <span>Hello World</span>
-          </div>
-          `
-        }
-      }).compileComponents()
-
-      const fixture = TestBed.createComponent(TestCmp)
-      fixture.detectChanges()
-
-      const cmp = fixture.componentInstance
-      cmp.directive.show()
-      fixture.detectChanges()
-      expect(cmp.directive.isShown).toBeTrue()
-    })
-
-    it('> on #show, if only comment exists, isShown will be false', () => {
-
-      TestBed.overrideComponent(TestCmp, {
-        set: {
-          template: `
-          <div fixedMouseContextualContainerDirective>
-            <!-- hello world -->
-          </div>
-          `
-        }
-      }).compileComponents()
-
-      const fixture = TestBed.createComponent(TestCmp)
-      fixture.detectChanges()
-
-      const cmp = fixture.componentInstance
-      cmp.directive.show()
-      fixture.detectChanges()
-      expect(cmp.directive.isShown).toBeFalse()
-    })
-
-    it('> on #show, if only text exists, isShown will be false', () => {
-
-      TestBed.overrideComponent(TestCmp, {
-        set: {
-          template: `
-          <div fixedMouseContextualContainerDirective>
-            hello world
-          </div>
-          `
-        }
-      }).compileComponents()
-
-      const fixture = TestBed.createComponent(TestCmp)
-      fixture.detectChanges()
-
-      const cmp = fixture.componentInstance
-      cmp.directive.show()
-      fixture.detectChanges()
-      expect(cmp.directive.isShown).toBeFalse()
-    })
-
-    it('> on #show, if nothing exists, isShown will be false', () => {
-
-      TestBed.overrideComponent(TestCmp, {
-        set: {
-          template: `
-          <div fixedMouseContextualContainerDirective>
-          </div>
-          `
-        }
-      }).compileComponents()
-
-      const fixture = TestBed.createComponent(TestCmp)
-      fixture.detectChanges()
-
-      const cmp = fixture.componentInstance
-      cmp.directive.show()
-      fixture.detectChanges()
-      expect(cmp.directive.isShown).toBeFalse()
-    })
-  })
-
-  // TODO complete tests for FixedMouseContextualContainerDirective
-})
\ No newline at end of file
diff --git a/src/util/directives/FixedMouseContextualContainerDirective.directive.ts b/src/util/directives/FixedMouseContextualContainerDirective.directive.ts
deleted file mode 100644
index d7fbf0905efa08166e8f864f45cf375a97950102..0000000000000000000000000000000000000000
--- a/src/util/directives/FixedMouseContextualContainerDirective.directive.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { Directive, ElementRef, EventEmitter, HostBinding, Input, Output, AfterContentChecked, ChangeDetectorRef, AfterViewInit } from "@angular/core";
-
-@Directive({
-  selector: '[fixedMouseContextualContainerDirective]',
-  exportAs: 'iavFixedMouseCtxContainer'
-})
-
-export class FixedMouseContextualContainerDirective implements AfterContentChecked {
-
-  private defaultPos: [number, number] = [-1e3, -1e3]
-  public isShown: boolean = false
-
-  @Input()
-  public mousePos: [number, number] = this.defaultPos
-
-  @Output()
-  public onShow: EventEmitter<null> = new EventEmitter()
-
-  @Output()
-  public onHide: EventEmitter<null> = new EventEmitter()
-
-  constructor(
-    public el: ElementRef,
-    private cdr: ChangeDetectorRef,
-  ) {
-  }
-
-  public recalculatePosition(){
-    const clientWidth = this.el.nativeElement.clientWidth
-    const clientHeight = this.el.nativeElement.clientHeight
-
-    const windowInnerWidth = window.innerWidth
-    const windowInnerHeight = window.innerHeight
-    if (windowInnerHeight - this.mousePos[1] < clientHeight) {
-      this.mousePos[1] = windowInnerHeight - clientHeight
-    }
-
-    if ((windowInnerWidth - this.mousePos[0]) < clientWidth) {
-      this.mousePos[0] = windowInnerWidth - clientWidth
-    }
-
-    this.transform = `translate(${this.mousePos.map(v => v.toString() + 'px').join(', ')})`
-  }
-
-  ngAfterContentChecked(){
-    if (this.el.nativeElement.childElementCount === 0) {
-      this.hide()
-    }
-    this.recalculatePosition()
-    this.cdr.markForCheck()
-  }
-
-  public show() {
-    this.styleDisplay = 'inline-block'
-    this.isShown = true
-    this.onShow.emit()
-  }
-
-  public hide() {
-    this.transform = `translate(${this.defaultPos.map(v => v.toString() + 'px').join(', ')})`
-    this.styleDisplay = 'none'
-    this.isShown = false
-    this.onHide.emit()
-  }
-
-  @HostBinding('style.display')
-  public styleDisplay = `none`
-
-  @HostBinding('style.transform')
-  public transform = `translate(${this.mousePos.map(v => v.toString() + 'px').join(', ')})`
-
-}
diff --git a/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts b/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts
index f68170be4a59e2610000d997b852084512529dc4..be87e8eeec2a8fad91596feadac14a1dde29da3f 100644
--- a/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts
+++ b/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts
@@ -46,13 +46,16 @@ export class NehubaLayerControlService implements OnDestroy{
     combineLatest([
       this.completeNgIdLabelRegionMap$,
       this.customLayers$,
+      this.selectedRegion$,
     ]).pipe(
-      map(([record, layers]) => {
+      map(([record, layers, selectedRegions]) => {
         const returnVal: IColorMap = {}
 
         const cmCustomLayers = layers.filter(l => l.clType === "customlayer/colormap") as atlasAppearance.const.ColorMapCustomLayer[]
         const cmBaseLayers = layers.filter(l => l.clType === "baselayer/colormap") as atlasAppearance.const.ColorMapCustomLayer[]
         
+        const usingCustomCM = cmCustomLayers.length > 0
+
         const useCm = (() => {
           /**
            * if custom layer exist, use the last custom layer
@@ -72,11 +75,20 @@ export class NehubaLayerControlService implements OnDestroy{
             get: (r: SxplrRegion) => r.color
           }
         })()
+
+        const selectedRegionNameSet = new Set(selectedRegions.map(v => v.name))
         
         for (const [ngId, labelRecord] of Object.entries(record)) {
           for (const [label, region] of Object.entries(labelRecord)) {
             if (!region.color) continue
-            const [ red, green, blue ] = useCm.get(region) || [200, 200, 200]
+            /**
+             * if custom color map is used, do *not* selectively paint selected region
+             * custom color map can choose to subscribe to selected regions, and update the color map accordingly, 
+             * if they wish to respect the selected regions
+             */
+            const [ red, green, blue ] = usingCustomCM || selectedRegionNameSet.size === 0 || selectedRegionNameSet.has(region.name)
+              ? useCm.get(region) || [200, 200, 200]
+              : [255, 255, 255]
             if (!returnVal[ngId]) {
               returnVal[ngId] = {}
             }
diff --git a/src/viewerModule/nehuba/mesh.service/mesh.service.spec.ts b/src/viewerModule/nehuba/mesh.service/mesh.service.spec.ts
index 051d366a882a44f75f782e10fe58ccd25314869e..7db5392a46b74554df8c9e2db2ab8d5e221ab44b 100644
--- a/src/viewerModule/nehuba/mesh.service/mesh.service.spec.ts
+++ b/src/viewerModule/nehuba/mesh.service/mesh.service.spec.ts
@@ -196,6 +196,8 @@ describe('> mesh.service.ts', () => {
           beforeEach(() => {
             const mockStore = TestBed.inject(MockStore)
             mockStore.overrideSelector(atlasSelection.selectors.selectedRegions, [])
+            mockStore.overrideSelector(atlasSelection.selectors.selectedTemplate, {} as any)
+            mockStore.overrideSelector(atlasSelection.selectors.selectedParcellation, {} as any)
           })
 
           it("> load all meshes", () => {
@@ -226,6 +228,8 @@ describe('> mesh.service.ts', () => {
           beforeEach(() => {
             const mockStore = TestBed.inject(MockStore)
             mockStore.overrideSelector(atlasSelection.selectors.selectedRegions, [fits1])
+            mockStore.overrideSelector(atlasSelection.selectors.selectedTemplate, {} as any)
+            mockStore.overrideSelector(atlasSelection.selectors.selectedParcellation, {} as any)
           })
           it("> load only selected mesh", () => {
 
diff --git a/src/viewerModule/nehuba/mesh.service/mesh.service.ts b/src/viewerModule/nehuba/mesh.service/mesh.service.ts
index 29a40e94c6882b6022033b2d55103627d3d9b8cf..d46e128f4a84d082272101b67a215bf75d5165c3 100644
--- a/src/viewerModule/nehuba/mesh.service/mesh.service.ts
+++ b/src/viewerModule/nehuba/mesh.service/mesh.service.ts
@@ -7,6 +7,7 @@ import { selectorAuxMeshes } from "../store";
 import { LayerCtrlEffects } from "../layerCtrl.service/layerCtrl.effects";
 import { atlasSelection } from "src/state";
 import { BaseService } from "../base.service/base.service";
+import { IDS } from "src/atlasComponents/sapi"
 
 /**
  * control mesh loading etc
@@ -126,8 +127,21 @@ export class NehubaMeshService implements OnDestroy {
     this.#allSegmentMeshes$,
     this.#selectedSegmentMeshes$,
     this.#auxMesh$,
+    this.store$.pipe(
+      select(atlasSelection.selectors.selectedTemplate)
+    ),
+    this.store$.pipe(
+      select(atlasSelection.selectors.selectedParcellation)
+    )
   ]).pipe(
-    switchMap(([ allSegMesh, selectedSegMesh, auxmesh ]) => {
+    switchMap(([ allSegMesh, selectedSegMesh, auxmesh, selectedTemplate, selectedParcellation ]) => {
+      /**
+       * TODO monkey patching jba29 in colin to show all meshes
+       * 
+       */
+      if (selectedParcellation.id === IDS.PARCELLATION.JBA29 && selectedTemplate.id === IDS.TEMPLATES.COLIN27) {
+        return of(...allSegMesh)
+      }
       const hasSegSelected = selectedSegMesh.some(v => v.labelIndicies.length !== 0)
       const hasAuxMesh = auxmesh.length > 0
       const meshesToLoad: IMeshesToLoad[] = []
diff --git a/src/viewerModule/nehuba/userLayers/service.ts b/src/viewerModule/nehuba/userLayers/service.ts
index 042cc54851be1e31cf457926d81768dfcbc2a5a8..3fe9d0a7db656354ed6217ebd13a0fd0354deae4 100644
--- a/src/viewerModule/nehuba/userLayers/service.ts
+++ b/src/viewerModule/nehuba/userLayers/service.ts
@@ -1,8 +1,8 @@
 import { Injectable, OnDestroy } from "@angular/core"
 import { MatDialog } from "@angular/material/dialog"
 import { select, Store } from "@ngrx/store"
-import { concat, of, Subscription } from "rxjs"
-import { pairwise } from "rxjs/operators"
+import { concat, from, of, Subscription } from "rxjs"
+import { catchError, map, pairwise, switchMap } from "rxjs/operators"
 import {
   linearTransform,
   TVALID_LINEAR_XFORM_DST,
@@ -198,29 +198,48 @@ export class UserLayerService implements OnDestroy {
   ) {
     this.#subscription.push(
       concat(
-        of(null),
-        this.routerSvc.customRoute$.pipe(select((v) => v[OVERLAY_LAYER_KEY]))
-      )
-        .pipe(pairwise())
-        .subscribe(([prev, curr]) => {
-          if (prev) {
-            this.removeUserLayer(prev)
+        of(null as string),
+        this.routerSvc.customRoute$.pipe(
+          select(v => v[OVERLAY_LAYER_KEY])
+        )
+      ).pipe(
+        pairwise(),
+        switchMap(([prev, curr]) => {
+          /**
+           * for precomputed sources, check if transform.json exists.
+           * if so, try to fetch it, and set it as transform
+           */
+          if (!curr) {
+            return of([prev, curr, null])
           }
-          if (curr) {
-            this.addUserLayer(
-              curr,
-              {
-                filename: curr,
-                message: `Overlay layer populated in URL`,
-              },
-              {
-                shader: getShader({
-                  colormap: EnumColorMapName.MAGMA,
-                }),
-              }
-            )
+          if (!curr.startsWith("precomputed://")) {
+            return of([prev, curr, null])
           }
+          return from(fetch(`${curr.replace('precomputed://', '')}/transform.json`).then(res => res.json())).pipe(
+            catchError(() => of([prev, curr, null])),
+            map(transform => [prev, curr, transform])
+          )
         })
+      ).subscribe(([prev, curr, transform]) => {
+        if (prev) {
+          this.removeUserLayer(prev)
+        }
+        if (curr) {
+          this.addUserLayer(
+            curr,
+            {
+              filename: curr,
+              message: `Overlay layer populated in URL`,
+            },
+            {
+              shader: getShader({
+                colormap: EnumColorMapName.MAGMA,
+              }),
+              transform
+            }
+          )
+        }
+      })
     )
   }
 
diff --git a/src/viewerModule/viewerCmp/viewerCmp.component.ts b/src/viewerModule/viewerCmp/viewerCmp.component.ts
index 136f0baf82166534a9e0d7480159e0dce58edc32..2dbd534dbd0a309ec23fcf1f6545a88bfe1b5a18 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.component.ts
+++ b/src/viewerModule/viewerCmp/viewerCmp.component.ts
@@ -14,6 +14,7 @@ import { atlasAppearance, atlasSelection, userInteraction } from "src/state";
 import { SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes";
 import { EntryComponent } from "src/features/entry/entry.component";
 import { TFace, TSandsPoint, getCoord } from "src/util/types";
+import { wait } from "src/util/fn";
 
 @Component({
   selector: 'iav-cmp-viewer-container',
@@ -438,4 +439,14 @@ export class ViewerCmp implements OnDestroy {
       })
     )
   }
+
+  @ViewChild('voiFeatureEntryCmp')
+  voiFeatureEntryCmp: EntryComponent
+
+  async pullAllVoi(){
+    if (this.voiFeatureEntryCmp){
+      await wait(320)
+      this.voiFeatureEntryCmp.pullAll()
+    }
+  }
 }
diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html
index 0c80076b1593496a3f94cfb7892f312d192cad22..459fb19e841d22944af9cf5a8bca36512bcb6d0c 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.template.html
+++ b/src/viewerModule/viewerCmp/viewerCmp.template.html
@@ -905,62 +905,69 @@
 <ng-template #viewerStatusCtxMenu let-data>
   <ng-template [ngIf]="data.context" let-context>
 
-    <mat-list>
+    <!-- ref space & position -->
+    <ng-container [ngSwitch]="context.viewerType">
 
-      <!-- ref space & position -->
-      <ng-container [ngSwitch]="context.viewerType">
-  
-        <!-- volumetric i.e. nehuba -->
-        <ng-container *ngSwitchCase="'nehuba'">
-          <mat-list-item mat-ripple
-            (click)="selectPoint({ point: context.payload.mouse.real }, data.metadata.template)">
-            <div mat-list-icon>
-              <i class="fas fa-map"></i>
-            </div>
-            
-            <div mat-line>
+      <!-- volumetric i.e. nehuba -->
+      <ng-container *ngSwitchCase="'nehuba'">
+        <button mat-button class="sxplr-list-like-button"
+          (click)="selectPoint({ point: context.payload.mouse.real }, data.metadata.template)">
+
+          <div class="sxplr-list-like-button-icon">
+            <i class="fas fa-map"></i>
+          </div>
+    
+          <div class="sxplr-list-like-button-body">
+    
+            <span class="sxplr-list-like-button-body-line">
               {{ context.payload.mouse.real | nmToMm | numbers | addUnitAndJoin : '' }} (mm)
-            </div>
-            <div mat-line class="text-muted">
+            </span>
+            <span class="sxplr-list-like-button-body-line text-muted">
               Point
-            </div>
-            <div mat-line class="text-muted">
+            </span>
+            <span class="sxplr-list-like-button-body-line text-muted">
               {{ data.metadata.template.name }}
-            </div>
-          </mat-list-item>
-        </ng-container>
-  
-        <ng-container *ngSwitchCase="'threeSurfer'">
-
-          <ng-template [ngIf]="context.payload?.faceIndex" let-faceIndex>
-            <ng-template [ngIf]="context.payload?.vertexIndices" let-vertexIndices>
-              <mat-list-item mat-ripple
-                (click)="selectPoint({ face: faceIndex, vertices: vertexIndices }, data.metadata.template)">
-
-                <div mat-list-icon>
-                  <i class="fas fa-map"></i>
-                </div>
-                
-                <div mat-line>
+            </span>
+          </div>    
+
+        </button>
+      </ng-container>
+
+      <ng-container *ngSwitchCase="'threeSurfer'">
+
+        <ng-template [ngIf]="context.payload?.faceIndex" let-faceIndex>
+          <ng-template [ngIf]="context.payload?.vertexIndices" let-vertexIndices>
+            <button mat-button class="sxplr-list-like-button"
+            (click)="selectPoint({ face: faceIndex, vertices: vertexIndices }, data.metadata.template)">
+    
+              <div class="sxplr-list-like-button-icon">
+                <i class="fas fa-map"></i>
+              </div>
+        
+              <div class="sxplr-list-like-button-body">
+        
+                <span class="sxplr-list-like-button-body-line">
                   Face Index: {{ faceIndex }}, Vertices Index: {{ vertexIndices | addUnitAndJoin : '' }}
-                </div>
-                <div mat-line class="text-muted">
+                </span>
+                <span class="sxplr-list-like-button-body-line text-muted">
                   Mesh Face
-                </div>
-                <div mat-line class="text-muted">
+                </span>
+                <span class="sxplr-list-like-button-body-line text-muted">
                   {{ data.metadata.template.name }}
-                </div>
-              </mat-list-item>
-            </ng-template>
+                </span>
+              </div>    
+    
+            </button>
+
           </ng-template>
-          
-        </ng-container>
-  
-        <ng-container *ngSwitchDefault>
-          DEFAULT
-        </ng-container>
+        </ng-template>
+        
+      </ng-container>
+
+      <ng-container *ngSwitchDefault>
+        DEFAULT
       </ng-container>
-    </mat-list>
+    </ng-container>
   </ng-template>
 </ng-template>
 
@@ -968,41 +975,32 @@
 <!-- viewer state hover ctx menu -->
 <ng-template #viewerStatusRegionCtxMenu let-data>
   <!-- hovered ROIs -->
-  <mat-list>
-    <ng-template ngFor [ngForOf]="data.metadata.hoveredRegions"
-      let-region
-      let-first="first">
+  <ng-template ngFor [ngForOf]="data.metadata.hoveredRegions"
+    let-region
+    let-first="first">
 
-      <mat-divider class="top-0" *ngIf="!first"></mat-divider>
+    <mat-divider class="top-0" *ngIf="!first"></mat-divider>
 
-      <mat-list-item mat-ripple
-        class="cursor-default"
-        (click)="$event.ctrlKey ? toggleRoi(region) : selectRoi(region)">
+    <button mat-button
+      (click)="$event.ctrlKey ? toggleRoi(region) : selectRoi(region)"
+      class="sxplr-list-like-button">
+      
+      <div class="sxplr-list-like-button-icon">
+        <i class="fas fa-brain"></i>
+      </div>
 
-        <div mat-list-icon>
-          <i class="fas fa-brain"></i>
-        </div>
+      <div class="sxplr-list-like-button-body">
 
-        <span mat-line>
+        <span class="sxplr-list-like-button-body-line">
           {{ region.name }}
         </span>
-        <span mat-line class="text-muted">
-          <span>
-            Brain region
-          </span>
+        <span class="sxplr-list-like-button-body-line text-muted">
+          Brain region
         </span>
-      
-        <!-- lookup region -->
-        <!-- <button mat-icon-button
-          (click)="selectRoi(region)"
-          ctx-menu-dismiss>
-          <i class="fas fa-search"></i>
-        </button> -->
-      </mat-list-item>
-      
+      </div>    
+    </button>
 
-    </ng-template>
-  </mat-list>
+  </ng-template>
 </ng-template>
 
 <!-- feature tmpls -->
@@ -1126,6 +1124,7 @@
     class="sxplr-pe-all mat-elevation-z8"
     [template]="view.selectedTemplate"
     [bbox]="bbox.bbox$ | async | getProperty : 'bbox'"
+    [attr.data-feature-length]="((voiFeatureEntryCmp.features$ | async) || []).length"
     #voiFeatureEntryCmp="featureEntryCmp">
   </sxplr-feature-entry>
 
@@ -1143,7 +1142,7 @@
     iav-switch
     [iav-switch-state]="false"
     #voiSwitch="iavSwitch"
-    (iav-switch-event)="$event && voiFeatureEntryCmp.pullAll()"
+    (iav-switch-event)="$event && pullAllVoi()"
     (click)="voiSwitch.toggle()">
 
     <ng-template [ngIf]="voiSwitch.switchState$ | async" [ngIfElse]="chevronCollapseTmpl">
@@ -1175,6 +1174,7 @@
 
 <div
   sxplr-sapiviews-core-space-boundingbox
+  (sxplr-sapiviews-core-space-boundingbox-changed)="pullAllVoi()"
   [sxplr-sapiviews-core-space-boundingbox-atlas]="selectedAtlas$ | async"
   [sxplr-sapiviews-core-space-boundingbox-space]="templateSelected$ | async"
   [sxplr-sapiviews-core-space-boundingbox-spec]="viewerCtx$ | async | nehubaVCtxToBbox"