diff --git a/indra/newview/llfloaterforgetuser.cpp b/indra/newview/llfloaterforgetuser.cpp
index 97b022699f1abaf0131165d8f347359d6b0f3a27..f5dd324d14e7a0e2ffe544458c3d8315a9c13dbf 100644
--- a/indra/newview/llfloaterforgetuser.cpp
+++ b/indra/newview/llfloaterforgetuser.cpp
@@ -61,49 +61,9 @@ BOOL LLFloaterForgetUser::postBuild()
     mScrollList = getChild<LLScrollListCtrl>("user_list");
 
 
-    bool show_grid_marks = gSavedSettings.getBOOL("ForceShowGrid");
-    show_grid_marks |= !LLGridManager::getInstance()->isInProductionGrid();
-
     std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids();
 
-    if (!show_grid_marks)
-    {
-        // Figure out if there are records for more than one grid in storage
-        for (std::map<std::string, std::string>::iterator grid_iter = known_grids.begin();
-            grid_iter != known_grids.end();
-            grid_iter++)
-        {
-            if (!grid_iter->first.empty()
-                && grid_iter->first != MAINGRID) // a workaround since 'mIsInProductionGrid' might not be set
-            {
-                if (!gSecAPIHandler->emptyCredentialMap("login_list", grid_iter->first))
-                {
-                    show_grid_marks = true;
-                    break;
-                }
-
-                // "Legacy" viewer support
-                LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(grid_iter->first);
-                if (cred.notNull())
-                {
-                    const LLSD &ident = cred->getIdentifier();
-                    if (ident.isMap() && ident.has("type"))
-                    {
-                        show_grid_marks = true;
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
     mUserGridsCount.clear();
-    if (!show_grid_marks)
-    {
-        // just load maingrid
-        loadGridToList(MAINGRID, false);
-    }
-    else
     {
         for (std::map<std::string, std::string>::iterator grid_iter = known_grids.begin();
             grid_iter != known_grids.end();
@@ -256,7 +216,7 @@ void LLFloaterForgetUser::loadGridToList(const std::string &grid, bool show_grid
     std::string grid_label;
     if (show_grid_name)
     {
-        grid_label = LLGridManager::getInstance()->getGridId(grid); //login id (shortened label)
+        grid_label = LLGridManager::getInstance()->getGridLabel(grid); //login id (shortened label)
     }
     if (gSecAPIHandler->hasCredentialMap("login_list", grid))
     {
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 3720eb8104938d1239f0c61ae88fb7401f8828ce..ebf6fb817897e830902b76b4b6cce78b6ccc3d06 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -735,7 +735,7 @@ LLSD LLFloaterReporter::gatherReport()
 	mCopyrightWarningSeen = FALSE;
 
 	std::ostringstream summary;
-	if (!LLGridManager::getInstance()->isInProductionGrid())
+	if (LLGridManager::getInstance()->isInSLBeta())
 	{
 		summary << "Preview ";
 	}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index a6a597c49958be46831dab6a85db39a9e9301be7..aa3b7a4bc2e5a6426ebbd84ce472fa73e4a7855f 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1900,7 +1900,7 @@ std::string LLInventoryModel::getInvCacheAddres(const LLUUID& owner_id)
     std::string owner_id_str;
     owner_id.toString(owner_id_str);
     std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str));
-    if (LLGridManager::getInstance()->isInProductionGrid())
+    if (LLGridManager::getInstance()->isInSLMain())
     {
         inventory_addr = llformat(PRODUCTION_CACHE_FORMAT_STRING, path.c_str());
     }
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 294a712f78dc53b27990a9a66852f3c9747c9be0..3475552c8163af6ed8e4db4776c6112d8e6f2e81 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -56,7 +56,7 @@ namespace {
     {
         std::string domain = "secondlife.com";
 
-        if (!LLGridManager::getInstance()->isInProductionGrid())
+        if (LLGridManager::getInstance()->isInSLBeta())
         {
             const std::string& grid_id = LLGridManager::getInstance()->getGridId();
             const std::string& grid_id_lower = utf8str_tolower(grid_id);
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index f2fc41b5a131205e8d5c89193656aea0da13888b..1df093ee9b958be4b248c50aee76b00bbc7ac7ae 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -953,7 +953,7 @@ void LLPanelLogin::loadLoginPage()
 									 login_page.path(),
 									 params));
 
-	gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
+	gViewerWindow->setMenuBackgroundColor(false, LLGridManager::getInstance()->isInSLBeta());
 
 	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
 	if (web_browser->getCurrentNavUrl() != login_uri.asString())
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 8063e2431c8a6ac645b3a5f6a01574dc672916f9..bebdfc87e828cf5fa43c67192a7448da21f0cc61 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2684,7 +2684,7 @@ bool callback_choose_gender(const LLSD& notification, const LLSD& response)
 
 std::string get_screen_filename(const std::string& pattern)
 {
-    if (LLGridManager::getInstance()->isInProductionGrid())
+    if (LLGridManager::getInstance()->isInSLMain())
     {
         return llformat(pattern.c_str(), "");
     }
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 95c3753a9dc72b88c236f6be21cb331741596c73..9c4adb9885317ffd5f58dbb55ed431ad8183c04d 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -501,13 +501,13 @@ void init_menus()
 	gPopupMenuView->setBackgroundColor( color );
 
 	// If we are not in production, use a different color to make it apparent.
-	if (LLGridManager::getInstance()->isInProductionGrid())
+	if (LLGridManager::getInstance()->isInSLBeta())
 	{
-		color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
+		color = LLUIColorTable::instance().getColor("MenuNonProductionBgColor");
 	}
 	else
 	{
-		color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
+		color = LLUIColorTable::instance().getColor("MenuBarBgColor");
 	}
 
 	LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder");
@@ -519,7 +519,7 @@ void init_menus()
 	menu_bar_holder->addChild(gMenuBarView);
   
     gViewerWindow->setMenuBackgroundColor(false, 
-        LLGridManager::getInstance()->isInProductionGrid());
+        LLGridManager::getInstance()->isInSLBeta());
 
 	// *TODO:Also fix cost in llfolderview.cpp for Inventory menus
 	const std::string texture_upload_cost_str = fmt::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
@@ -3972,7 +3972,7 @@ void set_god_level(U8 god_level)
         if(gViewerWindow)
         {
             gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT,
-            LLGridManager::getInstance()->isInProductionGrid());
+            LLGridManager::getInstance()->isInSLBeta());
         }
     
         LLSD args;
@@ -4012,7 +4012,7 @@ BOOL check_toggle_hacked_godmode(void*)
 
 bool enable_toggle_hacked_godmode(void*)
 {
-  return !LLGridManager::getInstance()->isInProductionGrid();
+  return LLGridManager::getInstance()->isInSLBeta();
 }
 #endif
 
@@ -5087,7 +5087,7 @@ BOOL enable_take()
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid() 
+		if (LLGridManager::getInstance()->isInSLBeta()
             && gAgent.isGodlike())
 		{
 			return TRUE;
@@ -5805,7 +5805,7 @@ bool enable_object_delete()
 	TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-	(!LLGridManager::getInstance()->isInProductionGrid()
+	(LLGridManager::getInstance()->isInSLBeta()
      && gAgent.isGodlike()) ||
 # endif
 	LLSelectMgr::getInstanceFast()->canDoDelete();
@@ -8070,7 +8070,7 @@ bool enable_object_take_copy()
 		all_valid = true;
 #ifndef HACKED_GODLIKE_VIEWER
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (LLGridManager::getInstanceFast()->isInProductionGrid()
+		if (!LLGridManager::getInstanceFast()->isInSLBeta()
             || !gAgent.isGodlike())
 # endif
 		{
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index b6261f37d1d070db2f40482eeeac784df8ae1a6d..eaee06ab011c9795362d8c7c1db68b2e05626938 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -99,9 +99,10 @@ const std::string ALCHEMY_UPDATE_SERVICE = "https://app.alchemyviewer.org/update
 
 //
 const std::string GRIDS_USER_FILE = "grids_user.xml";
+
 LLGridManager::LLGridManager()
 :	mLoggedIn(false)
-,   mIsInProductionGrid(false)
+,	mPlatform(NOPLATFORM)
 {
 	// by default, we use the 'grids.xml' file in the user settings directory
 	// this file is an LLSD file containing multiple grid definitions.
@@ -959,34 +960,86 @@ LLSD LLGridManager::getGridInfo(const std::string& grid) const
 
 void LLGridManager::updateIsInProductionGrid()
 {
-	mIsInProductionGrid = false;
-
 	// *NOTE:Mani This used to compare GRID_INFO_AGNI to gGridChoice,
 	// but it seems that loginURI trumps that.
 	std::vector<std::string> uris;
 	getLoginURIs(uris);
 	if (uris.empty())
 	{
-		mIsInProductionGrid = true;
+		LL_DEBUGS("GridManager") << "uri is empty, Setting grid platform to NOTHING." << LL_ENDL;
+		mPlatform = NOPLATFORM;
+		return;
 	}
-	else
+
+	// Detect Second Life Agni. We want to match the exact uri here because we're dealing with a live economy
+	for (const std::string& uri : uris)
 	{
-		for ( std::vector<std::string>::iterator uri_it = uris.begin();
-			  ! mIsInProductionGrid && uri_it != uris.end();
-			  uri_it++
-			 )
+		if (MAIN_GRID_LOGIN_URI == uri)
 		{
-			if( MAIN_GRID_LOGIN_URI == *uri_it )
-			{
-				mIsInProductionGrid = true;
-			}
+			LL_DEBUGS("GridManager") << "Setting grid platform to SLMAIN" << LL_ENDL;
+			mPlatform = SLMAIN;
+			return;
+		}
+	}
+	
+	// Detect Second Life Aditi et al.
+	for (const std::string& uri : uris)
+	{
+		LLURI login_uri = LLURI(uri);
+		if (login_uri.authority().find("lindenlab.com") != std::string::npos) // Any old lab domain will do
+		{
+			LL_DEBUGS("GridManager") << "Setting grid platform to SLBETA" << LL_ENDL;
+			mPlatform = SLBETA;
+			return;
 		}
 	}
+	
+	if (getPlatformString() == "OpenSim")
+	{
+		LL_DEBUGS("GridManager") << "Setting grid platform to OPENSIM" << LL_ENDL;
+		mPlatform = OPENSIM;
+		return;
+	}
+	if (getPlatformString() == "Halcyon")
+	{
+		LL_DEBUGS("GridManager") << "Setting grid platform to HALCYON" << LL_ENDL;
+		mPlatform = HALCYON;
+		return;
+	}
+	
+	// Default to OpenSim
+	LL_DEBUGS("GridManager")<< "Defaulting to OPENSIM" << LL_ENDL;
+	mPlatform = OPENSIM;
+}
+
+bool LLGridManager::isInSecondlife() const
+{
+	return (isInSLMain() || isInSLBeta());
+}
+
+bool LLGridManager::isInOpenSim() const
+{
+	return (mPlatform == OPENSIM || mPlatform == HALCYON);
+}
+
+bool LLGridManager::isInOpenSimulator() const
+{
+	return mPlatform == OPENSIM;
+}
+
+bool LLGridManager::isInHalcyon() const
+{
+	return mPlatform == HALCYON;
+}
+
+bool LLGridManager::isInSLMain() const
+{
+	return mPlatform == SLMAIN;
 }
 
-bool LLGridManager::isInProductionGrid()
+bool LLGridManager::isInSLBeta() const
 {
-	return mIsInProductionGrid;
+	return mPlatform == SLBETA;
 }
 
 bool LLGridManager::isSystemGrid(const std::string& grid) const
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 00c6fdb38e8f0f215e7b0d43b00e639df531eaf5..85222e1e6baedb7ba5dd4d3010d1e3b689db8494 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -229,12 +229,25 @@ class LLGridManager final : public LLSingleton<LLGridManager>
 
 	/// Is the selected grid one of the hard-coded default grids (Agni or Aditi)
 	bool isSystemGrid() const { return isSystemGrid(mGrid); }
-
-	/// Is the selected grid a production grid?
-	bool isInProductionGrid();
-	/**
-	 * yes, that's not a very helpful description.
-	 * I don't really know why that is different from isSystemGrid()
+	
+	/// Is the selected grid Second Life?
+	bool isInSecondlife() const;
+	
+	/// Is the selected grid OpenSim or OpenSim-derived?
+	bool isInOpenSim() const;
+	
+	/// Is the selected grid OpenSimulator?
+	bool isInOpenSimulator() const;
+	
+	/// Is the selected grid Halcyon?
+	bool isInHalcyon() const;
+	
+	/// Is the selected grid agni?
+	bool isInSLMain() const;
+	
+	/// Is the selected grid aditi?
+	bool isInSLBeta() const;
+	
 	/* ===============================================================
 	 * @name User grid management functions
 	 * @{
@@ -285,7 +298,7 @@ class LLGridManager final : public LLSingleton<LLGridManager>
 	std::string mGrid;
 	std::string mGridFile;
 	LLSD mGridList;
-	bool mIsInProductionGrid;
+	EGridPlatform mPlatform;
 	
 	
 	/* ===============================================================
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 0f31a44cb2fd260090d5e1a5314865edd950780f..f5ee448a85ac3be69244c9b37162a7200d88963c 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -6276,7 +6276,7 @@ BOOL LLViewerObject::permYouOwner() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstanceFast()->isInProductionGrid()
+		if (LLGridManager::getInstanceFast()->isInSLBeta()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
@@ -6313,7 +6313,7 @@ BOOL LLViewerObject::permOwnerModify() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstanceFast()->isInProductionGrid()
+		if (LLGridManager::getInstanceFast()->isInSLBeta()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 	{
 			return TRUE;
@@ -6337,7 +6337,7 @@ BOOL LLViewerObject::permModify() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstanceFast()->isInProductionGrid()
+		if (LLGridManager::getInstanceFast()->isInSLBeta()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 	{
 			return TRUE;
@@ -6361,7 +6361,7 @@ BOOL LLViewerObject::permCopy() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstanceFast()->isInProductionGrid()
+		if (LLGridManager::getInstanceFast()->isInSLBeta()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
@@ -6385,7 +6385,7 @@ BOOL LLViewerObject::permMove() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstanceFast()->isInProductionGrid()
+		if (LLGridManager::getInstanceFast()->isInSLBeta()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
@@ -6409,7 +6409,7 @@ BOOL LLViewerObject::permTransfer() const
 		return TRUE;
 #else
 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstanceFast()->isInProductionGrid()
+		if (LLGridManager::getInstanceFast()->isInSLBeta()
             && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
 		{
 			return TRUE;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index fe26623b3379e39302a82d0682349a636aaab880..dfb5fa010c0cc8ff7c9cd66e396cd1c7c2a22f98 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2631,7 +2631,7 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible )
 
 		// ...and set the menu color appropriately.
 		setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
-			LLGridManager::getInstance()->isInProductionGrid());
+			LLGridManager::getInstance()->isInSLBeta());
 	}
         
 	if ( gStatusBar )
@@ -5657,7 +5657,7 @@ void LLViewerWindow::initTextures(S32 location_id)
 {
     if (mProgressView)
     {
-        mProgressView->initTextures(location_id, LLGridManager::getInstance()->isInProductionGrid());
+        mProgressView->initTextures(location_id, !LLGridManager::getInstance()->isInSLBeta());
     }
 }
 
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 2f272b095bc4a1b339a7610ac38ed19a8a47d02a..0c8750ee4bbb88407f762324a6883ce3c19bdd3e 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -625,7 +625,7 @@ void LLVivoxVoiceClient::setLoginInfo(
 		// we have an empty account server name
 		// so we fall back to hardcoded defaults
 
-		if(LLGridManager::getInstance()->isInProductionGrid())
+		if(LLGridManager::getInstance()->isInSLMain())
 		{
 			// Use the release account server
 			mVoiceSIPURIHostName = "bhr.vivox.com";